use std::collections::HashMap;
use std::path::PathBuf;
use crate::chain::FailurePolicy;
use crate::config::LoadedConfig;
use crate::tool::node::OnFail;
use crate::types::{DetectionWarning, Ecosystem, PackageManager, ProjectContext, TaskRunner};
pub(crate) struct Resolver<'ctx> {
pub(super) ctx: &'ctx ProjectContext,
pub(super) overrides: &'ctx ResolutionOverrides,
}
#[derive(Debug, Clone, Default)]
pub(crate) struct ResolutionOverrides {
pub pm: Option<PmOverride>,
pub pm_by_ecosystem: HashMap<Ecosystem, PmOverride>,
pub runner: Option<RunnerOverride>,
pub prefer_runners: Vec<TaskRunner>,
pub fallback: FallbackPolicy,
pub on_mismatch: MismatchPolicy,
pub no_warnings: bool,
pub explain: bool,
pub failure_policy: FailurePolicy,
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
pub(crate) enum FallbackPolicy {
#[default]
Probe,
Npm,
Error,
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
pub(crate) enum MismatchPolicy {
#[default]
Warn,
Ignore,
Error,
}
#[derive(Debug, Clone)]
pub(crate) struct PmOverride {
pub pm: PackageManager,
pub origin: OverrideOrigin,
}
#[derive(Debug, Clone)]
pub(crate) struct RunnerOverride {
pub runner: TaskRunner,
#[allow(
dead_code,
reason = "consumed by --explain in Phase 6; kept on the type for future trace renderers"
)]
pub origin: OverrideOrigin,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub(crate) enum OverrideOrigin {
CliFlag,
EnvVar,
ConfigFile {
path: PathBuf,
},
}
#[derive(Debug, Clone)]
pub(crate) struct ResolvedPm {
pub pm: PackageManager,
pub via: ResolutionStep,
pub warnings: Vec<DetectionWarning>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub(crate) enum ResolutionStep {
Override(OverrideOrigin),
ManifestPackageManager,
ManifestDevEngines {
on_fail: OnFail,
},
Lockfile,
PathProbe {
binary: PathBuf,
},
LegacyNpmFallback,
}
#[derive(Debug, Default)]
pub(crate) struct OverrideSources<'a> {
pub pm: SourceValue<'a>,
pub runner: SourceValue<'a>,
pub fallback: SourceValue<'a>,
pub on_mismatch: SourceValue<'a>,
pub no_warnings: ExplainSource<'a>,
pub explain: ExplainSource<'a>,
pub keep_going: ExplainSource<'a>,
pub kill_on_fail: ExplainSource<'a>,
pub config: Option<&'a LoadedConfig>,
}
#[derive(Debug, Default, Clone, Copy)]
pub(crate) struct SourceValue<'a> {
pub cli: Option<&'a str>,
pub env: Option<&'a str>,
}
#[derive(Debug, Default, Clone, Copy)]
pub(crate) struct DiagnosticFlags {
pub no_warnings: bool,
pub explain: bool,
}
#[derive(Debug, Default, Clone, Copy)]
pub(crate) struct ExplainSource<'a> {
pub cli: bool,
pub env: Option<&'a str>,
}
impl ResolvedPm {
pub(crate) fn describe(&self) -> String {
match &self.via {
ResolutionStep::Override(OverrideOrigin::CliFlag) => {
format!("{} via --pm (CLI override)", self.pm.label())
}
ResolutionStep::Override(OverrideOrigin::EnvVar) => {
format!("{} via RUNNER_PM (environment)", self.pm.label())
}
ResolutionStep::Override(OverrideOrigin::ConfigFile { path }) => {
format!("{} via runner.toml at {}", self.pm.label(), path.display())
}
ResolutionStep::ManifestPackageManager => {
format!("{} via package.json \"packageManager\"", self.pm.label())
}
ResolutionStep::ManifestDevEngines { on_fail } => format!(
"{} via package.json \"devEngines.packageManager\" (onFail={on_fail:?})",
self.pm.label(),
),
ResolutionStep::Lockfile => {
format!("{} via detected lockfile", self.pm.label())
}
ResolutionStep::PathProbe { binary } => {
format!("{} via PATH probe at {}", self.pm.label(), binary.display())
}
ResolutionStep::LegacyNpmFallback => {
format!("{} via --fallback=npm (legacy)", self.pm.label())
}
}
}
}