fix(js-sandbox): improve scripting value handling and serialization
- Fix null/undefined environment variable handling across namespaces
- Fix pm.request console.log output to display properly
- Add pm.request.id and pm.request.name type definitions
- Fix assertion error messages to show actual values
- Strip `export {};` from collection exports and legacy sandbox editor display
This commit is contained in:
parent
c0e3ff49b3
commit
ae3d73bb32
8 changed files with 511 additions and 12 deletions
|
|
@ -2831,9 +2831,12 @@ const exportData = async (collection: HoppCollection | TeamCollection) => {
|
|||
if (collectionsType.value.type === "my-collections") {
|
||||
const collectionJSON = JSON.stringify(collection, null, 2)
|
||||
|
||||
// Strip `export {};\n` from `testScript` and `preRequestScript` fields
|
||||
const cleanedCollectionJSON = collectionJSON.replace(/export \{\};\\n/g, "")
|
||||
|
||||
const name = (collection as HoppCollection).name
|
||||
|
||||
initializeDownloadCollection(collectionJSON, name)
|
||||
initializeDownloadCollection(cleanedCollectionJSON, name)
|
||||
} else {
|
||||
if (!collection.id) return
|
||||
exportLoading.value = true
|
||||
|
|
@ -2850,8 +2853,14 @@ const exportData = async (collection: HoppCollection | TeamCollection) => {
|
|||
const hoppColl = teamCollToHoppRESTColl(coll)
|
||||
const collectionJSONString = JSON.stringify(hoppColl, null, 2)
|
||||
|
||||
// Strip `export {};\n` from `testScript` and `preRequestScript` fields
|
||||
const cleanedCollectionJSON = collectionJSONString.replace(
|
||||
/export \{\};\\n/g,
|
||||
""
|
||||
)
|
||||
|
||||
await initializeDownloadCollection(
|
||||
collectionJSONString,
|
||||
cleanedCollectionJSON,
|
||||
hoppColl.name
|
||||
)
|
||||
exportLoading.value = false
|
||||
|
|
|
|||
|
|
@ -268,6 +268,19 @@ const getEditorLanguage = (
|
|||
completer: Completer | undefined
|
||||
): Extension => hoppLang(getLanguage(langMime) ?? undefined, linter, completer)
|
||||
|
||||
const MODULE_PREFIX = "export {};\n" as const
|
||||
|
||||
/**
|
||||
* Strips the `export {};\n` prefix from the value for display in the editor.
|
||||
* The above is only used internally for Monaco editor's module scope,
|
||||
* and should not be visible in the CodeMirror editor.
|
||||
*/
|
||||
const stripModulePrefix = (value?: string): string | undefined => {
|
||||
return value?.startsWith(MODULE_PREFIX)
|
||||
? value.slice(MODULE_PREFIX.length)
|
||||
: value
|
||||
}
|
||||
|
||||
export function useCodemirror(
|
||||
el: Ref<any | null>,
|
||||
value: Ref<string | undefined>,
|
||||
|
|
@ -474,7 +487,10 @@ export function useCodemirror(
|
|||
view.value = new EditorView({
|
||||
parent: el,
|
||||
state: EditorState.create({
|
||||
doc: parseDoc(value.value, options.extendedEditorConfig.mode ?? ""),
|
||||
doc: parseDoc(
|
||||
stripModulePrefix(value.value),
|
||||
options.extendedEditorConfig.mode ?? ""
|
||||
),
|
||||
extensions,
|
||||
}),
|
||||
// scroll to top when mounting
|
||||
|
|
@ -514,13 +530,17 @@ export function useCodemirror(
|
|||
if (!view.value && el.value) {
|
||||
initView(el.value)
|
||||
}
|
||||
|
||||
// Strip `export {};\n` before displaying in CodeMirror
|
||||
const displayValue = stripModulePrefix(newVal) ?? ""
|
||||
|
||||
if (cachedValue.value !== newVal) {
|
||||
view.value?.dispatch({
|
||||
filter: false,
|
||||
changes: {
|
||||
from: 0,
|
||||
to: view.value.state.doc.length,
|
||||
insert: newVal,
|
||||
insert: displayValue,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -652,6 +652,8 @@ declare namespace pm {
|
|||
}>
|
||||
|
||||
const request: Readonly<{
|
||||
readonly id: string
|
||||
readonly name: string
|
||||
readonly url: Readonly<{
|
||||
toString(): string
|
||||
readonly protocol: string
|
||||
|
|
|
|||
|
|
@ -106,9 +106,8 @@ describe("Environment Variable Fallback Behavior - All Namespaces", () => {
|
|||
"$name - currentValue undefined/null fallback",
|
||||
({ get }) => {
|
||||
// Note: These tests check GET behavior with null/undefined in initial state.
|
||||
// Setting null via pm.environment.set(key, null) is currently NOT supported.
|
||||
// These tests validate fallback logic when null/undefined exists in the env state,
|
||||
// which can occur through other means (e.g., test setup, external sources).
|
||||
// Setting null via pm.environment.set(key, null) IS supported (via NULL_MARKER).
|
||||
// These tests validate fallback logic when null/undefined exists in the env state.
|
||||
|
||||
test("should fallback to initialValue when currentValue is undefined", async () => {
|
||||
const envs = {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,378 @@
|
|||
/**
|
||||
* Null and Undefined Value Preservation Across Namespaces
|
||||
*
|
||||
* Tests that null and undefined values are correctly preserved when setting
|
||||
* and getting environment variables across pm, pw, and hopp namespaces.
|
||||
*/
|
||||
|
||||
import { describe, expect, test } from "vitest"
|
||||
import { runTest } from "~/utils/test-helpers"
|
||||
|
||||
describe("Null and undefined value preservation across namespaces", () => {
|
||||
describe("Cross-namespace null value handling", () => {
|
||||
test("pm.environment.set with null should work across pm, pw, and hopp namespaces", () => {
|
||||
return expect(
|
||||
runTest(
|
||||
`
|
||||
pm.environment.set('key', null)
|
||||
|
||||
pm.test("pm.environment.get returns actual null", () => {
|
||||
pm.expect(pm.environment.get('key')).to.equal(null)
|
||||
})
|
||||
|
||||
pm.test("typeof null should be 'object'", () => {
|
||||
pm.expect(typeof pm.environment.get('key')).to.equal('object')
|
||||
})
|
||||
|
||||
pm.test("pw.env.get returns actual null (cross-namespace)", () => {
|
||||
pm.expect(pw.env.get('key')).to.equal(null)
|
||||
})
|
||||
|
||||
pm.test("typeof via pw.env.get should be 'object'", () => {
|
||||
pm.expect(typeof pw.env.get('key')).to.equal('object')
|
||||
})
|
||||
|
||||
pm.test("hopp.env.get returns actual null (cross-namespace)", () => {
|
||||
pm.expect(hopp.env.get('key')).to.equal(null)
|
||||
})
|
||||
|
||||
pm.test("typeof via hopp.env.get should be 'object'", () => {
|
||||
pm.expect(typeof hopp.env.get('key')).to.equal('object')
|
||||
})
|
||||
`,
|
||||
{ global: [], selected: [] }
|
||||
)()
|
||||
).resolves.toEqualRight(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
children: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
descriptor: "pm.environment.get returns actual null",
|
||||
expectResults: expect.arrayContaining([
|
||||
expect.objectContaining({ status: "pass" }),
|
||||
]),
|
||||
}),
|
||||
expect.objectContaining({
|
||||
descriptor: "typeof null should be 'object'",
|
||||
expectResults: expect.arrayContaining([
|
||||
expect.objectContaining({ status: "pass" }),
|
||||
]),
|
||||
}),
|
||||
expect.objectContaining({
|
||||
descriptor: "pw.env.get returns actual null (cross-namespace)",
|
||||
expectResults: expect.arrayContaining([
|
||||
expect.objectContaining({ status: "pass" }),
|
||||
]),
|
||||
}),
|
||||
expect.objectContaining({
|
||||
descriptor: "typeof via pw.env.get should be 'object'",
|
||||
expectResults: expect.arrayContaining([
|
||||
expect.objectContaining({ status: "pass" }),
|
||||
]),
|
||||
}),
|
||||
expect.objectContaining({
|
||||
descriptor:
|
||||
"hopp.env.get returns actual null (cross-namespace)",
|
||||
expectResults: expect.arrayContaining([
|
||||
expect.objectContaining({ status: "pass" }),
|
||||
]),
|
||||
}),
|
||||
expect.objectContaining({
|
||||
descriptor: "typeof via hopp.env.get should be 'object'",
|
||||
expectResults: expect.arrayContaining([
|
||||
expect.objectContaining({ status: "pass" }),
|
||||
]),
|
||||
}),
|
||||
]),
|
||||
}),
|
||||
])
|
||||
)
|
||||
})
|
||||
|
||||
test("pm.environment.set with undefined should work across pm, pw, and hopp namespaces", () => {
|
||||
return expect(
|
||||
runTest(
|
||||
`
|
||||
pm.environment.set('undefKey', undefined)
|
||||
|
||||
pm.test("pm.environment.get returns actual undefined", () => {
|
||||
pm.expect(pm.environment.get('undefKey')).to.equal(undefined)
|
||||
})
|
||||
|
||||
pm.test("typeof undefined should be 'undefined'", () => {
|
||||
pm.expect(typeof pm.environment.get('undefKey')).to.equal('undefined')
|
||||
})
|
||||
|
||||
pm.test("pw.env.get returns actual undefined (cross-namespace)", () => {
|
||||
pm.expect(pw.env.get('undefKey')).to.equal(undefined)
|
||||
})
|
||||
|
||||
pm.test("typeof via pw.env.get should be 'undefined'", () => {
|
||||
pm.expect(typeof pw.env.get('undefKey')).to.equal('undefined')
|
||||
})
|
||||
|
||||
pm.test("hopp.env.get returns actual undefined (cross-namespace)", () => {
|
||||
pm.expect(hopp.env.get('undefKey')).to.equal(undefined)
|
||||
})
|
||||
|
||||
pm.test("typeof via hopp.env.get should be 'undefined'", () => {
|
||||
pm.expect(typeof hopp.env.get('undefKey')).to.equal('undefined')
|
||||
})
|
||||
`,
|
||||
{ global: [], selected: [] }
|
||||
)()
|
||||
).resolves.toEqualRight(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
children: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
descriptor: "pm.environment.get returns actual undefined",
|
||||
expectResults: expect.arrayContaining([
|
||||
expect.objectContaining({ status: "pass" }),
|
||||
]),
|
||||
}),
|
||||
expect.objectContaining({
|
||||
descriptor: "typeof undefined should be 'undefined'",
|
||||
expectResults: expect.arrayContaining([
|
||||
expect.objectContaining({ status: "pass" }),
|
||||
]),
|
||||
}),
|
||||
expect.objectContaining({
|
||||
descriptor:
|
||||
"pw.env.get returns actual undefined (cross-namespace)",
|
||||
expectResults: expect.arrayContaining([
|
||||
expect.objectContaining({ status: "pass" }),
|
||||
]),
|
||||
}),
|
||||
expect.objectContaining({
|
||||
descriptor: "typeof via pw.env.get should be 'undefined'",
|
||||
expectResults: expect.arrayContaining([
|
||||
expect.objectContaining({ status: "pass" }),
|
||||
]),
|
||||
}),
|
||||
expect.objectContaining({
|
||||
descriptor:
|
||||
"hopp.env.get returns actual undefined (cross-namespace)",
|
||||
expectResults: expect.arrayContaining([
|
||||
expect.objectContaining({ status: "pass" }),
|
||||
]),
|
||||
}),
|
||||
expect.objectContaining({
|
||||
descriptor: "typeof via hopp.env.get should be 'undefined'",
|
||||
expectResults: expect.arrayContaining([
|
||||
expect.objectContaining({ status: "pass" }),
|
||||
]),
|
||||
}),
|
||||
]),
|
||||
}),
|
||||
])
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe("Assertion failure messages display actual values", () => {
|
||||
test("null assertion failures should show actual 'null' value in error messages", () => {
|
||||
return expect(
|
||||
runTest(
|
||||
`
|
||||
pm.environment.set('nullKey', null)
|
||||
|
||||
pm.test("pm.environment.get error message should not contain marker", () => {
|
||||
pm.expect(pm.environment.get('nullKey')).to.equal("this is not null")
|
||||
})
|
||||
|
||||
pm.test("pw.env.get error message should not contain marker", () => {
|
||||
pm.expect(pw.env.get('nullKey')).to.equal("this is not null")
|
||||
})
|
||||
|
||||
hopp.test("hopp.env.get error message should not contain marker", () => {
|
||||
hopp.expect(hopp.env.get('nullKey')).to.equal("this is not null")
|
||||
})
|
||||
`,
|
||||
{ global: [], selected: [] }
|
||||
)()
|
||||
).resolves.toEqualRight(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
children: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
descriptor:
|
||||
"pm.environment.get error message should not contain marker",
|
||||
expectResults: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
status: "fail",
|
||||
message: expect.not.stringContaining("__HOPPSCOTCH_NULL__"),
|
||||
}),
|
||||
]),
|
||||
}),
|
||||
expect.objectContaining({
|
||||
descriptor:
|
||||
"pw.env.get error message should not contain marker",
|
||||
expectResults: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
status: "fail",
|
||||
message: expect.not.stringContaining("__HOPPSCOTCH_NULL__"),
|
||||
}),
|
||||
]),
|
||||
}),
|
||||
expect.objectContaining({
|
||||
descriptor:
|
||||
"hopp.env.get error message should not contain marker",
|
||||
expectResults: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
status: "fail",
|
||||
message: expect.not.stringContaining("__HOPPSCOTCH_NULL__"),
|
||||
}),
|
||||
]),
|
||||
}),
|
||||
]),
|
||||
}),
|
||||
])
|
||||
)
|
||||
})
|
||||
|
||||
test("undefined assertion failures should show actual 'undefined' value in error messages", () => {
|
||||
return expect(
|
||||
runTest(
|
||||
`
|
||||
pm.environment.set('undefKey', undefined)
|
||||
|
||||
pm.test("pm.environment.get error message should not contain marker", () => {
|
||||
pm.expect(pm.environment.get('undefKey')).to.equal("this is not undefined")
|
||||
})
|
||||
|
||||
pm.test("pw.env.get error message should not contain marker", () => {
|
||||
pm.expect(pw.env.get('undefKey')).to.equal("this is not undefined")
|
||||
})
|
||||
|
||||
hopp.test("hopp.env.get error message should not contain marker", () => {
|
||||
hopp.expect(hopp.env.get('undefKey')).to.equal("this is not undefined")
|
||||
})
|
||||
`,
|
||||
{ global: [], selected: [] }
|
||||
)()
|
||||
).resolves.toEqualRight(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
children: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
descriptor:
|
||||
"pm.environment.get error message should not contain marker",
|
||||
expectResults: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
status: "fail",
|
||||
message: expect.not.stringContaining(
|
||||
"__HOPPSCOTCH_UNDEFINED__"
|
||||
),
|
||||
}),
|
||||
]),
|
||||
}),
|
||||
expect.objectContaining({
|
||||
descriptor:
|
||||
"pw.env.get error message should not contain marker",
|
||||
expectResults: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
status: "fail",
|
||||
message: expect.not.stringContaining(
|
||||
"__HOPPSCOTCH_UNDEFINED__"
|
||||
),
|
||||
}),
|
||||
]),
|
||||
}),
|
||||
expect.objectContaining({
|
||||
descriptor:
|
||||
"hopp.env.get error message should not contain marker",
|
||||
expectResults: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
status: "fail",
|
||||
message: expect.not.stringContaining(
|
||||
"__HOPPSCOTCH_UNDEFINED__"
|
||||
),
|
||||
}),
|
||||
]),
|
||||
}),
|
||||
]),
|
||||
}),
|
||||
])
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe("pm.globals namespace null and undefined handling", () => {
|
||||
test("pm.globals.set with null should work correctly", () => {
|
||||
return expect(
|
||||
runTest(
|
||||
`
|
||||
pm.globals.set('globalNull', null)
|
||||
|
||||
pm.test("pm.globals.get returns actual null", () => {
|
||||
pm.expect(pm.globals.get('globalNull')).to.equal(null)
|
||||
})
|
||||
|
||||
pm.test("typeof null should be 'object'", () => {
|
||||
pm.expect(typeof pm.globals.get('globalNull')).to.equal('object')
|
||||
})
|
||||
`,
|
||||
{ global: [], selected: [] }
|
||||
)()
|
||||
).resolves.toEqualRight(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
children: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
descriptor: "pm.globals.get returns actual null",
|
||||
expectResults: expect.arrayContaining([
|
||||
expect.objectContaining({ status: "pass" }),
|
||||
]),
|
||||
}),
|
||||
expect.objectContaining({
|
||||
descriptor: "typeof null should be 'object'",
|
||||
expectResults: expect.arrayContaining([
|
||||
expect.objectContaining({ status: "pass" }),
|
||||
]),
|
||||
}),
|
||||
]),
|
||||
}),
|
||||
])
|
||||
)
|
||||
})
|
||||
|
||||
test("pm.globals.set with undefined should work correctly", () => {
|
||||
return expect(
|
||||
runTest(
|
||||
`
|
||||
pm.globals.set('globalUndef', undefined)
|
||||
|
||||
pm.test("pm.globals.get returns actual undefined", () => {
|
||||
pm.expect(pm.globals.get('globalUndef')).to.equal(undefined)
|
||||
})
|
||||
|
||||
pm.test("typeof undefined should be 'undefined'", () => {
|
||||
pm.expect(typeof pm.globals.get('globalUndef')).to.equal('undefined')
|
||||
})
|
||||
`,
|
||||
{ global: [], selected: [] }
|
||||
)()
|
||||
).resolves.toEqualRight(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
children: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
descriptor: "pm.globals.get returns actual undefined",
|
||||
expectResults: expect.arrayContaining([
|
||||
expect.objectContaining({ status: "pass" }),
|
||||
]),
|
||||
}),
|
||||
expect.objectContaining({
|
||||
descriptor: "typeof undefined should be 'undefined'",
|
||||
expectResults: expect.arrayContaining([
|
||||
expect.objectContaining({ status: "pass" }),
|
||||
]),
|
||||
}),
|
||||
]),
|
||||
}),
|
||||
])
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
@ -2992,6 +2992,37 @@
|
|||
get auth() {
|
||||
return globalThis.hopp.request.auth
|
||||
},
|
||||
|
||||
// Custom serialization for console.log to match pre-request behavior
|
||||
// This method is called by faraday-cage's marshalling system
|
||||
toJSON() {
|
||||
// Return a plain object with all properties expanded
|
||||
// This ensures console.log(pm.request) shows the full structure
|
||||
const urlParsed = this.url._parseUrl()
|
||||
return {
|
||||
id: this.id,
|
||||
name: this.name,
|
||||
url: {
|
||||
protocol: urlParsed.protocol,
|
||||
host: urlParsed.host,
|
||||
hostname: urlParsed.host.join("."),
|
||||
port: urlParsed.port,
|
||||
path: urlParsed.path,
|
||||
hash: urlParsed.hash || "",
|
||||
query: this.url.query.all(),
|
||||
},
|
||||
method: this.method,
|
||||
headers: this.headers.toObject(),
|
||||
body: this.body,
|
||||
auth: this.auth,
|
||||
}
|
||||
},
|
||||
|
||||
toString() {
|
||||
return `Request { id: ${this.id}, name: ${this.name}, method: ${this.method}, url: ${this.url.toString()} }`
|
||||
},
|
||||
|
||||
[Symbol.toStringTag]: "Request",
|
||||
},
|
||||
|
||||
response: {
|
||||
|
|
|
|||
|
|
@ -1163,6 +1163,37 @@
|
|||
throw new Error("Auth must be an object or null")
|
||||
}
|
||||
},
|
||||
|
||||
// Custom serialization for console.log to ensure consistent behavior
|
||||
// This method is called by faraday-cage's marshalling system
|
||||
toJSON() {
|
||||
// Return a plain object with all properties expanded
|
||||
// This ensures console.log(pm.request) shows the full structure consistently
|
||||
const urlParsed = this.url._parseUrl()
|
||||
return {
|
||||
id: this.id,
|
||||
name: this.name,
|
||||
url: {
|
||||
protocol: urlParsed.protocol,
|
||||
host: urlParsed.host,
|
||||
hostname: urlParsed.host.join("."),
|
||||
port: urlParsed.port,
|
||||
path: urlParsed.path,
|
||||
hash: urlParsed.hash || "",
|
||||
query: this.url.query.all(),
|
||||
},
|
||||
method: this.method,
|
||||
headers: this.headers.toObject(),
|
||||
body: this.body,
|
||||
auth: this.auth,
|
||||
}
|
||||
},
|
||||
|
||||
toString() {
|
||||
return `Request { id: ${this.id}, name: ${this.name}, method: ${this.method}, url: ${this.url.toString()} }`
|
||||
},
|
||||
|
||||
[Symbol.toStringTag]: "Request",
|
||||
},
|
||||
|
||||
// Script context information
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ import {
|
|||
SandboxEnvironmentVariable,
|
||||
SandboxEnvs,
|
||||
} from "../types"
|
||||
import { UNDEFINED_MARKER, NULL_MARKER } from "~/constants/sandbox-markers"
|
||||
|
||||
export type EnvSource = "active" | "global" | "all"
|
||||
export type EnvAPIOptions = {
|
||||
|
|
@ -204,11 +205,10 @@ export function getSharedEnvMethods(
|
|||
* 3. Exit: getUpdatedEnvs() serializes back to strings via JSON.stringify()
|
||||
* { global: [{ key: "users", currentValue: "[{...}]", initialValue: "[]" }], ... }
|
||||
*
|
||||
* The cast acknowledges that during execution (steps 1-3), the runtime type is SandboxEnvs,
|
||||
* even though the declared type is TestResult["envs"] for API boundary compatibility.
|
||||
* The `satisfies` check acknowledges that during execution (steps 1-3), the runtime type is
|
||||
* SandboxEnvs, even though the declared type is TestResult["envs"] for API boundary compatibility.
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
|
||||
let updatedEnvs = envs as unknown as SandboxEnvs
|
||||
let updatedEnvs = envs satisfies SandboxEnvs
|
||||
|
||||
const envGetFn = (
|
||||
key: unknown,
|
||||
|
|
@ -232,6 +232,15 @@ export function getSharedEnvMethods(
|
|||
? env.currentValue
|
||||
: env.initialValue
|
||||
|
||||
// Convert markers back to their actual types for script execution
|
||||
// This ensures null/undefined values are properly represented in scripts
|
||||
if (valueToUse === UNDEFINED_MARKER) {
|
||||
return undefined
|
||||
}
|
||||
if (valueToUse === NULL_MARKER) {
|
||||
return null
|
||||
}
|
||||
|
||||
// Preserve complex types (arrays, objects) for PM namespace compatibility
|
||||
return valueToUse
|
||||
}
|
||||
|
|
@ -271,6 +280,14 @@ export function getSharedEnvMethods(
|
|||
? e.currentValue
|
||||
: e.initialValue
|
||||
|
||||
// Convert markers back to their actual types
|
||||
if (valueToUse === UNDEFINED_MARKER) {
|
||||
return undefined
|
||||
}
|
||||
if (valueToUse === NULL_MARKER) {
|
||||
return null
|
||||
}
|
||||
|
||||
// Only resolve templates for string values
|
||||
// Non-string values (arrays, objects, etc.) are returned as-is for PM namespace compatibility
|
||||
if (typeof valueToUse !== "string") {
|
||||
|
|
@ -399,7 +416,19 @@ export function getSharedEnvMethods(
|
|||
getEnv(key, updatedEnvs, options),
|
||||
O.fold(
|
||||
() => undefined,
|
||||
(env) => env.initialValue // Return as-is (PM namespace preserves types)
|
||||
(env) => {
|
||||
const initialValue = env.initialValue
|
||||
|
||||
// Convert markers back to their actual types
|
||||
if (initialValue === UNDEFINED_MARKER) {
|
||||
return undefined
|
||||
}
|
||||
if (initialValue === NULL_MARKER) {
|
||||
return null
|
||||
}
|
||||
|
||||
return initialValue // Return as-is (PM namespace preserves types)
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue