feat: recursive environment variable resolution
This commit is contained in:
@@ -1,25 +1,87 @@
|
|||||||
|
import * as E from "fp-ts/Either"
|
||||||
|
import { pipe } from "fp-ts/function"
|
||||||
import { Environment } from "~/newstore/environments"
|
import { Environment } from "~/newstore/environments"
|
||||||
|
|
||||||
export function parseBodyEnvVariables(
|
const REGEX_ENV_VAR = /<<([^>]*)>>/g // "<<myVariable>>"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* How much times can we expand environment variables
|
||||||
|
*/
|
||||||
|
const ENV_MAX_EXPAND_LIMIT = 10
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Error state when there is a suspected loop while
|
||||||
|
* recursively expanding variables
|
||||||
|
*/
|
||||||
|
const ENV_EXPAND_LOOP = "ENV_EXPAND_LOOP" as const
|
||||||
|
|
||||||
|
export function parseBodyEnvVariablesE(
|
||||||
body: string,
|
body: string,
|
||||||
env: Environment["variables"]
|
env: Environment["variables"]
|
||||||
) {
|
) {
|
||||||
return body.replace(/<<\w+>>/g, (key) => {
|
let result = body
|
||||||
const found = env.find((envVar) => envVar.key === key.replace(/[<>]/g, ""))
|
let depth = 0
|
||||||
return found ? found.value : key
|
|
||||||
})
|
while (result.match(REGEX_ENV_VAR) != null && depth <= ENV_MAX_EXPAND_LIMIT) {
|
||||||
|
result = result.replace(/<<\w+>>/g, (key) => {
|
||||||
|
const found = env.find(
|
||||||
|
(envVar) => envVar.key === key.replace(/[<>]/g, "")
|
||||||
|
)
|
||||||
|
return found ? found.value : key
|
||||||
|
})
|
||||||
|
|
||||||
|
depth++
|
||||||
|
}
|
||||||
|
|
||||||
|
return depth > ENV_MAX_EXPAND_LIMIT
|
||||||
|
? E.left(ENV_EXPAND_LOOP)
|
||||||
|
: E.right(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function parseTemplateString(
|
/**
|
||||||
|
* @deprecated Use `parseBodyEnvVariablesE` instead.
|
||||||
|
*/
|
||||||
|
export const parseBodyEnvVariables = (
|
||||||
|
body: string,
|
||||||
|
env: Environment["variables"]
|
||||||
|
) =>
|
||||||
|
pipe(
|
||||||
|
parseBodyEnvVariablesE(body, env),
|
||||||
|
E.getOrElse(() => body)
|
||||||
|
)
|
||||||
|
|
||||||
|
export function parseTemplateStringE(
|
||||||
str: string,
|
str: string,
|
||||||
variables: Environment["variables"]
|
variables: Environment["variables"]
|
||||||
) {
|
) {
|
||||||
if (!variables || !str) {
|
if (!variables || !str) {
|
||||||
return str
|
return E.right(str)
|
||||||
}
|
}
|
||||||
const searchTerm = /<<([^>]*)>>/g // "<<myVariable>>"
|
|
||||||
return decodeURI(encodeURI(str)).replace(
|
let result = str
|
||||||
searchTerm,
|
let depth = 0
|
||||||
(_, p1) => variables.find((x) => x.key === p1)?.value || ""
|
|
||||||
)
|
while (result.match(REGEX_ENV_VAR) != null && depth <= ENV_MAX_EXPAND_LIMIT) {
|
||||||
|
result = decodeURI(encodeURI(result)).replace(
|
||||||
|
REGEX_ENV_VAR,
|
||||||
|
(_, p1) => variables.find((x) => x.key === p1)?.value || ""
|
||||||
|
)
|
||||||
|
depth++
|
||||||
|
}
|
||||||
|
|
||||||
|
return depth > ENV_MAX_EXPAND_LIMIT
|
||||||
|
? E.left(ENV_EXPAND_LOOP)
|
||||||
|
: E.right(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated Use `parseTemplateStringE` instead
|
||||||
|
*/
|
||||||
|
export const parseTemplateString = (
|
||||||
|
str: string,
|
||||||
|
variables: Environment["variables"]
|
||||||
|
) =>
|
||||||
|
pipe(
|
||||||
|
parseTemplateStringE(str, variables),
|
||||||
|
E.getOrElse(() => str)
|
||||||
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user