diff --git a/docs/index.md b/docs/index.md index 0af88f5..0837a05 100644 --- a/docs/index.md +++ b/docs/index.md @@ -352,7 +352,7 @@ This library automatically transform query and headers parameters from Postman o The default schema used for parameters is `string` but the library try to infer the type of the parameters based on the value using regular expressions, the detected types are `integer`, `number`, `boolean` and `string`, if you find any problem in the inference process please open an issue. -Path parameters are also automatically detected, this library look for [Postman variables](https://learning.postman.com/docs/sending-requests/variables/) in the url as `{{{variable}}}` and transform to a single curly brace expression as `{variable}` as supported by OpenAPI, also create the parameter definition using the variable name. To provide additional information about a path parameter you can [Pass Meta-information as markdown](#pass-meta-information-as-markdown). +Path parameters are also automatically detected, this library look for [Postman variables](https://learning.postman.com/docs/sending-requests/variables/) in the url as "{{variable}}" and transform to a single curly brace expression as `{variable}` as supported by OpenAPI, also create the parameter definition using the variable name. To provide additional information about a path parameter you can [Pass Meta-information as markdown](#pass-meta-information-as-markdown). For headers and query fields you can indicate that this parameter is mandatory/required adding into the description the literal `[required]`. The library use a case insensitive regexp so all variations are supported (`[REQUIRED]`, `[Required]`...) and never mind the location inside the description (at the beginning, at the end...). diff --git a/lib/var-replacer.js b/lib/var-replacer.js new file mode 100644 index 0000000..c757c9d --- /dev/null +++ b/lib/var-replacer.js @@ -0,0 +1,21 @@ +const Mustache = require('mustache') + +/** + * Rewrite escapedValue() function to not delete undefined variables + */ +Mustache.Writer.prototype.escapedValue = function escapedValue (token, context, config) { + const value = context.lookup(token[1]) || `{{${token[1]}}}` + return String(value) +} + +function replacePostmanVariables (collectionString) { + const postmanJson = JSON.parse(collectionString) + const { variable } = postmanJson + const context = variable.reduce((obj, { key, value }) => { + obj[key] = value + return obj + }, {}) + return Mustache.render(collectionString, context) +} + +module.exports = replacePostmanVariables diff --git a/package-lock.json b/package-lock.json index c8eb017..59d2458 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,7 +10,8 @@ "dependencies": { "commander": "^7.2.0", "js-yaml": "^4.1.0", - "marked": "^2.0.7" + "marked": "^2.0.7", + "mustache": "^4.2.0" }, "bin": { "p2o": "bin/cli.js" @@ -3731,6 +3732,14 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, + "node_modules/mustache": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/mustache/-/mustache-4.2.0.tgz", + "integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==", + "bin": { + "mustache": "bin/mustache" + } + }, "node_modules/nanoid": { "version": "3.1.23", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.23.tgz", @@ -8286,6 +8295,11 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, + "mustache": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/mustache/-/mustache-4.2.0.tgz", + "integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==" + }, "nanoid": { "version": "3.1.23", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.23.tgz", diff --git a/package.json b/package.json index 996fcf6..9a439e6 100644 --- a/package.json +++ b/package.json @@ -88,7 +88,8 @@ "dependencies": { "commander": "^7.2.0", "js-yaml": "^4.1.0", - "marked": "^2.0.7" + "marked": "^2.0.7", + "mustache": "^4.2.0" }, "husky": { "hooks": { diff --git a/test/resources/input/v21/Variables.json b/test/resources/input/v21/Variables.json new file mode 100644 index 0000000..5450883 --- /dev/null +++ b/test/resources/input/v21/Variables.json @@ -0,0 +1,192 @@ +{ + "info": { + "_postman_id": "747abd37-e913-4bf8-a7e7-01730737b973", + "name": "Variables", + "description": "Mi super test collection from postman", + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" + }, + "item": [ + { + "name": "Create new User", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"example\": \"field\",\n \"other\": {\n \"data1\": \"yes\",\n \"service\": \"{{service}}\"\n }\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{server}}/users", + "host": [ + "{{server}}" + ], + "path": [ + "users" + ] + }, + "description": "Create a new user into your amazing API" + }, + "response": [] + }, + { + "name": "Create Post", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "formdata", + "formdata": [ + { + "key": "company", + "value": "{{company}}", + "type": "text" + }, + { + "key": "text", + "value": "This is an example text", + "type": "text" + }, + { + "key": "auditor", + "value": "{{auditor}}", + "type": "text" + } + ], + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{server}}/post", + "host": [ + "{{server}}" + ], + "path": [ + "post" + ] + } + }, + "response": [] + }, + { + "name": "Consult User data", + "request": { + "method": "GET", + "header": [ + { + "key": "X-Company", + "value": "{{company}}", + "type": "text" + }, + { + "key": "", + "value": "", + "type": "text", + "disabled": true + } + ], + "url": { + "raw": "{{server}}/users/{{user_id}}?company={{company}}", + "host": [ + "{{server}}" + ], + "path": [ + "users", + "{{user_id}}" + ], + "query": [ + { + "key": "company", + "value": "{{company}}" + } + ] + }, + "description": "Get one user instance data" + }, + "response": [] + }, + { + "name": "Get a list of user", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{server}}/users?size={{page-size}}&company={{company}}", + "host": [ + "{{server}}" + ], + "path": [ + "users" + ], + "query": [ + { + "key": "size", + "value": "{{page-size}}", + "description": "size of the list" + }, + { + "key": "company", + "value": "{{company}}", + "description": "company for filter users" + } + ] + }, + "description": "Get a list of users" + }, + "response": [] + } + ], + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + } + ], + "variable": [ + { + "key": "version", + "value": "1.1.0" + }, + { + "key": "server", + "value": "https://api.io" + }, + { + "key": "page-size", + "value": "10" + }, + { + "key": "company", + "value": "ServicesLTD" + }, + { + "key": "auditor", + "value": "IHA" + }, + { + "key": "service", + "value": "s23434" + } + ] +} \ No newline at end of file diff --git a/test/resources/var-replace/VariablesReplaced.json b/test/resources/var-replace/VariablesReplaced.json new file mode 100644 index 0000000..d38bbd0 --- /dev/null +++ b/test/resources/var-replace/VariablesReplaced.json @@ -0,0 +1,192 @@ +{ + "info": { + "_postman_id": "747abd37-e913-4bf8-a7e7-01730737b973", + "name": "Variables", + "description": "Mi super test collection from postman", + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" + }, + "item": [ + { + "name": "Create new User", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"example\": \"field\",\n \"other\": {\n \"data1\": \"yes\",\n \"service\": \"s23434\"\n }\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "https://api.io/users", + "host": [ + "https://api.io" + ], + "path": [ + "users" + ] + }, + "description": "Create a new user into your amazing API" + }, + "response": [] + }, + { + "name": "Create Post", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "formdata", + "formdata": [ + { + "key": "company", + "value": "ServicesLTD", + "type": "text" + }, + { + "key": "text", + "value": "This is an example text", + "type": "text" + }, + { + "key": "auditor", + "value": "IHA", + "type": "text" + } + ], + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "https://api.io/post", + "host": [ + "https://api.io" + ], + "path": [ + "post" + ] + } + }, + "response": [] + }, + { + "name": "Consult User data", + "request": { + "method": "GET", + "header": [ + { + "key": "X-Company", + "value": "ServicesLTD", + "type": "text" + }, + { + "key": "", + "value": "", + "type": "text", + "disabled": true + } + ], + "url": { + "raw": "https://api.io/users/{{user_id}}?company=ServicesLTD", + "host": [ + "https://api.io" + ], + "path": [ + "users", + "{{user_id}}" + ], + "query": [ + { + "key": "company", + "value": "ServicesLTD" + } + ] + }, + "description": "Get one user instance data" + }, + "response": [] + }, + { + "name": "Get a list of user", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "https://api.io/users?size=10&company=ServicesLTD", + "host": [ + "https://api.io" + ], + "path": [ + "users" + ], + "query": [ + { + "key": "size", + "value": "10", + "description": "size of the list" + }, + { + "key": "company", + "value": "ServicesLTD", + "description": "company for filter users" + } + ] + }, + "description": "Get a list of users" + }, + "response": [] + } + ], + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + } + ], + "variable": [ + { + "key": "version", + "value": "1.1.0" + }, + { + "key": "server", + "value": "https://api.io" + }, + { + "key": "page-size", + "value": "10" + }, + { + "key": "company", + "value": "ServicesLTD" + }, + { + "key": "auditor", + "value": "IHA" + }, + { + "key": "service", + "value": "s23434" + } + ] +} \ No newline at end of file diff --git a/test/var-replacer.spec.js b/test/var-replacer.spec.js new file mode 100644 index 0000000..ccf5690 --- /dev/null +++ b/test/var-replacer.spec.js @@ -0,0 +1,16 @@ +'use strict' + +const { describe, it } = require('mocha') +const { readFileSync } = require('fs') +const { equal } = require('assert').strict +const replacePostmanVariables = require('../lib/var-replacer') + +describe('replacePostmanVariables specs', function () { + const VARIABLES_COLLECTION = readFileSync('./test/resources/input/v21/Variables.json', 'utf8') + const RESULT = readFileSync('./test/resources/var-replace/VariablesReplaced.json', 'utf8') + + it('should replace all variables successfully', async function () { + const output = replacePostmanVariables(VARIABLES_COLLECTION) + equal(output, RESULT) + }) +})