import { netcattyBridge } from "../../infrastructure/services/netcattyBridge"; const requireBridge = () => { const bridge = netcattyBridge.get(); if (!bridge) throw new Error("Netcatty desktop bridge is unavailable"); return bridge; }; const EMPTY_CREDENTIAL_IDS: ReadonlyArray = Object.freeze([]); let credentialCatalogIds = EMPTY_CREDENTIAL_IDS; const credentialCatalogListeners = new Set<() => void>(); const publishCredentialCatalogIds = (ids: ReadonlyArray) => { const next = ids.length > 0 ? Object.freeze([...new Set(ids)]) : EMPTY_CREDENTIAL_IDS; if (next.length === credentialCatalogIds.length && next.every((id, index) => id === credentialCatalogIds[index])) return; credentialCatalogIds = next; for (const listener of credentialCatalogListeners) listener(); }; export const pluginExtensionBridge = Object.freeze({ async listProviders(kind: "connection" | "authentication" | "importer" | "sync") { return requireBridge().listPluginExtensionProviders?.({ kind }) ?? []; }, async updateCredentialCatalog(entries: ReadonlyArray<{ id: string; ciphertext: string }>) { try { const accepted = await (requireBridge().updatePluginCredentialCatalog?.(entries) ?? 0); publishCredentialCatalogIds(accepted === entries.length ? entries.map((entry) => entry.id) : []); return accepted; } catch (error) { publishCredentialCatalogIds([]); throw error; } }, getCredentialCatalogIds() { return credentialCatalogIds; }, subscribeCredentialCatalog(listener: () => void) { credentialCatalogListeners.add(listener); return () => credentialCatalogListeners.delete(listener); }, async detectImporter(request: Parameters>[0]) { const bridge = requireBridge(); if (!bridge.detectPluginImporter) return null; return bridge.detectPluginImporter(request); }, async parseImporterFile(request: Parameters>[0]) { const bridge = requireBridge(); if (!bridge.parsePluginImporterFile) throw new Error("Plugin importer bridge is unavailable"); return bridge.parsePluginImporterFile(request); }, async cancelRequest(requestId: string) { return requireBridge().cancelPluginExtensionRequest?.(requestId) ?? false; }, async selectImporterFile() { const bridge = requireBridge(); if (!bridge.selectPluginImporterFile) throw new Error("Plugin importer file selection is unavailable"); return bridge.selectPluginImporterFile(); }, async releaseImporterFile(selectionToken: string) { return requireBridge().releasePluginImporterFile?.(selectionToken) ?? false; }, onImporterProgress(listener: Parameters>[0]) { return netcattyBridge.get()?.onPluginImporterProgress?.(listener) ?? (() => {}); }, onAuthenticationChallenge(listener: Parameters>[0]) { return netcattyBridge.get()?.onPluginAuthenticationChallenge?.(listener) ?? (() => {}); }, onContributionsChanged(listener: Parameters>[0]) { return netcattyBridge.get()?.onPluginContributionsChanged?.(listener) ?? (() => {}); }, async respondAuthenticationChallenge( response: Parameters>[0], ) { const bridge = requireBridge(); if (!bridge.respondPluginAuthenticationChallenge) throw new Error("Plugin authentication bridge is unavailable"); return bridge.respondPluginAuthenticationChallenge(response); }, async openExternal(url: string) { return requireBridge().openExternal?.(url); }, });