spawn/packages/cli/src/shared/spawn-config.ts
A f5def4119f
refactor: remove dead exported types from picker.ts and spawn-config.ts (#2553)
PickOption, PickConfig, and PickResult interfaces in picker.ts were exported
but never imported by any external module. SpawnConfig type in spawn-config.ts
was similarly exported but not used outside the module. Made all four private
to reduce the public API surface.

Bump CLI patch version to 0.17.2.

-- qa/code-quality

Co-authored-by: spawn-qa-bot <qa@openrouter.ai>
Co-authored-by: L <6723574+louisgv@users.noreply.github.com>
2026-03-12 21:43:05 -04:00

56 lines
1.6 KiB
TypeScript

// shared/spawn-config.ts — Load and validate --config JSON files
import { readFileSync, statSync } from "node:fs";
import { resolve } from "node:path";
import * as v from "valibot";
import { parseJsonWith } from "./parse.js";
import { logWarn } from "./ui.js";
const SpawnConfigSetupSchema = v.object({
telegram_bot_token: v.optional(v.string()),
github_token: v.optional(v.string()),
});
const SpawnConfigSchema = v.object({
model: v.optional(v.string()),
steps: v.optional(v.array(v.string())),
name: v.optional(v.string()),
setup: v.optional(SpawnConfigSetupSchema),
});
type SpawnConfig = v.InferOutput<typeof SpawnConfigSchema>;
/** Maximum config file size (1 MB) */
const MAX_CONFIG_SIZE = 1024 * 1024;
/**
* Load and validate a spawn config file.
* Returns null on parse failure (with warning to stderr).
* Throws on missing file or security violations.
*/
export function loadSpawnConfig(filePath: string): SpawnConfig | null {
// Security: reject null bytes before any filesystem operations
if (filePath.includes("\0")) {
throw new Error("Config file path contains null bytes");
}
const resolved = resolve(filePath);
const stats = statSync(resolved);
if (!stats.isFile()) {
throw new Error(`Config path is not a file: ${resolved}`);
}
if (stats.size > MAX_CONFIG_SIZE) {
throw new Error(`Config file too large (${stats.size} bytes, max ${MAX_CONFIG_SIZE})`);
}
const content = readFileSync(resolved, "utf-8");
const parsed = parseJsonWith(content, SpawnConfigSchema);
if (!parsed) {
logWarn(`Invalid config file: ${resolved} — ignoring`);
return null;
}
return parsed;
}