Compare commits
8 Commits
hotfix/req
...
pr/danithe
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9581f1d747 | ||
|
|
882aafdb43 | ||
|
|
f33fa6ac1a | ||
|
|
b9a1cc21f1 | ||
|
|
f530fc2853 | ||
|
|
e0eb8af6f5 | ||
|
|
088f1d6b47 | ||
|
|
7d61e69b3d |
@@ -14,9 +14,10 @@ import { isHoppCLIError } from "../utils/checks";
|
||||
export const test = (path: string, options: TestCmdOptions) => async () => {
|
||||
try {
|
||||
const delay = options.delay ? parseDelayOption(options.delay) : 0
|
||||
const envs = options.env ? await parseEnvsData(options.env) : <HoppEnvs>{ global: [], selected: [] }
|
||||
const envName = options.envName
|
||||
const envs = options.env ? await parseEnvsData(options.env, envName) : <HoppEnvs>{ global: [], selected: [] }
|
||||
const collections = await parseCollectionData(path)
|
||||
|
||||
|
||||
const report = await collectionsRunner({collections, envs, delay})
|
||||
const hasSucceeded = collectionsRunnerResult(report)
|
||||
collectionsRunnerExit(hasSucceeded)
|
||||
|
||||
@@ -51,6 +51,9 @@ export const handleError = <T extends HoppErrorCode>(error: HoppError<T>) => {
|
||||
case "MALFORMED_COLLECTION":
|
||||
ERROR_MSG = `${error.path}\n${parseErrorData(error.data)}`;
|
||||
break;
|
||||
case "ENVIRONMENT_NAME_NOT_FOUND":
|
||||
ERROR_MSG = `\n${parseErrorData(error.data)}`;
|
||||
break;
|
||||
case "NO_FILE_PATH":
|
||||
ERROR_MSG = `Please provide a hoppscotch-collection file path.`;
|
||||
break;
|
||||
|
||||
@@ -50,6 +50,7 @@ program
|
||||
"path to a hoppscotch collection.json file for CI testing"
|
||||
)
|
||||
.option("-e, --env <file_path>", "path to an environment variables json file")
|
||||
.option("-eN, --envName <environment_name>","Specific Name of the environment")
|
||||
.option(
|
||||
"-d, --delay <delay_in_ms>",
|
||||
"delay in milliseconds(ms) between consecutive requests within a collection"
|
||||
|
||||
@@ -33,4 +33,5 @@ export interface EffectiveHoppRESTRequest extends HoppRESTRequest {
|
||||
effectiveFinalHeaders: { key: string; value: string; active: boolean }[];
|
||||
effectiveFinalParams: { key: string; value: string; active: boolean }[];
|
||||
effectiveFinalBody: FormData | string | null;
|
||||
effectiveFinalMaskedURL: string;
|
||||
}
|
||||
|
||||
@@ -5,23 +5,46 @@ import { readJsonFile } from "../../utils/mutators";
|
||||
/**
|
||||
* Parses env json file for given path and validates the parsed env json object.
|
||||
* @param path Path of env.json file to be parsed.
|
||||
* @param envName Name of the environment that should be used. If undefined first environment is used.
|
||||
* @returns For successful parsing we get HoppEnvs object.
|
||||
*/
|
||||
export async function parseEnvsData(path: string) {
|
||||
export async function parseEnvsData(path: string, envName: string | undefined) {
|
||||
const contents = await readJsonFile(path)
|
||||
|
||||
if(!(contents && typeof contents === "object" && !Array.isArray(contents))) {
|
||||
if(!(contents && typeof contents === "object" && Array.isArray(contents))) {
|
||||
throw error({ code: "MALFORMED_ENV_FILE", path, data: null })
|
||||
}
|
||||
|
||||
const envPairs: Array<HoppEnvPair> = []
|
||||
|
||||
for( const [key,value] of Object.entries(contents)) {
|
||||
if(typeof value !== "string") {
|
||||
throw error({ code: "MALFORMED_ENV_FILE", path, data: {value: value} })
|
||||
}
|
||||
const contentEntries = Object.entries(contents)
|
||||
let environmentFound = false;
|
||||
|
||||
envPairs.push({key, value})
|
||||
for(const [key, obj] of contentEntries) {
|
||||
if(!(typeof obj === "object" && "name" in obj && "variables" in obj)) {
|
||||
throw error({ code: "MALFORMED_ENV_FILE", path, data: { value: obj } })
|
||||
}
|
||||
if(envName && envName !== obj.name) {
|
||||
continue
|
||||
}
|
||||
environmentFound = true;
|
||||
for(const variable of obj.variables) {
|
||||
if(
|
||||
!(
|
||||
typeof variable === "object" &&
|
||||
"key" in variable &&
|
||||
"value" in variable &&
|
||||
"secret" in variable
|
||||
)
|
||||
) {
|
||||
throw error({ code: "MALFORMED_ENV_FILE", path, data: { value: variable } });
|
||||
}
|
||||
const { key, value, secret } = variable;
|
||||
envPairs.push({ key: key, value: value, secret: secret });
|
||||
}
|
||||
break
|
||||
}
|
||||
if(envName && !environmentFound) {
|
||||
throw error({ code: "ENVIRONMENT_NAME_NOT_FOUND", data: envName });
|
||||
}
|
||||
return <HoppEnvs>{ global: [], selected: envPairs }
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
export type TestCmdOptions = {
|
||||
env: string | undefined;
|
||||
delay: string | undefined;
|
||||
envName: string | undefined;
|
||||
};
|
||||
|
||||
export type HOPP_ENV_FILE_EXT = "json";
|
||||
|
||||
@@ -15,6 +15,7 @@ type HoppErrors = {
|
||||
FILE_NOT_FOUND: HoppErrorPath;
|
||||
UNKNOWN_COMMAND: HoppErrorCmd;
|
||||
MALFORMED_COLLECTION: HoppErrorPath & HoppErrorData;
|
||||
ENVIRONMENT_NAME_NOT_FOUND: HoppErrorData;
|
||||
NO_FILE_PATH: {};
|
||||
PRE_REQUEST_SCRIPT_ERROR: HoppErrorData;
|
||||
PARSING_ERROR: HoppErrorData;
|
||||
|
||||
@@ -7,7 +7,7 @@ export type FormDataEntry = {
|
||||
value: string | Blob;
|
||||
};
|
||||
|
||||
export type HoppEnvPair = { key: string; value: string };
|
||||
export type HoppEnvPair = { key: string; value: string; secret: boolean };
|
||||
|
||||
export type HoppEnvs = {
|
||||
global: HoppEnvPair[];
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { bold } from "chalk";
|
||||
import { groupEnd, group, log } from "console";
|
||||
import { handleError } from "../handlers/error";
|
||||
import { RequestConfig } from "../interfaces/request";
|
||||
import { Method } from "axios";
|
||||
import { RequestRunnerResponse, TestReport } from "../interfaces/response";
|
||||
import { HoppCLIError } from "../types/errors";
|
||||
import {
|
||||
@@ -172,11 +172,12 @@ export const printFailedTestsReport = (
|
||||
export const printRequestRunner = {
|
||||
/**
|
||||
* Request-runner starting message.
|
||||
* @param requestConfig Provides request's method and url.
|
||||
* @param requestMethod Provides request's method
|
||||
* @param maskedURL Provides the URL with secrets masked with asterisks
|
||||
*/
|
||||
start: (requestConfig: RequestConfig) => {
|
||||
const METHOD = BG_INFO(` ${requestConfig.method} `);
|
||||
const ENDPOINT = requestConfig.url;
|
||||
start: (requestMethod: Method | undefined, maskedURL: string) => {
|
||||
const METHOD = BG_INFO(` ${requestMethod} `);
|
||||
const ENDPOINT = maskedURL;
|
||||
|
||||
process.stdout.write(`${METHOD} ${ENDPOINT}`);
|
||||
},
|
||||
|
||||
@@ -50,9 +50,9 @@ export const preRequestScriptRunner = (
|
||||
isHoppCLIError(reason)
|
||||
? reason
|
||||
: error({
|
||||
code: "PRE_REQUEST_SCRIPT_ERROR",
|
||||
data: reason,
|
||||
})
|
||||
code: "PRE_REQUEST_SCRIPT_ERROR",
|
||||
data: reason,
|
||||
})
|
||||
)
|
||||
);
|
||||
|
||||
@@ -151,6 +151,12 @@ export function getEffectiveRESTRequest(
|
||||
request.endpoint,
|
||||
envVariables
|
||||
);
|
||||
|
||||
const maskedEnvVariables = setAllEnvironmentValuesToAsterisk(envVariables)
|
||||
const _effectiveFinalMaskedURL = parseTemplateStringE(
|
||||
request.endpoint,
|
||||
maskedEnvVariables)
|
||||
|
||||
if (E.isLeft(_effectiveFinalURL)) {
|
||||
return E.left(
|
||||
error({
|
||||
@@ -160,6 +166,7 @@ export function getEffectiveRESTRequest(
|
||||
);
|
||||
}
|
||||
const effectiveFinalURL = _effectiveFinalURL.right;
|
||||
const effectiveFinalMaskedURL = E.isLeft(_effectiveFinalMaskedURL) ? request.endpoint : _effectiveFinalMaskedURL.right;
|
||||
|
||||
return E.right({
|
||||
...request,
|
||||
@@ -167,6 +174,7 @@ export function getEffectiveRESTRequest(
|
||||
effectiveFinalHeaders,
|
||||
effectiveFinalParams,
|
||||
effectiveFinalBody,
|
||||
effectiveFinalMaskedURL,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -242,15 +250,15 @@ function getFinalBodyFromRequest(
|
||||
arrayFlatMap((x) =>
|
||||
x.isFile
|
||||
? x.value.map((v) => ({
|
||||
key: parseTemplateString(x.key, envVariables),
|
||||
value: v as string | Blob,
|
||||
}))
|
||||
key: parseTemplateString(x.key, envVariables),
|
||||
value: v as string | Blob,
|
||||
}))
|
||||
: [
|
||||
{
|
||||
key: parseTemplateString(x.key, envVariables),
|
||||
value: parseTemplateString(x.value, envVariables),
|
||||
},
|
||||
]
|
||||
{
|
||||
key: parseTemplateString(x.key, envVariables),
|
||||
value: parseTemplateString(x.value, envVariables),
|
||||
},
|
||||
]
|
||||
),
|
||||
toFormData,
|
||||
E.right
|
||||
@@ -287,3 +295,22 @@ export const getPreRequestMetrics = (
|
||||
hasPreReqErrors ? { failed: 1, passed: 0 } : { failed: 0, passed: 1 },
|
||||
(scripts) => <PreRequestMetrics>{ scripts, duration }
|
||||
);
|
||||
|
||||
/**
|
||||
* Mask all environment values with asterisks
|
||||
* @param variables Environment variable array
|
||||
* @returns Environment variable array with masked values
|
||||
*/
|
||||
const setAllEnvironmentValuesToAsterisk = (
|
||||
variables: Environment["variables"]
|
||||
): Environment["variables"] => {
|
||||
const envVariables: Environment["variables"] = [];
|
||||
for (const variable of variables) {
|
||||
let value = variable.value
|
||||
if (variable.secret) {
|
||||
value = "******"
|
||||
}
|
||||
envVariables.push({ key: variable.key, secret: variable.secret, value: value })
|
||||
}
|
||||
return envVariables
|
||||
}
|
||||
|
||||
@@ -220,6 +220,7 @@ export const processRequest =
|
||||
effectiveFinalHeaders: [],
|
||||
effectiveFinalParams: [],
|
||||
effectiveFinalURL: "",
|
||||
effectiveFinalMaskedURL:"",
|
||||
};
|
||||
|
||||
// Executing pre-request-script
|
||||
@@ -237,8 +238,8 @@ export const processRequest =
|
||||
|
||||
// Creating request-config for request-runner.
|
||||
const requestConfig = createRequest(effectiveRequest);
|
||||
|
||||
printRequestRunner.start(requestConfig);
|
||||
|
||||
printRequestRunner.start(requestConfig.method, effectiveRequest.effectiveFinalMaskedURL);
|
||||
|
||||
// Default value for request-runner's response.
|
||||
let _requestRunnerRes: RequestRunnerResponse = {
|
||||
|
||||
@@ -48,7 +48,8 @@
|
||||
"turn_off": "Ausschalten",
|
||||
"turn_on": "Einschalten",
|
||||
"undo": "Rückgängig machen",
|
||||
"yes": "Ja"
|
||||
"yes": "Ja",
|
||||
"secret": "Als Secret speichern"
|
||||
},
|
||||
"add": {
|
||||
"new": "Neue hinzufügen",
|
||||
@@ -880,4 +881,4 @@
|
||||
"team": "Team Workspace",
|
||||
"title": "Workspaces"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -48,7 +48,8 @@
|
||||
"turn_off": "Turn off",
|
||||
"turn_on": "Turn on",
|
||||
"undo": "Undo",
|
||||
"yes": "Yes"
|
||||
"yes": "Yes",
|
||||
"secret": "Save as secret"
|
||||
},
|
||||
"add": {
|
||||
"new": "Add new",
|
||||
|
||||
@@ -96,7 +96,6 @@ declare module 'vue' {
|
||||
HoppSmartExpand: typeof import('@hoppscotch/ui')['HoppSmartExpand']
|
||||
HoppSmartFileChip: typeof import('@hoppscotch/ui')['HoppSmartFileChip']
|
||||
HoppSmartInput: typeof import('@hoppscotch/ui')['HoppSmartInput']
|
||||
HoppSmartIntersection: typeof import('@hoppscotch/ui')['HoppSmartIntersection']
|
||||
HoppSmartItem: typeof import('@hoppscotch/ui')['HoppSmartItem']
|
||||
HoppSmartLink: typeof import('@hoppscotch/ui')['HoppSmartLink']
|
||||
HoppSmartModal: typeof import('@hoppscotch/ui')['HoppSmartModal']
|
||||
@@ -143,7 +142,6 @@ declare module 'vue' {
|
||||
IconLucideAlertTriangle: typeof import('~icons/lucide/alert-triangle')['default']
|
||||
IconLucideArrowLeft: typeof import('~icons/lucide/arrow-left')['default']
|
||||
IconLucideArrowUpRight: typeof import('~icons/lucide/arrow-up-right')['default']
|
||||
IconLucideBrush: typeof import('~icons/lucide/brush')['default']
|
||||
IconLucideCheckCircle: typeof import('~icons/lucide/check-circle')['default']
|
||||
IconLucideChevronRight: typeof import('~icons/lucide/chevron-right')['default']
|
||||
IconLucideGlobe: typeof import('~icons/lucide/globe')['default']
|
||||
@@ -153,10 +151,8 @@ declare module 'vue' {
|
||||
IconLucideLayers: typeof import('~icons/lucide/layers')['default']
|
||||
IconLucideListEnd: typeof import('~icons/lucide/list-end')['default']
|
||||
IconLucideMinus: typeof import('~icons/lucide/minus')['default']
|
||||
IconLucideRss: typeof import('~icons/lucide/rss')['default']
|
||||
IconLucideSearch: typeof import('~icons/lucide/search')['default']
|
||||
IconLucideUsers: typeof import('~icons/lucide/users')['default']
|
||||
IconLucideVerified: typeof import('~icons/lucide/verified')['default']
|
||||
InterceptorsExtensionSubtitle: typeof import('./components/interceptors/ExtensionSubtitle.vue')['default']
|
||||
LensesHeadersRenderer: typeof import('./components/lenses/HeadersRenderer.vue')['default']
|
||||
LensesHeadersRendererEntry: typeof import('./components/lenses/HeadersRendererEntry.vue')['default']
|
||||
|
||||
@@ -60,7 +60,17 @@
|
||||
:placeholder="`${t('count.value', { count: index + 1 })}`"
|
||||
:envs="liveEnvs"
|
||||
:name="'value' + index"
|
||||
:secret="env.secret"
|
||||
/>
|
||||
<div class="flex">
|
||||
<HoppButtonSecondary
|
||||
id="variable"
|
||||
v-tippy="{ theme: 'tooltip' }"
|
||||
:title="t('action.secret')"
|
||||
:icon="env.secret ? IconEyeOff : IconEye"
|
||||
@click="toggleEnvironmentSecret(index)"
|
||||
/>
|
||||
</div>
|
||||
<div class="flex">
|
||||
<HoppButtonSecondary
|
||||
id="variable"
|
||||
@@ -110,6 +120,8 @@ import IconTrash2 from "~icons/lucide/trash-2"
|
||||
import IconDone from "~icons/lucide/check"
|
||||
import IconPlus from "~icons/lucide/plus"
|
||||
import IconTrash from "~icons/lucide/trash"
|
||||
import IconEye from "~icons/lucide/eye"
|
||||
import IconEyeOff from "~icons/lucide/eye-off"
|
||||
import { clone } from "lodash-es"
|
||||
import { computed, ref, watch } from "vue"
|
||||
import * as E from "fp-ts/Either"
|
||||
@@ -140,6 +152,7 @@ type EnvironmentVariable = {
|
||||
env: {
|
||||
key: string
|
||||
value: string
|
||||
secret: boolean
|
||||
}
|
||||
}
|
||||
|
||||
@@ -172,7 +185,7 @@ const idTicker = ref(0)
|
||||
|
||||
const editingName = ref<string | null>(null)
|
||||
const vars = ref<EnvironmentVariable[]>([
|
||||
{ id: idTicker.value++, env: { key: "", value: "" } },
|
||||
{ id: idTicker.value++, env: { key: "", value: "", secret: false } },
|
||||
])
|
||||
|
||||
const clearIcon = refAutoReset<typeof IconTrash2 | typeof IconDone>(
|
||||
@@ -203,6 +216,8 @@ const workingEnv = computed(() => {
|
||||
}
|
||||
})
|
||||
|
||||
const oldEnvironments = ref<string[]>([])
|
||||
|
||||
const envList = useReadonlyStream(environments$, []) || props.envVars()
|
||||
|
||||
const evnExpandError = computed(() => {
|
||||
@@ -234,6 +249,28 @@ const liveEnvs = computed(() => {
|
||||
}
|
||||
})
|
||||
|
||||
watch(liveEnvs, (newLiveEnv, oldLiveEnv) => {
|
||||
const oldEnvLength = oldLiveEnv.length
|
||||
const newEnvLength = newLiveEnv.length
|
||||
if (oldEnvLength === newEnvLength) {
|
||||
const _oldEnvironments = []
|
||||
for (let i = 0; i < newEnvLength; i++) {
|
||||
const newVar = newLiveEnv[i]
|
||||
const oldVar = oldLiveEnv[i]
|
||||
let newValue = ""
|
||||
if (!newVar.secret) {
|
||||
newValue = newVar.value
|
||||
} else if (!oldVar.secret) {
|
||||
newValue = oldVar.value
|
||||
} else {
|
||||
newValue = oldEnvironments.value[i]
|
||||
}
|
||||
_oldEnvironments.push(newValue)
|
||||
}
|
||||
oldEnvironments.value = _oldEnvironments
|
||||
}
|
||||
})
|
||||
|
||||
watch(
|
||||
() => props.show,
|
||||
(show) => {
|
||||
@@ -262,6 +299,7 @@ const addEnvironmentVariable = () => {
|
||||
env: {
|
||||
key: "",
|
||||
value: "",
|
||||
secret: false,
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -270,12 +308,23 @@ const removeEnvironmentVariable = (index: number) => {
|
||||
vars.value.splice(index, 1)
|
||||
}
|
||||
|
||||
const toggleEnvironmentSecret = (index: number) => {
|
||||
vars.value[index].env.secret = !vars.value[index].env.secret
|
||||
}
|
||||
|
||||
const saveEnvironment = () => {
|
||||
if (!editingName.value) {
|
||||
toast.error(`${t("environment.invalid_name")}`)
|
||||
return
|
||||
}
|
||||
|
||||
const _vars = vars.value
|
||||
for (let i = 0; i < vars.value.length; i++) {
|
||||
const value = oldEnvironments.value[i]
|
||||
if (value) {
|
||||
_vars[i].env.value = value
|
||||
}
|
||||
}
|
||||
vars.value = _vars
|
||||
const filterdVariables = pipe(
|
||||
vars.value,
|
||||
A.filterMap(
|
||||
|
||||
@@ -63,7 +63,17 @@
|
||||
:envs="liveEnvs"
|
||||
:name="'value' + index"
|
||||
:readonly="isViewer"
|
||||
:secret="env.secret"
|
||||
/>
|
||||
<div v-if="!isViewer" class="flex">
|
||||
<HoppButtonSecondary
|
||||
id="variable"
|
||||
v-tippy="{ theme: 'tooltip' }"
|
||||
:title="t('action.secret')"
|
||||
:icon="env.secret ? IconEyeOff : IconEye"
|
||||
@click="toggleEnvironmentSecret(index)"
|
||||
/>
|
||||
</div>
|
||||
<div v-if="!isViewer" class="flex">
|
||||
<HoppButtonSecondary
|
||||
id="variable"
|
||||
@@ -139,6 +149,8 @@ import IconTrash from "~icons/lucide/trash"
|
||||
import IconTrash2 from "~icons/lucide/trash-2"
|
||||
import IconDone from "~icons/lucide/check"
|
||||
import IconPlus from "~icons/lucide/plus"
|
||||
import IconEye from "~icons/lucide/eye"
|
||||
import IconEyeOff from "~icons/lucide/eye-off"
|
||||
import { platform } from "~/platform"
|
||||
|
||||
type EnvironmentVariable = {
|
||||
@@ -146,6 +158,7 @@ type EnvironmentVariable = {
|
||||
env: {
|
||||
key: string
|
||||
value: string
|
||||
secret: boolean
|
||||
}
|
||||
}
|
||||
|
||||
@@ -182,9 +195,10 @@ const idTicker = ref(0)
|
||||
|
||||
const editingName = ref<string | null>(null)
|
||||
const vars = ref<EnvironmentVariable[]>([
|
||||
{ id: idTicker.value++, env: { key: "", value: "" } },
|
||||
{ id: idTicker.value++, env: { key: "", value: "", secret: false } },
|
||||
])
|
||||
|
||||
const oldEnvironments = ref<string[]>([])
|
||||
const clearIcon = refAutoReset<typeof IconTrash2 | typeof IconDone>(
|
||||
IconTrash2,
|
||||
1000
|
||||
@@ -212,6 +226,28 @@ const liveEnvs = computed(() => {
|
||||
}
|
||||
})
|
||||
|
||||
watch(liveEnvs, (newLiveEnv, oldLiveEnv) => {
|
||||
const oldEnvLength = oldLiveEnv.length
|
||||
const newEnvLength = newLiveEnv.length
|
||||
if (oldEnvLength === newEnvLength) {
|
||||
const _oldEnvironments = []
|
||||
for (let i = 0; i < newEnvLength; i++) {
|
||||
const newVar = newLiveEnv[i]
|
||||
const oldVar = oldLiveEnv[i]
|
||||
let newValue = ""
|
||||
if (!newVar.secret) {
|
||||
newValue = newVar.value
|
||||
} else if (!oldVar.secret) {
|
||||
newValue = oldVar.value
|
||||
} else {
|
||||
newValue = oldEnvironments.value[i]
|
||||
}
|
||||
_oldEnvironments.push(newValue)
|
||||
}
|
||||
oldEnvironments.value = _oldEnvironments
|
||||
}
|
||||
})
|
||||
|
||||
watch(
|
||||
() => props.show,
|
||||
(show) => {
|
||||
@@ -220,7 +256,7 @@ watch(
|
||||
editingName.value = null
|
||||
vars.value = pipe(
|
||||
props.envVars() ?? [],
|
||||
A.map((e: { key: string; value: string }) => ({
|
||||
A.map((e: { key: string; value: string; secret: boolean }) => ({
|
||||
id: idTicker.value++,
|
||||
env: clone(e),
|
||||
}))
|
||||
@@ -229,7 +265,7 @@ watch(
|
||||
editingName.value = props.editingEnvironment.environment.name ?? null
|
||||
vars.value = pipe(
|
||||
props.editingEnvironment.environment.variables ?? [],
|
||||
A.map((e: { key: string; value: string }) => ({
|
||||
A.map((e: { key: string; value: string; secret: boolean }) => ({
|
||||
id: idTicker.value++,
|
||||
env: clone(e),
|
||||
}))
|
||||
@@ -251,6 +287,7 @@ const addEnvironmentVariable = () => {
|
||||
env: {
|
||||
key: "",
|
||||
value: "",
|
||||
secret: false,
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -259,6 +296,10 @@ const removeEnvironmentVariable = (index: number) => {
|
||||
vars.value.splice(index, 1)
|
||||
}
|
||||
|
||||
const toggleEnvironmentSecret = (index: number) => {
|
||||
vars.value[index].env.secret = !vars.value[index].env.secret
|
||||
}
|
||||
|
||||
const isLoading = ref(false)
|
||||
|
||||
const saveEnvironment = async () => {
|
||||
@@ -269,6 +310,15 @@ const saveEnvironment = async () => {
|
||||
return
|
||||
}
|
||||
|
||||
const _vars = vars.value
|
||||
for (let i = 0; i < vars.value.length; i++) {
|
||||
const value = oldEnvironments.value[i]
|
||||
if (value) {
|
||||
_vars[i].env.value = value
|
||||
}
|
||||
}
|
||||
vars.value = _vars
|
||||
|
||||
const filterdVariables = pipe(
|
||||
vars.value,
|
||||
A.filterMap(
|
||||
|
||||
@@ -279,6 +279,7 @@ const globalEnvVars = useReadonlyStream(globalEnv$, []) as Ref<
|
||||
Array<{
|
||||
key: string
|
||||
value: string
|
||||
secret: boolean
|
||||
}>
|
||||
>
|
||||
|
||||
|
||||
@@ -48,6 +48,7 @@ type Props = {
|
||||
env: {
|
||||
key: string
|
||||
value: string
|
||||
secret: boolean
|
||||
previousValue?: string
|
||||
}
|
||||
status: Status
|
||||
|
||||
@@ -55,7 +55,12 @@ import {
|
||||
keymap,
|
||||
tooltips,
|
||||
} from "@codemirror/view"
|
||||
import { EditorSelection, EditorState, Extension } from "@codemirror/state"
|
||||
import {
|
||||
EditorSelection,
|
||||
EditorState,
|
||||
Extension,
|
||||
StateEffect,
|
||||
} from "@codemirror/state"
|
||||
import { clone } from "lodash-es"
|
||||
import { history, historyKeymap } from "@codemirror/commands"
|
||||
import { inputTheme } from "~/helpers/editor/themes/baseTheme"
|
||||
@@ -72,13 +77,17 @@ const props = withDefaults(
|
||||
modelValue?: string
|
||||
placeholder?: string
|
||||
styles?: string
|
||||
envs?: { key: string; value: string; source: string }[] | null
|
||||
envs?:
|
||||
| { key: string; value: string; secret: boolean; source: string }[]
|
||||
| null
|
||||
focus?: boolean
|
||||
selectTextOnMount?: boolean
|
||||
environmentHighlights?: boolean
|
||||
readonly?: boolean
|
||||
autoCompleteSource?: string[]
|
||||
inspectionResults?: InspectorResult[] | undefined
|
||||
defaultValue?: string
|
||||
secret?: boolean
|
||||
}>(),
|
||||
{
|
||||
modelValue: "",
|
||||
@@ -91,6 +100,8 @@ const props = withDefaults(
|
||||
autoCompleteSource: undefined,
|
||||
inspectionResult: undefined,
|
||||
inspectionResults: undefined,
|
||||
defaultValue: "",
|
||||
secret: false,
|
||||
}
|
||||
)
|
||||
|
||||
@@ -104,6 +115,8 @@ const emit = defineEmits<{
|
||||
(e: "click", ev: any): void
|
||||
}>()
|
||||
|
||||
const asterikedText = computed(() => "*".repeat(props.modelValue.length))
|
||||
|
||||
const cachedValue = ref(props.modelValue)
|
||||
|
||||
const view = ref<EditorView>()
|
||||
@@ -263,6 +276,22 @@ watch(
|
||||
}
|
||||
)
|
||||
|
||||
const prevModelValue = ref(props.modelValue)
|
||||
|
||||
watch(
|
||||
() => props.secret,
|
||||
(newValue) => {
|
||||
let visibleValue = asterikedText.value
|
||||
if (!newValue) {
|
||||
visibleValue = prevModelValue.value
|
||||
} else {
|
||||
prevModelValue.value = props.modelValue
|
||||
}
|
||||
emit("update:modelValue", visibleValue)
|
||||
updateEditorViewTheme(newValue)
|
||||
}
|
||||
)
|
||||
|
||||
/**
|
||||
* Used to scroll the active suggestion into view
|
||||
*/
|
||||
@@ -284,7 +313,6 @@ watch(
|
||||
() => props.modelValue,
|
||||
(newVal) => {
|
||||
const singleLinedText = newVal.replaceAll("\n", "")
|
||||
|
||||
const currDoc = view.value?.state.doc
|
||||
.toJSON()
|
||||
.join(view.value.state.lineBreak)
|
||||
@@ -320,6 +348,7 @@ const envVars = computed(() =>
|
||||
? props.envs.map((x) => ({
|
||||
key: x.key,
|
||||
value: x.value,
|
||||
secret: x.secret,
|
||||
sourceEnv: x.source,
|
||||
}))
|
||||
: aggregateEnvs.value
|
||||
@@ -354,6 +383,14 @@ function handleTextSelection() {
|
||||
}
|
||||
}
|
||||
}
|
||||
const updateEditorViewTheme = (readonly: boolean) => {
|
||||
if (view.value) {
|
||||
const extensions: Extension = getExtensions(readonly)
|
||||
view.value.dispatch({
|
||||
effects: [StateEffect.reconfigure.of(extensions)],
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const initView = (el: any) => {
|
||||
// Debounce to prevent double click from selecting the word
|
||||
@@ -364,17 +401,31 @@ const initView = (el: any) => {
|
||||
el.addEventListener("mouseup", debounceFn)
|
||||
el.addEventListener("keyup", debounceFn)
|
||||
|
||||
if (props.secret) {
|
||||
emit("update:modelValue", asterikedText.value)
|
||||
}
|
||||
const extensions: Extension = getExtensions(props.readonly || props.secret)
|
||||
view.value = new EditorView({
|
||||
parent: el,
|
||||
state: EditorState.create({
|
||||
doc: props.modelValue,
|
||||
extensions,
|
||||
}),
|
||||
})
|
||||
}
|
||||
|
||||
const getExtensions = (readonly: boolean): Extension => {
|
||||
const extensions: Extension = [
|
||||
EditorView.contentAttributes.of({ "aria-label": props.placeholder }),
|
||||
EditorView.contentAttributes.of({ "data-enable-grammarly": "false" }),
|
||||
EditorView.updateListener.of((update) => {
|
||||
if (props.readonly) {
|
||||
if (readonly) {
|
||||
update.view.contentDOM.inputMode = "none"
|
||||
}
|
||||
}),
|
||||
EditorState.changeFilter.of(() => !props.readonly),
|
||||
EditorState.changeFilter.of(() => !readonly),
|
||||
inputTheme,
|
||||
props.readonly
|
||||
readonly
|
||||
? EditorView.theme({
|
||||
".cm-content": {
|
||||
caretColor: "var(--secondary-dark-color)",
|
||||
@@ -406,7 +457,7 @@ const initView = (el: any) => {
|
||||
ViewPlugin.fromClass(
|
||||
class {
|
||||
update(update: ViewUpdate) {
|
||||
if (props.readonly) return
|
||||
if (readonly) return
|
||||
|
||||
if (update.docChanged) {
|
||||
const prevValue = clone(cachedValue.value)
|
||||
@@ -418,9 +469,14 @@ const initView = (el: any) => {
|
||||
// We do not update the cache directly in this case (to trigger value watcher to dispatch)
|
||||
// So, we desync cachedValue a bit so we can trigger updates
|
||||
const value = clone(cachedValue.value).replaceAll("\n", "")
|
||||
|
||||
emit("update:modelValue", value)
|
||||
emit("change", value)
|
||||
if (props.secret) {
|
||||
const asterikedValue = "*".repeat(value.length)
|
||||
emit("update:modelValue", asterikedValue)
|
||||
emit("change", asterikedValue)
|
||||
} else {
|
||||
emit("update:modelValue", value)
|
||||
emit("change", value)
|
||||
}
|
||||
|
||||
const pasted = !!update.transactions.find((txn) =>
|
||||
txn.isUserEvent("input.paste")
|
||||
@@ -445,14 +501,7 @@ const initView = (el: any) => {
|
||||
history(),
|
||||
keymap.of([...historyKeymap]),
|
||||
]
|
||||
|
||||
view.value = new EditorView({
|
||||
parent: el,
|
||||
state: EditorState.create({
|
||||
doc: props.modelValue,
|
||||
extensions,
|
||||
}),
|
||||
})
|
||||
return extensions
|
||||
}
|
||||
|
||||
const triggerTextSelection = () => {
|
||||
|
||||
@@ -66,7 +66,10 @@ const cursorTooltipField = (aggregateEnvs: AggregateEnvironment[]) =>
|
||||
|
||||
const envName = tooltipEnv?.sourceEnv ?? "Choose an Environment"
|
||||
|
||||
const envValue = tooltipEnv?.value ?? "Not found"
|
||||
let envValue = tooltipEnv?.value ?? "Not found"
|
||||
if (tooltipEnv?.secret) {
|
||||
envValue = "******"
|
||||
}
|
||||
|
||||
const result = parseTemplateStringE(envValue, aggregateEnvs)
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"!name": "pw-pre",
|
||||
"pw": {
|
||||
"env": {
|
||||
"set": "fn(key: string, value: string)",
|
||||
"set": "fn(key: string, value: string, secret: boolean)",
|
||||
"get": "fn(key: string) -> string",
|
||||
"getResolve": "fn(key: string) -> string",
|
||||
"resolve": "fn(value: string) -> string"
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
"body": "?"
|
||||
},
|
||||
"env": {
|
||||
"set": "fn(key: string, value: string)",
|
||||
"set": "fn(key: string, value: string, secret:boolean)",
|
||||
"get": "fn(key: string) -> string",
|
||||
"getResolve": "fn(key: string) -> string",
|
||||
"resolve": "fn(value: string) -> string"
|
||||
|
||||
@@ -186,14 +186,19 @@ const dispatchers = defineDispatchers({
|
||||
},
|
||||
addEnvironmentVariable(
|
||||
{ environments }: EnvironmentStore,
|
||||
{ envIndex, key, value }: { envIndex: number; key: string; value: string }
|
||||
{
|
||||
envIndex,
|
||||
key,
|
||||
value,
|
||||
secret,
|
||||
}: { envIndex: number; key: string; value: string; secret: boolean }
|
||||
) {
|
||||
return {
|
||||
environments: environments.map((env, index) =>
|
||||
index === envIndex
|
||||
? {
|
||||
...env,
|
||||
variables: [...env.variables, { key, value }],
|
||||
variables: [...env.variables, { key, value, secret }],
|
||||
}
|
||||
: env
|
||||
),
|
||||
@@ -221,7 +226,10 @@ const dispatchers = defineDispatchers({
|
||||
{
|
||||
envIndex,
|
||||
vars,
|
||||
}: { envIndex: number; vars: { key: string; value: string }[] }
|
||||
}: {
|
||||
envIndex: number
|
||||
vars: { key: string; value: string; secret: boolean }[]
|
||||
}
|
||||
) {
|
||||
return {
|
||||
environments: environments.map((env, index) =>
|
||||
@@ -241,11 +249,13 @@ const dispatchers = defineDispatchers({
|
||||
variableIndex,
|
||||
updatedKey,
|
||||
updatedValue,
|
||||
updatedSecret,
|
||||
}: {
|
||||
envIndex: number
|
||||
variableIndex: number
|
||||
updatedKey: string
|
||||
updatedValue: string
|
||||
updatedSecret: boolean
|
||||
}
|
||||
) {
|
||||
return {
|
||||
@@ -255,7 +265,11 @@ const dispatchers = defineDispatchers({
|
||||
...env,
|
||||
variables: env.variables.map((v, vIndex) =>
|
||||
vIndex === variableIndex
|
||||
? { key: updatedKey, value: updatedValue }
|
||||
? {
|
||||
key: updatedKey,
|
||||
value: updatedValue,
|
||||
secret: updatedSecret,
|
||||
}
|
||||
: v
|
||||
),
|
||||
}
|
||||
@@ -359,6 +373,7 @@ export const currentEnvironment$: Observable<Environment | undefined> =
|
||||
export type AggregateEnvironment = {
|
||||
key: string
|
||||
value: string
|
||||
secret: boolean
|
||||
sourceEnv: string
|
||||
}
|
||||
|
||||
@@ -373,11 +388,11 @@ export const aggregateEnvs$: Observable<AggregateEnvironment[]> = combineLatest(
|
||||
map(([selectedEnv, globalVars]) => {
|
||||
const results: AggregateEnvironment[] = []
|
||||
|
||||
selectedEnv?.variables.forEach(({ key, value }) =>
|
||||
results.push({ key, value, sourceEnv: selectedEnv.name })
|
||||
selectedEnv?.variables.forEach(({ key, value, secret }) =>
|
||||
results.push({ key, value, secret, sourceEnv: selectedEnv.name })
|
||||
)
|
||||
globalVars.forEach(({ key, value }) =>
|
||||
results.push({ key, value, sourceEnv: "Global" })
|
||||
globalVars.forEach(({ key, value, secret }) =>
|
||||
results.push({ key, value, secret, sourceEnv: "Global" })
|
||||
)
|
||||
|
||||
return results
|
||||
@@ -593,7 +608,7 @@ export function updateEnvironment(envIndex: number, updatedEnv: Environment) {
|
||||
|
||||
export function setEnvironmentVariables(
|
||||
envIndex: number,
|
||||
vars: { key: string; value: string }[]
|
||||
vars: { key: string; value: string; secret: boolean }[]
|
||||
) {
|
||||
environmentsStore.dispatch({
|
||||
dispatcher: "setEnvironmentVariables",
|
||||
@@ -606,7 +621,7 @@ export function setEnvironmentVariables(
|
||||
|
||||
export function addEnvironmentVariable(
|
||||
envIndex: number,
|
||||
{ key, value }: { key: string; value: string }
|
||||
{ key, value, secret }: { key: string; value: string; secret: boolean }
|
||||
) {
|
||||
environmentsStore.dispatch({
|
||||
dispatcher: "addEnvironmentVariable",
|
||||
@@ -614,6 +629,7 @@ export function addEnvironmentVariable(
|
||||
envIndex,
|
||||
key,
|
||||
value,
|
||||
secret,
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -634,7 +650,7 @@ export function removeEnvironmentVariable(
|
||||
export function updateEnvironmentVariable(
|
||||
envIndex: number,
|
||||
variableIndex: number,
|
||||
{ key, value }: { key: string; value: string }
|
||||
{ key, value, secret }: { key: string; value: string; secret: boolean }
|
||||
) {
|
||||
environmentsStore.dispatch({
|
||||
dispatcher: "updateEnvironmentVariable",
|
||||
@@ -643,6 +659,7 @@ export function updateEnvironmentVariable(
|
||||
variableIndex,
|
||||
updatedKey: key,
|
||||
updatedValue: value,
|
||||
updatedSecret: secret,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ export type Environment = {
|
||||
variables: {
|
||||
key: string
|
||||
value: string
|
||||
secret: boolean
|
||||
}[]
|
||||
}
|
||||
|
||||
|
||||
@@ -11,16 +11,16 @@ describe("execPreRequestScript", () => {
|
||||
{
|
||||
global: [],
|
||||
selected: [
|
||||
{ key: "bob", value: "oldbob" },
|
||||
{ key: "foo", value: "bar" },
|
||||
{ key: "bob", value: "oldbob", secret: false },
|
||||
{ key: "foo", value: "bar", secret: false },
|
||||
],
|
||||
}
|
||||
)()
|
||||
).resolves.toEqualRight({
|
||||
global: [],
|
||||
selected: [
|
||||
{ key: "bob", value: "newbob" },
|
||||
{ key: "foo", value: "bar" },
|
||||
{ key: "bob", value: "newbob", secret: false },
|
||||
{ key: "foo", value: "bar", secret: false },
|
||||
],
|
||||
})
|
||||
})
|
||||
@@ -34,8 +34,8 @@ describe("execPreRequestScript", () => {
|
||||
{
|
||||
global: [],
|
||||
selected: [
|
||||
{ key: "bob", value: "oldbob" },
|
||||
{ key: "foo", value: "bar" },
|
||||
{ key: "bob", value: "oldbob", secret: false },
|
||||
{ key: "foo", value: "bar", secret: false },
|
||||
],
|
||||
}
|
||||
)()
|
||||
@@ -51,8 +51,8 @@ describe("execPreRequestScript", () => {
|
||||
{
|
||||
global: [],
|
||||
selected: [
|
||||
{ key: "bob", value: "oldbob" },
|
||||
{ key: "foo", value: "bar" },
|
||||
{ key: "bob", value: "oldbob", secret: false },
|
||||
{ key: "foo", value: "bar", secret: false },
|
||||
],
|
||||
}
|
||||
)()
|
||||
@@ -68,8 +68,8 @@ describe("execPreRequestScript", () => {
|
||||
{
|
||||
global: [],
|
||||
selected: [
|
||||
{ key: "bob", value: "oldbob" },
|
||||
{ key: "foo", value: "bar" },
|
||||
{ key: "bob", value: "oldbob", secret: false },
|
||||
{ key: "foo", value: "bar", secret: false },
|
||||
],
|
||||
}
|
||||
)()
|
||||
@@ -86,7 +86,7 @@ describe("execPreRequestScript", () => {
|
||||
)()
|
||||
).resolves.toEqualRight({
|
||||
global: [],
|
||||
selected: [{ key: "foo", value: "bar" }],
|
||||
selected: [{ key: "foo", value: "bar", secret: false }],
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -30,6 +30,7 @@ describe("pw.env.get", () => {
|
||||
{
|
||||
key: "a",
|
||||
value: "b",
|
||||
secret: false,
|
||||
},
|
||||
],
|
||||
}
|
||||
@@ -58,6 +59,7 @@ describe("pw.env.get", () => {
|
||||
{
|
||||
key: "a",
|
||||
value: "b",
|
||||
secret: false,
|
||||
},
|
||||
],
|
||||
selected: [],
|
||||
@@ -111,12 +113,14 @@ describe("pw.env.get", () => {
|
||||
{
|
||||
key: "a",
|
||||
value: "global val",
|
||||
secret: false,
|
||||
},
|
||||
],
|
||||
selected: [
|
||||
{
|
||||
key: "a",
|
||||
value: "selected val",
|
||||
secret: false,
|
||||
},
|
||||
],
|
||||
}
|
||||
@@ -146,6 +150,7 @@ describe("pw.env.get", () => {
|
||||
{
|
||||
key: "a",
|
||||
value: "<<hello>>",
|
||||
secret: false,
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ describe("pw.env.getResolve", () => {
|
||||
{
|
||||
key: "a",
|
||||
value: "b",
|
||||
secret: false,
|
||||
},
|
||||
],
|
||||
}
|
||||
@@ -58,6 +59,7 @@ describe("pw.env.getResolve", () => {
|
||||
{
|
||||
key: "a",
|
||||
value: "b",
|
||||
secret: false,
|
||||
},
|
||||
],
|
||||
selected: [],
|
||||
@@ -111,12 +113,14 @@ describe("pw.env.getResolve", () => {
|
||||
{
|
||||
key: "a",
|
||||
value: "global val",
|
||||
secret: false,
|
||||
},
|
||||
],
|
||||
selected: [
|
||||
{
|
||||
key: "a",
|
||||
value: "selected val",
|
||||
secret: false,
|
||||
},
|
||||
],
|
||||
}
|
||||
@@ -146,10 +150,12 @@ describe("pw.env.getResolve", () => {
|
||||
{
|
||||
key: "a",
|
||||
value: "<<hello>>",
|
||||
secret: false,
|
||||
},
|
||||
{
|
||||
key: "hello",
|
||||
value: "there",
|
||||
secret: false,
|
||||
},
|
||||
],
|
||||
}
|
||||
@@ -179,10 +185,12 @@ describe("pw.env.getResolve", () => {
|
||||
{
|
||||
key: "a",
|
||||
value: "<<hello>>",
|
||||
secret: false,
|
||||
},
|
||||
{
|
||||
key: "hello",
|
||||
value: "<<a>>",
|
||||
secret: false,
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
@@ -41,6 +41,7 @@ describe("pw.env.resolve", () => {
|
||||
{
|
||||
key: "hello",
|
||||
value: "there",
|
||||
secret: false,
|
||||
},
|
||||
],
|
||||
selected: [],
|
||||
@@ -71,6 +72,7 @@ describe("pw.env.resolve", () => {
|
||||
{
|
||||
key: "hello",
|
||||
value: "there",
|
||||
secret: false,
|
||||
},
|
||||
],
|
||||
}
|
||||
@@ -99,12 +101,14 @@ describe("pw.env.resolve", () => {
|
||||
{
|
||||
key: "hello",
|
||||
value: "yo",
|
||||
secret: false,
|
||||
},
|
||||
],
|
||||
selected: [
|
||||
{
|
||||
key: "hello",
|
||||
value: "there",
|
||||
secret: false,
|
||||
},
|
||||
],
|
||||
}
|
||||
@@ -134,10 +138,12 @@ describe("pw.env.resolve", () => {
|
||||
{
|
||||
key: "hello",
|
||||
value: "<<there>>",
|
||||
secret: false,
|
||||
},
|
||||
{
|
||||
key: "there",
|
||||
value: "<<hello>>",
|
||||
secret: false,
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@ describe("pw.env.set", () => {
|
||||
{
|
||||
key: "a",
|
||||
value: "b",
|
||||
secret: false,
|
||||
},
|
||||
],
|
||||
}
|
||||
@@ -43,6 +44,7 @@ describe("pw.env.set", () => {
|
||||
{
|
||||
key: "a",
|
||||
value: "c",
|
||||
secret: false,
|
||||
},
|
||||
],
|
||||
})
|
||||
@@ -60,6 +62,7 @@ describe("pw.env.set", () => {
|
||||
{
|
||||
key: "a",
|
||||
value: "b",
|
||||
secret: false,
|
||||
},
|
||||
],
|
||||
selected: [],
|
||||
@@ -71,6 +74,7 @@ describe("pw.env.set", () => {
|
||||
{
|
||||
key: "a",
|
||||
value: "c",
|
||||
secret: false,
|
||||
},
|
||||
],
|
||||
})
|
||||
@@ -88,12 +92,14 @@ describe("pw.env.set", () => {
|
||||
{
|
||||
key: "a",
|
||||
value: "b",
|
||||
secret: false,
|
||||
},
|
||||
],
|
||||
selected: [
|
||||
{
|
||||
key: "a",
|
||||
value: "d",
|
||||
secret: false,
|
||||
},
|
||||
],
|
||||
}
|
||||
@@ -104,12 +110,14 @@ describe("pw.env.set", () => {
|
||||
{
|
||||
key: "a",
|
||||
value: "b",
|
||||
secret: false,
|
||||
},
|
||||
],
|
||||
selected: [
|
||||
{
|
||||
key: "a",
|
||||
value: "c",
|
||||
secret: false,
|
||||
},
|
||||
],
|
||||
})
|
||||
@@ -134,6 +142,7 @@ describe("pw.env.set", () => {
|
||||
{
|
||||
key: "a",
|
||||
value: "c",
|
||||
secret: false,
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
@@ -87,28 +87,32 @@ export const execPreRequestScript = (
|
||||
}
|
||||
})
|
||||
|
||||
const envSetHandle = vm.newFunction("set", (keyHandle, valueHandle) => {
|
||||
const key: unknown = vm.dump(keyHandle)
|
||||
const value: unknown = vm.dump(valueHandle)
|
||||
const envSetHandle = vm.newFunction(
|
||||
"set",
|
||||
(keyHandle, valueHandle, secretHandle) => {
|
||||
const key: unknown = vm.dump(keyHandle)
|
||||
const value: unknown = vm.dump(valueHandle)
|
||||
const secret: boolean = vm.dump(secretHandle)
|
||||
|
||||
if (typeof key !== "string") {
|
||||
return {
|
||||
error: vm.newString("Expected key to be a string"),
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof value !== "string") {
|
||||
return {
|
||||
error: vm.newString("Expected value to be a string"),
|
||||
}
|
||||
}
|
||||
|
||||
currentEnvs = setEnv(key, value, secret, currentEnvs)
|
||||
|
||||
if (typeof key !== "string") {
|
||||
return {
|
||||
error: vm.newString("Expected key to be a string"),
|
||||
value: vm.undefined,
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof value !== "string") {
|
||||
return {
|
||||
error: vm.newString("Expected value to be a string"),
|
||||
}
|
||||
}
|
||||
|
||||
currentEnvs = setEnv(key, value, currentEnvs)
|
||||
|
||||
return {
|
||||
value: vm.undefined,
|
||||
}
|
||||
})
|
||||
)
|
||||
|
||||
const envResolveHandle = vm.newFunction("resolve", (valueHandle) => {
|
||||
const value: unknown = vm.dump(valueHandle)
|
||||
|
||||
@@ -527,28 +527,32 @@ export const execTestScript = (
|
||||
}
|
||||
)
|
||||
|
||||
const envSetHandle = vm.newFunction("set", (keyHandle, valueHandle) => {
|
||||
const key: unknown = vm.dump(keyHandle)
|
||||
const value: unknown = vm.dump(valueHandle)
|
||||
const envSetHandle = vm.newFunction(
|
||||
"set",
|
||||
(keyHandle, valueHandle, secretHandle) => {
|
||||
const key: unknown = vm.dump(keyHandle)
|
||||
const value: unknown = vm.dump(valueHandle)
|
||||
const secret: boolean = vm.dump(secretHandle)
|
||||
|
||||
if (typeof key !== "string") {
|
||||
return {
|
||||
error: vm.newString("Expected key to be a string"),
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof value !== "string") {
|
||||
return {
|
||||
error: vm.newString("Expected value to be a string"),
|
||||
}
|
||||
}
|
||||
|
||||
currentEnvs = setEnv(key, value, secret, currentEnvs)
|
||||
|
||||
if (typeof key !== "string") {
|
||||
return {
|
||||
error: vm.newString("Expected key to be a string"),
|
||||
value: vm.undefined,
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof value !== "string") {
|
||||
return {
|
||||
error: vm.newString("Expected value to be a string"),
|
||||
}
|
||||
}
|
||||
|
||||
currentEnvs = setEnv(key, value, currentEnvs)
|
||||
|
||||
return {
|
||||
value: vm.undefined,
|
||||
}
|
||||
})
|
||||
)
|
||||
|
||||
const envResolveHandle = vm.newFunction("resolve", (valueHandle) => {
|
||||
const value: unknown = vm.dump(valueHandle)
|
||||
|
||||
@@ -50,6 +50,7 @@ export function getEnv(envName: string, envs: TestResult["envs"]) {
|
||||
export function setEnv(
|
||||
envName: string,
|
||||
envValue: string,
|
||||
envSecret: boolean,
|
||||
envs: TestResult["envs"]
|
||||
): TestResult["envs"] {
|
||||
const indexInSelected = envs.selected.findIndex((x) => x.key === envName)
|
||||
@@ -80,6 +81,7 @@ export function setEnv(
|
||||
envs.selected.push({
|
||||
key: envName,
|
||||
value: envValue,
|
||||
secret: envSecret,
|
||||
})
|
||||
|
||||
return {
|
||||
|
||||
Reference in New Issue
Block a user