📄 src/downloader/cache-store.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// Named-cache wrappers — never use global caches.match() (it searches all caches and returns wrong type).
16import { CACHES, pdfKey, previewKey, pageKey } from './keys';
17
18export const openPdfCache = () => caches.open(CACHES.pdf);
19export const openPreviewCache = () => caches.open(CACHES.preview);
20export const openPagesCache = () => caches.open(CACHES.pages);
21
22export const matchPdf = async (txId: string): Promise<Response | undefined> => {
23 const c = await openPdfCache();
24 return c.match(pdfKey(txId));
25};
26
27export const matchPreview = async (txId: string): Promise<Response | undefined> => {
28 const c = await openPreviewCache();
29 return c.match(previewKey(txId));
30};
31
32export const matchPage = async (txId: string, n: number): Promise<Response | undefined> => {
33 const c = await openPagesCache();
34 return c.match(pageKey(txId, n));
35};
36
37export const putPdf = async (txId: string, response: Response): Promise<void> => {
38 const c = await openPdfCache();
39 await c.put(pdfKey(txId), response);
40};
41
42export const putPreview = async (txId: string, response: Response): Promise<void> => {
43 const c = await openPreviewCache();
44 await c.put(previewKey(txId), response);
45};
46
47export const putPage = async (txId: string, n: number, response: Response): Promise<void> => {
48 const c = await openPagesCache();
49 await c.put(pageKey(txId, n), response);
50};
51
52export const deletePdf = async (txId: string): Promise<boolean> => {
53 const c = await openPdfCache();
54 return c.delete(pdfKey(txId));
55};
56
57export const deletePreview = async (txId: string): Promise<boolean> => {
58 const c = await openPreviewCache();
59 return c.delete(previewKey(txId));
60};
61
62// Returns txIds (not full keys) for the entries in each cache.
63export const pdfKeys = async (): Promise<string[]> => {
64 const c = await openPdfCache();
65 const reqs = await c.keys();
66 return reqs.map(r => txIdFromArKey(r.url)).filter(Boolean) as string[];
67};
68
69export const previewKeys = async (): Promise<string[]> => {
70 const c = await openPreviewCache();
71 const reqs = await c.keys();
72 return reqs.map(r => txIdFromArKey(r.url)).filter(Boolean) as string[];
73};
74
75export const pageKeys = async (): Promise<string[]> => {
76 const c = await openPagesCache();
77 const reqs = await c.keys();
78 return reqs.map(r => txIdFromPageKey(r.url)).filter(Boolean) as string[];
79};
80
81// Extract txId from `/ar/<txId>` or a full URL ending in that path.
82function txIdFromArKey(url: string): string | null {
83 const m = url.match(/\/ar\/([^/?#]+)/);
84 return m ? m[1] : null;
85}
86
87// Extract txId from `/pages/<encodedTxId>/<page>` or a full URL.
88function txIdFromPageKey(url: string): string | null {
89 const m = url.match(/\/pages\/([^/?#/]+)\//);
90 return m ? decodeURIComponent(m[1]) : null;
91}
92