mirror of
https://github.com/morluto/rea.git
synced 2026-11-11 01:13:39 +00:00
70 lines
2.7 KiB
TypeScript
70 lines
2.7 KiB
TypeScript
import { AnalysisError } from "../../domain/analysisErrorBase.js";
|
|
import {
|
|
AnalysisCancelledError,
|
|
AnalysisCapabilityUnavailableError,
|
|
AnalysisInputError,
|
|
} from "../../domain/analysisErrorCore.js";
|
|
import type { ProcessScenario } from "../../domain/process/processScenario.js";
|
|
import { admitFilesystemObservationRoots } from "../../process/capture/FilesystemSnapshot.js";
|
|
import { processCaptureOwnershipUnavailableReason } from "../../process/capture/ProcessCaptureCapability.js";
|
|
import { createProcessSensitiveOutput } from "../../process/capture/ProcessSensitiveOutput.js";
|
|
import { resolveProcessScenarioRuntimePaths } from "../../process/capture/ProcessScenarioRuntimeValidation.js";
|
|
import { err, ok, type Result } from "../../domain/result.js";
|
|
|
|
/** A scenario whose executable and observation paths are resolved for execution. */
|
|
export type ResolvedProcessScenario = Omit<ProcessScenario, "dry_run">;
|
|
|
|
/**
|
|
* Resolve a scenario for a dry run. This applies the same executable, working
|
|
* directory, path and platform admission checks as a capture, then stops
|
|
* before any process is launched.
|
|
*/
|
|
export const prepareProcessScenarioPlan = async (
|
|
scenario: ProcessScenario,
|
|
environment: Readonly<Record<string, string | undefined>> = process.env,
|
|
platform: NodeJS.Platform = process.platform,
|
|
signal?: AbortSignal,
|
|
): Promise<Result<ResolvedProcessScenario, AnalysisError>> => {
|
|
if (signal?.aborted === true)
|
|
return err(
|
|
new AnalysisCancelledError("capture_process_scenario", {
|
|
cause: signal.reason,
|
|
}),
|
|
);
|
|
const ownershipReason = processCaptureOwnershipUnavailableReason(platform);
|
|
if (ownershipReason !== undefined)
|
|
return err(
|
|
new AnalysisCapabilityUnavailableError(
|
|
"rea-process",
|
|
"capture_process_scenario",
|
|
ownershipReason,
|
|
{ userMessage: ownershipReason },
|
|
),
|
|
);
|
|
const cancelled = () =>
|
|
err(
|
|
new AnalysisCancelledError("capture_process_scenario", {
|
|
cause: signal?.reason,
|
|
}),
|
|
);
|
|
const aborted = () => signal?.aborted === true;
|
|
try {
|
|
const { dry_run: _dryRun, ...resolved } =
|
|
await resolveProcessScenarioRuntimePaths(scenario, environment, platform);
|
|
if (aborted()) return cancelled();
|
|
const privacy = createProcessSensitiveOutput(scenario);
|
|
if (!privacy.ok) return err(privacy.error);
|
|
const admitted = await admitFilesystemObservationRoots(resolved, signal);
|
|
if (!admitted.ok) return aborted() ? cancelled() : admitted;
|
|
if (aborted()) return cancelled();
|
|
return ok(resolved);
|
|
} catch (cause: unknown) {
|
|
if (aborted()) return cancelled();
|
|
return err(
|
|
cause instanceof AnalysisError
|
|
? cause
|
|
: new AnalysisInputError("capture_process_scenario", { cause }, []),
|
|
);
|
|
}
|
|
};
|