diff --git a/crates/yaak-plugins/src/manager.rs b/crates/yaak-plugins/src/manager.rs index 584952f2..e854dd04 100644 --- a/crates/yaak-plugins/src/manager.rs +++ b/crates/yaak-plugins/src/manager.rs @@ -1070,7 +1070,7 @@ impl PluginManager { &InternalEventPayload::ImportRequest(ImportRequest { content: content.to_string(), }), - Duration::from_secs(5), + Duration::from_secs(60), ) .await?; diff --git a/package-lock.json b/package-lock.json index af21ba5a..06182642 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1493,6 +1493,7 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/@exodus/schemasafe/-/schemasafe-1.3.0.tgz", "integrity": "sha512-5Aap/GaRupgNx/feGBwLLTVv8OQFfv3pq2lPRzPg9R+IOBnDgghTGW7l7EuVXOvg5cc/xSAlRW8rBrjIC3Nvqw==", + "dev": true, "license": "MIT" }, "node_modules/@faker-js/faker": { @@ -1500,6 +1501,7 @@ "resolved": "https://registry.npmjs.org/@faker-js/faker/-/faker-5.5.3.tgz", "integrity": "sha512-R11tGE6yIFwqpaIqcfkcg7AICXzFg14+5h5v0TfF/9+RMDL6jhzCy/pxHVOfbALGdtVYdt6JdR21tuxEgl34dw==", "deprecated": "Please update to a newer version.", + "dev": true, "license": "MIT" }, "node_modules/@gilbarbara/deep-equal": { @@ -5777,6 +5779,7 @@ "version": "3.2.6", "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", + "dev": true, "license": "MIT" }, "node_modules/async-function": { @@ -6146,6 +6149,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.2.tgz", "integrity": "sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ==", + "dev": true, "license": "MIT" }, "node_modules/callsites": { @@ -6269,6 +6273,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/charset/-/charset-1.0.1.tgz", "integrity": "sha512-6dVyOOYjpfFcL1Y4qChrAoQLRHvj2ziyhcm0QJlhOcAhykL/k1kTUPbeo+87MNRTRdk2OIIsIXbuF3x2wi5EXg==", + "dev": true, "license": "MIT", "engines": { "node": ">=4.0.0" @@ -6362,6 +6367,120 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/cliui/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/cliui/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/cliui/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/cliui/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/cliui/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/clone-regexp": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/clone-regexp/-/clone-regexp-3.0.0.tgz", @@ -6498,6 +6617,7 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/compute-gcd/-/compute-gcd-1.2.1.tgz", "integrity": "sha512-TwMbxBNz0l71+8Sc4czv13h4kEqnchV9igQZBi6QUaz09dnz13juGnnaWWJTRsP3brxOoxeB4SA2WELLw1hCtg==", + "dev": true, "dependencies": { "validate.io-array": "^1.0.3", "validate.io-function": "^1.0.2", @@ -6508,6 +6628,7 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/compute-lcm/-/compute-lcm-1.1.2.tgz", "integrity": "sha512-OFNPdQAXnQhDSKioX8/XYT6sdUlXwpeMjfd6ApxMJfyZ4GxmLR1xvMERctlYhlHwIiz6CSpBc2+qYKjHGZw4TQ==", + "dev": true, "dependencies": { "compute-gcd": "^1.2.1", "validate.io-array": "^1.0.3", @@ -7659,6 +7780,7 @@ "version": "3.3.1", "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.3.1.tgz", "integrity": "sha512-SOp9Phqvqn7jtEUxPWdWfWoLmyt2VaJ6MpvP9Comy1MceMXqE6bxvaTu4iaxpYYPzhny28Lc+M87/c2cPK6lDg==", + "dev": true, "license": "MIT" }, "node_modules/esbuild": { @@ -7707,6 +7829,7 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -7969,6 +8092,7 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", + "dev": true, "license": "MIT" }, "node_modules/fast-shallow-equal": { @@ -8162,6 +8286,7 @@ "version": "2.0.6", "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.6.tgz", "integrity": "sha512-k6GAGDyqLe9JaebCsFCoudPPWfihKu8pylYXRlqP1J7ms39iPoTtk2fviNglIeQEwdh0bQeKJ01ZPyuyQvKzwg==", + "dev": true, "license": "MIT" }, "node_modules/foreground-child": { @@ -8366,6 +8491,7 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, "license": "ISC", "engines": { "node": "6.* || 8.* || >= 10.*" @@ -8615,6 +8741,7 @@ "version": "2.1.8", "resolved": "https://registry.npmjs.org/graphlib/-/graphlib-2.1.8.tgz", "integrity": "sha512-jcLLfkpoVGmH7/InMC/1hIvOPSUh38oJtGhvrOFGzioE1DZ+0YW16RgmOJhHiuWTvGiJQ9Z1Ik43JvkRPRvE+A==", + "dev": true, "license": "MIT", "dependencies": { "lodash": "^4.17.15" @@ -8924,12 +9051,14 @@ "version": "0.1.0", "resolved": "https://registry.npmjs.org/http-reasons/-/http-reasons-0.1.0.tgz", "integrity": "sha512-P6kYh0lKZ+y29T2Gqz+RlC9WBLhKe8kDmcJ+A+611jFfxdPsbMRQ5aNmFRM3lENqFkK+HTTL+tlQviAiv0AbLQ==", + "dev": true, "license": "Apache-2.0" }, "node_modules/http2-client": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/http2-client/-/http2-client-1.3.5.tgz", "integrity": "sha512-EC2utToWl4RKfs5zd36Mxq7nzHHBuomZboI0yYL6Y0RmBgT7Sgkq4rQ0ezFTYoIsSs7Tm9SJe+o2FcAg6GBhGA==", + "dev": true, "license": "MIT" }, "node_modules/httpntlm": { @@ -9391,6 +9520,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -9864,6 +9994,7 @@ "version": "0.6.2", "resolved": "https://registry.npmjs.org/json-pointer/-/json-pointer-0.6.2.tgz", "integrity": "sha512-vLWcKbOaXlO+jvRy4qNd+TI1QUPZzfJj1tpJ3vAXDych5XJf93ftpUKe5pKCrzyIIwgBJcOcCVRUfqQP25afBw==", + "dev": true, "license": "MIT", "dependencies": { "foreach": "^2.0.4" @@ -9879,6 +10010,7 @@ "version": "0.2.2", "resolved": "https://registry.npmjs.org/json-schema-compare/-/json-schema-compare-0.2.2.tgz", "integrity": "sha512-c4WYmDKyJXhs7WWvAWm3uIYnfyWFoIp+JEoX34rctVvEkMYCPGhXtvmFFXiffBbxfZsvQ0RNnV5H7GvDF5HCqQ==", + "dev": true, "license": "MIT", "dependencies": { "lodash": "^4.17.4" @@ -9903,6 +10035,7 @@ "version": "0.8.1", "resolved": "https://registry.npmjs.org/json-schema-merge-allof/-/json-schema-merge-allof-0.8.1.tgz", "integrity": "sha512-CTUKmIlPJbsWfzRRnOXz+0MjIqvnleIXwFTzz+t9T86HnYX/Rozria6ZVGLktAU9e+NygNljveP+yxqtQp/Q4w==", + "dev": true, "license": "MIT", "dependencies": { "compute-lcm": "^1.1.2", @@ -10329,6 +10462,7 @@ "version": "0.3.1", "resolved": "https://registry.npmjs.org/liquid-json/-/liquid-json-0.3.1.tgz", "integrity": "sha512-wUayTU8MS827Dam6MxgD72Ui+KOSF+u/eIqpatOtjnvgJ0+mnDq33uC2M7J0tPK+upe/DpUAuK4JUU89iBoNKQ==", + "dev": true, "license": "Apache-2.0", "engines": { "node": ">=4" @@ -10354,6 +10488,7 @@ "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true, "license": "MIT" }, "node_modules/lodash.includes": { @@ -11559,6 +11694,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/mime-format/-/mime-format-2.0.2.tgz", "integrity": "sha512-Y5ERWVcyh3sby9Fx2U5F1yatiTFjNsqF5NltihTWI9QgNtr5o3dbCZdcKa1l2wyfhnwwoP9HGNxga7LqZLA6gw==", + "dev": true, "license": "Apache-2.0", "dependencies": { "charset": "^1.0.0" @@ -11775,6 +11911,7 @@ "version": "0.6.15", "resolved": "https://registry.npmjs.org/neotraverse/-/neotraverse-0.6.15.tgz", "integrity": "sha512-HZpdkco+JeXq0G+WWpMJ4NsX3pqb5O7eR9uGz3FfoFt+LYzU8iRWp49nJtud6hsDoywM8tIrDo3gjgmOqJA8LA==", + "dev": true, "license": "MIT", "engines": { "node": ">= 10" @@ -11829,6 +11966,7 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/node-fetch-h2/-/node-fetch-h2-2.3.0.tgz", "integrity": "sha512-ofRW94Ab0T4AOh5Fk8t0h8OBWrmjb0SSB20xh1H8YnPV9EJ+f5AMoYSUQ2zgJ4Iq2HAK0I2l5/Nequ8YzFS3Hg==", + "dev": true, "license": "MIT", "dependencies": { "http2-client": "^1.2.5" @@ -11841,6 +11979,7 @@ "version": "0.2.0", "resolved": "https://registry.npmjs.org/node-readfiles/-/node-readfiles-0.2.0.tgz", "integrity": "sha512-SU00ZarexNlE4Rjdm83vglt5Y9yiQ+XI1XpflWlb7q7UTN1JUItm69xMeiQCTxtTfnzt+83T8Cx+vI2ED++VDA==", + "dev": true, "license": "MIT", "dependencies": { "es6-promise": "^3.2.1" @@ -12016,6 +12155,7 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/oas-kit-common/-/oas-kit-common-1.0.8.tgz", "integrity": "sha512-pJTS2+T0oGIwgjGpw7sIRU8RQMcUoKCDWFLdBqKB2BNmGpbBMH2sdqAaOXUg8OzonZHU0L7vfJu1mJFEiYDWOQ==", + "dev": true, "license": "BSD-3-Clause", "dependencies": { "fast-safe-stringify": "^2.0.7" @@ -12025,6 +12165,7 @@ "version": "3.2.2", "resolved": "https://registry.npmjs.org/oas-linter/-/oas-linter-3.2.2.tgz", "integrity": "sha512-KEGjPDVoU5K6swgo9hJVA/qYGlwfbFx+Kg2QB/kd7rzV5N8N5Mg6PlsoCMohVnQmo+pzJap/F610qTodKzecGQ==", + "dev": true, "license": "BSD-3-Clause", "dependencies": { "@exodus/schemasafe": "^1.0.0-rc.2", @@ -12036,9 +12177,10 @@ } }, "node_modules/oas-linter/node_modules/yaml": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.3.tgz", + "integrity": "sha512-vIYeF1u3CjlhAFekPPAk2h/Kv4T3mAkMox5OymRiJQB0spDP10LHvt+K7G9Ny6NuuMAb25/6n1qyUjAcGNf/AA==", + "dev": true, "license": "ISC", "engines": { "node": ">= 6" @@ -12048,6 +12190,7 @@ "version": "2.5.6", "resolved": "https://registry.npmjs.org/oas-resolver/-/oas-resolver-2.5.6.tgz", "integrity": "sha512-Yx5PWQNZomfEhPPOphFbZKi9W93CocQj18NlD2Pa4GWZzdZpSJvYwoiuurRI7m3SpcChrnO08hkuQDL3FGsVFQ==", + "dev": true, "license": "BSD-3-Clause", "dependencies": { "node-fetch-h2": "^2.3.0", @@ -12067,6 +12210,7 @@ "version": "2.5.6", "resolved": "https://registry.npmjs.org/oas-resolver-browser/-/oas-resolver-browser-2.5.6.tgz", "integrity": "sha512-Jw5elT/kwUJrnGaVuRWe1D7hmnYWB8rfDDjBnpQ+RYY/dzAewGXeTexXzt4fGEo6PUE4eqKqPWF79MZxxvMppA==", + "dev": true, "license": "BSD-3-Clause", "dependencies": { "node-fetch-h2": "^2.3.0", @@ -12083,310 +12227,31 @@ "url": "https://github.com/Mermade/oas-kit?sponsor=1" } }, - "node_modules/oas-resolver-browser/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/oas-resolver-browser/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/oas-resolver-browser/node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "license": "ISC", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/oas-resolver-browser/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/oas-resolver-browser/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "license": "MIT" - }, - "node_modules/oas-resolver-browser/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "license": "MIT" - }, - "node_modules/oas-resolver-browser/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/oas-resolver-browser/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/oas-resolver-browser/node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/oas-resolver-browser/node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "license": "ISC", - "engines": { - "node": ">=10" - } - }, "node_modules/oas-resolver-browser/node_modules/yaml": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.3.tgz", + "integrity": "sha512-vIYeF1u3CjlhAFekPPAk2h/Kv4T3mAkMox5OymRiJQB0spDP10LHvt+K7G9Ny6NuuMAb25/6n1qyUjAcGNf/AA==", + "dev": true, "license": "ISC", "engines": { "node": ">= 6" } }, - "node_modules/oas-resolver-browser/node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "license": "MIT", - "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/oas-resolver-browser/node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/oas-resolver/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/oas-resolver/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/oas-resolver/node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "license": "ISC", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/oas-resolver/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/oas-resolver/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "license": "MIT" - }, - "node_modules/oas-resolver/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "license": "MIT" - }, - "node_modules/oas-resolver/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/oas-resolver/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/oas-resolver/node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/oas-resolver/node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "license": "ISC", - "engines": { - "node": ">=10" - } - }, "node_modules/oas-resolver/node_modules/yaml": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.3.tgz", + "integrity": "sha512-vIYeF1u3CjlhAFekPPAk2h/Kv4T3mAkMox5OymRiJQB0spDP10LHvt+K7G9Ny6NuuMAb25/6n1qyUjAcGNf/AA==", + "dev": true, "license": "ISC", "engines": { "node": ">= 6" } }, - "node_modules/oas-resolver/node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "license": "MIT", - "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/oas-resolver/node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "license": "ISC", - "engines": { - "node": ">=12" - } - }, "node_modules/oas-schema-walker": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/oas-schema-walker/-/oas-schema-walker-1.1.5.tgz", "integrity": "sha512-2yucenq1a9YPmeNExoUa9Qwrt9RFkjqaMAA1X+U7sbb0AqBeTIdMHky9SQQ6iN94bO5NW0W4TRYXerG+BdAvAQ==", + "dev": true, "license": "BSD-3-Clause", "funding": { "url": "https://github.com/Mermade/oas-kit?sponsor=1" @@ -12396,6 +12261,7 @@ "version": "5.0.8", "resolved": "https://registry.npmjs.org/oas-validator/-/oas-validator-5.0.8.tgz", "integrity": "sha512-cu20/HE5N5HKqVygs3dt94eYJfBi0TsZvPVXDhbXQHiEityDN+RROTleefoKRKKJ9dFAF2JBkDHgvWj0sjKGmw==", + "dev": true, "license": "BSD-3-Clause", "dependencies": { "call-me-maybe": "^1.0.1", @@ -12412,9 +12278,10 @@ } }, "node_modules/oas-validator/node_modules/yaml": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.3.tgz", + "integrity": "sha512-vIYeF1u3CjlhAFekPPAk2h/Kv4T3mAkMox5OymRiJQB0spDP10LHvt+K7G9Ny6NuuMAb25/6n1qyUjAcGNf/AA==", + "dev": true, "license": "ISC", "engines": { "node": ">= 6" @@ -12553,6 +12420,7 @@ "version": "5.8.0", "resolved": "https://registry.npmjs.org/openapi-to-postmanv2/-/openapi-to-postmanv2-5.8.0.tgz", "integrity": "sha512-7f02ypBlAx4G9z3bP/uDk8pBwRbYt97Eoso8XJLyclfyRvCC+CvERLUl0MD0x+GoumpkJYnQ0VGdib/kwtUdUw==", + "dev": true, "license": "Apache-2.0", "dependencies": { "ajv": "^8.11.0", @@ -12584,6 +12452,7 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "dev": true, "license": "MIT", "dependencies": { "ajv": "^8.0.0" @@ -12597,10 +12466,24 @@ } } }, + "node_modules/openapi-to-postmanv2/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, "node_modules/openapi-to-postmanv2/node_modules/yaml": { "version": "1.10.2", "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "dev": true, "license": "ISC", "engines": { "node": ">= 6" @@ -12892,6 +12775,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", + "dev": true, "license": "MIT" }, "node_modules/path-key": { @@ -13337,9 +13221,10 @@ "license": "MIT" }, "node_modules/postman-collection": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/postman-collection/-/postman-collection-5.2.0.tgz", - "integrity": "sha512-ktjlchtpoCw+FZRg+WwnGWH1w9oQDNUBLSRh+9ETPqFAz3SupqHqRuMh74xjQ+PvTWY/WH2JR4ZW+1sH58Ul1g==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/postman-collection/-/postman-collection-5.3.0.tgz", + "integrity": "sha512-PMa5vRheqDFfS1bkRg8WBidWxunRA80sT5YNLP27YC5+ycyfiLMCwPnqQd1zfvxkGk04Pr9UronWmmgsbpsVyQ==", + "dev": true, "license": "Apache-2.0", "dependencies": { "@faker-js/faker": "5.5.3", @@ -13347,7 +13232,7 @@ "http-reasons": "0.1.0", "iconv-lite": "0.6.3", "liquid-json": "0.3.1", - "lodash": "4.17.21", + "lodash": "4.17.23", "mime": "3.0.0", "mime-format": "2.0.2", "postman-url-encoder": "3.0.8", @@ -13362,6 +13247,7 @@ "version": "3.9.0", "resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz", "integrity": "sha512-RLoqTXE8/vPmMuTI88DAzhMYC99I8BWv7zYP4A1puo5HIjEJ5EX48ighy4ZyKMG9EDXxBgW6e++cn7d1xuFghA==", + "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -13371,6 +13257,7 @@ "version": "0.6.3", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, "license": "MIT", "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" @@ -13379,10 +13266,18 @@ "node": ">=0.10.0" } }, + "node_modules/postman-collection/node_modules/lodash": { + "version": "4.17.23", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz", + "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==", + "dev": true, + "license": "MIT" + }, "node_modules/postman-collection/node_modules/mime": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==", + "dev": true, "license": "MIT", "bin": { "mime": "cli.js" @@ -13395,6 +13290,7 @@ "version": "7.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", + "dev": true, "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -13407,6 +13303,7 @@ "version": "3.0.8", "resolved": "https://registry.npmjs.org/postman-url-encoder/-/postman-url-encoder-3.0.8.tgz", "integrity": "sha512-EOgUMBazo7JNP4TDrd64TsooCiWzzo4143Ws8E8WYGEpn2PKpq+S4XRTDhuRTYHm3VKOpUZs7ZYZq7zSDuesqA==", + "dev": true, "license": "Apache-2.0", "dependencies": { "punycode": "^2.3.1" @@ -13856,6 +13753,7 @@ "version": "1.1.9", "resolved": "https://registry.npmjs.org/reftools/-/reftools-1.1.9.tgz", "integrity": "sha512-OVede/NQE13xBQ+ob5CKd5KyeJYU2YInb1bmV4nRoOfquZPkAkxuOXicSe1PvqIuZZ4kD13sPKBbR7UFDmli6w==", + "dev": true, "license": "BSD-3-Clause", "funding": { "url": "https://github.com/Mermade/oas-kit?sponsor=1" @@ -13982,6 +13880,7 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -14566,6 +14465,7 @@ "version": "13.2.3", "resolved": "https://registry.npmjs.org/should/-/should-13.2.3.tgz", "integrity": "sha512-ggLesLtu2xp+ZxI+ysJTmNjh2U0TsC+rQ/pfED9bUZZ4DKefP27D+7YJVVTvKsmjLpIi9jAa7itwDGkDDmt1GQ==", + "dev": true, "license": "MIT", "dependencies": { "should-equal": "^2.0.0", @@ -14579,6 +14479,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/should-equal/-/should-equal-2.0.0.tgz", "integrity": "sha512-ZP36TMrK9euEuWQYBig9W55WPC7uo37qzAEmbjHz4gfyuXrEUgF8cUvQVO+w+d3OMfPvSRQJ22lSm8MQJ43LTA==", + "dev": true, "license": "MIT", "dependencies": { "should-type": "^1.4.0" @@ -14588,6 +14489,7 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/should-format/-/should-format-3.0.3.tgz", "integrity": "sha512-hZ58adtulAk0gKtua7QxevgUaXTTXxIi8t41L3zo9AHvjXO1/7sdLECuHeIN2SRtYXpNkmhoUP2pdeWgricQ+Q==", + "dev": true, "license": "MIT", "dependencies": { "should-type": "^1.3.0", @@ -14598,12 +14500,14 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/should-type/-/should-type-1.4.0.tgz", "integrity": "sha512-MdAsTu3n25yDbIe1NeN69G4n6mUnJGtSJHygX3+oN0ZbO3DTiATnf7XnYJdGT42JCXurTb1JI0qOBR65shvhPQ==", + "dev": true, "license": "MIT" }, "node_modules/should-type-adaptors": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/should-type-adaptors/-/should-type-adaptors-1.1.0.tgz", "integrity": "sha512-JA4hdoLnN+kebEp2Vs8eBe9g7uy0zbRo+RMcU0EsNy+R+k049Ki+N5tT5Jagst2g7EAja+euFuoXFCa8vIklfA==", + "dev": true, "license": "MIT", "dependencies": { "should-type": "^1.3.0", @@ -14614,6 +14518,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/should-util/-/should-util-1.0.1.tgz", "integrity": "sha512-oXF8tfxx5cDk8r2kYqlkUJzZpDBqVY/II2WhvU0n9Y3XYvAYRmeaf1PvvIvTgPnv4KJ+ES5M0PyDq5Jp+Ygy2g==", + "dev": true, "license": "MIT" }, "node_modules/side-channel": { @@ -15299,6 +15204,7 @@ "version": "7.0.8", "resolved": "https://registry.npmjs.org/swagger2openapi/-/swagger2openapi-7.0.8.tgz", "integrity": "sha512-upi/0ZGkYgEcLeGieoz8gT74oWHA0E7JivX7aN9mAf+Tc7BQoRBvnIGHoPDw+f9TXTW4s6kGYCZJtauP6OYp7g==", + "dev": true, "license": "BSD-3-Clause", "dependencies": { "call-me-maybe": "^1.0.1", @@ -15322,156 +15228,16 @@ "url": "https://github.com/Mermade/oas-kit?sponsor=1" } }, - "node_modules/swagger2openapi/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/swagger2openapi/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/swagger2openapi/node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "license": "ISC", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/swagger2openapi/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/swagger2openapi/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "license": "MIT" - }, - "node_modules/swagger2openapi/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "license": "MIT" - }, - "node_modules/swagger2openapi/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/swagger2openapi/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/swagger2openapi/node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/swagger2openapi/node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "license": "ISC", - "engines": { - "node": ">=10" - } - }, "node_modules/swagger2openapi/node_modules/yaml": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.3.tgz", + "integrity": "sha512-vIYeF1u3CjlhAFekPPAk2h/Kv4T3mAkMox5OymRiJQB0spDP10LHvt+K7G9Ny6NuuMAb25/6n1qyUjAcGNf/AA==", + "dev": true, "license": "ISC", "engines": { "node": ">= 6" } }, - "node_modules/swagger2openapi/node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "license": "MIT", - "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/swagger2openapi/node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "license": "ISC", - "engines": { - "node": ">=12" - } - }, "node_modules/tabbable": { "version": "6.4.0", "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.4.0.tgz", @@ -16191,6 +15957,8 @@ "version": "8.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "deprecated": "uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028).", + "dev": true, "license": "MIT", "bin": { "uuid": "dist/bin/uuid" @@ -16216,17 +15984,20 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/validate.io-array/-/validate.io-array-1.0.6.tgz", "integrity": "sha512-DeOy7CnPEziggrOO5CZhVKJw6S3Yi7e9e65R1Nl/RTN1vTQKnzjfvks0/8kQ40FP/dsjRAOd4hxmJ7uLa6vxkg==", + "dev": true, "license": "MIT" }, "node_modules/validate.io-function": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/validate.io-function/-/validate.io-function-1.0.2.tgz", - "integrity": "sha512-LlFybRJEriSuBnUhQyG5bwglhh50EpTL2ul23MPIuR1odjO7XaMLFV8vHGwp7AZciFxtYOeiSCT5st+XSPONiQ==" + "integrity": "sha512-LlFybRJEriSuBnUhQyG5bwglhh50EpTL2ul23MPIuR1odjO7XaMLFV8vHGwp7AZciFxtYOeiSCT5st+XSPONiQ==", + "dev": true }, "node_modules/validate.io-integer": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/validate.io-integer/-/validate.io-integer-1.0.5.tgz", "integrity": "sha512-22izsYSLojN/P6bppBqhgUDjCkr5RY2jd+N2a3DCAUey8ydvrZ/OkGvFPR7qfOpwR2LC5p4Ngzxz36g5Vgr/hQ==", + "dev": true, "dependencies": { "validate.io-number": "^1.0.3" } @@ -16235,6 +16006,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/validate.io-integer-array/-/validate.io-integer-array-1.0.0.tgz", "integrity": "sha512-mTrMk/1ytQHtCY0oNO3dztafHYyGU88KL+jRxWuzfOmQb+4qqnWmI+gykvGp8usKZOM0H7keJHEbRaFiYA0VrA==", + "dev": true, "dependencies": { "validate.io-array": "^1.0.3", "validate.io-integer": "^1.0.4" @@ -16243,7 +16015,8 @@ "node_modules/validate.io-number": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/validate.io-number/-/validate.io-number-1.0.3.tgz", - "integrity": "sha512-kRAyotcbNaSYoDnXvb4MHg/0a1egJdLwS6oJ38TJY7aw9n93Fl/3blIXdyYvPOp55CNxywooG/3BcrwNrBpcSg==" + "integrity": "sha512-kRAyotcbNaSYoDnXvb4MHg/0a1egJdLwS6oJ38TJY7aw9n93Fl/3blIXdyYvPOp55CNxywooG/3BcrwNrBpcSg==", + "dev": true }, "node_modules/vary": { "version": "1.1.2", @@ -16892,6 +16665,16 @@ "node": ">=0.4" } }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, "node_modules/yallist": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", @@ -16914,6 +16697,80 @@ "url": "https://github.com/sponsors/eemeli" } }, + "node_modules/yargs": { + "version": "17.7.3", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.3.tgz", + "integrity": "sha512-GZtjxm/J/4TSxuL3FNYjCmLktBTnIw/rVmKSIyKeYAZpmJB2ig9VauCC5xsa82GNKVKDAqpOn3KVzNt0zmrU0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/yargs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/yauzl": { "version": "2.10.0", "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", @@ -17206,11 +17063,11 @@ "name": "@yaak/importer-openapi", "version": "0.1.0", "dependencies": { - "openapi-to-postmanv2": "^5.8.0", "yaml": "^2.8.3" }, "devDependencies": { - "@types/openapi-to-postmanv2": "^5.0.0" + "@types/openapi-to-postmanv2": "^5.0.0", + "openapi-to-postmanv2": "^5.8.0" } }, "plugins/importer-postman": { diff --git a/plugins/importer-openapi/package.json b/plugins/importer-openapi/package.json index 5b119b53..8d34ebab 100644 --- a/plugins/importer-openapi/package.json +++ b/plugins/importer-openapi/package.json @@ -10,10 +10,10 @@ "test": "vp test --run tests" }, "dependencies": { - "openapi-to-postmanv2": "^5.8.0", "yaml": "^2.8.3" }, "devDependencies": { - "@types/openapi-to-postmanv2": "^5.0.0" + "@types/openapi-to-postmanv2": "^5.0.0", + "openapi-to-postmanv2": "^5.8.0" } } diff --git a/plugins/importer-openapi/src/index.ts b/plugins/importer-openapi/src/index.ts index a5ed442e..02e3ef4d 100644 --- a/plugins/importer-openapi/src/index.ts +++ b/plugins/importer-openapi/src/index.ts @@ -1,7 +1,35 @@ -import { convertPostman } from "@yaak/importer-postman/src"; -import type { Context, PluginDefinition } from "@yaakapp/api"; +import type { + Context, + Folder, + HttpRequest, + HttpRequestHeader, + HttpUrlParameter, + PartialImportResources, + PluginDefinition, + Workspace, +} from "@yaakapp/api"; import type { ImportPluginResponse } from "@yaakapp/api/lib/plugins/ImporterPlugin"; -import { convert } from "openapi-to-postmanv2"; +import YAML from "yaml"; + +type AtLeast = Partial & Pick; +type UnknownRecord = Record; +type ImportResources = { + workspaces: AtLeast[]; + folders: AtLeast[]; + httpRequests: AtLeast[]; +}; + +const HTTP_METHODS = ["delete", "get", "head", "options", "patch", "post", "put", "trace"]; +const BODY_CONTENT_TYPE_PREFERENCE = [ + "application/json", + "application/x-www-form-urlencoded", + "multipart/form-data", + "application/xml", + "text/plain", +]; +const MAX_EXAMPLE_DEPTH = 8; +const MAX_EXAMPLE_PROPERTIES = 25; +const MAX_DESCRIPTION_ITEMS = 40; export const plugin: PluginDefinition = { importer: { @@ -14,23 +42,754 @@ export const plugin: PluginDefinition = { }; export async function convertOpenApi(contents: string): Promise { - // oxlint-disable-next-line no-explicit-any - let postmanCollection: any; - try { - postmanCollection = await new Promise((resolve, reject) => { - // oxlint-disable-next-line no-explicit-any - convert({ type: "string", data: contents }, {}, (err, result: any) => { - if (err != null) reject(err); + const spec = parseSpec(contents); + if (!isOpenApiSpec(spec)) return undefined; - if (Array.isArray(result.output) && result.output.length > 0) { - resolve(result.output[0].data); - } - }); - }); - } catch { - // Probably not an OpenAPI file, so skip it - return undefined; + const importState = new ImportState(spec); + const workspace: ImportResources["workspaces"][0] = { + model: "workspace", + id: importState.generateId("workspace"), + name: stringAt(spec.info, "title") ?? "OpenAPI Import", + description: importInfoDescription(toRecord(spec.info)), + }; + + const resources: ImportResources = { + workspaces: [workspace], + folders: [], + httpRequests: [], + }; + + const folderIdsByTag = new Map(); + for (const tag of toArray(spec.tags)) { + const tagRecord = toRecord(tag); + const name = stringAt(tagRecord, "name"); + if (name == null || folderIdsByTag.has(name)) continue; + + const folder: ImportResources["folders"][0] = { + model: "folder", + id: importState.generateId("folder"), + workspaceId: workspace.id, + name, + description: importTagDescription(tagRecord), + folderId: null, + sortPriority: importState.nextSortPriority(), + }; + resources.folders.push(folder); + folderIdsByTag.set(name, folder.id); } - return convertPostman(JSON.stringify(postmanCollection)); + for (const [rawPath, rawPathItem] of Object.entries(toRecord(spec.paths))) { + const pathItem = importState.resolve(rawPathItem); + if (!isRecord(pathItem)) continue; + + const pathParameters = toArray(pathItem.parameters); + for (const method of HTTP_METHODS) { + const operation = importState.resolve(pathItem[method]); + if (!isRecord(operation)) continue; + + const folderId = findOrCreateFolderId({ + folderIdsByTag, + importState, + operation, + resources, + workspaceId: workspace.id, + }); + + resources.httpRequests.push( + importOperation({ + importState, + method, + operation, + path: rawPath, + pathParameters, + spec, + workspaceId: workspace.id, + folderId, + }), + ); + } + } + + if (resources.httpRequests.length === 0) return undefined; + + return { + resources: deleteUndefinedAttrs( + convertTemplateSyntax({ + environments: [], + folders: resources.folders, + grpcRequests: [], + httpRequests: resources.httpRequests, + websocketRequests: [], + workspaces: resources.workspaces, + }), + ) as PartialImportResources, + }; +} + +function importOperation({ + importState, + method, + operation, + path, + pathParameters, + spec, + workspaceId, + folderId, +}: { + importState: ImportState; + method: string; + operation: UnknownRecord; + path: string; + pathParameters: unknown[]; + spec: UnknownRecord; + workspaceId: string; + folderId: string | null; +}): ImportResources["httpRequests"][0] { + const parameters = [...pathParameters, ...toArray(operation.parameters)].map((p) => + importState.resolve(p), + ); + const body = importBody({ importState, operation, parameters, spec }); + const urlParameters = importUrlParameters({ importState, parameters }); + const headers = mergeHeaders(importHeaderParameters({ importState, parameters }), body.headers); + + return { + model: "http_request", + id: importState.generateId("http_request"), + workspaceId, + folderId, + name: importOperationName(operation, method, path), + description: importOperationDescription({ + importState, + operation, + parameters, + bodyContentType: body.bodyType, + }), + method: method.toUpperCase(), + url: buildOperationUrl(spec, path), + urlParameters, + headers, + body: body.body, + bodyType: body.bodyType, + sortPriority: importState.nextSortPriority(), + ...importAuthentication({ importState, operation, spec }), + }; +} + +function parseSpec(contents: string): unknown { + try { + return JSON.parse(contents); + } catch { + // Fall through to YAML. + } + + try { + return YAML.parse(contents); + } catch { + return null; + } +} + +function isOpenApiSpec(value: unknown): value is UnknownRecord { + const spec = toRecord(value); + const openapi = stringAt(spec, "openapi"); + const swagger = stringAt(spec, "swagger"); + return isRecord(spec.paths) && (openapi?.startsWith("3.") === true || swagger === "2.0"); +} + +function importInfoDescription(info: UnknownRecord): string | undefined { + const parts = [ + stringAt(info, "description"), + stringAt(info, "termsOfService") + ? `Terms of service: ${stringAt(info, "termsOfService")}` + : null, + isRecord(info.contact) && stringAt(info.contact, "email") + ? `Contact: ${stringAt(info.contact, "email")}` + : null, + isRecord(info.license) && stringAt(info.license, "name") + ? `License: ${stringAt(info.license, "name")}${ + stringAt(info.license, "url") ? ` (${stringAt(info.license, "url")})` : "" + }` + : null, + ].filter(isPresent); + return parts.length > 0 ? parts.join("\n\n") : undefined; +} + +function importTagDescription(tag: UnknownRecord): string | undefined { + const externalDocs = toRecord(tag.externalDocs); + const parts = [ + stringAt(tag, "description"), + stringAt(externalDocs, "url") + ? `${stringAt(externalDocs, "description") ?? "External docs"}: ${stringAt(externalDocs, "url")}` + : null, + ].filter(isPresent); + return parts.length > 0 ? parts.join("\n\n") : undefined; +} + +function importOperationName(operation: UnknownRecord, method: string, path: string): string { + return ( + stringAt(operation, "summary") ?? + stringAt(operation, "operationId") ?? + `${method.toUpperCase()} ${path}` + ); +} + +function importOperationDescription({ + importState, + operation, + parameters, + bodyContentType, +}: { + importState: ImportState; + operation: UnknownRecord; + parameters: unknown[]; + bodyContentType: string | null; +}): string | undefined { + const parts: string[] = []; + const summary = stringAt(operation, "summary"); + const description = stringAt(operation, "description"); + const operationId = stringAt(operation, "operationId"); + + if (description != null) { + parts.push(description); + } else if (summary != null) { + parts.push(summary); + } + + if (operationId != null) { + parts.push(`Operation ID: ${operationId}`); + } + + const parameterDescriptions = parameters + .map((p) => importState.resolve(p)) + .filter(isRecord) + .slice(0, MAX_DESCRIPTION_ITEMS) + .map((p) => { + const name = stringAt(p, "name") ?? "parameter"; + const location = stringAt(p, "in") ?? "unknown"; + const required = p.required === true ? ", required" : ""; + const description = stringAt(p, "description"); + return `- ${name} (${location}${required})${description ? `: ${description}` : ""}`; + }); + if (parameterDescriptions.length > 0) { + parts.push(["Parameters:", ...parameterDescriptions].join("\n")); + } + + const requestBody = importState.resolve(operation.requestBody); + if (isRecord(requestBody)) { + const content = toRecord(requestBody.content); + const contentTypes = Object.keys(content); + const bodyLines = [ + stringAt(requestBody, "description"), + bodyContentType ? `Selected content type: ${bodyContentType}` : null, + contentTypes.length > 0 ? `Available content types: ${contentTypes.join(", ")}` : null, + ].filter(isPresent); + if (bodyLines.length > 0) { + parts.push(["Request body:", ...bodyLines].join("\n")); + } + } + + const responseDescriptions = Object.entries(toRecord(operation.responses)) + .slice(0, MAX_DESCRIPTION_ITEMS) + .map(([status, response]) => { + const responseRecord = toRecord(importState.resolve(response)); + return `- ${status}: ${stringAt(responseRecord, "description") ?? ""}`.trimEnd(); + }); + if (responseDescriptions.length > 0) { + parts.push(["Responses:", ...responseDescriptions].join("\n")); + } + + const externalDocs = toRecord(operation.externalDocs); + if (stringAt(externalDocs, "url")) { + parts.push( + `${stringAt(externalDocs, "description") ?? "External docs"}: ${stringAt(externalDocs, "url")}`, + ); + } + + return parts.length > 0 ? parts.join("\n\n") : undefined; +} + +function findOrCreateFolderId({ + folderIdsByTag, + importState, + operation, + resources, + workspaceId, +}: { + folderIdsByTag: Map; + importState: ImportState; + operation: UnknownRecord; + resources: ImportResources; + workspaceId: string; +}): string | null { + const tag = toArray(operation.tags).find((t): t is string => typeof t === "string"); + if (tag == null) return null; + + const existingFolderId = folderIdsByTag.get(tag); + if (existingFolderId != null) return existingFolderId; + + const folder: ImportResources["folders"][0] = { + model: "folder", + id: importState.generateId("folder"), + workspaceId, + name: tag, + folderId: null, + sortPriority: importState.nextSortPriority(), + }; + resources.folders.push(folder); + folderIdsByTag.set(tag, folder.id); + return folder.id; +} + +function buildOperationUrl(spec: UnknownRecord, path: string): string { + return joinUrlParts(importBaseUrl(spec), path.replaceAll(/{([^}/]+)}/g, ":$1")); +} + +function importBaseUrl(spec: UnknownRecord): string { + const openApiServer = toArray(spec.servers) + .map((s) => toRecord(s)) + .map((s) => interpolateServerUrl(s)) + .find((url) => url.length > 0); + if (openApiServer != null) return openApiServer; + + const host = stringAt(spec, "host"); + if (host == null) return stringAt(spec, "basePath") ?? ""; + + const scheme = toArray(spec.schemes).find((s): s is string => typeof s === "string") ?? "https"; + return joinUrlParts(`${scheme}://${host}`, stringAt(spec, "basePath") ?? ""); +} + +function interpolateServerUrl(server: UnknownRecord): string { + let url = stringAt(server, "url") ?? ""; + for (const [name, variable] of Object.entries(toRecord(server.variables))) { + url = url.replaceAll(`{${name}}`, stringifyExampleValue(toRecord(variable).default)); + } + return url; +} + +function joinUrlParts(baseUrl: string, path: string): string { + if (baseUrl.length === 0) return path; + return `${baseUrl.replace(/\/+$/, "")}/${path.replace(/^\/+/, "")}`; +} + +function importUrlParameters({ + importState, + parameters, +}: { + importState: ImportState; + parameters: unknown[]; +}): HttpUrlParameter[] { + return parameters + .map((p) => importState.resolve(p)) + .filter(isRecord) + .filter((p) => stringAt(p, "in") === "query" || stringAt(p, "in") === "path") + .map((p) => ({ + enabled: p.required === true, + name: + stringAt(p, "in") === "path" + ? `:${stringAt(p, "name") ?? ""}` + : (stringAt(p, "name") ?? ""), + value: parameterExample(p, importState), + })) + .filter(({ name }) => name.length > 0); +} + +function importHeaderParameters({ + importState, + parameters, +}: { + importState: ImportState; + parameters: unknown[]; +}): HttpRequestHeader[] { + return parameters + .map((p) => importState.resolve(p)) + .filter(isRecord) + .filter((p) => stringAt(p, "in") === "header") + .map((p) => ({ + enabled: p.required === true, + name: stringAt(p, "name") ?? "", + value: parameterExample(p, importState), + })) + .filter(({ name }) => name.length > 0); +} + +function parameterExample(parameter: UnknownRecord, importState: ImportState): string { + const directExample = firstPresent(parameter.example, firstExampleValue(parameter.examples)); + if (directExample != null) return stringifyExampleValue(directExample); + return stringifyExampleValue(schemaToExample(importState.resolve(parameter.schema), importState)); +} + +function importBody({ + importState, + operation, + parameters, + spec, +}: { + importState: ImportState; + operation: UnknownRecord; + parameters: unknown[]; + spec: UnknownRecord; +}): { + headers: HttpRequestHeader[]; + body: Record; + bodyType: string | null; +} { + const openApiRequestBody = importState.resolve(operation.requestBody); + if (isRecord(openApiRequestBody)) { + return importBodyFromContent(importState, toRecord(openApiRequestBody.content)); + } + + const bodyParameter = parameters + .map((p) => importState.resolve(p)) + .find((p) => isRecord(p) && stringAt(p, "in") === "body"); + if (isRecord(bodyParameter)) { + const contentType = toArray(spec.consumes).find((c): c is string => typeof c === "string"); + const bodyType = contentType ?? "application/json"; + return { + headers: [{ enabled: true, name: "Content-Type", value: bodyType }], + bodyType, + body: { + text: formatBodyText( + schemaToExample(importState.resolve(bodyParameter.schema), importState), + ), + }, + }; + } + + const formParameters = parameters + .map((p) => importState.resolve(p)) + .filter(isRecord) + .filter((p) => stringAt(p, "in") === "formData"); + if (formParameters.length > 0) { + const contentType = + toArray(spec.consumes).find((c): c is string => typeof c === "string") ?? + (formParameters.some((p) => stringAt(p, "type") === "file") + ? "multipart/form-data" + : "application/x-www-form-urlencoded"); + return { + headers: [{ enabled: true, name: "Content-Type", value: contentType }], + bodyType: contentType, + body: { + form: formParameters.map((p) => ({ + enabled: p.required === true, + name: stringAt(p, "name") ?? "", + value: parameterExample(p, importState), + })), + }, + }; + } + + return { headers: [], body: {}, bodyType: null }; +} + +function importBodyFromContent(importState: ImportState, content: UnknownRecord) { + const contentType = chooseContentType(Object.keys(content)); + if (contentType == null) return { headers: [], body: {}, bodyType: null }; + + const mediaType = toRecord(content[contentType]); + const example = mediaTypeExample(mediaType, importState); + + if ( + contentType === "application/x-www-form-urlencoded" || + contentType === "multipart/form-data" + ) { + return { + headers: [{ enabled: true, name: "Content-Type", value: contentType }], + bodyType: contentType, + body: { + form: schemaToFormParameters(importState.resolve(mediaType.schema), importState), + }, + }; + } + + return { + headers: [{ enabled: true, name: "Content-Type", value: contentType }], + bodyType: contentType === "application/octet-stream" ? "binary" : contentType, + body: contentType === "application/octet-stream" ? {} : { text: formatBodyText(example) }, + }; +} + +function chooseContentType(contentTypes: string[]): string | null { + for (const preference of BODY_CONTENT_TYPE_PREFERENCE) { + const exact = contentTypes.find((c) => c.toLowerCase() === preference); + if (exact != null) return exact; + } + return contentTypes[0] ?? null; +} + +function mediaTypeExample(mediaType: UnknownRecord, importState: ImportState): unknown { + const directExample = firstPresent(mediaType.example, firstExampleValue(mediaType.examples)); + if (directExample != null) return directExample; + return schemaToExample(importState.resolve(mediaType.schema), importState); +} + +function schemaToFormParameters(schema: unknown, importState: ImportState) { + const resolvedSchema = toRecord(importState.resolve(schema)); + const required = toArray(resolvedSchema.required).filter( + (name): name is string => typeof name === "string", + ); + const properties = Object.entries(toRecord(resolvedSchema.properties)).slice( + 0, + MAX_EXAMPLE_PROPERTIES, + ); + + return properties.map(([name, property]) => { + const resolvedProperty = toRecord(importState.resolve(property)); + const example = schemaToExample(resolvedProperty, importState); + const base = { + enabled: required.includes(name), + name, + }; + if (stringAt(resolvedProperty, "format") === "binary") { + return { ...base, file: "" }; + } + return { ...base, value: stringifyExampleValue(example) }; + }); +} + +function schemaToExample( + schema: unknown, + importState: ImportState, + depth = 0, + visitedRefs = new Set(), +): unknown { + if (depth > MAX_EXAMPLE_DEPTH) return {}; + + const resolved = importState.resolve(schema, visitedRefs); + if (!isRecord(resolved)) return ""; + + const explicitExample = firstPresent( + resolved.example, + firstExampleValue(resolved.examples), + resolved.default, + ); + if (explicitExample != null) return explicitExample; + + const enumValues = toArray(resolved.enum); + if (enumValues.length > 0) return enumValues[0]; + + const allOf = toArray(resolved.allOf); + if (allOf.length > 0) { + return allOf.reduce((merged, childSchema) => { + const childExample = schemaToExample(childSchema, importState, depth + 1, visitedRefs); + return isRecord(childExample) ? { ...merged, ...childExample } : merged; + }, {}); + } + + const oneOf = toArray(resolved.oneOf); + const anyOf = toArray(resolved.anyOf); + if (oneOf.length > 0 || anyOf.length > 0) { + return schemaToExample(oneOf[0] ?? anyOf[0], importState, depth + 1, visitedRefs); + } + + const type = inferSchemaType(resolved); + if (type === "array") { + return [schemaToExample(resolved.items, importState, depth + 1, visitedRefs)]; + } + if (type === "object") { + const required = toArray(resolved.required).filter( + (name): name is string => typeof name === "string", + ); + const properties = Object.entries(toRecord(resolved.properties)).sort(([a], [b]) => { + const aRequired = required.includes(a); + const bRequired = required.includes(b); + return aRequired === bRequired ? 0 : aRequired ? -1 : 1; + }); + + return Object.fromEntries( + properties + .slice(0, MAX_EXAMPLE_PROPERTIES) + .map(([name, property]) => [ + name, + schemaToExample(property, importState, depth + 1, visitedRefs), + ]), + ); + } + if (type === "integer" || type === "number") return 0; + if (type === "boolean") return false; + if (stringAt(resolved, "format") === "date-time") return "2026-01-01T00:00:00Z"; + if (stringAt(resolved, "format") === "date") return "2026-01-01"; + return ""; +} + +function inferSchemaType(schema: UnknownRecord): string { + const rawType = schema.type; + if (typeof rawType === "string") return rawType; + if (Array.isArray(rawType)) { + const nonNullType = rawType.find((t) => t !== "null"); + if (typeof nonNullType === "string") return nonNullType; + } + if (isRecord(schema.properties) || isRecord(schema.additionalProperties)) return "object"; + if (schema.items != null) return "array"; + return "string"; +} + +function importAuthentication({ + importState, + operation, + spec, +}: { + importState: ImportState; + operation: UnknownRecord; + spec: UnknownRecord; +}): Pick { + const security = operation.security ?? spec.security; + if (!Array.isArray(security) || security.length === 0) { + return { authenticationType: null, authentication: {} }; + } + + const schemes = { + ...toRecord(toRecord(spec.components).securitySchemes), + ...toRecord(spec.securityDefinitions), + }; + for (const requirement of security) { + for (const schemeName of Object.keys(toRecord(requirement))) { + const scheme = toRecord(importState.resolve(schemes[schemeName])); + const type = stringAt(scheme, "type"); + if (type === "apiKey") { + return { + authenticationType: "apikey", + authentication: { + location: stringAt(scheme, "in") === "query" ? "query" : "header", + key: stringAt(scheme, "name") ?? schemeName, + value: "", + }, + }; + } + if (type === "http" && stringAt(scheme, "scheme")?.toLowerCase() === "basic") { + return { + authenticationType: "basic", + authentication: { username: "", password: "" }, + }; + } + if (type === "http" && stringAt(scheme, "scheme")?.toLowerCase() === "bearer") { + return { + authenticationType: "bearer", + authentication: { token: "", prefix: "Bearer" }, + }; + } + } + } + + return { authenticationType: null, authentication: {} }; +} + +function mergeHeaders(...headerGroups: HttpRequestHeader[][]): HttpRequestHeader[] { + const headers: HttpRequestHeader[] = []; + for (const header of headerGroups.flat()) { + const existing = headers.find((h) => h.name.toLowerCase() === header.name.toLowerCase()); + if (existing == null) { + headers.push(header); + } + } + return headers; +} + +function formatBodyText(example: unknown): string { + return typeof example === "string" ? example : JSON.stringify(example, null, 2); +} + +function stringifyExampleValue(value: unknown): string { + if (value == null) return ""; + if (typeof value === "string") return value; + if (typeof value === "number" || typeof value === "boolean") return String(value); + return JSON.stringify(value); +} + +function firstExampleValue(examples: unknown): unknown { + const firstExample = Object.values(toRecord(examples))[0]; + if (isRecord(firstExample) && "value" in firstExample) return firstExample.value; + return firstExample; +} + +function firstPresent(...values: unknown[]): unknown { + return values.find((value) => value !== undefined && value !== null); +} + +function stringAt(record: unknown, key: string): string | undefined { + const value = toRecord(record)[key]; + return typeof value === "string" ? value : undefined; +} + +function toArray(value: unknown): unknown[] { + return Array.isArray(value) ? value : []; +} + +function toRecord(value: unknown): UnknownRecord { + return isRecord(value) ? value : {}; +} + +function isRecord(value: unknown): value is UnknownRecord { + return value != null && typeof value === "object" && !Array.isArray(value); +} + +function isPresent(value: T | null | undefined): value is T { + return value != null && value !== ""; +} + +/** Recursively render all nested object properties */ +function convertTemplateSyntax(obj: T): T { + if (typeof obj === "string") { + // oxlint-disable-next-line no-template-curly-in-string -- Yaak template syntax + return obj.replaceAll(/{{\s*(_\.)?([^}]+)\s*}}/g, "${[$2]}") as T; + } + if (Array.isArray(obj) && obj != null) { + return obj.map(convertTemplateSyntax) as T; + } + if (typeof obj === "object" && obj != null) { + return Object.fromEntries( + Object.entries(obj).map(([k, v]) => [k, convertTemplateSyntax(v)]), + ) as T; + } + return obj; +} + +function deleteUndefinedAttrs(obj: T): T { + if (Array.isArray(obj) && obj != null) { + return obj.map(deleteUndefinedAttrs) as T; + } + if (typeof obj === "object" && obj != null) { + return Object.fromEntries( + Object.entries(obj) + .filter(([, v]) => v !== undefined) + .map(([k, v]) => [k, deleteUndefinedAttrs(v)]), + ) as T; + } + return obj; +} + +class ImportState { + readonly #spec: UnknownRecord; + readonly #idCount: Partial> = {}; + #sortPriority = 0; + + constructor(spec: UnknownRecord) { + this.#spec = spec; + } + + generateId(model: string): string { + this.#idCount[model] = (this.#idCount[model] ?? -1) + 1; + return `GENERATE_ID::${model.toUpperCase()}_${this.#idCount[model]}`; + } + + nextSortPriority(): number { + return this.#sortPriority++; + } + + resolve(value: unknown, visitedRefs = new Set()): unknown { + if (!isRecord(value) || typeof value.$ref !== "string") return value; + if (visitedRefs.has(value.$ref)) return {}; + + const nextVisitedRefs = new Set(visitedRefs); + nextVisitedRefs.add(value.$ref); + + if (!value.$ref.startsWith("#/")) return value; + + const resolved = value.$ref + .slice(2) + .split("/") + .map((part) => part.replaceAll("~1", "/").replaceAll("~0", "~")) + .reduce((current, part) => toRecord(current)[part], this.#spec); + + return this.resolve(resolved, nextVisitedRefs); + } } diff --git a/plugins/importer-openapi/src/legacy.ts b/plugins/importer-openapi/src/legacy.ts new file mode 100644 index 00000000..7492abf6 --- /dev/null +++ b/plugins/importer-openapi/src/legacy.ts @@ -0,0 +1,26 @@ +import { convertPostman } from "@yaak/importer-postman/src"; +import type { ImportPluginResponse } from "@yaakapp/api/lib/plugins/ImporterPlugin"; +import { convert } from "openapi-to-postmanv2"; + +export async function convertOpenApiWithPostman( + contents: string, +): Promise { + // oxlint-disable-next-line no-explicit-any + let postmanCollection: any; + try { + postmanCollection = await new Promise((resolve, reject) => { + // oxlint-disable-next-line no-explicit-any + convert({ type: "string", data: contents }, {}, (err, result: any) => { + if (err != null) reject(err); + + if (Array.isArray(result.output) && result.output.length > 0) { + resolve(result.output[0].data); + } + }); + }); + } catch { + return undefined; + } + + return convertPostman(JSON.stringify(postmanCollection)); +} diff --git a/plugins/importer-openapi/tests/__snapshots__/index.test.ts.snap b/plugins/importer-openapi/tests/__snapshots__/index.test.ts.snap new file mode 100644 index 00000000..dadaa6ac --- /dev/null +++ b/plugins/importer-openapi/tests/__snapshots__/index.test.ts.snap @@ -0,0 +1,2677 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`importer-openapi > Snapshots real-world fixture apis-guru.yaml 1`] = ` +{ + "resources": { + "environments": [], + "folders": [ + { + "description": "Actions relating to APIs in the collection", + "folderId": null, + "id": "GENERATE_ID::FOLDER_0", + "model": "folder", + "name": "APIs", + "sortPriority": 0, + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + ], + "grpcRequests": [], + "httpRequests": [ + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "description": "List all APIs in the directory. +Returns links to the OpenAPI definitions for each API in the directory. +If API exist in multiple versions \`preferred\` one is explicitly marked. +Some basic info from the OpenAPI definition is cached inside each object. +This allows you to generate some simple views without needing to fetch the OpenAPI definition for each API. + + +Operation ID: listAPIs + +Responses: +- 200: OK", + "folderId": "GENERATE_ID::FOLDER_0", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_0", + "method": "GET", + "model": "http_request", + "name": "List all APIs", + "sortPriority": 1, + "url": "https://api.apis.guru/v2/list.json", + "urlParameters": [], + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "description": "Some basic metrics for the entire directory. +Just stunning numbers to put on a front page and are intended purely for WoW effect :) + + +Operation ID: getMetrics + +Responses: +- 200: OK", + "folderId": "GENERATE_ID::FOLDER_0", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_1", + "method": "GET", + "model": "http_request", + "name": "Get basic metrics", + "sortPriority": 2, + "url": "https://api.apis.guru/v2/metrics.json", + "urlParameters": [], + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "description": "List all the providers in the directory + + +Operation ID: getProviders + +Responses: +- 200: OK", + "folderId": "GENERATE_ID::FOLDER_0", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_2", + "method": "GET", + "model": "http_request", + "name": "List all providers", + "sortPriority": 3, + "url": "https://api.apis.guru/v2/providers.json", + "urlParameters": [], + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "description": "Returns the API entry for one specific version of an API where there is no serviceName. + +Operation ID: getAPI + +Parameters: +- provider (path, required) +- api (path, required) + +Responses: +- 200: OK", + "folderId": "GENERATE_ID::FOLDER_0", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_3", + "method": "GET", + "model": "http_request", + "name": "Retrieve one version of a particular API", + "sortPriority": 4, + "url": "https://api.apis.guru/v2/specs/:provider/:api.json", + "urlParameters": [ + { + "enabled": true, + "name": ":provider", + "value": "apis.guru", + }, + { + "enabled": true, + "name": ":api", + "value": "2.1.0", + }, + ], + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "description": "Returns the API entry for one specific version of an API where there is a serviceName. + +Operation ID: getServiceAPI + +Parameters: +- provider (path, required) +- service (path, required) +- api (path, required) + +Responses: +- 200: OK", + "folderId": "GENERATE_ID::FOLDER_0", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_4", + "method": "GET", + "model": "http_request", + "name": "Retrieve one version of a particular API with a serviceName.", + "sortPriority": 5, + "url": "https://api.apis.guru/v2/specs/:provider/:service/:api.json", + "urlParameters": [ + { + "enabled": true, + "name": ":provider", + "value": "apis.guru", + }, + { + "enabled": true, + "name": ":service", + "value": "graph", + }, + { + "enabled": true, + "name": ":api", + "value": "2.1.0", + }, + ], + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "description": "List all APIs in the directory for a particular providerName +Returns links to the individual API entry for each API. + + +Operation ID: getProvider + +Parameters: +- provider (path, required) + +Responses: +- 200: OK", + "folderId": "GENERATE_ID::FOLDER_0", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_5", + "method": "GET", + "model": "http_request", + "name": "List all APIs for a particular provider", + "sortPriority": 6, + "url": "https://api.apis.guru/v2/:provider.json", + "urlParameters": [ + { + "enabled": true, + "name": ":provider", + "value": "apis.guru", + }, + ], + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "description": "List all serviceNames in the directory for a particular providerName + + +Operation ID: getServices + +Parameters: +- provider (path, required) + +Responses: +- 200: OK", + "folderId": "GENERATE_ID::FOLDER_0", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_6", + "method": "GET", + "model": "http_request", + "name": "List all serviceNames for a particular provider", + "sortPriority": 7, + "url": "https://api.apis.guru/v2/:provider/services.json", + "urlParameters": [ + { + "enabled": true, + "name": ":provider", + "value": "apis.guru", + }, + ], + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + ], + "websocketRequests": [], + "workspaces": [ + { + "description": "Wikipedia for Web APIs. Repository of API definitions in OpenAPI format. +**Warning**: If you want to be notified about changes in advance please join our [Slack channel](https://join.slack.com/t/mermade/shared_invite/zt-g78g7xir-MLE_CTCcXCdfJfG3CJe9qA). +Client sample: [[Demo]](https://apis.guru/simple-ui) [[Repo]](https://github.com/APIs-guru/simple-ui) + + +Contact: mike.ralphson@gmail.com + +License: CC0 1.0 (https://github.com/APIs-guru/openapi-directory#licenses)", + "id": "GENERATE_ID::WORKSPACE_0", + "model": "workspace", + "name": "APIs.guru", + }, + ], + }, +} +`; + +exports[`importer-openapi > Snapshots real-world fixture httpbin.yaml 1`] = ` +{ + "resources": { + "environments": [], + "folders": [ + { + "description": "Testing different HTTP verbs", + "folderId": null, + "id": "GENERATE_ID::FOLDER_0", + "model": "folder", + "name": "HTTP Methods", + "sortPriority": 0, + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + { + "description": "Auth methods", + "folderId": null, + "id": "GENERATE_ID::FOLDER_1", + "model": "folder", + "name": "Auth", + "sortPriority": 1, + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + { + "description": "Generates responses with given status code", + "folderId": null, + "id": "GENERATE_ID::FOLDER_2", + "model": "folder", + "name": "Status codes", + "sortPriority": 2, + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + { + "description": "Inspect the request data", + "folderId": null, + "id": "GENERATE_ID::FOLDER_3", + "model": "folder", + "name": "Request inspection", + "sortPriority": 3, + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + { + "description": "Inspect the response data like caching and headers", + "folderId": null, + "id": "GENERATE_ID::FOLDER_4", + "model": "folder", + "name": "Response inspection", + "sortPriority": 4, + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + { + "description": "Returns responses in different data formats", + "folderId": null, + "id": "GENERATE_ID::FOLDER_5", + "model": "folder", + "name": "Response formats", + "sortPriority": 5, + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + { + "description": "Generates random and dynamic data", + "folderId": null, + "id": "GENERATE_ID::FOLDER_6", + "model": "folder", + "name": "Dynamic data", + "sortPriority": 6, + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + { + "description": "Creates, reads and deletes Cookies", + "folderId": null, + "id": "GENERATE_ID::FOLDER_7", + "model": "folder", + "name": "Cookies", + "sortPriority": 7, + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + { + "description": "Returns different image formats", + "folderId": null, + "id": "GENERATE_ID::FOLDER_8", + "model": "folder", + "name": "Images", + "sortPriority": 8, + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + { + "description": "Returns different redirect responses", + "folderId": null, + "id": "GENERATE_ID::FOLDER_9", + "model": "folder", + "name": "Redirects", + "sortPriority": 9, + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + { + "description": "Returns anything that is passed to request", + "folderId": null, + "id": "GENERATE_ID::FOLDER_10", + "model": "folder", + "name": "Anything", + "sortPriority": 10, + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + ], + "grpcRequests": [], + "httpRequests": [ + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "description": "Absolutely 302 Redirects n times. + +Parameters: +- n (path, required) + +Responses: +- 302: A redirection.", + "folderId": "GENERATE_ID::FOLDER_9", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_0", + "method": "GET", + "model": "http_request", + "name": "Absolutely 302 Redirects n times.", + "sortPriority": 11, + "url": "https://httpbin.org/absolute-redirect/:n", + "urlParameters": [ + { + "enabled": true, + "name": ":n", + "value": "0", + }, + ], + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "description": "Returns anything passed in request data. + +Responses: +- 200: Anything passed in request", + "folderId": "GENERATE_ID::FOLDER_10", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_1", + "method": "DELETE", + "model": "http_request", + "name": "Returns anything passed in request data.", + "sortPriority": 12, + "url": "https://httpbin.org/anything", + "urlParameters": [], + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "description": "Returns anything passed in request data. + +Responses: +- 200: Anything passed in request", + "folderId": "GENERATE_ID::FOLDER_10", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_2", + "method": "GET", + "model": "http_request", + "name": "Returns anything passed in request data.", + "sortPriority": 13, + "url": "https://httpbin.org/anything", + "urlParameters": [], + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "description": "Returns anything passed in request data. + +Responses: +- 200: Anything passed in request", + "folderId": "GENERATE_ID::FOLDER_10", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_3", + "method": "PATCH", + "model": "http_request", + "name": "Returns anything passed in request data.", + "sortPriority": 14, + "url": "https://httpbin.org/anything", + "urlParameters": [], + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "description": "Returns anything passed in request data. + +Responses: +- 200: Anything passed in request", + "folderId": "GENERATE_ID::FOLDER_10", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_4", + "method": "POST", + "model": "http_request", + "name": "Returns anything passed in request data.", + "sortPriority": 15, + "url": "https://httpbin.org/anything", + "urlParameters": [], + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "description": "Returns anything passed in request data. + +Responses: +- 200: Anything passed in request", + "folderId": "GENERATE_ID::FOLDER_10", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_5", + "method": "PUT", + "model": "http_request", + "name": "Returns anything passed in request data.", + "sortPriority": 16, + "url": "https://httpbin.org/anything", + "urlParameters": [], + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "description": "Returns anything passed in request data. + +Responses: +- 200: Anything passed in request", + "folderId": "GENERATE_ID::FOLDER_10", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_6", + "method": "TRACE", + "model": "http_request", + "name": "Returns anything passed in request data.", + "sortPriority": 17, + "url": "https://httpbin.org/anything", + "urlParameters": [], + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "description": "Returns anything passed in request data. + +Parameters: +- anything (path, required): Automatically added + +Responses: +- 200: Anything passed in request", + "folderId": "GENERATE_ID::FOLDER_10", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_7", + "method": "DELETE", + "model": "http_request", + "name": "Returns anything passed in request data.", + "sortPriority": 18, + "url": "https://httpbin.org/anything/:anything", + "urlParameters": [ + { + "enabled": true, + "name": ":anything", + "value": "", + }, + ], + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "description": "Returns anything passed in request data. + +Parameters: +- anything (path, required): Automatically added + +Responses: +- 200: Anything passed in request", + "folderId": "GENERATE_ID::FOLDER_10", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_8", + "method": "GET", + "model": "http_request", + "name": "Returns anything passed in request data.", + "sortPriority": 19, + "url": "https://httpbin.org/anything/:anything", + "urlParameters": [ + { + "enabled": true, + "name": ":anything", + "value": "", + }, + ], + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "description": "Returns anything passed in request data. + +Parameters: +- anything (path, required): Automatically added + +Responses: +- 200: Anything passed in request", + "folderId": "GENERATE_ID::FOLDER_10", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_9", + "method": "PATCH", + "model": "http_request", + "name": "Returns anything passed in request data.", + "sortPriority": 20, + "url": "https://httpbin.org/anything/:anything", + "urlParameters": [ + { + "enabled": true, + "name": ":anything", + "value": "", + }, + ], + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "description": "Returns anything passed in request data. + +Parameters: +- anything (path, required): Automatically added + +Responses: +- 200: Anything passed in request", + "folderId": "GENERATE_ID::FOLDER_10", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_10", + "method": "POST", + "model": "http_request", + "name": "Returns anything passed in request data.", + "sortPriority": 21, + "url": "https://httpbin.org/anything/:anything", + "urlParameters": [ + { + "enabled": true, + "name": ":anything", + "value": "", + }, + ], + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "description": "Returns anything passed in request data. + +Parameters: +- anything (path, required): Automatically added + +Responses: +- 200: Anything passed in request", + "folderId": "GENERATE_ID::FOLDER_10", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_11", + "method": "PUT", + "model": "http_request", + "name": "Returns anything passed in request data.", + "sortPriority": 22, + "url": "https://httpbin.org/anything/:anything", + "urlParameters": [ + { + "enabled": true, + "name": ":anything", + "value": "", + }, + ], + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "description": "Returns anything passed in request data. + +Parameters: +- anything (path, required): Automatically added + +Responses: +- 200: Anything passed in request", + "folderId": "GENERATE_ID::FOLDER_10", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_12", + "method": "TRACE", + "model": "http_request", + "name": "Returns anything passed in request data.", + "sortPriority": 23, + "url": "https://httpbin.org/anything/:anything", + "urlParameters": [ + { + "enabled": true, + "name": ":anything", + "value": "", + }, + ], + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "description": "Decodes base64url-encoded string. + +Parameters: +- value (path, required) + +Responses: +- 200: Decoded base64 content.", + "folderId": "GENERATE_ID::FOLDER_6", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_13", + "method": "GET", + "model": "http_request", + "name": "Decodes base64url-encoded string.", + "sortPriority": 24, + "url": "https://httpbin.org/base64/:value", + "urlParameters": [ + { + "enabled": true, + "name": ":value", + "value": "SFRUUEJJTiBpcyBhd2Vzb21l", + }, + ], + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "description": "Prompts the user for authorization using HTTP Basic Auth. + +Parameters: +- user (path, required) +- passwd (path, required) + +Responses: +- 200: Sucessful authentication. +- 401: Unsuccessful authentication.", + "folderId": "GENERATE_ID::FOLDER_1", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_14", + "method": "GET", + "model": "http_request", + "name": "Prompts the user for authorization using HTTP Basic Auth.", + "sortPriority": 25, + "url": "https://httpbin.org/basic-auth/:user/:passwd", + "urlParameters": [ + { + "enabled": true, + "name": ":user", + "value": "", + }, + { + "enabled": true, + "name": ":passwd", + "value": "", + }, + ], + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "description": "Prompts the user for authorization using bearer authentication. + +Parameters: +- Authorization (header) + +Responses: +- 200: Sucessful authentication. +- 401: Unsuccessful authentication.", + "folderId": "GENERATE_ID::FOLDER_1", + "headers": [ + { + "enabled": false, + "name": "Authorization", + "value": "", + }, + ], + "id": "GENERATE_ID::HTTP_REQUEST_15", + "method": "GET", + "model": "http_request", + "name": "Prompts the user for authorization using bearer authentication.", + "sortPriority": 26, + "url": "https://httpbin.org/bearer", + "urlParameters": [], + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "description": "Returns Brotli-encoded data. + +Responses: +- 200: Brotli-encoded data.", + "folderId": "GENERATE_ID::FOLDER_5", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_16", + "method": "GET", + "model": "http_request", + "name": "Returns Brotli-encoded data.", + "sortPriority": 27, + "url": "https://httpbin.org/brotli", + "urlParameters": [], + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "description": "Returns n random bytes generated with given seed + +Parameters: +- n (path, required) + +Responses: +- 200: Bytes.", + "folderId": "GENERATE_ID::FOLDER_6", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_17", + "method": "GET", + "model": "http_request", + "name": "Returns n random bytes generated with given seed", + "sortPriority": 28, + "url": "https://httpbin.org/bytes/:n", + "urlParameters": [ + { + "enabled": true, + "name": ":n", + "value": "0", + }, + ], + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "description": "Returns a 304 if an If-Modified-Since header or If-None-Match is present. Returns the same as a GET otherwise. + +Parameters: +- If-Modified-Since (header) +- If-None-Match (header) + +Responses: +- 200: Cached response +- 304: Modified", + "folderId": "GENERATE_ID::FOLDER_4", + "headers": [ + { + "enabled": false, + "name": "If-Modified-Since", + "value": "", + }, + { + "enabled": false, + "name": "If-None-Match", + "value": "", + }, + ], + "id": "GENERATE_ID::HTTP_REQUEST_18", + "method": "GET", + "model": "http_request", + "name": "Returns a 304 if an If-Modified-Since header or If-None-Match is present. Returns the same as a GET otherwise.", + "sortPriority": 29, + "url": "https://httpbin.org/cache", + "urlParameters": [], + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "description": "Sets a Cache-Control header for n seconds. + +Parameters: +- value (path, required) + +Responses: +- 200: Cache control set", + "folderId": "GENERATE_ID::FOLDER_4", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_19", + "method": "GET", + "model": "http_request", + "name": "Sets a Cache-Control header for n seconds.", + "sortPriority": 30, + "url": "https://httpbin.org/cache/:value", + "urlParameters": [ + { + "enabled": true, + "name": ":value", + "value": "0", + }, + ], + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "description": "Returns cookie data. + +Responses: +- 200: Set cookies.", + "folderId": "GENERATE_ID::FOLDER_7", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_20", + "method": "GET", + "model": "http_request", + "name": "Returns cookie data.", + "sortPriority": 31, + "url": "https://httpbin.org/cookies", + "urlParameters": [], + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "description": "Deletes cookie(s) as provided by the query string and redirects to cookie list. + +Parameters: +- freeform (query) + +Responses: +- 200: Redirect to cookie list", + "folderId": "GENERATE_ID::FOLDER_7", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_21", + "method": "GET", + "model": "http_request", + "name": "Deletes cookie(s) as provided by the query string and redirects to cookie list.", + "sortPriority": 32, + "url": "https://httpbin.org/cookies/delete", + "urlParameters": [ + { + "enabled": false, + "name": "freeform", + "value": "", + }, + ], + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "description": "Sets cookie(s) as provided by the query string and redirects to cookie list. + +Parameters: +- freeform (query) + +Responses: +- 200: Redirect to cookie list", + "folderId": "GENERATE_ID::FOLDER_7", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_22", + "method": "GET", + "model": "http_request", + "name": "Sets cookie(s) as provided by the query string and redirects to cookie list.", + "sortPriority": 33, + "url": "https://httpbin.org/cookies/set", + "urlParameters": [ + { + "enabled": false, + "name": "freeform", + "value": "", + }, + ], + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "description": "Sets a cookie and redirects to cookie list. + +Parameters: +- name (path, required) +- value (path, required) + +Responses: +- 200: Set cookies and redirects to cookie list.", + "folderId": "GENERATE_ID::FOLDER_7", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_23", + "method": "GET", + "model": "http_request", + "name": "Sets a cookie and redirects to cookie list.", + "sortPriority": 34, + "url": "https://httpbin.org/cookies/set/:name/:value", + "urlParameters": [ + { + "enabled": true, + "name": ":name", + "value": "", + }, + { + "enabled": true, + "name": ":value", + "value": "", + }, + ], + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "description": "Returns Deflate-encoded data. + +Responses: +- 200: Defalte-encoded data.", + "folderId": "GENERATE_ID::FOLDER_5", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_24", + "method": "GET", + "model": "http_request", + "name": "Returns Deflate-encoded data.", + "sortPriority": 35, + "url": "https://httpbin.org/deflate", + "urlParameters": [], + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "description": "Returns a delayed response (max of 10 seconds). + +Parameters: +- delay (path, required) + +Responses: +- 200: A delayed response.", + "folderId": "GENERATE_ID::FOLDER_6", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_25", + "method": "DELETE", + "model": "http_request", + "name": "Returns a delayed response (max of 10 seconds).", + "sortPriority": 36, + "url": "https://httpbin.org/delay/:delay", + "urlParameters": [ + { + "enabled": true, + "name": ":delay", + "value": "0", + }, + ], + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "description": "Returns a delayed response (max of 10 seconds). + +Parameters: +- delay (path, required) + +Responses: +- 200: A delayed response.", + "folderId": "GENERATE_ID::FOLDER_6", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_26", + "method": "GET", + "model": "http_request", + "name": "Returns a delayed response (max of 10 seconds).", + "sortPriority": 37, + "url": "https://httpbin.org/delay/:delay", + "urlParameters": [ + { + "enabled": true, + "name": ":delay", + "value": "0", + }, + ], + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "description": "Returns a delayed response (max of 10 seconds). + +Parameters: +- delay (path, required) + +Responses: +- 200: A delayed response.", + "folderId": "GENERATE_ID::FOLDER_6", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_27", + "method": "PATCH", + "model": "http_request", + "name": "Returns a delayed response (max of 10 seconds).", + "sortPriority": 38, + "url": "https://httpbin.org/delay/:delay", + "urlParameters": [ + { + "enabled": true, + "name": ":delay", + "value": "0", + }, + ], + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "description": "Returns a delayed response (max of 10 seconds). + +Parameters: +- delay (path, required) + +Responses: +- 200: A delayed response.", + "folderId": "GENERATE_ID::FOLDER_6", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_28", + "method": "POST", + "model": "http_request", + "name": "Returns a delayed response (max of 10 seconds).", + "sortPriority": 39, + "url": "https://httpbin.org/delay/:delay", + "urlParameters": [ + { + "enabled": true, + "name": ":delay", + "value": "0", + }, + ], + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "description": "Returns a delayed response (max of 10 seconds). + +Parameters: +- delay (path, required) + +Responses: +- 200: A delayed response.", + "folderId": "GENERATE_ID::FOLDER_6", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_29", + "method": "PUT", + "model": "http_request", + "name": "Returns a delayed response (max of 10 seconds).", + "sortPriority": 40, + "url": "https://httpbin.org/delay/:delay", + "urlParameters": [ + { + "enabled": true, + "name": ":delay", + "value": "0", + }, + ], + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "description": "Returns a delayed response (max of 10 seconds). + +Parameters: +- delay (path, required) + +Responses: +- 200: A delayed response.", + "folderId": "GENERATE_ID::FOLDER_6", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_30", + "method": "TRACE", + "model": "http_request", + "name": "Returns a delayed response (max of 10 seconds).", + "sortPriority": 41, + "url": "https://httpbin.org/delay/:delay", + "urlParameters": [ + { + "enabled": true, + "name": ":delay", + "value": "0", + }, + ], + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "description": "The request's DELETE parameters. + +Responses: +- 200: The request's DELETE parameters.", + "folderId": "GENERATE_ID::FOLDER_0", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_31", + "method": "DELETE", + "model": "http_request", + "name": "The request's DELETE parameters.", + "sortPriority": 42, + "url": "https://httpbin.org/delete", + "urlParameters": [], + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "description": "Returns page denied by robots.txt rules. + +Responses: +- 200: Denied message", + "folderId": "GENERATE_ID::FOLDER_5", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_32", + "method": "GET", + "model": "http_request", + "name": "Returns page denied by robots.txt rules.", + "sortPriority": 43, + "url": "https://httpbin.org/deny", + "urlParameters": [], + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "description": "Prompts the user for authorization using Digest Auth. + +Parameters: +- qop (path, required): auth or auth-int +- user (path, required) +- passwd (path, required) + +Responses: +- 200: Sucessful authentication. +- 401: Unsuccessful authentication.", + "folderId": "GENERATE_ID::FOLDER_1", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_33", + "method": "GET", + "model": "http_request", + "name": "Prompts the user for authorization using Digest Auth.", + "sortPriority": 44, + "url": "https://httpbin.org/digest-auth/:qop/:user/:passwd", + "urlParameters": [ + { + "enabled": true, + "name": ":qop", + "value": "", + }, + { + "enabled": true, + "name": ":user", + "value": "", + }, + { + "enabled": true, + "name": ":passwd", + "value": "", + }, + ], + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "description": "Prompts the user for authorization using Digest Auth + Algorithm. + +Parameters: +- qop (path, required): auth or auth-int +- user (path, required) +- passwd (path, required) +- algorithm (path, required): MD5, SHA-256, SHA-512 + +Responses: +- 200: Sucessful authentication. +- 401: Unsuccessful authentication.", + "folderId": "GENERATE_ID::FOLDER_1", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_34", + "method": "GET", + "model": "http_request", + "name": "Prompts the user for authorization using Digest Auth + Algorithm.", + "sortPriority": 45, + "url": "https://httpbin.org/digest-auth/:qop/:user/:passwd/:algorithm", + "urlParameters": [ + { + "enabled": true, + "name": ":qop", + "value": "", + }, + { + "enabled": true, + "name": ":user", + "value": "", + }, + { + "enabled": true, + "name": ":passwd", + "value": "", + }, + { + "enabled": true, + "name": ":algorithm", + "value": "MD5", + }, + ], + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "description": "allow settings the stale_after argument. + + +Parameters: +- qop (path, required): auth or auth-int +- user (path, required) +- passwd (path, required) +- algorithm (path, required): MD5, SHA-256, SHA-512 +- stale_after (path, required) + +Responses: +- 200: Sucessful authentication. +- 401: Unsuccessful authentication.", + "folderId": "GENERATE_ID::FOLDER_1", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_35", + "method": "GET", + "model": "http_request", + "name": "Prompts the user for authorization using Digest Auth + Algorithm.", + "sortPriority": 46, + "url": "https://httpbin.org/digest-auth/:qop/:user/:passwd/:algorithm/:stale_after", + "urlParameters": [ + { + "enabled": true, + "name": ":qop", + "value": "", + }, + { + "enabled": true, + "name": ":user", + "value": "", + }, + { + "enabled": true, + "name": ":passwd", + "value": "", + }, + { + "enabled": true, + "name": ":algorithm", + "value": "MD5", + }, + { + "enabled": true, + "name": ":stale_after", + "value": "never", + }, + ], + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "description": "Drips data over a duration after an optional initial delay. + +Parameters: +- duration (query): The amount of time (in seconds) over which to drip each byte +- numbytes (query): The number of bytes to respond with +- code (query): The response code that will be returned +- delay (query): The amount of time (in seconds) to delay before responding + +Responses: +- 200: A dripped response.", + "folderId": "GENERATE_ID::FOLDER_6", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_36", + "method": "GET", + "model": "http_request", + "name": "Drips data over a duration after an optional initial delay.", + "sortPriority": 47, + "url": "https://httpbin.org/drip", + "urlParameters": [ + { + "enabled": false, + "name": "duration", + "value": "2", + }, + { + "enabled": false, + "name": "numbytes", + "value": "10", + }, + { + "enabled": false, + "name": "code", + "value": "200", + }, + { + "enabled": false, + "name": "delay", + "value": "2", + }, + ], + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "description": "Returns a UTF-8 encoded body. + +Responses: +- 200: Encoded UTF-8 content.", + "folderId": "GENERATE_ID::FOLDER_5", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_37", + "method": "GET", + "model": "http_request", + "name": "Returns a UTF-8 encoded body.", + "sortPriority": 48, + "url": "https://httpbin.org/encoding/utf8", + "urlParameters": [], + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "description": "Assumes the resource has the given etag and responds to If-None-Match and If-Match headers appropriately. + +Parameters: +- If-None-Match (header) +- If-Match (header) +- etag (path, required): Automatically added + +Responses: +- 200: Normal response +- 412: match", + "folderId": "GENERATE_ID::FOLDER_4", + "headers": [ + { + "enabled": false, + "name": "If-None-Match", + "value": "", + }, + { + "enabled": false, + "name": "If-Match", + "value": "", + }, + ], + "id": "GENERATE_ID::HTTP_REQUEST_38", + "method": "GET", + "model": "http_request", + "name": "Assumes the resource has the given etag and responds to If-None-Match and If-Match headers appropriately.", + "sortPriority": 49, + "url": "https://httpbin.org/etag/:etag", + "urlParameters": [ + { + "enabled": true, + "name": ":etag", + "value": "", + }, + ], + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "description": "The request's query parameters. + +Responses: +- 200: The request's query parameters.", + "folderId": "GENERATE_ID::FOLDER_0", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_39", + "method": "GET", + "model": "http_request", + "name": "The request's query parameters.", + "sortPriority": 50, + "url": "https://httpbin.org/get", + "urlParameters": [], + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "description": "Returns GZip-encoded data. + +Responses: +- 200: GZip-encoded data.", + "folderId": "GENERATE_ID::FOLDER_5", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_40", + "method": "GET", + "model": "http_request", + "name": "Returns GZip-encoded data.", + "sortPriority": 51, + "url": "https://httpbin.org/gzip", + "urlParameters": [], + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "description": "Return the incoming request's HTTP headers. + +Responses: +- 200: The request's headers.", + "folderId": "GENERATE_ID::FOLDER_3", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_41", + "method": "GET", + "model": "http_request", + "name": "Return the incoming request's HTTP headers.", + "sortPriority": 52, + "url": "https://httpbin.org/headers", + "urlParameters": [], + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "description": "Prompts the user for authorization using HTTP Basic Auth. + +Parameters: +- user (path, required) +- passwd (path, required) + +Responses: +- 200: Sucessful authentication. +- 404: Unsuccessful authentication.", + "folderId": "GENERATE_ID::FOLDER_1", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_42", + "method": "GET", + "model": "http_request", + "name": "Prompts the user for authorization using HTTP Basic Auth.", + "sortPriority": 53, + "url": "https://httpbin.org/hidden-basic-auth/:user/:passwd", + "urlParameters": [ + { + "enabled": true, + "name": ":user", + "value": "", + }, + { + "enabled": true, + "name": ":passwd", + "value": "", + }, + ], + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "description": "Returns a simple HTML document. + +Responses: +- 200: An HTML page.", + "folderId": "GENERATE_ID::FOLDER_5", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_43", + "method": "GET", + "model": "http_request", + "name": "Returns a simple HTML document.", + "sortPriority": 54, + "url": "https://httpbin.org/html", + "urlParameters": [], + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "description": "Returns a simple image of the type suggest by the Accept header. + +Responses: +- 200: An image.", + "folderId": "GENERATE_ID::FOLDER_8", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_44", + "method": "GET", + "model": "http_request", + "name": "Returns a simple image of the type suggest by the Accept header.", + "sortPriority": 55, + "url": "https://httpbin.org/image", + "urlParameters": [], + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "description": "Returns a simple JPEG image. + +Responses: +- 200: A JPEG image.", + "folderId": "GENERATE_ID::FOLDER_8", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_45", + "method": "GET", + "model": "http_request", + "name": "Returns a simple JPEG image.", + "sortPriority": 56, + "url": "https://httpbin.org/image/jpeg", + "urlParameters": [], + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "description": "Returns a simple PNG image. + +Responses: +- 200: A PNG image.", + "folderId": "GENERATE_ID::FOLDER_8", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_46", + "method": "GET", + "model": "http_request", + "name": "Returns a simple PNG image.", + "sortPriority": 57, + "url": "https://httpbin.org/image/png", + "urlParameters": [], + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "description": "Returns a simple SVG image. + +Responses: +- 200: An SVG image.", + "folderId": "GENERATE_ID::FOLDER_8", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_47", + "method": "GET", + "model": "http_request", + "name": "Returns a simple SVG image.", + "sortPriority": 58, + "url": "https://httpbin.org/image/svg", + "urlParameters": [], + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "description": "Returns a simple WEBP image. + +Responses: +- 200: A WEBP image.", + "folderId": "GENERATE_ID::FOLDER_8", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_48", + "method": "GET", + "model": "http_request", + "name": "Returns a simple WEBP image.", + "sortPriority": 59, + "url": "https://httpbin.org/image/webp", + "urlParameters": [], + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "description": "Returns the requester's IP Address. + +Responses: +- 200: The Requester's IP Address.", + "folderId": "GENERATE_ID::FOLDER_3", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_49", + "method": "GET", + "model": "http_request", + "name": "Returns the requester's IP Address.", + "sortPriority": 60, + "url": "https://httpbin.org/ip", + "urlParameters": [], + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "description": "Returns a simple JSON document. + +Responses: +- 200: An JSON document.", + "folderId": "GENERATE_ID::FOLDER_5", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_50", + "method": "GET", + "model": "http_request", + "name": "Returns a simple JSON document.", + "sortPriority": 61, + "url": "https://httpbin.org/json", + "urlParameters": [], + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "description": "Generate a page containing n links to other pages which do the same. + +Parameters: +- n (path, required) +- offset (path, required) + +Responses: +- 200: HTML links.", + "folderId": "GENERATE_ID::FOLDER_6", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_51", + "method": "GET", + "model": "http_request", + "name": "Generate a page containing n links to other pages which do the same.", + "sortPriority": 62, + "url": "https://httpbin.org/links/:n/:offset", + "urlParameters": [ + { + "enabled": true, + "name": ":n", + "value": "0", + }, + { + "enabled": true, + "name": ":offset", + "value": "0", + }, + ], + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "description": "The request's PATCH parameters. + +Responses: +- 200: The request's PATCH parameters.", + "folderId": "GENERATE_ID::FOLDER_0", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_52", + "method": "PATCH", + "model": "http_request", + "name": "The request's PATCH parameters.", + "sortPriority": 63, + "url": "https://httpbin.org/patch", + "urlParameters": [], + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "description": "The request's POST parameters. + +Responses: +- 200: The request's POST parameters.", + "folderId": "GENERATE_ID::FOLDER_0", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_53", + "method": "POST", + "model": "http_request", + "name": "The request's POST parameters.", + "sortPriority": 64, + "url": "https://httpbin.org/post", + "urlParameters": [], + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "description": "The request's PUT parameters. + +Responses: +- 200: The request's PUT parameters.", + "folderId": "GENERATE_ID::FOLDER_0", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_54", + "method": "PUT", + "model": "http_request", + "name": "The request's PUT parameters.", + "sortPriority": 65, + "url": "https://httpbin.org/put", + "urlParameters": [], + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "description": "Streams n random bytes generated with given seed, at given chunk size per packet. + +Parameters: +- numbytes (path, required) + +Responses: +- 200: Bytes.", + "folderId": "GENERATE_ID::FOLDER_6", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_55", + "method": "GET", + "model": "http_request", + "name": "Streams n random bytes generated with given seed, at given chunk size per packet.", + "sortPriority": 66, + "url": "https://httpbin.org/range/:numbytes", + "urlParameters": [ + { + "enabled": true, + "name": ":numbytes", + "value": "0", + }, + ], + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "description": "302/3XX Redirects to the given URL. + +Responses: +- 302: A redirection.", + "folderId": "GENERATE_ID::FOLDER_9", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_56", + "method": "DELETE", + "model": "http_request", + "name": "302/3XX Redirects to the given URL.", + "sortPriority": 67, + "url": "https://httpbin.org/redirect-to", + "urlParameters": [], + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "description": "302/3XX Redirects to the given URL. + +Parameters: +- url (query, required) +- status_code (query) + +Responses: +- 302: A redirection.", + "folderId": "GENERATE_ID::FOLDER_9", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_57", + "method": "GET", + "model": "http_request", + "name": "302/3XX Redirects to the given URL.", + "sortPriority": 68, + "url": "https://httpbin.org/redirect-to", + "urlParameters": [ + { + "enabled": true, + "name": "url", + "value": "", + }, + { + "enabled": false, + "name": "status_code", + "value": "0", + }, + ], + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "description": "302/3XX Redirects to the given URL. + +Responses: +- 302: A redirection.", + "folderId": "GENERATE_ID::FOLDER_9", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_58", + "method": "PATCH", + "model": "http_request", + "name": "302/3XX Redirects to the given URL.", + "sortPriority": 69, + "url": "https://httpbin.org/redirect-to", + "urlParameters": [], + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + { + "authentication": {}, + "authenticationType": null, + "body": { + "form": [ + { + "enabled": false, + "name": "status_code", + "value": "0", + }, + { + "enabled": true, + "name": "url", + "value": "", + }, + ], + }, + "bodyType": "application/x-www-form-urlencoded", + "description": "302/3XX Redirects to the given URL. + +Request body: +Selected content type: application/x-www-form-urlencoded +Available content types: application/x-www-form-urlencoded + +Responses: +- 302: A redirection.", + "folderId": "GENERATE_ID::FOLDER_9", + "headers": [ + { + "enabled": true, + "name": "Content-Type", + "value": "application/x-www-form-urlencoded", + }, + ], + "id": "GENERATE_ID::HTTP_REQUEST_59", + "method": "POST", + "model": "http_request", + "name": "302/3XX Redirects to the given URL.", + "sortPriority": 70, + "url": "https://httpbin.org/redirect-to", + "urlParameters": [], + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + { + "authentication": {}, + "authenticationType": null, + "body": { + "form": [ + { + "enabled": false, + "name": "status_code", + "value": "0", + }, + { + "enabled": true, + "name": "url", + "value": "", + }, + ], + }, + "bodyType": "application/x-www-form-urlencoded", + "description": "302/3XX Redirects to the given URL. + +Request body: +Selected content type: application/x-www-form-urlencoded +Available content types: application/x-www-form-urlencoded + +Responses: +- 302: A redirection.", + "folderId": "GENERATE_ID::FOLDER_9", + "headers": [ + { + "enabled": true, + "name": "Content-Type", + "value": "application/x-www-form-urlencoded", + }, + ], + "id": "GENERATE_ID::HTTP_REQUEST_60", + "method": "PUT", + "model": "http_request", + "name": "302/3XX Redirects to the given URL.", + "sortPriority": 71, + "url": "https://httpbin.org/redirect-to", + "urlParameters": [], + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "description": "302/3XX Redirects to the given URL. + +Responses: +- 302: A redirection.", + "folderId": "GENERATE_ID::FOLDER_9", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_61", + "method": "TRACE", + "model": "http_request", + "name": "302/3XX Redirects to the given URL.", + "sortPriority": 72, + "url": "https://httpbin.org/redirect-to", + "urlParameters": [], + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "description": "302 Redirects n times. + +Parameters: +- n (path, required) + +Responses: +- 302: A redirection.", + "folderId": "GENERATE_ID::FOLDER_9", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_62", + "method": "GET", + "model": "http_request", + "name": "302 Redirects n times.", + "sortPriority": 73, + "url": "https://httpbin.org/redirect/:n", + "urlParameters": [ + { + "enabled": true, + "name": ":n", + "value": "0", + }, + ], + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "description": "Relatively 302 Redirects n times. + +Parameters: +- n (path, required) + +Responses: +- 302: A redirection.", + "folderId": "GENERATE_ID::FOLDER_9", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_63", + "method": "GET", + "model": "http_request", + "name": "Relatively 302 Redirects n times.", + "sortPriority": 74, + "url": "https://httpbin.org/relative-redirect/:n", + "urlParameters": [ + { + "enabled": true, + "name": ":n", + "value": "0", + }, + ], + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "description": "Returns a set of response headers from the query string. + +Parameters: +- freeform (query) + +Responses: +- 200: Response headers", + "folderId": "GENERATE_ID::FOLDER_4", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_64", + "method": "GET", + "model": "http_request", + "name": "Returns a set of response headers from the query string.", + "sortPriority": 75, + "url": "https://httpbin.org/response-headers", + "urlParameters": [ + { + "enabled": false, + "name": "freeform", + "value": "", + }, + ], + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "description": "Returns a set of response headers from the query string. + +Parameters: +- freeform (query) + +Responses: +- 200: Response headers", + "folderId": "GENERATE_ID::FOLDER_4", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_65", + "method": "POST", + "model": "http_request", + "name": "Returns a set of response headers from the query string.", + "sortPriority": 76, + "url": "https://httpbin.org/response-headers", + "urlParameters": [ + { + "enabled": false, + "name": "freeform", + "value": "", + }, + ], + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "description": "Returns some robots.txt rules. + +Responses: +- 200: Robots file", + "folderId": "GENERATE_ID::FOLDER_5", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_66", + "method": "GET", + "model": "http_request", + "name": "Returns some robots.txt rules.", + "sortPriority": 77, + "url": "https://httpbin.org/robots.txt", + "urlParameters": [], + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "description": "Return status code or random status code if more than one are given + +Parameters: +- codes (path, required) + +Responses: +- 100: Informational responses +- 200: Success +- 300: Redirection +- 400: Client Errors +- 500: Server Errors", + "folderId": "GENERATE_ID::FOLDER_2", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_67", + "method": "DELETE", + "model": "http_request", + "name": "Return status code or random status code if more than one are given", + "sortPriority": 78, + "url": "https://httpbin.org/status/:codes", + "urlParameters": [ + { + "enabled": true, + "name": ":codes", + "value": "", + }, + ], + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "description": "Return status code or random status code if more than one are given + +Parameters: +- codes (path, required) + +Responses: +- 100: Informational responses +- 200: Success +- 300: Redirection +- 400: Client Errors +- 500: Server Errors", + "folderId": "GENERATE_ID::FOLDER_2", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_68", + "method": "GET", + "model": "http_request", + "name": "Return status code or random status code if more than one are given", + "sortPriority": 79, + "url": "https://httpbin.org/status/:codes", + "urlParameters": [ + { + "enabled": true, + "name": ":codes", + "value": "", + }, + ], + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "description": "Return status code or random status code if more than one are given + +Parameters: +- codes (path, required) + +Responses: +- 100: Informational responses +- 200: Success +- 300: Redirection +- 400: Client Errors +- 500: Server Errors", + "folderId": "GENERATE_ID::FOLDER_2", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_69", + "method": "PATCH", + "model": "http_request", + "name": "Return status code or random status code if more than one are given", + "sortPriority": 80, + "url": "https://httpbin.org/status/:codes", + "urlParameters": [ + { + "enabled": true, + "name": ":codes", + "value": "", + }, + ], + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "description": "Return status code or random status code if more than one are given + +Parameters: +- codes (path, required) + +Responses: +- 100: Informational responses +- 200: Success +- 300: Redirection +- 400: Client Errors +- 500: Server Errors", + "folderId": "GENERATE_ID::FOLDER_2", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_70", + "method": "POST", + "model": "http_request", + "name": "Return status code or random status code if more than one are given", + "sortPriority": 81, + "url": "https://httpbin.org/status/:codes", + "urlParameters": [ + { + "enabled": true, + "name": ":codes", + "value": "", + }, + ], + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "description": "Return status code or random status code if more than one are given + +Parameters: +- codes (path, required) + +Responses: +- 100: Informational responses +- 200: Success +- 300: Redirection +- 400: Client Errors +- 500: Server Errors", + "folderId": "GENERATE_ID::FOLDER_2", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_71", + "method": "PUT", + "model": "http_request", + "name": "Return status code or random status code if more than one are given", + "sortPriority": 82, + "url": "https://httpbin.org/status/:codes", + "urlParameters": [ + { + "enabled": true, + "name": ":codes", + "value": "", + }, + ], + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "description": "Return status code or random status code if more than one are given + +Parameters: +- codes (path, required) + +Responses: +- 100: Informational responses +- 200: Success +- 300: Redirection +- 400: Client Errors +- 500: Server Errors", + "folderId": "GENERATE_ID::FOLDER_2", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_72", + "method": "TRACE", + "model": "http_request", + "name": "Return status code or random status code if more than one are given", + "sortPriority": 83, + "url": "https://httpbin.org/status/:codes", + "urlParameters": [ + { + "enabled": true, + "name": ":codes", + "value": "", + }, + ], + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "description": "Streams n random bytes generated with given seed, at given chunk size per packet. + +Parameters: +- n (path, required) + +Responses: +- 200: Bytes.", + "folderId": "GENERATE_ID::FOLDER_6", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_73", + "method": "GET", + "model": "http_request", + "name": "Streams n random bytes generated with given seed, at given chunk size per packet.", + "sortPriority": 84, + "url": "https://httpbin.org/stream-bytes/:n", + "urlParameters": [ + { + "enabled": true, + "name": ":n", + "value": "0", + }, + ], + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "description": "Stream n JSON responses + +Parameters: +- n (path, required) + +Responses: +- 200: Streamed JSON responses.", + "folderId": "GENERATE_ID::FOLDER_6", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_74", + "method": "GET", + "model": "http_request", + "name": "Stream n JSON responses", + "sortPriority": 85, + "url": "https://httpbin.org/stream/:n", + "urlParameters": [ + { + "enabled": true, + "name": ":n", + "value": "0", + }, + ], + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "description": "Return the incoming requests's User-Agent header. + +Responses: +- 200: The request's User-Agent header.", + "folderId": "GENERATE_ID::FOLDER_3", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_75", + "method": "GET", + "model": "http_request", + "name": "Return the incoming requests's User-Agent header.", + "sortPriority": 86, + "url": "https://httpbin.org/user-agent", + "urlParameters": [], + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "description": "Return a UUID4. + +Responses: +- 200: A UUID4.", + "folderId": "GENERATE_ID::FOLDER_6", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_76", + "method": "GET", + "model": "http_request", + "name": "Return a UUID4.", + "sortPriority": 87, + "url": "https://httpbin.org/uuid", + "urlParameters": [], + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "description": "Returns a simple XML document. + +Responses: +- 200: An XML document.", + "folderId": "GENERATE_ID::FOLDER_5", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_77", + "method": "GET", + "model": "http_request", + "name": "Returns a simple XML document.", + "sortPriority": 88, + "url": "https://httpbin.org/xml", + "urlParameters": [], + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + ], + "websocketRequests": [], + "workspaces": [ + { + "description": "A simple HTTP Request & Response Service.

Run locally: $ docker run -p 80:80 kennethreitz/httpbin + +Contact: me@kennethreitz.org", + "id": "GENERATE_ID::WORKSPACE_0", + "model": "workspace", + "name": "httpbin.org", + }, + ], + }, +} +`; + +exports[`importer-openapi > Snapshots real-world fixture nasa-apod.yaml 1`] = ` +{ + "resources": { + "environments": [], + "folders": [ + { + "description": "An example tag + +Here's a link: https://example.com", + "folderId": null, + "id": "GENERATE_ID::FOLDER_0", + "model": "folder", + "name": "request tag", + "sortPriority": 0, + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + ], + "grpcRequests": [], + "httpRequests": [ + { + "authentication": { + "key": "api_key", + "location": "query", + "value": "", + }, + "authenticationType": "apikey", + "body": {}, + "bodyType": null, + "description": "Returns the picture of the day + +Parameters: +- date (query): The date of the APOD image to retrieve +- hd (query): Retrieve the URL for the high resolution image + +Responses: +- 200: successful operation +- 400: Date must be between Jun 16, 1995 and Mar 28, 2019.", + "folderId": "GENERATE_ID::FOLDER_0", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_0", + "method": "GET", + "model": "http_request", + "name": "Returns images", + "sortPriority": 1, + "url": "https://api.nasa.gov/planetary/apod", + "urlParameters": [ + { + "enabled": false, + "name": "date", + "value": "", + }, + { + "enabled": false, + "name": "hd", + "value": "false", + }, + ], + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + ], + "websocketRequests": [], + "workspaces": [ + { + "description": "This endpoint structures the APOD imagery and associated metadata so that it can be repurposed for other applications. In addition, if the concept_tags parameter is set to True, then keywords derived from the image explanation are returned. These keywords could be used as auto-generated hashtags for twitter or instagram feeds; but generally help with discoverability of relevant imagery + +Contact: evan.t.yates@nasa.gov + +License: Apache 2.0 (http://www.apache.org/licenses/LICENSE-2.0.html)", + "id": "GENERATE_ID::WORKSPACE_0", + "model": "workspace", + "name": "APOD", + }, + ], + }, +} +`; + +exports[`importer-openapi > Snapshots real-world fixture xkcd.yaml 1`] = ` +{ + "resources": { + "environments": [], + "folders": [], + "grpcRequests": [], + "httpRequests": [ + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "description": "Fetch current comic and metadata. + + +Responses: +- 200: OK", + "folderId": null, + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_0", + "method": "GET", + "model": "http_request", + "name": "GET /info.0.json", + "sortPriority": 0, + "url": "http://xkcd.com/info.0.json", + "urlParameters": [], + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "description": "Fetch comics and metadata by comic id. + + +Parameters: +- comicId (path, required) + +Responses: +- 200: OK", + "folderId": null, + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_1", + "method": "GET", + "model": "http_request", + "name": "GET /{comicId}/info.0.json", + "sortPriority": 1, + "url": "http://xkcd.com/:comicId/info.0.json", + "urlParameters": [ + { + "enabled": true, + "name": ":comicId", + "value": "0", + }, + ], + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + ], + "websocketRequests": [], + "workspaces": [ + { + "description": "Webcomic of romance, sarcasm, math, and language.", + "id": "GENERATE_ID::WORKSPACE_0", + "model": "workspace", + "name": "XKCD", + }, + ], + }, +} +`; diff --git a/plugins/importer-openapi/tests/__snapshots__/legacy.test.ts.snap b/plugins/importer-openapi/tests/__snapshots__/legacy.test.ts.snap new file mode 100644 index 00000000..b438f659 --- /dev/null +++ b/plugins/importer-openapi/tests/__snapshots__/legacy.test.ts.snap @@ -0,0 +1,2202 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`importer-openapi legacy converter > Snapshots legacy Postman-converter output for apis-guru.yaml 1`] = ` +{ + "resources": { + "environments": [ + { + "id": "GENERATE_ID::ENVIRONMENT_0", + "model": "environment", + "name": "Global Variables", + "parentId": null, + "parentModel": "workspace", + "variables": [ + { + "name": "baseUrl", + "value": "https://api.apis.guru/v2", + }, + { + "name": "api", + "value": "", + }, + { + "name": "provider", + "value": "", + }, + ], + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + ], + "folders": [ + { + "folderId": null, + "id": "GENERATE_ID::FOLDER_0", + "model": "folder", + "name": "specs/{provider}", + "sortPriority": 3, + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + ], + "httpRequests": [ + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "description": "List all APIs in the directory. +Returns links to the OpenAPI definitions for each API in the directory. +If API exist in multiple versions \`preferred\` one is explicitly marked. +Some basic info from the OpenAPI definition is cached inside each object. +This allows you to generate some simple views without needing to fetch the OpenAPI definition for each API. +", + "folderId": null, + "headers": [ + { + "enabled": true, + "name": "Accept", + "value": "application/json", + }, + ], + "id": "GENERATE_ID::HTTP_REQUEST_0", + "method": "GET", + "model": "http_request", + "name": "List all APIs", + "sortPriority": 0, + "url": "\${[baseUrl]}/list.json", + "urlParameters": [], + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "description": "Some basic metrics for the entire directory. +Just stunning numbers to put on a front page and are intended purely for WoW effect :) +", + "folderId": null, + "headers": [ + { + "enabled": true, + "name": "Accept", + "value": "application/json", + }, + ], + "id": "GENERATE_ID::HTTP_REQUEST_1", + "method": "GET", + "model": "http_request", + "name": "Get basic metrics", + "sortPriority": 1, + "url": "\${[baseUrl]}/metrics.json", + "urlParameters": [], + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "description": "List all the providers in the directory +", + "folderId": null, + "headers": [ + { + "enabled": true, + "name": "Accept", + "value": "application/json", + }, + ], + "id": "GENERATE_ID::HTTP_REQUEST_2", + "method": "GET", + "model": "http_request", + "name": "List all providers", + "sortPriority": 2, + "url": "\${[baseUrl]}/providers.json", + "urlParameters": [], + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "description": "Returns the API entry for one specific version of an API where there is no serviceName.", + "folderId": "GENERATE_ID::FOLDER_0", + "headers": [ + { + "enabled": true, + "name": "Accept", + "value": "application/json", + }, + ], + "id": "GENERATE_ID::HTTP_REQUEST_3", + "method": "GET", + "model": "http_request", + "name": "Retrieve one version of a particular API", + "sortPriority": 4, + "url": "\${[baseUrl]}/specs/:provider/\${[api]}.json", + "urlParameters": [ + { + "enabled": true, + "name": ":provider", + "value": "", + }, + ], + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "description": "Returns the API entry for one specific version of an API where there is a serviceName.", + "folderId": "GENERATE_ID::FOLDER_0", + "headers": [ + { + "enabled": true, + "name": "Accept", + "value": "application/json", + }, + ], + "id": "GENERATE_ID::HTTP_REQUEST_4", + "method": "GET", + "model": "http_request", + "name": "Retrieve one version of a particular API with a serviceName.", + "sortPriority": 5, + "url": "\${[baseUrl]}/specs/:provider/:service/\${[api]}.json", + "urlParameters": [ + { + "enabled": true, + "name": ":provider", + "value": "", + }, + { + "enabled": true, + "name": ":service", + "value": "", + }, + ], + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "description": "List all APIs in the directory for a particular providerName +Returns links to the individual API entry for each API. +", + "folderId": null, + "headers": [ + { + "enabled": true, + "name": "Accept", + "value": "application/json", + }, + ], + "id": "GENERATE_ID::HTTP_REQUEST_5", + "method": "GET", + "model": "http_request", + "name": "List all APIs for a particular provider", + "sortPriority": 6, + "url": "\${[baseUrl]}/\${[provider]}.json", + "urlParameters": [], + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "description": "List all serviceNames in the directory for a particular providerName +", + "folderId": null, + "headers": [ + { + "enabled": true, + "name": "Accept", + "value": "application/json", + }, + ], + "id": "GENERATE_ID::HTTP_REQUEST_6", + "method": "GET", + "model": "http_request", + "name": "List all serviceNames for a particular provider", + "sortPriority": 7, + "url": "\${[baseUrl]}/:provider/services.json", + "urlParameters": [ + { + "enabled": true, + "name": ":provider", + "value": "", + }, + ], + "workspaceId": "GENERATE_ID::WORKSPACE_0", + }, + ], + "workspaces": [ + { + "authentication": {}, + "authenticationType": null, + "description": "Wikipedia for Web APIs. Repository of API definitions in OpenAPI format. +**Warning**: If you want to be notified about changes in advance please join our [Slack channel](https://join.slack.com/t/mermade/shared_invite/zt-g78g7xir-MLE_CTCcXCdfJfG3CJe9qA). +Client sample: [[Demo]](https://apis.guru/simple-ui) [[Repo]](https://github.com/APIs-guru/simple-ui) + + +Contact Support: + Name: APIs.guru + Email: mike.ralphson@gmail.com", + "id": "GENERATE_ID::WORKSPACE_0", + "model": "workspace", + "name": "APIs.guru", + }, + ], + }, +} +`; + +exports[`importer-openapi legacy converter > Snapshots legacy Postman-converter output for httpbin.yaml 1`] = ` +{ + "resources": { + "environments": [ + { + "id": "GENERATE_ID::ENVIRONMENT_1", + "model": "environment", + "name": "Global Variables", + "parentId": null, + "parentModel": "workspace", + "variables": [ + { + "name": "baseUrl", + "value": "https://httpbin.org", + }, + ], + "workspaceId": "GENERATE_ID::WORKSPACE_1", + }, + ], + "folders": [ + { + "folderId": null, + "id": "GENERATE_ID::FOLDER_1", + "model": "folder", + "name": "anything", + "sortPriority": 1, + "workspaceId": "GENERATE_ID::WORKSPACE_1", + }, + { + "folderId": "GENERATE_ID::FOLDER_1", + "id": "GENERATE_ID::FOLDER_2", + "model": "folder", + "name": "{anything}", + "sortPriority": 8, + "workspaceId": "GENERATE_ID::WORKSPACE_1", + }, + { + "folderId": null, + "id": "GENERATE_ID::FOLDER_3", + "model": "folder", + "name": "cache", + "sortPriority": 20, + "workspaceId": "GENERATE_ID::WORKSPACE_1", + }, + { + "folderId": null, + "id": "GENERATE_ID::FOLDER_4", + "model": "folder", + "name": "cookies", + "sortPriority": 23, + "workspaceId": "GENERATE_ID::WORKSPACE_1", + }, + { + "folderId": "GENERATE_ID::FOLDER_4", + "id": "GENERATE_ID::FOLDER_5", + "model": "folder", + "name": "set", + "sortPriority": 26, + "workspaceId": "GENERATE_ID::WORKSPACE_1", + }, + { + "folderId": null, + "id": "GENERATE_ID::FOLDER_6", + "model": "folder", + "name": "delay/{delay}", + "sortPriority": 30, + "workspaceId": "GENERATE_ID::WORKSPACE_1", + }, + { + "folderId": null, + "id": "GENERATE_ID::FOLDER_7", + "model": "folder", + "name": "digest-auth/{qop}/{user}/{passwd}", + "sortPriority": 39, + "workspaceId": "GENERATE_ID::WORKSPACE_1", + }, + { + "folderId": "GENERATE_ID::FOLDER_7", + "id": "GENERATE_ID::FOLDER_8", + "model": "folder", + "name": "{algorithm}", + "sortPriority": 41, + "workspaceId": "GENERATE_ID::WORKSPACE_1", + }, + { + "folderId": null, + "id": "GENERATE_ID::FOLDER_9", + "model": "folder", + "name": "image", + "sortPriority": 52, + "workspaceId": "GENERATE_ID::WORKSPACE_1", + }, + { + "folderId": null, + "id": "GENERATE_ID::FOLDER_10", + "model": "folder", + "name": "redirect-to", + "sortPriority": 65, + "workspaceId": "GENERATE_ID::WORKSPACE_1", + }, + { + "folderId": null, + "id": "GENERATE_ID::FOLDER_11", + "model": "folder", + "name": "response-headers", + "sortPriority": 74, + "workspaceId": "GENERATE_ID::WORKSPACE_1", + }, + { + "folderId": null, + "id": "GENERATE_ID::FOLDER_12", + "model": "folder", + "name": "status/{codes}", + "sortPriority": 78, + "workspaceId": "GENERATE_ID::WORKSPACE_1", + }, + ], + "httpRequests": [ + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "folderId": null, + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_7", + "method": "GET", + "model": "http_request", + "name": "Absolutely 302 Redirects n times.", + "sortPriority": 0, + "url": "\${[baseUrl]}/absolute-redirect/:n", + "urlParameters": [ + { + "enabled": true, + "name": ":n", + "value": "", + }, + ], + "workspaceId": "GENERATE_ID::WORKSPACE_1", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "folderId": "GENERATE_ID::FOLDER_1", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_8", + "method": "DELETE", + "model": "http_request", + "name": "Returns anything passed in request data.", + "sortPriority": 2, + "url": "\${[baseUrl]}/anything", + "urlParameters": [], + "workspaceId": "GENERATE_ID::WORKSPACE_1", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "folderId": "GENERATE_ID::FOLDER_1", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_9", + "method": "GET", + "model": "http_request", + "name": "Returns anything passed in request data.", + "sortPriority": 3, + "url": "\${[baseUrl]}/anything", + "urlParameters": [], + "workspaceId": "GENERATE_ID::WORKSPACE_1", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "folderId": "GENERATE_ID::FOLDER_1", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_10", + "method": "PATCH", + "model": "http_request", + "name": "Returns anything passed in request data.", + "sortPriority": 4, + "url": "\${[baseUrl]}/anything", + "urlParameters": [], + "workspaceId": "GENERATE_ID::WORKSPACE_1", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "folderId": "GENERATE_ID::FOLDER_1", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_11", + "method": "POST", + "model": "http_request", + "name": "Returns anything passed in request data.", + "sortPriority": 5, + "url": "\${[baseUrl]}/anything", + "urlParameters": [], + "workspaceId": "GENERATE_ID::WORKSPACE_1", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "folderId": "GENERATE_ID::FOLDER_1", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_12", + "method": "PUT", + "model": "http_request", + "name": "Returns anything passed in request data.", + "sortPriority": 6, + "url": "\${[baseUrl]}/anything", + "urlParameters": [], + "workspaceId": "GENERATE_ID::WORKSPACE_1", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "folderId": "GENERATE_ID::FOLDER_1", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_13", + "method": "TRACE", + "model": "http_request", + "name": "Returns anything passed in request data.", + "sortPriority": 7, + "url": "\${[baseUrl]}/anything", + "urlParameters": [], + "workspaceId": "GENERATE_ID::WORKSPACE_1", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "folderId": "GENERATE_ID::FOLDER_2", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_14", + "method": "DELETE", + "model": "http_request", + "name": "Returns anything passed in request data.", + "sortPriority": 9, + "url": "\${[baseUrl]}/anything/:anything", + "urlParameters": [ + { + "enabled": true, + "name": ":anything", + "value": "", + }, + ], + "workspaceId": "GENERATE_ID::WORKSPACE_1", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "folderId": "GENERATE_ID::FOLDER_2", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_15", + "method": "GET", + "model": "http_request", + "name": "Returns anything passed in request data.", + "sortPriority": 10, + "url": "\${[baseUrl]}/anything/:anything", + "urlParameters": [ + { + "enabled": true, + "name": ":anything", + "value": "", + }, + ], + "workspaceId": "GENERATE_ID::WORKSPACE_1", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "folderId": "GENERATE_ID::FOLDER_2", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_16", + "method": "PATCH", + "model": "http_request", + "name": "Returns anything passed in request data.", + "sortPriority": 11, + "url": "\${[baseUrl]}/anything/:anything", + "urlParameters": [ + { + "enabled": true, + "name": ":anything", + "value": "", + }, + ], + "workspaceId": "GENERATE_ID::WORKSPACE_1", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "folderId": "GENERATE_ID::FOLDER_2", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_17", + "method": "POST", + "model": "http_request", + "name": "Returns anything passed in request data.", + "sortPriority": 12, + "url": "\${[baseUrl]}/anything/:anything", + "urlParameters": [ + { + "enabled": true, + "name": ":anything", + "value": "", + }, + ], + "workspaceId": "GENERATE_ID::WORKSPACE_1", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "folderId": "GENERATE_ID::FOLDER_2", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_18", + "method": "PUT", + "model": "http_request", + "name": "Returns anything passed in request data.", + "sortPriority": 13, + "url": "\${[baseUrl]}/anything/:anything", + "urlParameters": [ + { + "enabled": true, + "name": ":anything", + "value": "", + }, + ], + "workspaceId": "GENERATE_ID::WORKSPACE_1", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "folderId": "GENERATE_ID::FOLDER_2", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_19", + "method": "TRACE", + "model": "http_request", + "name": "Returns anything passed in request data.", + "sortPriority": 14, + "url": "\${[baseUrl]}/anything/:anything", + "urlParameters": [ + { + "enabled": true, + "name": ":anything", + "value": "", + }, + ], + "workspaceId": "GENERATE_ID::WORKSPACE_1", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "folderId": null, + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_20", + "method": "GET", + "model": "http_request", + "name": "Decodes base64url-encoded string.", + "sortPriority": 15, + "url": "\${[baseUrl]}/base64/:value", + "urlParameters": [ + { + "enabled": true, + "name": ":value", + "value": "SFRUUEJJTiBpcyBhd2Vzb21l", + }, + ], + "workspaceId": "GENERATE_ID::WORKSPACE_1", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "folderId": null, + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_21", + "method": "GET", + "model": "http_request", + "name": "Prompts the user for authorization using HTTP Basic Auth.", + "sortPriority": 16, + "url": "\${[baseUrl]}/basic-auth/:user/:passwd", + "urlParameters": [ + { + "enabled": true, + "name": ":user", + "value": "", + }, + { + "enabled": true, + "name": ":passwd", + "value": "", + }, + ], + "workspaceId": "GENERATE_ID::WORKSPACE_1", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "folderId": null, + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_22", + "method": "GET", + "model": "http_request", + "name": "Prompts the user for authorization using bearer authentication.", + "sortPriority": 17, + "url": "\${[baseUrl]}/bearer", + "urlParameters": [], + "workspaceId": "GENERATE_ID::WORKSPACE_1", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "folderId": null, + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_23", + "method": "GET", + "model": "http_request", + "name": "Returns Brotli-encoded data.", + "sortPriority": 18, + "url": "\${[baseUrl]}/brotli", + "urlParameters": [], + "workspaceId": "GENERATE_ID::WORKSPACE_1", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "folderId": null, + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_24", + "method": "GET", + "model": "http_request", + "name": "Returns n random bytes generated with given seed", + "sortPriority": 19, + "url": "\${[baseUrl]}/bytes/:n", + "urlParameters": [ + { + "enabled": true, + "name": ":n", + "value": "", + }, + ], + "workspaceId": "GENERATE_ID::WORKSPACE_1", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "folderId": "GENERATE_ID::FOLDER_3", + "headers": [ + { + "enabled": true, + "name": "If-Modified-Since", + "value": "", + }, + { + "enabled": true, + "name": "If-None-Match", + "value": "", + }, + ], + "id": "GENERATE_ID::HTTP_REQUEST_25", + "method": "GET", + "model": "http_request", + "name": "Returns a 304 if an If-Modified-Since header or If-None-Match is present. Returns the same as a GET otherwise.", + "sortPriority": 21, + "url": "\${[baseUrl]}/cache", + "urlParameters": [], + "workspaceId": "GENERATE_ID::WORKSPACE_1", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "folderId": "GENERATE_ID::FOLDER_3", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_26", + "method": "GET", + "model": "http_request", + "name": "Sets a Cache-Control header for n seconds.", + "sortPriority": 22, + "url": "\${[baseUrl]}/cache/:value", + "urlParameters": [ + { + "enabled": true, + "name": ":value", + "value": "", + }, + ], + "workspaceId": "GENERATE_ID::WORKSPACE_1", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "folderId": "GENERATE_ID::FOLDER_4", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_27", + "method": "GET", + "model": "http_request", + "name": "Returns cookie data.", + "sortPriority": 24, + "url": "\${[baseUrl]}/cookies", + "urlParameters": [], + "workspaceId": "GENERATE_ID::WORKSPACE_1", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "folderId": "GENERATE_ID::FOLDER_4", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_28", + "method": "GET", + "model": "http_request", + "name": "Deletes cookie(s) as provided by the query string and redirects to cookie list.", + "sortPriority": 25, + "url": "\${[baseUrl]}/cookies/delete", + "urlParameters": [ + { + "enabled": true, + "name": "freeform", + "value": "", + }, + ], + "workspaceId": "GENERATE_ID::WORKSPACE_1", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "folderId": "GENERATE_ID::FOLDER_5", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_29", + "method": "GET", + "model": "http_request", + "name": "Sets cookie(s) as provided by the query string and redirects to cookie list.", + "sortPriority": 27, + "url": "\${[baseUrl]}/cookies/set", + "urlParameters": [ + { + "enabled": true, + "name": "freeform", + "value": "", + }, + ], + "workspaceId": "GENERATE_ID::WORKSPACE_1", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "folderId": "GENERATE_ID::FOLDER_5", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_30", + "method": "GET", + "model": "http_request", + "name": "Sets a cookie and redirects to cookie list.", + "sortPriority": 28, + "url": "\${[baseUrl]}/cookies/set/:name/:value", + "urlParameters": [ + { + "enabled": true, + "name": ":name", + "value": "", + }, + { + "enabled": true, + "name": ":value", + "value": "", + }, + ], + "workspaceId": "GENERATE_ID::WORKSPACE_1", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "folderId": null, + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_31", + "method": "GET", + "model": "http_request", + "name": "Returns Deflate-encoded data.", + "sortPriority": 29, + "url": "\${[baseUrl]}/deflate", + "urlParameters": [], + "workspaceId": "GENERATE_ID::WORKSPACE_1", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "folderId": "GENERATE_ID::FOLDER_6", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_32", + "method": "DELETE", + "model": "http_request", + "name": "Returns a delayed response (max of 10 seconds).", + "sortPriority": 31, + "url": "\${[baseUrl]}/delay/:delay", + "urlParameters": [ + { + "enabled": true, + "name": ":delay", + "value": "", + }, + ], + "workspaceId": "GENERATE_ID::WORKSPACE_1", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "folderId": "GENERATE_ID::FOLDER_6", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_33", + "method": "GET", + "model": "http_request", + "name": "Returns a delayed response (max of 10 seconds).", + "sortPriority": 32, + "url": "\${[baseUrl]}/delay/:delay", + "urlParameters": [ + { + "enabled": true, + "name": ":delay", + "value": "", + }, + ], + "workspaceId": "GENERATE_ID::WORKSPACE_1", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "folderId": "GENERATE_ID::FOLDER_6", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_34", + "method": "PATCH", + "model": "http_request", + "name": "Returns a delayed response (max of 10 seconds).", + "sortPriority": 33, + "url": "\${[baseUrl]}/delay/:delay", + "urlParameters": [ + { + "enabled": true, + "name": ":delay", + "value": "", + }, + ], + "workspaceId": "GENERATE_ID::WORKSPACE_1", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "folderId": "GENERATE_ID::FOLDER_6", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_35", + "method": "POST", + "model": "http_request", + "name": "Returns a delayed response (max of 10 seconds).", + "sortPriority": 34, + "url": "\${[baseUrl]}/delay/:delay", + "urlParameters": [ + { + "enabled": true, + "name": ":delay", + "value": "", + }, + ], + "workspaceId": "GENERATE_ID::WORKSPACE_1", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "folderId": "GENERATE_ID::FOLDER_6", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_36", + "method": "PUT", + "model": "http_request", + "name": "Returns a delayed response (max of 10 seconds).", + "sortPriority": 35, + "url": "\${[baseUrl]}/delay/:delay", + "urlParameters": [ + { + "enabled": true, + "name": ":delay", + "value": "", + }, + ], + "workspaceId": "GENERATE_ID::WORKSPACE_1", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "folderId": "GENERATE_ID::FOLDER_6", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_37", + "method": "TRACE", + "model": "http_request", + "name": "Returns a delayed response (max of 10 seconds).", + "sortPriority": 36, + "url": "\${[baseUrl]}/delay/:delay", + "urlParameters": [ + { + "enabled": true, + "name": ":delay", + "value": "", + }, + ], + "workspaceId": "GENERATE_ID::WORKSPACE_1", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "folderId": null, + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_38", + "method": "DELETE", + "model": "http_request", + "name": "The request's DELETE parameters.", + "sortPriority": 37, + "url": "\${[baseUrl]}/delete", + "urlParameters": [], + "workspaceId": "GENERATE_ID::WORKSPACE_1", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "folderId": null, + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_39", + "method": "GET", + "model": "http_request", + "name": "Returns page denied by robots.txt rules.", + "sortPriority": 38, + "url": "\${[baseUrl]}/deny", + "urlParameters": [], + "workspaceId": "GENERATE_ID::WORKSPACE_1", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "folderId": "GENERATE_ID::FOLDER_7", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_40", + "method": "GET", + "model": "http_request", + "name": "Prompts the user for authorization using Digest Auth.", + "sortPriority": 40, + "url": "\${[baseUrl]}/digest-auth/:qop/:user/:passwd", + "urlParameters": [ + { + "enabled": true, + "name": ":qop", + "value": "", + }, + { + "enabled": true, + "name": ":user", + "value": "", + }, + { + "enabled": true, + "name": ":passwd", + "value": "", + }, + ], + "workspaceId": "GENERATE_ID::WORKSPACE_1", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "folderId": "GENERATE_ID::FOLDER_8", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_41", + "method": "GET", + "model": "http_request", + "name": "Prompts the user for authorization using Digest Auth + Algorithm.", + "sortPriority": 42, + "url": "\${[baseUrl]}/digest-auth/:qop/:user/:passwd/:algorithm", + "urlParameters": [ + { + "enabled": true, + "name": ":qop", + "value": "", + }, + { + "enabled": true, + "name": ":user", + "value": "", + }, + { + "enabled": true, + "name": ":passwd", + "value": "", + }, + { + "enabled": true, + "name": ":algorithm", + "value": "MD5", + }, + ], + "workspaceId": "GENERATE_ID::WORKSPACE_1", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "description": "allow settings the stale_after argument. +", + "folderId": "GENERATE_ID::FOLDER_8", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_42", + "method": "GET", + "model": "http_request", + "name": "Prompts the user for authorization using Digest Auth + Algorithm.", + "sortPriority": 43, + "url": "\${[baseUrl]}/digest-auth/:qop/:user/:passwd/:algorithm/:stale_after", + "urlParameters": [ + { + "enabled": true, + "name": ":qop", + "value": "", + }, + { + "enabled": true, + "name": ":user", + "value": "", + }, + { + "enabled": true, + "name": ":passwd", + "value": "", + }, + { + "enabled": true, + "name": ":algorithm", + "value": "MD5", + }, + { + "enabled": true, + "name": ":stale_after", + "value": "never", + }, + ], + "workspaceId": "GENERATE_ID::WORKSPACE_1", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "folderId": null, + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_43", + "method": "GET", + "model": "http_request", + "name": "Drips data over a duration after an optional initial delay.", + "sortPriority": 44, + "url": "\${[baseUrl]}/drip", + "urlParameters": [ + { + "enabled": true, + "name": "duration", + "value": "2", + }, + { + "enabled": true, + "name": "numbytes", + "value": "10", + }, + { + "enabled": true, + "name": "code", + "value": "200", + }, + { + "enabled": true, + "name": "delay", + "value": "2", + }, + ], + "workspaceId": "GENERATE_ID::WORKSPACE_1", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "folderId": null, + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_44", + "method": "GET", + "model": "http_request", + "name": "Returns a UTF-8 encoded body.", + "sortPriority": 45, + "url": "\${[baseUrl]}/encoding/utf8", + "urlParameters": [], + "workspaceId": "GENERATE_ID::WORKSPACE_1", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "folderId": null, + "headers": [ + { + "enabled": true, + "name": "If-None-Match", + "value": "", + }, + { + "enabled": true, + "name": "If-Match", + "value": "", + }, + ], + "id": "GENERATE_ID::HTTP_REQUEST_45", + "method": "GET", + "model": "http_request", + "name": "Assumes the resource has the given etag and responds to If-None-Match and If-Match headers appropriately.", + "sortPriority": 46, + "url": "\${[baseUrl]}/etag/:etag", + "urlParameters": [ + { + "enabled": true, + "name": ":etag", + "value": "", + }, + ], + "workspaceId": "GENERATE_ID::WORKSPACE_1", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "folderId": null, + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_46", + "method": "GET", + "model": "http_request", + "name": "The request's query parameters.", + "sortPriority": 47, + "url": "\${[baseUrl]}/get", + "urlParameters": [], + "workspaceId": "GENERATE_ID::WORKSPACE_1", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "folderId": null, + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_47", + "method": "GET", + "model": "http_request", + "name": "Returns GZip-encoded data.", + "sortPriority": 48, + "url": "\${[baseUrl]}/gzip", + "urlParameters": [], + "workspaceId": "GENERATE_ID::WORKSPACE_1", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "folderId": null, + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_48", + "method": "GET", + "model": "http_request", + "name": "Return the incoming request's HTTP headers.", + "sortPriority": 49, + "url": "\${[baseUrl]}/headers", + "urlParameters": [], + "workspaceId": "GENERATE_ID::WORKSPACE_1", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "folderId": null, + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_49", + "method": "GET", + "model": "http_request", + "name": "Prompts the user for authorization using HTTP Basic Auth.", + "sortPriority": 50, + "url": "\${[baseUrl]}/hidden-basic-auth/:user/:passwd", + "urlParameters": [ + { + "enabled": true, + "name": ":user", + "value": "", + }, + { + "enabled": true, + "name": ":passwd", + "value": "", + }, + ], + "workspaceId": "GENERATE_ID::WORKSPACE_1", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "folderId": null, + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_50", + "method": "GET", + "model": "http_request", + "name": "Returns a simple HTML document.", + "sortPriority": 51, + "url": "\${[baseUrl]}/html", + "urlParameters": [], + "workspaceId": "GENERATE_ID::WORKSPACE_1", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "folderId": "GENERATE_ID::FOLDER_9", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_51", + "method": "GET", + "model": "http_request", + "name": "Returns a simple image of the type suggest by the Accept header.", + "sortPriority": 53, + "url": "\${[baseUrl]}/image", + "urlParameters": [], + "workspaceId": "GENERATE_ID::WORKSPACE_1", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "folderId": "GENERATE_ID::FOLDER_9", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_52", + "method": "GET", + "model": "http_request", + "name": "Returns a simple JPEG image.", + "sortPriority": 54, + "url": "\${[baseUrl]}/image/jpeg", + "urlParameters": [], + "workspaceId": "GENERATE_ID::WORKSPACE_1", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "folderId": "GENERATE_ID::FOLDER_9", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_53", + "method": "GET", + "model": "http_request", + "name": "Returns a simple PNG image.", + "sortPriority": 55, + "url": "\${[baseUrl]}/image/png", + "urlParameters": [], + "workspaceId": "GENERATE_ID::WORKSPACE_1", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "folderId": "GENERATE_ID::FOLDER_9", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_54", + "method": "GET", + "model": "http_request", + "name": "Returns a simple SVG image.", + "sortPriority": 56, + "url": "\${[baseUrl]}/image/svg", + "urlParameters": [], + "workspaceId": "GENERATE_ID::WORKSPACE_1", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "folderId": "GENERATE_ID::FOLDER_9", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_55", + "method": "GET", + "model": "http_request", + "name": "Returns a simple WEBP image.", + "sortPriority": 57, + "url": "\${[baseUrl]}/image/webp", + "urlParameters": [], + "workspaceId": "GENERATE_ID::WORKSPACE_1", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "folderId": null, + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_56", + "method": "GET", + "model": "http_request", + "name": "Returns the requester's IP Address.", + "sortPriority": 58, + "url": "\${[baseUrl]}/ip", + "urlParameters": [], + "workspaceId": "GENERATE_ID::WORKSPACE_1", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "folderId": null, + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_57", + "method": "GET", + "model": "http_request", + "name": "Returns a simple JSON document.", + "sortPriority": 59, + "url": "\${[baseUrl]}/json", + "urlParameters": [], + "workspaceId": "GENERATE_ID::WORKSPACE_1", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "folderId": null, + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_58", + "method": "GET", + "model": "http_request", + "name": "Generate a page containing n links to other pages which do the same.", + "sortPriority": 60, + "url": "\${[baseUrl]}/links/:n/:offset", + "urlParameters": [ + { + "enabled": true, + "name": ":n", + "value": "", + }, + { + "enabled": true, + "name": ":offset", + "value": "", + }, + ], + "workspaceId": "GENERATE_ID::WORKSPACE_1", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "folderId": null, + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_59", + "method": "PATCH", + "model": "http_request", + "name": "The request's PATCH parameters.", + "sortPriority": 61, + "url": "\${[baseUrl]}/patch", + "urlParameters": [], + "workspaceId": "GENERATE_ID::WORKSPACE_1", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "folderId": null, + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_60", + "method": "POST", + "model": "http_request", + "name": "The request's POST parameters.", + "sortPriority": 62, + "url": "\${[baseUrl]}/post", + "urlParameters": [], + "workspaceId": "GENERATE_ID::WORKSPACE_1", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "folderId": null, + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_61", + "method": "PUT", + "model": "http_request", + "name": "The request's PUT parameters.", + "sortPriority": 63, + "url": "\${[baseUrl]}/put", + "urlParameters": [], + "workspaceId": "GENERATE_ID::WORKSPACE_1", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "folderId": null, + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_62", + "method": "GET", + "model": "http_request", + "name": "Streams n random bytes generated with given seed, at given chunk size per packet.", + "sortPriority": 64, + "url": "\${[baseUrl]}/range/:numbytes", + "urlParameters": [ + { + "enabled": true, + "name": ":numbytes", + "value": "", + }, + ], + "workspaceId": "GENERATE_ID::WORKSPACE_1", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "folderId": "GENERATE_ID::FOLDER_10", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_63", + "method": "DELETE", + "model": "http_request", + "name": "302/3XX Redirects to the given URL.", + "sortPriority": 66, + "url": "\${[baseUrl]}/redirect-to", + "urlParameters": [], + "workspaceId": "GENERATE_ID::WORKSPACE_1", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "folderId": "GENERATE_ID::FOLDER_10", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_64", + "method": "GET", + "model": "http_request", + "name": "302/3XX Redirects to the given URL.", + "sortPriority": 67, + "url": "\${[baseUrl]}/redirect-to", + "urlParameters": [ + { + "enabled": true, + "name": "url", + "value": "", + }, + { + "enabled": true, + "name": "status_code", + "value": "", + }, + ], + "workspaceId": "GENERATE_ID::WORKSPACE_1", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "folderId": "GENERATE_ID::FOLDER_10", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_65", + "method": "PATCH", + "model": "http_request", + "name": "302/3XX Redirects to the given URL.", + "sortPriority": 68, + "url": "\${[baseUrl]}/redirect-to", + "urlParameters": [], + "workspaceId": "GENERATE_ID::WORKSPACE_1", + }, + { + "authentication": {}, + "authenticationType": null, + "body": { + "form": [ + { + "enabled": true, + "name": "url", + "value": "", + }, + { + "enabled": true, + "name": "status_code", + "value": "", + }, + ], + }, + "bodyType": "application/x-www-form-urlencoded", + "folderId": "GENERATE_ID::FOLDER_10", + "headers": [ + { + "enabled": true, + "name": "Content-Type", + "value": "application/x-www-form-urlencoded", + }, + ], + "id": "GENERATE_ID::HTTP_REQUEST_66", + "method": "POST", + "model": "http_request", + "name": "302/3XX Redirects to the given URL.", + "sortPriority": 69, + "url": "\${[baseUrl]}/redirect-to", + "urlParameters": [], + "workspaceId": "GENERATE_ID::WORKSPACE_1", + }, + { + "authentication": {}, + "authenticationType": null, + "body": { + "form": [ + { + "enabled": true, + "name": "url", + "value": "", + }, + { + "enabled": true, + "name": "status_code", + "value": "", + }, + ], + }, + "bodyType": "application/x-www-form-urlencoded", + "folderId": "GENERATE_ID::FOLDER_10", + "headers": [ + { + "enabled": true, + "name": "Content-Type", + "value": "application/x-www-form-urlencoded", + }, + ], + "id": "GENERATE_ID::HTTP_REQUEST_67", + "method": "PUT", + "model": "http_request", + "name": "302/3XX Redirects to the given URL.", + "sortPriority": 70, + "url": "\${[baseUrl]}/redirect-to", + "urlParameters": [], + "workspaceId": "GENERATE_ID::WORKSPACE_1", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "folderId": "GENERATE_ID::FOLDER_10", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_68", + "method": "TRACE", + "model": "http_request", + "name": "302/3XX Redirects to the given URL.", + "sortPriority": 71, + "url": "\${[baseUrl]}/redirect-to", + "urlParameters": [], + "workspaceId": "GENERATE_ID::WORKSPACE_1", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "folderId": null, + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_69", + "method": "GET", + "model": "http_request", + "name": "302 Redirects n times.", + "sortPriority": 72, + "url": "\${[baseUrl]}/redirect/:n", + "urlParameters": [ + { + "enabled": true, + "name": ":n", + "value": "", + }, + ], + "workspaceId": "GENERATE_ID::WORKSPACE_1", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "folderId": null, + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_70", + "method": "GET", + "model": "http_request", + "name": "Relatively 302 Redirects n times.", + "sortPriority": 73, + "url": "\${[baseUrl]}/relative-redirect/:n", + "urlParameters": [ + { + "enabled": true, + "name": ":n", + "value": "", + }, + ], + "workspaceId": "GENERATE_ID::WORKSPACE_1", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "folderId": "GENERATE_ID::FOLDER_11", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_71", + "method": "GET", + "model": "http_request", + "name": "Returns a set of response headers from the query string.", + "sortPriority": 75, + "url": "\${[baseUrl]}/response-headers", + "urlParameters": [ + { + "enabled": true, + "name": "freeform", + "value": "", + }, + ], + "workspaceId": "GENERATE_ID::WORKSPACE_1", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "folderId": "GENERATE_ID::FOLDER_11", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_72", + "method": "POST", + "model": "http_request", + "name": "Returns a set of response headers from the query string.", + "sortPriority": 76, + "url": "\${[baseUrl]}/response-headers", + "urlParameters": [ + { + "enabled": true, + "name": "freeform", + "value": "", + }, + ], + "workspaceId": "GENERATE_ID::WORKSPACE_1", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "folderId": null, + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_73", + "method": "GET", + "model": "http_request", + "name": "Returns some robots.txt rules.", + "sortPriority": 77, + "url": "\${[baseUrl]}/robots.txt", + "urlParameters": [], + "workspaceId": "GENERATE_ID::WORKSPACE_1", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "folderId": "GENERATE_ID::FOLDER_12", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_74", + "method": "DELETE", + "model": "http_request", + "name": "Return status code or random status code if more than one are given", + "sortPriority": 79, + "url": "\${[baseUrl]}/status/:codes", + "urlParameters": [ + { + "enabled": true, + "name": ":codes", + "value": "", + }, + ], + "workspaceId": "GENERATE_ID::WORKSPACE_1", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "folderId": "GENERATE_ID::FOLDER_12", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_75", + "method": "GET", + "model": "http_request", + "name": "Return status code or random status code if more than one are given", + "sortPriority": 80, + "url": "\${[baseUrl]}/status/:codes", + "urlParameters": [ + { + "enabled": true, + "name": ":codes", + "value": "", + }, + ], + "workspaceId": "GENERATE_ID::WORKSPACE_1", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "folderId": "GENERATE_ID::FOLDER_12", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_76", + "method": "PATCH", + "model": "http_request", + "name": "Return status code or random status code if more than one are given", + "sortPriority": 81, + "url": "\${[baseUrl]}/status/:codes", + "urlParameters": [ + { + "enabled": true, + "name": ":codes", + "value": "", + }, + ], + "workspaceId": "GENERATE_ID::WORKSPACE_1", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "folderId": "GENERATE_ID::FOLDER_12", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_77", + "method": "POST", + "model": "http_request", + "name": "Return status code or random status code if more than one are given", + "sortPriority": 82, + "url": "\${[baseUrl]}/status/:codes", + "urlParameters": [ + { + "enabled": true, + "name": ":codes", + "value": "", + }, + ], + "workspaceId": "GENERATE_ID::WORKSPACE_1", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "folderId": "GENERATE_ID::FOLDER_12", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_78", + "method": "PUT", + "model": "http_request", + "name": "Return status code or random status code if more than one are given", + "sortPriority": 83, + "url": "\${[baseUrl]}/status/:codes", + "urlParameters": [ + { + "enabled": true, + "name": ":codes", + "value": "", + }, + ], + "workspaceId": "GENERATE_ID::WORKSPACE_1", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "folderId": "GENERATE_ID::FOLDER_12", + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_79", + "method": "TRACE", + "model": "http_request", + "name": "Return status code or random status code if more than one are given", + "sortPriority": 84, + "url": "\${[baseUrl]}/status/:codes", + "urlParameters": [ + { + "enabled": true, + "name": ":codes", + "value": "", + }, + ], + "workspaceId": "GENERATE_ID::WORKSPACE_1", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "folderId": null, + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_80", + "method": "GET", + "model": "http_request", + "name": "Streams n random bytes generated with given seed, at given chunk size per packet.", + "sortPriority": 85, + "url": "\${[baseUrl]}/stream-bytes/:n", + "urlParameters": [ + { + "enabled": true, + "name": ":n", + "value": "", + }, + ], + "workspaceId": "GENERATE_ID::WORKSPACE_1", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "folderId": null, + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_81", + "method": "GET", + "model": "http_request", + "name": "Stream n JSON responses", + "sortPriority": 86, + "url": "\${[baseUrl]}/stream/:n", + "urlParameters": [ + { + "enabled": true, + "name": ":n", + "value": "", + }, + ], + "workspaceId": "GENERATE_ID::WORKSPACE_1", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "folderId": null, + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_82", + "method": "GET", + "model": "http_request", + "name": "Return the incoming requests's User-Agent header.", + "sortPriority": 87, + "url": "\${[baseUrl]}/user-agent", + "urlParameters": [], + "workspaceId": "GENERATE_ID::WORKSPACE_1", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "folderId": null, + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_83", + "method": "GET", + "model": "http_request", + "name": "Return a UUID4.", + "sortPriority": 88, + "url": "\${[baseUrl]}/uuid", + "urlParameters": [], + "workspaceId": "GENERATE_ID::WORKSPACE_1", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "folderId": null, + "headers": [], + "id": "GENERATE_ID::HTTP_REQUEST_84", + "method": "GET", + "model": "http_request", + "name": "Returns a simple XML document.", + "sortPriority": 89, + "url": "\${[baseUrl]}/xml", + "urlParameters": [], + "workspaceId": "GENERATE_ID::WORKSPACE_1", + }, + ], + "workspaces": [ + { + "authentication": {}, + "authenticationType": null, + "description": "A simple HTTP Request & Response Service.

Run locally: $ docker run -p 80:80 kennethreitz/httpbin + +Contact Support: + Email: me@kennethreitz.org", + "id": "GENERATE_ID::WORKSPACE_1", + "model": "workspace", + "name": "httpbin.org", + }, + ], + }, +} +`; + +exports[`importer-openapi legacy converter > Snapshots legacy Postman-converter output for nasa-apod.yaml 1`] = ` +{ + "resources": { + "environments": [ + { + "id": "GENERATE_ID::ENVIRONMENT_2", + "model": "environment", + "name": "Global Variables", + "parentId": null, + "parentModel": "workspace", + "variables": [ + { + "name": "baseUrl", + "value": "https://api.nasa.gov/planetary", + }, + ], + "workspaceId": "GENERATE_ID::WORKSPACE_2", + }, + ], + "folders": [], + "httpRequests": [ + { + "authentication": { + "key": "\${[apiKey]}", + "location": "query", + "value": "api_key", + }, + "authenticationType": "apikey", + "body": {}, + "bodyType": null, + "description": "Returns the picture of the day", + "folderId": null, + "headers": [ + { + "enabled": true, + "name": "Accept", + "value": "application/json", + }, + ], + "id": "GENERATE_ID::HTTP_REQUEST_85", + "method": "GET", + "model": "http_request", + "name": "Returns images", + "sortPriority": 0, + "url": "\${[baseUrl]}/apod", + "urlParameters": [ + { + "enabled": true, + "name": "date", + "value": "", + }, + { + "enabled": true, + "name": "hd", + "value": "", + }, + ], + "workspaceId": "GENERATE_ID::WORKSPACE_2", + }, + ], + "workspaces": [ + { + "authentication": {}, + "authenticationType": null, + "description": "This endpoint structures the APOD imagery and associated metadata so that it can be repurposed for other applications. In addition, if the concept_tags parameter is set to True, then keywords derived from the image explanation are returned. These keywords could be used as auto-generated hashtags for twitter or instagram feeds; but generally help with discoverability of relevant imagery + +Contact Support: + Email: evan.t.yates@nasa.gov", + "id": "GENERATE_ID::WORKSPACE_2", + "model": "workspace", + "name": "APOD", + }, + ], + }, +} +`; + +exports[`importer-openapi legacy converter > Snapshots legacy Postman-converter output for xkcd.yaml 1`] = ` +{ + "resources": { + "environments": [ + { + "id": "GENERATE_ID::ENVIRONMENT_3", + "model": "environment", + "name": "Global Variables", + "parentId": null, + "parentModel": "workspace", + "variables": [ + { + "name": "baseUrl", + "value": "http://xkcd.com/", + }, + ], + "workspaceId": "GENERATE_ID::WORKSPACE_3", + }, + ], + "folders": [], + "httpRequests": [ + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "description": "Fetch current comic and metadata. +", + "folderId": null, + "headers": [ + { + "enabled": true, + "name": "Accept", + "value": "*/*", + }, + ], + "id": "GENERATE_ID::HTTP_REQUEST_86", + "method": "GET", + "model": "http_request", + "name": "Fetch current comic and metadata. +", + "sortPriority": 0, + "url": "\${[baseUrl]}/info.0.json", + "urlParameters": [], + "workspaceId": "GENERATE_ID::WORKSPACE_3", + }, + { + "authentication": {}, + "authenticationType": null, + "body": {}, + "bodyType": null, + "description": "Fetch comics and metadata by comic id. +", + "folderId": null, + "headers": [ + { + "enabled": true, + "name": "Accept", + "value": "*/*", + }, + ], + "id": "GENERATE_ID::HTTP_REQUEST_87", + "method": "GET", + "model": "http_request", + "name": "Fetch comics and metadata by comic id. +", + "sortPriority": 1, + "url": "\${[baseUrl]}/:comicId/info.0.json", + "urlParameters": [ + { + "enabled": true, + "name": ":comicId", + "value": "", + }, + ], + "workspaceId": "GENERATE_ID::WORKSPACE_3", + }, + ], + "workspaces": [ + { + "authentication": {}, + "authenticationType": null, + "description": "Webcomic of romance, sarcasm, math, and language.", + "id": "GENERATE_ID::WORKSPACE_3", + "model": "workspace", + "name": "XKCD", + }, + ], + }, +} +`; diff --git a/plugins/importer-openapi/tests/fixtures/real-world/SOURCES.md b/plugins/importer-openapi/tests/fixtures/real-world/SOURCES.md new file mode 100644 index 00000000..f4bd7af6 --- /dev/null +++ b/plugins/importer-openapi/tests/fixtures/real-world/SOURCES.md @@ -0,0 +1,8 @@ +# Real-World OpenAPI Fixtures + +These fixtures were copied from the public APIs.guru OpenAPI directory: + +- `apis-guru.yaml`: https://api.apis.guru/v2/specs/apis.guru/2.2.0/openapi.yaml +- `httpbin.yaml`: https://api.apis.guru/v2/specs/httpbin.org/0.9.2/openapi.yaml +- `nasa-apod.yaml`: https://api.apis.guru/v2/specs/nasa.gov/apod/1.0.0/openapi.yaml +- `xkcd.yaml`: https://api.apis.guru/v2/specs/xkcd.com/1.0.0/openapi.yaml diff --git a/plugins/importer-openapi/tests/fixtures/real-world/apis-guru.yaml b/plugins/importer-openapi/tests/fixtures/real-world/apis-guru.yaml new file mode 100644 index 00000000..4dc5db11 --- /dev/null +++ b/plugins/importer-openapi/tests/fixtures/real-world/apis-guru.yaml @@ -0,0 +1,399 @@ +openapi: 3.0.0 +servers: + - url: https://api.apis.guru/v2 +info: + contact: + email: mike.ralphson@gmail.com + name: APIs.guru + url: https://APIs.guru + description: | + Wikipedia for Web APIs. Repository of API definitions in OpenAPI format. + **Warning**: If you want to be notified about changes in advance please join our [Slack channel](https://join.slack.com/t/mermade/shared_invite/zt-g78g7xir-MLE_CTCcXCdfJfG3CJe9qA). + Client sample: [[Demo]](https://apis.guru/simple-ui) [[Repo]](https://github.com/APIs-guru/simple-ui) + license: + name: CC0 1.0 + url: https://github.com/APIs-guru/openapi-directory#licenses + title: APIs.guru + version: 2.2.0 + x-apisguru-categories: + - open_data + - developer_tools + x-logo: + url: https://api.apis.guru/v2/cache/logo/https_apis.guru_branding_logo_vertical.svg + x-origin: + - format: openapi + url: https://api.apis.guru/v2/openapi.yaml + version: "3.0" + x-providerName: apis.guru + x-tags: + - API + - Catalog + - Directory + - REST + - Swagger + - OpenAPI +externalDocs: + url: https://github.com/APIs-guru/openapi-directory/blob/master/API.md +security: [] +tags: + - description: Actions relating to APIs in the collection + name: APIs +paths: + /list.json: + get: + description: | + List all APIs in the directory. + Returns links to the OpenAPI definitions for each API in the directory. + If API exist in multiple versions `preferred` one is explicitly marked. + Some basic info from the OpenAPI definition is cached inside each object. + This allows you to generate some simple views without needing to fetch the OpenAPI definition for each API. + operationId: listAPIs + responses: + "200": + content: + application/json: + schema: + $ref: "#/components/schemas/APIs" + description: OK + summary: List all APIs + tags: + - APIs + /metrics.json: + get: + description: | + Some basic metrics for the entire directory. + Just stunning numbers to put on a front page and are intended purely for WoW effect :) + operationId: getMetrics + responses: + "200": + content: + application/json: + schema: + $ref: "#/components/schemas/Metrics" + description: OK + summary: Get basic metrics + tags: + - APIs + /providers.json: + get: + description: | + List all the providers in the directory + operationId: getProviders + responses: + "200": + content: + application/json: + schema: + properties: + data: + items: + minLength: 1 + type: string + minItems: 1 + type: array + type: object + description: OK + summary: List all providers + tags: + - APIs + "/specs/{provider}/{api}.json": + get: + description: Returns the API entry for one specific version of an API where there is no serviceName. + operationId: getAPI + parameters: + - $ref: "#/components/parameters/provider" + - $ref: "#/components/parameters/api" + responses: + "200": + content: + application/json: + schema: + $ref: "#/components/schemas/API" + description: OK + summary: Retrieve one version of a particular API + tags: + - APIs + "/specs/{provider}/{service}/{api}.json": + get: + description: Returns the API entry for one specific version of an API where there is a serviceName. + operationId: getServiceAPI + parameters: + - $ref: "#/components/parameters/provider" + - in: path + name: service + required: true + schema: + example: graph + maxLength: 255 + minLength: 1 + type: string + - $ref: "#/components/parameters/api" + responses: + "200": + content: + application/json: + schema: + $ref: "#/components/schemas/API" + description: OK + summary: Retrieve one version of a particular API with a serviceName. + tags: + - APIs + "/{provider}.json": + get: + description: | + List all APIs in the directory for a particular providerName + Returns links to the individual API entry for each API. + operationId: getProvider + parameters: + - $ref: "#/components/parameters/provider" + responses: + "200": + content: + application/json: + schema: + $ref: "#/components/schemas/APIs" + description: OK + summary: List all APIs for a particular provider + tags: + - APIs + "/{provider}/services.json": + get: + description: | + List all serviceNames in the directory for a particular providerName + operationId: getServices + parameters: + - $ref: "#/components/parameters/provider" + responses: + "200": + content: + application/json: + schema: + properties: + data: + items: + minLength: 0 + type: string + minItems: 1 + type: array + type: object + description: OK + summary: List all serviceNames for a particular provider + tags: + - APIs +components: + parameters: + api: + in: path + name: api + required: true + schema: + example: 2.1.0 + maxLength: 255 + minLength: 1 + type: string + provider: + in: path + name: provider + required: true + schema: + example: apis.guru + maxLength: 255 + minLength: 1 + type: string + schemas: + API: + additionalProperties: false + description: Meta information about API + properties: + added: + description: Timestamp when the API was first added to the directory + format: date-time + type: string + preferred: + description: Recommended version + type: string + versions: + additionalProperties: + $ref: "#/components/schemas/ApiVersion" + description: List of supported versions of the API + minProperties: 1 + type: object + required: + - added + - preferred + - versions + type: object + APIs: + additionalProperties: + $ref: "#/components/schemas/API" + description: | + List of API details. + It is a JSON object with API IDs(`[:]`) as keys. + example: + googleapis.com:drive: + added: 2015-02-22T20:00:45.000Z + preferred: v3 + versions: + v2: + added: 2015-02-22T20:00:45.000Z + info: + title: Drive + version: v2 + x-apiClientRegistration: + url: https://console.developers.google.com + x-logo: + url: https://api.apis.guru/v2/cache/logo/https_www.gstatic.com_images_icons_material_product_2x_drive_32dp.png + x-origin: + format: google + url: https://www.googleapis.com/discovery/v1/apis/drive/v2/rest + version: v1 + x-preferred: false + x-providerName: googleapis.com + x-serviceName: drive + swaggerUrl: https://api.apis.guru/v2/specs/googleapis.com/drive/v2/swagger.json + swaggerYamlUrl: https://api.apis.guru/v2/specs/googleapis.com/drive/v2/swagger.yaml + updated: 2016-06-17T00:21:44.000Z + v3: + added: 2015-12-12T00:25:13.000Z + info: + title: Drive + version: v3 + x-apiClientRegistration: + url: https://console.developers.google.com + x-logo: + url: https://api.apis.guru/v2/cache/logo/https_www.gstatic.com_images_icons_material_product_2x_drive_32dp.png + x-origin: + format: google + url: https://www.googleapis.com/discovery/v1/apis/drive/v3/rest + version: v1 + x-preferred: true + x-providerName: googleapis.com + x-serviceName: drive + swaggerUrl: https://api.apis.guru/v2/specs/googleapis.com/drive/v3/swagger.json + swaggerYamlUrl: https://api.apis.guru/v2/specs/googleapis.com/drive/v3/swagger.yaml + updated: 2016-06-17T00:21:44.000Z + minProperties: 1 + type: object + ApiVersion: + additionalProperties: false + properties: + added: + description: Timestamp when the version was added + format: date-time + type: string + externalDocs: + description: Copy of `externalDocs` section from OpenAPI definition + minProperties: 1 + type: object + info: + description: Copy of `info` section from OpenAPI definition + minProperties: 1 + type: object + link: + description: Link to the individual API entry for this API + format: url + type: string + openapiVer: + description: The value of the `openapi` or `swagger` property of the source definition + type: string + swaggerUrl: + description: URL to OpenAPI definition in JSON format + format: url + type: string + swaggerYamlUrl: + description: URL to OpenAPI definition in YAML format + format: url + type: string + updated: + description: Timestamp when the version was updated + format: date-time + type: string + required: + - added + - updated + - swaggerUrl + - swaggerYamlUrl + - info + - openapiVer + type: object + Metrics: + additionalProperties: false + description: List of basic metrics + example: + datasets: [] + fixedPct: 22 + fixes: 81119 + invalid: 598 + issues: 28 + numAPIs: 2501 + numDrivers: 10 + numEndpoints: 106448 + numProviders: 659 + numSpecs: 3329 + stars: 2429 + thisWeek: + added: 45 + updated: 171 + unofficial: 25 + unreachable: 123 + properties: + datasets: + description: Data used for charting etc + items: {} + type: array + fixedPct: + description: Percentage of all APIs where auto fixes have been applied + type: integer + fixes: + description: Total number of fixes applied across all APIs + type: integer + invalid: + description: Number of newly invalid APIs + type: integer + issues: + description: Open GitHub issues on our main repo + type: integer + numAPIs: + description: Number of unique APIs + minimum: 1 + type: integer + numDrivers: + description: Number of methods of API retrieval + type: integer + numEndpoints: + description: Total number of endpoints inside all definitions + minimum: 1 + type: integer + numProviders: + description: Number of API providers in directory + type: integer + numSpecs: + description: Number of API definitions including different versions of the same API + minimum: 1 + type: integer + stars: + description: GitHub stars for our main repo + type: integer + thisWeek: + description: Summary totals for the last 7 days + properties: + added: + description: APIs added in the last week + type: integer + updated: + description: APIs updated in the last week + type: integer + type: object + unofficial: + description: Number of unofficial APIs + type: integer + unreachable: + description: Number of unreachable (4XX,5XX status) APIs + type: integer + required: + - numSpecs + - numAPIs + - numEndpoints + type: object +x-optic-standard: "@febf8ac6-ee67-4565-b45a-5c85a469dca7/Fz6KU3_wMIO5iJ6_VUZ30" +x-optic-url: https://app.useoptic.com/organizations/febf8ac6-ee67-4565-b45a-5c85a469dca7/apis/_0fKWqUvhs9ssYNkq1k-c diff --git a/plugins/importer-openapi/tests/fixtures/real-world/httpbin.yaml b/plugins/importer-openapi/tests/fixtures/real-world/httpbin.yaml new file mode 100644 index 00000000..25e52a25 --- /dev/null +++ b/plugins/importer-openapi/tests/fixtures/real-world/httpbin.yaml @@ -0,0 +1,1121 @@ +openapi: 3.0.0 +servers: + - url: https://httpbin.org +info: + contact: + email: me@kennethreitz.org + url: https://kennethreitz.org + x-responsibleDeveloper: Kenneth Reitz + x-responsibleOrganization: Kenneth Reitz + description: "A simple HTTP Request & Response Service.

Run locally: $ docker run -p 80:80 kennethreitz/httpbin" + title: httpbin.org + version: 0.9.2 + x-apisguru-categories: + - developer_tools + x-origin: + - format: swagger + url: http://httpbin.org/spec.json + version: "2.0" + x-providerName: httpbin.org + x-logo: + url: https://api.apis.guru/v2/cache/logo/https_apis.guru_assets_images_no-logo.svg +tags: + - description: Testing different HTTP verbs + name: HTTP Methods + - description: Auth methods + name: Auth + - description: Generates responses with given status code + name: Status codes + - description: Inspect the request data + name: Request inspection + - description: Inspect the response data like caching and headers + name: Response inspection + - description: Returns responses in different data formats + name: Response formats + - description: Generates random and dynamic data + name: Dynamic data + - description: Creates, reads and deletes Cookies + name: Cookies + - description: Returns different image formats + name: Images + - description: Returns different redirect responses + name: Redirects + - description: Returns anything that is passed to request + name: Anything +paths: + "/absolute-redirect/{n}": + get: + parameters: + - in: path + name: n + required: true + schema: + type: integer + responses: + "302": + description: A redirection. + summary: Absolutely 302 Redirects n times. + tags: + - Redirects + /anything: + delete: + responses: + "200": + description: Anything passed in request + summary: Returns anything passed in request data. + tags: + - Anything + get: + responses: + "200": + description: Anything passed in request + summary: Returns anything passed in request data. + tags: + - Anything + patch: + responses: + "200": + description: Anything passed in request + summary: Returns anything passed in request data. + tags: + - Anything + post: + responses: + "200": + description: Anything passed in request + summary: Returns anything passed in request data. + tags: + - Anything + put: + responses: + "200": + description: Anything passed in request + summary: Returns anything passed in request data. + tags: + - Anything + trace: + responses: + "200": + description: Anything passed in request + summary: Returns anything passed in request data. + tags: + - Anything + "/anything/{anything}": + delete: + parameters: + - description: Automatically added + in: path + name: anything + required: true + schema: + type: string + responses: + "200": + description: Anything passed in request + summary: Returns anything passed in request data. + tags: + - Anything + get: + parameters: + - description: Automatically added + in: path + name: anything + required: true + schema: + type: string + responses: + "200": + description: Anything passed in request + summary: Returns anything passed in request data. + tags: + - Anything + patch: + parameters: + - description: Automatically added + in: path + name: anything + required: true + schema: + type: string + responses: + "200": + description: Anything passed in request + summary: Returns anything passed in request data. + tags: + - Anything + post: + parameters: + - description: Automatically added + in: path + name: anything + required: true + schema: + type: string + responses: + "200": + description: Anything passed in request + summary: Returns anything passed in request data. + tags: + - Anything + put: + parameters: + - description: Automatically added + in: path + name: anything + required: true + schema: + type: string + responses: + "200": + description: Anything passed in request + summary: Returns anything passed in request data. + tags: + - Anything + trace: + parameters: + - description: Automatically added + in: path + name: anything + required: true + schema: + type: string + responses: + "200": + description: Anything passed in request + summary: Returns anything passed in request data. + tags: + - Anything + "/base64/{value}": + get: + parameters: + - in: path + name: value + required: true + schema: + default: SFRUUEJJTiBpcyBhd2Vzb21l + type: string + responses: + "200": + description: Decoded base64 content. + summary: Decodes base64url-encoded string. + tags: + - Dynamic data + "/basic-auth/{user}/{passwd}": + get: + parameters: + - in: path + name: user + required: true + schema: + type: string + - in: path + name: passwd + required: true + schema: + type: string + responses: + "200": + description: Sucessful authentication. + "401": + description: Unsuccessful authentication. + summary: Prompts the user for authorization using HTTP Basic Auth. + tags: + - Auth + /bearer: + get: + parameters: + - in: header + name: Authorization + schema: + type: string + responses: + "200": + description: Sucessful authentication. + "401": + description: Unsuccessful authentication. + summary: Prompts the user for authorization using bearer authentication. + tags: + - Auth + /brotli: + get: + responses: + "200": + description: Brotli-encoded data. + summary: Returns Brotli-encoded data. + tags: + - Response formats + "/bytes/{n}": + get: + parameters: + - in: path + name: n + required: true + schema: + type: integer + responses: + "200": + description: Bytes. + summary: Returns n random bytes generated with given seed + tags: + - Dynamic data + /cache: + get: + parameters: + - in: header + name: If-Modified-Since + schema: + type: string + - in: header + name: If-None-Match + schema: + type: string + responses: + "200": + description: Cached response + "304": + description: Modified + summary: Returns a 304 if an If-Modified-Since header or If-None-Match is present. Returns the same as a GET otherwise. + tags: + - Response inspection + "/cache/{value}": + get: + parameters: + - in: path + name: value + required: true + schema: + type: integer + responses: + "200": + description: Cache control set + summary: Sets a Cache-Control header for n seconds. + tags: + - Response inspection + /cookies: + get: + responses: + "200": + description: Set cookies. + summary: Returns cookie data. + tags: + - Cookies + /cookies/delete: + get: + parameters: + - allowEmptyValue: true + explode: true + in: query + name: freeform + schema: + additionalProperties: + type: string + type: string + style: form + responses: + "200": + description: Redirect to cookie list + summary: Deletes cookie(s) as provided by the query string and redirects to cookie list. + tags: + - Cookies + /cookies/set: + get: + parameters: + - allowEmptyValue: true + explode: true + in: query + name: freeform + schema: + additionalProperties: + type: string + type: string + style: form + responses: + "200": + description: Redirect to cookie list + summary: Sets cookie(s) as provided by the query string and redirects to cookie list. + tags: + - Cookies + "/cookies/set/{name}/{value}": + get: + parameters: + - in: path + name: name + required: true + schema: + type: string + - in: path + name: value + required: true + schema: + type: string + responses: + "200": + description: Set cookies and redirects to cookie list. + summary: Sets a cookie and redirects to cookie list. + tags: + - Cookies + /deflate: + get: + responses: + "200": + description: Defalte-encoded data. + summary: Returns Deflate-encoded data. + tags: + - Response formats + "/delay/{delay}": + delete: + parameters: + - in: path + name: delay + required: true + schema: + type: integer + responses: + "200": + description: A delayed response. + summary: Returns a delayed response (max of 10 seconds). + tags: + - Dynamic data + get: + parameters: + - in: path + name: delay + required: true + schema: + type: integer + responses: + "200": + description: A delayed response. + summary: Returns a delayed response (max of 10 seconds). + tags: + - Dynamic data + patch: + parameters: + - in: path + name: delay + required: true + schema: + type: integer + responses: + "200": + description: A delayed response. + summary: Returns a delayed response (max of 10 seconds). + tags: + - Dynamic data + post: + parameters: + - in: path + name: delay + required: true + schema: + type: integer + responses: + "200": + description: A delayed response. + summary: Returns a delayed response (max of 10 seconds). + tags: + - Dynamic data + put: + parameters: + - in: path + name: delay + required: true + schema: + type: integer + responses: + "200": + description: A delayed response. + summary: Returns a delayed response (max of 10 seconds). + tags: + - Dynamic data + trace: + parameters: + - in: path + name: delay + required: true + schema: + type: integer + responses: + "200": + description: A delayed response. + summary: Returns a delayed response (max of 10 seconds). + tags: + - Dynamic data + /delete: + delete: + responses: + "200": + description: The request's DELETE parameters. + summary: The request's DELETE parameters. + tags: + - HTTP Methods + /deny: + get: + responses: + "200": + description: Denied message + summary: Returns page denied by robots.txt rules. + tags: + - Response formats + "/digest-auth/{qop}/{user}/{passwd}": + get: + parameters: + - description: auth or auth-int + in: path + name: qop + required: true + schema: + type: string + - in: path + name: user + required: true + schema: + type: string + - in: path + name: passwd + required: true + schema: + type: string + responses: + "200": + description: Sucessful authentication. + "401": + description: Unsuccessful authentication. + summary: Prompts the user for authorization using Digest Auth. + tags: + - Auth + "/digest-auth/{qop}/{user}/{passwd}/{algorithm}": + get: + parameters: + - description: auth or auth-int + in: path + name: qop + required: true + schema: + type: string + - in: path + name: user + required: true + schema: + type: string + - in: path + name: passwd + required: true + schema: + type: string + - description: MD5, SHA-256, SHA-512 + in: path + name: algorithm + required: true + schema: + default: MD5 + type: string + responses: + "200": + description: Sucessful authentication. + "401": + description: Unsuccessful authentication. + summary: Prompts the user for authorization using Digest Auth + Algorithm. + tags: + - Auth + "/digest-auth/{qop}/{user}/{passwd}/{algorithm}/{stale_after}": + get: + description: | + allow settings the stale_after argument. + parameters: + - description: auth or auth-int + in: path + name: qop + required: true + schema: + type: string + - in: path + name: user + required: true + schema: + type: string + - in: path + name: passwd + required: true + schema: + type: string + - description: MD5, SHA-256, SHA-512 + in: path + name: algorithm + required: true + schema: + default: MD5 + type: string + - in: path + name: stale_after + required: true + schema: + default: never + type: string + responses: + "200": + description: Sucessful authentication. + "401": + description: Unsuccessful authentication. + summary: Prompts the user for authorization using Digest Auth + Algorithm. + tags: + - Auth + /drip: + get: + parameters: + - description: The amount of time (in seconds) over which to drip each byte + in: query + name: duration + required: false + schema: + default: 2 + type: number + - description: The number of bytes to respond with + in: query + name: numbytes + required: false + schema: + default: 10 + type: integer + - description: The response code that will be returned + in: query + name: code + required: false + schema: + default: 200 + type: integer + - description: The amount of time (in seconds) to delay before responding + in: query + name: delay + required: false + schema: + default: 2 + type: number + responses: + "200": + description: A dripped response. + summary: Drips data over a duration after an optional initial delay. + tags: + - Dynamic data + /encoding/utf8: + get: + responses: + "200": + description: Encoded UTF-8 content. + summary: Returns a UTF-8 encoded body. + tags: + - Response formats + "/etag/{etag}": + get: + parameters: + - in: header + name: If-None-Match + schema: + type: string + - in: header + name: If-Match + schema: + type: string + - description: Automatically added + in: path + name: etag + required: true + schema: + type: string + responses: + "200": + description: Normal response + "412": + description: match + summary: Assumes the resource has the given etag and responds to If-None-Match and If-Match headers appropriately. + tags: + - Response inspection + /get: + get: + responses: + "200": + description: The request's query parameters. + summary: The request's query parameters. + tags: + - HTTP Methods + /gzip: + get: + responses: + "200": + description: GZip-encoded data. + summary: Returns GZip-encoded data. + tags: + - Response formats + /headers: + get: + responses: + "200": + description: The request's headers. + summary: Return the incoming request's HTTP headers. + tags: + - Request inspection + "/hidden-basic-auth/{user}/{passwd}": + get: + parameters: + - in: path + name: user + required: true + schema: + type: string + - in: path + name: passwd + required: true + schema: + type: string + responses: + "200": + description: Sucessful authentication. + "404": + description: Unsuccessful authentication. + summary: Prompts the user for authorization using HTTP Basic Auth. + tags: + - Auth + /html: + get: + responses: + "200": + description: An HTML page. + summary: Returns a simple HTML document. + tags: + - Response formats + /image: + get: + responses: + "200": + description: An image. + summary: Returns a simple image of the type suggest by the Accept header. + tags: + - Images + /image/jpeg: + get: + responses: + "200": + description: A JPEG image. + summary: Returns a simple JPEG image. + tags: + - Images + /image/png: + get: + responses: + "200": + description: A PNG image. + summary: Returns a simple PNG image. + tags: + - Images + /image/svg: + get: + responses: + "200": + description: An SVG image. + summary: Returns a simple SVG image. + tags: + - Images + /image/webp: + get: + responses: + "200": + description: A WEBP image. + summary: Returns a simple WEBP image. + tags: + - Images + /ip: + get: + responses: + "200": + description: The Requester's IP Address. + summary: Returns the requester's IP Address. + tags: + - Request inspection + /json: + get: + responses: + "200": + description: An JSON document. + summary: Returns a simple JSON document. + tags: + - Response formats + "/links/{n}/{offset}": + get: + parameters: + - in: path + name: n + required: true + schema: + type: integer + - in: path + name: offset + required: true + schema: + type: integer + responses: + "200": + description: HTML links. + summary: Generate a page containing n links to other pages which do the same. + tags: + - Dynamic data + /patch: + patch: + responses: + "200": + description: The request's PATCH parameters. + summary: The request's PATCH parameters. + tags: + - HTTP Methods + /post: + post: + responses: + "200": + description: The request's POST parameters. + summary: The request's POST parameters. + tags: + - HTTP Methods + /put: + put: + responses: + "200": + description: The request's PUT parameters. + summary: The request's PUT parameters. + tags: + - HTTP Methods + "/range/{numbytes}": + get: + parameters: + - in: path + name: numbytes + required: true + schema: + type: integer + responses: + "200": + description: Bytes. + summary: Streams n random bytes generated with given seed, at given chunk size per packet. + tags: + - Dynamic data + /redirect-to: + delete: + responses: + "302": + description: A redirection. + summary: 302/3XX Redirects to the given URL. + tags: + - Redirects + get: + parameters: + - in: query + name: url + required: true + schema: + type: string + - in: query + name: status_code + schema: + type: integer + responses: + "302": + description: A redirection. + summary: 302/3XX Redirects to the given URL. + tags: + - Redirects + patch: + responses: + "302": + description: A redirection. + summary: 302/3XX Redirects to the given URL. + tags: + - Redirects + post: + requestBody: + $ref: "#/components/requestBodies/postRedirectTo" + responses: + "302": + description: A redirection. + summary: 302/3XX Redirects to the given URL. + tags: + - Redirects + put: + requestBody: + $ref: "#/components/requestBodies/postRedirectTo" + responses: + "302": + description: A redirection. + summary: 302/3XX Redirects to the given URL. + tags: + - Redirects + trace: + responses: + "302": + description: A redirection. + summary: 302/3XX Redirects to the given URL. + tags: + - Redirects + "/redirect/{n}": + get: + parameters: + - in: path + name: n + required: true + schema: + type: integer + responses: + "302": + description: A redirection. + summary: 302 Redirects n times. + tags: + - Redirects + "/relative-redirect/{n}": + get: + parameters: + - in: path + name: n + required: true + schema: + type: integer + responses: + "302": + description: A redirection. + summary: Relatively 302 Redirects n times. + tags: + - Redirects + /response-headers: + get: + parameters: + - allowEmptyValue: true + explode: true + in: query + name: freeform + schema: + additionalProperties: + type: string + type: string + style: form + responses: + "200": + description: Response headers + summary: Returns a set of response headers from the query string. + tags: + - Response inspection + post: + parameters: + - allowEmptyValue: true + explode: true + in: query + name: freeform + schema: + additionalProperties: + type: string + type: string + style: form + responses: + "200": + description: Response headers + summary: Returns a set of response headers from the query string. + tags: + - Response inspection + /robots.txt: + get: + responses: + "200": + description: Robots file + summary: Returns some robots.txt rules. + tags: + - Response formats + "/status/{codes}": + delete: + parameters: + - in: path + name: codes + required: true + schema: + type: string + responses: + "100": + description: Informational responses + "200": + description: Success + "300": + description: Redirection + "400": + description: Client Errors + "500": + description: Server Errors + summary: Return status code or random status code if more than one are given + tags: + - Status codes + get: + parameters: + - in: path + name: codes + required: true + schema: + type: string + responses: + "100": + description: Informational responses + "200": + description: Success + "300": + description: Redirection + "400": + description: Client Errors + "500": + description: Server Errors + summary: Return status code or random status code if more than one are given + tags: + - Status codes + patch: + parameters: + - in: path + name: codes + required: true + schema: + type: string + responses: + "100": + description: Informational responses + "200": + description: Success + "300": + description: Redirection + "400": + description: Client Errors + "500": + description: Server Errors + summary: Return status code or random status code if more than one are given + tags: + - Status codes + post: + parameters: + - in: path + name: codes + required: true + schema: + type: string + responses: + "100": + description: Informational responses + "200": + description: Success + "300": + description: Redirection + "400": + description: Client Errors + "500": + description: Server Errors + summary: Return status code or random status code if more than one are given + tags: + - Status codes + put: + parameters: + - in: path + name: codes + required: true + schema: + type: string + responses: + "100": + description: Informational responses + "200": + description: Success + "300": + description: Redirection + "400": + description: Client Errors + "500": + description: Server Errors + summary: Return status code or random status code if more than one are given + tags: + - Status codes + trace: + parameters: + - in: path + name: codes + required: true + schema: + type: string + responses: + "100": + description: Informational responses + "200": + description: Success + "300": + description: Redirection + "400": + description: Client Errors + "500": + description: Server Errors + summary: Return status code or random status code if more than one are given + tags: + - Status codes + "/stream-bytes/{n}": + get: + parameters: + - in: path + name: n + required: true + schema: + type: integer + responses: + "200": + description: Bytes. + summary: Streams n random bytes generated with given seed, at given chunk size per packet. + tags: + - Dynamic data + "/stream/{n}": + get: + parameters: + - in: path + name: n + required: true + schema: + type: integer + responses: + "200": + description: Streamed JSON responses. + summary: Stream n JSON responses + tags: + - Dynamic data + /user-agent: + get: + responses: + "200": + description: The request's User-Agent header. + summary: Return the incoming requests's User-Agent header. + tags: + - Request inspection + /uuid: + get: + responses: + "200": + description: A UUID4. + summary: Return a UUID4. + tags: + - Dynamic data + /xml: + get: + responses: + "200": + description: An XML document. + summary: Returns a simple XML document. + tags: + - Response formats +components: + requestBodies: + postRedirectTo: + content: + application/x-www-form-urlencoded: + schema: + properties: + status_code: + type: integer + url: + type: string + required: + - url + type: object + required: true +x-protocol: https diff --git a/plugins/importer-openapi/tests/fixtures/real-world/nasa-apod.yaml b/plugins/importer-openapi/tests/fixtures/real-world/nasa-apod.yaml new file mode 100644 index 00000000..172317fc --- /dev/null +++ b/plugins/importer-openapi/tests/fixtures/real-world/nasa-apod.yaml @@ -0,0 +1,69 @@ +openapi: 3.0.0 +servers: + - url: https://api.nasa.gov/planetary + - url: http://api.nasa.gov/planetary +info: + contact: + email: evan.t.yates@nasa.gov + description: This endpoint structures the APOD imagery and associated metadata so that it can be repurposed for other applications. In addition, if the concept_tags parameter is set to True, then keywords derived from the image explanation are returned. These keywords could be used as auto-generated hashtags for twitter or instagram feeds; but generally help with discoverability of relevant imagery + license: + name: Apache 2.0 + url: http://www.apache.org/licenses/LICENSE-2.0.html + title: APOD + version: 1.0.0 + x-apisguru-categories: + - media + - open_data + x-origin: + - format: swagger + url: https://raw.githubusercontent.com/nasa/api-docs/gh-pages/assets/json/APOD + version: "2.0" + x-providerName: nasa.gov + x-serviceName: apod + x-logo: + url: https://api.apis.guru/v2/cache/logo/https_apis.guru_assets_images_no-logo.svg +tags: + - description: An example tag + externalDocs: + description: Here's a link + url: https://example.com + name: request tag +paths: + /apod: + get: + description: Returns the picture of the day + parameters: + - description: The date of the APOD image to retrieve + in: query + name: date + required: false + schema: + type: string + - description: Retrieve the URL for the high resolution image + in: query + name: hd + required: false + schema: + type: boolean + responses: + "200": + content: + application/json: + schema: + items: + x-thing: ok + type: array + description: successful operation + "400": + description: Date must be between Jun 16, 1995 and Mar 28, 2019. + security: + - api_key: [] + summary: Returns images + tags: + - request tag +components: + securitySchemes: + api_key: + in: query + name: api_key + type: apiKey diff --git a/plugins/importer-openapi/tests/fixtures/real-world/xkcd.yaml b/plugins/importer-openapi/tests/fixtures/real-world/xkcd.yaml new file mode 100644 index 00000000..49016335 --- /dev/null +++ b/plugins/importer-openapi/tests/fixtures/real-world/xkcd.yaml @@ -0,0 +1,78 @@ +openapi: 3.0.0 +servers: + - url: http://xkcd.com/ +info: + description: Webcomic of romance, sarcasm, math, and language. + title: XKCD + version: 1.0.0 + x-apisguru-categories: + - media + x-logo: + url: https://api.apis.guru/v2/cache/logo/http_imgs.xkcd.com_static_terrible_small_logo.png + x-origin: + - format: openapi + url: https://raw.githubusercontent.com/APIs-guru/unofficial_openapi_specs/master/xkcd.com/1.0.0/openapi.yaml + version: "3.0" + x-providerName: xkcd.com + x-tags: + - humor + - comics + x-unofficialSpec: true +externalDocs: + url: https://xkcd.com/json.html +paths: + /info.0.json: + get: + description: | + Fetch current comic and metadata. + responses: + "200": + content: + "*/*": + schema: + $ref: "#/components/schemas/comic" + description: OK + "/{comicId}/info.0.json": + get: + description: | + Fetch comics and metadata by comic id. + parameters: + - in: path + name: comicId + required: true + schema: + type: number + responses: + "200": + content: + "*/*": + schema: + $ref: "#/components/schemas/comic" + description: OK +components: + schemas: + comic: + properties: + alt: + type: string + day: + type: string + img: + type: string + link: + type: string + month: + type: string + news: + type: string + num: + type: number + safe_title: + type: string + title: + type: string + transcript: + type: string + year: + type: string + type: object diff --git a/plugins/importer-openapi/tests/index.test.ts b/plugins/importer-openapi/tests/index.test.ts index efb29c9a..7b26c942 100644 --- a/plugins/importer-openapi/tests/index.test.ts +++ b/plugins/importer-openapi/tests/index.test.ts @@ -5,7 +5,13 @@ import { convertOpenApi } from "../src"; describe("importer-openapi", () => { const p = path.join(__dirname, "fixtures"); - const fixtures = fs.readdirSync(p); + const fixtures = fs.readdirSync(p).filter((fixture) => { + return fs.statSync(path.join(p, fixture)).isFile(); + }); + const realWorldFixturesPath = path.join(p, "real-world"); + const realWorldFixtures = fs + .readdirSync(realWorldFixturesPath) + .filter((fixture) => fixture.endsWith(".yaml")); test("Maps operation description to request description", async () => { const imported = await convertOpenApi( @@ -25,11 +31,188 @@ describe("importer-openapi", () => { expect(imported?.resources.httpRequests).toEqual([ expect.objectContaining({ - description: "Lijst van klanten", + description: expect.stringContaining("Lijst van klanten"), }), ]); }); + test("Imports requests directly from OpenAPI details", async () => { + const imported = await convertOpenApi( + JSON.stringify({ + openapi: "3.0.0", + info: { title: "Native Import Test", version: "1.0.0" }, + servers: [ + { url: "https://api.example.com/{version}", variables: { version: { default: "v1" } } }, + ], + tags: [{ name: "accounts", description: "Account operations" }], + paths: { + "/accounts/{accountId}/members": { + parameters: [ + { + name: "accountId", + in: "path", + required: true, + description: "Account identifier", + schema: { type: "string", example: "acct_123" }, + }, + ], + post: { + tags: ["accounts"], + summary: "Create member", + operationId: "createMember", + parameters: [ + { + name: "include", + in: "query", + description: "Related resources to include", + schema: { type: "string", enum: ["roles"] }, + }, + { + name: "X-Trace-Id", + in: "header", + schema: { type: "string", example: "trace-123" }, + }, + ], + security: [{ tokenAuth: [] }], + requestBody: { + description: "Member payload", + content: { + "application/json": { + schema: { $ref: "#/components/schemas/MemberInput" }, + }, + }, + }, + responses: { + "201": { description: "Created" }, + }, + }, + }, + }, + components: { + securitySchemes: { + tokenAuth: { type: "http", scheme: "bearer" }, + }, + schemas: { + MemberInput: { + type: "object", + required: ["email"], + properties: { + email: { type: "string", example: "me@example.com" }, + admin: { type: "boolean", default: false }, + primaryContact: { $ref: "#/components/schemas/Contact" }, + secondaryContact: { $ref: "#/components/schemas/Contact" }, + }, + }, + Contact: { + type: "object", + properties: { + name: { type: "string", example: "Taylor" }, + }, + }, + }, + }, + }), + ); + + expect(imported?.resources.folders).toEqual([ + expect.objectContaining({ name: "accounts", description: "Account operations" }), + ]); + expect(imported?.resources.httpRequests).toEqual([ + expect.objectContaining({ + name: "Create member", + method: "POST", + url: "https://api.example.com/v1/accounts/:accountId/members", + authenticationType: "bearer", + authentication: { token: "", prefix: "Bearer" }, + bodyType: "application/json", + body: { + text: JSON.stringify( + { + email: "me@example.com", + admin: false, + primaryContact: { name: "Taylor" }, + secondaryContact: { name: "Taylor" }, + }, + null, + 2, + ), + }, + headers: expect.arrayContaining([ + { enabled: false, name: "X-Trace-Id", value: "trace-123" }, + { enabled: true, name: "Content-Type", value: "application/json" }, + ]), + urlParameters: [ + { enabled: true, name: ":accountId", value: "acct_123" }, + { enabled: false, name: "include", value: "roles" }, + ], + description: expect.stringContaining("Operation ID: createMember"), + }), + ]); + expect(imported?.resources.httpRequests[0]?.description).toContain("Member payload"); + expect(imported?.resources.httpRequests[0]?.description).toContain("201: Created"); + }); + + test("Handles large schemas without the Postman converter path", async () => { + const paths: Record = {}; + for (let i = 0; i < 500; i++) { + paths[`/zones/{zoneId}/resources/${i}`] = { + get: { + tags: ["zones"], + summary: `Read resource ${i}`, + parameters: [ + { name: "zoneId", in: "path", required: true, schema: { type: "string" } }, + { name: "page", in: "query", schema: { type: "integer", default: 1 } }, + ], + responses: { + "200": { + description: "OK", + content: { + "application/json": { schema: { $ref: "#/components/schemas/Resource" } }, + }, + }, + }, + }, + }; + } + + const imported = await convertOpenApi( + JSON.stringify({ + openapi: "3.1.0", + info: { title: "Large API", version: "1.0.0" }, + servers: [{ url: "https://api.example.com/client/v4" }], + tags: [{ name: "zones" }], + paths, + components: { + schemas: { + Resource: { + type: "object", + properties: { + id: { type: "string" }, + name: { type: "string" }, + metadata: { $ref: "#/components/schemas/Metadata" }, + }, + }, + Metadata: { + type: "object", + properties: { + createdOn: { type: "string", format: "date-time" }, + tags: { type: "array", items: { type: "string" } }, + }, + }, + }, + }, + }), + ); + + expect(imported?.resources.httpRequests.length).toBe(500); + expect(imported?.resources.httpRequests[499]).toEqual( + expect.objectContaining({ + name: "Read resource 499", + url: "https://api.example.com/client/v4/zones/:zoneId/resources/499", + }), + ); + }); + test("Skips invalid file", async () => { const imported = await convertOpenApi("{}"); expect(imported).toBeUndefined(); @@ -46,7 +229,15 @@ describe("importer-openapi", () => { }), ]); expect(imported?.resources.httpRequests.length).toBe(19); - expect(imported?.resources.folders.length).toBe(7); + expect(imported?.resources.folders.map((f) => f.name)).toEqual(["pet", "store", "user"]); + }); + } + + for (const fixture of realWorldFixtures) { + test(`Snapshots real-world fixture ${fixture}`, async () => { + const contents = fs.readFileSync(path.join(realWorldFixturesPath, fixture), "utf-8"); + const imported = await convertOpenApi(contents); + expect(imported).toMatchSnapshot(); }); } }); diff --git a/plugins/importer-openapi/tests/legacy.test.ts b/plugins/importer-openapi/tests/legacy.test.ts new file mode 100644 index 00000000..f5ba615b --- /dev/null +++ b/plugins/importer-openapi/tests/legacy.test.ts @@ -0,0 +1,19 @@ +import * as fs from "node:fs"; +import * as path from "node:path"; +import { describe, expect, test } from "vite-plus/test"; +import { convertOpenApiWithPostman } from "../src/legacy"; + +describe("importer-openapi legacy converter", () => { + const realWorldFixturesPath = path.join(__dirname, "fixtures", "real-world"); + const realWorldFixtures = fs + .readdirSync(realWorldFixturesPath) + .filter((fixture) => fixture.endsWith(".yaml")); + + for (const fixture of realWorldFixtures) { + test(`Snapshots legacy Postman-converter output for ${fixture}`, async () => { + const contents = fs.readFileSync(path.join(realWorldFixturesPath, fixture), "utf-8"); + const imported = await convertOpenApiWithPostman(contents); + expect(imported).toMatchSnapshot(); + }); + } +});