Browse Source

feat: collection level headers and authorization (#3505)

Co-authored-by: Andrew Bastin <andrewbastin.k@gmail.com>
Nivedin 1 year ago
parent
commit
47e009267b

+ 2 - 2
packages/hoppscotch-cli/src/types/collections.ts

@@ -1,8 +1,8 @@
-import { HoppCollection, HoppRESTRequest } from "@hoppscotch/data";
+import { HoppCollection } from "@hoppscotch/data";
 import { HoppEnvs } from "./request";
 
 export type CollectionRunnerParam = {
-  collections: HoppCollection<HoppRESTRequest>[];
+  collections: HoppCollection[];
   envs: HoppEnvs;
   delay?: number;
 };

+ 1 - 1
packages/hoppscotch-cli/src/types/request.ts

@@ -33,7 +33,7 @@ export type HoppEnvs = {
 
 export type CollectionStack = {
   path: string;
-  collection: HoppCollection<HoppRESTRequest>;
+  collection: HoppCollection;
 };
 
 export type RequestReport = {

+ 2 - 9
packages/hoppscotch-cli/src/utils/checks.ts

@@ -1,8 +1,4 @@
-import {
-  HoppCollection,
-  HoppRESTRequest,
-  isHoppRESTRequest,
-} from "@hoppscotch/data";
+import { HoppCollection, isHoppRESTRequest } from "@hoppscotch/data";
 import * as A from "fp-ts/Array";
 import { CommanderError } from "commander";
 import { HoppCLIError, HoppErrnoException } from "../types/errors";
@@ -24,9 +20,7 @@ export const hasProperty = <P extends PropertyKey>(
  * @returns True, if unknown parameter is valid Hoppscotch REST Collection;
  * False, otherwise.
  */
-export const isRESTCollection = (
-  param: unknown
-): param is HoppCollection<HoppRESTRequest> => {
+export const isRESTCollection = (param: unknown): param is HoppCollection => {
   if (!!param && typeof param === "object") {
     if (!hasProperty(param, "v") || typeof param.v !== "number") {
       return false;
@@ -62,7 +56,6 @@ export const isRESTCollection = (
   return false;
 };
 
-
 /**
  * Checks if given error data is of type HoppCLIError, based on existence
  * of code property.

+ 52 - 54
packages/hoppscotch-cli/src/utils/collections.ts

@@ -3,7 +3,7 @@ import { pipe } from "fp-ts/function";
 import { bold } from "chalk";
 import { log } from "console";
 import round from "lodash/round";
-import { HoppCollection, HoppRESTRequest } from "@hoppscotch/data";
+import { HoppCollection } from "@hoppscotch/data";
 import {
   HoppEnvs,
   CollectionStack,
@@ -41,58 +41,58 @@ const { WARN, FAIL } = exceptionColors;
  * @param param Data of hopp-collection with hopp-requests, envs to be processed.
  * @returns List of report for each processed request.
  */
-export const collectionsRunner =
-  async (param: CollectionRunnerParam): Promise<RequestReport[]> =>
-   {
-    const envs: HoppEnvs = param.envs;
-    const delay = param.delay ?? 0;
-    const requestsReport: RequestReport[] = [];
-    const collectionStack: CollectionStack[] = getCollectionStack(
-      param.collections
-    );
-
-    while (collectionStack.length) {
-      // Pop out top-most collection from stack to be processed.
-      const { collection, path } = <CollectionStack>collectionStack.pop();
-
-      // Processing each request in collection
-      for (const request of collection.requests) {
-        const _request = preProcessRequest(request);
-        const requestPath = `${path}/${_request.name}`;
-        const processRequestParams: ProcessRequestParams = {
-          path: requestPath,
-          request: _request,
-          envs,
-          delay,
-        };
-
-        // Request processing initiated message.
-        log(WARN(`\nRunning: ${bold(requestPath)}`));
-
-        // Processing current request.
-        const result = await processRequest(processRequestParams)();
-
-        // Updating global & selected envs with new envs from processed-request output.
-        const { global, selected } = result.envs;
-        envs.global = global;
-        envs.selected = selected;
-
-        // Storing current request's report.
-        const requestReport = result.report;
-        requestsReport.push(requestReport);
-      }
-
-      // Pushing remaining folders realted collection to stack.
-      for (const folder of collection.folders) {
-        collectionStack.push({
-          path: `${path}/${folder.name}`,
-          collection: folder,
-        });
-      }
+export const collectionsRunner = async (
+  param: CollectionRunnerParam
+): Promise<RequestReport[]> => {
+  const envs: HoppEnvs = param.envs;
+  const delay = param.delay ?? 0;
+  const requestsReport: RequestReport[] = [];
+  const collectionStack: CollectionStack[] = getCollectionStack(
+    param.collections
+  );
+
+  while (collectionStack.length) {
+    // Pop out top-most collection from stack to be processed.
+    const { collection, path } = <CollectionStack>collectionStack.pop();
+
+    // Processing each request in collection
+    for (const request of collection.requests) {
+      const _request = preProcessRequest(request);
+      const requestPath = `${path}/${_request.name}`;
+      const processRequestParams: ProcessRequestParams = {
+        path: requestPath,
+        request: _request,
+        envs,
+        delay,
+      };
+
+      // Request processing initiated message.
+      log(WARN(`\nRunning: ${bold(requestPath)}`));
+
+      // Processing current request.
+      const result = await processRequest(processRequestParams)();
+
+      // Updating global & selected envs with new envs from processed-request output.
+      const { global, selected } = result.envs;
+      envs.global = global;
+      envs.selected = selected;
+
+      // Storing current request's report.
+      const requestReport = result.report;
+      requestsReport.push(requestReport);
     }
 
-    return requestsReport;
-  };
+    // Pushing remaining folders realted collection to stack.
+    for (const folder of collection.folders) {
+      collectionStack.push({
+        path: `${path}/${folder.name}`,
+        collection: folder,
+      });
+    }
+  }
+
+  return requestsReport;
+};
 
 /**
  * Transforms collections to generate collection-stack which describes each collection's
@@ -100,9 +100,7 @@ export const collectionsRunner =
  * @param collections Hopp-collection objects to be mapped to collection-stack type.
  * @returns Mapped collections to collection-stack.
  */
-const getCollectionStack = (
-  collections: HoppCollection<HoppRESTRequest>[]
-): CollectionStack[] =>
+const getCollectionStack = (collections: HoppCollection[]): CollectionStack[] =>
   pipe(
     collections,
     A.map(

+ 18 - 16
packages/hoppscotch-cli/src/utils/mutators.ts

@@ -2,7 +2,7 @@ import fs from "fs/promises";
 import { FormDataEntry } from "../types/request";
 import { error } from "../types/errors";
 import { isRESTCollection, isHoppErrnoException } from "./checks";
-import { HoppCollection, HoppRESTRequest } from "@hoppscotch/data";
+import { HoppCollection } from "@hoppscotch/data";
 
 /**
  * Parses array of FormDataEntry to FormData.
@@ -35,20 +35,20 @@ export const parseErrorMessage = (e: unknown) => {
 };
 
 export async function readJsonFile(path: string): Promise<unknown> {
-  if(!path.endsWith('.json')) {
-    throw error({ code: "INVALID_FILE_TYPE", data: path })
+  if (!path.endsWith(".json")) {
+    throw error({ code: "INVALID_FILE_TYPE", data: path });
   }
 
   try {
-    await fs.access(path)
+    await fs.access(path);
   } catch (e) {
-    throw error({ code: "FILE_NOT_FOUND", path: path })
+    throw error({ code: "FILE_NOT_FOUND", path: path });
   }
 
   try {
-    return JSON.parse((await fs.readFile(path)).toString())
-  } catch(e) {
-    throw error({ code: "UNKNOWN_ERROR", data: e })
+    return JSON.parse((await fs.readFile(path)).toString());
+  } catch (e) {
+    throw error({ code: "UNKNOWN_ERROR", data: e });
   }
 }
 
@@ -56,22 +56,24 @@ export async function readJsonFile(path: string): Promise<unknown> {
  * Parses collection json file for given path:context.path, and validates
  * the parsed collectiona array.
  * @param path Collection json file path.
- * @returns For successful parsing we get array of HoppCollection<HoppRESTRequest>,
+ * @returns For successful parsing we get array of HoppCollection,
  */
 export async function parseCollectionData(
   path: string
-): Promise<HoppCollection<HoppRESTRequest>[]> {
-  let contents = await readJsonFile(path)
+): Promise<HoppCollection[]> {
+  let contents = await readJsonFile(path);
 
-  const maybeArrayOfCollections: unknown[] = Array.isArray(contents) ? contents : [contents]
+  const maybeArrayOfCollections: unknown[] = Array.isArray(contents)
+    ? contents
+    : [contents];
 
-  if(maybeArrayOfCollections.some((x) => !isRESTCollection(x))) {
+  if (maybeArrayOfCollections.some((x) => !isRESTCollection(x))) {
     throw error({
       code: "MALFORMED_COLLECTION",
       path,
       data: "Please check the collection data.",
-    })
+    });
   }
 
-  return maybeArrayOfCollections as HoppCollection<HoppRESTRequest>[]
-};
+  return maybeArrayOfCollections as HoppCollection[];
+}

+ 1 - 0
packages/hoppscotch-common/assets/themes/base-themes.scss

@@ -17,6 +17,7 @@
   --lower-tertiary-sticky-fold: 7.125rem;
   --lower-fourth-sticky-fold: 9.188rem;
   --sidebar-primary-sticky-fold: 2rem;
+  --properties-primary-sticky-fold: 2.05rem;
 }
 
 @mixin light-theme {

+ 5 - 0
packages/hoppscotch-common/locales/en.json

@@ -33,6 +33,7 @@
     "open_workspace": "Open workspace",
     "paste": "Paste",
     "prettify": "Prettify",
+    "properties":"Properties",
     "remove": "Remove",
     "rename": "Rename",
     "restore": "Restore",
@@ -172,6 +173,8 @@
     "name_length_insufficient": "Collection name should be at least 3 characters long",
     "new": "New Collection",
     "order_changed": "Collection Order Updated",
+    "properties":"Colection Properties",
+    "properties_updated": "Collection Properties Updated",
     "renamed": "Collection renamed",
     "request_in_use": "Request in use",
     "save_as": "Save as",
@@ -354,6 +357,8 @@
     "offline_short": "You're using Hoppscotch offline.",
     "post_request_tests": "Test scripts are written in JavaScript, and are run after the response is received.",
     "pre_request_script": "Pre-request scripts are written in JavaScript, and are run before the request is sent.",
+    "collection_properties_authorization": " This authorization will be set for every request in this collection.",
+    "collection_properties_header": "This header will be set for every request in this collection.",
     "script_fail": "It seems there is a glitch in the pre-request script. Check the error below and fix the script accordingly.",
     "test_script_fail": "There seems to be an error with test script. Please fix the errors and run tests again",
     "tests": "Write a test script to automate debugging."

+ 1 - 0
packages/hoppscotch-common/src/components.d.ts

@@ -56,6 +56,7 @@ declare module 'vue' {
     CollectionsGraphqlRequest: typeof import('./components/collections/graphql/Request.vue')['default']
     CollectionsImportExport: typeof import('./components/collections/ImportExport.vue')['default']
     CollectionsMyCollections: typeof import('./components/collections/MyCollections.vue')['default']
+    CollectionsProperties: typeof import('./components/collections/Properties.vue')['default']
     CollectionsRequest: typeof import('./components/collections/Request.vue')['default']
     CollectionsSaveRequest: typeof import('./components/collections/SaveRequest.vue')['default']
     CollectionsTeamCollections: typeof import('./components/collections/TeamCollections.vue')['default']

+ 2 - 2
packages/hoppscotch-common/src/components/app/spotlight/entry/GQLRequest.vue

@@ -13,7 +13,7 @@
 </template>
 
 <script setup lang="ts">
-import { HoppCollection, HoppGQLRequest } from "@hoppscotch/data"
+import { HoppCollection } from "@hoppscotch/data"
 import { computed } from "vue"
 import { graphqlCollectionStore } from "~/newstore/collections"
 
@@ -28,7 +28,7 @@ const pathFolders = computed(() => {
       .slice(0, -1)
       .map((x) => parseInt(x))
 
-    const pathItems: HoppCollection<HoppGQLRequest>[] = []
+    const pathItems: HoppCollection[] = []
 
     let currentFolder =
       graphqlCollectionStore.value.state[folderIndicies.shift()!]

+ 2 - 2
packages/hoppscotch-common/src/components/app/spotlight/entry/RESTRequest.vue

@@ -20,7 +20,7 @@
 </template>
 
 <script setup lang="ts">
-import { HoppCollection, HoppRESTRequest } from "@hoppscotch/data"
+import { HoppCollection } from "@hoppscotch/data"
 import { computed } from "vue"
 import { restCollectionStore } from "~/newstore/collections"
 import { getMethodLabelColorClassOf } from "~/helpers/rest/labelColoring"
@@ -36,7 +36,7 @@ const pathFolders = computed(() => {
       .slice(0, -1)
       .map((x) => parseInt(x))
 
-    const pathItems: HoppCollection<HoppRESTRequest>[] = []
+    const pathItems: HoppCollection[] = []
 
     let currentFolder = restCollectionStore.value.state[folderIndicies.shift()!]
     pathItems.push(currentFolder)

Some files were not shown because too many files changed in this diff