Compare commits
15 Commits
feat/reque
...
feat/serve
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f5a654b27a | ||
|
|
c2c5cf25b1 | ||
|
|
f92c70e1ff | ||
|
|
f0adc5b2e4 | ||
|
|
fdcf55552a | ||
|
|
b0b7df0a3e | ||
|
|
01fd27f81a | ||
|
|
2d7fb8e23a | ||
|
|
600e0eea76 | ||
|
|
9e9907b4be | ||
|
|
2ba79a043b | ||
|
|
1be466efcd | ||
|
|
0c13ca7dca | ||
|
|
b6b6acd2fa | ||
|
|
9c00d6238e |
@@ -17,7 +17,7 @@
|
|||||||
"folders": [],
|
"folders": [],
|
||||||
"requests": [
|
"requests": [
|
||||||
{
|
{
|
||||||
"v": "2",
|
"v": "1",
|
||||||
"endpoint": "https://echo.hoppscotch.io",
|
"endpoint": "https://echo.hoppscotch.io",
|
||||||
"name": "RequestD",
|
"name": "RequestD",
|
||||||
"params": [],
|
"params": [],
|
||||||
@@ -40,8 +40,7 @@
|
|||||||
"body": {
|
"body": {
|
||||||
"contentType": null,
|
"contentType": null,
|
||||||
"body": null
|
"body": null
|
||||||
},
|
}
|
||||||
"requestVariables": []
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"auth": {
|
"auth": {
|
||||||
@@ -53,7 +52,7 @@
|
|||||||
],
|
],
|
||||||
"requests": [
|
"requests": [
|
||||||
{
|
{
|
||||||
"v": "2",
|
"v": "1",
|
||||||
"endpoint": "https://echo.hoppscotch.io",
|
"endpoint": "https://echo.hoppscotch.io",
|
||||||
"name": "RequestC",
|
"name": "RequestC",
|
||||||
"params": [],
|
"params": [],
|
||||||
@@ -68,8 +67,7 @@
|
|||||||
"body": {
|
"body": {
|
||||||
"contentType": null,
|
"contentType": null,
|
||||||
"body": null
|
"body": null
|
||||||
},
|
}
|
||||||
"requestVariables": []
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"auth": {
|
"auth": {
|
||||||
@@ -90,7 +88,7 @@
|
|||||||
],
|
],
|
||||||
"requests": [
|
"requests": [
|
||||||
{
|
{
|
||||||
"v": "2",
|
"v": "1",
|
||||||
"endpoint": "https://echo.hoppscotch.io",
|
"endpoint": "https://echo.hoppscotch.io",
|
||||||
"name": "RequestB",
|
"name": "RequestB",
|
||||||
"params": [],
|
"params": [],
|
||||||
@@ -106,7 +104,6 @@
|
|||||||
"contentType": null,
|
"contentType": null,
|
||||||
"body": null
|
"body": null
|
||||||
},
|
},
|
||||||
"requestVariables": [],
|
|
||||||
"id": "clpttpdq00003qp16kut6doqv"
|
"id": "clpttpdq00003qp16kut6doqv"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@@ -119,7 +116,7 @@
|
|||||||
],
|
],
|
||||||
"requests": [
|
"requests": [
|
||||||
{
|
{
|
||||||
"v": "2",
|
"v": "1",
|
||||||
"endpoint": "https://echo.hoppscotch.io",
|
"endpoint": "https://echo.hoppscotch.io",
|
||||||
"name": "RequestA",
|
"name": "RequestA",
|
||||||
"params": [],
|
"params": [],
|
||||||
@@ -135,7 +132,6 @@
|
|||||||
"contentType": null,
|
"contentType": null,
|
||||||
"body": null
|
"body": null
|
||||||
},
|
},
|
||||||
"requestVariables": [],
|
|
||||||
"id": "clpttpdq00003qp16kut6doqv"
|
"id": "clpttpdq00003qp16kut6doqv"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@@ -162,7 +158,7 @@
|
|||||||
"folders": [],
|
"folders": [],
|
||||||
"requests": [
|
"requests": [
|
||||||
{
|
{
|
||||||
"v": "2",
|
"v": "1",
|
||||||
"endpoint": "https://echo.hoppscotch.io",
|
"endpoint": "https://echo.hoppscotch.io",
|
||||||
"name": "RequestB",
|
"name": "RequestB",
|
||||||
"params": [],
|
"params": [],
|
||||||
@@ -178,7 +174,6 @@
|
|||||||
"contentType": null,
|
"contentType": null,
|
||||||
"body": null
|
"body": null
|
||||||
},
|
},
|
||||||
"requestVariables": [],
|
|
||||||
"id": "clpttpdq00003qp16kut6doqv"
|
"id": "clpttpdq00003qp16kut6doqv"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@@ -191,7 +186,7 @@
|
|||||||
],
|
],
|
||||||
"requests": [
|
"requests": [
|
||||||
{
|
{
|
||||||
"v": "2",
|
"v": "1",
|
||||||
"endpoint": "https://echo.hoppscotch.io",
|
"endpoint": "https://echo.hoppscotch.io",
|
||||||
"name": "RequestA",
|
"name": "RequestA",
|
||||||
"params": [],
|
"params": [],
|
||||||
@@ -207,7 +202,6 @@
|
|||||||
"contentType": null,
|
"contentType": null,
|
||||||
"body": null
|
"body": null
|
||||||
},
|
},
|
||||||
"requestVariables": [],
|
|
||||||
"id": "clpttpdq00003qp16kut6doqv"
|
"id": "clpttpdq00003qp16kut6doqv"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@@ -224,4 +218,4 @@
|
|||||||
"token": "BearerToken"
|
"token": "BearerToken"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -4,7 +4,7 @@
|
|||||||
"folders": [],
|
"folders": [],
|
||||||
"requests": [
|
"requests": [
|
||||||
{
|
{
|
||||||
"v": "2",
|
"v": "1",
|
||||||
"endpoint": "<<URL>>",
|
"endpoint": "<<URL>>",
|
||||||
"name": "test1",
|
"name": "test1",
|
||||||
"params": [],
|
"params": [],
|
||||||
@@ -16,8 +16,7 @@
|
|||||||
"body": {
|
"body": {
|
||||||
"contentType": "application/json",
|
"contentType": "application/json",
|
||||||
"body": "{\n \"<<BODY_KEY>>\":\"<<BODY_VALUE>>\"\n}"
|
"body": "{\n \"<<BODY_KEY>>\":\"<<BODY_VALUE>>\"\n}"
|
||||||
},
|
}
|
||||||
"requestVariables": []
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
"folders": [],
|
"folders": [],
|
||||||
"requests": [
|
"requests": [
|
||||||
{
|
{
|
||||||
"v": "2",
|
"v": "1",
|
||||||
"endpoint": "https://echo.hoppscotch.io/<<HEADERS_TYPE1>>",
|
"endpoint": "https://echo.hoppscotch.io/<<HEADERS_TYPE1>>",
|
||||||
"name": "",
|
"name": "",
|
||||||
"params": [],
|
"params": [],
|
||||||
@@ -23,11 +23,10 @@
|
|||||||
"body": {
|
"body": {
|
||||||
"contentType": "application/json",
|
"contentType": "application/json",
|
||||||
"body": "{\n\"test\": \"<<HEADERS_TYPE1>>\"\n}"
|
"body": "{\n\"test\": \"<<HEADERS_TYPE1>>\"\n}"
|
||||||
},
|
}
|
||||||
"requestVariables": [],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"v": "2",
|
"v": "1",
|
||||||
"endpoint": "https://echo.hoppscotch.dio/<<HEADERS_TYPE2>>",
|
"endpoint": "https://echo.hoppscotch.dio/<<HEADERS_TYPE2>>",
|
||||||
"name": "success",
|
"name": "success",
|
||||||
"params": [],
|
"params": [],
|
||||||
@@ -45,8 +44,7 @@
|
|||||||
"body": {
|
"body": {
|
||||||
"contentType": "application/json",
|
"contentType": "application/json",
|
||||||
"body": "{\n\"test\": \"<<HEADERS_TYPE2>>\"\n}"
|
"body": "{\n\"test\": \"<<HEADERS_TYPE2>>\"\n}"
|
||||||
},
|
}
|
||||||
"requestVariables": []
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,9 +2,9 @@
|
|||||||
{
|
{
|
||||||
"v": 1,
|
"v": 1,
|
||||||
"folders": [],
|
"folders": [],
|
||||||
"requests":
|
"requests":
|
||||||
{
|
{
|
||||||
"v": "2",
|
"v": "1",
|
||||||
"endpoint": "https://echo.hoppscotch.io/<<HEADERS_TYPE1>>",
|
"endpoint": "https://echo.hoppscotch.io/<<HEADERS_TYPE1>>",
|
||||||
"name": "fail",
|
"name": "fail",
|
||||||
"params": [],
|
"params": [],
|
||||||
@@ -22,11 +22,10 @@
|
|||||||
"body": {
|
"body": {
|
||||||
"contentType": "application/json",
|
"contentType": "application/json",
|
||||||
"body": "{\n\"test\": \"<<HEADERS_TYPE1>>\"\n}"
|
"body": "{\n\"test\": \"<<HEADERS_TYPE1>>\"\n}"
|
||||||
},
|
}
|
||||||
"requestVariables": [],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"v": "2",
|
"v": "1",
|
||||||
"endpoint": "https://echo.hoppscotch.io/<<HEADERS_TYPE2>>",
|
"endpoint": "https://echo.hoppscotch.io/<<HEADERS_TYPE2>>",
|
||||||
"name": "success",
|
"name": "success",
|
||||||
"params": [],
|
"params": [],
|
||||||
@@ -44,8 +43,7 @@
|
|||||||
"body": {
|
"body": {
|
||||||
"contentType": "application/json",
|
"contentType": "application/json",
|
||||||
"body": "{\n\"test\": \"<<HEADERS_TYPE2>>\"\n}"
|
"body": "{\n\"test\": \"<<HEADERS_TYPE2>>\"\n}"
|
||||||
},
|
}
|
||||||
"requestVariables": []
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,9 +2,9 @@
|
|||||||
{
|
{
|
||||||
"v": 1,
|
"v": 1,
|
||||||
"folders": [],
|
"folders": [],
|
||||||
"requests":
|
"requests":
|
||||||
{
|
{
|
||||||
"v": "2",
|
"v": "1",
|
||||||
"endpoint": "https://echo.hoppscotch.io/<<HEADERS_TYPE1>>",
|
"endpoint": "https://echo.hoppscotch.io/<<HEADERS_TYPE1>>",
|
||||||
"name": "fail",
|
"name": "fail",
|
||||||
"params": [],
|
"params": [],
|
||||||
@@ -22,8 +22,7 @@
|
|||||||
"body": {
|
"body": {
|
||||||
"contentType": "application/json",
|
"contentType": "application/json",
|
||||||
"body": "{\n\"test\": \"<<HEADERS_TYPE1>>\"\n}"
|
"body": "{\n\"test\": \"<<HEADERS_TYPE1>>\"\n}"
|
||||||
},
|
}
|
||||||
"requestVariables": []
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
"folders": [],
|
"folders": [],
|
||||||
"requests": [
|
"requests": [
|
||||||
{
|
{
|
||||||
"v": "2",
|
"v": "1",
|
||||||
"endpoint": "https://echo.hoppscotch.io/<<HEADERS_TYPE1>>",
|
"endpoint": "https://echo.hoppscotch.io/<<HEADERS_TYPE1>>",
|
||||||
"name": "",
|
"name": "",
|
||||||
"params": [],
|
"params": [],
|
||||||
@@ -23,11 +23,10 @@
|
|||||||
"body": {
|
"body": {
|
||||||
"contentType": "application/json",
|
"contentType": "application/json",
|
||||||
"body": "{\n\"test\": \"<<HEADERS_TYPE1>>\"\n}"
|
"body": "{\n\"test\": \"<<HEADERS_TYPE1>>\"\n}"
|
||||||
},
|
}
|
||||||
"requestVariables": []
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"v": "2",
|
"v": "1",
|
||||||
"endpoint": "https://echo.hoppscotch.io/<<HEADERS_TYPE2>>",
|
"endpoint": "https://echo.hoppscotch.io/<<HEADERS_TYPE2>>",
|
||||||
"name": "success",
|
"name": "success",
|
||||||
"params": [],
|
"params": [],
|
||||||
@@ -45,8 +44,7 @@
|
|||||||
"body": {
|
"body": {
|
||||||
"contentType": "application/json",
|
"contentType": "application/json",
|
||||||
"body": "{\n\"test\": \"<<HEADERS_TYPE2>>\"\n}"
|
"body": "{\n\"test\": \"<<HEADERS_TYPE2>>\"\n}"
|
||||||
},
|
}
|
||||||
"requestVariables": []
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
"folders": [],
|
"folders": [],
|
||||||
"requests": [
|
"requests": [
|
||||||
{
|
{
|
||||||
"v": "2",
|
"v": "1",
|
||||||
"auth": { "authType": "none", "authActive": true },
|
"auth": { "authType": "none", "authActive": true },
|
||||||
"body": { "body": null, "contentType": null },
|
"body": { "body": null, "contentType": null },
|
||||||
"name": "sample-req",
|
"name": "sample-req",
|
||||||
@@ -13,8 +13,7 @@
|
|||||||
"headers": [],
|
"headers": [],
|
||||||
"endpoint": "https://echo.hoppscotch.io",
|
"endpoint": "https://echo.hoppscotch.io",
|
||||||
"testScript": "pw.expect(pw.env.get(\"variable\")).toBe(\"value\")",
|
"testScript": "pw.expect(pw.env.get(\"variable\")).toBe(\"value\")",
|
||||||
"preRequestScript": "pw.env.set(\"variable\", \"value\");",
|
"preRequestScript": "pw.env.set(\"variable\", \"value\");"
|
||||||
"requestVariables": []
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"auth": { "authType": "inherit", "authActive": true },
|
"auth": { "authType": "inherit", "authActive": true },
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
"folders": [],
|
"folders": [],
|
||||||
"requests": [
|
"requests": [
|
||||||
{
|
{
|
||||||
"v": "2",
|
"v": "1",
|
||||||
"name": "test-request",
|
"name": "test-request",
|
||||||
"endpoint": "https://echo.hoppscotch.io",
|
"endpoint": "https://echo.hoppscotch.io",
|
||||||
"method": "POST",
|
"method": "POST",
|
||||||
@@ -19,8 +19,7 @@
|
|||||||
"body": "{\n \"firstName\": \"<<firstName>>\",\n \"lastName\": \"<<lastName>>\",\n \"greetText\": \"<<salutation>>, <<fullName>>\",\n \"fullName\": \"<<fullName>>\",\n \"id\": \"<<id>>\"\n}"
|
"body": "{\n \"firstName\": \"<<firstName>>\",\n \"lastName\": \"<<lastName>>\",\n \"greetText\": \"<<salutation>>, <<fullName>>\",\n \"fullName\": \"<<fullName>>\",\n \"id\": \"<<id>>\"\n}"
|
||||||
},
|
},
|
||||||
"preRequestScript": "",
|
"preRequestScript": "",
|
||||||
"testScript": "pw.test(\"Status code is 200\", ()=> {\n pw.expect(pw.response.status).toBe(200);\n});\n\npw.test(\"Successfully resolves environments recursively\", ()=> {\n pw.expect(pw.env.getResolve(\"recursiveVarX\")).toBe(\"Hello\")\n pw.expect(pw.env.getResolve(\"recursiveVarY\")).toBe(\"Hello\")\n pw.expect(pw.env.getResolve(\"salutation\")).toBe(\"Hello\")\n});\n\npw.test(\"Successfully resolves environments referenced in the request body\", () => {\n const expectedId = \"7\"\n const expectedFirstName = \"John\"\n const expectedLastName = \"Doe\"\n const expectedFullName = `${expectedFirstName} ${expectedLastName}`\n const expectedGreetText = `Hello, ${expectedFullName}`\n\n pw.expect(pw.env.getResolve(\"recursiveVarX\")).toBe(\"Hello\")\n pw.expect(pw.env.getResolve(\"recursiveVarY\")).toBe(\"Hello\")\n pw.expect(pw.env.getResolve(\"salutation\")).toBe(\"Hello\")\n\n const { id, firstName, lastName, fullName, greetText } = JSON.parse(pw.response.body.data)\n\n pw.expect(id).toBe(expectedId)\n pw.expect(expectedFirstName).toBe(firstName)\n pw.expect(expectedLastName).toBe(lastName)\n pw.expect(fullName).toBe(expectedFullName)\n pw.expect(greetText).toBe(expectedGreetText)\n});",
|
"testScript": "pw.test(\"Status code is 200\", ()=> {\n pw.expect(pw.response.status).toBe(200);\n});\n\npw.test(\"Successfully resolves environments recursively\", ()=> {\n pw.expect(pw.env.getResolve(\"recursiveVarX\")).toBe(\"Hello\")\n pw.expect(pw.env.getResolve(\"recursiveVarY\")).toBe(\"Hello\")\n pw.expect(pw.env.getResolve(\"salutation\")).toBe(\"Hello\")\n});\n\npw.test(\"Successfully resolves environments referenced in the request body\", () => {\n const expectedId = \"7\"\n const expectedFirstName = \"John\"\n const expectedLastName = \"Doe\"\n const expectedFullName = `${expectedFirstName} ${expectedLastName}`\n const expectedGreetText = `Hello, ${expectedFullName}`\n\n pw.expect(pw.env.getResolve(\"recursiveVarX\")).toBe(\"Hello\")\n pw.expect(pw.env.getResolve(\"recursiveVarY\")).toBe(\"Hello\")\n pw.expect(pw.env.getResolve(\"salutation\")).toBe(\"Hello\")\n\n const { id, firstName, lastName, fullName, greetText } = JSON.parse(pw.response.body.data)\n\n pw.expect(id).toBe(expectedId)\n pw.expect(expectedFirstName).toBe(firstName)\n pw.expect(expectedLastName).toBe(lastName)\n pw.expect(fullName).toBe(expectedFullName)\n pw.expect(greetText).toBe(expectedGreetText)\n});"
|
||||||
"requestVariables": []
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"auth": {
|
"auth": {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
"folders": [],
|
"folders": [],
|
||||||
"requests": [
|
"requests": [
|
||||||
{
|
{
|
||||||
"v": "2",
|
"v": "1",
|
||||||
"auth": { "authType": "none", "authActive": true },
|
"auth": { "authType": "none", "authActive": true },
|
||||||
"body": { "body": null, "contentType": null },
|
"body": { "body": null, "contentType": null },
|
||||||
"name": "test-secret-headers",
|
"name": "test-secret-headers",
|
||||||
@@ -17,13 +17,12 @@
|
|||||||
"active": true
|
"active": true
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"requestVariables": [],
|
|
||||||
"endpoint": "<<baseURL>>/headers",
|
"endpoint": "<<baseURL>>/headers",
|
||||||
"testScript": "pw.test(\"Successfully parses secret variable holding the header value\", () => {\n const secretHeaderValue = pw.env.get(\"secretHeaderValue\")\n pw.expect(secretHeaderValue).toBe(\"secret-header-value\")\n \n if (secretHeaderValue) {\n pw.expect(pw.response.body.headers[\"Secret-Header-Key\"]).toBe(secretHeaderValue)\n }\n\n pw.expect(pw.env.get(\"secretHeaderValueFromPreReqScript\")).toBe(\"secret-header-value\")\n})",
|
"testScript": "pw.test(\"Successfully parses secret variable holding the header value\", () => {\n const secretHeaderValue = pw.env.get(\"secretHeaderValue\")\n pw.expect(secretHeaderValue).toBe(\"secret-header-value\")\n \n if (secretHeaderValue) {\n pw.expect(pw.response.body.headers[\"Secret-Header-Key\"]).toBe(secretHeaderValue)\n }\n\n pw.expect(pw.env.get(\"secretHeaderValueFromPreReqScript\")).toBe(\"secret-header-value\")\n})",
|
||||||
"preRequestScript": "const secretHeaderValueFromPreReqScript = pw.env.get(\"secretHeaderValue\")\npw.env.set(\"secretHeaderValueFromPreReqScript\", secretHeaderValueFromPreReqScript)"
|
"preRequestScript": "const secretHeaderValueFromPreReqScript = pw.env.get(\"secretHeaderValue\")\npw.env.set(\"secretHeaderValueFromPreReqScript\", secretHeaderValueFromPreReqScript)"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"v": "2",
|
"v": "1",
|
||||||
"auth": { "authType": "none", "authActive": true },
|
"auth": { "authType": "none", "authActive": true },
|
||||||
"body": {
|
"body": {
|
||||||
"body": "{\n \"secretBodyKey\": \"<<secretBodyValue>>\"\n}",
|
"body": "{\n \"secretBodyKey\": \"<<secretBodyValue>>\"\n}",
|
||||||
@@ -33,13 +32,12 @@
|
|||||||
"method": "POST",
|
"method": "POST",
|
||||||
"params": [],
|
"params": [],
|
||||||
"headers": [],
|
"headers": [],
|
||||||
"requestVariables": [],
|
|
||||||
"endpoint": "<<baseURL>>/post",
|
"endpoint": "<<baseURL>>/post",
|
||||||
"testScript": "pw.test(\"Successfully parses secret variable holding the request body value\", () => {\n const secretBodyValue = pw.env.get(\"secretBodyValue\")\n pw.expect(secretBodyValue).toBe(\"secret-body-value\")\n \n if (secretBodyValue) {\n pw.expect(pw.response.body.json.secretBodyKey).toBe(secretBodyValue)\n }\n\n pw.expect(pw.env.get(\"secretBodyValueFromPreReqScript\")).toBe(\"secret-body-value\")\n})",
|
"testScript": "pw.test(\"Successfully parses secret variable holding the request body value\", () => {\n const secretBodyValue = pw.env.get(\"secretBodyValue\")\n pw.expect(secretBodyValue).toBe(\"secret-body-value\")\n \n if (secretBodyValue) {\n pw.expect(pw.response.body.json.secretBodyKey).toBe(secretBodyValue)\n }\n\n pw.expect(pw.env.get(\"secretBodyValueFromPreReqScript\")).toBe(\"secret-body-value\")\n})",
|
||||||
"preRequestScript": "const secretBodyValueFromPreReqScript = pw.env.get(\"secretBodyValue\")\npw.env.set(\"secretBodyValueFromPreReqScript\", secretBodyValueFromPreReqScript)"
|
"preRequestScript": "const secretBodyValueFromPreReqScript = pw.env.get(\"secretBodyValue\")\npw.env.set(\"secretBodyValueFromPreReqScript\", secretBodyValueFromPreReqScript)"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"v": "2",
|
"v": "1",
|
||||||
"auth": { "authType": "none", "authActive": true },
|
"auth": { "authType": "none", "authActive": true },
|
||||||
"body": { "body": null, "contentType": null },
|
"body": { "body": null, "contentType": null },
|
||||||
"name": "test-secret-query-params",
|
"name": "test-secret-query-params",
|
||||||
@@ -52,13 +50,12 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"headers": [],
|
"headers": [],
|
||||||
"requestVariables": [],
|
|
||||||
"endpoint": "<<baseURL>>/get",
|
"endpoint": "<<baseURL>>/get",
|
||||||
"testScript": "pw.test(\"Successfully parses secret variable holding the query param value\", () => {\n const secretQueryParamValue = pw.env.get(\"secretQueryParamValue\")\n pw.expect(secretQueryParamValue).toBe(\"secret-query-param-value\")\n \n if (secretQueryParamValue) {\n pw.expect(pw.response.body.args.secretQueryParamKey).toBe(secretQueryParamValue)\n }\n\n pw.expect(pw.env.get(\"secretQueryParamValueFromPreReqScript\")).toBe(\"secret-query-param-value\")\n})",
|
"testScript": "pw.test(\"Successfully parses secret variable holding the query param value\", () => {\n const secretQueryParamValue = pw.env.get(\"secretQueryParamValue\")\n pw.expect(secretQueryParamValue).toBe(\"secret-query-param-value\")\n \n if (secretQueryParamValue) {\n pw.expect(pw.response.body.args.secretQueryParamKey).toBe(secretQueryParamValue)\n }\n\n pw.expect(pw.env.get(\"secretQueryParamValueFromPreReqScript\")).toBe(\"secret-query-param-value\")\n})",
|
||||||
"preRequestScript": "const secretQueryParamValueFromPreReqScript = pw.env.get(\"secretQueryParamValue\")\npw.env.set(\"secretQueryParamValueFromPreReqScript\", secretQueryParamValueFromPreReqScript)"
|
"preRequestScript": "const secretQueryParamValueFromPreReqScript = pw.env.get(\"secretQueryParamValue\")\npw.env.set(\"secretQueryParamValueFromPreReqScript\", secretQueryParamValueFromPreReqScript)"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"v": "2",
|
"v": "1",
|
||||||
"auth": {
|
"auth": {
|
||||||
"authType": "basic",
|
"authType": "basic",
|
||||||
"password": "<<secretBasicAuthPassword>>",
|
"password": "<<secretBasicAuthPassword>>",
|
||||||
@@ -70,13 +67,12 @@
|
|||||||
"method": "GET",
|
"method": "GET",
|
||||||
"params": [],
|
"params": [],
|
||||||
"headers": [],
|
"headers": [],
|
||||||
"requestVariables": [],
|
|
||||||
"endpoint": "<<baseURL>>/basic-auth/<<secretBasicAuthUsername>>/<<secretBasicAuthPassword>>",
|
"endpoint": "<<baseURL>>/basic-auth/<<secretBasicAuthUsername>>/<<secretBasicAuthPassword>>",
|
||||||
"testScript": "pw.test(\"Successfully parses secret variables holding basic auth credentials\", () => {\n\tconst secretBasicAuthUsername = pw.env.get(\"secretBasicAuthUsername\")\n \tconst secretBasicAuthPassword = pw.env.get(\"secretBasicAuthPassword\")\n\n pw.expect(secretBasicAuthUsername).toBe(\"test-user\")\n pw.expect(secretBasicAuthPassword).toBe(\"test-pass\")\n\n if (secretBasicAuthUsername && secretBasicAuthPassword) {\n const { authenticated, user } = pw.response.body\n pw.expect(authenticated).toBe(true)\n pw.expect(user).toBe(secretBasicAuthUsername)\n }\n});",
|
"testScript": "pw.test(\"Successfully parses secret variables holding basic auth credentials\", () => {\n\tconst secretBasicAuthUsername = pw.env.get(\"secretBasicAuthUsername\")\n \tconst secretBasicAuthPassword = pw.env.get(\"secretBasicAuthPassword\")\n\n pw.expect(secretBasicAuthUsername).toBe(\"test-user\")\n pw.expect(secretBasicAuthPassword).toBe(\"test-pass\")\n\n if (secretBasicAuthUsername && secretBasicAuthPassword) {\n const { authenticated, user } = pw.response.body\n pw.expect(authenticated).toBe(true)\n pw.expect(user).toBe(secretBasicAuthUsername)\n }\n});",
|
||||||
"preRequestScript": ""
|
"preRequestScript": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"v": "2",
|
"v": "1",
|
||||||
"auth": {
|
"auth": {
|
||||||
"token": "<<secretBearerToken>>",
|
"token": "<<secretBearerToken>>",
|
||||||
"authType": "bearer",
|
"authType": "bearer",
|
||||||
@@ -89,20 +85,18 @@
|
|||||||
"method": "GET",
|
"method": "GET",
|
||||||
"params": [],
|
"params": [],
|
||||||
"headers": [],
|
"headers": [],
|
||||||
"requestVariables": [],
|
|
||||||
"endpoint": "<<baseURL>>/bearer",
|
"endpoint": "<<baseURL>>/bearer",
|
||||||
"testScript": "pw.test(\"Successfully parses secret variable holding the bearer token\", () => {\n const secretBearerToken = pw.env.get(\"secretBearerToken\")\n const preReqSecretBearerToken = pw.env.get(\"preReqSecretBearerToken\")\n\n pw.expect(secretBearerToken).toBe(\"test-token\")\n\n if (secretBearerToken) { \n pw.expect(pw.response.body.token).toBe(secretBearerToken)\n pw.expect(preReqSecretBearerToken).toBe(\"test-token\")\n }\n});",
|
"testScript": "pw.test(\"Successfully parses secret variable holding the bearer token\", () => {\n const secretBearerToken = pw.env.get(\"secretBearerToken\")\n const preReqSecretBearerToken = pw.env.get(\"preReqSecretBearerToken\")\n\n pw.expect(secretBearerToken).toBe(\"test-token\")\n\n if (secretBearerToken) { \n pw.expect(pw.response.body.token).toBe(secretBearerToken)\n pw.expect(preReqSecretBearerToken).toBe(\"test-token\")\n }\n});",
|
||||||
"preRequestScript": "const secretBearerToken = pw.env.get(\"secretBearerToken\")\npw.env.set(\"preReqSecretBearerToken\", secretBearerToken)"
|
"preRequestScript": "const secretBearerToken = pw.env.get(\"secretBearerToken\")\npw.env.set(\"preReqSecretBearerToken\", secretBearerToken)"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"v": "2",
|
"v": "1",
|
||||||
"auth": { "authType": "none", "authActive": true },
|
"auth": { "authType": "none", "authActive": true },
|
||||||
"body": { "body": null, "contentType": null },
|
"body": { "body": null, "contentType": null },
|
||||||
"name": "test-secret-fallback",
|
"name": "test-secret-fallback",
|
||||||
"method": "GET",
|
"method": "GET",
|
||||||
"params": [],
|
"params": [],
|
||||||
"headers": [],
|
"headers": [],
|
||||||
"requestVariables": [],
|
|
||||||
"endpoint": "<<baseURL>>",
|
"endpoint": "<<baseURL>>",
|
||||||
"testScript": "pw.test(\"Returns an empty string if the value for a secret environment variable is not found in the system environment\", () => {\n pw.expect(pw.env.get(\"nonExistentValueInSystemEnv\")).toBe(\"\")\n})",
|
"testScript": "pw.test(\"Returns an empty string if the value for a secret environment variable is not found in the system environment\", () => {\n pw.expect(pw.env.get(\"nonExistentValueInSystemEnv\")).toBe(\"\")\n})",
|
||||||
"preRequestScript": ""
|
"preRequestScript": ""
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
"folders": [],
|
"folders": [],
|
||||||
"requests": [
|
"requests": [
|
||||||
{
|
{
|
||||||
"v": "2",
|
"v": "1",
|
||||||
"auth": {
|
"auth": {
|
||||||
"authType": "none",
|
"authType": "none",
|
||||||
"authActive": true
|
"authActive": true
|
||||||
@@ -16,7 +16,6 @@
|
|||||||
"name": "test-secret-headers",
|
"name": "test-secret-headers",
|
||||||
"method": "GET",
|
"method": "GET",
|
||||||
"params": [],
|
"params": [],
|
||||||
"requestVariables": [],
|
|
||||||
"headers": [
|
"headers": [
|
||||||
{
|
{
|
||||||
"key": "Secret-Header-Key",
|
"key": "Secret-Header-Key",
|
||||||
@@ -29,7 +28,7 @@
|
|||||||
"preRequestScript": "pw.env.set(\"secretHeaderValue\", \"secret-header-value\")\n\nconst secretHeaderValueFromPreReqScript = pw.env.getResolve(\"secretHeaderValue\")\npw.env.set(\"secretHeaderValueFromPreReqScript\", secretHeaderValueFromPreReqScript)"
|
"preRequestScript": "pw.env.set(\"secretHeaderValue\", \"secret-header-value\")\n\nconst secretHeaderValueFromPreReqScript = pw.env.getResolve(\"secretHeaderValue\")\npw.env.set(\"secretHeaderValueFromPreReqScript\", secretHeaderValueFromPreReqScript)"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"v": "2",
|
"v": "1",
|
||||||
"auth": {
|
"auth": {
|
||||||
"authType": "none",
|
"authType": "none",
|
||||||
"authActive": true
|
"authActive": true
|
||||||
@@ -41,7 +40,6 @@
|
|||||||
"name": "test-secret-headers-overrides",
|
"name": "test-secret-headers-overrides",
|
||||||
"method": "GET",
|
"method": "GET",
|
||||||
"params": [],
|
"params": [],
|
||||||
"requestVariables": [],
|
|
||||||
"headers": [
|
"headers": [
|
||||||
{
|
{
|
||||||
"key": "Secret-Header-Key",
|
"key": "Secret-Header-Key",
|
||||||
@@ -54,7 +52,7 @@
|
|||||||
"preRequestScript": "pw.env.set(\"secretHeaderValue\", \"secret-header-value-overriden\")\n\nconst secretHeaderValueFromPreReqScript = pw.env.getResolve(\"secretHeaderValue\")\npw.env.set(\"secretHeaderValueFromPreReqScript\", secretHeaderValueFromPreReqScript)"
|
"preRequestScript": "pw.env.set(\"secretHeaderValue\", \"secret-header-value-overriden\")\n\nconst secretHeaderValueFromPreReqScript = pw.env.getResolve(\"secretHeaderValue\")\npw.env.set(\"secretHeaderValueFromPreReqScript\", secretHeaderValueFromPreReqScript)"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"v": "2",
|
"v": "1",
|
||||||
"auth": {
|
"auth": {
|
||||||
"authType": "none",
|
"authType": "none",
|
||||||
"authActive": true
|
"authActive": true
|
||||||
@@ -66,14 +64,13 @@
|
|||||||
"name": "test-secret-body",
|
"name": "test-secret-body",
|
||||||
"method": "POST",
|
"method": "POST",
|
||||||
"params": [],
|
"params": [],
|
||||||
"requestVariables": [],
|
|
||||||
"headers": [],
|
"headers": [],
|
||||||
"endpoint": "<<baseURL>>/post",
|
"endpoint": "<<baseURL>>/post",
|
||||||
"testScript": "pw.test(\"Successfully parses secret variable holding the request body value\", () => {\n const secretBodyValue = pw.env.get(\"secretBodyValue\")\n pw.expect(secretBodyValue).toBe(\"secret-body-value\")\n \n if (secretBodyValue) {\n pw.expect(pw.response.body.json.secretBodyKey).toBe(secretBodyValue)\n }\n\n pw.expect(pw.env.get(\"secretBodyValueFromPreReqScript\")).toBe(\"secret-body-value\")\n})",
|
"testScript": "pw.test(\"Successfully parses secret variable holding the request body value\", () => {\n const secretBodyValue = pw.env.get(\"secretBodyValue\")\n pw.expect(secretBodyValue).toBe(\"secret-body-value\")\n \n if (secretBodyValue) {\n pw.expect(pw.response.body.json.secretBodyKey).toBe(secretBodyValue)\n }\n\n pw.expect(pw.env.get(\"secretBodyValueFromPreReqScript\")).toBe(\"secret-body-value\")\n})",
|
||||||
"preRequestScript": "const secretBodyValue = pw.env.get(\"secretBodyValue\")\n\nif (!secretBodyValue) { \n pw.env.set(\"secretBodyValue\", \"secret-body-value\")\n}\n\nconst secretBodyValueFromPreReqScript = pw.env.get(\"secretBodyValue\")\npw.env.set(\"secretBodyValueFromPreReqScript\", secretBodyValueFromPreReqScript)"
|
"preRequestScript": "const secretBodyValue = pw.env.get(\"secretBodyValue\")\n\nif (!secretBodyValue) { \n pw.env.set(\"secretBodyValue\", \"secret-body-value\")\n}\n\nconst secretBodyValueFromPreReqScript = pw.env.get(\"secretBodyValue\")\npw.env.set(\"secretBodyValueFromPreReqScript\", secretBodyValueFromPreReqScript)"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"v": "2",
|
"v": "1",
|
||||||
"auth": {
|
"auth": {
|
||||||
"authType": "none",
|
"authType": "none",
|
||||||
"authActive": true
|
"authActive": true
|
||||||
@@ -91,14 +88,13 @@
|
|||||||
"active": true
|
"active": true
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"requestVariables": [],
|
|
||||||
"headers": [],
|
"headers": [],
|
||||||
"endpoint": "<<baseURL>>/get",
|
"endpoint": "<<baseURL>>/get",
|
||||||
"testScript": "pw.test(\"Successfully parses secret variable holding the query param value\", () => {\n const secretQueryParamValue = pw.env.get(\"secretQueryParamValue\")\n pw.expect(secretQueryParamValue).toBe(\"secret-query-param-value\")\n \n if (secretQueryParamValue) {\n pw.expect(pw.response.body.args.secretQueryParamKey).toBe(secretQueryParamValue)\n }\n\n pw.expect(pw.env.get(\"secretQueryParamValueFromPreReqScript\")).toBe(\"secret-query-param-value\")\n})",
|
"testScript": "pw.test(\"Successfully parses secret variable holding the query param value\", () => {\n const secretQueryParamValue = pw.env.get(\"secretQueryParamValue\")\n pw.expect(secretQueryParamValue).toBe(\"secret-query-param-value\")\n \n if (secretQueryParamValue) {\n pw.expect(pw.response.body.args.secretQueryParamKey).toBe(secretQueryParamValue)\n }\n\n pw.expect(pw.env.get(\"secretQueryParamValueFromPreReqScript\")).toBe(\"secret-query-param-value\")\n})",
|
||||||
"preRequestScript": "const secretQueryParamValue = pw.env.get(\"secretQueryParamValue\")\n\nif (!secretQueryParamValue) {\n pw.env.set(\"secretQueryParamValue\", \"secret-query-param-value\")\n}\n\nconst secretQueryParamValueFromPreReqScript = pw.env.get(\"secretQueryParamValue\")\npw.env.set(\"secretQueryParamValueFromPreReqScript\", secretQueryParamValueFromPreReqScript)"
|
"preRequestScript": "const secretQueryParamValue = pw.env.get(\"secretQueryParamValue\")\n\nif (!secretQueryParamValue) {\n pw.env.set(\"secretQueryParamValue\", \"secret-query-param-value\")\n}\n\nconst secretQueryParamValueFromPreReqScript = pw.env.get(\"secretQueryParamValue\")\npw.env.set(\"secretQueryParamValueFromPreReqScript\", secretQueryParamValueFromPreReqScript)"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"v": "2",
|
"v": "1",
|
||||||
"auth": {
|
"auth": {
|
||||||
"authType": "basic",
|
"authType": "basic",
|
||||||
"password": "<<secretBasicAuthPassword>>",
|
"password": "<<secretBasicAuthPassword>>",
|
||||||
@@ -112,14 +108,13 @@
|
|||||||
"name": "test-secret-basic-auth",
|
"name": "test-secret-basic-auth",
|
||||||
"method": "GET",
|
"method": "GET",
|
||||||
"params": [],
|
"params": [],
|
||||||
"requestVariables": [],
|
|
||||||
"headers": [],
|
"headers": [],
|
||||||
"endpoint": "<<baseURL>>/basic-auth/<<secretBasicAuthUsername>>/<<secretBasicAuthPassword>>",
|
"endpoint": "<<baseURL>>/basic-auth/<<secretBasicAuthUsername>>/<<secretBasicAuthPassword>>",
|
||||||
"testScript": "pw.test(\"Successfully parses secret variables holding basic auth credentials\", () => {\n\tconst secretBasicAuthUsername = pw.env.get(\"secretBasicAuthUsername\")\n \tconst secretBasicAuthPassword = pw.env.get(\"secretBasicAuthPassword\")\n\n pw.expect(secretBasicAuthUsername).toBe(\"test-user\")\n pw.expect(secretBasicAuthPassword).toBe(\"test-pass\")\n\n if (secretBasicAuthUsername && secretBasicAuthPassword) {\n const { authenticated, user } = pw.response.body\n pw.expect(authenticated).toBe(true)\n pw.expect(user).toBe(secretBasicAuthUsername)\n }\n});",
|
"testScript": "pw.test(\"Successfully parses secret variables holding basic auth credentials\", () => {\n\tconst secretBasicAuthUsername = pw.env.get(\"secretBasicAuthUsername\")\n \tconst secretBasicAuthPassword = pw.env.get(\"secretBasicAuthPassword\")\n\n pw.expect(secretBasicAuthUsername).toBe(\"test-user\")\n pw.expect(secretBasicAuthPassword).toBe(\"test-pass\")\n\n if (secretBasicAuthUsername && secretBasicAuthPassword) {\n const { authenticated, user } = pw.response.body\n pw.expect(authenticated).toBe(true)\n pw.expect(user).toBe(secretBasicAuthUsername)\n }\n});",
|
||||||
"preRequestScript": "let secretBasicAuthUsername = pw.env.get(\"secretBasicAuthUsername\")\n\nlet secretBasicAuthPassword = pw.env.get(\"secretBasicAuthPassword\")\n\nif (!secretBasicAuthUsername) {\n pw.env.set(\"secretBasicAuthUsername\", \"test-user\")\n}\n\nif (!secretBasicAuthPassword) {\n pw.env.set(\"secretBasicAuthPassword\", \"test-pass\")\n}"
|
"preRequestScript": "let secretBasicAuthUsername = pw.env.get(\"secretBasicAuthUsername\")\n\nlet secretBasicAuthPassword = pw.env.get(\"secretBasicAuthPassword\")\n\nif (!secretBasicAuthUsername) {\n pw.env.set(\"secretBasicAuthUsername\", \"test-user\")\n}\n\nif (!secretBasicAuthPassword) {\n pw.env.set(\"secretBasicAuthPassword\", \"test-pass\")\n}"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"v": "2",
|
"v": "1",
|
||||||
"auth": {
|
"auth": {
|
||||||
"token": "<<secretBearerToken>>",
|
"token": "<<secretBearerToken>>",
|
||||||
"authType": "bearer",
|
"authType": "bearer",
|
||||||
@@ -134,7 +129,6 @@
|
|||||||
"name": "test-secret-bearer-auth",
|
"name": "test-secret-bearer-auth",
|
||||||
"method": "GET",
|
"method": "GET",
|
||||||
"params": [],
|
"params": [],
|
||||||
"requestVariables": [],
|
|
||||||
"headers": [],
|
"headers": [],
|
||||||
"endpoint": "<<baseURL>>/bearer",
|
"endpoint": "<<baseURL>>/bearer",
|
||||||
"testScript": "pw.test(\"Successfully parses secret variable holding the bearer token\", () => {\n const secretBearerToken = pw.env.resolve(\"<<secretBearerToken>>\")\n const preReqSecretBearerToken = pw.env.resolve(\"<<preReqSecretBearerToken>>\")\n\n pw.expect(secretBearerToken).toBe(\"test-token\")\n\n if (secretBearerToken) { \n pw.expect(pw.response.body.token).toBe(secretBearerToken)\n pw.expect(preReqSecretBearerToken).toBe(\"test-token\")\n }\n});",
|
"testScript": "pw.test(\"Successfully parses secret variable holding the bearer token\", () => {\n const secretBearerToken = pw.env.resolve(\"<<secretBearerToken>>\")\n const preReqSecretBearerToken = pw.env.resolve(\"<<preReqSecretBearerToken>>\")\n\n pw.expect(secretBearerToken).toBe(\"test-token\")\n\n if (secretBearerToken) { \n pw.expect(pw.response.body.token).toBe(secretBearerToken)\n pw.expect(preReqSecretBearerToken).toBe(\"test-token\")\n }\n});",
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
"folders": [],
|
"folders": [],
|
||||||
"requests": [
|
"requests": [
|
||||||
{
|
{
|
||||||
"v": "2",
|
"v": "1",
|
||||||
"endpoint": "https://httpbin.org/post",
|
"endpoint": "https://httpbin.org/post",
|
||||||
"name": "req",
|
"name": "req",
|
||||||
"params": [],
|
"params": [],
|
||||||
@@ -22,8 +22,7 @@
|
|||||||
"body": {
|
"body": {
|
||||||
"contentType": "application/json",
|
"contentType": "application/json",
|
||||||
"body": "{\n \"key\": \"<<customBodyValue>>\"\n}"
|
"body": "{\n \"key\": \"<<customBodyValue>>\"\n}"
|
||||||
},
|
}
|
||||||
"requestVariables": []
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"auth": { "authType": "inherit", "authActive": false },
|
"auth": { "authType": "inherit", "authActive": false },
|
||||||
|
|||||||
@@ -563,22 +563,12 @@ details[open] summary .indicator {
|
|||||||
.env-highlight {
|
.env-highlight {
|
||||||
@apply text-accentContrast;
|
@apply text-accentContrast;
|
||||||
|
|
||||||
&.request-variable-highlight {
|
&.env-found {
|
||||||
@apply bg-amber-500;
|
@apply bg-accentDark;
|
||||||
@apply hover:bg-amber-600;
|
@apply hover:bg-accent;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.environment-variable-highlight {
|
&.env-not-found {
|
||||||
@apply bg-green-500;
|
|
||||||
@apply hover:bg-green-600;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.global-variable-highlight {
|
|
||||||
@apply bg-blue-500;
|
|
||||||
@apply hover:bg-blue-600;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.environment-not-found-highlight {
|
|
||||||
@apply bg-red-500;
|
@apply bg-red-500;
|
||||||
@apply hover:bg-red-600;
|
@apply hover:bg-red-600;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -239,7 +239,6 @@
|
|||||||
"pending_invites": "There are no pending invites for this team",
|
"pending_invites": "There are no pending invites for this team",
|
||||||
"profile": "Login to view your profile",
|
"profile": "Login to view your profile",
|
||||||
"protocols": "Protocols are empty",
|
"protocols": "Protocols are empty",
|
||||||
"request_variables": "This request does not have any request variables",
|
|
||||||
"schema": "Connect to a GraphQL endpoint to view schema",
|
"schema": "Connect to a GraphQL endpoint to view schema",
|
||||||
"secret_environments": "Secrets are not synced to Hoppscotch",
|
"secret_environments": "Secrets are not synced to Hoppscotch",
|
||||||
"shared_requests": "Shared requests are empty",
|
"shared_requests": "Shared requests are empty",
|
||||||
@@ -561,7 +560,6 @@
|
|||||||
"raw_body": "Raw Request Body",
|
"raw_body": "Raw Request Body",
|
||||||
"rename": "Rename Request",
|
"rename": "Rename Request",
|
||||||
"renamed": "Request renamed",
|
"renamed": "Request renamed",
|
||||||
"request_variables": "Request variables",
|
|
||||||
"run": "Run",
|
"run": "Run",
|
||||||
"save": "Save",
|
"save": "Save",
|
||||||
"save_as": "Save as",
|
"save_as": "Save as",
|
||||||
|
|||||||
@@ -32,13 +32,9 @@
|
|||||||
{{ tab.document.request.method }}
|
{{ tab.document.request.method }}
|
||||||
</span>
|
</span>
|
||||||
<div
|
<div
|
||||||
class="flex items-center flex-1 flex-shrink-0 min-w-0 truncate rounded-r"
|
class="flex items-center flex-1 flex-shrink-0 min-w-0 px-4 py-2 truncate rounded-r"
|
||||||
>
|
>
|
||||||
<SmartEnvInput
|
{{ tab.document.request.endpoint }}
|
||||||
v-model="tab.document.request.endpoint"
|
|
||||||
:readonly="true"
|
|
||||||
:envs="tabRequestVariables"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex mt-2 space-x-2 sm:mt-0">
|
<div class="flex mt-2 space-x-2 sm:mt-0">
|
||||||
@@ -73,7 +69,6 @@
|
|||||||
v-model="tab.document.request"
|
v-model="tab.document.request"
|
||||||
v-model:option-tab="selectedOptionTab"
|
v-model:option-tab="selectedOptionTab"
|
||||||
:properties="properties"
|
:properties="properties"
|
||||||
:envs="tabRequestVariables"
|
|
||||||
/>
|
/>
|
||||||
<HttpResponse
|
<HttpResponse
|
||||||
v-if="tab.document.response"
|
v-if="tab.document.response"
|
||||||
@@ -122,15 +117,6 @@ const sharedRequestURL = computed(() => {
|
|||||||
return `${shortcodeBaseURL}/r/${props.sharedRequestID}`
|
return `${shortcodeBaseURL}/r/${props.sharedRequestID}`
|
||||||
})
|
})
|
||||||
|
|
||||||
const tabRequestVariables = computed(() => {
|
|
||||||
return tab.value.document.request.requestVariables.map(({ key, value }) => ({
|
|
||||||
key,
|
|
||||||
value,
|
|
||||||
secret: false,
|
|
||||||
sourceEnv: "RequestVariable",
|
|
||||||
}))
|
|
||||||
})
|
|
||||||
|
|
||||||
const { subscribeToStream } = useStreamSubscriber()
|
const { subscribeToStream } = useStreamSubscriber()
|
||||||
|
|
||||||
const newSendRequest = async () => {
|
const newSendRequest = async () => {
|
||||||
|
|||||||
@@ -150,7 +150,7 @@
|
|||||||
<div v-else class="flex flex-1 border-b border-dividerLight">
|
<div v-else class="flex flex-1 border-b border-dividerLight">
|
||||||
<div class="w-2/3 border-r border-dividerLight">
|
<div class="w-2/3 border-r border-dividerLight">
|
||||||
<div v-if="auth.authType === 'basic'">
|
<div v-if="auth.authType === 'basic'">
|
||||||
<HttpAuthorizationBasic v-model="auth" :envs="envs" />
|
<HttpAuthorizationBasic v-model="auth" />
|
||||||
</div>
|
</div>
|
||||||
<div v-if="auth.authType === 'inherit'" class="p-4">
|
<div v-if="auth.authType === 'inherit'" class="p-4">
|
||||||
<span v-if="inheritedProperties?.auth">
|
<span v-if="inheritedProperties?.auth">
|
||||||
@@ -169,26 +169,17 @@
|
|||||||
</div>
|
</div>
|
||||||
<div v-if="auth.authType === 'bearer'">
|
<div v-if="auth.authType === 'bearer'">
|
||||||
<div class="flex flex-1 border-b border-dividerLight">
|
<div class="flex flex-1 border-b border-dividerLight">
|
||||||
<SmartEnvInput
|
<SmartEnvInput v-model="auth.token" placeholder="Token" />
|
||||||
v-model="auth.token"
|
|
||||||
placeholder="Token"
|
|
||||||
:auto-complete-env="true"
|
|
||||||
:envs="envs"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="auth.authType === 'oauth-2'">
|
<div v-if="auth.authType === 'oauth-2'">
|
||||||
<div class="flex flex-1 border-b border-dividerLight">
|
<div class="flex flex-1 border-b border-dividerLight">
|
||||||
<SmartEnvInput
|
<SmartEnvInput v-model="auth.token" placeholder="Token" />
|
||||||
v-model="auth.token"
|
|
||||||
placeholder="Token"
|
|
||||||
:envs="envs"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
<HttpOAuth2Authorization v-model="auth" :envs="envs" />
|
<HttpOAuth2Authorization v-model="auth" />
|
||||||
</div>
|
</div>
|
||||||
<div v-if="auth.authType === 'api-key'">
|
<div v-if="auth.authType === 'api-key'">
|
||||||
<HttpAuthorizationApiKey v-model="auth" :envs="envs" />
|
<HttpAuthorizationApiKey v-model="auth" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
@@ -224,7 +215,6 @@ import { useColorMode } from "@composables/theming"
|
|||||||
import { useVModel } from "@vueuse/core"
|
import { useVModel } from "@vueuse/core"
|
||||||
import { onMounted } from "vue"
|
import { onMounted } from "vue"
|
||||||
import { HoppInheritedProperty } from "~/helpers/types/HoppInheritedProperties"
|
import { HoppInheritedProperty } from "~/helpers/types/HoppInheritedProperties"
|
||||||
import { AggregateEnvironment } from "~/newstore/environments"
|
|
||||||
|
|
||||||
const t = useI18n()
|
const t = useI18n()
|
||||||
|
|
||||||
@@ -235,7 +225,6 @@ const props = defineProps<{
|
|||||||
isCollectionProperty?: boolean
|
isCollectionProperty?: boolean
|
||||||
isRootCollection?: boolean
|
isRootCollection?: boolean
|
||||||
inheritedProperties?: HoppInheritedProperty
|
inheritedProperties?: HoppInheritedProperty
|
||||||
envs?: AggregateEnvironment[]
|
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
|
|||||||
@@ -100,12 +100,10 @@
|
|||||||
<HttpBodyParameters
|
<HttpBodyParameters
|
||||||
v-if="body.contentType === 'multipart/form-data'"
|
v-if="body.contentType === 'multipart/form-data'"
|
||||||
v-model="body"
|
v-model="body"
|
||||||
:envs="envs"
|
|
||||||
/>
|
/>
|
||||||
<HttpURLEncodedParams
|
<HttpURLEncodedParams
|
||||||
v-else-if="body.contentType === 'application/x-www-form-urlencoded'"
|
v-else-if="body.contentType === 'application/x-www-form-urlencoded'"
|
||||||
v-model="body"
|
v-model="body"
|
||||||
:envs="envs"
|
|
||||||
/>
|
/>
|
||||||
<HttpRawBody v-else-if="body.contentType !== null" v-model="body" />
|
<HttpRawBody v-else-if="body.contentType !== null" v-model="body" />
|
||||||
<HoppSmartPlaceholder
|
<HoppSmartPlaceholder
|
||||||
@@ -143,7 +141,6 @@ import IconExternalLink from "~icons/lucide/external-link"
|
|||||||
import IconInfo from "~icons/lucide/info"
|
import IconInfo from "~icons/lucide/info"
|
||||||
import IconRefreshCW from "~icons/lucide/refresh-cw"
|
import IconRefreshCW from "~icons/lucide/refresh-cw"
|
||||||
import { RESTOptionTabs } from "./RequestOptions.vue"
|
import { RESTOptionTabs } from "./RequestOptions.vue"
|
||||||
import { AggregateEnvironment } from "~/newstore/environments"
|
|
||||||
|
|
||||||
const colorMode = useColorMode()
|
const colorMode = useColorMode()
|
||||||
const t = useI18n()
|
const t = useI18n()
|
||||||
@@ -151,7 +148,6 @@ const t = useI18n()
|
|||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
body: HoppRESTReqBody
|
body: HoppRESTReqBody
|
||||||
headers: HoppRESTHeader[]
|
headers: HoppRESTHeader[]
|
||||||
envs?: AggregateEnvironment[]
|
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
|
|||||||
@@ -65,8 +65,6 @@
|
|||||||
<SmartEnvInput
|
<SmartEnvInput
|
||||||
v-model="entry.key"
|
v-model="entry.key"
|
||||||
:placeholder="`${t('count.parameter', { count: index + 1 })}`"
|
:placeholder="`${t('count.parameter', { count: index + 1 })}`"
|
||||||
:auto-complete-env="true"
|
|
||||||
:envs="envs"
|
|
||||||
@change="
|
@change="
|
||||||
updateBodyParam(index, {
|
updateBodyParam(index, {
|
||||||
key: $event,
|
key: $event,
|
||||||
@@ -89,8 +87,6 @@
|
|||||||
<SmartEnvInput
|
<SmartEnvInput
|
||||||
v-model="entry.value"
|
v-model="entry.value"
|
||||||
:placeholder="`${t('count.value', { count: index + 1 })}`"
|
:placeholder="`${t('count.value', { count: index + 1 })}`"
|
||||||
:auto-complete-env="true"
|
|
||||||
:envs="envs"
|
|
||||||
@change="
|
@change="
|
||||||
updateBodyParam(index, {
|
updateBodyParam(index, {
|
||||||
key: entry.key,
|
key: entry.key,
|
||||||
@@ -194,13 +190,11 @@ import { useI18n } from "@composables/i18n"
|
|||||||
import { useToast } from "@composables/toast"
|
import { useToast } from "@composables/toast"
|
||||||
import { useColorMode } from "@composables/theming"
|
import { useColorMode } from "@composables/theming"
|
||||||
import { useVModel } from "@vueuse/core"
|
import { useVModel } from "@vueuse/core"
|
||||||
import { AggregateEnvironment } from "~/newstore/environments"
|
|
||||||
|
|
||||||
type Body = HoppRESTReqBody & { contentType: "multipart/form-data" }
|
type Body = HoppRESTReqBody & { contentType: "multipart/form-data" }
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
modelValue: Body
|
modelValue: Body
|
||||||
envs: AggregateEnvironment[]
|
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
|
|||||||
@@ -188,25 +188,11 @@ const copyCodeIcon = refAutoReset<typeof IconCopy | typeof IconCheck>(
|
|||||||
|
|
||||||
const requestCode = computed(() => {
|
const requestCode = computed(() => {
|
||||||
const aggregateEnvs = getAggregateEnvs()
|
const aggregateEnvs = getAggregateEnvs()
|
||||||
const requestVariables = request.value.requestVariables.map(
|
|
||||||
(requestVariable) => {
|
|
||||||
if (requestVariable.active)
|
|
||||||
return {
|
|
||||||
key: requestVariable.key,
|
|
||||||
value: requestVariable.value,
|
|
||||||
secret: false,
|
|
||||||
}
|
|
||||||
return {}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
const env: Environment = {
|
const env: Environment = {
|
||||||
v: 1,
|
v: 1,
|
||||||
id: "env",
|
id: "env",
|
||||||
name: "Env",
|
name: "Env",
|
||||||
variables: [
|
variables: aggregateEnvs,
|
||||||
...(requestVariables as Environment["variables"]),
|
|
||||||
...aggregateEnvs,
|
|
||||||
],
|
|
||||||
}
|
}
|
||||||
const effectiveRequest = getEffectiveRESTRequest(request.value, env)
|
const effectiveRequest = getEffectiveRESTRequest(request.value, env)
|
||||||
|
|
||||||
@@ -226,12 +212,6 @@ const requestCode = computed(() => {
|
|||||||
active: true,
|
active: true,
|
||||||
})),
|
})),
|
||||||
endpoint: effectiveRequest.effectiveFinalURL,
|
endpoint: effectiveRequest.effectiveFinalURL,
|
||||||
requestVariables: effectiveRequest.effectiveFinalRequestVariables.map(
|
|
||||||
(requestVariable) => ({
|
|
||||||
...requestVariable,
|
|
||||||
active: true,
|
|
||||||
})
|
|
||||||
),
|
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
@click="clearContent()"
|
@click="clearContent()"
|
||||||
/>
|
/>
|
||||||
<HoppButtonSecondary
|
<HoppButtonSecondary
|
||||||
v-if="bulkHeaders"
|
v-if="bulkMode"
|
||||||
v-tippy="{ theme: 'tooltip' }"
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
:title="t('state.linewrap')"
|
:title="t('state.linewrap')"
|
||||||
:class="{ '!text-accent': WRAP_LINES }"
|
:class="{ '!text-accent': WRAP_LINES }"
|
||||||
@@ -92,8 +92,6 @@
|
|||||||
:auto-complete-source="commonHeaders"
|
:auto-complete-source="commonHeaders"
|
||||||
:env-index="index"
|
:env-index="index"
|
||||||
:inspection-results="getInspectorResult(headerKeyResults, index)"
|
:inspection-results="getInspectorResult(headerKeyResults, index)"
|
||||||
:auto-complete-env="true"
|
|
||||||
:envs="envs"
|
|
||||||
@change="
|
@change="
|
||||||
updateHeader(index, {
|
updateHeader(index, {
|
||||||
id: header.id,
|
id: header.id,
|
||||||
@@ -110,8 +108,6 @@
|
|||||||
getInspectorResult(headerValueResults, index)
|
getInspectorResult(headerValueResults, index)
|
||||||
"
|
"
|
||||||
:env-index="index"
|
:env-index="index"
|
||||||
:auto-complete-env="true"
|
|
||||||
:envs="envs"
|
|
||||||
@change="
|
@change="
|
||||||
updateHeader(index, {
|
updateHeader(index, {
|
||||||
id: header.id,
|
id: header.id,
|
||||||
@@ -333,11 +329,7 @@ import {
|
|||||||
getComputedHeaders,
|
getComputedHeaders,
|
||||||
getComputedAuthHeaders,
|
getComputedAuthHeaders,
|
||||||
} from "~/helpers/utils/EffectiveURL"
|
} from "~/helpers/utils/EffectiveURL"
|
||||||
import {
|
import { aggregateEnvs$, getAggregateEnvs } from "~/newstore/environments"
|
||||||
AggregateEnvironment,
|
|
||||||
aggregateEnvs$,
|
|
||||||
getAggregateEnvs,
|
|
||||||
} from "~/newstore/environments"
|
|
||||||
import { useVModel } from "@vueuse/core"
|
import { useVModel } from "@vueuse/core"
|
||||||
import { useService } from "dioc/vue"
|
import { useService } from "dioc/vue"
|
||||||
import { InspectionService, InspectorResult } from "~/services/inspection"
|
import { InspectionService, InspectorResult } from "~/services/inspection"
|
||||||
@@ -367,7 +359,6 @@ const props = defineProps<{
|
|||||||
modelValue: HoppRESTRequest
|
modelValue: HoppRESTRequest
|
||||||
isCollectionProperty?: boolean
|
isCollectionProperty?: boolean
|
||||||
inheritedProperties?: HoppInheritedProperty
|
inheritedProperties?: HoppInheritedProperty
|
||||||
envs?: AggregateEnvironment[]
|
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
|
|||||||
@@ -6,52 +6,31 @@
|
|||||||
:styles="
|
:styles="
|
||||||
hasAccessTokenOrAuthURL ? 'pointer-events-none opacity-70' : ''
|
hasAccessTokenOrAuthURL ? 'pointer-events-none opacity-70' : ''
|
||||||
"
|
"
|
||||||
:auto-complete-env="true"
|
|
||||||
placeholder="OpenID Connect Discovery URL"
|
placeholder="OpenID Connect Discovery URL"
|
||||||
:envs="envs"
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-1 border-b border-dividerLight">
|
<div class="flex flex-1 border-b border-dividerLight">
|
||||||
<SmartEnvInput
|
<SmartEnvInput
|
||||||
v-model="authURL"
|
v-model="authURL"
|
||||||
placeholder="Authorization URL"
|
placeholder="Authorization URL"
|
||||||
:auto-complete-env="true"
|
|
||||||
:styles="hasOIDCURL ? 'pointer-events-none opacity-70' : ''"
|
:styles="hasOIDCURL ? 'pointer-events-none opacity-70' : ''"
|
||||||
:envs="envs"
|
></SmartEnvInput>
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-1 border-b border-dividerLight">
|
<div class="flex flex-1 border-b border-dividerLight">
|
||||||
<SmartEnvInput
|
<SmartEnvInput
|
||||||
v-model="accessTokenURL"
|
v-model="accessTokenURL"
|
||||||
placeholder="Access Token URL"
|
placeholder="Access Token URL"
|
||||||
:auto-complete-env="true"
|
|
||||||
:styles="hasOIDCURL ? 'pointer-events-none opacity-70' : ''"
|
:styles="hasOIDCURL ? 'pointer-events-none opacity-70' : ''"
|
||||||
:envs="envs"
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-1 border-b border-dividerLight">
|
<div class="flex flex-1 border-b border-dividerLight">
|
||||||
<SmartEnvInput
|
<SmartEnvInput v-model="clientID" placeholder="Client ID" />
|
||||||
v-model="clientID"
|
|
||||||
:auto-complete-env="true"
|
|
||||||
placeholder="Client ID"
|
|
||||||
:envs="envs"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-1 border-b border-dividerLight">
|
<div class="flex flex-1 border-b border-dividerLight">
|
||||||
<SmartEnvInput
|
<SmartEnvInput v-model="clientSecret" placeholder="Client Secret" />
|
||||||
v-model="clientSecret"
|
|
||||||
:auto-complete-env="true"
|
|
||||||
placeholder="Client Secret"
|
|
||||||
:envs="envs"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-1 border-b border-dividerLight">
|
<div class="flex flex-1 border-b border-dividerLight">
|
||||||
<SmartEnvInput
|
<SmartEnvInput v-model="scope" placeholder="Scope" />
|
||||||
v-model="scope"
|
|
||||||
:auto-complete-env="true"
|
|
||||||
placeholder="Scope"
|
|
||||||
:envs="envs"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="p-2">
|
<div class="p-2">
|
||||||
<HoppButtonSecondary
|
<HoppButtonSecondary
|
||||||
@@ -83,7 +62,6 @@ const toast = useToast()
|
|||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
modelValue: HoppRESTAuthOAuth2 | HoppGQLAuthOAuth2
|
modelValue: HoppRESTAuthOAuth2 | HoppGQLAuthOAuth2
|
||||||
envs?: AggregateEnvironment[]
|
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
|
|||||||
@@ -87,8 +87,6 @@
|
|||||||
:inspection-results="
|
:inspection-results="
|
||||||
getInspectorResult(parameterKeyResults, index)
|
getInspectorResult(parameterKeyResults, index)
|
||||||
"
|
"
|
||||||
:auto-complete-env="true"
|
|
||||||
:envs="envs"
|
|
||||||
@change="
|
@change="
|
||||||
updateParam(index, {
|
updateParam(index, {
|
||||||
id: param.id,
|
id: param.id,
|
||||||
@@ -104,8 +102,6 @@
|
|||||||
:inspection-results="
|
:inspection-results="
|
||||||
getInspectorResult(parameterValueResults, index)
|
getInspectorResult(parameterValueResults, index)
|
||||||
"
|
"
|
||||||
:auto-complete-env="true"
|
|
||||||
:envs="envs"
|
|
||||||
@change="
|
@change="
|
||||||
updateParam(index, {
|
updateParam(index, {
|
||||||
id: param.id,
|
id: param.id,
|
||||||
@@ -213,7 +209,6 @@ import { InspectionService, InspectorResult } from "~/services/inspection"
|
|||||||
import { RESTTabService } from "~/services/tab/rest"
|
import { RESTTabService } from "~/services/tab/rest"
|
||||||
import { useNestedSetting } from "~/composables/settings"
|
import { useNestedSetting } from "~/composables/settings"
|
||||||
import { toggleNestedSetting } from "~/newstore/settings"
|
import { toggleNestedSetting } from "~/newstore/settings"
|
||||||
import { AggregateEnvironment } from "~/newstore/environments"
|
|
||||||
|
|
||||||
const colorMode = useColorMode()
|
const colorMode = useColorMode()
|
||||||
|
|
||||||
@@ -247,7 +242,6 @@ useCodemirror(
|
|||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
modelValue: HoppRESTParam[]
|
modelValue: HoppRESTParam[]
|
||||||
envs?: AggregateEnvironment[]
|
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
|
|||||||
@@ -56,7 +56,6 @@
|
|||||||
v-model="tab.document.request.endpoint"
|
v-model="tab.document.request.endpoint"
|
||||||
:placeholder="`${t('request.url')}`"
|
:placeholder="`${t('request.url')}`"
|
||||||
:auto-complete-source="userHistories"
|
:auto-complete-source="userHistories"
|
||||||
:auto-complete-env="true"
|
|
||||||
:inspection-results="tabResults"
|
:inspection-results="tabResults"
|
||||||
@paste="onPasteUrl($event)"
|
@paste="onPasteUrl($event)"
|
||||||
@enter="newSendRequest"
|
@enter="newSendRequest"
|
||||||
|
|||||||
@@ -5,51 +5,48 @@
|
|||||||
render-inactive-tabs
|
render-inactive-tabs
|
||||||
>
|
>
|
||||||
<HoppSmartTab
|
<HoppSmartTab
|
||||||
v-if="properties?.includes('params') ?? true"
|
v-if="properties ? properties.includes('params') : true"
|
||||||
:id="'params'"
|
:id="'params'"
|
||||||
:label="`${t('tab.parameters')}`"
|
:label="`${t('tab.parameters')}`"
|
||||||
:info="`${newActiveParamsCount}`"
|
:info="`${newActiveParamsCount$}`"
|
||||||
>
|
>
|
||||||
<HttpParameters v-model="request.params" :envs="envs" />
|
<HttpParameters v-model="request.params" />
|
||||||
</HoppSmartTab>
|
</HoppSmartTab>
|
||||||
<HoppSmartTab
|
<HoppSmartTab
|
||||||
v-if="properties?.includes('bodyParams') ?? true"
|
v-if="properties ? properties.includes('bodyParams') : true"
|
||||||
:id="'bodyParams'"
|
:id="'bodyParams'"
|
||||||
:label="`${t('tab.body')}`"
|
:label="`${t('tab.body')}`"
|
||||||
>
|
>
|
||||||
<HttpBody
|
<HttpBody
|
||||||
v-model:headers="request.headers"
|
v-model:headers="request.headers"
|
||||||
v-model:body="request.body"
|
v-model:body="request.body"
|
||||||
:envs="envs"
|
|
||||||
@change-tab="changeOptionTab"
|
@change-tab="changeOptionTab"
|
||||||
/>
|
/>
|
||||||
</HoppSmartTab>
|
</HoppSmartTab>
|
||||||
<HoppSmartTab
|
<HoppSmartTab
|
||||||
v-if="properties?.includes('headers') ?? true"
|
v-if="properties ? properties.includes('headers') : true"
|
||||||
:id="'headers'"
|
:id="'headers'"
|
||||||
:label="`${t('tab.headers')}`"
|
:label="`${t('tab.headers')}`"
|
||||||
:info="`${newActiveHeadersCount}`"
|
:info="`${newActiveHeadersCount$}`"
|
||||||
>
|
>
|
||||||
<HttpHeaders
|
<HttpHeaders
|
||||||
v-model="request"
|
v-model="request"
|
||||||
:inherited-properties="inheritedProperties"
|
:inherited-properties="inheritedProperties"
|
||||||
:envs="envs"
|
|
||||||
@change-tab="changeOptionTab"
|
@change-tab="changeOptionTab"
|
||||||
/>
|
/>
|
||||||
</HoppSmartTab>
|
</HoppSmartTab>
|
||||||
<HoppSmartTab
|
<HoppSmartTab
|
||||||
v-if="properties?.includes('authorization') ?? true"
|
v-if="properties ? properties.includes('authorization') : true"
|
||||||
:id="'authorization'"
|
:id="'authorization'"
|
||||||
:label="`${t('tab.authorization')}`"
|
:label="`${t('tab.authorization')}`"
|
||||||
>
|
>
|
||||||
<HttpAuthorization
|
<HttpAuthorization
|
||||||
v-model="request.auth"
|
v-model="request.auth"
|
||||||
:inherited-properties="inheritedProperties"
|
:inherited-properties="inheritedProperties"
|
||||||
:envs="envs"
|
|
||||||
/>
|
/>
|
||||||
</HoppSmartTab>
|
</HoppSmartTab>
|
||||||
<HoppSmartTab
|
<HoppSmartTab
|
||||||
v-if="properties?.includes('preRequestScript') ?? true"
|
v-if="properties ? properties.includes('preRequestScript') : true"
|
||||||
:id="'preRequestScript'"
|
:id="'preRequestScript'"
|
||||||
:label="`${t('tab.pre_request_script')}`"
|
:label="`${t('tab.pre_request_script')}`"
|
||||||
:indicator="
|
:indicator="
|
||||||
@@ -61,7 +58,7 @@
|
|||||||
<HttpPreRequestScript v-model="request.preRequestScript" />
|
<HttpPreRequestScript v-model="request.preRequestScript" />
|
||||||
</HoppSmartTab>
|
</HoppSmartTab>
|
||||||
<HoppSmartTab
|
<HoppSmartTab
|
||||||
v-if="properties?.includes('tests') ?? true"
|
v-if="properties ? properties.includes('tests') : true"
|
||||||
:id="'tests'"
|
:id="'tests'"
|
||||||
:label="`${t('tab.tests')}`"
|
:label="`${t('tab.tests')}`"
|
||||||
:indicator="
|
:indicator="
|
||||||
@@ -70,15 +67,6 @@
|
|||||||
>
|
>
|
||||||
<HttpTests v-model="request.testScript" />
|
<HttpTests v-model="request.testScript" />
|
||||||
</HoppSmartTab>
|
</HoppSmartTab>
|
||||||
<HoppSmartTab
|
|
||||||
v-if="properties?.includes('requestVariables') ?? true"
|
|
||||||
:id="'requestVariables'"
|
|
||||||
:label="`${t('tab.variables')}`"
|
|
||||||
:info="`${newActiveRequestVariablesCount}`"
|
|
||||||
:align-last="true"
|
|
||||||
>
|
|
||||||
<HttpRequestVariables v-model="request.requestVariables" />
|
|
||||||
</HoppSmartTab>
|
|
||||||
</HoppSmartTabs>
|
</HoppSmartTabs>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -89,7 +77,6 @@ import { useVModel } from "@vueuse/core"
|
|||||||
import { computed } from "vue"
|
import { computed } from "vue"
|
||||||
import { defineActionHandler } from "~/helpers/actions"
|
import { defineActionHandler } from "~/helpers/actions"
|
||||||
import { HoppInheritedProperty } from "~/helpers/types/HoppInheritedProperties"
|
import { HoppInheritedProperty } from "~/helpers/types/HoppInheritedProperties"
|
||||||
import { AggregateEnvironment } from "~/newstore/environments"
|
|
||||||
|
|
||||||
const VALID_OPTION_TABS = [
|
const VALID_OPTION_TABS = [
|
||||||
"params",
|
"params",
|
||||||
@@ -98,7 +85,6 @@ const VALID_OPTION_TABS = [
|
|||||||
"authorization",
|
"authorization",
|
||||||
"preRequestScript",
|
"preRequestScript",
|
||||||
"tests",
|
"tests",
|
||||||
"requestVariables",
|
|
||||||
] as const
|
] as const
|
||||||
|
|
||||||
export type RESTOptionTabs = (typeof VALID_OPTION_TABS)[number]
|
export type RESTOptionTabs = (typeof VALID_OPTION_TABS)[number]
|
||||||
@@ -112,7 +98,6 @@ const props = withDefaults(
|
|||||||
optionTab: RESTOptionTabs
|
optionTab: RESTOptionTabs
|
||||||
properties?: string[]
|
properties?: string[]
|
||||||
inheritedProperties?: HoppInheritedProperty
|
inheritedProperties?: HoppInheritedProperty
|
||||||
envs?: AggregateEnvironment[]
|
|
||||||
}>(),
|
}>(),
|
||||||
{
|
{
|
||||||
optionTab: "params",
|
optionTab: "params",
|
||||||
@@ -131,27 +116,22 @@ const changeOptionTab = (e: RESTOptionTabs) => {
|
|||||||
selectedOptionTab.value = e
|
selectedOptionTab.value = e
|
||||||
}
|
}
|
||||||
|
|
||||||
const newActiveParamsCount = computed(() => {
|
const newActiveParamsCount$ = computed(() => {
|
||||||
const count = request.value.params.filter(
|
const e = request.value.params.filter(
|
||||||
(x) => x.active && (x.key || x.value)
|
(x) => x.active && (x.key !== "" || x.value !== "")
|
||||||
).length
|
).length
|
||||||
|
|
||||||
return count ? count : null
|
if (e === 0) return null
|
||||||
|
return `${e}`
|
||||||
})
|
})
|
||||||
|
|
||||||
const newActiveHeadersCount = computed(() => {
|
const newActiveHeadersCount$ = computed(() => {
|
||||||
const count = request.value.headers.filter(
|
const e = request.value.headers.filter(
|
||||||
(x) => x.active && (x.key || x.value)
|
(x) => x.active && (x.key !== "" || x.value !== "")
|
||||||
).length
|
).length
|
||||||
|
|
||||||
return count ? count : null
|
if (e === 0) return null
|
||||||
})
|
return `${e}`
|
||||||
|
|
||||||
const newActiveRequestVariablesCount = computed(() => {
|
|
||||||
const count = request.value.requestVariables.filter(
|
|
||||||
(x) => x.active && (x.key || x.value)
|
|
||||||
).length
|
|
||||||
return count ? count : null
|
|
||||||
})
|
})
|
||||||
|
|
||||||
defineActionHandler("request.open-tab", ({ tab }) => {
|
defineActionHandler("request.open-tab", ({ tab }) => {
|
||||||
|
|||||||
@@ -1,412 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="flex flex-1 flex-col">
|
|
||||||
<div
|
|
||||||
class="sticky top-upperMobileSecondaryStickyFold z-10 flex flex-shrink-0 items-center justify-between overflow-x-auto border-b border-dividerLight bg-primary pl-4 sm:top-upperSecondaryStickyFold"
|
|
||||||
>
|
|
||||||
<label class="truncate font-semibold text-secondaryLight">
|
|
||||||
{{ t("request.request_variables") }}
|
|
||||||
</label>
|
|
||||||
<div class="flex">
|
|
||||||
<HoppButtonSecondary
|
|
||||||
v-tippy="{ theme: 'tooltip' }"
|
|
||||||
to="https://docs.hoppscotch.io/documentation/features/rest-api-testing"
|
|
||||||
blank
|
|
||||||
:title="t('app.wiki')"
|
|
||||||
:icon="IconHelpCircle"
|
|
||||||
/>
|
|
||||||
<HoppButtonSecondary
|
|
||||||
v-tippy="{ theme: 'tooltip' }"
|
|
||||||
:title="t('action.clear_all')"
|
|
||||||
:icon="IconTrash2"
|
|
||||||
@click="clearContent()"
|
|
||||||
/>
|
|
||||||
<HoppButtonSecondary
|
|
||||||
v-if="bulkVariables"
|
|
||||||
v-tippy="{ theme: 'tooltip' }"
|
|
||||||
:title="t('state.linewrap')"
|
|
||||||
:class="{ '!text-accent': WRAP_LINES }"
|
|
||||||
:icon="IconWrapText"
|
|
||||||
@click.prevent="
|
|
||||||
toggleNestedSetting('WRAP_LINES', 'httpRequestVariables')
|
|
||||||
"
|
|
||||||
/>
|
|
||||||
<HoppButtonSecondary
|
|
||||||
v-tippy="{ theme: 'tooltip' }"
|
|
||||||
:title="t('state.bulk_mode')"
|
|
||||||
:icon="IconEdit"
|
|
||||||
:class="{ '!text-accent': bulkMode }"
|
|
||||||
@click="bulkMode = !bulkMode"
|
|
||||||
/>
|
|
||||||
<HoppButtonSecondary
|
|
||||||
v-tippy="{ theme: 'tooltip' }"
|
|
||||||
:title="t('add.new')"
|
|
||||||
:icon="IconPlus"
|
|
||||||
:disabled="bulkMode"
|
|
||||||
@click="addVariable"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div v-if="bulkMode" class="h-full relative">
|
|
||||||
<div ref="bulkEditor" class="absolute inset-0"></div>
|
|
||||||
</div>
|
|
||||||
<div v-else>
|
|
||||||
<draggable
|
|
||||||
v-model="workingRequestVariables"
|
|
||||||
item-key="id"
|
|
||||||
animation="250"
|
|
||||||
handle=".draggable-handle"
|
|
||||||
draggable=".draggable-content"
|
|
||||||
ghost-class="cursor-move"
|
|
||||||
chosen-class="bg-primaryLight"
|
|
||||||
drag-class="cursor-grabbing"
|
|
||||||
>
|
|
||||||
<template #item="{ element: variable, index }">
|
|
||||||
<div
|
|
||||||
class="draggable-content group flex divide-x divide-dividerLight border-b border-dividerLight"
|
|
||||||
>
|
|
||||||
<HoppButtonSecondary
|
|
||||||
v-tippy="{
|
|
||||||
theme: 'tooltip',
|
|
||||||
delay: [500, 20],
|
|
||||||
content:
|
|
||||||
index !== workingRequestVariables?.length - 1
|
|
||||||
? t('action.drag_to_reorder')
|
|
||||||
: null,
|
|
||||||
}"
|
|
||||||
:icon="IconGripVertical"
|
|
||||||
class="opacity-0"
|
|
||||||
:class="{
|
|
||||||
'draggable-handle cursor-grab group-hover:opacity-100':
|
|
||||||
index !== workingRequestVariables?.length - 1,
|
|
||||||
}"
|
|
||||||
tabindex="-1"
|
|
||||||
/>
|
|
||||||
<SmartEnvInput
|
|
||||||
v-model="variable.key"
|
|
||||||
:placeholder="`${t('count.variable', { count: index + 1 })}`"
|
|
||||||
@change="
|
|
||||||
updateVariable(index, {
|
|
||||||
id: variable.id,
|
|
||||||
key: $event,
|
|
||||||
value: variable.value,
|
|
||||||
active: variable.active,
|
|
||||||
})
|
|
||||||
"
|
|
||||||
/>
|
|
||||||
<SmartEnvInput
|
|
||||||
v-model="variable.value"
|
|
||||||
:placeholder="`${t('count.value', { count: index + 1 })}`"
|
|
||||||
@change="
|
|
||||||
updateVariable(index, {
|
|
||||||
id: variable.id,
|
|
||||||
key: variable.key,
|
|
||||||
value: $event,
|
|
||||||
active: variable.active,
|
|
||||||
})
|
|
||||||
"
|
|
||||||
/>
|
|
||||||
<HoppButtonSecondary
|
|
||||||
v-tippy="{ theme: 'tooltip' }"
|
|
||||||
:title="
|
|
||||||
variable.hasOwnProperty('active')
|
|
||||||
? variable.active
|
|
||||||
? t('action.turn_off')
|
|
||||||
: t('action.turn_on')
|
|
||||||
: t('action.turn_off')
|
|
||||||
"
|
|
||||||
:icon="
|
|
||||||
variable.hasOwnProperty('active')
|
|
||||||
? variable.active
|
|
||||||
? IconCheckCircle
|
|
||||||
: IconCircle
|
|
||||||
: IconCheckCircle
|
|
||||||
"
|
|
||||||
color="green"
|
|
||||||
@click="
|
|
||||||
updateVariable(index, {
|
|
||||||
id: variable.id,
|
|
||||||
key: variable.key,
|
|
||||||
value: variable.value,
|
|
||||||
active: variable.hasOwnProperty('active')
|
|
||||||
? !variable.active
|
|
||||||
: false,
|
|
||||||
})
|
|
||||||
"
|
|
||||||
/>
|
|
||||||
<HoppButtonSecondary
|
|
||||||
v-tippy="{ theme: 'tooltip' }"
|
|
||||||
:title="t('action.remove')"
|
|
||||||
:icon="IconTrash"
|
|
||||||
color="red"
|
|
||||||
@click="deleteVariable(index)"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</draggable>
|
|
||||||
<HoppSmartPlaceholder
|
|
||||||
v-if="workingRequestVariables.length === 0"
|
|
||||||
:src="`/images/states/${colorMode.value}/add_files.svg`"
|
|
||||||
:alt="`${t('empty.request_variables')}`"
|
|
||||||
:text="t('empty.request_variables')"
|
|
||||||
>
|
|
||||||
<template #body>
|
|
||||||
<HoppButtonSecondary
|
|
||||||
:label="`${t('add.new')}`"
|
|
||||||
:icon="IconPlus"
|
|
||||||
filled
|
|
||||||
@click="addVariable"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
</HoppSmartPlaceholder>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts" setup>
|
|
||||||
import { throwError } from "@functional/error"
|
|
||||||
import {
|
|
||||||
HoppRESTRequestVariable,
|
|
||||||
RawKeyValueEntry,
|
|
||||||
parseRawKeyValueEntriesE,
|
|
||||||
rawKeyValueEntriesToString,
|
|
||||||
} from "@hoppscotch/data"
|
|
||||||
import { useVModel } from "@vueuse/core"
|
|
||||||
import * as A from "fp-ts/Array"
|
|
||||||
import * as E from "fp-ts/Either"
|
|
||||||
import * as O from "fp-ts/Option"
|
|
||||||
import * as RA from "fp-ts/ReadonlyArray"
|
|
||||||
import { flow, pipe } from "fp-ts/function"
|
|
||||||
import { cloneDeep, isEqual } from "lodash-es"
|
|
||||||
import { reactive, ref, watch } from "vue"
|
|
||||||
import draggable from "vuedraggable-es"
|
|
||||||
|
|
||||||
import { useCodemirror } from "~/composables/codemirror"
|
|
||||||
import { useI18n } from "~/composables/i18n"
|
|
||||||
import { useNestedSetting } from "~/composables/settings"
|
|
||||||
import { useColorMode } from "~/composables/theming"
|
|
||||||
import { useToast } from "~/composables/toast"
|
|
||||||
import linter from "~/helpers/editor/linting/rawKeyValue"
|
|
||||||
import { objRemoveKey } from "~/helpers/functional/object"
|
|
||||||
import { toggleNestedSetting } from "~/newstore/settings"
|
|
||||||
import IconCheckCircle from "~icons/lucide/check-circle"
|
|
||||||
import IconCircle from "~icons/lucide/circle"
|
|
||||||
import IconEdit from "~icons/lucide/edit"
|
|
||||||
import IconGripVertical from "~icons/lucide/grip-vertical"
|
|
||||||
import IconHelpCircle from "~icons/lucide/help-circle"
|
|
||||||
import IconPlus from "~icons/lucide/plus"
|
|
||||||
import IconTrash from "~icons/lucide/trash"
|
|
||||||
import IconTrash2 from "~icons/lucide/trash-2"
|
|
||||||
import IconWrapText from "~icons/lucide/wrap-text"
|
|
||||||
|
|
||||||
const colorMode = useColorMode()
|
|
||||||
|
|
||||||
const t = useI18n()
|
|
||||||
const toast = useToast()
|
|
||||||
|
|
||||||
const bulkMode = ref(false)
|
|
||||||
const bulkEditor = ref<any | null>(null)
|
|
||||||
const bulkVariables = ref("")
|
|
||||||
|
|
||||||
const WRAP_LINES = useNestedSetting("WRAP_LINES", "httpRequestVariables")
|
|
||||||
|
|
||||||
const deletionToast = ref<{ goAway: (delay: number) => void } | null>(null)
|
|
||||||
|
|
||||||
const props = defineProps<{
|
|
||||||
modelValue: HoppRESTRequestVariable[]
|
|
||||||
}>()
|
|
||||||
|
|
||||||
const emit = defineEmits<{
|
|
||||||
(e: "update:modelValue", value: Array<HoppRESTRequestVariable>): void
|
|
||||||
}>()
|
|
||||||
|
|
||||||
// The functional requestVariable list (the requestVariable actually applied to the session)
|
|
||||||
const requestVariables = useVModel(props, "modelValue", emit)
|
|
||||||
|
|
||||||
useCodemirror(
|
|
||||||
bulkEditor,
|
|
||||||
bulkVariables,
|
|
||||||
reactive({
|
|
||||||
extendedEditorConfig: {
|
|
||||||
mode: "text/x-yaml",
|
|
||||||
placeholder: `${t("state.bulk_mode_placeholder")}`,
|
|
||||||
lineWrapping: WRAP_LINES,
|
|
||||||
},
|
|
||||||
linter,
|
|
||||||
completer: null,
|
|
||||||
environmentHighlights: true,
|
|
||||||
})
|
|
||||||
)
|
|
||||||
|
|
||||||
const idTicker = ref(0)
|
|
||||||
|
|
||||||
const workingRequestVariables = ref<
|
|
||||||
Array<HoppRESTRequestVariable & { id: number }>
|
|
||||||
>([
|
|
||||||
{
|
|
||||||
id: idTicker.value++,
|
|
||||||
key: "",
|
|
||||||
value: "",
|
|
||||||
active: true,
|
|
||||||
},
|
|
||||||
])
|
|
||||||
|
|
||||||
// Sync logic between params and working/bulk params
|
|
||||||
watch(
|
|
||||||
requestVariables,
|
|
||||||
(newRequestVariableList) => {
|
|
||||||
// Sync should overwrite working params
|
|
||||||
const filteredWorkingRequestVariables: HoppRESTRequestVariable[] = pipe(
|
|
||||||
workingRequestVariables.value,
|
|
||||||
A.filterMap(
|
|
||||||
flow(
|
|
||||||
O.fromPredicate((e) => e.key !== ""),
|
|
||||||
O.map(objRemoveKey("id"))
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
const filteredBulkRequestVariables = pipe(
|
|
||||||
parseRawKeyValueEntriesE(bulkVariables.value),
|
|
||||||
E.map(
|
|
||||||
flow(
|
|
||||||
RA.filter((e) => e.key !== ""),
|
|
||||||
RA.toArray
|
|
||||||
)
|
|
||||||
),
|
|
||||||
E.getOrElse(() => [] as RawKeyValueEntry[])
|
|
||||||
)
|
|
||||||
|
|
||||||
if (!isEqual(newRequestVariableList, filteredWorkingRequestVariables)) {
|
|
||||||
workingRequestVariables.value = pipe(
|
|
||||||
newRequestVariableList,
|
|
||||||
A.map((x) => ({ id: idTicker.value++, ...x }))
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isEqual(newRequestVariableList, filteredBulkRequestVariables)) {
|
|
||||||
bulkVariables.value = rawKeyValueEntriesToString(newRequestVariableList)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{ immediate: true }
|
|
||||||
)
|
|
||||||
|
|
||||||
watch(workingRequestVariables, (newWorkingRequestVariables) => {
|
|
||||||
const fixedRequestVariables = pipe(
|
|
||||||
newWorkingRequestVariables,
|
|
||||||
A.filterMap(
|
|
||||||
flow(
|
|
||||||
O.fromPredicate((e) => e.key !== ""),
|
|
||||||
O.map(objRemoveKey("id"))
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
if (!isEqual(requestVariables.value, fixedRequestVariables)) {
|
|
||||||
requestVariables.value = cloneDeep(fixedRequestVariables)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
watch(bulkVariables, (newBulkParams) => {
|
|
||||||
const filteredBulkRequestVariables = pipe(
|
|
||||||
parseRawKeyValueEntriesE(newBulkParams),
|
|
||||||
E.map(
|
|
||||||
flow(
|
|
||||||
RA.filter((e) => e.key !== ""),
|
|
||||||
RA.toArray
|
|
||||||
)
|
|
||||||
),
|
|
||||||
E.getOrElse(() => [] as RawKeyValueEntry[])
|
|
||||||
)
|
|
||||||
|
|
||||||
if (!isEqual(requestVariables.value, filteredBulkRequestVariables)) {
|
|
||||||
requestVariables.value = filteredBulkRequestVariables
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// Rule: Working Request variable always have last element is always an empty param
|
|
||||||
watch(workingRequestVariables, (variableList) => {
|
|
||||||
if (
|
|
||||||
variableList.length > 0 &&
|
|
||||||
variableList[variableList.length - 1].key !== ""
|
|
||||||
) {
|
|
||||||
workingRequestVariables.value.push({
|
|
||||||
id: idTicker.value++,
|
|
||||||
key: "",
|
|
||||||
value: "",
|
|
||||||
active: true,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const addVariable = () => {
|
|
||||||
workingRequestVariables.value.push({
|
|
||||||
id: idTicker.value++,
|
|
||||||
key: "",
|
|
||||||
value: "",
|
|
||||||
active: true,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const updateVariable = (index: number, variable: any & { id: number }) => {
|
|
||||||
workingRequestVariables.value = workingRequestVariables.value.map((h, i) =>
|
|
||||||
i === index ? variable : h
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
const deleteVariable = (index: number) => {
|
|
||||||
const requestVariablesBeforeDeletion = cloneDeep(
|
|
||||||
workingRequestVariables.value
|
|
||||||
)
|
|
||||||
|
|
||||||
if (
|
|
||||||
!(
|
|
||||||
requestVariablesBeforeDeletion.length > 0 &&
|
|
||||||
index === requestVariablesBeforeDeletion.length - 1
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
if (deletionToast.value) {
|
|
||||||
deletionToast.value.goAway(0)
|
|
||||||
deletionToast.value = null
|
|
||||||
}
|
|
||||||
|
|
||||||
deletionToast.value = toast.success(`${t("state.deleted")}`, {
|
|
||||||
action: [
|
|
||||||
{
|
|
||||||
text: `${t("action.undo")}`,
|
|
||||||
onClick: (_, toastObject) => {
|
|
||||||
workingRequestVariables.value = requestVariablesBeforeDeletion
|
|
||||||
toastObject.goAway(0)
|
|
||||||
deletionToast.value = null
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
|
|
||||||
onComplete: () => {
|
|
||||||
deletionToast.value = null
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
workingRequestVariables.value = pipe(
|
|
||||||
workingRequestVariables.value,
|
|
||||||
A.deleteAt(index),
|
|
||||||
O.getOrElseW(() =>
|
|
||||||
throwError("Working Request Variable Deletion Out of Bounds")
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
const clearContent = () => {
|
|
||||||
// set params list to the initial state
|
|
||||||
workingRequestVariables.value = [
|
|
||||||
{
|
|
||||||
id: idTicker.value++,
|
|
||||||
key: "",
|
|
||||||
value: "",
|
|
||||||
active: true,
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
bulkVariables.value = ""
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
@@ -21,7 +21,7 @@
|
|||||||
@click="clearContent()"
|
@click="clearContent()"
|
||||||
/>
|
/>
|
||||||
<HoppButtonSecondary
|
<HoppButtonSecondary
|
||||||
v-if="bulkUrlEncodedParams"
|
v-if="bulkMode"
|
||||||
v-tippy="{ theme: 'tooltip' }"
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
:title="t('state.linewrap')"
|
:title="t('state.linewrap')"
|
||||||
:class="{ '!text-accent': WRAP_LINES }"
|
:class="{ '!text-accent': WRAP_LINES }"
|
||||||
@@ -84,8 +84,6 @@
|
|||||||
<SmartEnvInput
|
<SmartEnvInput
|
||||||
v-model="param.key"
|
v-model="param.key"
|
||||||
:placeholder="`${t('count.parameter', { count: index + 1 })}`"
|
:placeholder="`${t('count.parameter', { count: index + 1 })}`"
|
||||||
:auto-complete-env="true"
|
|
||||||
:envs="envs"
|
|
||||||
@change="
|
@change="
|
||||||
updateUrlEncodedParam(index, {
|
updateUrlEncodedParam(index, {
|
||||||
id: param.id,
|
id: param.id,
|
||||||
@@ -98,8 +96,6 @@
|
|||||||
<SmartEnvInput
|
<SmartEnvInput
|
||||||
v-model="param.value"
|
v-model="param.value"
|
||||||
:placeholder="`${t('count.value', { count: index + 1 })}`"
|
:placeholder="`${t('count.value', { count: index + 1 })}`"
|
||||||
:auto-complete-env="true"
|
|
||||||
:envs="envs"
|
|
||||||
@change="
|
@change="
|
||||||
updateUrlEncodedParam(index, {
|
updateUrlEncodedParam(index, {
|
||||||
id: param.id,
|
id: param.id,
|
||||||
@@ -204,7 +200,6 @@ import { throwError } from "~/helpers/functional/error"
|
|||||||
import { useVModel } from "@vueuse/core"
|
import { useVModel } from "@vueuse/core"
|
||||||
import { useNestedSetting } from "~/composables/settings"
|
import { useNestedSetting } from "~/composables/settings"
|
||||||
import { toggleNestedSetting } from "~/newstore/settings"
|
import { toggleNestedSetting } from "~/newstore/settings"
|
||||||
import { AggregateEnvironment } from "~/newstore/environments"
|
|
||||||
|
|
||||||
type Body = HoppRESTReqBody & {
|
type Body = HoppRESTReqBody & {
|
||||||
contentType: "application/x-www-form-urlencoded"
|
contentType: "application/x-www-form-urlencoded"
|
||||||
@@ -212,7 +207,6 @@ type Body = HoppRESTReqBody & {
|
|||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
modelValue: Body
|
modelValue: Body
|
||||||
envs: AggregateEnvironment[]
|
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
|
|||||||
@@ -1,19 +1,9 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="flex flex-1 border-b border-dividerLight">
|
<div class="flex flex-1 border-b border-dividerLight">
|
||||||
<SmartEnvInput
|
<SmartEnvInput v-model="auth.key" placeholder="Key" />
|
||||||
v-model="auth.key"
|
|
||||||
:auto-complete-env="true"
|
|
||||||
placeholder="Key"
|
|
||||||
:envs="envs"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-1 border-b border-dividerLight">
|
<div class="flex flex-1 border-b border-dividerLight">
|
||||||
<SmartEnvInput
|
<SmartEnvInput v-model="auth.value" placeholder="Value" />
|
||||||
v-model="auth.value"
|
|
||||||
:auto-complete-env="true"
|
|
||||||
placeholder="Value"
|
|
||||||
:envs="envs"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="flex items-center border-b border-dividerLight">
|
<div class="flex items-center border-b border-dividerLight">
|
||||||
<span class="flex items-center">
|
<span class="flex items-center">
|
||||||
@@ -75,13 +65,11 @@ import { useI18n } from "@composables/i18n"
|
|||||||
import { HoppRESTAuthAPIKey } from "@hoppscotch/data"
|
import { HoppRESTAuthAPIKey } from "@hoppscotch/data"
|
||||||
import { useVModel } from "@vueuse/core"
|
import { useVModel } from "@vueuse/core"
|
||||||
import { ref } from "vue"
|
import { ref } from "vue"
|
||||||
import { AggregateEnvironment } from "~/newstore/environments"
|
|
||||||
|
|
||||||
const t = useI18n()
|
const t = useI18n()
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
modelValue: HoppRESTAuthAPIKey
|
modelValue: HoppRESTAuthAPIKey
|
||||||
envs?: AggregateEnvironment[]
|
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
|
|||||||
@@ -3,16 +3,12 @@
|
|||||||
<SmartEnvInput
|
<SmartEnvInput
|
||||||
v-model="auth.username"
|
v-model="auth.username"
|
||||||
:placeholder="t('authorization.username')"
|
:placeholder="t('authorization.username')"
|
||||||
:auto-complete-env="true"
|
|
||||||
:envs="envs"
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-1 border-b border-dividerLight">
|
<div class="flex flex-1 border-b border-dividerLight">
|
||||||
<SmartEnvInput
|
<SmartEnvInput
|
||||||
v-model="auth.password"
|
v-model="auth.password"
|
||||||
:placeholder="t('authorization.password')"
|
:placeholder="t('authorization.password')"
|
||||||
:auto-complete-env="true"
|
|
||||||
:envs="envs"
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -21,13 +17,11 @@
|
|||||||
import { useI18n } from "@composables/i18n"
|
import { useI18n } from "@composables/i18n"
|
||||||
import { HoppRESTAuthBasic } from "@hoppscotch/data"
|
import { HoppRESTAuthBasic } from "@hoppscotch/data"
|
||||||
import { useVModel } from "@vueuse/core"
|
import { useVModel } from "@vueuse/core"
|
||||||
import { AggregateEnvironment } from "~/newstore/environments"
|
|
||||||
|
|
||||||
const t = useI18n()
|
const t = useI18n()
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
modelValue: HoppRESTAuthBasic
|
modelValue: HoppRESTAuthBasic
|
||||||
envs?: AggregateEnvironment[]
|
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
|
|||||||
@@ -21,24 +21,28 @@
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-col space-y-2 py-4">
|
<div class="flex flex-col space-y-2 py-4">
|
||||||
<HoppSmartItem
|
<span>
|
||||||
to="https://chrome.google.com/webstore/detail/hoppscotch-browser-extens/amknoiejhlmhancpahfcfcfhllgkpbld"
|
<HoppSmartItem
|
||||||
blank
|
to="https://chrome.google.com/webstore/detail/hoppscotch-browser-extens/amknoiejhlmhancpahfcfcfhllgkpbld"
|
||||||
:icon="IconChrome"
|
blank
|
||||||
label="Chrome"
|
:icon="IconChrome"
|
||||||
:info-icon="hasChromeExtInstalled ? IconCheckCircle : null"
|
label="Chrome"
|
||||||
:active-info-icon="hasChromeExtInstalled"
|
:info-icon="hasChromeExtInstalled ? IconCheckCircle : null"
|
||||||
outline
|
:active-info-icon="hasChromeExtInstalled"
|
||||||
/>
|
outline
|
||||||
<HoppSmartItem
|
/>
|
||||||
to="https://addons.mozilla.org/en-US/firefox/addon/hoppscotch"
|
</span>
|
||||||
blank
|
<span>
|
||||||
:icon="IconFirefox"
|
<HoppSmartItem
|
||||||
label="Firefox"
|
to="https://addons.mozilla.org/en-US/firefox/addon/hoppscotch"
|
||||||
:info-icon="hasFirefoxExtInstalled ? IconCheckCircle : null"
|
blank
|
||||||
:active-info-icon="hasFirefoxExtInstalled"
|
:icon="IconFirefox"
|
||||||
outline
|
label="Firefox"
|
||||||
/>
|
:info-icon="hasFirefoxExtInstalled ? IconCheckCircle : null"
|
||||||
|
:active-info-icon="hasFirefoxExtInstalled"
|
||||||
|
outline
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="space-y-4 py-4">
|
<div class="space-y-4 py-4">
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
|
|||||||
@@ -290,12 +290,7 @@ const widgets: Widget[] = [
|
|||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
type EmbedTabs =
|
type EmbedTabs = "params" | "bodyParams" | "headers" | "authorization"
|
||||||
| "params"
|
|
||||||
| "bodyParams"
|
|
||||||
| "headers"
|
|
||||||
| "authorization"
|
|
||||||
| "requestVariables"
|
|
||||||
|
|
||||||
type EmbedOption = {
|
type EmbedOption = {
|
||||||
selectedTab: EmbedTabs
|
selectedTab: EmbedTabs
|
||||||
|
|||||||
@@ -56,12 +56,7 @@ import { useI18n } from "~/composables/i18n"
|
|||||||
|
|
||||||
const t = useI18n()
|
const t = useI18n()
|
||||||
|
|
||||||
type EmbedTabs =
|
type EmbedTabs = "params" | "bodyParams" | "headers" | "authorization"
|
||||||
| "params"
|
|
||||||
| "bodyParams"
|
|
||||||
| "headers"
|
|
||||||
| "authorization"
|
|
||||||
| "requestVariables"
|
|
||||||
|
|
||||||
type EmbedOption = {
|
type EmbedOption = {
|
||||||
selectedTab: EmbedTabs
|
selectedTab: EmbedTabs
|
||||||
|
|||||||
@@ -173,11 +173,6 @@ const embedOptions = ref<EmbedOption>({
|
|||||||
label: t("tab.authorization"),
|
label: t("tab.authorization"),
|
||||||
enabled: false,
|
enabled: false,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
value: "requestVariables",
|
|
||||||
label: t("tab.variables"),
|
|
||||||
enabled: false,
|
|
||||||
},
|
|
||||||
],
|
],
|
||||||
theme: "system",
|
theme: "system",
|
||||||
})
|
})
|
||||||
@@ -228,12 +223,7 @@ const currentUser = useReadonlyStream(
|
|||||||
|
|
||||||
const step = ref(1)
|
const step = ref(1)
|
||||||
|
|
||||||
type EmbedTabs =
|
type EmbedTabs = "params" | "bodyParams" | "headers" | "authorization"
|
||||||
| "params"
|
|
||||||
| "bodyParams"
|
|
||||||
| "headers"
|
|
||||||
| "authorization"
|
|
||||||
| "requestVariables"
|
|
||||||
|
|
||||||
type EmbedOption = {
|
type EmbedOption = {
|
||||||
selectedTab: EmbedTabs
|
selectedTab: EmbedTabs
|
||||||
@@ -379,11 +369,6 @@ const displayCustomizeRequestModal = (
|
|||||||
label: t("tab.authorization"),
|
label: t("tab.authorization"),
|
||||||
enabled: false,
|
enabled: false,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
value: "requestVariables",
|
|
||||||
label: t("tab.variables"),
|
|
||||||
enabled: false,
|
|
||||||
},
|
|
||||||
],
|
],
|
||||||
theme: "system",
|
theme: "system",
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,7 +28,7 @@
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="flex overflow-x-scroll"
|
class="flex"
|
||||||
:class="[{ 'border-b pt-2 ': !noActiveTab }, embedColours]"
|
:class="[{ 'border-b pt-2 ': !noActiveTab }, embedColours]"
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
@@ -57,12 +57,7 @@ import { computed } from "vue"
|
|||||||
|
|
||||||
import { useI18n } from "~/composables/i18n"
|
import { useI18n } from "~/composables/i18n"
|
||||||
|
|
||||||
type Tabs =
|
type Tabs = "params" | "bodyParams" | "headers" | "authorization"
|
||||||
| "params"
|
|
||||||
| "bodyParams"
|
|
||||||
| "headers"
|
|
||||||
| "authorization"
|
|
||||||
| "requestVariables"
|
|
||||||
|
|
||||||
type EmbedOption = {
|
type EmbedOption = {
|
||||||
selectedTab: Tabs
|
selectedTab: Tabs
|
||||||
|
|||||||
@@ -79,27 +79,29 @@ import { history, historyKeymap } from "@codemirror/commands"
|
|||||||
import { inputTheme } from "~/helpers/editor/themes/baseTheme"
|
import { inputTheme } from "~/helpers/editor/themes/baseTheme"
|
||||||
import { HoppReactiveEnvPlugin } from "~/helpers/editor/extensions/HoppEnvironment"
|
import { HoppReactiveEnvPlugin } from "~/helpers/editor/extensions/HoppEnvironment"
|
||||||
import { useReadonlyStream } from "@composables/stream"
|
import { useReadonlyStream } from "@composables/stream"
|
||||||
import { AggregateEnvironment, aggregateEnvs$ } from "~/newstore/environments"
|
import {
|
||||||
|
AggregateEnvironment,
|
||||||
|
aggregateEnvsWithSecrets$,
|
||||||
|
} from "~/newstore/environments"
|
||||||
import { platform } from "~/platform"
|
import { platform } from "~/platform"
|
||||||
import { onClickOutside, useDebounceFn } from "@vueuse/core"
|
import { onClickOutside, useDebounceFn } from "@vueuse/core"
|
||||||
import { InspectorResult } from "~/services/inspection"
|
import { InspectorResult } from "~/services/inspection"
|
||||||
import { invokeAction } from "~/helpers/actions"
|
import { invokeAction } from "~/helpers/actions"
|
||||||
|
import { Environment } from "@hoppscotch/data"
|
||||||
import { useI18n } from "~/composables/i18n"
|
import { useI18n } from "~/composables/i18n"
|
||||||
import IconEye from "~icons/lucide/eye"
|
import IconEye from "~icons/lucide/eye"
|
||||||
import IconEyeoff from "~icons/lucide/eye-off"
|
import IconEyeoff from "~icons/lucide/eye-off"
|
||||||
import { CompletionContext, autocompletion } from "@codemirror/autocomplete"
|
|
||||||
import { useService } from "dioc/vue"
|
|
||||||
import { RESTTabService } from "~/services/tab/rest"
|
|
||||||
import { syntaxTree } from "@codemirror/language"
|
|
||||||
|
|
||||||
const t = useI18n()
|
const t = useI18n()
|
||||||
|
|
||||||
|
type Env = Environment["variables"][number] & { source: string }
|
||||||
|
|
||||||
const props = withDefaults(
|
const props = withDefaults(
|
||||||
defineProps<{
|
defineProps<{
|
||||||
modelValue?: string
|
modelValue?: string
|
||||||
placeholder?: string
|
placeholder?: string
|
||||||
styles?: string
|
styles?: string
|
||||||
envs?: AggregateEnvironment[] | null
|
envs?: Env[] | null
|
||||||
focus?: boolean
|
focus?: boolean
|
||||||
selectTextOnMount?: boolean
|
selectTextOnMount?: boolean
|
||||||
environmentHighlights?: boolean
|
environmentHighlights?: boolean
|
||||||
@@ -108,7 +110,6 @@ const props = withDefaults(
|
|||||||
inspectionResults?: InspectorResult[] | undefined
|
inspectionResults?: InspectorResult[] | undefined
|
||||||
contextMenuEnabled?: boolean
|
contextMenuEnabled?: boolean
|
||||||
secret?: boolean
|
secret?: boolean
|
||||||
autoCompleteEnv?: boolean
|
|
||||||
}>(),
|
}>(),
|
||||||
{
|
{
|
||||||
modelValue: "",
|
modelValue: "",
|
||||||
@@ -123,7 +124,6 @@ const props = withDefaults(
|
|||||||
inspectionResults: undefined,
|
inspectionResults: undefined,
|
||||||
contextMenuEnabled: true,
|
contextMenuEnabled: true,
|
||||||
secret: false,
|
secret: false,
|
||||||
autoCompleteEnvSource: false,
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -353,62 +353,29 @@ watch(
|
|||||||
let clipboardEv: ClipboardEvent | null = null
|
let clipboardEv: ClipboardEvent | null = null
|
||||||
let pastedValue: string | null = null
|
let pastedValue: string | null = null
|
||||||
|
|
||||||
const aggregateEnvs = useReadonlyStream(aggregateEnvs$, []) as Ref<
|
const aggregateEnvs = useReadonlyStream(aggregateEnvsWithSecrets$, []) as Ref<
|
||||||
AggregateEnvironment[]
|
AggregateEnvironment[]
|
||||||
>
|
>
|
||||||
|
|
||||||
const tabs = useService(RESTTabService)
|
|
||||||
|
|
||||||
const envVars = computed(() => {
|
const envVars = computed(() => {
|
||||||
if (props.envs) {
|
return props.envs
|
||||||
return props.envs.map((x) => {
|
? props.envs.map((x) => {
|
||||||
const { key, secret } = x
|
if (x.secret) {
|
||||||
const value = secret ? "********" : x.value
|
return {
|
||||||
const sourceEnv = "sourceEnv" in x ? x.sourceEnv : null
|
key: x.key,
|
||||||
return {
|
sourceEnv: "source" in x ? x.source : null,
|
||||||
key,
|
value: "********",
|
||||||
value,
|
}
|
||||||
sourceEnv,
|
}
|
||||||
secret,
|
return {
|
||||||
}
|
key: x.key,
|
||||||
})
|
value: x.value,
|
||||||
}
|
sourceEnv: "source" in x ? x.source : null,
|
||||||
return [
|
}
|
||||||
...tabs.currentActiveTab.value.document.request.requestVariables.map(
|
})
|
||||||
({ active, key, value }) =>
|
: aggregateEnvs.value
|
||||||
active
|
|
||||||
? {
|
|
||||||
key,
|
|
||||||
value,
|
|
||||||
sourceEnv: "RequestVariable",
|
|
||||||
secret: false,
|
|
||||||
}
|
|
||||||
: ({} as AggregateEnvironment)
|
|
||||||
),
|
|
||||||
...aggregateEnvs.value,
|
|
||||||
]
|
|
||||||
})
|
})
|
||||||
|
|
||||||
function envAutoCompletion(context: CompletionContext) {
|
|
||||||
const options = (envVars.value ?? [])
|
|
||||||
.map((env) => ({
|
|
||||||
label: env?.key ? `<<${env.key}>>` : "",
|
|
||||||
info: env?.value ?? "",
|
|
||||||
apply: env?.key ? `<<${env.key}>>` : "",
|
|
||||||
}))
|
|
||||||
.filter((x) => x)
|
|
||||||
|
|
||||||
const nodeBefore = syntaxTree(context.state).resolveInner(context.pos, -1)
|
|
||||||
const textBefore = context.state.sliceDoc(nodeBefore.from, context.pos)
|
|
||||||
const tagBefore = /<<\w*$/.exec(textBefore)
|
|
||||||
if (!tagBefore && !context.explicit) return null
|
|
||||||
return {
|
|
||||||
from: tagBefore ? nodeBefore.from + tagBefore.index : context.pos,
|
|
||||||
options: options,
|
|
||||||
validFor: /^(<<\w*)?$/,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const envTooltipPlugin = new HoppReactiveEnvPlugin(envVars, view)
|
const envTooltipPlugin = new HoppReactiveEnvPlugin(envVars, view)
|
||||||
|
|
||||||
function handleTextSelection() {
|
function handleTextSelection() {
|
||||||
@@ -502,12 +469,6 @@ const getExtensions = (readonly: boolean): Extension => {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
props.autoCompleteEnv
|
|
||||||
? autocompletion({
|
|
||||||
activateOnTyping: true,
|
|
||||||
override: [envAutoCompletion],
|
|
||||||
})
|
|
||||||
: [],
|
|
||||||
ViewPlugin.fromClass(
|
ViewPlugin.fromClass(
|
||||||
class {
|
class {
|
||||||
update(update: ViewUpdate) {
|
update(update: ViewUpdate) {
|
||||||
|
|||||||
@@ -243,7 +243,7 @@ export function useCodemirror(
|
|||||||
if (from === to) return
|
if (from === to) return
|
||||||
const text = view.value?.state.doc.sliceString(from, to)
|
const text = view.value?.state.doc.sliceString(from, to)
|
||||||
const { top, left } = view.value?.coordsAtPos(from)
|
const { top, left } = view.value?.coordsAtPos(from)
|
||||||
if (text?.trim()) {
|
if (text) {
|
||||||
invokeAction("contextmenu.open", {
|
invokeAction("contextmenu.open", {
|
||||||
position: {
|
position: {
|
||||||
top,
|
top,
|
||||||
|
|||||||
293
packages/hoppscotch-common/src/helpers/RESTRequest.ts
Normal file
293
packages/hoppscotch-common/src/helpers/RESTRequest.ts
Normal file
@@ -0,0 +1,293 @@
|
|||||||
|
import {
|
||||||
|
FormDataKeyValue,
|
||||||
|
HoppRESTAuth,
|
||||||
|
HoppRESTHeader,
|
||||||
|
HoppRESTParam,
|
||||||
|
HoppRESTReqBody,
|
||||||
|
HoppRESTRequest,
|
||||||
|
RESTReqSchemaVersion,
|
||||||
|
ValidContentTypes,
|
||||||
|
} from "@hoppscotch/data"
|
||||||
|
import { BehaviorSubject, combineLatest, map } from "rxjs"
|
||||||
|
import { applyBodyTransition } from "~/helpers/rules/BodyTransition"
|
||||||
|
import { HoppRESTResponse } from "./types/HoppRESTResponse"
|
||||||
|
|
||||||
|
export class RESTRequest {
|
||||||
|
public v$ = new BehaviorSubject<typeof RESTReqSchemaVersion>(
|
||||||
|
RESTReqSchemaVersion
|
||||||
|
)
|
||||||
|
public name$ = new BehaviorSubject("Untitled")
|
||||||
|
public endpoint$ = new BehaviorSubject("https://echo.hoppscotch.io/")
|
||||||
|
public params$ = new BehaviorSubject<HoppRESTParam[]>([])
|
||||||
|
public headers$ = new BehaviorSubject<HoppRESTHeader[]>([])
|
||||||
|
public method$ = new BehaviorSubject("GET")
|
||||||
|
public auth$ = new BehaviorSubject<HoppRESTAuth>({
|
||||||
|
authType: "none",
|
||||||
|
authActive: true,
|
||||||
|
})
|
||||||
|
public preRequestScript$ = new BehaviorSubject("")
|
||||||
|
public testScript$ = new BehaviorSubject("")
|
||||||
|
public body$ = new BehaviorSubject<HoppRESTReqBody>({
|
||||||
|
contentType: null,
|
||||||
|
body: null,
|
||||||
|
})
|
||||||
|
|
||||||
|
public response$ = new BehaviorSubject<HoppRESTResponse | null>(null)
|
||||||
|
|
||||||
|
get request$() {
|
||||||
|
// any of above changes construct requests
|
||||||
|
return combineLatest([
|
||||||
|
this.v$,
|
||||||
|
this.name$,
|
||||||
|
this.endpoint$,
|
||||||
|
this.params$,
|
||||||
|
this.headers$,
|
||||||
|
this.method$,
|
||||||
|
this.auth$,
|
||||||
|
this.preRequestScript$,
|
||||||
|
this.testScript$,
|
||||||
|
this.body$,
|
||||||
|
]).pipe(
|
||||||
|
map(
|
||||||
|
([
|
||||||
|
v,
|
||||||
|
name,
|
||||||
|
endpoint,
|
||||||
|
params,
|
||||||
|
headers,
|
||||||
|
method,
|
||||||
|
auth,
|
||||||
|
preRequestScript,
|
||||||
|
testScript,
|
||||||
|
body,
|
||||||
|
]) => ({
|
||||||
|
v,
|
||||||
|
name,
|
||||||
|
endpoint,
|
||||||
|
params,
|
||||||
|
headers,
|
||||||
|
method,
|
||||||
|
auth,
|
||||||
|
preRequestScript,
|
||||||
|
testScript,
|
||||||
|
body,
|
||||||
|
})
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
get contentType$() {
|
||||||
|
return this.body$.pipe(map((body) => body.contentType))
|
||||||
|
}
|
||||||
|
|
||||||
|
get bodyContent$() {
|
||||||
|
return this.body$.pipe(map((body) => body.body))
|
||||||
|
}
|
||||||
|
|
||||||
|
get headersCount$() {
|
||||||
|
return this.headers$.pipe(
|
||||||
|
map(
|
||||||
|
(params) =>
|
||||||
|
params.filter((x) => x.active && (x.key !== "" || x.value !== ""))
|
||||||
|
.length
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
get paramsCount$() {
|
||||||
|
return this.params$.pipe(
|
||||||
|
map(
|
||||||
|
(params) =>
|
||||||
|
params.filter((x) => x.active && (x.key !== "" || x.value !== ""))
|
||||||
|
.length
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
setName(name: string) {
|
||||||
|
this.name$.next(name)
|
||||||
|
}
|
||||||
|
|
||||||
|
setEndpoint(newURL: string) {
|
||||||
|
this.endpoint$.next(newURL)
|
||||||
|
}
|
||||||
|
|
||||||
|
setMethod(newMethod: string) {
|
||||||
|
this.method$.next(newMethod)
|
||||||
|
}
|
||||||
|
|
||||||
|
setParams(entries: HoppRESTParam[]) {
|
||||||
|
this.params$.next(entries)
|
||||||
|
}
|
||||||
|
|
||||||
|
addParam(newParam: HoppRESTParam) {
|
||||||
|
const newParams = this.params$.value.concat(newParam)
|
||||||
|
this.params$.next(newParams)
|
||||||
|
}
|
||||||
|
|
||||||
|
updateParam(index: number, updatedParam: HoppRESTParam) {
|
||||||
|
const newParams = this.params$.value.map((param, i) =>
|
||||||
|
i === index ? updatedParam : param
|
||||||
|
)
|
||||||
|
this.params$.next(newParams)
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteParam(index: number) {
|
||||||
|
const newParams = this.params$.value.filter((_, i) => i !== index)
|
||||||
|
this.params$.next(newParams)
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteAllParams() {
|
||||||
|
this.params$.next([])
|
||||||
|
}
|
||||||
|
|
||||||
|
setHeaders(entries: HoppRESTHeader[]) {
|
||||||
|
this.headers$.next(entries)
|
||||||
|
}
|
||||||
|
|
||||||
|
addHeader(newHeader: HoppRESTHeader) {
|
||||||
|
const newHeaders = this.headers$.value.concat(newHeader)
|
||||||
|
this.headers$.next(newHeaders)
|
||||||
|
}
|
||||||
|
|
||||||
|
updateHeader(index: number, updatedHeader: HoppRESTHeader) {
|
||||||
|
const newHeaders = this.headers$.value.map((header, i) =>
|
||||||
|
i === index ? updatedHeader : header
|
||||||
|
)
|
||||||
|
this.headers$.next(newHeaders)
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteHeader(index: number) {
|
||||||
|
const newHeaders = this.headers$.value.filter((_, i) => i !== index)
|
||||||
|
this.headers$.next(newHeaders)
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteAllHeaders() {
|
||||||
|
this.headers$.next([])
|
||||||
|
}
|
||||||
|
|
||||||
|
setContentType(newContentType: ValidContentTypes | null) {
|
||||||
|
// TODO: persist body evenafter switching content typees
|
||||||
|
this.body$.next(applyBodyTransition(this.body$.value, newContentType))
|
||||||
|
}
|
||||||
|
|
||||||
|
setBody(newBody: string | FormDataKeyValue[] | null) {
|
||||||
|
const body = { ...this.body$.value }
|
||||||
|
body.body = newBody
|
||||||
|
this.body$.next({ ...body })
|
||||||
|
}
|
||||||
|
|
||||||
|
addFormDataEntry(entry: FormDataKeyValue) {
|
||||||
|
if (this.body$.value.contentType !== "multipart/form-data") return {}
|
||||||
|
const body: HoppRESTReqBody = {
|
||||||
|
contentType: "multipart/form-data",
|
||||||
|
body: [...this.body$.value.body, entry],
|
||||||
|
}
|
||||||
|
this.body$.next(body)
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteFormDataEntry(index: number) {
|
||||||
|
// Only perform update if the current content-type is formdata
|
||||||
|
if (this.body$.value.contentType !== "multipart/form-data") return {}
|
||||||
|
|
||||||
|
const body: HoppRESTReqBody = {
|
||||||
|
contentType: "multipart/form-data",
|
||||||
|
body: [...this.body$.value.body.filter((_, i) => i !== index)],
|
||||||
|
}
|
||||||
|
|
||||||
|
this.body$.next(body)
|
||||||
|
}
|
||||||
|
|
||||||
|
updateFormDataEntry(index: number, entry: FormDataKeyValue) {
|
||||||
|
// Only perform update if the current content-type is formdata
|
||||||
|
if (this.body$.value.contentType !== "multipart/form-data") return {}
|
||||||
|
|
||||||
|
const body: HoppRESTReqBody = {
|
||||||
|
contentType: "multipart/form-data",
|
||||||
|
body: [
|
||||||
|
...this.body$.value.body.map((oldEntry, i) =>
|
||||||
|
i === index ? entry : oldEntry
|
||||||
|
),
|
||||||
|
],
|
||||||
|
}
|
||||||
|
this.body$.next(body)
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteAllFormDataEntries() {
|
||||||
|
// Only perform update if the current content-type is formdata
|
||||||
|
if (this.body$.value.contentType !== "multipart/form-data") return {}
|
||||||
|
|
||||||
|
const body: HoppRESTReqBody = {
|
||||||
|
contentType: "multipart/form-data",
|
||||||
|
body: [],
|
||||||
|
}
|
||||||
|
this.body$.next(body)
|
||||||
|
}
|
||||||
|
|
||||||
|
setRequestBody(newBody: HoppRESTReqBody) {
|
||||||
|
this.body$.next(newBody)
|
||||||
|
}
|
||||||
|
|
||||||
|
setAuth(newAuth: HoppRESTAuth) {
|
||||||
|
this.auth$.next(newAuth)
|
||||||
|
}
|
||||||
|
|
||||||
|
setPreRequestScript(newScript: string) {
|
||||||
|
this.preRequestScript$.next(newScript)
|
||||||
|
}
|
||||||
|
|
||||||
|
setTestScript(newScript: string) {
|
||||||
|
this.testScript$.next(newScript)
|
||||||
|
}
|
||||||
|
|
||||||
|
updateResponse(response: HoppRESTResponse | null) {
|
||||||
|
this.response$.next(response)
|
||||||
|
}
|
||||||
|
|
||||||
|
setRequest(request: HoppRESTRequest) {
|
||||||
|
this.v$.next(RESTReqSchemaVersion)
|
||||||
|
this.name$.next(request.name)
|
||||||
|
this.endpoint$.next(request.endpoint)
|
||||||
|
this.params$.next(request.params)
|
||||||
|
this.headers$.next(request.headers)
|
||||||
|
this.method$.next(request.method)
|
||||||
|
this.auth$.next(request.auth)
|
||||||
|
this.preRequestScript$.next(request.preRequestScript)
|
||||||
|
this.testScript$.next(request.testScript)
|
||||||
|
this.body$.next(request.body)
|
||||||
|
}
|
||||||
|
|
||||||
|
getRequest() {
|
||||||
|
return {
|
||||||
|
v: this.v$.value,
|
||||||
|
name: this.name$.value,
|
||||||
|
endpoint: this.endpoint$.value,
|
||||||
|
params: this.params$.value,
|
||||||
|
headers: this.headers$.value,
|
||||||
|
method: this.method$.value,
|
||||||
|
auth: this.auth$.value,
|
||||||
|
preRequestScript: this.preRequestScript$.value,
|
||||||
|
testScript: this.testScript$.value,
|
||||||
|
body: this.body$.value,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resetRequest() {
|
||||||
|
this.v$.next(RESTReqSchemaVersion)
|
||||||
|
this.name$.next("")
|
||||||
|
this.endpoint$.next("")
|
||||||
|
this.params$.next([])
|
||||||
|
this.headers$.next([])
|
||||||
|
this.method$.next("GET")
|
||||||
|
this.auth$.next({
|
||||||
|
authType: "none",
|
||||||
|
authActive: false,
|
||||||
|
})
|
||||||
|
this.preRequestScript$.next("")
|
||||||
|
this.testScript$.next("")
|
||||||
|
this.body$.next({
|
||||||
|
contentType: null,
|
||||||
|
body: null,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,8 +1,4 @@
|
|||||||
import {
|
import { Environment } from "@hoppscotch/data"
|
||||||
Environment,
|
|
||||||
HoppRESTHeaders,
|
|
||||||
HoppRESTRequestVariable,
|
|
||||||
} from "@hoppscotch/data"
|
|
||||||
import { SandboxTestResult, TestDescriptor } from "@hoppscotch/js-sandbox"
|
import { SandboxTestResult, TestDescriptor } from "@hoppscotch/js-sandbox"
|
||||||
import { runTestScript } from "@hoppscotch/js-sandbox/web"
|
import { runTestScript } from "@hoppscotch/js-sandbox/web"
|
||||||
import * as A from "fp-ts/Array"
|
import * as A from "fp-ts/Array"
|
||||||
@@ -69,17 +65,10 @@ const getTestableBody = (
|
|||||||
return x
|
return x
|
||||||
}
|
}
|
||||||
|
|
||||||
const combineEnvVariables = (variables: {
|
const combineEnvVariables = (envs: {
|
||||||
environments: {
|
global: Environment["variables"]
|
||||||
selected: Environment["variables"]
|
selected: Environment["variables"]
|
||||||
global: Environment["variables"]
|
}) => [...envs.selected, ...envs.global]
|
||||||
}
|
|
||||||
requestVariables: Environment["variables"]
|
|
||||||
}) => [
|
|
||||||
...variables.requestVariables,
|
|
||||||
...variables.environments.selected,
|
|
||||||
...variables.environments.global,
|
|
||||||
]
|
|
||||||
|
|
||||||
export const executedResponses$ = new Subject<
|
export const executedResponses$ = new Subject<
|
||||||
HoppRESTResponse & { type: "success" | "fail " }
|
HoppRESTResponse & { type: "success" | "fail " }
|
||||||
@@ -133,38 +122,6 @@ const updateEnvironmentsWithSecret = (
|
|||||||
return updatedEnv
|
return updatedEnv
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Transforms the environment list to a list with unique keys with value
|
|
||||||
* @param envs The environment list to be transformed
|
|
||||||
* @returns The transformed environment list with keys with value
|
|
||||||
*/
|
|
||||||
const filterNonEmptyEnvironmentVariables = (
|
|
||||||
envs: Environment["variables"]
|
|
||||||
): Environment["variables"] => {
|
|
||||||
const envsMap = new Map<string, Environment["variables"][number]>()
|
|
||||||
|
|
||||||
envs.forEach((env) => {
|
|
||||||
if (env.secret) {
|
|
||||||
envsMap.set(env.key, env)
|
|
||||||
} else if (envsMap.has(env.key)) {
|
|
||||||
const existingEnv = envsMap.get(env.key)
|
|
||||||
|
|
||||||
if (
|
|
||||||
existingEnv &&
|
|
||||||
"value" in existingEnv &&
|
|
||||||
existingEnv.value === "" &&
|
|
||||||
env.value !== ""
|
|
||||||
) {
|
|
||||||
envsMap.set(env.key, env)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
envsMap.set(env.key, env)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
return Array.from(envsMap.values())
|
|
||||||
}
|
|
||||||
|
|
||||||
export function runRESTRequest$(
|
export function runRESTRequest$(
|
||||||
tab: Ref<HoppTab<HoppRESTDocument>>
|
tab: Ref<HoppTab<HoppRESTDocument>>
|
||||||
): [
|
): [
|
||||||
@@ -218,40 +175,15 @@ export function runRESTRequest$(
|
|||||||
requestHeaders = [...tab.value.document.request.headers]
|
requestHeaders = [...tab.value.document.request.headers]
|
||||||
}
|
}
|
||||||
|
|
||||||
const finalRequestVariables =
|
|
||||||
tab.value.document.request.requestVariables.map(
|
|
||||||
(v: HoppRESTRequestVariable) => {
|
|
||||||
if (v.active) {
|
|
||||||
return {
|
|
||||||
key: v.key,
|
|
||||||
value: v.value,
|
|
||||||
secret: false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return []
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
const finalRequest = {
|
const finalRequest = {
|
||||||
...tab.value.document.request,
|
...tab.value.document.request,
|
||||||
auth: requestAuth ?? { authType: "none", authActive: false },
|
auth: requestAuth ?? { authType: "none", authActive: false },
|
||||||
headers: requestHeaders as HoppRESTHeaders,
|
headers: requestHeaders,
|
||||||
}
|
}
|
||||||
|
|
||||||
const finalEnvs = {
|
|
||||||
requestVariables: finalRequestVariables as Environment["variables"],
|
|
||||||
environments: envs.right,
|
|
||||||
}
|
|
||||||
|
|
||||||
const finalEnvsWithNonEmptyValues = filterNonEmptyEnvironmentVariables(
|
|
||||||
combineEnvVariables(finalEnvs)
|
|
||||||
)
|
|
||||||
|
|
||||||
const effectiveRequest = getEffectiveRESTRequest(finalRequest, {
|
const effectiveRequest = getEffectiveRESTRequest(finalRequest, {
|
||||||
id: "env-id",
|
|
||||||
v: 1,
|
|
||||||
name: "Env",
|
name: "Env",
|
||||||
variables: finalEnvsWithNonEmptyValues,
|
variables: combineEnvVariables(envs.right),
|
||||||
})
|
})
|
||||||
|
|
||||||
const [stream, cancelRun] = createRESTNetworkRequestStream(effectiveRequest)
|
const [stream, cancelRun] = createRESTNetworkRequestStream(effectiveRequest)
|
||||||
|
|||||||
@@ -38,7 +38,6 @@ const samples = [
|
|||||||
params: [],
|
params: [],
|
||||||
preRequestScript: "",
|
preRequestScript: "",
|
||||||
testScript: "",
|
testScript: "",
|
||||||
requestVariables: [],
|
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -142,7 +141,6 @@ const samples = [
|
|||||||
params: [],
|
params: [],
|
||||||
preRequestScript: "",
|
preRequestScript: "",
|
||||||
testScript: "",
|
testScript: "",
|
||||||
requestVariables: [],
|
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -160,7 +158,6 @@ const samples = [
|
|||||||
params: [],
|
params: [],
|
||||||
preRequestScript: "",
|
preRequestScript: "",
|
||||||
testScript: "",
|
testScript: "",
|
||||||
requestVariables: [],
|
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -184,7 +181,6 @@ const samples = [
|
|||||||
],
|
],
|
||||||
preRequestScript: "",
|
preRequestScript: "",
|
||||||
testScript: "",
|
testScript: "",
|
||||||
requestVariables: [],
|
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -213,7 +209,6 @@ const samples = [
|
|||||||
],
|
],
|
||||||
preRequestScript: "",
|
preRequestScript: "",
|
||||||
testScript: "",
|
testScript: "",
|
||||||
requestVariables: [],
|
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -244,7 +239,6 @@ const samples = [
|
|||||||
params: [],
|
params: [],
|
||||||
preRequestScript: "",
|
preRequestScript: "",
|
||||||
testScript: "",
|
testScript: "",
|
||||||
requestVariables: [],
|
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -274,7 +268,6 @@ const samples = [
|
|||||||
],
|
],
|
||||||
preRequestScript: "",
|
preRequestScript: "",
|
||||||
testScript: "",
|
testScript: "",
|
||||||
requestVariables: [],
|
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -298,7 +291,6 @@ const samples = [
|
|||||||
headers: [],
|
headers: [],
|
||||||
preRequestScript: "",
|
preRequestScript: "",
|
||||||
testScript: "",
|
testScript: "",
|
||||||
requestVariables: [],
|
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -320,7 +312,6 @@ const samples = [
|
|||||||
headers: [],
|
headers: [],
|
||||||
preRequestScript: "",
|
preRequestScript: "",
|
||||||
testScript: "",
|
testScript: "",
|
||||||
requestVariables: [],
|
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -344,7 +335,6 @@ const samples = [
|
|||||||
headers: [],
|
headers: [],
|
||||||
preRequestScript: "",
|
preRequestScript: "",
|
||||||
testScript: "",
|
testScript: "",
|
||||||
requestVariables: [],
|
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -376,7 +366,6 @@ const samples = [
|
|||||||
headers: [],
|
headers: [],
|
||||||
preRequestScript: "",
|
preRequestScript: "",
|
||||||
testScript: "",
|
testScript: "",
|
||||||
requestVariables: [],
|
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -441,7 +430,6 @@ const samples = [
|
|||||||
],
|
],
|
||||||
preRequestScript: "",
|
preRequestScript: "",
|
||||||
testScript: "",
|
testScript: "",
|
||||||
requestVariables: [],
|
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -470,7 +458,6 @@ const samples = [
|
|||||||
headers: [],
|
headers: [],
|
||||||
preRequestScript: "",
|
preRequestScript: "",
|
||||||
testScript: "",
|
testScript: "",
|
||||||
requestVariables: [],
|
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -528,7 +515,6 @@ const samples = [
|
|||||||
],
|
],
|
||||||
preRequestScript: "",
|
preRequestScript: "",
|
||||||
testScript: "",
|
testScript: "",
|
||||||
requestVariables: [],
|
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -574,7 +560,6 @@ const samples = [
|
|||||||
],
|
],
|
||||||
preRequestScript: "",
|
preRequestScript: "",
|
||||||
testScript: "",
|
testScript: "",
|
||||||
requestVariables: [],
|
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -622,7 +607,6 @@ const samples = [
|
|||||||
],
|
],
|
||||||
preRequestScript: "",
|
preRequestScript: "",
|
||||||
testScript: "",
|
testScript: "",
|
||||||
requestVariables: [],
|
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -637,7 +621,6 @@ const samples = [
|
|||||||
params: [],
|
params: [],
|
||||||
preRequestScript: "",
|
preRequestScript: "",
|
||||||
testScript: "",
|
testScript: "",
|
||||||
requestVariables: [],
|
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -662,7 +645,6 @@ const samples = [
|
|||||||
params: [],
|
params: [],
|
||||||
preRequestScript: "",
|
preRequestScript: "",
|
||||||
testScript: "",
|
testScript: "",
|
||||||
requestVariables: [],
|
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -680,7 +662,6 @@ const samples = [
|
|||||||
params: [],
|
params: [],
|
||||||
preRequestScript: "",
|
preRequestScript: "",
|
||||||
testScript: "",
|
testScript: "",
|
||||||
requestVariables: [],
|
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -704,7 +685,6 @@ const samples = [
|
|||||||
params: [],
|
params: [],
|
||||||
preRequestScript: "",
|
preRequestScript: "",
|
||||||
testScript: "",
|
testScript: "",
|
||||||
requestVariables: [],
|
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -722,7 +702,6 @@ const samples = [
|
|||||||
params: [],
|
params: [],
|
||||||
preRequestScript: "",
|
preRequestScript: "",
|
||||||
testScript: "",
|
testScript: "",
|
||||||
requestVariables: [],
|
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -746,7 +725,6 @@ const samples = [
|
|||||||
],
|
],
|
||||||
preRequestScript: "",
|
preRequestScript: "",
|
||||||
testScript: "",
|
testScript: "",
|
||||||
requestVariables: [],
|
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -769,7 +747,6 @@ const samples = [
|
|||||||
headers: [],
|
headers: [],
|
||||||
preRequestScript: "",
|
preRequestScript: "",
|
||||||
testScript: "",
|
testScript: "",
|
||||||
requestVariables: [],
|
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -790,7 +767,6 @@ const samples = [
|
|||||||
headers: [],
|
headers: [],
|
||||||
preRequestScript: "",
|
preRequestScript: "",
|
||||||
testScript: "",
|
testScript: "",
|
||||||
requestVariables: [],
|
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -812,7 +788,6 @@ const samples = [
|
|||||||
headers: [],
|
headers: [],
|
||||||
preRequestScript: "",
|
preRequestScript: "",
|
||||||
testScript: "",
|
testScript: "",
|
||||||
requestVariables: [],
|
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -833,7 +808,6 @@ const samples = [
|
|||||||
headers: [],
|
headers: [],
|
||||||
preRequestScript: "",
|
preRequestScript: "",
|
||||||
testScript: "",
|
testScript: "",
|
||||||
requestVariables: [],
|
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -865,7 +839,6 @@ const samples = [
|
|||||||
headers: [],
|
headers: [],
|
||||||
preRequestScript: "",
|
preRequestScript: "",
|
||||||
testScript: "",
|
testScript: "",
|
||||||
requestVariables: [],
|
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -181,6 +181,5 @@ export const parseCurlCommand = (curlCommand: string) => {
|
|||||||
testScript: defaultRESTReq.testScript,
|
testScript: defaultRESTReq.testScript,
|
||||||
auth,
|
auth,
|
||||||
body: finalBody,
|
body: finalBody,
|
||||||
requestVariables: defaultRESTReq.requestVariables,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import { StreamSubscriberFunc } from "@composables/stream"
|
|||||||
import {
|
import {
|
||||||
AggregateEnvironment,
|
AggregateEnvironment,
|
||||||
aggregateEnvsWithSecrets$,
|
aggregateEnvsWithSecrets$,
|
||||||
getAggregateEnvs,
|
getAggregateEnvsWithSecrets,
|
||||||
getCurrentEnvironment,
|
getCurrentEnvironment,
|
||||||
getSelectedEnvironmentType,
|
getSelectedEnvironmentType,
|
||||||
} from "~/newstore/environments"
|
} from "~/newstore/environments"
|
||||||
@@ -23,45 +23,15 @@ import IconUsers from "~icons/lucide/users?raw"
|
|||||||
import IconEdit from "~icons/lucide/edit?raw"
|
import IconEdit from "~icons/lucide/edit?raw"
|
||||||
import { SecretEnvironmentService } from "~/services/secret-environment.service"
|
import { SecretEnvironmentService } from "~/services/secret-environment.service"
|
||||||
import { getService } from "~/modules/dioc"
|
import { getService } from "~/modules/dioc"
|
||||||
import { RESTTabService } from "~/services/tab/rest"
|
|
||||||
|
|
||||||
const HOPP_ENVIRONMENT_REGEX = /(<<[a-zA-Z0-9-_]+>>)/g
|
const HOPP_ENVIRONMENT_REGEX = /(<<[a-zA-Z0-9-_]+>>)/g
|
||||||
|
|
||||||
const HOPP_ENV_HIGHLIGHT =
|
const HOPP_ENV_HIGHLIGHT =
|
||||||
"cursor-help transition rounded px-1 focus:outline-none mx-0.5 env-highlight"
|
"cursor-help transition rounded px-1 focus:outline-none mx-0.5 env-highlight"
|
||||||
|
const HOPP_ENV_HIGHLIGHT_FOUND = "env-found"
|
||||||
const HOPP_REQUEST_VARIABLE_HIGHLIGHT = "request-variable-highlight"
|
const HOPP_ENV_HIGHLIGHT_NOT_FOUND = "env-not-found"
|
||||||
const HOPP_ENVIRONMENT_HIGHLIGHT = "environment-variable-highlight"
|
|
||||||
const HOPP_GLOBAL_ENVIRONMENT_HIGHLIGHT = "global-variable-highlight"
|
|
||||||
const HOPP_ENV_HIGHLIGHT_NOT_FOUND = "environment-not-found-highlight"
|
|
||||||
|
|
||||||
const secretEnvironmentService = getService(SecretEnvironmentService)
|
const secretEnvironmentService = getService(SecretEnvironmentService)
|
||||||
const restTabs = getService(RESTTabService)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Transforms the environment list to a list with unique keys with value
|
|
||||||
* @param envs The environment list to be transformed
|
|
||||||
* @returns The transformed environment list with keys with value
|
|
||||||
*/
|
|
||||||
const filterNonEmptyEnvironmentVariables = (
|
|
||||||
envs: AggregateEnvironment[]
|
|
||||||
): AggregateEnvironment[] => {
|
|
||||||
const envsMap = new Map<string, AggregateEnvironment>()
|
|
||||||
|
|
||||||
envs.forEach((env) => {
|
|
||||||
if (envsMap.has(env.key)) {
|
|
||||||
const existingEnv = envsMap.get(env.key)
|
|
||||||
|
|
||||||
if (existingEnv?.value === "" && env.value !== "") {
|
|
||||||
envsMap.set(env.key, env)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
envsMap.set(env.key, env)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
return Array.from(envsMap.values())
|
|
||||||
}
|
|
||||||
|
|
||||||
const cursorTooltipField = (aggregateEnvs: AggregateEnvironment[]) =>
|
const cursorTooltipField = (aggregateEnvs: AggregateEnvironment[]) =>
|
||||||
hoverTooltip(
|
hoverTooltip(
|
||||||
@@ -97,12 +67,7 @@ const cursorTooltipField = (aggregateEnvs: AggregateEnvironment[]) =>
|
|||||||
|
|
||||||
const parsedEnvKey = text.slice(start - from, end - from)
|
const parsedEnvKey = text.slice(start - from, end - from)
|
||||||
|
|
||||||
const envsWithNoEmptyValues =
|
const tooltipEnv = aggregateEnvs.find((env) => env.key === parsedEnvKey)
|
||||||
filterNonEmptyEnvironmentVariables(aggregateEnvs)
|
|
||||||
|
|
||||||
const tooltipEnv = envsWithNoEmptyValues.find(
|
|
||||||
(env) => env.key === parsedEnvKey
|
|
||||||
)
|
|
||||||
|
|
||||||
const envName = tooltipEnv?.sourceEnv ?? "Choose an Environment"
|
const envName = tooltipEnv?.sourceEnv ?? "Choose an Environment"
|
||||||
|
|
||||||
@@ -130,12 +95,7 @@ const cursorTooltipField = (aggregateEnvs: AggregateEnvironment[]) =>
|
|||||||
|
|
||||||
const result = parseTemplateStringE(envValue, aggregateEnvs)
|
const result = parseTemplateStringE(envValue, aggregateEnvs)
|
||||||
|
|
||||||
let finalEnv = E.isLeft(result) ? "error" : result.right
|
const finalEnv = E.isLeft(result) ? "error" : result.right
|
||||||
|
|
||||||
// If the request variable has an secret variable
|
|
||||||
// parseTemplateStringE is passed the secret value which has value undefined
|
|
||||||
// So, we need to check if the result is undefined and then set the finalEnv to ******
|
|
||||||
if (finalEnv === "undefined") finalEnv = "******"
|
|
||||||
|
|
||||||
const selectedEnvType = getSelectedEnvironmentType()
|
const selectedEnvType = getSelectedEnvironmentType()
|
||||||
|
|
||||||
@@ -163,16 +123,11 @@ const cursorTooltipField = (aggregateEnvs: AggregateEnvironment[]) =>
|
|||||||
invokeActionType = "modals.my.environment.edit"
|
invokeActionType = "modals.my.environment.edit"
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tooltipEnv?.sourceEnv === "RequestVariable") {
|
invokeAction(invokeActionType, {
|
||||||
restTabs.currentActiveTab.value.document.optionTabPreference =
|
envName: tooltipEnv?.sourceEnv !== "Global" ? envName : "Global",
|
||||||
"requestVariables"
|
variableName: parsedEnvKey,
|
||||||
} else {
|
isSecret: tooltipEnv?.secret,
|
||||||
invokeAction(invokeActionType, {
|
})
|
||||||
envName: tooltipEnv?.sourceEnv === "Global" ? "Global" : envName,
|
|
||||||
variableName: parsedEnvKey,
|
|
||||||
isSecret: tooltipEnv?.secret,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
editIcon.innerHTML = `<span class="inline-flex items-center justify-center my-1">${IconEdit}</span>`
|
editIcon.innerHTML = `<span class="inline-flex items-center justify-center my-1">${IconEdit}</span>`
|
||||||
tooltip.appendChild(editIcon)
|
tooltip.appendChild(editIcon)
|
||||||
@@ -210,16 +165,11 @@ const cursorTooltipField = (aggregateEnvs: AggregateEnvironment[]) =>
|
|||||||
)
|
)
|
||||||
|
|
||||||
function checkEnv(env: string, aggregateEnvs: AggregateEnvironment[]) {
|
function checkEnv(env: string, aggregateEnvs: AggregateEnvironment[]) {
|
||||||
let className = HOPP_ENV_HIGHLIGHT_NOT_FOUND
|
const className = aggregateEnvs.find(
|
||||||
|
|
||||||
const envSource = aggregateEnvs.find(
|
|
||||||
(k: { key: string }) => k.key === env.slice(2, -2)
|
(k: { key: string }) => k.key === env.slice(2, -2)
|
||||||
)?.sourceEnv
|
)
|
||||||
|
? HOPP_ENV_HIGHLIGHT_FOUND
|
||||||
if (envSource === "RequestVariable")
|
: HOPP_ENV_HIGHLIGHT_NOT_FOUND
|
||||||
className = HOPP_REQUEST_VARIABLE_HIGHLIGHT
|
|
||||||
else if (envSource === "Global") className = HOPP_GLOBAL_ENVIRONMENT_HIGHLIGHT
|
|
||||||
else if (envSource !== undefined) className = HOPP_ENVIRONMENT_HIGHLIGHT
|
|
||||||
|
|
||||||
return Decoration.mark({
|
return Decoration.mark({
|
||||||
class: `${HOPP_ENV_HIGHLIGHT} ${className}`,
|
class: `${HOPP_ENV_HIGHLIGHT} ${className}`,
|
||||||
@@ -235,10 +185,7 @@ const getMatchDecorator = (aggregateEnvs: AggregateEnvironment[]) =>
|
|||||||
export const environmentHighlightStyle = (
|
export const environmentHighlightStyle = (
|
||||||
aggregateEnvs: AggregateEnvironment[]
|
aggregateEnvs: AggregateEnvironment[]
|
||||||
) => {
|
) => {
|
||||||
const envsWithNoEmptyValues =
|
const decorator = getMatchDecorator(aggregateEnvs)
|
||||||
filterNonEmptyEnvironmentVariables(aggregateEnvs)
|
|
||||||
|
|
||||||
const decorator = getMatchDecorator(envsWithNoEmptyValues)
|
|
||||||
|
|
||||||
return ViewPlugin.define(
|
return ViewPlugin.define(
|
||||||
(view) => ({
|
(view) => ({
|
||||||
@@ -262,45 +209,10 @@ export class HoppEnvironmentPlugin {
|
|||||||
subscribeToStream: StreamSubscriberFunc,
|
subscribeToStream: StreamSubscriberFunc,
|
||||||
private editorView: Ref<EditorView | undefined>
|
private editorView: Ref<EditorView | undefined>
|
||||||
) {
|
) {
|
||||||
const aggregateEnvs = getAggregateEnvs()
|
this.envs = getAggregateEnvsWithSecrets()
|
||||||
const currentTab = restTabs.currentActiveTab.value
|
|
||||||
|
|
||||||
watch(
|
|
||||||
currentTab.document.request,
|
|
||||||
(reqVariables) => {
|
|
||||||
this.envs = [
|
|
||||||
...reqVariables.requestVariables.map(({ key, value }) => ({
|
|
||||||
key,
|
|
||||||
value,
|
|
||||||
sourceEnv: "RequestVariable",
|
|
||||||
secret: false,
|
|
||||||
})),
|
|
||||||
...aggregateEnvs,
|
|
||||||
]
|
|
||||||
|
|
||||||
this.editorView.value?.dispatch({
|
|
||||||
effects: this.compartment.reconfigure([
|
|
||||||
cursorTooltipField(this.envs),
|
|
||||||
environmentHighlightStyle(this.envs),
|
|
||||||
]),
|
|
||||||
})
|
|
||||||
},
|
|
||||||
{ immediate: true, deep: true }
|
|
||||||
)
|
|
||||||
|
|
||||||
subscribeToStream(aggregateEnvsWithSecrets$, (envs) => {
|
subscribeToStream(aggregateEnvsWithSecrets$, (envs) => {
|
||||||
this.envs = [
|
this.envs = envs
|
||||||
...currentTab.document.request.requestVariables.map(
|
|
||||||
({ key, value }) => ({
|
|
||||||
key,
|
|
||||||
value,
|
|
||||||
sourceEnv: "RequestVariable",
|
|
||||||
secret: false,
|
|
||||||
})
|
|
||||||
),
|
|
||||||
...envs,
|
|
||||||
]
|
|
||||||
|
|
||||||
this.editorView.value?.dispatch({
|
this.editorView.value?.dispatch({
|
||||||
effects: this.compartment.reconfigure([
|
effects: this.compartment.reconfigure([
|
||||||
cursorTooltipField(this.envs),
|
cursorTooltipField(this.envs),
|
||||||
@@ -339,7 +251,7 @@ export class HoppReactiveEnvPlugin {
|
|||||||
]),
|
]),
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
{ immediate: true, deep: true }
|
{ immediate: true }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import {
|
|||||||
knownContentTypes,
|
knownContentTypes,
|
||||||
makeCollection,
|
makeCollection,
|
||||||
makeRESTRequest,
|
makeRESTRequest,
|
||||||
HoppRESTRequestVariable,
|
|
||||||
} from "@hoppscotch/data"
|
} from "@hoppscotch/data"
|
||||||
|
|
||||||
import * as A from "fp-ts/Array"
|
import * as A from "fp-ts/Array"
|
||||||
@@ -29,27 +28,14 @@ type UnwrapPromise<T extends Promise<any>> = T extends Promise<infer Y>
|
|||||||
type InsomniaDoc = UnwrapPromise<ReturnType<typeof convert>>
|
type InsomniaDoc = UnwrapPromise<ReturnType<typeof convert>>
|
||||||
type InsomniaResource = ImportRequest
|
type InsomniaResource = ImportRequest
|
||||||
|
|
||||||
// insomnia-importers v3.6.0 doesn't provide a type for path parameters and they have deprecated the library
|
|
||||||
type InsomniaPathParameter = {
|
|
||||||
name: string
|
|
||||||
value: string
|
|
||||||
}
|
|
||||||
|
|
||||||
type InsomniaFolderResource = ImportRequest & { _type: "request_group" }
|
type InsomniaFolderResource = ImportRequest & { _type: "request_group" }
|
||||||
type InsomniaRequestResource = ImportRequest & {
|
type InsomniaRequestResource = ImportRequest & { _type: "request" }
|
||||||
_type: "request"
|
|
||||||
} & {
|
|
||||||
pathParameters?: InsomniaPathParameter[]
|
|
||||||
}
|
|
||||||
|
|
||||||
const parseInsomniaDoc = (content: string) =>
|
const parseInsomniaDoc = (content: string) =>
|
||||||
TO.tryCatch(() => convert(content))
|
TO.tryCatch(() => convert(content))
|
||||||
|
|
||||||
const replacePathVarTemplating = (expression: string) =>
|
|
||||||
expression.replaceAll(/:([^/]+)/g, "<<$1>>")
|
|
||||||
|
|
||||||
const replaceVarTemplating = (expression: string) =>
|
const replaceVarTemplating = (expression: string) =>
|
||||||
pipe(expression, replacePathVarTemplating, replaceInsomniaTemplating)
|
replaceInsomniaTemplating(expression)
|
||||||
|
|
||||||
const getFoldersIn = (
|
const getFoldersIn = (
|
||||||
folder: InsomniaFolderResource | null,
|
folder: InsomniaFolderResource | null,
|
||||||
@@ -191,15 +177,6 @@ const getHoppReqParams = (req: InsomniaRequestResource): HoppRESTParam[] =>
|
|||||||
active: !(param.disabled ?? false),
|
active: !(param.disabled ?? false),
|
||||||
})) ?? []
|
})) ?? []
|
||||||
|
|
||||||
const getHoppReqVariables = (
|
|
||||||
req: InsomniaRequestResource
|
|
||||||
): HoppRESTRequestVariable[] =>
|
|
||||||
req.pathParameters?.map((variable) => ({
|
|
||||||
key: replaceVarTemplating(variable.name),
|
|
||||||
value: replaceVarTemplating(variable.value ?? ""),
|
|
||||||
active: true,
|
|
||||||
})) ?? []
|
|
||||||
|
|
||||||
const getHoppRequest = (req: InsomniaRequestResource): HoppRESTRequest =>
|
const getHoppRequest = (req: InsomniaRequestResource): HoppRESTRequest =>
|
||||||
makeRESTRequest({
|
makeRESTRequest({
|
||||||
name: req.name ?? "Untitled Request",
|
name: req.name ?? "Untitled Request",
|
||||||
@@ -212,8 +189,6 @@ const getHoppRequest = (req: InsomniaRequestResource): HoppRESTRequest =>
|
|||||||
|
|
||||||
preRequestScript: "",
|
preRequestScript: "",
|
||||||
testScript: "",
|
testScript: "",
|
||||||
|
|
||||||
requestVariables: getHoppReqVariables(req),
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const getHoppFolder = (
|
const getHoppFolder = (
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ import {
|
|||||||
makeRESTRequest,
|
makeRESTRequest,
|
||||||
HoppCollection,
|
HoppCollection,
|
||||||
makeCollection,
|
makeCollection,
|
||||||
HoppRESTRequestVariable,
|
|
||||||
} from "@hoppscotch/data"
|
} from "@hoppscotch/data"
|
||||||
import { pipe, flow } from "fp-ts/function"
|
import { pipe, flow } from "fp-ts/function"
|
||||||
import * as A from "fp-ts/Array"
|
import * as A from "fp-ts/Array"
|
||||||
@@ -83,27 +82,6 @@ const parseOpenAPIParams = (params: OpenAPIParamsType[]): HoppRESTParam[] =>
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
const parseOpenAPIVariables = (
|
|
||||||
variables: OpenAPIParamsType[]
|
|
||||||
): HoppRESTRequestVariable[] =>
|
|
||||||
pipe(
|
|
||||||
variables,
|
|
||||||
|
|
||||||
A.filterMap(
|
|
||||||
flow(
|
|
||||||
O.fromPredicate((param) => param.in === "path"),
|
|
||||||
O.map(
|
|
||||||
(param) =>
|
|
||||||
<HoppRESTRequestVariable>{
|
|
||||||
key: param.name,
|
|
||||||
value: "", // TODO: Can we do anything more ? (parse default values maybe)
|
|
||||||
active: true,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
const parseOpenAPIHeaders = (params: OpenAPIParamsType[]): HoppRESTHeader[] =>
|
const parseOpenAPIHeaders = (params: OpenAPIParamsType[]): HoppRESTHeader[] =>
|
||||||
pipe(
|
pipe(
|
||||||
params,
|
params,
|
||||||
@@ -599,10 +577,6 @@ const convertPathToHoppReqs = (
|
|||||||
|
|
||||||
preRequestScript: "",
|
preRequestScript: "",
|
||||||
testScript: "",
|
testScript: "",
|
||||||
|
|
||||||
requestVariables: parseOpenAPIVariables(
|
|
||||||
(info.parameters as OpenAPIParamsType[] | undefined) ?? []
|
|
||||||
),
|
|
||||||
})
|
})
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import {
|
|||||||
QueryParam,
|
QueryParam,
|
||||||
RequestAuthDefinition,
|
RequestAuthDefinition,
|
||||||
VariableDefinition,
|
VariableDefinition,
|
||||||
Variable,
|
|
||||||
} from "postman-collection"
|
} from "postman-collection"
|
||||||
import {
|
import {
|
||||||
HoppRESTAuth,
|
HoppRESTAuth,
|
||||||
@@ -19,7 +18,6 @@ import {
|
|||||||
ValidContentTypes,
|
ValidContentTypes,
|
||||||
knownContentTypes,
|
knownContentTypes,
|
||||||
FormDataKeyValue,
|
FormDataKeyValue,
|
||||||
HoppRESTRequestVariable,
|
|
||||||
} from "@hoppscotch/data"
|
} from "@hoppscotch/data"
|
||||||
import { pipe, flow } from "fp-ts/function"
|
import { pipe, flow } from "fp-ts/function"
|
||||||
import * as S from "fp-ts/string"
|
import * as S from "fp-ts/string"
|
||||||
@@ -93,25 +91,6 @@ const getHoppReqParams = (item: Item): HoppRESTParam[] => {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const getHoppReqVariables = (item: Item) => {
|
|
||||||
return pipe(
|
|
||||||
item.request.url.variables.all(),
|
|
||||||
A.filter(
|
|
||||||
(variable): variable is Variable =>
|
|
||||||
variable.key !== undefined &&
|
|
||||||
variable.key !== null &&
|
|
||||||
variable.key.length > 0
|
|
||||||
),
|
|
||||||
A.map((variable) => {
|
|
||||||
return <HoppRESTRequestVariable>{
|
|
||||||
key: replacePMVarTemplating(variable.key ?? ""),
|
|
||||||
value: replacePMVarTemplating(variable.value ?? ""),
|
|
||||||
active: !variable.disabled,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
type PMRequestAuthDef<
|
type PMRequestAuthDef<
|
||||||
AuthType extends
|
AuthType extends
|
||||||
RequestAuthDefinition["type"] = RequestAuthDefinition["type"],
|
RequestAuthDefinition["type"] = RequestAuthDefinition["type"],
|
||||||
@@ -301,7 +280,6 @@ const getHoppRequest = (item: Item): HoppRESTRequest => {
|
|||||||
params: getHoppReqParams(item),
|
params: getHoppReqParams(item),
|
||||||
auth: getHoppReqAuth(item),
|
auth: getHoppReqAuth(item),
|
||||||
body: getHoppReqBody(item),
|
body: getHoppReqBody(item),
|
||||||
requestVariables: getHoppReqVariables(item),
|
|
||||||
|
|
||||||
// TODO: Decide about this
|
// TODO: Decide about this
|
||||||
preRequestScript: "",
|
preRequestScript: "",
|
||||||
|
|||||||
@@ -14,8 +14,8 @@ import { SecretEnvironmentService } from "~/services/secret-environment.service"
|
|||||||
const secretEnvironmentService = getService(SecretEnvironmentService)
|
const secretEnvironmentService = getService(SecretEnvironmentService)
|
||||||
|
|
||||||
const unsecretEnvironments = (
|
const unsecretEnvironments = (
|
||||||
selected: Environment,
|
global: Environment["variables"],
|
||||||
global: Environment["variables"]
|
selected: Environment
|
||||||
) => {
|
) => {
|
||||||
const resolvedGlobalWithSecrets = global.map((globalVar, index) => {
|
const resolvedGlobalWithSecrets = global.map((globalVar, index) => {
|
||||||
const secretVar = secretEnvironmentService.getSecretEnvironmentVariable(
|
const secretVar = secretEnvironmentService.getSecretEnvironmentVariable(
|
||||||
@@ -65,8 +65,8 @@ const unsecretEnvironments = (
|
|||||||
|
|
||||||
export const getCombinedEnvVariables = () => {
|
export const getCombinedEnvVariables = () => {
|
||||||
const reformedVars = unsecretEnvironments(
|
const reformedVars = unsecretEnvironments(
|
||||||
getCurrentEnvironment(),
|
getGlobalVariables(),
|
||||||
getGlobalVariables()
|
getCurrentEnvironment()
|
||||||
)
|
)
|
||||||
return {
|
return {
|
||||||
global: cloneDeep(reformedVars.global),
|
global: cloneDeep(reformedVars.global),
|
||||||
|
|||||||
@@ -17,5 +17,4 @@ export const getDefaultRESTRequest = (): HoppRESTRequest => ({
|
|||||||
contentType: null,
|
contentType: null,
|
||||||
body: null,
|
body: null,
|
||||||
},
|
},
|
||||||
requestVariables: [],
|
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import {
|
|||||||
import { arrayFlatMap, arraySort } from "../functional/array"
|
import { arrayFlatMap, arraySort } from "../functional/array"
|
||||||
import { toFormData } from "../functional/formData"
|
import { toFormData } from "../functional/formData"
|
||||||
import { tupleWithSameKeysToRecord } from "../functional/record"
|
import { tupleWithSameKeysToRecord } from "../functional/record"
|
||||||
|
import { getGlobalVariables } from "~/newstore/environments"
|
||||||
|
|
||||||
export interface EffectiveHoppRESTRequest extends HoppRESTRequest {
|
export interface EffectiveHoppRESTRequest extends HoppRESTRequest {
|
||||||
/**
|
/**
|
||||||
@@ -33,7 +34,6 @@ export interface EffectiveHoppRESTRequest extends HoppRESTRequest {
|
|||||||
effectiveFinalHeaders: { key: string; value: string }[]
|
effectiveFinalHeaders: { key: string; value: string }[]
|
||||||
effectiveFinalParams: { key: string; value: string }[]
|
effectiveFinalParams: { key: string; value: string }[]
|
||||||
effectiveFinalBody: FormData | string | null
|
effectiveFinalBody: FormData | string | null
|
||||||
effectiveFinalRequestVariables: { key: string; value: string }[]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -313,53 +313,38 @@ export function getEffectiveRESTRequest(
|
|||||||
request: HoppRESTRequest,
|
request: HoppRESTRequest,
|
||||||
environment: Environment
|
environment: Environment
|
||||||
): EffectiveHoppRESTRequest {
|
): EffectiveHoppRESTRequest {
|
||||||
|
const envVariables = [...environment.variables, ...getGlobalVariables()]
|
||||||
|
|
||||||
const effectiveFinalHeaders = pipe(
|
const effectiveFinalHeaders = pipe(
|
||||||
getComputedHeaders(request, environment.variables).map((h) => h.header),
|
getComputedHeaders(request, envVariables).map((h) => h.header),
|
||||||
A.concat(request.headers),
|
A.concat(request.headers),
|
||||||
A.filter((x) => x.active && x.key !== ""),
|
A.filter((x) => x.active && x.key !== ""),
|
||||||
A.map((x) => ({
|
A.map((x) => ({
|
||||||
active: true,
|
active: true,
|
||||||
key: parseTemplateString(x.key, environment.variables),
|
key: parseTemplateString(x.key, envVariables),
|
||||||
value: parseTemplateString(x.value, environment.variables),
|
value: parseTemplateString(x.value, envVariables),
|
||||||
}))
|
}))
|
||||||
)
|
)
|
||||||
|
|
||||||
const effectiveFinalParams = pipe(
|
const effectiveFinalParams = pipe(
|
||||||
getComputedParams(request, environment.variables).map((p) => p.param),
|
getComputedParams(request, envVariables).map((p) => p.param),
|
||||||
A.concat(request.params),
|
A.concat(request.params),
|
||||||
A.filter((x) => x.active && x.key !== ""),
|
A.filter((x) => x.active && x.key !== ""),
|
||||||
A.map((x) => ({
|
A.map((x) => ({
|
||||||
active: true,
|
active: true,
|
||||||
key: parseTemplateString(x.key, environment.variables),
|
key: parseTemplateString(x.key, envVariables),
|
||||||
value: parseTemplateString(x.value, environment.variables),
|
value: parseTemplateString(x.value, envVariables),
|
||||||
}))
|
}))
|
||||||
)
|
)
|
||||||
|
|
||||||
const effectiveFinalRequestVariables = pipe(
|
const effectiveFinalBody = getFinalBodyFromRequest(request, envVariables)
|
||||||
request.requestVariables,
|
|
||||||
A.filter((x) => x.active && x.key !== ""),
|
|
||||||
A.map((x) => ({
|
|
||||||
active: true,
|
|
||||||
key: parseTemplateString(x.key, environment.variables),
|
|
||||||
value: parseTemplateString(x.value, environment.variables),
|
|
||||||
}))
|
|
||||||
)
|
|
||||||
|
|
||||||
const effectiveFinalBody = getFinalBodyFromRequest(
|
|
||||||
request,
|
|
||||||
environment.variables
|
|
||||||
)
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...request,
|
...request,
|
||||||
effectiveFinalURL: parseTemplateString(
|
effectiveFinalURL: parseTemplateString(request.endpoint, envVariables),
|
||||||
request.endpoint,
|
|
||||||
environment.variables
|
|
||||||
),
|
|
||||||
effectiveFinalHeaders,
|
effectiveFinalHeaders,
|
||||||
effectiveFinalParams,
|
effectiveFinalParams,
|
||||||
effectiveFinalBody,
|
effectiveFinalBody,
|
||||||
effectiveFinalRequestVariables,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -353,7 +353,6 @@ executedResponses$.subscribe((res) => {
|
|||||||
params: res.req.params,
|
params: res.req.params,
|
||||||
preRequestScript: res.req.preRequestScript,
|
preRequestScript: res.req.preRequestScript,
|
||||||
testScript: res.req.testScript,
|
testScript: res.req.testScript,
|
||||||
requestVariables: res.req.requestVariables,
|
|
||||||
v: res.req.v,
|
v: res.req.v,
|
||||||
},
|
},
|
||||||
responseMeta: {
|
responseMeta: {
|
||||||
|
|||||||
@@ -38,7 +38,6 @@ export type SettingsDef = {
|
|||||||
httpUrlEncoded: boolean
|
httpUrlEncoded: boolean
|
||||||
httpPreRequest: boolean
|
httpPreRequest: boolean
|
||||||
httpTest: boolean
|
httpTest: boolean
|
||||||
httpRequestVariables: boolean
|
|
||||||
graphqlQuery: boolean
|
graphqlQuery: boolean
|
||||||
graphqlResponseBody: boolean
|
graphqlResponseBody: boolean
|
||||||
graphqlHeaders: boolean
|
graphqlHeaders: boolean
|
||||||
@@ -80,7 +79,6 @@ export const getDefaultSettings = (): SettingsDef => ({
|
|||||||
httpUrlEncoded: true,
|
httpUrlEncoded: true,
|
||||||
httpPreRequest: true,
|
httpPreRequest: true,
|
||||||
httpTest: true,
|
httpTest: true,
|
||||||
httpRequestVariables: true,
|
|
||||||
graphqlQuery: true,
|
graphqlQuery: true,
|
||||||
graphqlResponseBody: true,
|
graphqlResponseBody: true,
|
||||||
graphqlHeaders: false,
|
graphqlHeaders: false,
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ import { Ref, markRaw } from "vue"
|
|||||||
import IconPlusCircle from "~icons/lucide/plus-circle"
|
import IconPlusCircle from "~icons/lucide/plus-circle"
|
||||||
import { HoppRESTRequest } from "@hoppscotch/data"
|
import { HoppRESTRequest } from "@hoppscotch/data"
|
||||||
import {
|
import {
|
||||||
AggregateEnvironment,
|
|
||||||
aggregateEnvsWithSecrets$,
|
aggregateEnvsWithSecrets$,
|
||||||
getCurrentEnvironment,
|
getCurrentEnvironment,
|
||||||
getSelectedEnvironmentType,
|
getSelectedEnvironmentType,
|
||||||
@@ -19,7 +18,6 @@ import { invokeAction } from "~/helpers/actions"
|
|||||||
import { computed } from "vue"
|
import { computed } from "vue"
|
||||||
import { useStreamStatic } from "~/composables/stream"
|
import { useStreamStatic } from "~/composables/stream"
|
||||||
import { SecretEnvironmentService } from "~/services/secret-environment.service"
|
import { SecretEnvironmentService } from "~/services/secret-environment.service"
|
||||||
import { RESTTabService } from "~/services/tab/rest"
|
|
||||||
|
|
||||||
const HOPP_ENVIRONMENT_REGEX = /(<<[a-zA-Z0-9-_]+>>)/g
|
const HOPP_ENVIRONMENT_REGEX = /(<<[a-zA-Z0-9-_]+>>)/g
|
||||||
|
|
||||||
@@ -43,7 +41,6 @@ export class EnvironmentInspectorService extends Service implements Inspector {
|
|||||||
|
|
||||||
private readonly inspection = this.bind(InspectionService)
|
private readonly inspection = this.bind(InspectionService)
|
||||||
private readonly secretEnvs = this.bind(SecretEnvironmentService)
|
private readonly secretEnvs = this.bind(SecretEnvironmentService)
|
||||||
private readonly restTabs = this.bind(RESTTabService)
|
|
||||||
|
|
||||||
private aggregateEnvsWithSecrets = useStreamStatic(
|
private aggregateEnvsWithSecrets = useStreamStatic(
|
||||||
aggregateEnvsWithSecrets$,
|
aggregateEnvsWithSecrets$,
|
||||||
@@ -71,14 +68,7 @@ export class EnvironmentInspectorService extends Service implements Inspector {
|
|||||||
) => {
|
) => {
|
||||||
const newErrors: InspectorResult[] = []
|
const newErrors: InspectorResult[] = []
|
||||||
|
|
||||||
const currentTab = this.restTabs.currentActiveTab.value
|
const envKeys = this.aggregateEnvsWithSecrets.value.map((e) => e.key)
|
||||||
|
|
||||||
const environmentVariables = [
|
|
||||||
...currentTab.document.request.requestVariables,
|
|
||||||
...this.aggregateEnvsWithSecrets.value,
|
|
||||||
]
|
|
||||||
|
|
||||||
const envKeys = environmentVariables.map((e) => e.key)
|
|
||||||
|
|
||||||
target.forEach((element, index) => {
|
target.forEach((element, index) => {
|
||||||
if (isENVInString(element)) {
|
if (isENVInString(element)) {
|
||||||
@@ -134,31 +124,6 @@ export class EnvironmentInspectorService extends Service implements Inspector {
|
|||||||
return newErrors
|
return newErrors
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Transforms the environment list to a list with unique keys with value
|
|
||||||
* @param envs The environment list to be transformed
|
|
||||||
* @returns The transformed environment list with keys with value
|
|
||||||
*/
|
|
||||||
private filterNonEmptyEnvironmentVariables = (
|
|
||||||
envs: AggregateEnvironment[]
|
|
||||||
): AggregateEnvironment[] => {
|
|
||||||
const envsMap = new Map<string, AggregateEnvironment>()
|
|
||||||
|
|
||||||
envs.forEach((env) => {
|
|
||||||
if (envsMap.has(env.key)) {
|
|
||||||
const existingEnv = envsMap.get(env.key)
|
|
||||||
|
|
||||||
if (existingEnv?.value === "" && env.value !== "") {
|
|
||||||
envsMap.set(env.key, env)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
envsMap.set(env.key, env)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
return Array.from(envsMap.values())
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if the environment variables in the target array are empty
|
* Checks if the environment variables in the target array are empty
|
||||||
* @param target The target array to validate
|
* @param target The target array to validate
|
||||||
@@ -180,19 +145,7 @@ export class EnvironmentInspectorService extends Service implements Inspector {
|
|||||||
const formattedExEnv = exEnv.slice(2, -2)
|
const formattedExEnv = exEnv.slice(2, -2)
|
||||||
const currentSelectedEnvironment = getCurrentEnvironment()
|
const currentSelectedEnvironment = getCurrentEnvironment()
|
||||||
|
|
||||||
const currentTab = this.restTabs.currentActiveTab.value
|
this.aggregateEnvsWithSecrets.value.forEach((env) => {
|
||||||
|
|
||||||
const environmentVariables =
|
|
||||||
this.filterNonEmptyEnvironmentVariables([
|
|
||||||
...currentTab.document.request.requestVariables.map((env) => ({
|
|
||||||
...env,
|
|
||||||
secret: false,
|
|
||||||
sourceEnv: "RequestVariable",
|
|
||||||
})),
|
|
||||||
...this.aggregateEnvsWithSecrets.value,
|
|
||||||
])
|
|
||||||
|
|
||||||
environmentVariables.forEach((env) => {
|
|
||||||
const hasSecretEnv = this.secretEnvs.hasSecretValue(
|
const hasSecretEnv = this.secretEnvs.hasSecretValue(
|
||||||
env.sourceEnv !== "Global"
|
env.sourceEnv !== "Global"
|
||||||
? currentSelectedEnvironment.id
|
? currentSelectedEnvironment.id
|
||||||
@@ -246,19 +199,14 @@ export class EnvironmentInspectorService extends Service implements Inspector {
|
|||||||
"inspections.environment.add_environment_value"
|
"inspections.environment.add_environment_value"
|
||||||
),
|
),
|
||||||
apply: () => {
|
apply: () => {
|
||||||
if (env.sourceEnv === "RequestVariable") {
|
invokeAction(invokeActionType, {
|
||||||
currentTab.document.optionTabPreference =
|
envName:
|
||||||
"requestVariables"
|
env.sourceEnv !== "Global"
|
||||||
} else {
|
? currentSelectedEnvironment.name
|
||||||
invokeAction(invokeActionType, {
|
: "Global",
|
||||||
envName:
|
variableName: formattedExEnv,
|
||||||
env.sourceEnv === "Global"
|
isSecret: env.secret,
|
||||||
? "Global"
|
})
|
||||||
: currentSelectedEnvironment.name,
|
|
||||||
variableName: formattedExEnv,
|
|
||||||
isSecret: env.secret,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
severity: 2,
|
severity: 2,
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ export const REST_COLLECTIONS_MOCK: HoppCollection[] = [
|
|||||||
folders: [],
|
folders: [],
|
||||||
requests: [
|
requests: [
|
||||||
{
|
{
|
||||||
v: "2",
|
v: "1",
|
||||||
endpoint: "https://echo.hoppscotch.io",
|
endpoint: "https://echo.hoppscotch.io",
|
||||||
name: "Echo test",
|
name: "Echo test",
|
||||||
params: [],
|
params: [],
|
||||||
@@ -35,7 +35,6 @@ export const REST_COLLECTIONS_MOCK: HoppCollection[] = [
|
|||||||
preRequestScript: "",
|
preRequestScript: "",
|
||||||
testScript: "",
|
testScript: "",
|
||||||
body: { contentType: null, body: null },
|
body: { contentType: null, body: null },
|
||||||
requestVariables: [],
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
auth: { authType: "none", authActive: true },
|
auth: { authType: "none", authActive: true },
|
||||||
@@ -137,8 +136,7 @@ export const REST_HISTORY_MOCK: RESTHistoryEntry[] = [
|
|||||||
params: [],
|
params: [],
|
||||||
preRequestScript: "",
|
preRequestScript: "",
|
||||||
testScript: "",
|
testScript: "",
|
||||||
requestVariables: [],
|
v: "1",
|
||||||
v: "2",
|
|
||||||
},
|
},
|
||||||
responseMeta: { duration: 807, statusCode: 200 },
|
responseMeta: { duration: 807, statusCode: 200 },
|
||||||
star: false,
|
star: false,
|
||||||
@@ -194,7 +192,7 @@ export const REST_TAB_STATE_MOCK: PersistableTabState<HoppRESTDocument> = {
|
|||||||
tabID: "e6e8d800-caa8-44a2-a6a6-b4765a3167aa",
|
tabID: "e6e8d800-caa8-44a2-a6a6-b4765a3167aa",
|
||||||
doc: {
|
doc: {
|
||||||
request: {
|
request: {
|
||||||
v: "2",
|
v: "1",
|
||||||
endpoint: "https://echo.hoppscotch.io",
|
endpoint: "https://echo.hoppscotch.io",
|
||||||
name: "Echo test",
|
name: "Echo test",
|
||||||
params: [],
|
params: [],
|
||||||
@@ -204,7 +202,6 @@ export const REST_TAB_STATE_MOCK: PersistableTabState<HoppRESTDocument> = {
|
|||||||
preRequestScript: "",
|
preRequestScript: "",
|
||||||
testScript: "",
|
testScript: "",
|
||||||
body: { contentType: null, body: null },
|
body: { contentType: null, body: null },
|
||||||
requestVariables: [],
|
|
||||||
},
|
},
|
||||||
isDirty: false,
|
isDirty: false,
|
||||||
saveContext: {
|
saveContext: {
|
||||||
|
|||||||
@@ -48,22 +48,21 @@ const SettingsDefSchema = z.object({
|
|||||||
|
|
||||||
WRAP_LINES: z.optional(
|
WRAP_LINES: z.optional(
|
||||||
z.object({
|
z.object({
|
||||||
httpRequestBody: z.boolean().catch(true),
|
httpRequestBody: z.boolean(),
|
||||||
httpResponseBody: z.boolean().catch(true),
|
httpResponseBody: z.boolean(),
|
||||||
httpHeaders: z.boolean().catch(true),
|
httpHeaders: z.boolean(),
|
||||||
httpParams: z.boolean().catch(true),
|
httpParams: z.boolean(),
|
||||||
httpUrlEncoded: z.boolean().catch(true),
|
httpUrlEncoded: z.boolean(),
|
||||||
httpPreRequest: z.boolean().catch(true),
|
httpPreRequest: z.boolean(),
|
||||||
httpTest: z.boolean().catch(true),
|
httpTest: z.boolean(),
|
||||||
httpRequestVariables: z.boolean().catch(true),
|
graphqlQuery: z.boolean(),
|
||||||
graphqlQuery: z.boolean().catch(true),
|
graphqlResponseBody: z.boolean(),
|
||||||
graphqlResponseBody: z.boolean().catch(true),
|
graphqlHeaders: z.boolean(),
|
||||||
graphqlHeaders: z.boolean().catch(false),
|
graphqlVariables: z.boolean(),
|
||||||
graphqlVariables: z.boolean().catch(false),
|
graphqlSchema: z.boolean(),
|
||||||
graphqlSchema: z.boolean().catch(true),
|
importCurl: z.boolean(),
|
||||||
importCurl: z.boolean().catch(true),
|
codeGen: z.boolean(),
|
||||||
codeGen: z.boolean().catch(true),
|
cookie: z.boolean(),
|
||||||
cookie: z.boolean().catch(true),
|
|
||||||
})
|
})
|
||||||
),
|
),
|
||||||
})
|
})
|
||||||
@@ -515,7 +514,6 @@ const validRestOperations = [
|
|||||||
"authorization",
|
"authorization",
|
||||||
"preRequestScript",
|
"preRequestScript",
|
||||||
"tests",
|
"tests",
|
||||||
"requestVariables",
|
|
||||||
] as const
|
] as const
|
||||||
|
|
||||||
export const REST_TAB_STATE_SCHEMA = z
|
export const REST_TAB_STATE_SCHEMA = z
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ import * as S from "fp-ts/string"
|
|||||||
import cloneDeep from "lodash/cloneDeep"
|
import cloneDeep from "lodash/cloneDeep"
|
||||||
import V0_VERSION from "./v/0"
|
import V0_VERSION from "./v/0"
|
||||||
import V1_VERSION from "./v/1"
|
import V1_VERSION from "./v/1"
|
||||||
import V2_VERSION from "./v/2"
|
|
||||||
import { createVersionedEntity, InferredEntity } from "verzod"
|
import { createVersionedEntity, InferredEntity } from "verzod"
|
||||||
import { lodashIsEqualEq, mapThenEq, undefinedEq } from "../utils/eq"
|
import { lodashIsEqualEq, mapThenEq, undefinedEq } from "../utils/eq"
|
||||||
import {
|
import {
|
||||||
@@ -12,7 +11,6 @@ import {
|
|||||||
HoppRESTHeaders,
|
HoppRESTHeaders,
|
||||||
HoppRESTParams,
|
HoppRESTParams,
|
||||||
} from "./v/1"
|
} from "./v/1"
|
||||||
import { HoppRESTRequestVariables } from "./v/2"
|
|
||||||
import { z } from "zod"
|
import { z } from "zod"
|
||||||
|
|
||||||
export * from "./content-types"
|
export * from "./content-types"
|
||||||
@@ -30,19 +28,16 @@ export {
|
|||||||
HoppRESTHeaders,
|
HoppRESTHeaders,
|
||||||
} from "./v/1"
|
} from "./v/1"
|
||||||
|
|
||||||
export { HoppRESTRequestVariables } from "./v/2"
|
|
||||||
|
|
||||||
const versionedObject = z.object({
|
const versionedObject = z.object({
|
||||||
// v is a stringified number
|
// v is a stringified number
|
||||||
v: z.string().regex(/^\d+$/).transform(Number),
|
v: z.string().regex(/^\d+$/).transform(Number),
|
||||||
})
|
})
|
||||||
|
|
||||||
export const HoppRESTRequest = createVersionedEntity({
|
export const HoppRESTRequest = createVersionedEntity({
|
||||||
latestVersion: 2,
|
latestVersion: 1,
|
||||||
versionMap: {
|
versionMap: {
|
||||||
0: V0_VERSION,
|
0: V0_VERSION,
|
||||||
1: V1_VERSION,
|
1: V1_VERSION,
|
||||||
2: V2_VERSION,
|
|
||||||
},
|
},
|
||||||
getVersion(data) {
|
getVersion(data) {
|
||||||
// For V1 onwards we have the v string storing the number
|
// For V1 onwards we have the v string storing the number
|
||||||
@@ -78,18 +73,12 @@ const HoppRESTRequestEq = Eq.struct<HoppRESTRequest>({
|
|||||||
name: S.Eq,
|
name: S.Eq,
|
||||||
preRequestScript: S.Eq,
|
preRequestScript: S.Eq,
|
||||||
testScript: S.Eq,
|
testScript: S.Eq,
|
||||||
requestVariables: mapThenEq(
|
|
||||||
(arr) => arr.filter((v: any) => v.key !== "" && v.value !== ""),
|
|
||||||
lodashIsEqualEq
|
|
||||||
),
|
|
||||||
})
|
})
|
||||||
|
|
||||||
export const RESTReqSchemaVersion = "2"
|
export const RESTReqSchemaVersion = "1"
|
||||||
|
|
||||||
export type HoppRESTParam = HoppRESTRequest["params"][number]
|
export type HoppRESTParam = HoppRESTRequest["params"][number]
|
||||||
export type HoppRESTHeader = HoppRESTRequest["headers"][number]
|
export type HoppRESTHeader = HoppRESTRequest["headers"][number]
|
||||||
export type HoppRESTRequestVariable =
|
|
||||||
HoppRESTRequest["requestVariables"][number]
|
|
||||||
|
|
||||||
export const isEqualHoppRESTRequest = HoppRESTRequestEq.equals
|
export const isEqualHoppRESTRequest = HoppRESTRequestEq.equals
|
||||||
|
|
||||||
@@ -155,14 +144,6 @@ export function safelyExtractRESTRequest(
|
|||||||
req.headers = result.data
|
req.headers = result.data
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ("requestVariables" in x) {
|
|
||||||
const result = HoppRESTRequestVariables.safeParse(x.requestVariables)
|
|
||||||
|
|
||||||
if (result.success) {
|
|
||||||
req.requestVariables = result.data
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return req
|
return req
|
||||||
@@ -179,7 +160,7 @@ export function makeRESTRequest(
|
|||||||
|
|
||||||
export function getDefaultRESTRequest(): HoppRESTRequest {
|
export function getDefaultRESTRequest(): HoppRESTRequest {
|
||||||
return {
|
return {
|
||||||
v: "2",
|
v: "1",
|
||||||
endpoint: "https://echo.hoppscotch.io",
|
endpoint: "https://echo.hoppscotch.io",
|
||||||
name: "Untitled",
|
name: "Untitled",
|
||||||
params: [],
|
params: [],
|
||||||
@@ -195,7 +176,6 @@ export function getDefaultRESTRequest(): HoppRESTRequest {
|
|||||||
contentType: null,
|
contentType: null,
|
||||||
body: null,
|
body: null,
|
||||||
},
|
},
|
||||||
requestVariables: [],
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -141,7 +141,7 @@ export const HoppRESTHeaders = z.array(
|
|||||||
|
|
||||||
export type HoppRESTHeaders = z.infer<typeof HoppRESTHeaders>
|
export type HoppRESTHeaders = z.infer<typeof HoppRESTHeaders>
|
||||||
|
|
||||||
export const V1_SCHEMA = z.object({
|
const V1_SCHEMA = z.object({
|
||||||
v: z.literal("1"),
|
v: z.literal("1"),
|
||||||
id: z.optional(z.string()), // Firebase Firestore ID
|
id: z.optional(z.string()), // Firebase Firestore ID
|
||||||
|
|
||||||
@@ -158,7 +158,7 @@ export const V1_SCHEMA = z.object({
|
|||||||
body: HoppRESTReqBody,
|
body: HoppRESTReqBody,
|
||||||
})
|
})
|
||||||
|
|
||||||
export function parseRequestBody(
|
function parseRequestBody(
|
||||||
x: z.infer<typeof V0_SCHEMA>
|
x: z.infer<typeof V0_SCHEMA>
|
||||||
): z.infer<typeof V1_SCHEMA>["body"] {
|
): z.infer<typeof V1_SCHEMA>["body"] {
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -1,50 +0,0 @@
|
|||||||
import { defineVersion } from "verzod"
|
|
||||||
import { z } from "zod"
|
|
||||||
import {
|
|
||||||
HoppRESTAuth,
|
|
||||||
HoppRESTHeaders,
|
|
||||||
HoppRESTParams,
|
|
||||||
HoppRESTReqBody,
|
|
||||||
} from "./1"
|
|
||||||
import { V1_SCHEMA } from "./1"
|
|
||||||
|
|
||||||
export const HoppRESTRequestVariables = z.array(
|
|
||||||
z.object({
|
|
||||||
key: z.string().catch(""),
|
|
||||||
value: z.string().catch(""),
|
|
||||||
active: z.boolean().catch(true),
|
|
||||||
})
|
|
||||||
)
|
|
||||||
|
|
||||||
export type HoppRESTRequestVariables = z.infer<typeof HoppRESTRequestVariables>
|
|
||||||
|
|
||||||
const V2_SCHEMA = z.object({
|
|
||||||
v: z.literal("2"),
|
|
||||||
id: z.optional(z.string()), // Firebase Firestore ID
|
|
||||||
|
|
||||||
name: z.string(),
|
|
||||||
method: z.string(),
|
|
||||||
endpoint: z.string(),
|
|
||||||
params: HoppRESTParams,
|
|
||||||
headers: HoppRESTHeaders,
|
|
||||||
preRequestScript: z.string().catch(""),
|
|
||||||
testScript: z.string().catch(""),
|
|
||||||
|
|
||||||
auth: HoppRESTAuth,
|
|
||||||
|
|
||||||
body: HoppRESTReqBody,
|
|
||||||
|
|
||||||
requestVariables: HoppRESTRequestVariables,
|
|
||||||
})
|
|
||||||
|
|
||||||
export default defineVersion({
|
|
||||||
initial: false,
|
|
||||||
schema: V2_SCHEMA,
|
|
||||||
up(old: z.infer<typeof V1_SCHEMA>) {
|
|
||||||
return {
|
|
||||||
...old,
|
|
||||||
v: "2",
|
|
||||||
requestVariables: [],
|
|
||||||
} as z.infer<typeof V2_SCHEMA>
|
|
||||||
},
|
|
||||||
})
|
|
||||||
@@ -133,7 +133,6 @@ function exportedCollectionToHoppCollection(
|
|||||||
params,
|
params,
|
||||||
preRequestScript,
|
preRequestScript,
|
||||||
testScript,
|
testScript,
|
||||||
requestVariables,
|
|
||||||
}) => ({
|
}) => ({
|
||||||
id,
|
id,
|
||||||
v,
|
v,
|
||||||
@@ -146,7 +145,6 @@ function exportedCollectionToHoppCollection(
|
|||||||
params,
|
params,
|
||||||
preRequestScript,
|
preRequestScript,
|
||||||
testScript,
|
testScript,
|
||||||
requestVariables,
|
|
||||||
})
|
})
|
||||||
),
|
),
|
||||||
auth: data.auth,
|
auth: data.auth,
|
||||||
|
|||||||
Reference in New Issue
Block a user