"use strict";
/**
 * User-authored tool-location config — `.dxkit/tools.json`.
 *
 * Lets a developer point dxkit at tool binaries that don't live in any
 * of the default probe locations, and choose where `tools install`
 * drops them. The motivating case is locked-down or non-standard
 * environments (corporate Windows boxes, air-gapped CI) where the
 * scanner toolchain is installed into a project- or team-specific
 * directory rather than `~/.local/bin` / the npm global prefix / brew.
 *
 * Shape (every field optional):
 *
 *   {
 *     "probePaths": ["D:\\devtools\\bin", "/opt/team/bin"],
 *     "installDir": "D:\\devtools\\bin"
 *   }
 *
 *   - `probePaths` — extra directories `findTool` searches (PATHEXT-aware
 *     on Windows) AFTER PATH / brew / npm-g / pipx / system probes. A
 *     hit here reports the tool as available with `source: 'probe'`.
 *   - `installDir` — directory `tools install` targets, injected into the
 *     per-ecosystem install command via the ecosystem's bin-dir env var
 *     / flag. Implies a matching `probePaths` entry so the freshly
 *     installed binary is immediately discoverable.
 *
 * The file is optional and hand-authored (or written by the
 * `dxkit-config` skill). Absent / malformed → empty config, never an
 * error: tool detection must degrade gracefully, not crash.
 */
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.toolsConfigPath = toolsConfigPath;
exports.clearToolsConfigCache = clearToolsConfigCache;
exports.loadToolsConfig = loadToolsConfig;
const fs = __importStar(require("fs"));
const path = __importStar(require("path"));
const EMPTY = { probePaths: [], installDir: null };
/** Location of the config inside a project. */
function toolsConfigPath(cwd) {
    return path.join(cwd, '.dxkit', 'tools.json');
}
/**
 * Per-process cache keyed by cwd. Tool config doesn't change mid-run,
 * and `findTool` calls into this on every probe — caching avoids
 * re-reading + re-parsing the file for every tool on every analyzer.
 */
const CACHE = new Map();
/** Test seam: drop the cache so per-test fixtures don't leak. */
function clearToolsConfigCache() {
    CACHE.clear();
}
/**
 * Load `.dxkit/tools.json` for `cwd`. Returns an empty config when the
 * file is absent or unparseable — detection never depends on this file
 * existing.
 */
function loadToolsConfig(cwd) {
    const cached = CACHE.get(cwd);
    if (cached)
        return cached;
    const resolved = readToolsConfig(cwd);
    CACHE.set(cwd, resolved);
    return resolved;
}
function readToolsConfig(cwd) {
    let raw;
    try {
        raw = fs.readFileSync(toolsConfigPath(cwd), 'utf8');
    }
    catch {
        return EMPTY;
    }
    let parsed;
    try {
        parsed = JSON.parse(raw);
    }
    catch {
        return EMPTY;
    }
    if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed))
        return EMPTY;
    const obj = parsed;
    const probePaths = Array.isArray(obj.probePaths)
        ? obj.probePaths.filter((p) => typeof p === 'string' && p.length > 0)
        : [];
    const installDir = typeof obj.installDir === 'string' && obj.installDir.length > 0 ? obj.installDir : null;
    // The install target is always also a probe location so a freshly
    // installed binary is found without the user duplicating the path.
    // Probe both `installDir` (pipx / go install land binaries here) and
    // `installDir/bin` (npm-g / cargo install nest under `bin/`).
    const allProbes = installDir
        ? [...new Set([...probePaths, installDir, path.join(installDir, 'bin')])]
        : probePaths;
    return { probePaths: allProbes, installDir };
}
//# sourceMappingURL=tools-config.js.map