From 077427cfd1f0e646c1d064e187df3a4c6fe39799 Mon Sep 17 00:00:00 2001 From: Kalin Chernev Date: Wed, 16 Dec 2020 08:46:53 +0100 Subject: [PATCH 1/2] Rename example folder --- .npmignore | 2 +- docs/README.md | 2 +- {example => examples}/app/app.js | 2 +- {example => examples}/app/app.spec.js | 0 {example => examples}/app/parameters.yaml | 0 {example => examples}/app/parameters.yml | 0 {example => examples}/app/route.coffee | 0 {example => examples}/app/routes.js | 0 {example => examples}/app/routes2.js | 0 {example => examples}/app/swagger-spec.json | 0 {example => examples}/app/swaggerDefinition.js | 0 .../yaml-anchors-aliases/example.js | 0 .../reference-specification.json | 0 .../x-amazon-apigateway-integrations.yaml | 0 .../yaml-anchors-aliases.spec.js | 4 ++-- package.json | 2 +- test/cli.spec.js | 18 +++++++++--------- test/utils.spec.js | 10 ++++++---- 18 files changed, 21 insertions(+), 19 deletions(-) rename {example => examples}/app/app.js (96%) rename {example => examples}/app/app.spec.js (100%) rename {example => examples}/app/parameters.yaml (100%) rename {example => examples}/app/parameters.yml (100%) rename {example => examples}/app/route.coffee (100%) rename {example => examples}/app/routes.js (100%) rename {example => examples}/app/routes2.js (100%) rename {example => examples}/app/swagger-spec.json (100%) rename {example => examples}/app/swaggerDefinition.js (100%) rename {example => examples}/yaml-anchors-aliases/example.js (100%) rename {example => examples}/yaml-anchors-aliases/reference-specification.json (100%) rename {example => examples}/yaml-anchors-aliases/x-amazon-apigateway-integrations.yaml (100%) rename {example => examples}/yaml-anchors-aliases/yaml-anchors-aliases.spec.js (79%) diff --git a/.npmignore b/.npmignore index e8568723..99807f57 100644 --- a/.npmignore +++ b/.npmignore @@ -7,7 +7,7 @@ .nvm .eslintrc.js external.jsdoc -example/ +examples/ docs/ jsdoc/ test/ diff --git a/docs/README.md b/docs/README.md index 3e61a6f3..8a49f000 100644 --- a/docs/README.md +++ b/docs/README.md @@ -4,7 +4,7 @@ Quick-start: - [Getting started](./GETTING-STARTED.md) - [CLI](./CLI.md) -- [Examples](../example) +- [Examples](../examples) Before you submit an issue: diff --git a/example/app/app.js b/examples/app/app.js similarity index 96% rename from example/app/app.js rename to examples/app/app.js index a4e86f42..a64585bf 100644 --- a/example/app/app.js +++ b/examples/app/app.js @@ -40,7 +40,7 @@ const options = { swaggerDefinition, // Path to the API docs // Note that this path is relative to the current directory from which the Node.js is ran, not the application itself. - apis: ['./example/app/routes*.js', './example/app/parameters.yaml'], + apis: ['./examples/app/routes*.js', './examples/app/parameters.yaml'], }; // Initialize swagger-jsdoc -> returns validated swagger spec in json format diff --git a/example/app/app.spec.js b/examples/app/app.spec.js similarity index 100% rename from example/app/app.spec.js rename to examples/app/app.spec.js diff --git a/example/app/parameters.yaml b/examples/app/parameters.yaml similarity index 100% rename from example/app/parameters.yaml rename to examples/app/parameters.yaml diff --git a/example/app/parameters.yml b/examples/app/parameters.yml similarity index 100% rename from example/app/parameters.yml rename to examples/app/parameters.yml diff --git a/example/app/route.coffee b/examples/app/route.coffee similarity index 100% rename from example/app/route.coffee rename to examples/app/route.coffee diff --git a/example/app/routes.js b/examples/app/routes.js similarity index 100% rename from example/app/routes.js rename to examples/app/routes.js diff --git a/example/app/routes2.js b/examples/app/routes2.js similarity index 100% rename from example/app/routes2.js rename to examples/app/routes2.js diff --git a/example/app/swagger-spec.json b/examples/app/swagger-spec.json similarity index 100% rename from example/app/swagger-spec.json rename to examples/app/swagger-spec.json diff --git a/example/app/swaggerDefinition.js b/examples/app/swaggerDefinition.js similarity index 100% rename from example/app/swaggerDefinition.js rename to examples/app/swaggerDefinition.js diff --git a/example/yaml-anchors-aliases/example.js b/examples/yaml-anchors-aliases/example.js similarity index 100% rename from example/yaml-anchors-aliases/example.js rename to examples/yaml-anchors-aliases/example.js diff --git a/example/yaml-anchors-aliases/reference-specification.json b/examples/yaml-anchors-aliases/reference-specification.json similarity index 100% rename from example/yaml-anchors-aliases/reference-specification.json rename to examples/yaml-anchors-aliases/reference-specification.json diff --git a/example/yaml-anchors-aliases/x-amazon-apigateway-integrations.yaml b/examples/yaml-anchors-aliases/x-amazon-apigateway-integrations.yaml similarity index 100% rename from example/yaml-anchors-aliases/x-amazon-apigateway-integrations.yaml rename to examples/yaml-anchors-aliases/x-amazon-apigateway-integrations.yaml diff --git a/example/yaml-anchors-aliases/yaml-anchors-aliases.spec.js b/examples/yaml-anchors-aliases/yaml-anchors-aliases.spec.js similarity index 79% rename from example/yaml-anchors-aliases/yaml-anchors-aliases.spec.js rename to examples/yaml-anchors-aliases/yaml-anchors-aliases.spec.js index c549fe75..9cd0c3af 100644 --- a/example/yaml-anchors-aliases/yaml-anchors-aliases.spec.js +++ b/examples/yaml-anchors-aliases/yaml-anchors-aliases.spec.js @@ -11,8 +11,8 @@ describe('Example for using anchors and aliases in YAML documents', () => { }, }, apis: [ - './example/yaml-anchors-aliases/x-amazon-apigateway-integrations.yaml', - './example/yaml-anchors-aliases/example.js', + './examples/yaml-anchors-aliases/x-amazon-apigateway-integrations.yaml', + './examples/yaml-anchors-aliases/example.js', ], }); expect(result).toEqual(referenceSpecification); diff --git a/package.json b/package.json index 594e8537..0a110f4e 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "node": ">=12.0.0" }, "scripts": { - "start": "node example/app/app.js", + "start": "node examples/app/app.js", "lint": "eslint .", "test:lint": "eslint .", "test:js": "jest --verbose", diff --git a/test/cli.spec.js b/test/cli.spec.js index 3ec89d6c..5d61052f 100644 --- a/test/cli.spec.js +++ b/test/cli.spec.js @@ -33,13 +33,13 @@ describe('CLI module', () => { }); it('should require arguments with jsDoc data about an API', async () => { - const result = await sh(`${bin} -d example/app/swaggerDefinition.js`); + const result = await sh(`${bin} -d examples/app/swaggerDefinition.js`); expect(result.stdout).toMatchSnapshot(); }); it('should create swagger.json by default when the API input is good', async () => { const result = await sh( - `${bin} -d example/app/swaggerDefinition.js example/app/routes.js` + `${bin} -d examples/app/swaggerDefinition.js examples/app/routes.js` ); expect(result.stdout).toBe('Swagger specification is ready.\n'); const specification = fs.statSync('swagger.json'); @@ -48,7 +48,7 @@ describe('CLI module', () => { it('should create swagger.json by default when the API input is from definition file', async () => { const result = await sh( - `${bin} -d test/files/v2/api_definition.js example/app/routes.js` + `${bin} -d test/files/v2/api_definition.js examples/app/routes.js` ); expect(result.stdout).toBe('Swagger specification is ready.\n'); const specification = fs.statSync('swagger.json'); @@ -57,7 +57,7 @@ describe('CLI module', () => { it('should accept custom configuration for output specification', async () => { const result = await sh( - `${bin} -d example/app/swaggerDefinition.js -o customSpec.json example/app/routes.js` + `${bin} -d examples/app/swaggerDefinition.js -o customSpec.json examples/app/routes.js` ); expect(result.stdout).toBe('Swagger specification is ready.\n'); const specification = fs.statSync('customSpec.json'); @@ -66,7 +66,7 @@ describe('CLI module', () => { it('should create a YAML swagger spec when a custom output configuration with a .yaml extension is used', async () => { const result = await sh( - `${bin} -d example/app/swaggerDefinition.js -o customSpec.yaml example/app/routes.js` + `${bin} -d examples/app/swaggerDefinition.js -o customSpec.yaml examples/app/routes.js` ); expect(result.stdout).toBe('Swagger specification is ready.\n'); const specification = fs.statSync('customSpec.yaml'); @@ -75,7 +75,7 @@ describe('CLI module', () => { it('should allow a JavaScript definition file', async () => { const result = await sh( - `${bin} -d test/files/v2/api_definition.js example/app/routes.js` + `${bin} -d test/files/v2/api_definition.js examples/app/routes.js` ); expect(result.stdout).toBe('Swagger specification is ready.\n'); const specification = fs.statSync('swagger.json'); @@ -84,7 +84,7 @@ describe('CLI module', () => { it('should allow a JSON definition file', async () => { const result = await sh( - `${bin} -d test/files/v2/api_definition.json example/app/routes.js` + `${bin} -d test/files/v2/api_definition.json examples/app/routes.js` ); expect(result.stdout).toBe('Swagger specification is ready.\n'); const specification = fs.statSync('swagger.json'); @@ -93,7 +93,7 @@ describe('CLI module', () => { it('should allow a YAML definition file', async () => { const result = await sh( - `${bin} -d test/files/v2/api_definition.yaml example/app/routes.js` + `${bin} -d test/files/v2/api_definition.yaml examples/app/routes.js` ); expect(result.stdout).toBe('Swagger specification is ready.\n'); const specification = fs.statSync('swagger.json'); @@ -112,7 +112,7 @@ describe('CLI module', () => { it('should report YAML documents with errors', async () => { const result = await sh( - `${bin} -d example/app/swaggerDefinition.js test/files/v2/wrong-yaml-identation.js` + `${bin} -d examples/app/swaggerDefinition.js test/files/v2/wrong-yaml-identation.js` ); expect(result.stdout).toContain( diff --git a/test/utils.spec.js b/test/utils.spec.js index e9edf537..89848b37 100644 --- a/test/utils.spec.js +++ b/test/utils.spec.js @@ -22,7 +22,7 @@ describe('Utilities module', () => { describe('extractAnnotations', () => { it('should extract jsdoc comments by default', () => { expect( - utils.extractAnnotations(require.resolve('../example/app/routes2.js')) + utils.extractAnnotations(require.resolve('../examples/app/routes2.js')) ).toEqual({ yaml: [], jsdoc: [ @@ -34,7 +34,7 @@ describe('Utilities module', () => { it('should extract data from YAML files', () => { expect( utils.extractAnnotations( - require.resolve('../example/app/parameters.yaml') + require.resolve('../examples/app/parameters.yaml') ) ).toEqual({ yaml: [ @@ -45,7 +45,7 @@ describe('Utilities module', () => { expect( utils.extractAnnotations( - require.resolve('../example/app/parameters.yml') + require.resolve('../examples/app/parameters.yml') ) ).toEqual({ yaml: [ @@ -57,7 +57,9 @@ describe('Utilities module', () => { it('should extract jsdoc comments from coffeescript files/syntax', () => { expect( - utils.extractAnnotations(require.resolve('../example/app/route.coffee')) + utils.extractAnnotations( + require.resolve('../examples/app/route.coffee') + ) ).toEqual({ yaml: [], jsdoc: [ From 781aa06b9d542f9b901421d44d736547f2b032da Mon Sep 17 00:00:00 2001 From: Kalin Chernev Date: Wed, 16 Dec 2020 09:46:13 +0100 Subject: [PATCH 2/2] support x-webhooks --- examples/extensions/example.js | 23 +++++++++++++ examples/extensions/extensions.spec.js | 17 ++++++++++ .../extensions/reference-specification.json | 32 +++++++++++++++++++ src/specification.js | 11 ++++++- 4 files changed, 82 insertions(+), 1 deletion(-) create mode 100644 examples/extensions/example.js create mode 100644 examples/extensions/extensions.spec.js create mode 100644 examples/extensions/reference-specification.json diff --git a/examples/extensions/example.js b/examples/extensions/example.js new file mode 100644 index 00000000..c0ad6a5f --- /dev/null +++ b/examples/extensions/example.js @@ -0,0 +1,23 @@ +/* istanbul ignore file */ + +/** + * Example taken from https://redocly.github.io/redoc/openapi.yaml + * + * @swagger + * x-webhooks: + * newPet: + * post: + * summary: New pet + * description: Information about a new pet in the systems + * operationId: newPet + * tags: + * - pet + * requestBody: + * content: + * application/json: + * schema: + * $ref: "#/components/schemas/Pet" + * responses: + * "200": + * description: Return a 200 status to indicate that the data was received successfully + */ diff --git a/examples/extensions/extensions.spec.js b/examples/extensions/extensions.spec.js new file mode 100644 index 00000000..4479cbae --- /dev/null +++ b/examples/extensions/extensions.spec.js @@ -0,0 +1,17 @@ +const swaggerJsdoc = require('../..'); +const referenceSpecification = require('./reference-specification.json'); + +describe('Example for using extensions', () => { + it('should support x-webhooks', () => { + const result = swaggerJsdoc({ + swaggerDefinition: { + info: { + title: 'Example with extensions', + version: '0.0.1', + }, + }, + apis: ['./examples/extensions/example.js'], + }); + expect(result).toEqual(referenceSpecification); + }); +}); diff --git a/examples/extensions/reference-specification.json b/examples/extensions/reference-specification.json new file mode 100644 index 00000000..7b352e0f --- /dev/null +++ b/examples/extensions/reference-specification.json @@ -0,0 +1,32 @@ +{ + "info": { "title": "Example with extensions", "version": "0.0.1" }, + "swagger": "2.0", + "paths": {}, + "definitions": {}, + "responses": {}, + "parameters": {}, + "securityDefinitions": {}, + "tags": [], + "x-webhooks": { + "newPet": { + "post": { + "summary": "New pet", + "description": "Information about a new pet in the systems", + "operationId": "newPet", + "tags": ["pet"], + "requestBody": { + "content": { + "application/json": { + "schema": { "$ref": "#/components/schemas/Pet" } + } + } + }, + "responses": { + "200": { + "description": "Return a 200 status to indicate that the data was received successfully" + } + } + } + } + } +} diff --git a/src/specification.js b/src/specification.js index 3c77d868..f58d3821 100644 --- a/src/specification.js +++ b/src/specification.js @@ -104,7 +104,16 @@ function finalize(swaggerObject) { * @param {string} property */ function organize(swaggerObject, annotation, property) { - if (property.startsWith('x-')) return; // extensions defined "inline" in annotations are not useful for the end specification + // Root property on purpose. + // @see https://github.com/OAI/OpenAPI-Specification/blob/master/proposals/002_Webhooks.md#proposed-solution + if (property === 'x-webhooks') { + swaggerObject[property] = annotation[property]; + } + + // Other extensions can be in varying places depending on different vendors and opinions. + // The following return makes it so that they are not put in `paths` in the last case. + // New specific extensions will need to be handled on case-by-case if to be included in `paths`. + if (property.startsWith('x-')) return; const commonProperties = [ 'components',