diff --git a/packages/hoppscotch-common/src/helpers/RequestRunner.ts b/packages/hoppscotch-common/src/helpers/RequestRunner.ts index 8469b24b8..22ed93468 100644 --- a/packages/hoppscotch-common/src/helpers/RequestRunner.ts +++ b/packages/hoppscotch-common/src/helpers/RequestRunner.ts @@ -133,6 +133,38 @@ const updateEnvironmentsWithSecret = ( return updatedEnv } +/** + * Transforms the environment list to a list with unique keys with value + * @param envs The environment list to be transformed + * @returns The transformed environment list with keys with value + */ +const filterNonEmptyEnvironmentVariables = ( + envs: Environment["variables"] +): Environment["variables"] => { + const envsMap = new Map() + + envs.forEach((env) => { + if (env.secret) { + envsMap.set(env.key, env) + } else if (envsMap.has(env.key)) { + const existingEnv = envsMap.get(env.key) + + if ( + existingEnv && + "value" in existingEnv && + existingEnv.value === "" && + env.value !== "" + ) { + envsMap.set(env.key, env) + } + } else { + envsMap.set(env.key, env) + } + }) + + return Array.from(envsMap.values()) +} + export function runRESTRequest$( tab: Ref> ): [ @@ -207,15 +239,19 @@ export function runRESTRequest$( } const finalEnvs = { - environments: envs.right, requestVariables: finalRequestVariables as Environment["variables"], + environments: envs.right, } + const finalEnvsWithNonEmptyValues = filterNonEmptyEnvironmentVariables( + combineEnvVariables(finalEnvs) + ) + const effectiveRequest = getEffectiveRESTRequest(finalRequest, { id: "env-id", v: 1, name: "Env", - variables: combineEnvVariables(finalEnvs), + variables: finalEnvsWithNonEmptyValues, }) const [stream, cancelRun] = createRESTNetworkRequestStream(effectiveRequest) diff --git a/packages/hoppscotch-common/src/helpers/editor/extensions/HoppEnvironment.ts b/packages/hoppscotch-common/src/helpers/editor/extensions/HoppEnvironment.ts index 31ab8f2bc..04b65dd28 100644 --- a/packages/hoppscotch-common/src/helpers/editor/extensions/HoppEnvironment.ts +++ b/packages/hoppscotch-common/src/helpers/editor/extensions/HoppEnvironment.ts @@ -38,6 +38,31 @@ const HOPP_ENV_HIGHLIGHT_NOT_FOUND = "environment-not-found-highlight" const secretEnvironmentService = getService(SecretEnvironmentService) const restTabs = getService(RESTTabService) +/** + * Transforms the environment list to a list with unique keys with value + * @param envs The environment list to be transformed + * @returns The transformed environment list with keys with value + */ +const filterNonEmptyEnvironmentVariables = ( + envs: AggregateEnvironment[] +): AggregateEnvironment[] => { + const envsMap = new Map() + + envs.forEach((env) => { + if (envsMap.has(env.key)) { + const existingEnv = envsMap.get(env.key) + + if (existingEnv?.value === "" && env.value !== "") { + envsMap.set(env.key, env) + } + } else { + envsMap.set(env.key, env) + } + }) + + return Array.from(envsMap.values()) +} + const cursorTooltipField = (aggregateEnvs: AggregateEnvironment[]) => hoverTooltip( (view, pos, side) => { @@ -72,7 +97,12 @@ const cursorTooltipField = (aggregateEnvs: AggregateEnvironment[]) => const parsedEnvKey = text.slice(start - from, end - from) - const tooltipEnv = aggregateEnvs.find((env) => env.key === parsedEnvKey) + const envsWithNoEmptyValues = + filterNonEmptyEnvironmentVariables(aggregateEnvs) + + const tooltipEnv = envsWithNoEmptyValues.find( + (env) => env.key === parsedEnvKey + ) const envName = tooltipEnv?.sourceEnv ?? "Choose an Environment" @@ -205,7 +235,10 @@ const getMatchDecorator = (aggregateEnvs: AggregateEnvironment[]) => export const environmentHighlightStyle = ( aggregateEnvs: AggregateEnvironment[] ) => { - const decorator = getMatchDecorator(aggregateEnvs) + const envsWithNoEmptyValues = + filterNonEmptyEnvironmentVariables(aggregateEnvs) + + const decorator = getMatchDecorator(envsWithNoEmptyValues) return ViewPlugin.define( (view) => ({ diff --git a/packages/hoppscotch-common/src/services/inspection/inspectors/environment.inspector.ts b/packages/hoppscotch-common/src/services/inspection/inspectors/environment.inspector.ts index 0a444bf64..89a603966 100644 --- a/packages/hoppscotch-common/src/services/inspection/inspectors/environment.inspector.ts +++ b/packages/hoppscotch-common/src/services/inspection/inspectors/environment.inspector.ts @@ -10,6 +10,7 @@ import { Ref, markRaw } from "vue" import IconPlusCircle from "~icons/lucide/plus-circle" import { HoppRESTRequest } from "@hoppscotch/data" import { + AggregateEnvironment, aggregateEnvsWithSecrets$, getCurrentEnvironment, getSelectedEnvironmentType, @@ -133,6 +134,31 @@ export class EnvironmentInspectorService extends Service implements Inspector { return newErrors } + /** + * Transforms the environment list to a list with unique keys with value + * @param envs The environment list to be transformed + * @returns The transformed environment list with keys with value + */ + private filterNonEmptyEnvironmentVariables = ( + envs: AggregateEnvironment[] + ): AggregateEnvironment[] => { + const envsMap = new Map() + + envs.forEach((env) => { + if (envsMap.has(env.key)) { + const existingEnv = envsMap.get(env.key) + + if (existingEnv?.value === "" && env.value !== "") { + envsMap.set(env.key, env) + } + } else { + envsMap.set(env.key, env) + } + }) + + return Array.from(envsMap.values()) + } + /** * Checks if the environment variables in the target array are empty * @param target The target array to validate @@ -156,14 +182,15 @@ export class EnvironmentInspectorService extends Service implements Inspector { const currentTab = this.restTabs.currentActiveTab.value - const environmentVariables = [ - ...currentTab.document.request.requestVariables.map((env) => ({ - ...env, - secret: false, - sourceEnv: "RequestVariable", - })), - ...this.aggregateEnvsWithSecrets.value, - ] + const environmentVariables = + this.filterNonEmptyEnvironmentVariables([ + ...currentTab.document.request.requestVariables.map((env) => ({ + ...env, + secret: false, + sourceEnv: "RequestVariable", + })), + ...this.aggregateEnvsWithSecrets.value, + ]) environmentVariables.forEach((env) => { const hasSecretEnv = this.secretEnvs.hasSecretValue(