feat: collection level headers and authorization (#3505)
Co-authored-by: Andrew Bastin <andrewbastin.k@gmail.com>
This commit is contained in:
@@ -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;
|
||||
};
|
||||
|
||||
@@ -33,7 +33,7 @@ export type HoppEnvs = {
|
||||
|
||||
export type CollectionStack = {
|
||||
path: string;
|
||||
collection: HoppCollection<HoppRESTRequest>;
|
||||
collection: HoppCollection;
|
||||
};
|
||||
|
||||
export type RequestReport = {
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
);
|
||||
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();
|
||||
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,
|
||||
};
|
||||
// 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)}`));
|
||||
// Request processing initiated message.
|
||||
log(WARN(`\nRunning: ${bold(requestPath)}`));
|
||||
|
||||
// Processing current request.
|
||||
const result = await processRequest(processRequestParams)();
|
||||
// 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;
|
||||
// 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,
|
||||
});
|
||||
}
|
||||
// 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(
|
||||
|
||||
@@ -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[];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user