CVE-2024-34347: Insufficient Information (NVD-CWE-noinfo)
value: @hoppscotch/cli is a CLI to run Hoppscotch Test Scripts in CI environments. Prior to 0.8.0, the @hoppscotch/js-sandbox package provides a Javascript sandbox that uses the Node.js vm module. However, the vm module is not safe for sandboxing untrusted Javascript code. This is because code inside the vm context can break out if it can get a hold of any reference to an object created outside of the vm. In the case of @hoppscotch/js-sandbox, multiple references to external objects are passed into the vm context to allow pre-request scripts interactions with environment variables and more. But this also allows the pre-request script to escape the sandbox. This vulnerability is fixed in 0.8.0.
CWE description: There is insufficient information about the issue to classify it; details are unkown or unspecified.
Published: 2024-05-08T15:15Z
Repository: https://github.com/hoppscotch/hoppscotch
Language: TypeScript
Files changed: .github/workflows/tests.yml, packages/hoppscotch-cli/bin/hopp.js, packages/hoppscotch-cli/package.json, packages/hoppscotch-cli/src/__tests__/commands/test.spec.ts, packages/hoppscotch-cli/src/__tests__/samples/collections/coll-v1-req-v0.json, packages/hoppscotch-cli/src/__tests__/samples/collections/coll-v1-req-v1.json, packages/hoppscotch-cli/src/__tests__/samples/collections/coll-v2-req-v2.json, packages/hoppscotch-cli/src/__tests__/samples/collections/coll-v2-req-v3.json, packages/hoppscotch-cli/src/__tests__/samples/collections/secret-envs-coll.json, packages/hoppscotch-cli/src/__tests__/samples/collections/secret-envs-persistence-coll.json, packages/hoppscotch-cli/src/__tests__/samples/collections/secret-envs-persistence-scripting-coll.json, packages/hoppscotch-cli/src/__tests__/samples/environments/secret-envs.json, packages/hoppscotch-cli/src/__tests__/samples/environments/secret-supplied-values-envs.json, packages/hoppscotch-cli/src/__tests__/utils.ts, packages/hoppscotch-cli/src/index.ts, packages/hoppscotch-cli/src/utils/mutators.ts, packages/hoppscotch-js-sandbox/node.d.ts, packages/hoppscotch-js-sandbox/package.json, packages/hoppscotch-js-sandbox/setupFiles.ts, packages/hoppscotch-js-sandbox/src/__tests__/base64-helper-functions.spec.ts, packages/hoppscotch-js-sandbox/src/__tests__/env/get.spec.ts, packages/hoppscotch-js-sandbox/src/__tests__/env/getResolve.spec.ts, packages/hoppscotch-js-sandbox/src/__tests__/env/resolve.spec.ts, packages/hoppscotch-js-sandbox/src/__tests__/env/set.spec.ts, packages/hoppscotch-js-sandbox/src/__tests__/env/unset.spec.ts, packages/hoppscotch-js-sandbox/src/__tests__/expect/toBe.spec.ts, packages/hoppscotch-js-sandbox/src/__tests__/expect/toBeLevelxxx.spec.ts, packages/hoppscotch-js-sandbox/src/__tests__/expect/toBeType.spec.ts, packages/hoppscotch-js-sandbox/src/__tests__/expect/toHaveLength.spec.ts, packages/hoppscotch-js-sandbox/src/__tests__/expect/toInclude.spec.ts, packages/hoppscotch-js-sandbox/src/__tests__/pre-request.spec.ts, packages/hoppscotch-js-sandbox/src/__tests__/shared-utils.spec.ts, packages/hoppscotch-js-sandbox/src/__tests__/test-runner.spec.ts, packages/hoppscotch-js-sandbox/src/node/index.ts, packages/hoppscotch-js-sandbox/src/node/pre-request.ts, packages/hoppscotch-js-sandbox/src/node/test-runner.ts, packages/hoppscotch-js-sandbox/src/node/utils.ts, packages/hoppscotch-js-sandbox/src/shared-utils.ts, packages/hoppscotch-js-sandbox/src/web/index.ts, packages/hoppscotch-js-sandbox/src/web/pre-request/worker.ts, packages/hoppscotch-js-sandbox/src/web/test-runner/worker.ts, packages/hoppscotch-js-sandbox/vite.config.ts, packages/hoppscotch-js-sandbox/web.d.ts, pnpm-lock.yaml
Commit date: 2024-04-19 21:08:46 +0530
Commit message: chore: migrate `Node.js` implementation for `js-sandbox` to `isolated-vm` (#3973)

Co-authored-by: Andrew Bastin <andrewbastin.k@gmail.com>
Diff: diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index 9a2af6430..00cb46d6f 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -15,24 +15,23 @@ jobs:
       matrix:
         node-version: ["lts/*"]
 
     steps:
       - name: Checkout
-        uses: actions/checkout@v3
+        uses: actions/checkout@v4
 
       - name: Setup environment
         run: mv .env.example .env
 
+      - name: Setup node
+        uses: actions/setup-node@v4
+        with:
+          node-version: ${{ matrix.node-version }}
+
       - name: Setup pnpm
-        uses: pnpm/action-setup@v2.2.4
+        uses: pnpm/action-setup@v3
         with:
           version: 8
           run_install: true
 
-      - name: Setup node
-        uses: actions/setup-node@v3
-        with:
-          node-version: ${{ matrix.node }}
-          cache: pnpm
-
       - name: Run tests
         run: pnpm test
diff --git a/packages/hoppscotch-cli/bin/hopp.js b/packages/hoppscotch-cli/bin/hopp.js
index 06750bef9..2a5e91a60 100755
--- a/packages/hoppscotch-cli/bin/hopp.js
+++ b/packages/hoppscotch-cli/bin/hopp.js
@@ -1,6 +1,31 @@
 #!/usr/bin/env node
 // * The entry point of the CLI
+// @ts-check
 
 import { cli } from "../dist/index.js";
 
-cli(process.argv);
+import { spawnSync } from "child_process";
+import { cloneDeep } from "lodash-es";
+
+const nodeVersion = parseInt(process.versions.node.split(".")[0]);
+
+// As per isolated-vm documentation, we need to supply `--no-node-snapshot` for node >= 20
+// src: https://github.com/laverdet/isolated-vm?tab=readme-ov-file#requirements
+if (nodeVersion >= 20 && !process.execArgv.includes("--no-node-snapshot")) {
+  const argCopy = cloneDeep(process.argv);
+
+  // Replace first argument with --no-node-snapshot
+  // We can get argv[0] from process.argv0
+  argCopy[0] = "--no-node-snapshot";
+
+  const result = spawnSync(
+    process.argv0,
+    argCopy,
+    { stdio: "inherit" }
+  );
+
+  // Exit with the same status code as the spawned process
+  process.exit(result.status ?? 0);
+} else {
+  cli(process.argv);
+}
diff --git a/packages/hoppscotch-cli/package.json b/packages/hoppscotch-cli/package.json
index 33892bcd5..2a6ea7d30 100644
--- a/packages/hoppscotch-cli/package.json
+++ b/packages/hoppscotch-cli/package.json
@@ -1,8 +1,8 @@
 {
   "name": "@hoppscotch/cli",
-  "version": "0.7.0",
+  "version": "0.7.1",
   "description": "A CLI to run Hoppscotch test scripts in CI environments.",
   "homepage": "https://hoppscotch.io",
   "type": "module",
   "main": "dist/index.js",
   "bin": {
@@ -42,10 +42,11 @@
   "private": false,
   "dependencies": {
     "axios": "1.6.7",
     "chalk": "5.3.0",
     "commander": "11.1.0",
+    "isolated-vm": "4.7.2",
     "lodash-es": "4.17.21",
     "qs": "6.11.2",
     "verzod": "0.2.2",
     "zod": "3.22.4"
   },
diff --git a/packages/hoppscotch-cli/src/__tests__/commands/test.spec.ts b/packages/hoppscotch-cli/src/__tests__/commands/test.spec.ts
index 25b3325d2..e65fac753 100644
--- a/packages/hoppscotch-cli/src/__tests__/commands/test.spec.ts
+++ b/packages/hoppscotch-cli/src/__tests__/commands/test.spec.ts
@@ -222,11 +222,11 @@ describe("Test `hopp test <file> --env <file>` command:", () => {
     const { error } = await runCLI(args);
     expect(error).toBeNull();
   });
 
   describe("Secret environment variables", () => {
-    jest.setTimeout(10000);
+    jest.setTimeout(100000);
 
     // Reads secret environment values from system environment
     test("Successfully picks the values for secret environment variables from `process.env` and persists the variables set from the pre-request script", async () => {
       const env = {
         ...process.env,
diff --git a/packages/hoppscotch-cli/src/__tests__/samples/collections/coll-v1-req-v0.json b/packages/hoppscotch-cli/src/__tests__/samples/collections/coll-v1-req-v0.json
index 6393ba6ad..bf63d2ae1 100644
--- a/packages/hoppscotch-cli/src/__tests__/samples/collections/coll-v1-req-v0.json
+++ b/packages/hoppscotch-cli/src/__tests__/samples/collections/coll-v1-req-v0.json
@@ -1,27 +1,55 @@
 {
-    "v": 1,
-    "name": "coll-v1",
-    "folders": [],
-    "requests": [
+  "v": 1,
+  "name": "coll-v1",
+  "folders": [
+    {
+      "v": 1,
+      "name": "coll-v1-child",
+      "folders": [],
+      "requests": [
         {
-            "url": "https://httpbin.org",
-            "path": "/get",
-            "headers": [
-              { "key": "Inactive-Header", "value": "Inactive Header", "active": false },
-              { "key": "Authorization", "value": "Bearer token123", "active": true }
-            ],
-            "params": [
-              { "key": "key", "value": "value", "active": true },
-              { "key": "inactive-key", "value": "inactive-param", "active": false }
-            ],
-            "name": "req-v0",
-            "method": "GET",
-            "preRequestScript": "",
-            "testScript": "pw.test(\"Asserts request params\", () => {\n  pw.expect(pw.response.body.args.key).toBe(\"value\")\n  pw.expect(pw.response.body.args[\"inactive-key\"]).toBe(undefined)\n})\n\npw.test(\"Asserts request headers\", () => {\n  pw.expect(pw.response.body.headers[\"Authorization\"]).toBe(\"Bearer token123\")\n  pw.expect(pw.response.body.headers[\"Inactive-Header\"]).toBe(undefined)\n})",
-            "contentType": "application/json",
-            "body": "",
-            "auth": "Bearer Token",
-            "bearerToken": "token123"
-          }
-    ]
-}
\ No newline at end of file
+          "url": "https://echo.hoppscotch.io",
+          "path": "/get",
+          "headers": [
+            { "key": "Inactive-Header", "value": "Inactive Header", "active": false },
+            { "key": "Authorization", "value": "Bearer token123", "active": true }
+          ],
+          "params": [
+            { "key": "key", "value": "value", "active": true },
+            { "key": "inactive-key", "value": "inactive-param", "active": false }
+          ],
+          "name": "req-v0-II",
+          "method": "GET",
+          "preRequestScript": "",
+          "testScript": "pw.test(\"Asserts request params\", () => {\n  pw.expect(pw.response.body.args.key).toBe(\"value\")\n  pw.expect(pw.response.body.args[\"inactive-key\"]).toBe(undefined)\n})\n\npw.test(\"Asserts request headers\", () => {\n  pw.expect(pw.response.body.headers[\"authorization\"]).toBe(\"Bearer token123\")\n  pw.expect(pw.response.body.headers[\"inactive-header\"]).toBe(undefined)\n})",
+          "contentType": "application/json",
+          "body": "",
+          "auth": "Bearer Token",
+          "bearerToken": "token123"
+        }
+      ]
+    }
+  ],
+  "requests": [
+    {
+      "url": "https://echo.hoppscotch.io",
+      "path": "/get",
+      "headers": [
+        { "key": "Inactive-Header", "value": "Inactive Header", "active": false },
+        { "key": "Authorization", "value": "Bearer token123", "active": true }
+      ],
+      "params": [
+        { "key": "key", "value": "value", "active": true },
+        { "key": "inactive-key", "value": "inactive-param", "active": false }
+      ],
+      "name": "req-v0",
+      "method": "GET",
+      "preRequestScript": "",
+      "testScript": "pw.test(\"Asserts request params\", () => {\n  pw.expect(pw.response.body.args.key).toBe(\"value\")\n  pw.expect(pw.response.body.args[\"inactive-key\"]).toBe(undefined)\n})\n\npw.test(\"Asserts request headers\", () => {\n  pw.expect(pw.response.body.headers[\"authorization\"]).toBe(\"Bearer token123\")\n  pw.expect(pw.response.body.headers[\"inactive-header\"]).toBe(undefined)\n})",
+      "contentType": "application/json",
+      "body": "",
+      "auth": "Bearer Token",
+      "bearerToken": "token123"
+    }
+  ]
+}
diff --git a/packages/hoppscotch-cli/src/__tests__/samples/collections/coll-v1-req-v1.json b/packages/hoppscotch-cli/src/__tests__/samples/collections/coll-v1-req-v1.json
index 61f9adb52..9bfc979e8 100644
--- a/packages/hoppscotch-cli/src/__tests__/samples/collections/coll-v1-req-v1.json
+++ b/packages/hoppscotch-cli/src/__tests__/samples/collections/coll-v1-req-v1.json
@@ -1,13 +1,62 @@
 {
     "v": 1,
     "name": "coll-v1",
-    "folders": [],
+    "folders": [
+        {
+            "v": 1,
+            "name": "coll-v1-child",
+            "folders": [],
+            "requests": [
+                {
+                    "v": "1",
+                    "endpoint": "https://echo.hoppscotch.io",
+                    "headers": [
+                        {
+                            "key": "Inactive-Header",
+                            "value": "Inactive Header",
+                            "active": false
+                        },
+                        {
+                            "key": "Authorization",
+                            "value": "Bearer token123",
+                            "active": true
+                        }
+                    ],
+                    "params": [
+                        {
+                            "key": "key",
+                            "value": "value",
+                            "active": true
+                        },
+                        {
+                            "key": "inactive-key",
+                            "value": "inactive-param",
+                            "active": false
+                        }
+                    ],
+                    "name": "req-v1-II",
+                    "method": "GET",
+                    "preRequestScript": "",
+                    "testScript": "pw.test(\"Asserts request params\", () => {\n  pw.expect(pw.response.body.args.key).toBe(\"value\")\n  pw.expect(pw.response.body.args[\"inactive-key\"]).toBe(undefined)\n})\n\npw.test(\"Asserts request headers\", () => {\n  pw.expect(pw.response.body.headers[\"authorization\"]).toBe(\"Bearer token123\")\n  pw.expect(pw.response.body.headers[\"inactive-header\"]).toBe(undefined)\n})",
+                    "body": {
+                        "contentType": null,
+                        "body": null
+                    },
+                    "auth": {
+                        "authType": "bearer",
+                        "authActive": true,
+                        "token": "token123"
+                    }
+                }
+            ]
+        }
+    ],
     "requests": [
         {
             "v": "1",
-            "endpoint": "https://httpbin.org/get",
+            "endpoint": "https://echo.hoppscotch.io",
             "headers": [
                 {
                     "key": "Inactive-Header",
                     "value": "Inactive Header",
                     "active": false
@@ -31,11 +80,11 @@
                 }
             ],
             "name": "req-v1",
             "method": "GET",
             "preRequestScript": "",
-            "testScript": "pw.test(\"Asserts request params\", () => {\n  pw.expect(pw.response.body.args.key).toBe(\"value\")\n  pw.expect(pw.response.body.args[\"inactive-key\"]).toBe(undefined)\n})\n\npw.test(\"Asserts request headers\", () => {\n  pw.expect(pw.response.body.headers[\"Authorization\"]).toBe(\"Bearer token123\")\n  pw.expect(pw.response.body.headers[\"Inactive-Header\"]).toBe(undefined)\n})",
+            "testScript": "pw.test(\"Asserts request params\", () => {\n  pw.expect(pw.response.body.args.key).toBe(\"value\")\n  pw.expect(pw.response.body.args[\"inactive-key\"]).toBe(undefined)\n})\n\npw.test(\"Asserts request headers\", () => {\n  pw.expect(pw.response.body.headers[\"authorization\"]).toBe(\"Bearer token123\")\n  pw.expect(pw.response.body.headers[\"inactive-header\"]).toBe(undefined)\n})",
             "body": {
                 "contentType": null,
                 "body": null
             },
             "auth": {
diff --git a/packages/hoppscotch-cli/src/__tests__/samples/collections/coll-v2-req-v2.json b/packages/hoppscotch-cli/src/__tests__/samples/collections/coll-v2-req-v2.json
index 780373f82..0bcbd1321 100644
--- a/packages/hoppscotch-cli/src/__tests__/samples/collections/coll-v2-req-v2.json
+++ b/packages/hoppscotch-cli/src/__tests__/samples/collections/coll-v2-req-v2.json
@@ -1,13 +1,68 @@
 {
     "v": 2,
     "name": "coll-v2",
-    "folders": [],
+    "folders": [
+        {
+            "v": 2,
+            "name": "coll-v2-child",
+            "folders": [],
+            "requests": [
+                {
+                    "v": "2",
+                    "endpoint": "https://echo.hoppscotch.io",
+                    "headers": [
+                        {
+                            "key": "Inactive-Header",
+                            "value": "Inactive Header",
+                            "active": false
+                        },
+                        {
+                            "key": "Authorization",
+                            "value": "Bearer token123",
+                            "active": true
+                        }
+                    ],
+                    "params": [
+                        {
+                            "key": "key",
+                            "value": "value",
+                            "active": true
+                        },
+                        {
+                            "key": "inactive-key",
+                            "value": "inactive-param",
+                            "active": false
+                        }
+                    ],
+                    "name": "req-v2-II",
+                    "method": "GET",
+                    "preRequestScript": "",
+                    "testScript": "pw.test(\"Asserts request params\", () => {\n  pw.expect(pw.response.body.args.key).toBe(\"value\")\n  pw.expect(pw.response.body.args[\"inactive-key\"]).toBe(undefined)\n})\n\npw.test(\"Asserts request headers\", () => {\n  pw.expect(pw.response.body.headers[\"authorization\"]).toBe(\"Bearer token123\")\n  pw.expect(pw.response.body.headers[\"inactive-header\"]).toBe(undefined)\n})",
+                    "body": {
+                        "contentType": null,
+                        "body": null
+                    },
+                    "auth": {
+                        "authType": "bearer",
+                        "authActive": true,
+                        "token": "token123"
+                    },
+                    "requestVariables": []
+                }
+            ],
+            "auth": {
+                "authType": "inherit",
+                "authActive": true
+            },
+            "headers": []
+        }
+    ],
     "requests": [
         {
             "v": "2",
-            "endpoint": "https://httpbin.org/get",
+            "endpoint": "https://echo.hoppscotch.io",
             "headers": [
                 {
                     "key": "Inactive-Header",
                     "value": "Inactive Header",
                     "active": false
@@ -31,11 +86,11 @@
                 }
             ],
             "name": "req-v2",
             "method": "GET",
             "preRequestScript": "",
-            "testScript": "pw.test(\"Asserts request params\", () => {\n  pw.expect(pw.response.body.args.key).toBe(\"value\")\n  pw.expect(pw.response.body.args[\"inactive-key\"]).toBe(undefined)\n})\n\npw.test(\"Asserts request headers\", () => {\n  pw.expect(pw.response.body.headers[\"Authorization\"]).toBe(\"Bearer token123\")\n  pw.expect(pw.response.body.headers[\"Inactive-Header\"]).toBe(undefined)\n})",
+            "testScript": "pw.test(\"Asserts request params\", () => {\n  pw.expect(pw.response.body.args.key).toBe(\"value\")\n  pw.expect(pw.response.body.args[\"inactive-key\"]).toBe(undefined)\n})\n\npw.test(\"Asserts request headers\", () => {\n  pw.expect(pw.response.body.headers[\"authorization\"]).toBe(\"Bearer token123\")\n  pw.expect(pw.response.body.headers[\"inactive-header\"]).toBe(undefined)\n})",
             "body": {
                 "contentType": null,
                 "body": null
             },
             "auth": {
diff --git a/packages/hoppscotch-cli/src/__tests__/samples/collections/coll-v2-req-v3.json b/packages/hoppscotch-cli/src/__tests__/samples/collections/coll-v2-req-v3.json
index fcce134a8..916e809db 100644
--- a/packages/hoppscotch-cli/src/__tests__/samples/collections/coll-v2-req-v3.json
+++ b/packages/hoppscotch-cli/src/__tests__/samples/collections/coll-v2-req-v3.json
@@ -1,13 +1,68 @@
 {
     "v": 2,
     "name": "coll-v2",
-    "folders": [],
+    "folders": [
+        {
+            "v": 2,
+            "name": "coll-v2-child",
+            "folders": [],
+            "requests": [
+                {
+                    "v": "3",
+                    "endpoint": "https://echo.hoppscotch.io",
+                    "headers": [
+                        {
+                            "key": "Inactive-Header",
+                            "value": "Inactive Header",
+                            "active": false
+                        },
+                        {
+                            "key": "Authorization",
+                            "value": "Bearer token123",
+                            "active": true
+                        }
+                    ],
+                    "params": [
+                        {
+                            "key": "key",
+                            "value": "value",
+                            "active": true
+                        },
+                        {
+                            "key": "inactive-key",
+                            "value": "inactive-param",
+                            "active": false
+                        }
+                    ],
+                    "name": "req-v3-II",
+                    "method": "GET",
+                    "preRequestScript": "",
+                    "testScript": "pw.test(\"Asserts request params\", () => {\n  pw.expect(pw.response.body.args.key).toBe(\"value\")\n  pw.expect(pw.response.body.args[\"inactive-key\"]).toBe(undefined)\n})\n\npw.test(\"Asserts request headers\", () => {\n  pw.expect(pw.response.body.headers[\"authorization\"]).toBe(\"Bearer token123\")\n  pw.expect(pw.response.body.headers[\"inactive-header\"]).toBe(undefined)\n})",
+                    "body": {
+                        "contentType": null,
+                        "body": null
+                    },
+                    "auth": {
+                        "authType": "bearer",
+                        "authActive": true,
+                        "token": "token123"
+                    },
+                    "requestVariables": []
+                }
+            ],
+            "auth": {
+                "authType": "inherit",
+                "authActive": true
+            },
+            "headers": []
+        }
+    ],
     "requests": [
         {
             "v": "3",
-            "endpoint": "https://httpbin.org/get",
+            "endpoint": "https://echo.hoppscotch.io",
             "headers": [
                 {
                     "key": "Inactive-Header",
                     "value": "Inactive Header",
                     "active": false
@@ -31,11 +86,11 @@
                 }
             ],
             "name": "req-v3",
             "method": "GET",
             "preRequestScript": "",
-            "testScript": "pw.test(\"Asserts request params\", () => {\n  pw.expect(pw.response.body.args.key).toBe(\"value\")\n  pw.expect(pw.response.body.args[\"inactive-key\"]).toBe(undefined)\n})\n\npw.test(\"Asserts request headers\", () => {\n  pw.expect(pw.response.body.headers[\"Authorization\"]).toBe(\"Bearer token123\")\n  pw.expect(pw.response.body.headers[\"Inactive-Header\"]).toBe(undefined)\n})",
+            "testScript": "pw.test(\"Asserts request params\", () => {\n  pw.expect(pw.response.body.args.key).toBe(\"value\")\n  pw.expect(pw.response.body.args[\"inactive-key\"]).toBe(undefined)\n})\n\npw.test(\"Asserts request headers\", () => {\n  pw.expect(pw.response.body.headers[\"authorization\"]).toBe(\"Bearer token123\")\n  pw.expect(pw.response.body.headers[\"inactive-header\"]).toBe(undefined)\n})",
             "body": {
                 "contentType": null,
                 "body": null
             },
             "auth": {
diff --git a/packages/hoppscotch-cli/src/__tests__/samples/collections/secret-envs-coll.json b/packages/hoppscotch-cli/src/__tests__/samples/collections/secret-envs-coll.json
index 2cea26e85..a79d5a23e 100644
--- a/packages/hoppscotch-cli/src/__tests__/samples/collections/secret-envs-coll.json
+++ b/packages/hoppscotch-cli/src/__tests__/samples/collections/secret-envs-coll.json
@@ -3,12 +3,18 @@
   "name": "secret-envs-coll",
   "folders": [],
   "requests": [
     {
       "v": "3",
-      "auth": { "authType": "none", "authActive": true },
-      "body": { "body": null, "contentType": null },
+      "auth": {
+        "authType": "none",
+        "authActive": true
+      },
+      "body": {
+        "body": null,
+        "contentType": null
+      },
       "name": "test-secret-headers",
       "method": "GET",
       "params": [],
       "headers": [
         {
@@ -16,34 +22,43 @@
           "value": "<<secretHeaderValue>>",
           "active": true
         }
       ],
       "requestVariables": [],
-      "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})",
+      "endpoint": "<<echoHoppBaseURL>>/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})",
       "preRequestScript": "const secretHeaderValueFromPreReqScript = pw.env.get(\"secretHeaderValue\")\npw.env.set(\"secretHeaderValueFromPreReqScript\", secretHeaderValueFromPreReqScript)"
     },
     {
       "v": "3",
-      "auth": { "authType": "none", "authActive": true },
+      "auth": {
+        "authType": "none",
+        "authActive": true
+      },
       "body": {
         "body": "{\n  \"secretBodyKey\": \"<<secretBodyValue>>\"\n}",
         "contentType": "application/json"
       },
       "name": "test-secret-body",
       "method": "POST",
       "params": [],
       "headers": [],
       "requestVariables": [],
-      "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})",
+      "endpoint": "<<echoHoppBaseURL>>/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(JSON.parse(pw.response.body.data).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)"
     },
     {
       "v": "3",
-      "auth": { "authType": "none", "authActive": true },
-      "body": { "body": null, "contentType": null },
+      "auth": {
+        "authType": "none",
+        "authActive": true
+      },
+      "body": {
+        "body": null,
+        "contentType": null
+      },
       "name": "test-secret-query-params",
       "method": "GET",
       "params": [
         {
           "key": "secretQueryParamKey",
@@ -51,11 +66,11 @@
           "active": true
         }
       ],
       "headers": [],
       "requestVariables": [],
-      "endpoint": "<<baseURL>>/get",
+      "endpoint": "<<echoHoppBaseURL>>",
       "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)"
     },
     {
       "v": "3",
@@ -63,18 +78,21 @@
         "authType": "basic",
         "password": "<<secretBasicAuthPassword>>",
         "username": "<<secretBasicAuthUsername>>",
         "authActive": true
       },
-      "body": { "body": null, "contentType": null },
+      "body": {
+        "body": null,
+        "contentType": null
+      },
       "name": "test-secret-basic-auth",
       "method": "GET",
       "params": [],
       "headers": [],
       "requestVariables": [],
-      "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});",
+      "endpoint": "<<httpbinBaseURL>>/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    // The endpoint at times results in a `502` bad gateway\n    if (pw.response.status !== 200) {\n      return\n    }\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": ""
     },
     {
       "v": "3",
       "auth": {
@@ -82,32 +100,44 @@
         "authType": "bearer",
         "password": "testpassword",
         "username": "testuser",
         "authActive": true
       },
-      "body": { "body": null, "contentType": null },
+      "body": {
+        "body": null,
+        "contentType": null
+      },
       "name": "test-secret-bearer-auth",
       "method": "GET",
       "params": [],
       "headers": [],
       "requestVariables": [],
-      "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});",
+      "endpoint": "<<httpbinBaseURL>>/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    // Safeguard to prevent test failures due to the endpoint\n    if (pw.response.status !== 200) {\n      return\n    }\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)"
     },
     {
       "v": "3",
-      "auth": { "authType": "none", "authActive": true },
-      "body": { "body": null, "contentType": null },
+      "auth": {
+        "authType": "none",
+        "authActive": true
+      },
+      "body": {
+        "body": null,
+        "contentType": null
+      },
       "name": "test-secret-fallback",
       "method": "GET",
       "params": [],
       "headers": [],
       "requestVariables": [],
-      "endpoint": "<<baseURL>>",
+      "endpoint": "<<echoHoppBaseURL>>",
       "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": ""
     }
   ],
-  "auth": { "authType": "inherit", "authActive": false },
+  "auth": {
+    "authType": "inherit",
+    "authActive": false
+  },
   "headers": []
-}
+}
\ No newline at end of file
diff --git a/packages/hoppscotch-cli/src/__tests__/samples/collections/secret-envs-persistence-coll.json b/packages/hoppscotch-cli/src/__tests__/samples/collections/secret-envs-persistence-coll.json
index 823eec801..1de038c5f 100644
--- a/packages/hoppscotch-cli/src/__tests__/samples/collections/secret-envs-persistence-coll.json
+++ b/packages/hoppscotch-cli/src/__tests__/samples/collections/secret-envs-persistence-coll.json
@@ -1,8 +1,8 @@
 {
   "v": 2,
-  "name": "secret-envs-setters-coll",
+  "name": "secret-envs-persistence-coll",
   "folders": [],
   "requests": [
     {
       "v": "3",
       "auth": {
@@ -22,12 +22,12 @@
           "key": "Secret-Header-Key",
           "value": "<<secretHeaderValue>>",
           "active": true
         }
       ],
-      "endpoint": "<<baseURL>>/headers",
-      "testScript": "pw.test(\"Successfully parses secret variable holding the header value\", () => {\n    const secretHeaderValue = pw.env.getResolve(\"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.getResolve(\"secretHeaderValueFromPreReqScript\")).toBe(\"secret-header-value\")\n})",
+      "endpoint": "<<echoHoppBaseURL>>",
+      "testScript": "pw.test(\"Successfully parses secret variable holding the header value\", () => {\n    const secretHeaderValue = pw.env.getResolve(\"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.getResolve(\"secretHeaderValueFromPreReqScript\")).toBe(\"secret-header-value\")\n})",
       "preRequestScript": "pw.env.set(\"secretHeaderValue\", \"secret-header-value\")\n\nconst secretHeaderValueFromPreReqScript = pw.env.getResolve(\"secretHeaderValue\")\npw.env.set(\"secretHeaderValueFromPreReqScript\", secretHeaderValueFromPreReqScript)"
     },
     {
       "v": "3",
       "auth": {
@@ -47,12 +47,12 @@
           "key": "Secret-Header-Key",
           "value": "<<secretHeaderValue>>",
           "active": true
         }
       ],
-      "endpoint": "<<baseURL>>/headers",
-      "testScript": "pw.test(\"Value set at the pre-request script takes precedence\", () => {\n    const secretHeaderValue = pw.env.getResolve(\"secretHeaderValue\")\n    pw.expect(secretHeaderValue).toBe(\"secret-header-value-overriden\")\n    \n    if (secretHeaderValue) {\n      pw.expect(pw.response.body.headers[\"Secret-Header-Key\"]).toBe(secretHeaderValue)\n    }\n\n    pw.expect(pw.env.getResolve(\"secretHeaderValueFromPreReqScript\")).toBe(\"secret-header-value-overriden\")\n})",
+      "endpoint": "<<echoHoppBaseURL>>",
+      "testScript": "pw.test(\"Value set at the pre-request script takes precedence\", () => {\n    const secretHeaderValue = pw.env.getResolve(\"secretHeaderValue\")\n    pw.expect(secretHeaderValue).toBe(\"secret-header-value-overriden\")\n    \n    if (secretHeaderValue) {\n      pw.expect(pw.response.body.headers[\"secret-header-key\"]).toBe(secretHeaderValue)\n    }\n\n    pw.expect(pw.env.getResolve(\"secretHeaderValueFromPreReqScript\")).toBe(\"secret-header-value-overriden\")\n})",
       "preRequestScript": "pw.env.set(\"secretHeaderValue\", \"secret-header-value-overriden\")\n\nconst secretHeaderValueFromPreReqScript = pw.env.getResolve(\"secretHeaderValue\")\npw.env.set(\"secretHeaderValueFromPreReqScript\", secretHeaderValueFromPreReqScript)"
     },
     {
       "v": "3",
       "auth": {
@@ -66,12 +66,12 @@
       "name": "test-secret-body",
       "method": "POST",
       "params": [],
       "requestVariables": [],
       "headers": [],
-      "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})",
+      "endpoint": "<<echoHoppBaseURL>>/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(JSON.parse(pw.response.body.data).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)"
     },
     {
       "v": "3",
       "auth": {
@@ -91,11 +91,11 @@
           "active": true
         }
       ],
       "requestVariables": [],
       "headers": [],
-      "endpoint": "<<baseURL>>/get",
+      "endpoint": "<<echoHoppBaseURL>>",
       "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)"
     },
     {
       "v": "3",
@@ -112,12 +112,12 @@
       "name": "test-secret-basic-auth",
       "method": "GET",
       "params": [],
       "requestVariables": [],
       "headers": [],
-      "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});",
+      "endpoint": "<<httpbinBaseURL>>/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    // The endpoint at times results in a `502` bad gateway\n    if (pw.response.status !== 200) {\n      return\n    }\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}"
     },
     {
       "v": "3",
       "auth": {
@@ -134,16 +134,16 @@
       "name": "test-secret-bearer-auth",
       "method": "GET",
       "params": [],
       "requestVariables": [],
       "headers": [],
-      "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});",
+      "endpoint": "<<httpbinBaseURL>>/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    // Safeguard to prevent test failures due to the endpoint\n    if (pw.response.status !== 200) {\n      return\n    }\n\n    if (secretBearerToken) { \n      pw.expect(pw.response.body.token).toBe(secretBearerToken)\n      pw.expect(preReqSecretBearerToken).toBe(\"test-token\")\n    }\n});",
       "preRequestScript": "let secretBearerToken = pw.env.resolve(\"<<secretBearerToken>>\")\n\nif (!secretBearerToken) {\n  pw.env.set(\"secretBearerToken\", \"test-token\")\n  secretBearerToken = pw.env.resolve(\"<<secretBearerToken>>\")\n}\n\npw.env.set(\"preReqSecretBearerToken\", secretBearerToken)"
     }
   ],
   "auth": {
     "authType": "inherit",
     "authActive": false
   },
   "headers": []
-}
+}
\ No newline at end of file
diff --git a/packages/hoppscotch-cli/src/__tests__/samples/collections/secret-envs-persistence-scripting-coll.json b/packages/hoppscotch-cli/src/__tests__/samples/collections/secret-envs-persistence-scripting-coll.json
index 61dc17cd2..6a103ed44 100644
--- a/packages/hoppscotch-cli/src/__tests__/samples/collections/secret-envs-persistence-scripting-coll.json
+++ b/packages/hoppscotch-cli/src/__tests__/samples/collections/secret-envs-persistence-scripting-coll.json
@@ -3,11 +3,11 @@
   "name": "secret-envs-persistence-scripting-req",
   "folders": [],
   "requests": [
     {
       "v": "3",
-      "endpoint": "https://httpbin.org/post",
+      "endpoint": "https://echo.hoppscotch.io/post",
       "name": "req",
       "params": [],
       "headers": [
         {
           "active": true,
@@ -16,11 +16,11 @@
         }
       ],
       "method": "POST",
       "auth": { "authType": "none", "authActive": true },
       "preRequestScript": "pw.env.set(\"preReqVarOne\", \"pre-req-value-one\")\n\npw.env.set(\"preReqVarTwo\", \"pre-req-value-two\")\n\npw.env.set(\"customHeaderValueFromSecretVar\", \"custom-header-secret-value\")\n\npw.env.set(\"customBodyValue\", \"custom-body-value\")",
-      "testScript": "pw.test(\"Secret environment value set from the pre-request script takes precedence\", () => {\n  pw.expect(pw.env.get(\"preReqVarOne\")).toBe(\"pre-req-value-one\")\n})\n\npw.test(\"Successfully sets initial value for the secret variable from the pre-request script\", () => {\n  pw.env.set(\"postReqVarTwo\", \"post-req-value-two\")\n  pw.expect(pw.env.get(\"postReqVarTwo\")).toBe(\"post-req-value-two\")\n})\n\npw.test(\"Successfully resolves secret variable values referred in request headers that are set in pre-request sccript\", () => {\n  pw.expect(pw.response.body.headers[\"Custom-Header\"]).toBe(\"custom-header-secret-value\")\n})\n\npw.test(\"Successfully resolves secret variable values referred in request body that are set in pre-request sccript\", () => {\n  pw.expect(pw.response.body.json.key).toBe(\"custom-body-value\")\n})\n\npw.test(\"Secret environment variable set from the post-request script takes precedence\", () => {\n  pw.env.set(\"postReqVarOne\", \"post-req-value-one\")\n  pw.expect(pw.env.get(\"postReqVarOne\")).toBe(\"post-req-value-one\")\n})\n\npw.test(\"Successfully sets initial value for the secret variable from the post-request script\", () => {\n  pw.env.set(\"postReqVarTwo\", \"post-req-value-two\")\n  pw.expect(pw.env.get(\"postReqVarTwo\")).toBe(\"post-req-value-two\")\n})\n\npw.test(\"Successfully removes environment variables via the pw.env.unset method\", () => {\n  pw.env.unset(\"preReqVarOne\")\n  pw.env.unset(\"postReqVarTwo\")\n\n  pw.expect(pw.env.get(\"preReqVarOne\")).toBe(undefined)\n  pw.expect(pw.env.get(\"postReqVarTwo\")).toBe(undefined)\n})",
+      "testScript": "pw.test(\"Secret environment value set from the pre-request script takes precedence\", () => {\n  pw.expect(pw.env.get(\"preReqVarOne\")).toBe(\"pre-req-value-one\")\n})\n\npw.test(\"Successfully sets initial value for the secret variable from the pre-request script\", () => {\n  pw.env.set(\"postReqVarTwo\", \"post-req-value-two\")\n  pw.expect(pw.env.get(\"postReqVarTwo\")).toBe(\"post-req-value-two\")\n})\n\npw.test(\"Successfully resolves secret variable values referred in request headers that are set in pre-request script\", () => {\n  pw.expect(pw.response.body.headers[\"custom-header\"]).toBe(\"custom-header-secret-value\")\n})\n\npw.test(\"Successfully resolves secret variable values referred in request body that are set in pre-request script\", () => {\n  pw.expect(JSON.parse(pw.response.body.data).key).toBe(\"custom-body-value\")\n})\n\npw.test(\"Secret environment variable set from the post-request script takes precedence\", () => {\n  pw.env.set(\"postReqVarOne\", \"post-req-value-one\")\n  pw.expect(pw.env.get(\"postReqVarOne\")).toBe(\"post-req-value-one\")\n})\n\npw.test(\"Successfully sets initial value for the secret variable from the post-request script\", () => {\n  pw.env.set(\"postReqVarTwo\", \"post-req-value-two\")\n  pw.expect(pw.env.get(\"postReqVarTwo\")).toBe(\"post-req-value-two\")\n})\n\npw.test(\"Successfully removes environment variables via the pw.env.unset method\", () => {\n  pw.env.unset(\"preReqVarOne\")\n  pw.env.unset(\"postReqVarTwo\")\n\n  pw.expect(pw.env.get(\"preReqVarOne\")).toBe(undefined)\n  pw.expect(pw.env.get(\"postReqVarTwo\")).toBe(undefined)\n})",
       "body": {
         "contentType": "application/json",
         "body": "{\n  \"key\": \"<<customBodyValue>>\"\n}"
       },
       "requestVariables": []
diff --git a/packages/hoppscotch-cli/src/__tests__/samples/environments/secret-envs.json b/packages/hoppscotch-cli/src/__tests__/samples/environments/secret-envs.json
index 53d33bb35..266f821c8 100644
--- a/packages/hoppscotch-cli/src/__tests__/samples/environments/secret-envs.json
+++ b/packages/hoppscotch-cli/src/__tests__/samples/environments/secret-envs.json
@@ -30,11 +30,16 @@
     {
       "key": "nonExistentValueInSystemEnv",
       "secret": true
     },
     {
-      "key": "baseURL",
+      "key": "echoHoppBaseURL",
+      "value": "https://echo.hoppscotch.io",
+      "secret": false
+    },
+    {
+      "key": "httpbinBaseURL",
       "value": "https://httpbin.org",
       "secret": false
     }
   ]
 }
diff --git a/packages/hoppscotch-cli/src/__tests__/samples/environments/secret-supplied-values-envs.json b/packages/hoppscotch-cli/src/__tests__/samples/environments/secret-supplied-values-envs.json
index fec73a293..88155f84e 100644
--- a/packages/hoppscotch-cli/src/__tests__/samples/environments/secret-supplied-values-envs.json
+++ b/packages/hoppscotch-cli/src/__tests__/samples/environments/secret-supplied-values-envs.json
@@ -36,11 +36,16 @@
     {
       "key": "nonExistentValueInSystemEnv",
       "secret": true
     },
     {
-      "key": "baseURL",
+      "key": "echoHoppBaseURL",
+      "value": "https://echo.hoppscotch.io",
+      "secret": false
+    },
+    {
+      "key": "httpbinBaseURL",
       "value": "https://httpbin.org",
       "secret": false
     }
   ]
 }
diff --git a/packages/hoppscotch-cli/src/__tests__/utils.ts b/packages/hoppscotch-cli/src/__tests__/utils.ts
index f6068b2d6..40c4d70f0 100644
--- a/packages/hoppscotch-cli/src/__tests__/utils.ts
+++ b/packages/hoppscotch-cli/src/__tests__/utils.ts
@@ -1,19 +1,20 @@
 import { exec } from "child_process";
 import { resolve } from "path";
 
 import { ExecResponse } from "./types";
 
-export const runCLI = (args: string, options = {}): Promise<ExecResponse> =>
-  {
-    const CLI_PATH = resolve(__dirname, "../../bin/hopp");
-    const command = `node ${CLI_PATH} ${args}`
-
-    return new Promise((resolve) =>
-      exec(command, options, (error, stdout, stderr) => resolve({ error, stdout, stderr }))
-    );
-  }
+export const runCLI = (args: string, options = {}): Promise<ExecResponse> => {
+  const CLI_PATH = resolve(__dirname, "../../bin/hopp.js");
+  const command = `node ${CLI_PATH} ${args}`;
+
+  return new Promise((resolve) =>
+    exec(command, options, (error, stdout, stderr) =>
+      resolve({ error, stdout, stderr })
+    )
+  );
+};
 
 export const trimAnsi = (target: string) => {
   const ansiRegex =
     /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g;
 
@@ -23,14 +24,20 @@ export const trimAnsi = (target: string) => {
 export const getErrorCode = (out: string) => {
   const ansiTrimmedStr = trimAnsi(out);
   return ansiTrimmedStr.split(" ")[0];
 };
 
-export const getTestJsonFilePath = (file: string, kind: "collection" | "environment") => {
+export const getTestJsonFilePath = (
+  file: string,
+  kind: "collection" | "environment"
+) => {
   const kindDir = {
     collection: "collections",
     environment: "environments",
   }[kind];
 
-  const filePath = resolve(__dirname, `../../src/__tests__/samples/${kindDir}/${file}`);
+  const filePath = resolve(
+    __dirname,
+    `../../src/__tests__/samples/${kindDir}/${file}`
+  );
   return filePath;
 };
diff --git a/packages/hoppscotch-cli/src/index.ts b/packages/hoppscotch-cli/src/index.ts
index bf81a7ab4..daa71995a 100644
--- a/packages/hoppscotch-cli/src/index.ts
+++ b/packages/hoppscotch-cli/src/index.ts
@@ -1,8 +1,9 @@
 import chalk from "chalk";
 import { Command } from "commander";
 import * as E from "fp-ts/Either";
+
 import { version } from "../package.json";
 import { test } from "./commands/test";
 import { handleError } from "./handlers/error";
 
 const accent = chalk.greenBright;
@@ -18,11 +19,11 @@ const CLI_BEFORE_ALL_TXT = `hopp: The ${accent(
 
 const CLI_AFTER_ALL_TXT = `\nFor more help, head on to ${accent(
   "https://docs.hoppscotch.io/documentation/clients/cli"
 )}`;
 
-const program = new Command()
+const program = new Command();
 
 program
   .name("hopp")
   .version(version, "-v, --ver", "see the current version of hopp-cli")
   .usage("[options or commands] arguments")
diff --git a/packages/hoppscotch-cli/src/utils/mutators.ts b/packages/hoppscotch-cli/src/utils/mutators.ts
index 91b1383f4..516f720e2 100644
--- a/packages/hoppscotch-cli/src/utils/mutators.ts
+++ b/packages/hoppscotch-cli/src/utils/mutators.ts
@@ -5,10 +5,45 @@ import { z } from "zod";
 
 import { error } from "../types/errors";
 import { FormDataEntry } from "../types/request";
 import { isHoppErrnoException } from "./checks";
 
+const getValidRequests = (
+  collections: HoppCollection[],
+  collectionFilePath: string
+) => {
+  return collections.map((collection) => {
+    // Validate requests using zod schema
+    const requestSchemaParsedResult = z
+      .array(entityReference(HoppRESTRequest))
+      .safeParse(collection.requests);
+
+    // Handle validation errors
+    if (!requestSchemaParsedResult.success) {
+      throw error({
+        code: "MALFORMED_COLLECTION",
+        path: collectionFilePath,
+        data: "Please check the collection data.",
+      });
+    }
+
+    // Recursively validate requests in nested folders
+    if (collection.folders.length > 0) {
+      collection.folders = getValidRequests(
+        collection.folders,
+        collectionFilePath
+      );
+    }
+
+    // Return validated collection
+    return {
+      ...collection,
+      requests: requestSchemaParsedResult.data,
+    };
+  });
+};
+
 /**
  * Parses array of FormDataEntry to FormData.
  * @param values Array of FormDataEntry.
  * @returns FormData with key-value pair from FormDataEntry.
  */
@@ -80,24 +115,7 @@ export async function parseCollectionData(
       path,
       data: "Please check the collection data.",
     });
   }
 
-  return collectionSchemaParsedResult.data.map((collection) => {
-    const requestSchemaParsedResult = z
-      .array(entityReference(HoppRESTRequest))
-      .safeParse(collection.requests);
-
-    if (!requestSchemaParsedResult.success) {
-      throw error({
-        code: "MALFORMED_COLLECTION",
-        path,
-        data: "Please check the collection data.",
-      });
-    }
-
-    return {
-      ...collection,
-      requests: requestSchemaParsedResult.data,
-    };
-  });
+  return getValidRequests(collectionSchemaParsedResult.data, path);
 }
diff --git a/packages/hoppscotch-js-sandbox/jest.config.js b/packages/hoppscotch-js-sandbox/jest.config.js
deleted file mode 100644
index 078d001b1..000000000
--- a/packages/hoppscotch-js-sandbox/jest.config.js
+++ /dev/null
@@ -1,10 +0,0 @@
-export default {
-  preset: "ts-jest",
-  testEnvironment: "jsdom",
-  collectCoverage: true,
-  setupFilesAfterEnv: ["./jest.setup.ts"],
-  moduleNameMapper: {
-    "~/(.*)": "<rootDir>/src/$1",
-    "^lodash-es$": "lodash",
-  },
-}
diff --git a/packages/hoppscotch-js-sandbox/jest.setup.ts b/packages/hoppscotch-js-sandbox/jest.setup.ts
deleted file mode 100644
index 9960425a6..000000000
--- a/packages/hoppscotch-js-sandbox/jest.setup.ts
+++ /dev/null
@@ -1 +0,0 @@
-require("@relmify/jest-fp-ts")
diff --git a/packages/hoppscotch-js-sandbox/node.d.ts b/packages/hoppscotch-js-sandbox/node.d.ts
index 70ca9c627..32567df82 100644
--- a/packages/hoppscotch-js-sandbox/node.d.ts
+++ b/packages/hoppscotch-js-sandbox/node.d.ts
@@ -1,2 +1,2 @@
-export { default } from "./dist/node.d.ts"
-export * from "./dist/node.d.ts"
+export { default } from "./dist/node/index.d.ts"
+export * from "./dist/node/index.d.ts"
diff --git a/packages/hoppscotch-js-sandbox/package.json b/packages/hoppscotch-js-sandbox/package.json
index 3026e0efc..d38b67825 100644
--- a/packages/hoppscotch-js-sandbox/package.json
+++ b/packages/hoppscotch-js-sandbox/package.json
@@ -28,11 +28,11 @@
     "pnpm": ">=3"
   },
   "scripts": {
     "lint": "eslint --ext .ts,.js --ignore-path .gitignore .",
     "lintfix": "eslint --fix --ext .ts,.js --ignore-path .gitignore .",
-    "test": "pnpm exec jest",
+    "test": "vitest run",
     "build": "vite build && tsc --emitDeclarationOnly",
     "clean": "pnpm tsc --build --clean",
     "postinstall": "pnpm run build",
     "prepublish": "pnpm run build",
     "do-lint": "pnpm run lint",
@@ -67,12 +67,20 @@
     "@typescript-eslint/parser": "5.30.6",
     "eslint": "8.19.0",
     "eslint-config-prettier": "8.6.0",
     "eslint-plugin-prettier": "4.2.1",
     "io-ts": "2.2.16",
-    "jest": "27.5.1",
     "prettier": "2.8.4",
     "ts-jest": "27.1.5",
     "typescript": "4.9.5",
-    "vite": "5.0.5"
+    "vite": "5.0.5",
+    "vitest": "0.34.6"
+  },
+  "peerDependencies": {
+    "isolated-vm": "4.7.2"
+  },
+  "peerDependenciesMeta": {
+    "isolated-vm": {
+      "optional": true
+    }
   }
 }
\ No newline at end of file
diff --git a/packages/hoppscotch-js-sandbox/setupFiles.ts b/packages/hoppscotch-js-sandbox/setupFiles.ts
new file mode 100644
index 000000000..11b1985d4
--- /dev/null
+++ b/packages/hoppscotch-js-sandbox/setupFiles.ts
@@ -0,0 +1,15 @@
+// Vitest doesn't work without globals
+// Ref: https://github.com/relmify/jest-fp-ts/issues/11
+
+import decodeMatchers from "@relmify/jest-fp-ts/dist/decodeMatchers"
+import eitherMatchers from "@relmify/jest-fp-ts/dist/eitherMatchers"
+import optionMatchers from "@relmify/jest-fp-ts/dist/optionMatchers"
+import theseMatchers from "@relmify/jest-fp-ts/dist/theseMatchers"
+import eitherOrTheseMatchers from "@relmify/jest-fp-ts/dist/eitherOrTheseMatchers"
+import { expect } from "vitest"
+
+expect.extend(decodeMatchers.matchers)
+expect.extend(eitherMatchers.matchers)
+expect.extend(optionMatchers.matchers)
+expect.extend(theseMatchers.matchers)
+expect.extend(eitherOrTheseMatchers.matchers)
diff --git a/packages/hoppscotch-js-sandbox/src/__tests__/testing/base64-helper-functions.spec.ts b/packages/hoppscotch-js-sandbox/src/__tests__/base64-helper-functions.spec.ts
similarity index 95%
rename from packages/hoppscotch-js-sandbox/src/__tests__/testing/base64-helper-functions.spec.ts
rename to packages/hoppscotch-js-sandbox/src/__tests__/base64-helper-functions.spec.ts
index c1fc1e106..ff0cf21fc 100644
--- a/packages/hoppscotch-js-sandbox/src/__tests__/testing/base64-helper-functions.spec.ts
+++ b/packages/hoppscotch-js-sandbox/src/__tests__/base64-helper-functions.spec.ts
@@ -1,10 +1,11 @@
 import * as TE from "fp-ts/TaskEither"
 import { pipe } from "fp-ts/function"
 
-import { runPreRequestScript } from "~/pre-request/node-vm"
-import { runTestScript } from "~/test-runner/node-vm"
+import { describe, expect, test } from "vitest"
+
+import { runPreRequestScript, runTestScript } from "~/node"
 import { TestResponse, TestResult } from "~/types"
 
 describe("Base64 helper functions", () => {
   const scriptExpectations = {
     atob: {
diff --git a/packages/hoppscotch-js-sandbox/src/__tests__/testing/envs/get.spec.ts b/packages/hoppscotch-js-sandbox/src/__tests__/env/get.spec.ts
similarity index 97%
rename from packages/hoppscotch-js-sandbox/src/__tests__/testing/envs/get.spec.ts
rename to packages/hoppscotch-js-sandbox/src/__tests__/env/get.spec.ts
index fb433eac8..ed2f78005 100644
--- a/packages/hoppscotch-js-sandbox/src/__tests__/testing/envs/get.spec.ts
+++ b/packages/hoppscotch-js-sandbox/src/__tests__/env/get.spec.ts
@@ -1,10 +1,11 @@
-import "@relmify/jest-fp-ts"
 import * as TE from "fp-ts/TaskEither"
 import { pipe } from "fp-ts/function"
 
-import { runTestScript } from "~/test-runner/node-vm"
+import { describe, expect, test } from "vitest"
+
+import { runTestScript } from "~/node"
 import { TestResponse, TestResult } from "~/types"
 
 const fakeResponse: TestResponse = {
   status: 200,
   body: "hoi",
diff --git a/packages/hoppscotch-js-sandbox/src/__tests__/testing/envs/getResolve.spec.ts b/packages/hoppscotch-js-sandbox/src/__tests__/env/getResolve.spec.ts
similarity index 98%
rename from packages/hoppscotch-js-sandbox/src/__tests__/testing/envs/getResolve.spec.ts
rename to packages/hoppscotch-js-sandbox/src/__tests__/env/getResolve.spec.ts
index 0d64e6d41..d1942ec58 100644
--- a/packages/hoppscotch-js-sandbox/src/__tests__/testing/envs/getResolve.spec.ts
+++ b/packages/hoppscotch-js-sandbox/src/__tests__/env/getResolve.spec.ts
@@ -1,10 +1,11 @@
-import "@relmify/jest-fp-ts"
 import * as TE from "fp-ts/TaskEither"
 import { pipe } from "fp-ts/function"
 
-import { runTestScript } from "~/test-runner/node-vm"
+import { describe, expect, test } from "vitest"
+
+import { runTestScript } from "~/node"
 import { TestResponse, TestResult } from "~/types"
 
 const fakeResponse: TestResponse = {
   status: 200,
   body: "hoi",
diff --git a/packages/hoppscotch-js-sandbox/src/__tests__/testing/envs/resolve.spec.ts b/packages/hoppscotch-js-sandbox/src/__tests__/env/resolve.spec.ts
similarity index 97%
rename from packages/hoppscotch-js-sandbox/src/__tests__/testing/envs/resolve.spec.ts
rename to packages/hoppscotch-js-sandbox/src/__tests__/env/resolve.spec.ts
index 022d7083a..d691a9fd6 100644
--- a/packages/hoppscotch-js-sandbox/src/__tests__/testing/envs/resolve.spec.ts
+++ b/packages/hoppscotch-js-sandbox/src/__tests__/env/resolve.spec.ts
@@ -1,9 +1,11 @@
 import * as TE from "fp-ts/TaskEither"
 import { pipe } from "fp-ts/function"
 
-import { runTestScript } from "~/test-runner/node-vm"
+import { describe, expect, test } from "vitest"
+
+import { runTestScript } from "~/node"
 import { TestResponse, TestResult } from "~/types"
 
 const fakeResponse: TestResponse = {
   status: 200,
   body: "hoi",
diff --git a/packages/hoppscotch-js-sandbox/src/__tests__/testing/envs/set.spec.ts b/packages/hoppscotch-js-sandbox/src/__tests__/env/set.spec.ts
similarity index 97%
rename from packages/hoppscotch-js-sandbox/src/__tests__/testing/envs/set.spec.ts
rename to packages/hoppscotch-js-sandbox/src/__tests__/env/set.spec.ts
index d3726d249..4b35aa02b 100644
--- a/packages/hoppscotch-js-sandbox/src/__tests__/testing/envs/set.spec.ts
+++ b/packages/hoppscotch-js-sandbox/src/__tests__/env/set.spec.ts
@@ -1,9 +1,11 @@
 import * as TE from "fp-ts/TaskEither"
 import { pipe } from "fp-ts/function"
 
-import { runTestScript } from "~/test-runner/node-vm"
+import { describe, expect, test } from "vitest"
+
+import { runTestScript } from "~/node"
 import { TestResponse, TestResult } from "~/types"
 
 const fakeResponse: TestResponse = {
   status: 200,
   body: "hoi",
diff --git a/packages/hoppscotch-js-sandbox/src/__tests__/testing/envs/unset.spec.ts b/packages/hoppscotch-js-sandbox/src/__tests__/env/unset.spec.ts
similarity index 98%
rename from packages/hoppscotch-js-sandbox/src/__tests__/testing/envs/unset.spec.ts
rename to packages/hoppscotch-js-sandbox/src/__tests__/env/unset.spec.ts
index eb6ae5783..be165d873 100644
--- a/packages/hoppscotch-js-sandbox/src/__tests__/testing/envs/unset.spec.ts
+++ b/packages/hoppscotch-js-sandbox/src/__tests__/env/unset.spec.ts
@@ -1,9 +1,11 @@
 import * as TE from "fp-ts/TaskEither"
 import { pipe } from "fp-ts/function"
 
-import { runTestScript } from "~/test-runner/node-vm"
+import { describe, expect, test } from "vitest"
+
+import { runTestScript } from "~/node"
 import { TestResponse, TestResult } from "~/types"
 
 const fakeResponse: TestResponse = {
   status: 200,
   body: "hoi",
diff --git a/packages/hoppscotch-js-sandbox/src/__tests__/testing/expect/toBe.spec.ts b/packages/hoppscotch-js-sandbox/src/__tests__/expect/toBe.spec.ts
similarity index 95%
rename from packages/hoppscotch-js-sandbox/src/__tests__/testing/expect/toBe.spec.ts
rename to packages/hoppscotch-js-sandbox/src/__tests__/expect/toBe.spec.ts
index 0d3dd19ac..079fc2198 100644
--- a/packages/hoppscotch-js-sandbox/src/__tests__/testing/expect/toBe.spec.ts
+++ b/packages/hoppscotch-js-sandbox/src/__tests__/expect/toBe.spec.ts
@@ -1,10 +1,11 @@
-import "@relmify/jest-fp-ts"
 import * as TE from "fp-ts/TaskEither"
 import { pipe } from "fp-ts/function"
 
-import { runTestScript } from "~/test-runner/node-vm"
+import { describe, expect, test } from "vitest"
+
+import { runTestScript } from "~/node"
 import { TestResponse } from "~/types"
 
 const fakeResponse: TestResponse = {
   status: 200,
   body: "hoi",
@@ -21,11 +22,11 @@ describe("toBe", () => {
   describe("general assertion (no negation)", () => {
     test("expect equals expected passes assertion", () => {
       return expect(
         func(
           `
-              pw.expect(2).toBe(2)
+            pw.expect(2).toBe(2)
           `,
           fakeResponse
         )()
       ).resolves.toEqualRight([
         expect.objectContaining({
diff --git a/packages/hoppscotch-js-sandbox/src/__tests__/testing/expect/toBeLevelxxx.spec.ts b/packages/hoppscotch-js-sandbox/src/__tests__/expect/toBeLevelxxx.spec.ts
similarity index 99%
rename from packages/hoppscotch-js-sandbox/src/__tests__/testing/expect/toBeLevelxxx.spec.ts
rename to packages/hoppscotch-js-sandbox/src/__tests__/expect/toBeLevelxxx.spec.ts
index dede20810..8a8eae8f2 100644
--- a/packages/hoppscotch-js-sandbox/src/__tests__/testing/expect/toBeLevelxxx.spec.ts
+++ b/packages/hoppscotch-js-sandbox/src/__tests__/expect/toBeLevelxxx.spec.ts
@@ -1,10 +1,11 @@
-import "@relmify/jest-fp-ts"
 import * as TE from "fp-ts/TaskEither"
 import { pipe } from "fp-ts/function"
 
-import { runTestScript } from "~/test-runner/node-vm"
+import { describe, expect, test } from "vitest"
+
+import { runTestScript } from "~/node"
 import { TestResponse } from "~/types"
 
 const fakeResponse: TestResponse = {
   status: 200,
   body: "hoi",
diff --git a/packages/hoppscotch-js-sandbox/src/__tests__/testing/expect/toBeType.spec.ts b/packages/hoppscotch-js-sandbox/src/__tests__/expect/toBeType.spec.ts
similarity index 98%
rename from packages/hoppscotch-js-sandbox/src/__tests__/testing/expect/toBeType.spec.ts
rename to packages/hoppscotch-js-sandbox/src/__tests__/expect/toBeType.spec.ts
index 6ab9a9b90..a18600553 100644
--- a/packages/hoppscotch-js-sandbox/src/__tests__/testing/expect/toBeType.spec.ts
+++ b/packages/hoppscotch-js-sandbox/src/__tests__/expect/toBeType.spec.ts
@@ -1,9 +1,11 @@
 import * as TE from "fp-ts/TaskEither"
 import { pipe } from "fp-ts/function"
 
-import { runTestScript } from "~/test-runner/node-vm"
+import { describe, expect, test } from "vitest"
+
+import { runTestScript } from "~/node"
 import { TestResponse } from "~/types"
 
 const fakeResponse: TestResponse = {
   status: 200,
   body: "hoi",
diff --git a/packages/hoppscotch-js-sandbox/src/__tests__/testing/expect/toHaveLength.spec.ts b/packages/hoppscotch-js-sandbox/src/__tests__/expect/toHaveLength.spec.ts
similarity index 98%
rename from packages/hoppscotch-js-sandbox/src/__tests__/testing/expect/toHaveLength.spec.ts
rename to packages/hoppscotch-js-sandbox/src/__tests__/expect/toHaveLength.spec.ts
index 970fe374d..b05a0a499 100644
--- a/packages/hoppscotch-js-sandbox/src/__tests__/testing/expect/toHaveLength.spec.ts
+++ b/packages/hoppscotch-js-sandbox/src/__tests__/expect/toHaveLength.spec.ts
@@ -1,9 +1,11 @@
 import * as TE from "fp-ts/TaskEither"
 import { pipe } from "fp-ts/function"
 
-import { runTestScript } from "~/test-runner/node-vm"
+import { describe, expect, test } from "vitest"
+
+import { runTestScript } from "~/node"
 import { TestResponse } from "~/types"
 
 const fakeResponse: TestResponse = {
   status: 200,
   body: "hoi",
diff --git a/packages/hoppscotch-js-sandbox/src/__tests__/testing/expect/toInclude.spec.ts b/packages/hoppscotch-js-sandbox/src/__tests__/expect/toInclude.spec.ts
similarity index 98%
rename from packages/hoppscotch-js-sandbox/src/__tests__/testing/expect/toInclude.spec.ts
rename to packages/hoppscotch-js-sandbox/src/__tests__/expect/toInclude.spec.ts
index 132120d92..7b68fe062 100644
--- a/packages/hoppscotch-js-sandbox/src/__tests__/testing/expect/toInclude.spec.ts
+++ b/packages/hoppscotch-js-sandbox/src/__tests__/expect/toInclude.spec.ts
@@ -1,9 +1,11 @@
 import * as TE from "fp-ts/TaskEither"
 import { pipe } from "fp-ts/function"
 
-import { runTestScript } from "~/test-runner/node-vm"
+import { describe, expect, test } from "vitest"
+
+import { runTestScript } from "~/node"
 import { TestResponse } from "~/types"
 
 const fakeResponse: TestResponse = {
   status: 200,
   body: "hoi",
diff --git a/packages/hoppscotch-js-sandbox/src/__tests__/preRequest.spec.ts b/packages/hoppscotch-js-sandbox/src/__tests__/pre-request.spec.ts
similarity index 95%
rename from packages/hoppscotch-js-sandbox/src/__tests__/preRequest.spec.ts
rename to packages/hoppscotch-js-sandbox/src/__tests__/pre-request.spec.ts
index ce8bf9555..c94a440bd 100644
--- a/packages/hoppscotch-js-sandbox/src/__tests__/preRequest.spec.ts
+++ b/packages/hoppscotch-js-sandbox/src/__tests__/pre-request.spec.ts
@@ -1,8 +1,8 @@
-import "@relmify/jest-fp-ts"
+import { describe, expect, test } from "vitest"
 
-import { runPreRequestScript } from "~/pre-request/node-vm"
+import { runPreRequestScript } from "~/node"
 
 describe("runPreRequestScript", () => {
   test("returns the updated environment properly", () => {
     return expect(
       runPreRequestScript(
diff --git a/packages/hoppscotch-js-sandbox/src/__tests__/utils.spec.ts b/packages/hoppscotch-js-sandbox/src/__tests__/shared-utils.spec.ts
similarity index 78%
rename from packages/hoppscotch-js-sandbox/src/__tests__/utils.spec.ts
rename to packages/hoppscotch-js-sandbox/src/__tests__/shared-utils.spec.ts
index a9871a1b1..f016b891f 100644
--- a/packages/hoppscotch-js-sandbox/src/__tests__/utils.spec.ts
+++ b/packages/hoppscotch-js-sandbox/src/__tests__/shared-utils.spec.ts
@@ -1,6 +1,8 @@
-import { preventCyclicObjects } from "~/utils"
+import { preventCyclicObjects } from "~/shared-utils"
+
+import { describe, expect, test } from "vitest"
 
 describe("preventCyclicObjects", () => {
   test("succeeds with a simple object", () => {
     const testObj = {
       a: 1,
diff --git a/packages/hoppscotch-js-sandbox/src/__tests__/testing/test-runner.spec.ts b/packages/hoppscotch-js-sandbox/src/__tests__/test-runner.spec.ts
similarity index 95%
rename from packages/hoppscotch-js-sandbox/src/__tests__/testing/test-runner.spec.ts
rename to packages/hoppscotch-js-sandbox/src/__tests__/test-runner.spec.ts
index 214ee7d6d..293e83d23 100644
--- a/packages/hoppscotch-js-sandbox/src/__tests__/testing/test-runner.spec.ts
+++ b/packages/hoppscotch-js-sandbox/src/__tests__/test-runner.spec.ts
@@ -1,9 +1,11 @@
 import * as TE from "fp-ts/TaskEither"
 import { pipe } from "fp-ts/function"
 
-import { runTestScript } from "~/test-runner/node-vm"
+import { describe, expect, test } from "vitest"
+
+import { runTestScript } from "~/node"
 import { TestResponse } from "~/types"
 
 const fakeResponse: TestResponse = {
   status: 200,
   body: "hoi",
diff --git a/packages/hoppscotch-js-sandbox/src/node.ts b/packages/hoppscotch-js-sandbox/src/node.ts
deleted file mode 100644
index c5d403251..000000000
--- a/packages/hoppscotch-js-sandbox/src/node.ts
+++ /dev/null
@@ -1,2 +0,0 @@
-export * from "./pre-request/node-vm"
-export * from "./test-runner/node-vm"
diff --git a/packages/hoppscotch-js-sandbox/src/node/index.ts b/packages/hoppscotch-js-sandbox/src/node/index.ts
new file mode 100644
index 000000000..a329c048b
--- /dev/null
+++ b/packages/hoppscotch-js-sandbox/src/node/index.ts
@@ -0,0 +1,2 @@
+export { runPreRequestScript } from "./pre-request"
+export { runTestScript } from "./test-runner"
diff --git a/packages/hoppscotch-js-sandbox/src/node/pre-request.ts b/packages/hoppscotch-js-sandbox/src/node/pre-request.ts
new file mode 100644
index 000000000..ae60c9d76
--- /dev/null
+++ b/packages/hoppscotch-js-sandbox/src/node/pre-request.ts
@@ -0,0 +1,91 @@
+import { pipe } from "fp-ts/function"
+import * as TE from "fp-ts/lib/TaskEither"
+import { createRequire } from "module"
+
+import type ivmT from "isolated-vm"
+
+import { TestResult } from "~/types"
+import { getPreRequestScriptMethods } from "~/shared-utils"
+import { getSerializedAPIMethods } from "./utils"
+
+const nodeRequire = createRequire(import.meta.url)
+const ivm = nodeRequire("isolated-vm")
+
+export const runPreRequestScript = (
+  preRequestScript: string,
+  envs: TestResult["envs"]
+): TE.TaskEither<string, TestResult["envs"]> =>
+  pipe(
+    TE.tryCatch(
+      async () => {
+        const isolate: ivmT.Isolate = new ivm.Isolate()
+        const context = await isolate.createContext()
+        return { isolate, context }
+      },
+      (reason) => `Context initialization failed: ${reason}`
+    ),
+    TE.chain(({ isolate, context }) =>
+      pipe(
+        TE.tryCatch(
+          async () => {
+            const jail = context.global
+
+            const { pw, updatedEnvs } = getPreRequestScriptMethods(envs)
+
+            const serializedAPIMethods = getSerializedAPIMethods(pw)
+            jail.setSync("serializedAPIMethods", serializedAPIMethods, {
+              copy: true,
+            })
+
+            jail.setSync("atob", atob)
+            jail.setSync("btoa", btoa)
+
+            // Methods in the isolate context can't be invoked straightaway
+            const finalScript = `
+              const pw = new Proxy(serializedAPIMethods, {
+                get: (pwObjTarget, pwObjProp) => {
+                  const topLevelEntry = pwObjTarget[pwObjProp]
+
+                  // "pw.env" set of API methods
+                    if (topLevelEntry && typeof topLevelEntry === "object") {
+                      return new Proxy(topLevelEntry, {
+                        get: (subTarget, subProp) => {
+                          const subLevelProperty = subTarget[subProp]
+                          if (subLevelProperty && subLevelProperty.typeof === "function") {
+                            return (...args) => subLevelProperty.applySync(null, args)
+                          }
+                        },
+                      })
+                    }
+                }
+              })
+
+              ${preRequestScript}
+            `
+
+            // Create a script and compile it
+            const script = await isolate.compileScript(finalScript)
+
+            // Run the pre-request script in the provided context
+            await script.run(context)
+
+            return updatedEnvs
+          },
+          (reason) => reason
+        ),
+        TE.fold(
+          (error) => TE.left(`Script execution failed: ${error}`),
+          (result) =>
+            pipe(
+              TE.tryCatch(
+                async () => {
+                  await isolate.dispose()
+                  return result
+                },
+                (disposeError) => `Isolate disposal failed: ${disposeError}`
+              )
+            )
+        )
+      )
+    )
+  )
diff --git a/packages/hoppscotch-js-sandbox/src/node/test-runner.ts b/packages/hoppscotch-js-sandbox/src/node/test-runner.ts
new file mode 100644
index 000000000..14bf0c3e2
--- /dev/null
+++ b/packages/hoppscotch-js-sandbox/src/node/test-runner.ts
@@ -0,0 +1,217 @@
+import * as E from "fp-ts/Either"
+import * as TE from "fp-ts/TaskEither"
+import { pipe } from "fp-ts/function"
+import { createRequire } from "module"
+
+import type ivmT from "isolated-vm"
+
+import { TestResponse, TestResult } from "~/types"
+import {
+  getTestRunnerScriptMethods,
+  preventCyclicObjects,
+} from "~/shared-utils"
+import { getSerializedAPIMethods } from "./utils"
+
+const nodeRequire = createRequire(import.meta.url)
+const ivm = nodeRequire("isolated-vm")
+
+export const runTestScript = (
+  testScript: string,
+  envs: TestResult["envs"],
+  response: TestResponse
+): TE.TaskEither<string, TestResult> =>
+  pipe(
+    TE.tryCatch(
+      async () => {
+        const isolate: ivmT.Isolate = new ivm.Isolate()
+        const context = await isolate.createContext()
+        return { isolate, context }
+      },
+      (reason) => `Context initialization failed: ${reason}`
+    ),
+    TE.chain(({ isolate, context }) =>
+      pipe(
+        TE.tryCatch(
+          async () =>
+            executeScriptInContext(
+              testScript,
+              envs,
+              response,
+              isolate,
+              context
+            ),
+          (reason) => `Script execution failed: ${reason}`
+        ),
+        TE.chain((result) =>
+          TE.tryCatch(
+            async () => {
+              await isolate.dispose()
+              return result
+            },
+            (disposeReason) => `Isolate disposal failed: ${disposeReason}`
+          )
+        )
+      )
+    )
+  )
+const executeScriptInContext = (
+  testScript: string,
+  envs: TestResult["envs"],
+  response: TestResponse,
+  isolate: ivmT.Isolate,
+  context: ivmT.Context
+): Promise<TestResult> => {
+  return new Promise((resolve, reject) => {
+    // Parse response object
+    const responseObjHandle = preventCyclicObjects(response)
+    if (E.isLeft(responseObjHandle)) {
+      return reject(`Response parsing failed: ${responseObjHandle.left}`)
+    }
+
+    const jail = context.global
+
+    const { pw, testRunStack, updatedEnvs } = getTestRunnerScriptMethods(envs)
+
+    const serializedAPIMethods = getSerializedAPIMethods({
+      ...pw,
+      response: responseObjHandle.right,
+    })
+    jail.setSync("serializedAPIMethods", serializedAPIMethods, { copy: true })
+
+    jail.setSync("atob", atob)
+    jail.setSync("btoa", btoa)
+
+    jail.setSync("ivm", ivm)
+
+    // Methods in the isolate context can't be invoked straightaway
+    const finalScript = `
+    const pw = new Proxy(serializedAPIMethods, {
+      get: (pwObj, pwObjProp) => {
+        // pw.expect(), pw.env, etc.
+        const topLevelEntry = pwObj[pwObjProp]
+
+        // If the entry exists and is a function
+        // pw.expect(), pw.test(), etc.
+        if (topLevelEntry && topLevelEntry.typeof === "function") {
+          // pw.test() just involves invoking the function via "applySync()"
+          if (pwObjProp === "test") {
+            return (...args) => topLevelEntry.applySync(null, args)
+          }
+
+          // pw.expect() returns an object with matcher methods
+          return (...args) => {
+            // Invoke "pw.expect()" and get access to the object with matcher methods
+            const expectFnResult = topLevelEntry.applySync(
+              null,
+              args.map((expectVal) => {
+                if (typeof expectVal === "object") {
+                  if (expectVal === null) {
+                    return null
+                  }
+
+                  // Only arrays and objects stringified here should be parsed from the "pw.expect()" method definition
+                  // The usecase is that any JSON string supplied should be preserved
+                  // An extra "isStringifiedWithinIsolate" prop is added to indicate it has to be parsed
+
+                  if (Array.isArray(expectVal)) {
+                    return JSON.stringify({
+                      arr: expectVal,
+                      isStringifiedWithinIsolate: true,
+                    })
+                  }
+
+                  return JSON.stringify({
+                    ...expectVal,
+                    isStringifiedWithinIsolate: true,
+                  })
+                }
+
+                return expectVal
+              })
+            )
+
+            // Matcher methods that can be chained with "pw.expect()"
+            // pw.expect().toBe(), etc
+            if (expectFnResult.typeof === "object") {
+              // Access the getter that points to the negated matcher methods via "{ accessors: true }"
+              const matcherMethods = {
+                not: expectFnResult.getSync("not", { accessors: true }),
+              }
+
+              // Serialize matcher methods for use in the isolate context
+              const matcherMethodNames = [
+                "toBe",
+                "toBeLevel2xx",
+                "toBeLevel3xx",
+                "toBeLevel4xx",
+                "toBeLevel5xx",
+                "toBeType",
+                "toHaveLength",
+                "toInclude",
+              ]
+              matcherMethodNames.forEach((methodName) => {
+                matcherMethods[methodName] = expectFnResult.getSync(methodName)
+              })
+
+              return new Proxy(matcherMethods, {
+                get: (matcherMethodTarget, matcherMethodProp) => {
+                  // pw.expect().not.toBe(), etc
+                  const matcherMethodEntry = matcherMethodTarget[matcherMethodProp]
+
+                  if (matcherMethodProp === "not") {
+                    return new Proxy(matcherMethodEntry, {
+                      get: (negatedObjTarget, negatedObjprop) => {
+                        // Return the negated matcher method defn that is invoked from the test script
+                        const negatedMatcherMethodDefn = negatedObjTarget.getSync(negatedObjprop)
+                        return negatedMatcherMethodDefn
+                      },
+                    })
+                  }
+
+                  // Return the matcher method defn that is invoked from the test script
+                  return matcherMethodEntry
+                },
+              })
+            }
+          }
+        }
+
+        // "pw.env" set of API methods
+        if (typeof topLevelEntry === "object" && pwObjProp !== "response") {
+          return new Proxy(topLevelEntry, {
+            get: (subTarget, subProp) => {
+              const subLevelProperty = subTarget[subProp]
+              if (
+                subLevelProperty &&
+                subLevelProperty.typeof === "function"
+              ) {
+                return (...args) => subLevelProperty.applySync(null, args)
+              }
+            },
+          })
+        }
+
+        return topLevelEntry
+      },
+    })
+
+      ${testScript}
+    `
+
+    // Create a script and compile it
+    const script = isolate.compileScript(finalScript)
+
+    // Run the test script in the provided context
+    script
+      .then((script) => script.run(context))
+      .then(() => {
+        resolve({
+          tests: testRunStack,
+          envs: updatedEnvs,
+        })
+      })
+      .catch((error: Error) => {
+        reject(error)
+      })
+  })
+}
diff --git a/packages/hoppscotch-js-sandbox/src/node/utils.ts b/packages/hoppscotch-js-sandbox/src/node/utils.ts
new file mode 100644
index 000000000..7e44e4d54
--- /dev/null
+++ b/packages/hoppscotch-js-sandbox/src/node/utils.ts
@@ -0,0 +1,23 @@
+import { createRequire } from "module"
+
+const nodeRequire = createRequire(import.meta.url)
+const ivm = nodeRequire("isolated-vm")
+
+// Helper function to recursively wrap methods in `ivm.Reference`
+export const getSerializedAPIMethods = (
+  namespaceObj: Record<string, unknown>
+): Record<string, unknown> => {
+  const result: Record<string, unknown> = {}
+
+  for (const [key, value] of Object.entries(namespaceObj)) {
+    if (typeof value === "object" && value !== null && !Array.isArray(value)) {
+      result[key] = getSerializedAPIMethods(value as Record<string, unknown>)
+    } else if (typeof value === "function") {
+      result[key] = new ivm.Reference(value)
+    } else {
+      result[key] = value
+    }
+  }
+
+  return result
+}
diff --git a/packages/hoppscotch-js-sandbox/src/pre-request/node-vm/index.ts b/packages/hoppscotch-js-sandbox/src/pre-request/node-vm/index.ts
deleted file mode 100644
index 220a18d77..000000000
--- a/packages/hoppscotch-js-sandbox/src/pre-request/node-vm/index.ts
+++ /dev/null
@@ -1,38 +0,0 @@
-import { pipe } from "fp-ts/function"
-import * as TE from "fp-ts/lib/TaskEither"
-import { createContext, runInContext } from "vm"
-
-import { TestResult } from "~/types"
-import { getPreRequestScriptMethods } from "~/utils"
-
-export const runPreRequestScript = (
-  preRequestScript: string,
-  envs: TestResult["envs"]
-): TE.TaskEither<string, TestResult["envs"]> =>
-  pipe(
-    TE.tryCatch(
-      async () => {
-        return createContext()
-      },
-      (reason) => `Context initialization failed: ${reason}`
-    ),
-    TE.chain((context) =>
-      TE.tryCatch(
-        () =>
-          new Promise((resolve) => {
-            const { pw, updatedEnvs } = getPreRequestScriptMethods(envs)
-
-            // Expose pw to the context
-            context.pw = pw
-            context.atob = atob
-            context.btoa = btoa
-
-            // Run the pre-request script in the provided context
-            runInContext(preRequestScript, context)
-
-            resolve(updatedEnvs)
-          }),
-        (reason) => `Script execution failed: ${reason}`
-      )
-    )
-  )
diff --git a/packages/hoppscotch-js-sandbox/src/utils.ts b/packages/hoppscotch-js-sandbox/src/shared-utils.ts
similarity index 85%
rename from packages/hoppscotch-js-sandbox/src/utils.ts
rename to packages/hoppscotch-js-sandbox/src/shared-utils.ts
index a6d298c23..d8908f16d 100644
--- a/packages/hoppscotch-js-sandbox/src/utils.ts
+++ b/packages/hoppscotch-js-sandbox/src/shared-utils.ts
@@ -180,10 +180,40 @@ const getSharedMethods = (envs: TestResult["envs"]) => {
     },
     updatedEnvs,
   }
 }
 
+const getResolvedExpectValue = (expectVal: any) => {
+  if (typeof expectVal !== "string") {
+    return expectVal
+  }
+
+  try {
+    const parsedExpectVal = JSON.parse(expectVal)
+
+    // Supplying non-primitive values is not permitted in the `isStringifiedWithinIsolate` property indicates that the object was stringified before executing the script from the isolate context
+    // This is done to ensure a JSON string supplied as the "expectVal" is not parsed and preserved as is
+    if (typeof parsedExpectVal === "object") {
+      if (parsedExpectVal.isStringifiedWithinIsolate !== true) {
+        return expectVal
+      }
+
+      // For an array, the contents are stored in the `arr` property
+      if (Array.isArray(parsedExpectVal.arr)) {
+        return parsedExpectVal.arr
+      }
+
+      delete parsedExpectVal.isStringifiedWithinIsolate
+      return parsedExpectVal
+    }
+
+    return expectVal
+  } catch (_) {
+    return expectVal
+  }
+}
+
 export function preventCyclicObjects(
   obj: Record<string, any>
 ): E.Left<string> | E.Right<Record<string, any>> {
   let jsonString
 
@@ -213,19 +243,22 @@ export const createExpectation = (
   negated: boolean,
   currTestStack: TestDescriptor[]
 ) => {
   const result: Record<string, unknown> = {}
 
+  // Non-primitive values supplied are stringified in the isolate context
+  const resolvedExpectVal = getResolvedExpectValue(expectVal)
+
   const toBeFn = (expectedVal: any) => {
-    let assertion = expectVal === expectedVal
+    let assertion = resolvedExpectVal === expectedVal
 
     if (negated) {
       assertion = !assertion
     }
 
     const status = assertion ? "pass" : "fail"
-    const message = `Expected '${expectVal}' to${
+    const message = `Expected '${resolvedExpectVal}' to${
       negated ? " not" : ""
     } be '${expectedVal}'`
 
     currTestStack[currTestStack.length - 1].expectResults.push({
       status,
@@ -238,11 +271,11 @@ export const createExpectation = (
   const toBeLevelXxx = (
     level: string,
     rangeStart: number,
     rangeEnd: number
   ) => {
-    const parsedExpectVal = parseInt(expectVal)
+    const parsedExpectVal = parseInt(resolvedExpectVal)
 
     if (!Number.isNaN(parsedExpectVal)) {
       let assertion =
         parsedExpectVal >= rangeStart && parsedExpectVal <= rangeEnd
 
@@ -258,11 +291,11 @@ export const createExpectation = (
       currTestStack[currTestStack.length - 1].expectResults.push({
         status,
         message,
       })
     } else {
-      const message = `Expected ${level}-level status but could not parse value '${expectVal}'`
+      const message = `Expected ${level}-level status but could not parse value '${resolvedExpectVal}'`
       currTestStack[currTestStack.length - 1].expectResults.push({
         status: "error",
         message,
       })
     }
@@ -286,18 +319,18 @@ export const createExpectation = (
         "bigint",
         "symbol",
         "function",
       ].includes(expectedType)
     ) {
-      let assertion = typeof expectVal === expectedType
+      let assertion = typeof resolvedExpectVal === expectedType
 
       if (negated) {
         assertion = !assertion
       }
 
       const status = assertion ? "pass" : "fail"
-      const message = `Expected '${expectVal}' to${
+      const message = `Expected '${resolvedExpectVal}' to${
         negated ? " not" : ""
       } be type '${expectedType}'`
 
       currTestStack[currTestStack.length - 1].expectResults.push({
         status,
@@ -314,11 +347,16 @@ export const createExpectation = (
 
     return undefined
   }
 
   const toHaveLengthFn = (expectedLength: any) => {
-    if (!(Array.isArray(expectVal) || typeof expectVal === "string")) {
+    if (
+      !(
+        Array.isArray(resolvedExpectVal) ||
+        typeof resolvedExpectVal === "string"
+      )
+    ) {
       const message =
         "Expected toHaveLength to be called for an array or string"
       currTestStack[currTestStack.length - 1].expectResults.push({
         status: "error",
         message,
@@ -326,11 +364,11 @@ export const createExpectation = (
 
       return undefined
     }
 
     if (typeof expectedLength === "number" && !Number.isNaN(expectedLength)) {
-      let assertion = expectVal.length === expectedLength
+      let assertion = resolvedExpectVal.length === expectedLength
 
       if (negated) {
         assertion = !assertion
       }
 
@@ -353,11 +391,16 @@ export const createExpectation = (
 
     return undefined
   }
 
   const toIncludeFn = (needle: any) => {
-    if (!(Array.isArray(expectVal) || typeof expectVal === "string")) {
+    if (
+      !(
+        Array.isArray(resolvedExpectVal) ||
+        typeof resolvedExpectVal === "string"
+      )
+    ) {
       const message = "Expected toInclude to be called for an array or string"
       currTestStack[currTestStack.length - 1].expectResults.push({
         status: "error",
         message,
       })
@@ -380,17 +423,17 @@ export const createExpectation = (
         message,
       })
       return undefined
     }
 
-    let assertion = expectVal.includes(needle)
+    let assertion = resolvedExpectVal.includes(needle)
 
     if (negated) {
       assertion = !assertion
     }
 
-    const expectValPretty = JSON.stringify(expectVal)
+    const expectValPretty = JSON.stringify(resolvedExpectVal)
     const needlePretty = JSON.stringify(needle)
     const status = assertion ? "pass" : "fail"
     const message = `Expected ${expectValPretty} to${
       negated ? " not" : ""
     } include ${needlePretty}`
diff --git a/packages/hoppscotch-js-sandbox/src/test-runner/node-vm/index.ts b/packages/hoppscotch-js-sandbox/src/test-runner/node-vm/index.ts
deleted file mode 100644
index 89d5a8f68..000000000
--- a/packages/hoppscotch-js-sandbox/src/test-runner/node-vm/index.ts
+++ /dev/null
@@ -1,57 +0,0 @@
-import * as E from "fp-ts/Either"
-import * as TE from "fp-ts/TaskEither"
-import { pipe } from "fp-ts/function"
-import { createContext, runInContext } from "vm"
-
-import { TestResponse, TestResult } from "~/types"
-import { getTestRunnerScriptMethods, preventCyclicObjects } from "~/utils"
-
-export const runTestScript = (
-  testScript: string,
-  envs: TestResult["envs"],
-  response: TestResponse
-): TE.TaskEither<string, TestResult> =>
-  pipe(
-    TE.tryCatch(
-      async () => {
-        return createContext()
-      },
-      (reason) => `Context initialization failed: ${reason}`
-    ),
-    TE.chain((context) =>
-      TE.tryCatch(
-        () => executeScriptInContext(testScript, envs, response, context),
-        (reason) => `Script execution failed: ${reason}`
-      )
-    )
-  )
-
-const executeScriptInContext = (
-  testScript: string,
-  envs: TestResult["envs"],
-  response: TestResponse,
-  context: any
-): Promise<TestResult> => {
-  return new Promise((resolve, reject) => {
-    // Parse response object
-    const responseObjHandle = preventCyclicObjects(response)
-    if (E.isLeft(responseObjHandle)) {
-      return reject(`Response parsing failed: ${responseObjHandle.left}`)
-    }
-
-    const { pw, testRunStack, updatedEnvs } = getTestRunnerScriptMethods(envs)
-
-    // Expose pw to the context
-    context.pw = { ...pw, response: responseObjHandle.right }
-    context.atob = atob
-    context.btoa = btoa
-
-    // Run the test script in the provided context
-    runInContext(testScript, context)
-
-    resolve({
-      tests: testRunStack,
-      envs: updatedEnvs,
-    })
-  })
-}
diff --git a/packages/hoppscotch-js-sandbox/src/web.ts b/packages/hoppscotch-js-sandbox/src/web.ts
deleted file mode 100644
index 5077e9311..000000000
--- a/packages/hoppscotch-js-sandbox/src/web.ts
+++ /dev/null
@@ -1,2 +0,0 @@
-export * from "./pre-request/web-worker"
-export * from "./test-runner/web-worker"
diff --git a/packages/hoppscotch-js-sandbox/src/web/index.ts b/packages/hoppscotch-js-sandbox/src/web/index.ts
new file mode 100644
index 000000000..a329c048b
--- /dev/null
+++ b/packages/hoppscotch-js-sandbox/src/web/index.ts
@@ -0,0 +1,2 @@
+export { runPreRequestScript } from "./pre-request"
+export { runTestScript } from "./test-runner"
diff --git a/packages/hoppscotch-js-sandbox/src/pre-request/web-worker/index.ts b/packages/hoppscotch-js-sandbox/src/web/pre-request/index.ts
similarity index 100%
rename from packages/hoppscotch-js-sandbox/src/pre-request/web-worker/index.ts
rename to packages/hoppscotch-js-sandbox/src/web/pre-request/index.ts
diff --git a/packages/hoppscotch-js-sandbox/src/pre-request/web-worker/worker.ts b/packages/hoppscotch-js-sandbox/src/web/pre-request/worker.ts
similarity index 93%
rename from packages/hoppscotch-js-sandbox/src/pre-request/web-worker/worker.ts
rename to packages/hoppscotch-js-sandbox/src/web/pre-request/worker.ts
index 0825f3831..694973e11 100644
--- a/packages/hoppscotch-js-sandbox/src/pre-request/web-worker/worker.ts
+++ b/packages/hoppscotch-js-sandbox/src/web/pre-request/worker.ts
@@ -1,9 +1,9 @@
 import * as TE from "fp-ts/TaskEither"
 
 import { TestResult } from "~/types"
-import { getPreRequestScriptMethods } from "~/utils"
+import { getPreRequestScriptMethods } from "~/shared-utils"
 
 const executeScriptInContext = (
   preRequestScript: string,
   envs: TestResult["envs"]
 ): TE.TaskEither<string, TestResult["envs"]> => {
diff --git a/packages/hoppscotch-js-sandbox/src/test-runner/web-worker/index.ts b/packages/hoppscotch-js-sandbox/src/web/test-runner/index.ts
similarity index 100%
rename from packages/hoppscotch-js-sandbox/src/test-runner/web-worker/index.ts
rename to packages/hoppscotch-js-sandbox/src/web/test-runner/index.ts
diff --git a/packages/hoppscotch-js-sandbox/src/test-runner/web-worker/worker.ts b/packages/hoppscotch-js-sandbox/src/web/test-runner/worker.ts
similarity index 93%
rename from packages/hoppscotch-js-sandbox/src/test-runner/web-worker/worker.ts
rename to packages/hoppscotch-js-sandbox/src/web/test-runner/worker.ts
index c6b9374a2..0f759c9c9 100644
--- a/packages/hoppscotch-js-sandbox/src/test-runner/web-worker/worker.ts
+++ b/packages/hoppscotch-js-sandbox/src/web/test-runner/worker.ts
@@ -1,10 +1,13 @@
 import * as E from "fp-ts/Either"
 import * as TE from "fp-ts/TaskEither"
 
 import { SandboxTestResult, TestResponse, TestResult } from "~/types"
-import { getTestRunnerScriptMethods, preventCyclicObjects } from "~/utils"
+import {
+  getTestRunnerScriptMethods,
+  preventCyclicObjects,
+} from "~/shared-utils"
 
 const executeScriptInContext = (
   testScript: string,
   envs: TestResult["envs"],
   response: TestResponse
diff --git a/packages/hoppscotch-js-sandbox/vite.config.ts b/packages/hoppscotch-js-sandbox/vite.config.ts
index aa01475b0..c47ddd4c7 100644
--- a/packages/hoppscotch-js-sandbox/vite.config.ts
+++ b/packages/hoppscotch-js-sandbox/vite.config.ts
@@ -5,20 +5,24 @@ export default defineConfig({
   build: {
     outDir: "./dist",
     emptyOutDir: true,
     lib: {
       entry: {
-        web: "./src/web.ts",
-        node: "./src/node.ts",
+        web: "./src/web/index.ts",
+        node: "./src/node/index.ts",
       },
       name: "js-sandbox",
       formats: ["es", "cjs"],
     },
     rollupOptions: {
-      external: ["vm"],
+      external: ["module"],
     },
   },
+  test: {
+    environment: "node",
+    setupFiles: ["./setupFiles.ts"],
+  },
   resolve: {
     alias: {
       "~": resolve(__dirname, "./src"),
     },
   },
diff --git a/packages/hoppscotch-js-sandbox/web.d.ts b/packages/hoppscotch-js-sandbox/web.d.ts
index 2ab2266dc..27b45c844 100644
--- a/packages/hoppscotch-js-sandbox/web.d.ts
+++ b/packages/hoppscotch-js-sandbox/web.d.ts
@@ -1,2 +1,2 @@
-export { default } from "./dist/web.d.ts"
-export * from "./dist/web.d.ts"
+export { default } from "./dist/web/index.d.ts"
+export * from "./dist/web/index.d.ts"
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 541e980da..16a955e86 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -307,10 +307,13 @@ importers:
         specifier: 5.3.0
         version: 5.3.0
       commander:
         specifier: 11.1.0
         version: 11.1.0
+      isolated-vm:
+        specifier: 4.7.2
+        version: 4.7.2
       lodash-es:
         specifier: 4.17.21
         version: 4.17.21
       qs:
         specifier: 6.11.2
@@ -826,10 +829,13 @@ importers:
         specifier: 4.17.12
         version: 4.17.12
       fp-ts:
         specifier: 2.12.1
         version: 2.12.1
+      isolated-vm:
+        specifier: 4.7.2
+        version: 4.7.2
       lodash:
         specifier: 4.17.21
         version: 4.17.21
       lodash-es:
         specifier: 4.17.21
@@ -866,13 +872,10 @@ importers:
         specifier: 4.2.1
         version: 4.2.1(eslint-config-prettier@8.6.0)(eslint@8.19.0)(prettier@2.8.4)
       io-ts:
         specifier: 2.2.16
         version: 2.2.16(fp-ts@2.12.1)
-      jest:
-        specifier: 27.5.1
-        version: 27.5.1
       prettier:
         specifier: 2.8.4
         version: 2.8.4
       ts-jest:
         specifier: 27.1.5
@@ -881,10 +884,13 @@ importers:
         specifier: 4.9.5
         version: 4.9.5
       vite:
         specifier: 5.0.5
         version: 5.0.5(@types/node@17.0.45)(terser@5.27.0)
+      vitest:
+        specifier: 0.34.6
+        version: 0.34.6(sass@1.69.5)(terser@5.27.0)
 
   packages/hoppscotch-selfhost-desktop:
     dependencies:
       '@fontsource-variable/inter':
         specifier: 5.0.15
@@ -3059,11 +3065,11 @@ packages:
   /@boringer-avatars/vue3@0.2.1(vue@3.3.9):
     resolution: {integrity: sha512-KzAfh31SDXToTvFL0tBNG5Ur+VzfD1PP4jmY5/GS+eIuObGTIAiUu9eiht0LjuAGI+0xCgnaEgsTrOx8H3vLOQ==}
     peerDependencies:
       vue: 3.3.9
     dependencies:
-      vue: 3.3.9(typescript@5.3.2)
+      vue: 3.3.9(typescript@4.9.5)
 
   /@codemirror/autocomplete@6.13.0(@codemirror/language@6.10.1)(@codemirror/state@6.4.1)(@codemirror/view@6.25.1)(@lezer/common@1.2.1):
     resolution: {integrity: sha512-SuDrho1klTINfbcMPnyro1ZxU9xJtwDMtb62R8TjL/tOl71IoOsvBo1a9x+hDvHhIzkTcJHy2VC+rmpGgYkRSw==}
     peerDependencies:
       '@codemirror/language': ^6.0.0
@@ -6118,11 +6124,11 @@ packages:
   /@hoppscotch/vue-toasted@0.1.0(vue@3.3.9):
     resolution: {integrity: sha512-DIgmeTHxWwX5UeaHLEqDYNLJFGRosx/5N1fCHkaO8zt+sZv8GrHlkrIpjfKF2drmA3kKw5cY42Cw7WuCoabR3g==}
     peerDependencies:
       vue: 3.3.9
     dependencies:
-      vue: 3.3.9(typescript@5.3.2)
+      vue: 3.3.9(typescript@4.9.5)
 
   /@humanwhocodes/config-array@0.11.14:
     resolution: {integrity: sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==}
     engines: {node: '>=10.10.0'}
     dependencies:
@@ -8394,11 +8400,11 @@ packages:
       '@types/serve-static': 1.15.0
 
   /@types/graceful-fs@4.1.5:
     resolution: {integrity: sha512-anKkLmZZ+xm4p8JWBf4hElkM4XR+EZeA2M9BAkkTldmcyDY4mbdIJnRghDJH3Ov5ooY7/UAoENtmdMSkaAd7Cw==}
     dependencies:
-      '@types/node': 18.18.8
+      '@types/node': 17.0.45
     dev: true
 
   /@types/har-format@1.2.15:
     resolution: {integrity: sha512-RpQH4rXLuvTXKR0zqHq3go0RVXYv/YVqv4TnPH95VbwUxZdQlK1EtcMvQvMpDngHbt13Csh9Z4qT9AbkiQH5BA==}
     dev: true
@@ -9619,11 +9625,11 @@ packages:
       core-js: 3.32.1
       magic-string: 0.26.7
       regenerator-runtime: 0.13.11
       systemjs: 6.14.2
       terser: 5.27.0
-      vite: 3.2.4(@types/node@18.18.8)(sass@1.58.0)(terser@5.27.0)
+      vite: 3.2.4(@types/node@17.0.27)(terser@5.27.0)
 
   /@vitejs/plugin-legacy@2.3.0(terser@5.27.0)(vite@4.5.0):
     resolution: {integrity: sha512-Bh62i0gzQvvT8AeAAb78nOnqSYXypkRmQmOTImdPZ39meHR9e2une3AIFmVo4s1SDmcmJ6qj18Sa/lRc/14KaA==}
     engines: {node: ^14.18.0 || >=16.0.0}
     peerDependencies:
@@ -10141,11 +10147,11 @@ packages:
         optional: true
     dependencies:
       '@types/web-bluetooth': 0.0.14
       '@vueuse/metadata': 8.7.5
       '@vueuse/shared': 8.7.5(vue@3.3.9)
-      vue: 3.3.9(typescript@5.3.2)
+      vue: 3.3.9(typescript@4.9.5)
       vue-demi: 0.14.6(vue@3.3.9)
 
   /@vueuse/core@9.12.0(vue@3.3.9):
     resolution: {integrity: sha512-h/Di8Bvf6xRcvS/PvUVheiMYYz3U0tH3X25YxONSaAUBa841ayMwxkuzx/DGUMCW/wHWzD8tRy2zYmOC36r4sg==}
     dependencies:
@@ -10200,11 +10206,11 @@ packages:
       '@vue/composition-api':
         optional: true
       vue:
         optional: true
     dependencies:
-      vue: 3.3.9(typescript@5.3.2)
+      vue: 3.3.9(typescript@4.9.5)
       vue-demi: 0.14.6(vue@3.3.9)
 
   /@vueuse/shared@9.12.0(vue@3.3.9):
     resolution: {integrity: sha512-TWuJLACQ0BVithVTRbex4Wf1a1VaRuSpVeyEd4vMUWl54PzlE0ciFUshKCXnlLuD0lxIaLK4Ypj3NXYzZh4+SQ==}
     dependencies:
@@ -11118,11 +11124,10 @@ packages:
     resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==}
     dependencies:
       buffer: 5.7.1
       inherits: 2.0.4
       readable-stream: 3.6.0
-    dev: true
 
   /blob@0.0.5:
     resolution: {integrity: sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig==}
     dev: false
 
@@ -11255,11 +11260,10 @@ packages:
   /buffer@5.7.1:
     resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==}
     dependencies:
       base64-js: 1.5.1
       ieee754: 1.2.1
-    dev: true
 
   /buffer@6.0.3:
     resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==}
     dependencies:
       base64-js: 1.5.1
@@ -11517,10 +11521,14 @@ packages:
       normalize-path: 3.0.0
       readdirp: 3.6.0
     optionalDependencies:
       fsevents: 2.3.3
 
+  /chownr@1.1.4:
+    resolution: {integrity: sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==}
+    dev: false
+
   /chownr@2.0.0:
     resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==}
     engines: {node: '>=10'}
 
   /chrome-trace-event@1.0.3:
@@ -12231,10 +12239,17 @@ packages:
 
   /decimal.js@10.4.3:
     resolution: {integrity: sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==}
     dev: true
 
+  /decompress-response@6.0.0:
+    resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==}
+    engines: {node: '>=10'}
+    dependencies:
+      mimic-response: 3.1.0
+    dev: false
+
   /dedent@0.7.0:
     resolution: {integrity: sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==}
     dev: true
 
   /dedent@1.5.1:
@@ -12625,11 +12640,10 @@ packages:
 
   /end-of-stream@1.4.4:
     resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==}
     dependencies:
       once: 1.4.0
-    dev: true
 
   /engine.io-client@3.5.3:
     resolution: {integrity: sha512-qsgyc/CEhJ6cgMUwxRRtOndGVhIu5hpL5tR4umSpmX/MvkFoIxUTM7oFMDQumHNzlNLwSVy6qhstFPoWTf7dOw==}
     dependencies:
       component-emitter: 1.3.0
@@ -13989,10 +14003,15 @@ packages:
   /exit@0.1.2:
     resolution: {integrity: sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==}
     engines: {node: '>= 0.8.0'}
     dev: true
 
+  /expand-template@2.0.3:
+    resolution: {integrity: sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==}
+    engines: {node: '>=6'}
+    dev: false
+
   /expect@27.5.1:
     resolution: {integrity: sha512-E1q5hSUG2AmYQwQJ041nvgpkODHQvB+RKlB4IYdru6uJsyFTRyZAP463M+1lINorwbqAmUggi6+WwkD8lCS/Dw==}
     engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0}
     dependencies:
       '@jest/types': 27.5.1
@@ -14407,10 +14426,14 @@ packages:
 
   /from@0.1.7:
     resolution: {integrity: sha512-twe20eF1OxVxp/ML/kq2p1uc6KvFK/+vs8WjEbeKmV2He22MKm7YF2ANIt+EOqhJ5L3K/SuuPhk0hWQDjOM23g==}
     dev: false
 
+  /fs-constants@1.0.0:
+    resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==}
+    dev: false
+
   /fs-extra@10.1.0:
     resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==}
     engines: {node: '>=12'}
     dependencies:
       graceful-fs: 4.2.11
@@ -14590,10 +14613,14 @@ packages:
       meow: 8.1.2
       split2: 3.2.2
       through2: 4.0.2
     dev: true
 
+  /github-from-package@0.0.0:
+    resolution: {integrity: sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==}
+    dev: false
+
   /glob-parent@5.1.2:
     resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
     engines: {node: '>= 6'}
     dependencies:
       is-glob: 4.0.3
@@ -15967,10 +15994,18 @@ packages:
     dev: true
 
   /isexe@2.0.0:
     resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
 
+  /isolated-vm@4.7.2:
+    resolution: {integrity: sha512-JVEs5gzWObzZK5+OlBplCdYSpokMcdhLSs/xWYYxmYWVfOOFF4oZJsYh7E/FmfX8e7gMioXMpMMeEyX1afuKrg==}
+    engines: {node: '>=16.0.0'}
+    requiresBuild: true
+    dependencies:
+      prebuild-install: 7.1.2
+    dev: false
+
   /isomorphic-fetch@3.0.0:
     resolution: {integrity: sha512-qvUtwJ3j6qwsF3jLxkZ72qCgjMysPzDfeV240JHiGZsANBYd+EEuu35v7dfrJ9Up0Ak07D7GGSkGhCHTqg/5wA==}
     dependencies:
       node-fetch: 2.6.12
       whatwg-fetch: 3.6.2
@@ -16952,11 +16987,11 @@ packages:
       jest-matcher-utils: 27.5.1
       jest-message-util: 27.5.1
       jest-util: 27.5.1
       natural-compare: 1.4.0
       pretty-format: 27.5.1
-      semver: 7.5.4
+      semver: 7.6.0
     transitivePeerDependencies:
       - supports-color
     dev: true
 
   /jest-snapshot@29.7.0:
@@ -17097,11 +17132,11 @@ packages:
 
   /jest-worker@27.5.1:
     resolution: {integrity: sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==}
     engines: {node: '>= 10.13.0'}
     dependencies:
-      '@types/node': 18.18.8
+      '@types/node': 17.0.45
       merge-stream: 2.0.0
       supports-color: 8.1.1
     dev: true
 
   /jest-worker@29.7.0:
@@ -18002,10 +18037,15 @@ packages:
   /mimic-fn@4.0.0:
     resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==}
     engines: {node: '>=12'}
     dev: true
 
+  /mimic-response@3.1.0:
+    resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==}
+    engines: {node: '>=10'}
+    dev: false
+
   /min-indent@1.0.1:
     resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==}
     engines: {node: '>=4'}
     dev: true
 
@@ -18444,10 +18484,14 @@ packages:
       mjml-validator: 4.13.0
     transitivePeerDependencies:
       - encoding
     dev: false
 
+  /mkdirp-classic@0.5.3:
+    resolution: {integrity: sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==}
+    dev: false
+
   /mkdirp@0.5.6:
     resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==}
     hasBin: true
     dependencies:
       minimist: 1.2.6
@@ -18546,10 +18590,14 @@ packages:
   /nanoid@3.3.7:
     resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==}
     engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
     hasBin: true
 
+  /napi-build-utils@1.0.2:
+    resolution: {integrity: sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==}
+    dev: false
+
   /natural-compare-lite@1.4.0:
     resolution: {integrity: sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==}
     dev: true
 
   /natural-compare@1.4.0:
@@ -18580,10 +18628,17 @@ packages:
     resolution: {integrity: sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==}
     dependencies:
       lower-case: 2.0.2
       tslib: 2.6.2
 
+  /node-abi@3.57.0:
+    resolution: {integrity: sha512-Dp+A9JWxRaKuHP35H77I4kCKesDy5HUDEmScia2FyncMTOXASMyg251F5PhFoDA5uqBrDDffiLpbqnrZmNXW+g==}
+    engines: {node: '>=10'}
+    dependencies:
+      semver: 7.6.0
+    dev: false
+
   /node-abort-controller@3.1.1:
     resolution: {integrity: sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==}
 
   /node-addon-api@5.0.0:
     resolution: {integrity: sha512-CvkDw2OEnme7ybCykJpVcKH+uAOLV2qLqiyla128dN9TkEWfrYmxG6C2boDe5KcNQqZF3orkqzGgOMvZ/JNekA==}
@@ -19455,10 +19510,29 @@ packages:
     engines: {node: '>=10'}
     dependencies:
       punycode: 2.3.0
     dev: false
 
+  /prebuild-install@7.1.2:
+    resolution: {integrity: sha512-UnNke3IQb6sgarcZIDU3gbMeTp/9SSU1DAIkil7PrqG1vZlBtY5msYccSKSHDqa3hNg436IXK+SNImReuA1wEQ==}
+    engines: {node: '>=10'}
+    hasBin: true
+    dependencies:
+      detect-libc: 2.0.1
+      expand-template: 2.0.3
+      github-from-package: 0.0.0
+      minimist: 1.2.6
+      mkdirp-classic: 0.5.3
+      napi-build-utils: 1.0.2
+      node-abi: 3.57.0
+      pump: 3.0.0
+      rc: 1.2.8
+      simple-get: 4.0.1
+      tar-fs: 2.1.1
+      tunnel-agent: 0.6.0
+    dev: false
+
   /prelude-ls@1.1.2:
     resolution: {integrity: sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==}
     engines: {node: '>= 0.8.0'}
     dev: false
 
@@ -19817,11 +19891,10 @@ packages:
   /pump@3.0.0:
     resolution: {integrity: sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==}
     dependencies:
       end-of-stream: 1.4.4
       once: 1.4.0
-    dev: true
 
   /punycode@1.4.1:
     resolution: {integrity: sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==}
 
   /punycode@2.3.0:
@@ -20575,11 +20648,10 @@ packages:
     resolution: {integrity: sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==}
     engines: {node: '>=10'}
     hasBin: true
     dependencies:
       lru-cache: 6.0.0
-    dev: true
 
   /send@0.18.0:
     resolution: {integrity: sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==}
     engines: {node: '>= 0.8.0'}
     dependencies:
@@ -20745,10 +20817,22 @@ packages:
 
   /signedsource@1.0.0:
     resolution: {integrity: sha512-6+eerH9fEnNmi/hyM1DXcRK3pWdoMQtlkQ+ns0ntzunjKqp5i3sKCc80ym8Fib3iaYhdJUOPdhlJWj1tvge2Ww==}
     dev: true
 
+  /simple-concat@1.0.1:
+    resolution: {integrity: sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==}
+    dev: false
+
+  /simple-get@4.0.1:
+    resolution: {integrity: sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==}
+    dependencies:
+      decompress-response: 6.0.0
+      once: 1.4.0
+      simple-concat: 1.0.1
+    dev: false
+
   /sirv@2.0.3:
     resolution: {integrity: sha512-O9jm9BsID1P+0HOi81VpXPoDxYP374pkOLzACAoyUQ/3OUVndNpsz6wMnY2z+yOxzbllCKZrM+9QrWsv4THnyA==}
     engines: {node: '>= 10'}
     dependencies:
       '@polka/url': 1.0.0-next.21
@@ -21465,10 +21549,30 @@ packages:
   /tapable@2.2.1:
     resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==}
     engines: {node: '>=6'}
     dev: true
 
+  /tar-fs@2.1.1:
+    resolution: {integrity: sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==}
+    dependencies:
+      chownr: 1.1.4
+      mkdirp-classic: 0.5.3
+      pump: 3.0.0
+      tar-stream: 2.2.0
+    dev: false
+
+  /tar-stream@2.2.0:
+    resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==}
+    engines: {node: '>=6'}
+    dependencies:
+      bl: 4.1.0
+      end-of-stream: 1.4.4
+      fs-constants: 1.0.0
+      inherits: 2.0.4
+      readable-stream: 3.6.0
+    dev: false
+
   /tar@6.1.13:
     resolution: {integrity: sha512-jdIBIN6LTIe2jqzay/2vtYLlBHa3JF42ot3h1dW8Q0PaAG4v8rm0cvpVePtau5C6OKXGGcgO9q2AMNSWxiLqKw==}
     engines: {node: '>=10'}
     dependencies:
       chownr: 2.0.0
@@ -22135,10 +22239,16 @@ packages:
     dependencies:
       tslib: 1.14.1
       typescript: 4.9.5
     dev: true
 
+  /tunnel-agent@0.6.0:
+    resolution: {integrity: sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==}
+    dependencies:
+      safe-buffer: 5.2.1
+    dev: false
+
   /type-check@0.3.2:
     resolution: {integrity: sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==}
     engines: {node: '>= 0.8.0'}
     dependencies:
       prelude-ls: 1.1.2
@@ -23029,11 +23139,11 @@ packages:
     dependencies:
       '@rollup/pluginutils': 4.2.1
       '@types/eslint': 8.56.2
       eslint: 8.57.0
       rollup: 2.79.1
-      vite: 3.2.4(@types/node@18.18.8)(sass@1.58.0)(terser@5.27.0)
+      vite: 3.2.4(@types/node@17.0.27)(terser@5.27.0)
 
   /vite-plugin-eslint@1.8.1(eslint@8.57.0)(vite@4.5.0):
     resolution: {integrity: sha512-PqdMf3Y2fLO9FsNPmMX+//2BF5SF8nEWspZdgl4kSt7UvHDRHVVfHvxsD7ULYzZrJDGRxR81Nq7TOFgwMnUang==}
     peerDependencies:
       eslint: '>=7'
@@ -23323,10 +23433,44 @@ packages:
       vue-router: 4.2.5(vue@3.3.9)
     transitivePeerDependencies:
       - supports-color
     dev: true
 
+  /vite@3.2.4(@types/node@17.0.27)(terser@5.27.0):
+    resolution: {integrity: sha512-Z2X6SRAffOUYTa+sLy3NQ7nlHFU100xwanq1WDwqaiFiCe+25zdxP1TfCS5ojPV2oDDcXudHIoPnI1Z/66B7Yw==}
+    engines: {node: ^14.18.0 || >=16.0.0}
+    hasBin: true
+    peerDependencies:
+      '@types/node': '>= 14'
+      less: '*'
+      sass: '*'
+      stylus: '*'
+      sugarss: '*'
+      terser: ^5.4.0
+    peerDependenciesMeta:
+      '@types/node':
+        optional: true
+      less:
+        optional: true
+      sass:
+        optional: true
+      stylus:
+        optional: true
+      sugarss:
+        optional: true
+      terser:
+        optional: true
+    dependencies:
+      '@types/node': 17.0.27
+      esbuild: 0.15.18
+      postcss: 8.4.32
+      resolve: 1.22.8
+      rollup: 2.79.1
+      terser: 5.27.0
+    optionalDependencies:
+      fsevents: 2.3.3
+
   /vite@3.2.4(@types/node@18.18.8)(sass@1.58.0)(terser@5.27.0):
     resolution: {integrity: sha512-Z2X6SRAffOUYTa+sLy3NQ7nlHFU100xwanq1WDwqaiFiCe+25zdxP1TfCS5ojPV2oDDcXudHIoPnI1Z/66B7Yw==}
     engines: {node: ^14.18.0 || >=16.0.0}
     hasBin: true
     peerDependencies:
@@ -23744,11 +23888,11 @@ packages:
       vue: 3.3.9
     peerDependenciesMeta:
       '@vue/composition-api':
         optional: true
     dependencies:
-      vue: 3.3.9(typescript@5.3.2)
+      vue: 3.3.9(typescript@4.9.5)
 
   /vue-eslint-parser@9.3.1(eslint@8.47.0):
     resolution: {integrity: sha512-Clr85iD2XFZ3lJ52/ppmUDG/spxQu6+MAeHXjjyI4I1NUYZ9xmenQp4N0oaHJhrA8OOxltCVxMRfANGa70vU0g==}
     engines: {node: ^14.17.0 || >=16.0.0}
     peerDependencies:
@@ -23976,11 +24120,11 @@ packages:
     resolution: {integrity: sha512-F35pjSwC8HS/lnaOd+B59nYR4FZmwuhWAzccK9xftRuWds8SU1TZh5myKVM86j5dFOI7S26O64Kwe7LUHnXjlA==}
     peerDependencies:
       vue: 3.3.9
     dependencies:
       sortablejs: 1.14.0
-      vue: 3.3.9(typescript@5.3.2)
+      vue: 3.3.9(typescript@4.9.5)
 
   /w3c-hr-time@1.0.2:
     resolution: {integrity: sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==}
     deprecated: Use your platform's native performance.now() and performance.timeOrigin.
     dependencies:
@@ -24460,19 +24604,21 @@ packages:
       workbox-core: 7.0.0
     dev: true
 
   /workbox-google-analytics@6.6.0:
     resolution: {integrity: sha512-p4DJa6OldXWd6M9zRl0H6vB9lkrmqYFkRQ2xEiNdBFp9U0LhsGO7hsBscVEyH9H2/3eZZt8c97NB2FD9U2NJ+Q==}
+    deprecated: It is not compatible with newer versions of GA starting with v4, as long as you are using GAv3 it should be ok, but the package is not longer being maintained
     dependencies:
       workbox-background-sync: 6.6.0
       workbox-core: 6.6.0
       workbox-routing: 6.6.0
       workbox-strategies: 6.6.0
     dev: true
 
   /workbox-google-analytics@7.0.0:
     resolution: {integrity: sha512-MEYM1JTn/qiC3DbpvP2BVhyIH+dV/5BjHk756u9VbwuAhu0QHyKscTnisQuz21lfRpOwiS9z4XdqeVAKol0bzg==}
+    deprecated: It is not compatible with newer versions of GA starting with v4, as long as you are using GAv3 it should be ok, but the package is not longer being maintained
     dependencies:
       workbox-background-sync: 7.0.0
       workbox-core: 7.0.0
       workbox-routing: 7.0.0
       workbox-strategies: 7.0.0

Vulnerable code:         uses: actions/checkout@v3
        uses: pnpm/action-setup@v2.2.4
      - name: Setup node
        uses: actions/setup-node@v3
        with:
          node-version: ${{ matrix.node }}
          cache: pnpm

cli(process.argv);
  "version": "0.7.0",
    jest.setTimeout(10000);
    "v": 1,
    "name": "coll-v1",
    "folders": [],
    "requests": [
            "url": "https://httpbin.org",
            "path": "/get",
            "headers": [
              { "key": "Inactive-Header", "value": "Inactive Header", "active": false },
              { "key": "Authorization", "value": "Bearer token123", "active": true }
            ],
            "params": [
              { "key": "key", "value": "value", "active": true },
              { "key": "inactive-key", "value": "inactive-param", "active": false }
            ],
            "name": "req-v0",
            "method": "GET",
            "preRequestScript": "",
            "testScript": "pw.test(\"Asserts request params\", () => {\n  pw.expect(pw.response.body.args.key).toBe(\"value\")\n  pw.expect(pw.response.body.args[\"inactive-key\"]).toBe(undefined)\n})\n\npw.test(\"Asserts request headers\", () => {\n  pw.expect(pw.response.body.headers[\"Authorization\"]).toBe(\"Bearer token123\")\n  pw.expect(pw.response.body.headers[\"Inactive-Header\"]).toBe(undefined)\n})",
            "contentType": "application/json",
            "body": "",
            "auth": "Bearer Token",
            "bearerToken": "token123"
          }
    ]
}
    "folders": [],
            "endpoint": "https://httpbin.org/get",
            "testScript": "pw.test(\"Asserts request params\", () => {\n  pw.expect(pw.response.body.args.key).toBe(\"value\")\n  pw.expect(pw.response.body.args[\"inactive-key\"]).toBe(undefined)\n})\n\npw.test(\"Asserts request headers\", () => {\n  pw.expect(pw.response.body.headers[\"Authorization\"]).toBe(\"Bearer token123\")\n  pw.expect(pw.response.body.headers[\"Inactive-Header\"]).toBe(undefined)\n})",
    "folders": [],
            "endpoint": "https://httpbin.org/get",
            "testScript": "pw.test(\"Asserts request params\", () => {\n  pw.expect(pw.response.body.args.key).toBe(\"value\")\n  pw.expect(pw.response.body.args[\"inactive-key\"]).toBe(undefined)\n})\n\npw.test(\"Asserts request headers\", () => {\n  pw.expect(pw.response.body.headers[\"Authorization\"]).toBe(\"Bearer token123\")\n  pw.expect(pw.response.body.headers[\"Inactive-Header\"]).toBe(undefined)\n})",
    "folders": [],
            "endpoint": "https://httpbin.org/get",
            "testScript": "pw.test(\"Asserts request params\", () => {\n  pw.expect(pw.response.body.args.key).toBe(\"value\")\n  pw.expect(pw.response.body.args[\"inactive-key\"]).toBe(undefined)\n})\n\npw.test(\"Asserts request headers\", () => {\n  pw.expect(pw.response.body.headers[\"Authorization\"]).toBe(\"Bearer token123\")\n  pw.expect(pw.response.body.headers[\"Inactive-Header\"]).toBe(undefined)\n})",
      "auth": { "authType": "none", "authActive": true },
      "body": { "body": null, "contentType": null },
      "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})",
      "auth": { "authType": "none", "authActive": true },
      "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})",
      "auth": { "authType": "none", "authActive": true },
      "body": { "body": null, "contentType": null },
      "endpoint": "<<baseURL>>/get",
      "body": { "body": null, "contentType": null },
      "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});",
      "body": { "body": null, "contentType": null },
      "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});",
      "auth": { "authType": "none", "authActive": true },
      "body": { "body": null, "contentType": null },
      "endpoint": "<<baseURL>>",
  "auth": { "authType": "inherit", "authActive": false },
}
  "name": "secret-envs-setters-coll",
      "endpoint": "<<baseURL>>/headers",
      "testScript": "pw.test(\"Successfully parses secret variable holding the header value\", () => {\n    const secretHeaderValue = pw.env.getResolve(\"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.getResolve(\"secretHeaderValueFromPreReqScript\")).toBe(\"secret-header-value\")\n})",
      "endpoint": "<<baseURL>>/headers",
      "testScript": "pw.test(\"Value set at the pre-request script takes precedence\", () => {\n    const secretHeaderValue = pw.env.getResolve(\"secretHeaderValue\")\n    pw.expect(secretHeaderValue).toBe(\"secret-header-value-overriden\")\n    \n    if (secretHeaderValue) {\n      pw.expect(pw.response.body.headers[\"Secret-Header-Key\"]).toBe(secretHeaderValue)\n    }\n\n    pw.expect(pw.env.getResolve(\"secretHeaderValueFromPreReqScript\")).toBe(\"secret-header-value-overriden\")\n})",
      "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})",
      "endpoint": "<<baseURL>>/get",
      "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});",
      "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});",
}
      "endpoint": "https://httpbin.org/post",
      "testScript": "pw.test(\"Secret environment value set from the pre-request script takes precedence\", () => {\n  pw.expect(pw.env.get(\"preReqVarOne\")).toBe(\"pre-req-value-one\")\n})\n\npw.test(\"Successfully sets initial value for the secret variable from the pre-request script\", () => {\n  pw.env.set(\"postReqVarTwo\", \"post-req-value-two\")\n  pw.expect(pw.env.get(\"postReqVarTwo\")).toBe(\"post-req-value-two\")\n})\n\npw.test(\"Successfully resolves secret variable values referred in request headers that are set in pre-request sccript\", () => {\n  pw.expect(pw.response.body.headers[\"Custom-Header\"]).toBe(\"custom-header-secret-value\")\n})\n\npw.test(\"Successfully resolves secret variable values referred in request body that are set in pre-request sccript\", () => {\n  pw.expect(pw.response.body.json.key).toBe(\"custom-body-value\")\n})\n\npw.test(\"Secret environment variable set from the post-request script takes precedence\", () => {\n  pw.env.set(\"postReqVarOne\", \"post-req-value-one\")\n  pw.expect(pw.env.get(\"postReqVarOne\")).toBe(\"post-req-value-one\")\n})\n\npw.test(\"Successfully sets initial value for the secret variable from the post-request script\", () => {\n  pw.env.set(\"postReqVarTwo\", \"post-req-value-two\")\n  pw.expect(pw.env.get(\"postReqVarTwo\")).toBe(\"post-req-value-two\")\n})\n\npw.test(\"Successfully removes environment variables via the pw.env.unset method\", () => {\n  pw.env.unset(\"preReqVarOne\")\n  pw.env.unset(\"postReqVarTwo\")\n\n  pw.expect(pw.env.get(\"preReqVarOne\")).toBe(undefined)\n  pw.expect(pw.env.get(\"postReqVarTwo\")).toBe(undefined)\n})",
      "key": "baseURL",
      "key": "baseURL",
export const runCLI = (args: string, options = {}): Promise<ExecResponse> =>
  {
    const CLI_PATH = resolve(__dirname, "../../bin/hopp");
    const command = `node ${CLI_PATH} ${args}`

    return new Promise((resolve) =>
      exec(command, options, (error, stdout, stderr) => resolve({ error, stdout, stderr }))
    );
  }
export const getTestJsonFilePath = (file: string, kind: "collection" | "environment") => {
  const filePath = resolve(__dirname, `../../src/__tests__/samples/${kindDir}/${file}`);
const program = new Command()
  return collectionSchemaParsedResult.data.map((collection) => {
    const requestSchemaParsedResult = z
      .array(entityReference(HoppRESTRequest))
      .safeParse(collection.requests);

    if (!requestSchemaParsedResult.success) {
      throw error({
        code: "MALFORMED_COLLECTION",
        path,
        data: "Please check the collection data.",
      });
    }

    return {
      ...collection,
      requests: requestSchemaParsedResult.data,
    };
  });
export default {
  preset: "ts-jest",
  testEnvironment: "jsdom",
  collectCoverage: true,
  setupFilesAfterEnv: ["./jest.setup.ts"],
  moduleNameMapper: {
    "~/(.*)": "<rootDir>/src/$1",
    "^lodash-es$": "lodash",
  },
}
require("@relmify/jest-fp-ts")
export { default } from "./dist/node.d.ts"
export * from "./dist/node.d.ts"
    "test": "pnpm exec jest",
    "jest": "27.5.1",
    "vite": "5.0.5"
import { runPreRequestScript } from "~/pre-request/node-vm"
import { runTestScript } from "~/test-runner/node-vm"
import "@relmify/jest-fp-ts"
import { runTestScript } from "~/test-runner/node-vm"
import "@relmify/jest-fp-ts"
import { runTestScript } from "~/test-runner/node-vm"
import { runTestScript } from "~/test-runner/node-vm"
import { runTestScript } from "~/test-runner/node-vm"
import { runTestScript } from "~/test-runner/node-vm"
import "@relmify/jest-fp-ts"
import { runTestScript } from "~/test-runner/node-vm"
              pw.expect(2).toBe(2)
import "@relmify/jest-fp-ts"
import { runTestScript } from "~/test-runner/node-vm"
import { runTestScript } from "~/test-runner/node-vm"
import { runTestScript } from "~/test-runner/node-vm"
import { runTestScript } from "~/test-runner/node-vm"
import "@relmify/jest-fp-ts"
import { runPreRequestScript } from "~/pre-request/node-vm"
import { preventCyclicObjects } from "~/utils"
import { runTestScript } from "~/test-runner/node-vm"
export * from "./pre-request/node-vm"
export * from "./test-runner/node-vm"
import { pipe } from "fp-ts/function"
import * as TE from "fp-ts/lib/TaskEither"
import { createContext, runInContext } from "vm"

import { TestResult } from "~/types"
import { getPreRequestScriptMethods } from "~/utils"

export const runPreRequestScript = (
  preRequestScript: string,
  envs: TestResult["envs"]
): TE.TaskEither<string, TestResult["envs"]> =>
  pipe(
    TE.tryCatch(
      async () => {
        return createContext()
      },
      (reason) => `Context initialization failed: ${reason}`
    ),
    TE.chain((context) =>
      TE.tryCatch(
        () =>
          new Promise((resolve) => {
            const { pw, updatedEnvs } = getPreRequestScriptMethods(envs)

            // Expose pw to the context
            context.pw = pw
            context.atob = atob
            context.btoa = btoa

            // Run the pre-request script in the provided context
            runInContext(preRequestScript, context)

            resolve(updatedEnvs)
          }),
        (reason) => `Script execution failed: ${reason}`
      )
    )
  )
    let assertion = expectVal === expectedVal
    const message = `Expected '${expectVal}' to${
    const parsedExpectVal = parseInt(expectVal)
      const message = `Expected ${level}-level status but could not parse value '${expectVal}'`
      let assertion = typeof expectVal === expectedType
      const message = `Expected '${expectVal}' to${
    if (!(Array.isArray(expectVal) || typeof expectVal === "string")) {
      let assertion = expectVal.length === expectedLength
    if (!(Array.isArray(expectVal) || typeof expectVal === "string")) {
    let assertion = expectVal.includes(needle)
    const expectValPretty = JSON.stringify(expectVal)
import * as E from "fp-ts/Either"
import * as TE from "fp-ts/TaskEither"
import { pipe } from "fp-ts/function"
import { createContext, runInContext } from "vm"

import { TestResponse, TestResult } from "~/types"
import { getTestRunnerScriptMethods, preventCyclicObjects } from "~/utils"

export const runTestScript = (
  testScript: string,
  envs: TestResult["envs"],
  response: TestResponse
): TE.TaskEither<string, TestResult> =>
  pipe(
    TE.tryCatch(
      async () => {
        return createContext()
      },
      (reason) => `Context initialization failed: ${reason}`
    ),
    TE.chain((context) =>
      TE.tryCatch(
        () => executeScriptInContext(testScript, envs, response, context),
        (reason) => `Script execution failed: ${reason}`
      )
    )
  )

const executeScriptInContext = (
  testScript: string,
  envs: TestResult["envs"],
  response: TestResponse,
  context: any
): Promise<TestResult> => {
  return new Promise((resolve, reject) => {
    // Parse response object
    const responseObjHandle = preventCyclicObjects(response)
    if (E.isLeft(responseObjHandle)) {
      return reject(`Response parsing failed: ${responseObjHandle.left}`)
    }

    const { pw, testRunStack, updatedEnvs } = getTestRunnerScriptMethods(envs)

    // Expose pw to the context
    context.pw = { ...pw, response: responseObjHandle.right }
    context.atob = atob
    context.btoa = btoa

    // Run the test script in the provided context
    runInContext(testScript, context)

    resolve({
      tests: testRunStack,
      envs: updatedEnvs,
    })
  })
}
export * from "./pre-request/web-worker"
export * from "./test-runner/web-worker"
import { getPreRequestScriptMethods } from "~/utils"
import { getTestRunnerScriptMethods, preventCyclicObjects } from "~/utils"
        web: "./src/web.ts",
        node: "./src/node.ts",
      external: ["vm"],
export { default } from "./dist/web.d.ts"
export * from "./dist/web.d.ts"
      jest:
        specifier: 27.5.1
        version: 27.5.1
      vue: 3.3.9(typescript@5.3.2)
      vue: 3.3.9(typescript@5.3.2)
      '@types/node': 18.18.8
      vite: 3.2.4(@types/node@18.18.8)(sass@1.58.0)(terser@5.27.0)
      vue: 3.3.9(typescript@5.3.2)
      vue: 3.3.9(typescript@5.3.2)
    dev: true
    dev: true
    dev: true
      semver: 7.5.4
      '@types/node': 18.18.8
    dev: true
    dev: true
      vite: 3.2.4(@types/node@18.18.8)(sass@1.58.0)(terser@5.27.0)
      vue: 3.3.9(typescript@5.3.2)
      vue: 3.3.9(typescript@5.3.2)
Fixed code:         uses: actions/checkout@v4
      - name: Setup node
        uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node-version }}

        uses: pnpm/action-setup@v3
// @ts-check
import { spawnSync } from "child_process";
import { cloneDeep } from "lodash-es";

const nodeVersion = parseInt(process.versions.node.split(".")[0]);

// As per isolated-vm documentation, we need to supply `--no-node-snapshot` for node >= 20
// src: https://github.com/laverdet/isolated-vm?tab=readme-ov-file#requirements
if (nodeVersion >= 20 && !process.execArgv.includes("--no-node-snapshot")) {
  const argCopy = cloneDeep(process.argv);

  // Replace first argument with --no-node-snapshot
  // We can get argv[0] from process.argv0
  argCopy[0] = "--no-node-snapshot";

  const result = spawnSync(
    process.argv0,
    argCopy,
    { stdio: "inherit" }
  );

  // Exit with the same status code as the spawned process
  process.exit(result.status ?? 0);
} else {
  cli(process.argv);
}
  "version": "0.7.1",
    "isolated-vm": "4.7.2",
    jest.setTimeout(100000);
  "v": 1,
  "name": "coll-v1",
  "folders": [
    {
      "v": 1,
      "name": "coll-v1-child",
      "folders": [],
      "requests": [
          "url": "https://echo.hoppscotch.io",
          "path": "/get",
          "headers": [
            { "key": "Inactive-Header", "value": "Inactive Header", "active": false },
            { "key": "Authorization", "value": "Bearer token123", "active": true }
          ],
          "params": [
            { "key": "key", "value": "value", "active": true },
            { "key": "inactive-key", "value": "inactive-param", "active": false }
          ],
          "name": "req-v0-II",
          "method": "GET",
          "preRequestScript": "",
          "testScript": "pw.test(\"Asserts request params\", () => {\n  pw.expect(pw.response.body.args.key).toBe(\"value\")\n  pw.expect(pw.response.body.args[\"inactive-key\"]).toBe(undefined)\n})\n\npw.test(\"Asserts request headers\", () => {\n  pw.expect(pw.response.body.headers[\"authorization\"]).toBe(\"Bearer token123\")\n  pw.expect(pw.response.body.headers[\"inactive-header\"]).toBe(undefined)\n})",
          "contentType": "application/json",
          "body": "",
          "auth": "Bearer Token",
          "bearerToken": "token123"
        }
      ]
    }
  ],
  "requests": [
    {
      "url": "https://echo.hoppscotch.io",
      "path": "/get",
      "headers": [
        { "key": "Inactive-Header", "value": "Inactive Header", "active": false },
        { "key": "Authorization", "value": "Bearer token123", "active": true }
      ],
      "params": [
        { "key": "key", "value": "value", "active": true },
        { "key": "inactive-key", "value": "inactive-param", "active": false }
      ],
      "name": "req-v0",
      "method": "GET",
      "preRequestScript": "",
      "testScript": "pw.test(\"Asserts request params\", () => {\n  pw.expect(pw.response.body.args.key).toBe(\"value\")\n  pw.expect(pw.response.body.args[\"inactive-key\"]).toBe(undefined)\n})\n\npw.test(\"Asserts request headers\", () => {\n  pw.expect(pw.response.body.headers[\"authorization\"]).toBe(\"Bearer token123\")\n  pw.expect(pw.response.body.headers[\"inactive-header\"]).toBe(undefined)\n})",
      "contentType": "application/json",
      "body": "",
      "auth": "Bearer Token",
      "bearerToken": "token123"
    }
  ]
}
    "folders": [
        {
            "v": 1,
            "name": "coll-v1-child",
            "folders": [],
            "requests": [
                {
                    "v": "1",
                    "endpoint": "https://echo.hoppscotch.io",
                    "headers": [
                        {
                            "key": "Inactive-Header",
                            "value": "Inactive Header",
                            "active": false
                        },
                        {
                            "key": "Authorization",
                            "value": "Bearer token123",
                            "active": true
                        }
                    ],
                    "params": [
                        {
                            "key": "key",
                            "value": "value",
                            "active": true
                        },
                        {
                            "key": "inactive-key",
                            "value": "inactive-param",
                            "active": false
                        }
                    ],
                    "name": "req-v1-II",
                    "method": "GET",
                    "preRequestScript": "",
                    "testScript": "pw.test(\"Asserts request params\", () => {\n  pw.expect(pw.response.body.args.key).toBe(\"value\")\n  pw.expect(pw.response.body.args[\"inactive-key\"]).toBe(undefined)\n})\n\npw.test(\"Asserts request headers\", () => {\n  pw.expect(pw.response.body.headers[\"authorization\"]).toBe(\"Bearer token123\")\n  pw.expect(pw.response.body.headers[\"inactive-header\"]).toBe(undefined)\n})",
                    "body": {
                        "contentType": null,
                        "body": null
                    },
                    "auth": {
                        "authType": "bearer",
                        "authActive": true,
                        "token": "token123"
                    }
                }
            ]
        }
    ],
            "endpoint": "https://echo.hoppscotch.io",
            "testScript": "pw.test(\"Asserts request params\", () => {\n  pw.expect(pw.response.body.args.key).toBe(\"value\")\n  pw.expect(pw.response.body.args[\"inactive-key\"]).toBe(undefined)\n})\n\npw.test(\"Asserts request headers\", () => {\n  pw.expect(pw.response.body.headers[\"authorization\"]).toBe(\"Bearer token123\")\n  pw.expect(pw.response.body.headers[\"inactive-header\"]).toBe(undefined)\n})",
    "folders": [
        {
            "v": 2,
            "name": "coll-v2-child",
            "folders": [],
            "requests": [
                {
                    "v": "2",
                    "endpoint": "https://echo.hoppscotch.io",
                    "headers": [
                        {
                            "key": "Inactive-Header",
                            "value": "Inactive Header",
                            "active": false
                        },
                        {
                            "key": "Authorization",
                            "value": "Bearer token123",
                            "active": true
                        }
                    ],
                    "params": [
                        {
                            "key": "key",
                            "value": "value",
                            "active": true
                        },
                        {
                            "key": "inactive-key",
                            "value": "inactive-param",
                            "active": false
                        }
                    ],
                    "name": "req-v2-II",
                    "method": "GET",
                    "preRequestScript": "",
                    "testScript": "pw.test(\"Asserts request params\", () => {\n  pw.expect(pw.response.body.args.key).toBe(\"value\")\n  pw.expect(pw.response.body.args[\"inactive-key\"]).toBe(undefined)\n})\n\npw.test(\"Asserts request headers\", () => {\n  pw.expect(pw.response.body.headers[\"authorization\"]).toBe(\"Bearer token123\")\n  pw.expect(pw.response.body.headers[\"inactive-header\"]).toBe(undefined)\n})",
                    "body": {
                        "contentType": null,
                        "body": null
                    },
                    "auth": {
                        "authType": "bearer",
                        "authActive": true,
                        "token": "token123"
                    },
                    "requestVariables": []
                }
            ],
            "auth": {
                "authType": "inherit",
                "authActive": true
            },
            "headers": []
        }
    ],
            "endpoint": "https://echo.hoppscotch.io",
            "testScript": "pw.test(\"Asserts request params\", () => {\n  pw.expect(pw.response.body.args.key).toBe(\"value\")\n  pw.expect(pw.response.body.args[\"inactive-key\"]).toBe(undefined)\n})\n\npw.test(\"Asserts request headers\", () => {\n  pw.expect(pw.response.body.headers[\"authorization\"]).toBe(\"Bearer token123\")\n  pw.expect(pw.response.body.headers[\"inactive-header\"]).toBe(undefined)\n})",
    "folders": [
        {
            "v": 2,
            "name": "coll-v2-child",
            "folders": [],
            "requests": [
                {
                    "v": "3",
                    "endpoint": "https://echo.hoppscotch.io",
                    "headers": [
                        {
                            "key": "Inactive-Header",
                            "value": "Inactive Header",
                            "active": false
                        },
                        {
                            "key": "Authorization",
                            "value": "Bearer token123",
                            "active": true
                        }
                    ],
                    "params": [
                        {
                            "key": "key",
                            "value": "value",
                            "active": true
                        },
                        {
                            "key": "inactive-key",
                            "value": "inactive-param",
                            "active": false
                        }
                    ],
                    "name": "req-v3-II",
                    "method": "GET",
                    "preRequestScript": "",
                    "testScript": "pw.test(\"Asserts request params\", () => {\n  pw.expect(pw.response.body.args.key).toBe(\"value\")\n  pw.expect(pw.response.body.args[\"inactive-key\"]).toBe(undefined)\n})\n\npw.test(\"Asserts request headers\", () => {\n  pw.expect(pw.response.body.headers[\"authorization\"]).toBe(\"Bearer token123\")\n  pw.expect(pw.response.body.headers[\"inactive-header\"]).toBe(undefined)\n})",
                    "body": {
                        "contentType": null,
                        "body": null
                    },
                    "auth": {
                        "authType": "bearer",
                        "authActive": true,
                        "token": "token123"
                    },
                    "requestVariables": []
                }
            ],
            "auth": {
                "authType": "inherit",
                "authActive": true
            },
            "headers": []
        }
    ],
            "endpoint": "https://echo.hoppscotch.io",
            "testScript": "pw.test(\"Asserts request params\", () => {\n  pw.expect(pw.response.body.args.key).toBe(\"value\")\n  pw.expect(pw.response.body.args[\"inactive-key\"]).toBe(undefined)\n})\n\npw.test(\"Asserts request headers\", () => {\n  pw.expect(pw.response.body.headers[\"authorization\"]).toBe(\"Bearer token123\")\n  pw.expect(pw.response.body.headers[\"inactive-header\"]).toBe(undefined)\n})",
      "auth": {
        "authType": "none",
        "authActive": true
      },
      "body": {
        "body": null,
        "contentType": null
      },
      "endpoint": "<<echoHoppBaseURL>>/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})",
      "auth": {
        "authType": "none",
        "authActive": true
      },
      "endpoint": "<<echoHoppBaseURL>>/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(JSON.parse(pw.response.body.data).secretBodyKey).toBe(secretBodyValue)\n    }\n\n    pw.expect(pw.env.get(\"secretBodyValueFromPreReqScript\")).toBe(\"secret-body-value\")\n})",
      "auth": {
        "authType": "none",
        "authActive": true
      },
      "body": {
        "body": null,
        "contentType": null
      },
      "endpoint": "<<echoHoppBaseURL>>",
      "body": {
        "body": null,
        "contentType": null
      },
      "endpoint": "<<httpbinBaseURL>>/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    // The endpoint at times results in a `502` bad gateway\n    if (pw.response.status !== 200) {\n      return\n    }\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});",
      "body": {
        "body": null,
        "contentType": null
      },
      "endpoint": "<<httpbinBaseURL>>/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    // Safeguard to prevent test failures due to the endpoint\n    if (pw.response.status !== 200) {\n      return\n    }\n\n    if (secretBearerToken) { \n      pw.expect(pw.response.body.token).toBe(secretBearerToken)\n      pw.expect(preReqSecretBearerToken).toBe(\"test-token\")\n    }\n});",
      "auth": {
        "authType": "none",
        "authActive": true
      },
      "body": {
        "body": null,
        "contentType": null
      },
      "endpoint": "<<echoHoppBaseURL>>",
  "auth": {
    "authType": "inherit",
    "authActive": false
  },
}
  "name": "secret-envs-persistence-coll",
      "endpoint": "<<echoHoppBaseURL>>",
      "testScript": "pw.test(\"Successfully parses secret variable holding the header value\", () => {\n    const secretHeaderValue = pw.env.getResolve(\"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.getResolve(\"secretHeaderValueFromPreReqScript\")).toBe(\"secret-header-value\")\n})",
      "endpoint": "<<echoHoppBaseURL>>",
      "testScript": "pw.test(\"Value set at the pre-request script takes precedence\", () => {\n    const secretHeaderValue = pw.env.getResolve(\"secretHeaderValue\")\n    pw.expect(secretHeaderValue).toBe(\"secret-header-value-overriden\")\n    \n    if (secretHeaderValue) {\n      pw.expect(pw.response.body.headers[\"secret-header-key\"]).toBe(secretHeaderValue)\n    }\n\n    pw.expect(pw.env.getResolve(\"secretHeaderValueFromPreReqScript\")).toBe(\"secret-header-value-overriden\")\n})",
      "endpoint": "<<echoHoppBaseURL>>/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(JSON.parse(pw.response.body.data).secretBodyKey).toBe(secretBodyValue)\n    }\n\n    pw.expect(pw.env.get(\"secretBodyValueFromPreReqScript\")).toBe(\"secret-body-value\")\n})",
      "endpoint": "<<echoHoppBaseURL>>",
      "endpoint": "<<httpbinBaseURL>>/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    // The endpoint at times results in a `502` bad gateway\n    if (pw.response.status !== 200) {\n      return\n    }\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});",
      "endpoint": "<<httpbinBaseURL>>/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    // Safeguard to prevent test failures due to the endpoint\n    if (pw.response.status !== 200) {\n      return\n    }\n\n    if (secretBearerToken) { \n      pw.expect(pw.response.body.token).toBe(secretBearerToken)\n      pw.expect(preReqSecretBearerToken).toBe(\"test-token\")\n    }\n});",
}
      "endpoint": "https://echo.hoppscotch.io/post",
      "testScript": "pw.test(\"Secret environment value set from the pre-request script takes precedence\", () => {\n  pw.expect(pw.env.get(\"preReqVarOne\")).toBe(\"pre-req-value-one\")\n})\n\npw.test(\"Successfully sets initial value for the secret variable from the pre-request script\", () => {\n  pw.env.set(\"postReqVarTwo\", \"post-req-value-two\")\n  pw.expect(pw.env.get(\"postReqVarTwo\")).toBe(\"post-req-value-two\")\n})\n\npw.test(\"Successfully resolves secret variable values referred in request headers that are set in pre-request script\", () => {\n  pw.expect(pw.response.body.headers[\"custom-header\"]).toBe(\"custom-header-secret-value\")\n})\n\npw.test(\"Successfully resolves secret variable values referred in request body that are set in pre-request script\", () => {\n  pw.expect(JSON.parse(pw.response.body.data).key).toBe(\"custom-body-value\")\n})\n\npw.test(\"Secret environment variable set from the post-request script takes precedence\", () => {\n  pw.env.set(\"postReqVarOne\", \"post-req-value-one\")\n  pw.expect(pw.env.get(\"postReqVarOne\")).toBe(\"post-req-value-one\")\n})\n\npw.test(\"Successfully sets initial value for the secret variable from the post-request script\", () => {\n  pw.env.set(\"postReqVarTwo\", \"post-req-value-two\")\n  pw.expect(pw.env.get(\"postReqVarTwo\")).toBe(\"post-req-value-two\")\n})\n\npw.test(\"Successfully removes environment variables via the pw.env.unset method\", () => {\n  pw.env.unset(\"preReqVarOne\")\n  pw.env.unset(\"postReqVarTwo\")\n\n  pw.expect(pw.env.get(\"preReqVarOne\")).toBe(undefined)\n  pw.expect(pw.env.get(\"postReqVarTwo\")).toBe(undefined)\n})",
      "key": "echoHoppBaseURL",
      "value": "https://echo.hoppscotch.io",
      "secret": false
    },
    {
      "key": "httpbinBaseURL",
      "key": "echoHoppBaseURL",
      "value": "https://echo.hoppscotch.io",
      "secret": false
    },
    {
      "key": "httpbinBaseURL",
export const runCLI = (args: string, options = {}): Promise<ExecResponse> => {
  const CLI_PATH = resolve(__dirname, "../../bin/hopp.js");
  const command = `node ${CLI_PATH} ${args}`;

  return new Promise((resolve) =>
    exec(command, options, (error, stdout, stderr) =>
      resolve({ error, stdout, stderr })
    )
  );
};
export const getTestJsonFilePath = (
  file: string,
  kind: "collection" | "environment"
) => {
  const filePath = resolve(
    __dirname,
    `../../src/__tests__/samples/${kindDir}/${file}`
  );

const program = new Command();
const getValidRequests = (
  collections: HoppCollection[],
  collectionFilePath: string
) => {
  return collections.map((collection) => {
    // Validate requests using zod schema
    const requestSchemaParsedResult = z
      .array(entityReference(HoppRESTRequest))
      .safeParse(collection.requests);

    // Handle validation errors
    if (!requestSchemaParsedResult.success) {
      throw error({
        code: "MALFORMED_COLLECTION",
        path: collectionFilePath,
        data: "Please check the collection data.",
      });
    }

    // Recursively validate requests in nested folders
    if (collection.folders.length > 0) {
      collection.folders = getValidRequests(
        collection.folders,
        collectionFilePath
      );
    }

    // Return validated collection
    return {
      ...collection,
      requests: requestSchemaParsedResult.data,
    };
  });
};

  return getValidRequests(collectionSchemaParsedResult.data, path);
export { default } from "./dist/node/index.d.ts"
export * from "./dist/node/index.d.ts"
    "test": "vitest run",
    "vite": "5.0.5",
    "vitest": "0.34.6"
  },
  "peerDependencies": {
    "isolated-vm": "4.7.2"
  },
  "peerDependenciesMeta": {
    "isolated-vm": {
      "optional": true
    }
// Vitest doesn't work without globals
// Ref: https://github.com/relmify/jest-fp-ts/issues/11

import decodeMatchers from "@relmify/jest-fp-ts/dist/decodeMatchers"
import eitherMatchers from "@relmify/jest-fp-ts/dist/eitherMatchers"
import optionMatchers from "@relmify/jest-fp-ts/dist/optionMatchers"
import theseMatchers from "@relmify/jest-fp-ts/dist/theseMatchers"
import eitherOrTheseMatchers from "@relmify/jest-fp-ts/dist/eitherOrTheseMatchers"
import { expect } from "vitest"

expect.extend(decodeMatchers.matchers)
expect.extend(eitherMatchers.matchers)
expect.extend(optionMatchers.matchers)
expect.extend(theseMatchers.matchers)
expect.extend(eitherOrTheseMatchers.matchers)
import { describe, expect, test } from "vitest"

import { runPreRequestScript, runTestScript } from "~/node"
import { describe, expect, test } from "vitest"

import { runTestScript } from "~/node"
import { describe, expect, test } from "vitest"

import { runTestScript } from "~/node"
import { describe, expect, test } from "vitest"

import { runTestScript } from "~/node"
import { describe, expect, test } from "vitest"

import { runTestScript } from "~/node"
import { describe, expect, test } from "vitest"

import { runTestScript } from "~/node"
import { describe, expect, test } from "vitest"

import { runTestScript } from "~/node"
            pw.expect(2).toBe(2)
import { describe, expect, test } from "vitest"

import { runTestScript } from "~/node"
import { describe, expect, test } from "vitest"

import { runTestScript } from "~/node"
import { describe, expect, test } from "vitest"

import { runTestScript } from "~/node"
import { describe, expect, test } from "vitest"

import { runTestScript } from "~/node"
import { describe, expect, test } from "vitest"
import { runPreRequestScript } from "~/node"
import { preventCyclicObjects } from "~/shared-utils"

import { describe, expect, test } from "vitest"
import { describe, expect, test } from "vitest"

import { runTestScript } from "~/node"
export { runPreRequestScript } from "./pre-request"
export { runTestScript } from "./test-runner"
import { pipe } from "fp-ts/function"
import * as TE from "fp-ts/lib/TaskEither"
import { createRequire } from "module"

import type ivmT from "isolated-vm"

import { TestResult } from "~/types"
import { getPreRequestScriptMethods } from "~/shared-utils"
import { getSerializedAPIMethods } from "./utils"

const nodeRequire = createRequire(import.meta.url)
const ivm = nodeRequire("isolated-vm")

export const runPreRequestScript = (
  preRequestScript: string,
  envs: TestResult["envs"]
): TE.TaskEither<string, TestResult["envs"]> =>
  pipe(
    TE.tryCatch(
      async () => {
        const isolate: ivmT.Isolate = new ivm.Isolate()
        const context = await isolate.createContext()
        return { isolate, context }
      },
      (reason) => `Context initialization failed: ${reason}`
    ),
    TE.chain(({ isolate, context }) =>
      pipe(
        TE.tryCatch(
          async () => {
            const jail = context.global

            const { pw, updatedEnvs } = getPreRequestScriptMethods(envs)

            const serializedAPIMethods = getSerializedAPIMethods(pw)
            jail.setSync("serializedAPIMethods", serializedAPIMethods, {
              copy: true,
            })

            jail.setSync("atob", atob)
            jail.setSync("btoa", btoa)

            // Methods in the isolate context can't be invoked straightaway
            const finalScript = `
              const pw = new Proxy(serializedAPIMethods, {
                get: (pwObjTarget, pwObjProp) => {
                  const topLevelEntry = pwObjTarget[pwObjProp]

                  // "pw.env" set of API methods
                    if (topLevelEntry && typeof topLevelEntry === "object") {
                      return new Proxy(topLevelEntry, {
                        get: (subTarget, subProp) => {
                          const subLevelProperty = subTarget[subProp]
                          if (subLevelProperty && subLevelProperty.typeof === "function") {
                            return (...args) => subLevelProperty.applySync(null, args)
                          }
                        },
                      })
                    }
                }
              })

              ${preRequestScript}
            `

            // Create a script and compile it
            const script = await isolate.compileScript(finalScript)

            // Run the pre-request script in the provided context
            await script.run(context)

            return updatedEnvs
          },
          (reason) => reason
        ),
        TE.fold(
          (error) => TE.left(`Script execution failed: ${error}`),
          (result) =>
            pipe(
              TE.tryCatch(
                async () => {
                  await isolate.dispose()
                  return result
                },
                (disposeError) => `Isolate disposal failed: ${disposeError}`
              )
            )
        )
      )
    )
  )
import * as E from "fp-ts/Either"
import * as TE from "fp-ts/TaskEither"
import { pipe } from "fp-ts/function"
import { createRequire } from "module"

import type ivmT from "isolated-vm"

import { TestResponse, TestResult } from "~/types"
import {
  getTestRunnerScriptMethods,
  preventCyclicObjects,
} from "~/shared-utils"
import { getSerializedAPIMethods } from "./utils"

const nodeRequire = createRequire(import.meta.url)
const ivm = nodeRequire("isolated-vm")

export const runTestScript = (
  testScript: string,
  envs: TestResult["envs"],
  response: TestResponse
): TE.TaskEither<string, TestResult> =>
  pipe(
    TE.tryCatch(
      async () => {
        const isolate: ivmT.Isolate = new ivm.Isolate()
        const context = await isolate.createContext()
        return { isolate, context }
      },
      (reason) => `Context initialization failed: ${reason}`
    ),
    TE.chain(({ isolate, context }) =>
      pipe(
        TE.tryCatch(
          async () =>
            executeScriptInContext(
              testScript,
              envs,
              response,
              isolate,
              context
            ),
          (reason) => `Script execution failed: ${reason}`
        ),
        TE.chain((result) =>
          TE.tryCatch(
            async () => {
              await isolate.dispose()
              return result
            },
            (disposeReason) => `Isolate disposal failed: ${disposeReason}`
          )
        )
      )
    )
  )
const executeScriptInContext = (
  testScript: string,
  envs: TestResult["envs"],
  response: TestResponse,
  isolate: ivmT.Isolate,
  context: ivmT.Context
): Promise<TestResult> => {
  return new Promise((resolve, reject) => {
    // Parse response object
    const responseObjHandle = preventCyclicObjects(response)
    if (E.isLeft(responseObjHandle)) {
      return reject(`Response parsing failed: ${responseObjHandle.left}`)
    }

    const jail = context.global

    const { pw, testRunStack, updatedEnvs } = getTestRunnerScriptMethods(envs)

    const serializedAPIMethods = getSerializedAPIMethods({
      ...pw,
      response: responseObjHandle.right,
    })
    jail.setSync("serializedAPIMethods", serializedAPIMethods, { copy: true })

    jail.setSync("atob", atob)
    jail.setSync("btoa", btoa)

    jail.setSync("ivm", ivm)

    // Methods in the isolate context can't be invoked straightaway
    const finalScript = `
    const pw = new Proxy(serializedAPIMethods, {
      get: (pwObj, pwObjProp) => {
        // pw.expect(), pw.env, etc.
        const topLevelEntry = pwObj[pwObjProp]

        // If the entry exists and is a function
        // pw.expect(), pw.test(), etc.
        if (topLevelEntry && topLevelEntry.typeof === "function") {
          // pw.test() just involves invoking the function via "applySync()"
          if (pwObjProp === "test") {
            return (...args) => topLevelEntry.applySync(null, args)
          }

          // pw.expect() returns an object with matcher methods
          return (...args) => {
            // Invoke "pw.expect()" and get access to the object with matcher methods
            const expectFnResult = topLevelEntry.applySync(
              null,
              args.map((expectVal) => {
                if (typeof expectVal === "object") {
                  if (expectVal === null) {
                    return null
                  }

                  // Only arrays and objects stringified here should be parsed from the "pw.expect()" method definition
                  // The usecase is that any JSON string supplied should be preserved
                  // An extra "isStringifiedWithinIsolate" prop is added to indicate it has to be parsed

                  if (Array.isArray(expectVal)) {
                    return JSON.stringify({
                      arr: expectVal,
                      isStringifiedWithinIsolate: true,
                    })
                  }

                  return JSON.stringify({
                    ...expectVal,
                    isStringifiedWithinIsolate: true,
                  })
                }

                return expectVal
              })
            )

            // Matcher methods that can be chained with "pw.expect()"
            // pw.expect().toBe(), etc
            if (expectFnResult.typeof === "object") {
              // Access the getter that points to the negated matcher methods via "{ accessors: true }"
              const matcherMethods = {
                not: expectFnResult.getSync("not", { accessors: true }),
              }

              // Serialize matcher methods for use in the isolate context
              const matcherMethodNames = [
                "toBe",
                "toBeLevel2xx",
                "toBeLevel3xx",
                "toBeLevel4xx",
                "toBeLevel5xx",
                "toBeType",
                "toHaveLength",
                "toInclude",
              ]
              matcherMethodNames.forEach((methodName) => {
                matcherMethods[methodName] = expectFnResult.getSync(methodName)
              })

              return new Proxy(matcherMethods, {
                get: (matcherMethodTarget, matcherMethodProp) => {
                  // pw.expect().not.toBe(), etc
                  const matcherMethodEntry = matcherMethodTarget[matcherMethodProp]

                  if (matcherMethodProp === "not") {
                    return new Proxy(matcherMethodEntry, {
                      get: (negatedObjTarget, negatedObjprop) => {
                        // Return the negated matcher method defn that is invoked from the test script
                        const negatedMatcherMethodDefn = negatedObjTarget.getSync(negatedObjprop)
                        return negatedMatcherMethodDefn
                      },
                    })
                  }

                  // Return the matcher method defn that is invoked from the test script
                  return matcherMethodEntry
                },
              })
            }
          }
        }

        // "pw.env" set of API methods
        if (typeof topLevelEntry === "object" && pwObjProp !== "response") {
          return new Proxy(topLevelEntry, {
            get: (subTarget, subProp) => {
              const subLevelProperty = subTarget[subProp]
              if (
                subLevelProperty &&
                subLevelProperty.typeof === "function"
              ) {
                return (...args) => subLevelProperty.applySync(null, args)
              }
            },
          })
        }

        return topLevelEntry
      },
    })

      ${testScript}
    `

    // Create a script and compile it
    const script = isolate.compileScript(finalScript)

    // Run the test script in the provided context
    script
      .then((script) => script.run(context))
      .then(() => {
        resolve({
          tests: testRunStack,
          envs: updatedEnvs,
        })
      })
      .catch((error: Error) => {
        reject(error)
      })
  })
}
import { createRequire } from "module"

const nodeRequire = createRequire(import.meta.url)
const ivm = nodeRequire("isolated-vm")

// Helper function to recursively wrap methods in `ivm.Reference`
export const getSerializedAPIMethods = (
  namespaceObj: Record<string, unknown>
): Record<string, unknown> => {
  const result: Record<string, unknown> = {}

  for (const [key, value] of Object.entries(namespaceObj)) {
    if (typeof value === "object" && value !== null && !Array.isArray(value)) {
      result[key] = getSerializedAPIMethods(value as Record<string, unknown>)
    } else if (typeof value === "function") {
      result[key] = new ivm.Reference(value)
    } else {
      result[key] = value
    }
  }

  return result
}
const getResolvedExpectValue = (expectVal: any) => {
  if (typeof expectVal !== "string") {
    return expectVal
  }

  try {
    const parsedExpectVal = JSON.parse(expectVal)

    // Supplying non-primitive values is not permitted in the `isStringifiedWithinIsolate` property indicates that the object was stringified before executing the script from the isolate context
    // This is done to ensure a JSON string supplied as the "expectVal" is not parsed and preserved as is
    if (typeof parsedExpectVal === "object") {
      if (parsedExpectVal.isStringifiedWithinIsolate !== true) {
        return expectVal
      }

      // For an array, the contents are stored in the `arr` property
      if (Array.isArray(parsedExpectVal.arr)) {
        return parsedExpectVal.arr
      }

      delete parsedExpectVal.isStringifiedWithinIsolate
      return parsedExpectVal
    }

    return expectVal
  } catch (_) {
    return expectVal
  }
}

  // Non-primitive values supplied are stringified in the isolate context
  const resolvedExpectVal = getResolvedExpectValue(expectVal)

    let assertion = resolvedExpectVal === expectedVal
    const message = `Expected '${resolvedExpectVal}' to${
    const parsedExpectVal = parseInt(resolvedExpectVal)
      const message = `Expected ${level}-level status but could not parse value '${resolvedExpectVal}'`
      let assertion = typeof resolvedExpectVal === expectedType
      const message = `Expected '${resolvedExpectVal}' to${
    if (
      !(
        Array.isArray(resolvedExpectVal) ||
        typeof resolvedExpectVal === "string"
      )
    ) {
      let assertion = resolvedExpectVal.length === expectedLength
    if (
      !(
        Array.isArray(resolvedExpectVal) ||
        typeof resolvedExpectVal === "string"
      )
    ) {
    let assertion = resolvedExpectVal.includes(needle)
    const expectValPretty = JSON.stringify(resolvedExpectVal)
export { runPreRequestScript } from "./pre-request"
export { runTestScript } from "./test-runner"
import { getPreRequestScriptMethods } from "~/shared-utils"
import {
  getTestRunnerScriptMethods,
  preventCyclicObjects,
} from "~/shared-utils"
        web: "./src/web/index.ts",
        node: "./src/node/index.ts",
      external: ["module"],
  test: {
    environment: "node",
    setupFiles: ["./setupFiles.ts"],
  },
export { default } from "./dist/web/index.d.ts"
export * from "./dist/web/index.d.ts"
      isolated-vm:
        specifier: 4.7.2
        version: 4.7.2
      isolated-vm:
        specifier: 4.7.2
        version: 4.7.2
      vitest:
        specifier: 0.34.6
        version: 0.34.6(sass@1.69.5)(terser@5.27.0)
      vue: 3.3.9(typescript@4.9.5)
      vue: 3.3.9(typescript@4.9.5)
      '@types/node': 17.0.45
      vite: 3.2.4(@types/node@17.0.27)(terser@5.27.0)
      vue: 3.3.9(typescript@4.9.5)
      vue: 3.3.9(typescript@4.9.5)
  /chownr@1.1.4:
    resolution: {integrity: sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==}
    dev: false

  /decompress-response@6.0.0:
    resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==}
    engines: {node: '>=10'}
    dependencies:
      mimic-response: 3.1.0
    dev: false

  /expand-template@2.0.3:
    resolution: {integrity: sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==}
    engines: {node: '>=6'}
    dev: false

  /fs-constants@1.0.0:
    resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==}
    dev: false

  /github-from-package@0.0.0:
    resolution: {integrity: sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==}
    dev: false

  /isolated-vm@4.7.2:
    resolution: {integrity: sha512-JVEs5gzWObzZK5+OlBplCdYSpokMcdhLSs/xWYYxmYWVfOOFF4oZJsYh7E/FmfX8e7gMioXMpMMeEyX1afuKrg==}
    engines: {node: '>=16.0.0'}
    requiresBuild: true
    dependencies:
      prebuild-install: 7.1.2
    dev: false

      semver: 7.6.0
      '@types/node': 17.0.45
  /mimic-response@3.1.0:
    resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==}
    engines: {node: '>=10'}
    dev: false

  /mkdirp-classic@0.5.3:
    resolution: {integrity: sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==}
    dev: false

  /napi-build-utils@1.0.2:
    resolution: {integrity: sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==}
    dev: false

  /node-abi@3.57.0:
    resolution: {integrity: sha512-Dp+A9JWxRaKuHP35H77I4kCKesDy5HUDEmScia2FyncMTOXASMyg251F5PhFoDA5uqBrDDffiLpbqnrZmNXW+g==}
    engines: {node: '>=10'}
    dependencies:
      semver: 7.6.0
    dev: false

  /prebuild-install@7.1.2:
    resolution: {integrity: sha512-UnNke3IQb6sgarcZIDU3gbMeTp/9SSU1DAIkil7PrqG1vZlBtY5msYccSKSHDqa3hNg436IXK+SNImReuA1wEQ==}
    engines: {node: '>=10'}
    hasBin: true
    dependencies:
      detect-libc: 2.0.1
      expand-template: 2.0.3
      github-from-package: 0.0.0
      minimist: 1.2.6
      mkdirp-classic: 0.5.3
      napi-build-utils: 1.0.2
      node-abi: 3.57.0
      pump: 3.0.0
      rc: 1.2.8
      simple-get: 4.0.1
      tar-fs: 2.1.1
      tunnel-agent: 0.6.0
    dev: false

  /simple-concat@1.0.1:
    resolution: {integrity: sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==}
    dev: false

  /simple-get@4.0.1:
    resolution: {integrity: sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==}
    dependencies:
      decompress-response: 6.0.0
      once: 1.4.0
      simple-concat: 1.0.1
    dev: false

  /tar-fs@2.1.1:
    resolution: {integrity: sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==}
    dependencies:
      chownr: 1.1.4
      mkdirp-classic: 0.5.3
      pump: 3.0.0
      tar-stream: 2.2.0
    dev: false

  /tar-stream@2.2.0:
    resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==}
    engines: {node: '>=6'}
    dependencies:
      bl: 4.1.0
      end-of-stream: 1.4.4
      fs-constants: 1.0.0
      inherits: 2.0.4
      readable-stream: 3.6.0
    dev: false

  /tunnel-agent@0.6.0:
    resolution: {integrity: sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==}
    dependencies:
      safe-buffer: 5.2.1
    dev: false

      vite: 3.2.4(@types/node@17.0.27)(terser@5.27.0)
  /vite@3.2.4(@types/node@17.0.27)(terser@5.27.0):
    resolution: {integrity: sha512-Z2X6SRAffOUYTa+sLy3NQ7nlHFU100xwanq1WDwqaiFiCe+25zdxP1TfCS5ojPV2oDDcXudHIoPnI1Z/66B7Yw==}
    engines: {node: ^14.18.0 || >=16.0.0}
    hasBin: true
    peerDependencies:
      '@types/node': '>= 14'
      less: '*'
      sass: '*'
      stylus: '*'
      sugarss: '*'
      terser: ^5.4.0
    peerDependenciesMeta:
      '@types/node':
        optional: true
      less:
        optional: true
      sass:
        optional: true
      stylus:
        optional: true
      sugarss:
        optional: true
      terser:
        optional: true
    dependencies:
      '@types/node': 17.0.27
      esbuild: 0.15.18
      postcss: 8.4.32
      resolve: 1.22.8
      rollup: 2.79.1
      terser: 5.27.0
    optionalDependencies:
      fsevents: 2.3.3

      vue: 3.3.9(typescript@4.9.5)
      vue: 3.3.9(typescript@4.9.5)
    deprecated: It is not compatible with newer versions of GA starting with v4, as long as you are using GAv3 it should be ok, but the package is not longer being maintained
    deprecated: It is not compatible with newer versions of GA starting with v4, as long as you are using GAv3 it should be ok, but the package is not longer being maintained