import type { Workspace } from '../../pm/index.ts';
import type { CheckPackageParams, CheckSourceParams } from './checkPackage/index.ts';
import type { FileContext } from './implicitDevDependencies.ts';
import type { PeerBoundType } from './packageJsonEditor.ts';
export type DeplintSeverity = 'error' | 'warning';
export type DeplintCategory = 'dependencies' | 'devDependencies' | 'peerDependencies' | 'workspace';
export type DeplintFixKind = 'manifest';
export type DeplintPackageKind = 'library' | 'library/cli' | 'terminal[cli]' | 'terminal[private]';
export type DeplintSection = 'dependencies' | 'devDependencies' | 'peerDependencies';
export interface DeplintCheckFlags {
    checkDependencies: boolean;
    checkDevDependencies: boolean;
    checkPeerDependencies: boolean;
    checkWorkspace: boolean;
}
export type DeplintFix = {
    action: 'add';
    dependency: string;
    detail: string;
    /**
     * Only meaningful when `section === 'peerDependencies'`.
     * `true` writes `peerDependenciesMeta[dependency].optional = true`.
     * `false` clears any existing optional flag.
     * `undefined` leaves `peerDependenciesMeta` untouched.
     */
    optional?: boolean;
    section: DeplintSection;
    version: string;
} | {
    action: 'move';
    dependency: string;
    detail: string;
    fromSection: DeplintSection;
    /** Same semantics as `add.optional`; only meaningful when `toSection === 'peerDependencies'`. */
    optional?: boolean;
    toSection: DeplintSection;
    version?: string;
} | {
    action: 'remove';
    dependency: string;
    detail: string;
    section: DeplintSection;
} | {
    action: 'set-version';
    dependency: string;
    detail: string;
    section: DeplintSection;
    version: string;
} | {
    /**
     * Pending intent: "the installed peer doesn't satisfy the range that the
     * requiring dep's current registry version declares — bump this dep to
     * whichever published version accepts the installed peer." Resolved into
     * a concrete `set-version` fix by `resolvePeerBumpFixes` before the
     * fix applier runs.
     */
    action: 'resolve-peer-bump';
    currentRange: string;
    /** The requiring dep whose range in our package.json should be bumped. */
    dependency: string;
    detail: string;
    /** Version of the peer currently installed (what we need to accept). */
    installedPeerVersion: string;
    /** The peer that isn't satisfied (for logging only). */
    peer: string;
    section: DeplintSection;
};
export interface DeplintDiagnostic {
    data?: unknown;
    dependency?: string;
    evidence?: string[];
    file: string;
    fixable: boolean;
    fixes?: DeplintFix[];
    id: string;
    message: string;
    severity: DeplintSeverity;
    workspace: Workspace;
}
/**
 * How the active classifier wants an external runtime dependency placed.
 * `review` (AEI classifier only) means the score is borderline: keep the
 * current placement and surface a warning instead of auto-fixing.
 */
export type DeplintDependencyClassification = 'dependency' | 'peer' | 'review';
export interface DeplintWorkspaceContext {
    /** Active dep-vs-peer classifier (`commands.deplint.classifier`). */
    classifierMode: 'aei' | 'legacy';
    /**
     * Classifies an external runtime dependency for library packages.
     * Callers are expected to have already applied the higher-precedence
     * checks (refType overrides, terminal packages) before consulting this.
     * Memoized per workspace snapshot — the AEI classifier runs its analysis
     * once on first use.
     */
    classifyDependency: (dependency: string) => DeplintDependencyClassification;
    exclude?: Set<string>;
    fileContext: FileContext;
    /** Packages that must stay in `dependencies` (never promoted to peerDependencies). */
    forceDeps: Set<string>;
    /** Packages that must only appear in `devDependencies` (moved out of dependencies/peerDependencies). */
    forceDevs: Set<string>;
    /**
     * User overrides for `peerDependenciesMeta[<name>].optional`. Presence
     * forces the value, absence falls back to the auto rule (every requiring
     * source marks the peer optional).
     */
    forcePeerOptional: Map<string, boolean>;
    /** Packages that must be in `peerDependencies` (moved from dependencies if needed). */
    forcePeers: Set<string>;
    isTerminalPackage: boolean;
    packageJsonPath: string;
    packageKind: DeplintPackageKind;
    packageParams: CheckPackageParams;
    /**
     * Configured peer-range form (from `deplint.peerDependencies.range-style`).
     * Every rule that writes a `peerDependencies` version reads this and
     * produces the configured form directly, so the range-style rule never has
     * to rewrite another rule's output on a second pass.
     */
    peerRangeBound?: PeerBoundType;
    peerRangeForm: 'broad' | 'shorthand';
    sourceExclude: string[];
    sourceParams: CheckSourceParams;
    unusedDependencyExclude: Set<string>;
    /**
     * Exclude set used by `unusedPeerDependenciesRule`. Narrower than
     * `unusedDependencyExclude`: only peers reached via runtime chains (or
     * vouched for via `refType: 'dep' | 'peer'` / `peerOptional` override) are
     * preserved here. `forceDevs` is intentionally NOT included — a package
     * the user has classified as a devDep should be allowed to leave
     * `peerDependencies`.
     */
    unusedPeerDependencyExclude: Set<string>;
    workspace: Workspace;
    workspaceNames?: Set<string>;
}
export interface DeplintReportInput {
    data?: unknown;
    dependency?: string;
    evidence?: string[];
    file?: string;
    message: string;
}
export interface DeplintRuleOptions {
    [key: string]: unknown;
    ignore?: string[];
}
export interface DeplintRuleContext extends DeplintWorkspaceContext {
    options: DeplintRuleOptions;
    report: (diagnostic: DeplintReportInput) => void;
}
export interface DeplintRuleMeta {
    description?: string;
    fixable?: DeplintFixKind[];
    severity: DeplintSeverity;
}
export interface DeplintRule {
    category: DeplintCategory;
    enabled?: boolean;
    evaluate: (context: DeplintRuleContext) => Promise<void> | void;
    id: string;
    meta: DeplintRuleMeta;
    options?: DeplintRuleOptions;
    resolveFixes?: (diagnostic: DeplintDiagnostic, context: DeplintWorkspaceContext & {
        options: DeplintRuleOptions;
    }) => Promise<DeplintFix[]> | DeplintFix[];
}
export interface DeplintPlugin {
    name: string;
    rules: DeplintRule[];
}
export interface DeplintRuleProgress {
    category: DeplintCategory;
    id: string;
}
export interface DeplintWorkspaceProgressContext {
    allFiles: number;
    dependencies: number;
    devDependencies: number;
    distFiles: number;
    excludeCount: number;
    forceDeps: number;
    forceDevs: number;
    forcePeerOptional: number;
    forcePeers: number;
    isTerminalPackage: boolean;
    packageKind: DeplintPackageKind;
    peerDependencies: number;
}
export type DeplintProgressEvent = {
    activeCategories: DeplintCategory[];
    fix: boolean;
    maxFixPasses: number;
    type: 'run-start';
    workspaces: Workspace[];
} | {
    pass: number;
    type: 'pass-start';
    workspaces: Workspace[];
} | {
    diagnostics: number;
    pass: number;
    rulesEvaluated: number;
    rulesSkipped: number;
    type: 'pass-end';
} | {
    context: DeplintWorkspaceProgressContext;
    pass: number;
    type: 'workspace-start';
    workspace: Workspace;
    workspaceIndex: number;
    workspaceTotal: number;
} | {
    diagnostics: number;
    pass: number;
    type: 'workspace-end';
    workspace: Workspace;
} | {
    pass: number;
    rule: DeplintRuleProgress;
    ruleIndex: number;
    ruleTotal: number;
    type: 'rule-start';
    workspace: Workspace;
} | {
    diagnostics: number;
    elapsedMs: number;
    pass: number;
    rule: DeplintRuleProgress;
    ruleIndex: number;
    ruleTotal: number;
    type: 'rule-end';
    workspace: Workspace;
} | {
    pass: number;
    reason: string;
    rule: DeplintRuleProgress;
    ruleIndex: number;
    ruleTotal: number;
    type: 'rule-skip';
    workspace: Workspace;
} | {
    diagnostics: number;
    fixPass: number;
    type: 'fix-start';
} | {
    appliedFixes: number;
    fixPass: number;
    type: 'fix-end';
};
export type DeplintProgressReporter = (event: DeplintProgressEvent) => void;
export interface DeplintRunOptions {
    /** CLI override for the dep-vs-peer classifier (`commands.deplint.classifier`). */
    classifier?: 'aei' | 'legacy';
    /** Source paths passed via --exclude on the CLI (merged with config). */
    cliExclude?: string[];
    deps?: boolean;
    devDeps?: boolean;
    fix?: boolean;
    jobs?: number;
    peerDeps?: boolean;
    pkg?: string;
    progress?: DeplintProgressReporter;
    reporter?: 'human' | 'json';
    verbose?: boolean;
}
export interface DeplintAppliedFix {
    dependency: string;
    detail: string;
    workspace: Workspace;
}
export interface DeplintSummary {
    appliedFixes: number;
    diagnosticsByRule?: Record<string, number>;
    errorCount: number;
    fixPassesRun?: number;
    fixableErrorCount: number;
    fixableWarningCount: number;
    passesRun?: number;
    problemCount: number;
    rulesEvaluated?: number;
    rulesSkipped?: number;
    warningCount: number;
    workspacesChecked: number;
}
export interface DeplintRunResult {
    appliedFixes: DeplintAppliedFix[];
    diagnostics: DeplintDiagnostic[];
    summary: DeplintSummary;
}
export interface DeplintReporter {
    render: (result: DeplintRunResult) => void;
}
//# sourceMappingURL=types.d.ts.map