import { existsSync } from "node:fs"; import { join } from "node:path"; import { pathToFileURL } from "node:url"; import { resolveTypeStrippingFlag } from "./ts-subprocess-flags.ts"; export interface SfCliEntry { command: string; args: string[]; cwd: string; } /** @deprecated Use SfCliEntry instead */ export interface ResolveSfCliEntryOptions { packageRoot: string; cwd: string; execPath?: string; hostKind?: string; mode?: "interactive" | "rpc"; sessionDir?: string; messages?: string[]; existsSync?: (path: string) => boolean; } /** @deprecated Use ResolveSfCliEntryOptions instead */ function buildExtraArgs(options: ResolveSfCliEntryOptions): string[] { if (options.mode !== "rpc") return []; if (!options.sessionDir) { throw new Error("RPC CLI entry requires sessionDir"); } return ["--mode", "rpc", "--continue", "--session-dir", options.sessionDir]; } export function resolveSfCliEntry( options: ResolveSfCliEntryOptions, ): SfCliEntry { const checkExists = options.existsSync ?? existsSync; const execPath = options.execPath ?? process.execPath; const extraArgs = buildExtraArgs(options); const messageArgs = options.mode === "interactive" ? (options.messages ?? []) : []; const sourceEntry = join(options.packageRoot, "src", "loader.ts"); const resolveTsLoader = join( options.packageRoot, "src", "resources", "extensions", "sf", "tests", "resolve-ts.mjs", ); const builtEntry = join(options.packageRoot, "dist", "loader.js"); const sourceCliEntry = checkExists(sourceEntry) && checkExists(resolveTsLoader) ? ({ command: execPath, args: [ "--import", pathToFileURL(resolveTsLoader).href, resolveTypeStrippingFlag(options.packageRoot), sourceEntry, ...extraArgs, ...messageArgs, ], cwd: options.cwd, } satisfies SfCliEntry) : null; const builtCliEntry = checkExists(builtEntry) ? ({ command: execPath, args: [builtEntry, ...extraArgs, ...messageArgs], cwd: options.cwd, } satisfies SfCliEntry) : null; if (options.hostKind === "packaged-standalone") { if (builtCliEntry) return builtCliEntry; if (sourceCliEntry) return sourceCliEntry; } else { if (sourceCliEntry) return sourceCliEntry; if (builtCliEntry) return builtCliEntry; } throw new Error( `SF CLI entry not found; checked=${sourceEntry},${builtEntry}`, ); }