Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 | 4x 4x 461x 461x 461x 71x 119x 16x 103x 2x 101x 101x 224x 224x 218x 101x 101x 105x 105x 105x 237x 177x 105x 218x 218x 55x 163x 163x 105x 101x 62x 61x 56x 54x 5x 49x 49x 49x 23x 49x 119x 49x 49x | import type { VariableSchema, VariableValue } from "@featurevisor/types";
import { mutate } from "./mutator";
const MUTATION_OP_SUFFIX = /:((?:append|prepend|after|before|remove))$/;
/**
* Get the root variable name from an override key (e.g. "tags:append" -> "tags", "payload.rows:append" -> "payload").
*/
function rootVariableFromOverrideKey(overrideKey: string): string {
const withoutSuffix = overrideKey.replace(MUTATION_OP_SUFFIX, "").trim();
const firstSegment = withoutSuffix.includes(".") ? withoutSuffix.split(".")[0] : withoutSuffix;
return firstSegment.replace(/\s*\[.*\]\s*$/, "").trim();
}
/**
* Resolve variable values from schema defaults and overrides.
* Override keys may be variable keys or dot-notation paths (e.g. "foo", "foo.a.b", "tags:append", "items[id=2]:after").
* Uses the mutator so nested paths and mutation notations are supported.
* Returns only variables that were desired to be overridden (i.e. appear in overrides).
*/
export function resolveMutationsForMultipleVariables(
variablesSchema: Record<string, VariableSchema> | undefined,
overrides: Record<string, VariableValue> | undefined,
): Record<string, VariableValue> | undefined {
if (!overrides || Object.keys(overrides).length === 0) {
return undefined;
}
if (!variablesSchema || Object.keys(variablesSchema).length === 0) {
return undefined;
}
const variableKeysToOutput = new Set<string>();
for (const overrideKey of Object.keys(overrides)) {
const variableKey = rootVariableFromOverrideKey(overrideKey);
if (variableKey && variablesSchema[variableKey]) {
variableKeysToOutput.add(variableKey);
}
}
const result: Record<string, VariableValue> = {};
for (const variableKey of variableKeysToOutput) {
const schema = variablesSchema[variableKey];
let value: VariableValue =
schema.defaultValue !== undefined && schema.defaultValue !== null
? (JSON.parse(JSON.stringify(schema.defaultValue)) as VariableValue)
: undefined;
const keysForThisVariable = Object.keys(overrides)
.filter(
(k) =>
rootVariableFromOverrideKey(k) === variableKey &&
(k === variableKey ||
k.startsWith(variableKey + ".") ||
k.startsWith(variableKey + "[") ||
k.startsWith(variableKey + ":")),
)
.sort((a, b) => a.length - b.length);
for (const overrideKey of keysForThisVariable) {
const overrideValue = overrides[overrideKey];
if (overrideKey === variableKey) {
value =
overrideValue !== undefined && overrideValue !== null
? (JSON.parse(JSON.stringify(overrideValue)) as VariableValue)
: overrideValue;
} else {
const notation = overrideKey.startsWith(variableKey + "[")
? overrideKey.slice(variableKey.length)
: overrideKey.startsWith(variableKey + ":")
? overrideKey.slice(variableKey.length)
: overrideKey.slice(variableKey.length + 1);
value = mutate(schema, value, notation, overrideValue);
}
}
result[variableKey] = value;
}
return Object.keys(result).length > 0 ? result : undefined;
}
/**
* Resolve a single variable's override value (e.g. from variableOverrides).
* If the value is a plain object with path-like keys, it is merged with the variable's default;
* otherwise the value is returned as-is (full replacement).
*/
export function resolveMutationsForSingleVariable(
variablesSchema: Record<string, VariableSchema> | undefined,
variableKey: string,
overrideValue: VariableValue,
baseValue?: VariableValue,
): VariableValue {
if (!variablesSchema || !variablesSchema[variableKey]) return overrideValue;
if (overrideValue === null || overrideValue === undefined) return overrideValue;
if (typeof overrideValue !== "object" || Array.isArray(overrideValue)) {
return overrideValue;
}
const pathMap = overrideValue as Record<string, VariableValue>;
const flat: Record<string, VariableValue> = {};
if (typeof baseValue !== "undefined") {
flat[variableKey] = JSON.parse(JSON.stringify(baseValue)) as VariableValue;
}
for (const [k, v] of Object.entries(pathMap)) {
flat[k === variableKey ? variableKey : variableKey + "." + k] = v;
}
const resolved = resolveMutationsForMultipleVariables(variablesSchema, flat);
return resolved && variableKey in resolved ? resolved[variableKey] : overrideValue;
}
|