import type { PluginInstallRecord } from "../config/types.plugins.js"; import { readJsonFile, readJsonFileSync } from "../infra/json-files.js"; import { resolveInstalledPluginIndexStorePath, type InstalledPluginIndexStoreOptions, } from "./installed-plugin-index-store-path.js"; function isRecord(value: unknown): value is Record { return typeof value === "object" && value !== null && !Array.isArray(value); } function cloneInstallRecords( records: Record | undefined, ): Record { return structuredClone(records ?? {}); } function readRecordMap(value: unknown): Record | null { if (!isRecord(value)) { return null; } const records: Record = {}; for (const [pluginId, record] of Object.entries(value).toSorted(([left], [right]) => left.localeCompare(right), )) { if (isRecord(record) && typeof record.source === "string") { records[pluginId] = structuredClone(record) as PluginInstallRecord; } } return records; } export function extractPluginInstallRecordsFromPersistedInstalledPluginIndex( index: unknown, ): Record | null { if (!isRecord(index) || !Array.isArray(index.plugins)) { return null; } if (Object.prototype.hasOwnProperty.call(index, "installRecords")) { return readRecordMap(index.installRecords) ?? {}; } const records: Record = {}; for (const entry of index.plugins) { if (!isRecord(entry) || typeof entry.pluginId !== "string" || !isRecord(entry.installRecord)) { continue; } records[entry.pluginId] = structuredClone(entry.installRecord) as PluginInstallRecord; } return records; } export async function readPersistedInstalledPluginIndexInstallRecords( options: InstalledPluginIndexStoreOptions = {}, ): Promise | null> { const parsed = await readJsonFile(resolveInstalledPluginIndexStorePath(options)); return extractPluginInstallRecordsFromPersistedInstalledPluginIndex(parsed); } export function readPersistedInstalledPluginIndexInstallRecordsSync( options: InstalledPluginIndexStoreOptions = {}, ): Record | null { const parsed = readJsonFileSync(resolveInstalledPluginIndexStorePath(options)); return extractPluginInstallRecordsFromPersistedInstalledPluginIndex(parsed); } export async function loadInstalledPluginIndexInstallRecords( params: InstalledPluginIndexStoreOptions = {}, ): Promise> { return cloneInstallRecords((await readPersistedInstalledPluginIndexInstallRecords(params)) ?? {}); } export function loadInstalledPluginIndexInstallRecordsSync( params: InstalledPluginIndexStoreOptions = {}, ): Record { return cloneInstallRecords(readPersistedInstalledPluginIndexInstallRecordsSync(params) ?? {}); }