65 lines
1.9 KiB
TypeScript
65 lines
1.9 KiB
TypeScript
import { homedir } from "node:os";
|
|
import { join } from "node:path";
|
|
import { z } from "zod";
|
|
|
|
const optionalNonEmptyString = z.string().trim().min(1).optional();
|
|
|
|
const booleanOneZero = z
|
|
.enum(["0", "1"])
|
|
.optional()
|
|
.transform((value) => value === "1");
|
|
|
|
export const sfEnvSchema = z.object({
|
|
SF_HOME: optionalNonEmptyString,
|
|
SF_AGENT_DIR: optionalNonEmptyString,
|
|
SF_CODING_AGENT_DIR: optionalNonEmptyString,
|
|
SF_STATE_DIR: optionalNonEmptyString,
|
|
SF_PROJECT_ID: z
|
|
.string()
|
|
.trim()
|
|
.regex(/^[A-Za-z0-9_-]+$/, {
|
|
message:
|
|
"SF_PROJECT_ID must contain only letters, numbers, hyphens, and underscores",
|
|
})
|
|
.optional(),
|
|
SF_BIN_PATH: optionalNonEmptyString,
|
|
SF_VERSION: optionalNonEmptyString,
|
|
SF_WEB_PROJECT_CWD: optionalNonEmptyString,
|
|
SF_WEB_DAEMON_MODE: booleanOneZero,
|
|
});
|
|
|
|
export type SfEnv = z.infer<typeof sfEnvSchema>;
|
|
|
|
/**
|
|
* Parse supported SF_* environment variables into a typed object.
|
|
*
|
|
* Purpose: give runtime code a shared contract for SF-specific environment
|
|
* variables instead of scattering ad hoc `process.env` parsing across entry
|
|
* points.
|
|
*
|
|
* Consumer: root CLI/headless modules and web bridge code that need stable SF
|
|
* path and mode values.
|
|
*/
|
|
export function parseSfEnv(env: NodeJS.ProcessEnv = process.env): SfEnv {
|
|
return sfEnvSchema.parse(env);
|
|
}
|
|
|
|
/**
|
|
* Return typed SF environment values with path defaults applied.
|
|
*
|
|
* Purpose: centralize default path behavior for SF_HOME and the managed agent
|
|
* directory while still validating user-provided overrides.
|
|
*
|
|
* Consumer: app-paths.ts, cli-logs.ts, headless-query.ts, and future env readers.
|
|
*/
|
|
export function getSfEnv(env: NodeJS.ProcessEnv = process.env) {
|
|
const parsed = parseSfEnv(env);
|
|
const sfHome = parsed.SF_HOME ?? join(homedir(), ".sf");
|
|
const agentDir =
|
|
parsed.SF_AGENT_DIR ?? parsed.SF_CODING_AGENT_DIR ?? join(sfHome, "agent");
|
|
return {
|
|
...parsed,
|
|
sfHome,
|
|
agentDir,
|
|
};
|
|
}
|