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
120 lines
3.5 KiB
TypeScript
120 lines
3.5 KiB
TypeScript
import type {
|
|
VaultImportFormat,
|
|
VaultImportResult,
|
|
} from "../../domain/vaultImport";
|
|
|
|
import type { VaultImportFileEncoding } from "./vaultImportFile";
|
|
|
|
export type VaultImportWorkerStage = "reading" | "parsing";
|
|
|
|
export interface VaultImportWorkerProgress {
|
|
stage: VaultImportWorkerStage;
|
|
percent: number;
|
|
completedFiles?: number;
|
|
totalFiles?: number;
|
|
currentFileName?: string;
|
|
}
|
|
|
|
export type VaultImportWorkerRequest = {
|
|
type: "import";
|
|
format: VaultImportFormat;
|
|
files: File[];
|
|
relativePaths: string[];
|
|
encoding: VaultImportFileEncoding | undefined;
|
|
masterPassword?: string;
|
|
};
|
|
|
|
export type VaultImportWorkerResponse =
|
|
| { type: "progress"; progress: VaultImportWorkerProgress }
|
|
| { type: "result"; result: VaultImportResult }
|
|
| { type: "error"; message: string };
|
|
|
|
type VaultImportWorkerEvent = MessageEvent<VaultImportWorkerResponse> | ErrorEvent;
|
|
type VaultImportWorkerListener = (event: VaultImportWorkerEvent) => void;
|
|
|
|
export interface VaultImportWorkerLike {
|
|
addEventListener(type: "message" | "error", listener: VaultImportWorkerListener): void;
|
|
removeEventListener(type: "message" | "error", listener: VaultImportWorkerListener): void;
|
|
postMessage(message: VaultImportWorkerRequest): void;
|
|
terminate(): void;
|
|
}
|
|
|
|
interface ImportVaultHostsInWorkerOptions {
|
|
format: VaultImportFormat;
|
|
files: File[];
|
|
encoding?: VaultImportFileEncoding;
|
|
masterPassword?: string;
|
|
signal?: AbortSignal;
|
|
createWorker?: () => VaultImportWorkerLike;
|
|
onProgress?: (progress: VaultImportWorkerProgress) => void;
|
|
}
|
|
|
|
const createVaultImportWorker = (): VaultImportWorkerLike => (
|
|
new Worker(new URL("../workers/vaultImport.worker.ts", import.meta.url), {
|
|
type: "module",
|
|
})
|
|
);
|
|
|
|
export function importVaultHostsInWorker({
|
|
format,
|
|
files,
|
|
encoding,
|
|
masterPassword,
|
|
signal,
|
|
createWorker = createVaultImportWorker,
|
|
onProgress,
|
|
}: ImportVaultHostsInWorkerOptions): Promise<VaultImportResult> {
|
|
if (signal?.aborted) {
|
|
return Promise.reject(new DOMException("Vault import cancelled.", "AbortError"));
|
|
}
|
|
const worker = createWorker();
|
|
|
|
return new Promise((resolve, reject) => {
|
|
const cleanup = () => {
|
|
worker.removeEventListener("message", handleMessage);
|
|
worker.removeEventListener("error", handleWorkerError);
|
|
signal?.removeEventListener("abort", handleAbort);
|
|
worker.terminate();
|
|
};
|
|
|
|
const handleAbort = () => {
|
|
cleanup();
|
|
reject(new DOMException("Vault import cancelled.", "AbortError"));
|
|
};
|
|
|
|
const handleMessage: VaultImportWorkerListener = (event) => {
|
|
const message = (event as MessageEvent<VaultImportWorkerResponse>).data;
|
|
if (message.type === "progress") {
|
|
onProgress?.(message.progress);
|
|
return;
|
|
}
|
|
cleanup();
|
|
if (message.type === "result") {
|
|
resolve(message.result);
|
|
return;
|
|
}
|
|
reject(new Error(message.message));
|
|
};
|
|
|
|
const handleWorkerError: VaultImportWorkerListener = (event) => {
|
|
cleanup();
|
|
const message = event instanceof ErrorEvent && event.message
|
|
? event.message
|
|
: "Vault import worker failed.";
|
|
reject(new Error(message));
|
|
};
|
|
|
|
worker.addEventListener("message", handleMessage);
|
|
worker.addEventListener("error", handleWorkerError);
|
|
signal?.addEventListener("abort", handleAbort, { once: true });
|
|
worker.postMessage({
|
|
type: "import",
|
|
format,
|
|
files,
|
|
relativePaths: files.map((file) => file.webkitRelativePath),
|
|
encoding,
|
|
...(masterPassword ? { masterPassword } : {}),
|
|
});
|
|
});
|
|
}
|