diff --git a/CHANGELOG.md b/CHANGELOG.md index 9dbac63..1b1f9e7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,38 @@ +## [1.15.0](https://github.com/joolfe/postman-to-openapi/compare/1.14.0...1.15.0) (2021-07-30) + + +### Features + +* adding x-www-form-urlencoded support ([8311563](https://github.com/joolfe/postman-to-openapi/commit/8311563e556cc5fdf791f7304d43de994203ae3d)) + + +### Bug Fixes + +* move import to try to fix erro in gh pages ([326c745](https://github.com/joolfe/postman-to-openapi/commit/326c745a957cd0dc38187adeb1aaf81309dc8a89)) +* put color to the beginning of the css ([9cc56b0](https://github.com/joolfe/postman-to-openapi/commit/9cc56b06963cf775232dea9134cb30c362f2c4e9)) + + +### Tests + +* trying to fix docs theme error ([8c6428b](https://github.com/joolfe/postman-to-openapi/commit/8c6428b119607d92aa7adf46a86cf4caa5729acc)) + + +### Build System + +* update version and mocha dep ([cc4f4c5](https://github.com/joolfe/postman-to-openapi/commit/cc4f4c5c67ea7f1f9fda87527144cfcaf9456439)) + + +### Code Refactoring + +* change collection name ([8115bc7](https://github.com/joolfe/postman-to-openapi/commit/8115bc76aa944ee16c460363bbf27ffc6932a458)) +* form data drop encoding section from and removed require code ([9994c8d](https://github.com/joolfe/postman-to-openapi/commit/9994c8d24805f125244af1b320dedb106a05fd78)) +* improving the mapFormData function ([a85eef6](https://github.com/joolfe/postman-to-openapi/commit/a85eef63d7d9d67538fbf089ff7514d11f64357e)) + + +### Documentation + +* mention new feature about "x-www-form-urlencoded" ([2c38fd9](https://github.com/joolfe/postman-to-openapi/commit/2c38fd91db2e9401840b37094cdf3a53c5f75221)) + ## [1.14.0](https://github.com/joolfe/postman-to-openapi/compare/1.13.0...1.14.0) (2021-07-24) diff --git a/docs/index.md b/docs/index.md index 0af88f5..a7dfc8b 100644 --- a/docs/index.md +++ b/docs/index.md @@ -25,7 +25,7 @@ * Transform query, headers and path parameters (description, required...). * Postman variables as Path parameters. * Automatic infer types from query and headers parameters. -* Support postman "raw" body for `Json` and `Text` formats and also postman body "form-data". +* Support postman "raw" body (`Json` and `Text`), "form-data" and "x-www-form-urlencoded". * Postman Authorization parse or by configuration (Basic and Bearer). * Contact and License from variables or by configuration. * Provide meta-information as a markdown table. @@ -320,7 +320,7 @@ The default value is `true`, so headers are by default added to the response def ## Basic conversion -This library support the transformation from Postman collection to all the basic HTTP method as GET, POST, PUT... parse the body request of type "raw" (`Json` and `Text`) and "form-data" (see ["form-data" body](#form-data-body) section for more info about this mode). [Query parameters](#parameters-parsing) are also supported. +This library support the transformation from Postman collection to all the basic HTTP method as GET, POST, PUT... parse the body request of type "raw" (`Json` and `Text`), "form-data" (see ["form-data" body](#form-data-body) section for more info about this mode) and "x-www-form-urlencoded" formats. [Query parameters](#parameters-parsing) are also supported. Have a look to the [PostmantoOpenAPI collection](https://github.com/joolfe/postman-to-openapi/blob/master/test/resources/input/v21/PostmantoOpenAPI.json) file for an example of how to use this feature. diff --git a/lib/index.js b/lib/index.js index 6185e9a..13d4e12 100644 --- a/lib/index.js +++ b/lib/index.js @@ -171,15 +171,16 @@ function parseBody (body = {}, method) { 'multipart/form-data': { schema: { type: 'object', - properties: body.formdata.reduce((obj, { key, type, description, value }) => { - obj[key] = { - type: 'string', - ...(description ? { description } : {}), - ...(value ? { example: value } : {}), - ...(type === 'file' ? { format: 'binary' } : {}) - } - return obj - }, {}) + properties: body.formdata.reduce(mapFormData(), {}) + } + } + } + break + case 'urlencoded': + content = { + 'application/x-www-form-urlencoded': { + schema: { + properties: body.urlencoded.reduce(mapFormData(), {}) } } } @@ -188,6 +189,19 @@ function parseBody (body = {}, method) { return { requestBody: { content } } } +/* Accumulator function for form data values */ +function mapFormData () { + return (obj, { key, type, description, value }) => { + obj[key] = { + type: inferType(value), + ...(description ? { description: description.replace(/ ?\[required\] ?/gi, '') } : {}), + ...(value ? { example: value } : {}), + ...(type === 'file' ? { format: 'binary' } : {}) + } + return obj + } +} + /* Parse the Postman query and header and transform into OpenApi parameters */ function parseParameters (query = [], header, paths, paramsMeta = {}) { // parse Headers diff --git a/package-lock.json b/package-lock.json index c8eb017..62cd1bd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,11 +1,11 @@ { "name": "postman-to-openapi", - "version": "1.14.0", + "version": "1.15.0", "lockfileVersion": 2, "requires": true, "packages": { "": { - "version": "1.14.0", + "version": "1.15.0", "license": "MIT", "dependencies": { "commander": "^7.2.0", @@ -25,7 +25,7 @@ "eslint-plugin-promise": "^5.1.0", "execa": "^5.1.1", "husky": "^6.0.0", - "mocha": "^9.0.2", + "mocha": "^9.0.3", "nyc": "^15.1.0", "typescript": "^4.3.2" }, @@ -3629,9 +3629,9 @@ } }, "node_modules/mocha": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-9.0.2.tgz", - "integrity": "sha512-FpspiWU+UT9Sixx/wKimvnpkeW0mh6ROAKkIaPokj3xZgxeRhcna/k5X57jJghEr8X+Cgu/Vegf8zCX5ugSuTA==", + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-9.0.3.tgz", + "integrity": "sha512-hnYFrSefHxYS2XFGtN01x8un0EwNu2bzKvhpRFhgoybIvMaOkkL60IVPmkb5h6XDmUl4IMSB+rT5cIO4/4bJgg==", "dev": true, "dependencies": { "@ungap/promise-all-settled": "1.1.2", @@ -8208,9 +8208,9 @@ } }, "mocha": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-9.0.2.tgz", - "integrity": "sha512-FpspiWU+UT9Sixx/wKimvnpkeW0mh6ROAKkIaPokj3xZgxeRhcna/k5X57jJghEr8X+Cgu/Vegf8zCX5ugSuTA==", + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-9.0.3.tgz", + "integrity": "sha512-hnYFrSefHxYS2XFGtN01x8un0EwNu2bzKvhpRFhgoybIvMaOkkL60IVPmkb5h6XDmUl4IMSB+rT5cIO4/4bJgg==", "dev": true, "requires": { "@ungap/promise-all-settled": "1.1.2", diff --git a/package.json b/package.json index 996fcf6..331124d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "postman-to-openapi", - "version": "1.14.0", + "version": "1.15.0", "description": "Convert postman collection to OpenAPI spec", "main": "lib/index.js", "types": "types/index.d.ts", @@ -54,7 +54,7 @@ "eslint-plugin-promise": "^5.1.0", "execa": "^5.1.1", "husky": "^6.0.0", - "mocha": "^9.0.2", + "mocha": "^9.0.3", "nyc": "^15.1.0", "typescript": "^4.3.2" }, diff --git a/test/index.spec.js b/test/index.spec.js index e14fc31..b540b5a 100644 --- a/test/index.spec.js +++ b/test/index.spec.js @@ -49,6 +49,7 @@ const EXPECTED_RESPONSES_MULTI_LANG = readFileSync('./test/resources/output/Resp const EXPECTED_AUTH_REQUEST = readFileSync('./test/resources/output/AuthRequest.yml', 'utf8') const EXPECTED_RESPONSES_NO_HEADERS = readFileSync('./test/resources/output/ResponsesNoHeaders.yml', 'utf8') const EXPECTED_FORM_DATA = readFileSync('./test/resources/output/FormData.yml', 'utf8') +const EXPECTED_FORM_URLENCODED = readFileSync('./test/resources/output/FormUrlencoded.yml', 'utf8') const AUTH_DEFINITIONS = { myCustomAuth: { @@ -104,6 +105,7 @@ describe('Library specs', function () { const COLLECTION_RESPONSES_MULTI_LANG = `./test/resources/input/${version}/ResponsesMultiLang.json` const COLLECTION_AUTH_REQUEST = `./test/resources/input/${version}/AuthRequest.json` const COLLECTION_FORM_DATA = `./test/resources/input/${version}/FormData.json` + const COLLECTION_FORM_URLENCODED = `./test/resources/input/${version}/FormUrlencoded.json` it('should work with a basic transform', async function () { const result = await postmanToOpenApi(COLLECTION_BASIC, OUTPUT_PATH, {}) @@ -402,6 +404,11 @@ describe('Library specs', function () { const result = await postmanToOpenApi(COLLECTION_FORM_DATA, OUTPUT_PATH, {}) equal(result, EXPECTED_FORM_DATA) }) + + it('should parse POST methods with www form urlencoded', async function () { + const result = await postmanToOpenApi(COLLECTION_FORM_URLENCODED, OUTPUT_PATH, {}) + equal(result, EXPECTED_FORM_URLENCODED) + }) }) }) diff --git a/test/resources/input/v2/FormData.json b/test/resources/input/v2/FormData.json index 586a94a..8c74f1f 100644 --- a/test/resources/input/v2/FormData.json +++ b/test/resources/input/v2/FormData.json @@ -17,13 +17,13 @@ { "key": "name", "value": "New User", - "description": "full name of the user (accepts spaces)", + "description": "full name of the user (accepts spaces) [required]", "type": "text" }, { "key": "email", "value": "newuser@example.com", - "description": "email of the user (for notifications and login)", + "description": "email of the user (for notifications and login) [required]", "type": "text" }, { @@ -34,6 +34,7 @@ { "key": "profileImage", "description": "User avatar", + "contentType": "application/octet-stream", "type": "file", "src": [] } @@ -44,4 +45,4 @@ "response": [] } ] -} \ No newline at end of file +} diff --git a/test/resources/input/v2/FormUrlencoded.json b/test/resources/input/v2/FormUrlencoded.json new file mode 100644 index 0000000..e199615 --- /dev/null +++ b/test/resources/input/v2/FormUrlencoded.json @@ -0,0 +1,41 @@ +{ + "info": { + "_postman_id": "c7890cb4-aa39-4569-9701-a9d6f4abc750", + "name": "Form Url Encoded", + "schema": "https://schema.getpostman.com/json/collection/v2.0.0/collection.json" + }, + "item": [ + { + "name": "Register New User", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "urlencoded", + "urlencoded": [ + { + "key": "name", + "value": "New User", + "description": "full name of the user (accepts spaces) [required]", + "type": "text" + }, + { + "key": "email", + "value": "newuser@example.com", + "description": "email of the user (for notifications and login) [required]", + "type": "text" + }, + { + "key": "password", + "value": "pasword123", + "description": "password (to be used for logging in) [required]", + "type": "text" + } + ] + }, + "url": "https://api.io/register" + }, + "response": [] + } + ] +} \ No newline at end of file diff --git a/test/resources/input/v21/FormData.json b/test/resources/input/v21/FormData.json index 247c2a6..759c664 100644 --- a/test/resources/input/v21/FormData.json +++ b/test/resources/input/v21/FormData.json @@ -17,13 +17,13 @@ { "key": "name", "value": "New User", - "description": "full name of the user (accepts spaces)", + "description": "full name of the user (accepts spaces) [required]", "type": "text" }, { "key": "email", "value": "newuser@example.com", - "description": "email of the user (for notifications and login)", + "description": "email of the user (for notifications and login) [required]", "type": "text" }, { @@ -34,6 +34,7 @@ { "key": "profileImage", "description": "User avatar", + "contentType": "application/octet-stream", "type": "file", "src": [] } @@ -54,4 +55,4 @@ "response": [] } ] -} \ No newline at end of file +} diff --git a/test/resources/input/v21/FormUrlencoded.json b/test/resources/input/v21/FormUrlencoded.json new file mode 100644 index 0000000..d0cc333 --- /dev/null +++ b/test/resources/input/v21/FormUrlencoded.json @@ -0,0 +1,51 @@ +{ + "info": { + "_postman_id": "c7890cb4-aa39-4569-9701-a9d6f4abc750", + "name": "Form Url Encoded", + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" + }, + "item": [ + { + "name": "Register New User", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "urlencoded", + "urlencoded": [ + { + "key": "name", + "value": "New User", + "description": "full name of the user (accepts spaces) [required]", + "type": "text" + }, + { + "key": "email", + "value": "newuser@example.com", + "description": "email of the user (for notifications and login) [required]", + "type": "text" + }, + { + "key": "password", + "value": "pasword123", + "description": "password (to be used for logging in) [required]", + "type": "text" + } + ] + }, + "url": { + "raw": "https://api.io/register", + "protocol": "https", + "host": [ + "api", + "io" + ], + "path": [ + "register" + ] + } + }, + "response": [] + } + ] +} \ No newline at end of file diff --git a/test/resources/output/FormUrlencoded.yml b/test/resources/output/FormUrlencoded.yml new file mode 100644 index 0000000..6e1d141 --- /dev/null +++ b/test/resources/output/FormUrlencoded.yml @@ -0,0 +1,34 @@ +openapi: 3.0.0 +info: + title: Form Url Encoded + version: 1.0.0 +servers: + - url: https://api.io +paths: + /register: + post: + tags: + - default + summary: Register New User + requestBody: + content: + application/x-www-form-urlencoded: + schema: + properties: + name: + type: string + description: full name of the user (accepts spaces) + example: New User + email: + type: string + description: email of the user (for notifications and login) + example: newuser@example.com + password: + type: string + description: password (to be used for logging in) + example: pasword123 + responses: + '200': + description: Successful response + content: + application/json: {}