Files
NetMesh/application/state/pluginExtensionBridge.ts
zhaolei 3c72efcb7f
Some checks failed
build-packages / resolve bundled mosh-client (push) Has been cancelled
build-packages / resolve bundled et-client (push) Has been cancelled
build-packages / build-macos (push) Has been cancelled
build-packages / build-windows (push) Has been cancelled
build-packages / build-linux-x64 (push) Has been cancelled
build-packages / build-linux-arm64 (push) Has been cancelled
build-packages / release (push) Has been cancelled
build-packages / update Nix release metadata (push) Has been cancelled
build-packages / bump homebrew tap (push) Has been cancelled
test / lint-and-test (push) Has been cancelled
AI automation / Route event (push) Has been cancelled
AI automation / Hand reopened issue to maintainers (push) Has been cancelled
AI automation / Clean source issue state (push) Has been cancelled
AI automation / Reconcile handoffs (push) Has been cancelled
AI automation / Classify issue (push) Has been cancelled
AI automation / Claude Code smoke (push) Has been cancelled
AI automation / Review issue follow-up (push) Has been cancelled
AI automation / Publish issue follow-up (push) Has been cancelled
AI automation / Implement with Claude Code (push) Has been cancelled
AI automation / Publish implement PR (push) Has been cancelled
AI automation / Continue queued issue comments (push) Has been cancelled
AI automation / Codex review loop (push) Has been cancelled
AI automation / Publish Codex fix (push) Has been cancelled
AI automation / Clear Codex dispatch marker (push) Has been cancelled
AI automation / Own PR re-request Codex (push) Has been cancelled
AI automation / External PR re-request Codex (push) Has been cancelled
AI automation / Poll Codex reaction / retry (push) Has been cancelled
build-et-binaries / build-linux-x64 (push) Has been cancelled
build-et-binaries / build-linux-arm64 (push) Has been cancelled
build-et-binaries / build-macos-universal (push) Has been cancelled
build-et-binaries / build-windows-x64 (push) Has been cancelled
build-et-binaries / release (push) Has been cancelled
[Init] Initial commit - NetMesh terminal manager
2026-09-13 18:24:01 +08:00

83 lines
3.7 KiB
TypeScript

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<string> = Object.freeze([]);
let credentialCatalogIds = EMPTY_CREDENTIAL_IDS;
const credentialCatalogListeners = new Set<() => void>();
const publishCredentialCatalogIds = (ids: ReadonlyArray<string>) => {
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<NonNullable<NetcattyBridge["detectPluginImporter"]>>[0]) {
const bridge = requireBridge();
if (!bridge.detectPluginImporter) return null;
return bridge.detectPluginImporter(request);
},
async parseImporterFile(request: Parameters<NonNullable<NetcattyBridge["parsePluginImporterFile"]>>[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<NonNullable<NetcattyBridge["onPluginImporterProgress"]>>[0]) {
return netcattyBridge.get()?.onPluginImporterProgress?.(listener) ?? (() => {});
},
onAuthenticationChallenge(listener: Parameters<NonNullable<NetcattyBridge["onPluginAuthenticationChallenge"]>>[0]) {
return netcattyBridge.get()?.onPluginAuthenticationChallenge?.(listener) ?? (() => {});
},
onContributionsChanged(listener: Parameters<NonNullable<NetcattyBridge["onPluginContributionsChanged"]>>[0]) {
return netcattyBridge.get()?.onPluginContributionsChanged?.(listener) ?? (() => {});
},
async respondAuthenticationChallenge(
response: Parameters<NonNullable<NetcattyBridge["respondPluginAuthenticationChallenge"]>>[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);
},
});