Files
triggershell/src/cli/lib/variables.ts
T

69 lines
2.4 KiB
TypeScript
Raw Normal View History

import type { VariableConfig } from "../../lib/config/schema";
/** Splits each `name=value` pair and groups by name - repeats accumulate into an array, which is
* how a `multiselect` variable is given more than one selection on the command line. */
export function parseVarFlags(pairs: string[]): Record<string, string[]> {
const grouped: Record<string, string[]> = {};
for (const pair of pairs) {
const eq = pair.indexOf("=");
if (eq === -1) {
throw new Error(`--var ${pair} is missing '=' - expected --var name=value`);
}
const name = pair.slice(0, eq);
const value = pair.slice(eq + 1);
(grouped[name] ??= []).push(value);
}
return grouped;
}
/** Coerces raw `--var` strings into the JS type each variable expects, ready for
* `buildVariableSchema(script).safeParse(...)` - the same schema the web form and the
* `/api/scripts/:id/runs` route already validate against. Variables not present in `grouped`
* are left out entirely (the caller fills those from `defaultValuesForScript` first). */
export function coerceVariables(
variables: readonly VariableConfig[],
grouped: Record<string, string[]>,
): Record<string, unknown> {
const values: Record<string, unknown> = {};
const known = new Set(variables.map((v) => v.name));
for (const name of Object.keys(grouped)) {
if (!known.has(name)) {
throw new Error(`--var ${name}=... does not match any variable on this script`);
}
}
for (const variable of variables) {
const raw = grouped[variable.name];
if (!raw) continue;
if (variable.type === "multiselect") {
values[variable.name] = raw;
continue;
}
if (raw.length > 1) {
throw new Error(
`--var ${variable.name}=... was given ${raw.length} times, but '${variable.name}' is not a multiselect variable`,
);
}
const value = raw[0];
if (variable.type === "boolean") {
if (value === "true") values[variable.name] = true;
else if (value === "false") values[variable.name] = false;
else throw new Error(`--var ${variable.name}=${value} must be 'true' or 'false'`);
} else if (variable.type === "number") {
const n = Number(value);
if (Number.isNaN(n)) {
throw new Error(`--var ${variable.name}=${value} is not a valid number`);
}
values[variable.name] = n;
} else {
values[variable.name] = value;
}
}
return values;
}