/// <reference types="node" />

export declare interface AddRuleOptions extends Rule {
    /**
     * The id of the vulnerability to which the rule applies.
     */
    id: string;
    /**
     * The path or the dependency to which the rule applies.
     */
    path: string;
    ignoredBy?: {
        email: string;
    };
    patched?: string;
    reasonType?: ReasonType;
}

/**
 * Type of a function returning the root of a vulnerability URL
 */
export declare type ApiRootFunction = (vulnId: string) => string;

/** Returns an empty policy */
export declare const create: () => Promise<Policy>;

/**
 * Demunges the given policy object.
 * @param policy  The policy object to demunge
 * @param apiRoot A string or func calculating the base URL for the Snyk API
 * @returns The demunged policy object
 */
export declare function demunge(policy: Policy, apiRoot?: ApiRootFunction | string): DemungedResults;

export declare interface DemungedResults {
    exclude: VulnRules[];
    ignore: VulnRules[];
    patch: VulnRules[];
    version: string;
}

export declare type ExcludeRuleSet = Record<PatternGroup, (string | PathObj)[]>;

export declare interface FilteredRule extends Rule {
    path: string[];
}

export declare type FilteredVulnerability<T extends Vulnerability = Vulnerability> = T & {
    filtered?: {
        ignored?: FilteredRule[];
        patches?: FilteredRule[];
    };
    note?: string;
};

export declare interface FilteredVulnerabilityReport<T extends Vulnerability = Vulnerability> {
    ok: boolean;
    vulnerabilities: FilteredVulnerability<T>[];
    filtered: {
        ignore: Vulnerability[];
        patch: Vulnerability[];
    };
}

/**
 * Returns any matching rule given a specific vulnerability object. The `vuln` object must contain
 * `id` and `from` to match correctly.
 * @param policy the policy object to apply to the vulnerabilities
 * @param vuln a single vulnerability, where `from` contains the dependency path in which it was introduced
 * @returns the matching rule, or null if no match was found
 */
export declare function getByVuln(policy?: Policy, vuln?: Vulnerability): VulnRule | null;

/**
 * Returns true if the error is a NodeJS error.
 * @param value The value to check.
 */
export declare function isNodeError(value: unknown): value is NodeJS.ErrnoException;

/**
 * Returns true if the value is an object. This is a more reliable check than `typeof` or
 * `instanceof`, because `typeof null` is `object` and `typeof []` is `object` which is not what
 * we want.
 * @param v The value to check.
 * @returns True if the value is an object.
 */
export declare function isObject(v: unknown): v is Record<string, unknown>;

/**
 * Loads a policy from disk. If `root` is an array of strings, the policies will be merged together.
 * @param root the root directory to load the policy from (default is `process.cwd())`
 * @param options options for loading the policy or policies
 * @returns a single policy if `root` is a string, or a merged policy if `root` is an array of strings
 */
export declare function load(root?: string | string[] | loadOptions, options?: loadOptions): Promise<Policy>;

/**
 * Loads a policy from text
 * @param text the policy text
 * @returns the policy
 */
export declare function loadFromText(text?: string): Promise<Policy>;

declare interface loadOptions {
    loose?: boolean;
    'ignore-policy'?: boolean;
    'trust-policies'?: boolean;
}

export declare type MatchStrategy = 'packageManager' | 'exact';

/**
 * Returns whether any of the rule paths match the path in which the vulnerability was introduced.
 * @param vuln a single vulnerability, where `from` contains the dependency path in which it was introduced
 * @param rule an ignore rule for the given vulnerability with one or more paths to ignore
 * @param matchStrategy the strategy used to match vulnerabilities (defaults to 'packageManager')
 * @returns whether any ignore rules match the vulnerabilities import path
 */
export declare function matchToRule(vuln: {
    id?: string;
    from: string[];
}, pathObj: PathObj, matchStrategy?: MatchStrategy): boolean;

export declare interface MetaRule extends Rule {
    path: string[] | {
        module: string;
        url?: string;
    }[];
}

/**
 * A dependency package.
 */
export declare interface Package {
    name: string;
    version: string;
}

/**
 * @example
 * {
 *  "urls": [
 *    "https://raw.githubusercontent.com/Snyk/vulndb/snapshots/master/patches/npm/handlebars/20151207/handlebars_0.patch"
 *  ],
 *  "version": "<4.0.0 >=3.0.2",
 *  "modificationTime": "2015-12-14T23:52:16.811Z",
 *  "comments": [
 *    "https://github.com/wycats/handlebars.js/commit/83b8e846a3569bd366cf0b6bdc1e4604d1a2077e"
 *  ],
 *  "id": "patch:npm:handlebars:20151207:0"
 * }
 */
declare interface Patch {
    urls?: string[];
    version?: string;
    modificationTime: string;
    comments?: string[];
    id: string;
}

export declare interface PatchMetaData {
    patched: string;
}

/**
 * @example
 * {
 *   "sqlite > sqlite3 > node-pre-gyp > request > hawk": {
 *     "reason": "None given",
 *     "expires": "2016-03-01T14:30:04.136Z"
 *   }
 * }
 */
export declare type PathObj = Record<string, Rule>;

export declare type PathRule = {
    /**
     * The path to which the rule is applied.
     */
    path: string;
    /**
     * If true, the rule is disregarded if the vulnerability is fixable.
     */
    disregardIfFixable?: boolean;
    /**
     * The date the rule expires.
     */
    expires?: Date;
    /**
     * The reason for the rule.
     */
    reason?: string;
};

export declare type PatternGroup = 'global' | 'code' | 'iac-drift';

export declare interface Policy {
    __filename: string | null;
    __created: Date | number;
    __modified: Date | number;
    ignore: RuleSet;
    patch: RuleSet;
    suggest: RuleSet;
    exclude?: ExcludeRuleSet;
    failThreshold: Severity;
    skipVerifyPatch: boolean;
    version: string;
    add: (type: 'ignore' | 'patch', options: AddRuleOptions) => Policy;
    addExclude: (pattern: string, group?: PatternGroup, options?: Rule) => void;
    addIgnore: (options: AddRuleOptions) => Policy;
    addPatch: (options: AddRuleOptions) => Policy;
    demunge: (apiRoot?: ApiRootFunction | string) => DemungedResults;
    filter: <VulnType extends Vulnerability, ReportType>(vulns: ReportType & VulnerabilityReport<VulnType>, root?: string, matchStrategy?: MatchStrategy) => ReportType & FilteredVulnerabilityReport<VulnType>;
    save: (root?: string | undefined, spinner?: Spinner) => Promise<void>;
}

export declare class PolicyError extends Error {
    code?: string;
    constructor(message: string, code?: string);
}

export declare type ReasonType = 'not-vulnerable' | 'wont-fix' | 'temporary-ignore';

/**
 * @example
 * {
 *   "reason": "None given",
 *   "expires": "2016-03-01T14:30:04.136Z"
 * }
 */
export declare interface Rule {
    created?: Date;
    disregardIfFixable?: boolean;
    expires?: string | Date;
    ignoredBy?: {
        email?: string;
        name?: string;
    };
    reason?: string;
    reasonType?: ReasonType;
    source?: string;
    from?: string;
}

/**
 * @example
 * {
 *   "npm:hawk:20160119": [
 *     {
 *       "sqlite > sqlite3 > node-pre-gyp > request > hawk": {
 *         "reason": "None given",
 *         "expires": "2016-03-01T14:30:04.136Z"
 *       }
 *     }
 *   ],
 *   "npm:is-my-json-valid:20160118": [
 *     {
 *       "sqlite > sqlite3 > node-pre-gyp > request > har-validator > is-my-json-valid": {
 *         "reason": "None given",
 *         "expires": "2016-03-01T14:30:04.136Z"
 *       }
 *     }
 *   ],
 * }
 */
export declare type RuleSet = Record<string, PathObj[]>;

/**
 * Saves a policy to disk.
 * @param object the policy to save
 * @param root the root directory to save the policy to (default is `process.cwd())`
 * @param spinner a progress indicator, as used in the [Snyk CLI](https://github.com/Snyk/snyk-internal/blob/0459a7b21709c6a1d3c5edeb61b4abf2103ffaf0/cli/commands/protect/wizard.js#L268)
 * @returns the result of `spinner.clear()`
 */
export declare function save(object: Policy, root?: string, spinner?: Spinner): Promise<any>;

export declare interface SecurityPolicyMetaData {
    ignore?: MetaRule;
}

/**
 * Vulnerability severity.
 */
export declare type Severity = 'critical' | 'high' | 'medium' | 'low';

export declare type Spinner = {
    (label: string): Promise<any>;
    clear: (label: string) => Promise<any>;
};

export declare interface Vulnerability {
    __filename?: string;
    readonly id: string;
    severity?: Severity;
    /**
     * The dependency path in which the vulnerability was introduced. A chain of the packages leading
     * to the culprit, in the `name` or `name@version` format.This should include the project
     * itself.
     * The element [0] is the root package (the scanned project). The element [1] is a top-level
     * dependency etc.
     */
    from: string[];
    isUpgradable?: boolean;
    /**
     * A possible upgrade remediation path. Mirrors the `from` field above, but contains upgraded
     * versions. The element [0] is usually `false` and is of no use.  If the element [1] is false,
     * there's no valid complete upgrade path yet.
     */
    upgradePath?: (string | boolean)[];
    isPatchable?: boolean;
    isPinnable?: boolean;
    patches?: Patch[];
    securityPolicyMetaData?: SecurityPolicyMetaData;
}

export declare interface VulnerabilityReport<T extends Vulnerability = Vulnerability> {
    /**
     * If all the vulns are stripped because of the policy, then the `ok` bool is set to `true`.
     */
    ok?: boolean;
    /**
     * The vulnerabilities found in the project.
     */
    vulnerabilities: T[];
}

export declare interface VulnRule extends Rule {
    /**
     * The vulnerability ID.
     */
    id: string;
    /**
     * The type of rule.
     */
    type: 'ignore' | 'patch';
    /**
     * An array of dependencies (`package@version`) in which the vulnerability was introduced.
     */
    rule: Array<string>;
}

export declare interface VulnRules {
    /**
     * The vulnerability ID.
     */
    id: string;
    /**
     * The URL to the vulnerability on the Snyk website.
     */
    url: string;
    /**
     * The vulnerability's rules with paths to ignore.
     */
    paths: PathRule[];
}

export { }
