"use strict";
/**
 * Shared Routes — Plugin collection and registry helpers
 *
 * Handles installed_plugins.json registry reads, legacy plugin directory
 * scanning, and plugin path encode/decode.
 *
 * Registry content rendering is in shared-routes-plugin-registry-content.ts.
 */
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 (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
    __setModuleDefault(result, mod);
    return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getPluginItems = exports.getLegacyPluginDirectoryItems = exports.getPluginRegistryItems = exports.stringifyJson = exports.isPluginInfrastructurePath = exports.describeInstalledPlugin = exports.extractMarketplaceFromPluginName = exports.readPluginInstalledRegistry = exports.readJsonObject = exports.decodePluginRegistryPath = exports.encodePluginRegistryPath = void 0;
const fs = __importStar(require("fs"));
const path = __importStar(require("path"));
const shared_routes_path_guards_1 = require("./shared-routes-path-guards");
const shared_routes_markdown_1 = require("./shared-routes-markdown");
const PLUGIN_REGISTRY_PATH_PREFIX = 'plugin-registry:';
const PLUGIN_INFRASTRUCTURE_DIRECTORIES = new Set(['cache', 'data', 'marketplaces']);
// ---------------------------------------------------------------------------
// Path encode / decode
// ---------------------------------------------------------------------------
function encodePluginRegistryPath(pluginName) {
    return `${PLUGIN_REGISTRY_PATH_PREFIX}${encodeURIComponent(pluginName)}`;
}
exports.encodePluginRegistryPath = encodePluginRegistryPath;
function decodePluginRegistryPath(itemPath) {
    if (!itemPath.startsWith(PLUGIN_REGISTRY_PATH_PREFIX)) {
        return null;
    }
    try {
        const encodedName = itemPath.slice(PLUGIN_REGISTRY_PATH_PREFIX.length);
        const pluginName = decodeURIComponent(encodedName);
        return pluginName.length > 0 ? pluginName : null;
    }
    catch {
        return null;
    }
}
exports.decodePluginRegistryPath = decodePluginRegistryPath;
// ---------------------------------------------------------------------------
// JSON helpers
// ---------------------------------------------------------------------------
function readJsonObject(filePath, allowedRoots) {
    const resolvedPath = (0, shared_routes_path_guards_1.safeRealPath)(filePath);
    if (!resolvedPath || !(0, shared_routes_path_guards_1.isPathWithinAny)(resolvedPath, allowedRoots)) {
        return null;
    }
    try {
        const stats = fs.statSync(resolvedPath);
        if (!stats.isFile() || stats.size > shared_routes_markdown_1.MAX_CONTENT_FILE_BYTES) {
            return null;
        }
        const parsed = JSON.parse(fs.readFileSync(resolvedPath, 'utf8'));
        if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
            return null;
        }
        return parsed;
    }
    catch {
        return null;
    }
}
exports.readJsonObject = readJsonObject;
function readPluginInstalledRegistry(sharedDir, allowedRoots) {
    const parsed = readJsonObject(path.join(sharedDir, 'installed_plugins.json'), allowedRoots);
    if (!parsed ||
        !parsed.plugins ||
        typeof parsed.plugins !== 'object' ||
        Array.isArray(parsed.plugins)) {
        return null;
    }
    return {
        version: typeof parsed.version === 'number' ? parsed.version : undefined,
        plugins: parsed.plugins,
    };
}
exports.readPluginInstalledRegistry = readPluginInstalledRegistry;
// ---------------------------------------------------------------------------
// Description helpers
// ---------------------------------------------------------------------------
function extractMarketplaceFromPluginName(pluginName) {
    const atIndex = pluginName.lastIndexOf('@');
    if (atIndex <= 0 || atIndex === pluginName.length - 1) {
        return null;
    }
    return pluginName.slice(atIndex + 1);
}
exports.extractMarketplaceFromPluginName = extractMarketplaceFromPluginName;
function describeInstalledPlugin(pluginName, metadata) {
    const recordCount = Array.isArray(metadata) ? metadata.length : 1;
    const marketplace = extractMarketplaceFromPluginName(pluginName);
    const recordLabel = `${recordCount} ${recordCount === 1 ? 'record' : 'records'}`;
    return marketplace
        ? `Installed from ${marketplace}; ${recordLabel} in shared registry`
        : `Installed plugin; ${recordLabel} in shared registry`;
}
exports.describeInstalledPlugin = describeInstalledPlugin;
// ---------------------------------------------------------------------------
// Infrastructure path guard
// ---------------------------------------------------------------------------
function isPluginInfrastructurePath(candidatePath, sharedDir) {
    for (const directoryName of PLUGIN_INFRASTRUCTURE_DIRECTORIES) {
        const resolvedInfrastructurePath = (0, shared_routes_path_guards_1.safeRealPath)(path.join(sharedDir, directoryName));
        if (resolvedInfrastructurePath && (0, shared_routes_path_guards_1.isPathWithin)(candidatePath, resolvedInfrastructurePath)) {
            return true;
        }
    }
    return false;
}
exports.isPluginInfrastructurePath = isPluginInfrastructurePath;
// ---------------------------------------------------------------------------
// JSON serialization
// ---------------------------------------------------------------------------
function stringifyJson(value) {
    return JSON.stringify(value, null, 2) ?? 'null';
}
exports.stringifyJson = stringifyJson;
// ---------------------------------------------------------------------------
// Item list builders
// ---------------------------------------------------------------------------
function getPluginRegistryItems(sharedDir, allowedRoots) {
    const registry = readPluginInstalledRegistry(sharedDir, allowedRoots);
    if (!registry) {
        return [];
    }
    return Object.entries(registry.plugins).map(([pluginName, metadata]) => ({
        name: pluginName,
        description: describeInstalledPlugin(pluginName, metadata),
        path: encodePluginRegistryPath(pluginName),
        type: 'plugin',
    }));
}
exports.getPluginRegistryItems = getPluginRegistryItems;
function getLegacyPluginDirectoryItems(sharedDir, allowedRoots) {
    let entries = [];
    try {
        entries = fs.readdirSync(sharedDir, { withFileTypes: true });
    }
    catch {
        return [];
    }
    const items = [];
    for (const entry of entries) {
        if (!entry.isDirectory() || PLUGIN_INFRASTRUCTURE_DIRECTORIES.has(entry.name)) {
            continue;
        }
        const entryPath = path.join(sharedDir, entry.name);
        const resolvedEntryPath = (0, shared_routes_path_guards_1.safeRealPath)(entryPath);
        if (!resolvedEntryPath || !(0, shared_routes_path_guards_1.isPathWithinAny)(resolvedEntryPath, allowedRoots)) {
            continue;
        }
        const description = (0, shared_routes_markdown_1.readFirstMarkdownDescription)([
            path.join(resolvedEntryPath, 'README.md'),
            path.join(resolvedEntryPath, 'readme.md'),
            path.join(resolvedEntryPath, 'PLUGIN.md'),
        ], allowedRoots);
        if (!description) {
            continue;
        }
        items.push({ name: entry.name, description, path: entryPath, type: 'plugin' });
    }
    return items;
}
exports.getLegacyPluginDirectoryItems = getLegacyPluginDirectoryItems;
function getPluginItems(sharedDir, allowedRoots) {
    const registryItems = getPluginRegistryItems(sharedDir, allowedRoots);
    const legacyDirectoryItems = getLegacyPluginDirectoryItems(sharedDir, allowedRoots);
    const itemsByPath = new Map();
    for (const item of [...registryItems, ...legacyDirectoryItems]) {
        itemsByPath.set(item.path, item);
    }
    return [...itemsByPath.values()].sort((a, b) => a.name.localeCompare(b.name));
}
exports.getPluginItems = getPluginItems;
//# sourceMappingURL=shared-routes-plugins.js.map