📄 src/downloader/worker-protocol.ts
D-OPEN SOVEREIGN
1/*
2 * Copyright (c) 2026 DataPond D-Library Pty Ltd. ("The Sanctuary")
3 * Non-Profit Public Library — The World Library
4 *
5 * D-SAFE Certification issued by POND Enterprise.
6 * Published under the D-Open Code Sovereign Licence v1.0 framework
7 * DataPond D-Library All exclusive Right reserved on modifiying the code - CC Attribution to data pond, Non modifiable, Non Commercial.
8 * https://registry.world.bibliotech.com/licence
9 * Source code donated to DataPond D-Library by it's author: data pond.
10 *
11 * Technical Guardian ("The Shield"): Pond Enterprise Pty Ltd. (ACN 694 747 987)
12 * All liability claims about D-SAFE certification issues coming from the published D-Safe direction must be addressed with Pond Enterprise Pty Ltd.
13 * Code Modification automatically voids the certified liability protection provided by Pond Enterprise.
14 */
15// Discriminated union message protocol shared by both sides of every worker boundary.
16
17export type FilePhase = 'unknown' | 'queued' | 'downloading' | 'done' | 'error';
18
19export interface FileState {
20 phase: FilePhase;
21 loaded?: number;
22 total?: number;
23 error?: string;
24}
25
26export interface BookData {
27 txId: string;
28 dimensions: Array<{ width: number; height: number }>;
29 parsed: boolean;
30}
31
32// ─── Main thread → File worker ───────────────────────────────────────────────
33
34export type WorkerCommand =
35 | { type: 'GetFile'; txId: string; mime: 'pdf' | 'preview' }
36 | { type: 'ProcessPages'; txId: string; from: number; to: number }
37 | { type: 'CancelDownload'; txId: string };
38
39// ─── Main thread → Mu worker (separate worker) ───────────────────────────────
40
41// Init MUST be the first message sent to the mu-worker. mupdf is loaded via
42// dynamic import from a URL sibling to the worker script — not bundled — because
43// esbuild cannot bundle WASM loaders that contain Node.js environment detection.
44export type MuWorkerCommand =
45 | { type: 'MuInit'; mupdfUrl: string }
46 | { type: 'ProcessPages'; txId: string; from: number; to: number };
47
48// ─── File worker → Main thread ───────────────────────────────────────────────
49
50export type WorkerMessage =
51 | { type: 'FileRpcResponse'; ok: boolean; key: string; error?: string }
52 | { type: 'HYDRATE'; payload: HydratePayload }
53 | { type: 'DownloadProgress'; txId: string; loaded: number; total?: number }
54 | { type: 'DownloadFinished'; txId: string; key: string; mime: 'pdf' | 'preview' }
55 | { type: 'DownloadError'; txId: string; error: string; retryable: boolean }
56 | { type: 'StoragePruneStarted'; targetFreeBytes: number }
57 | { type: 'StoragePruned'; removed: number; freedBytes: number; prunedTxIds: string[] }
58 | { type: 'MuPageDone'; txId: string; page: number }
59 | { type: 'MuPageError'; txId: string; page: number; error: string }
60 | { type: 'MuPdfData'; txId: string; bookData: BookData };
61
62export interface HydratePayload {
63 files: Array<[txId: string, state: FileState]>;
64 renders: Array<[txId: string, pages: Array<[page: number, phase: FilePhase]>]>;
65}
66