@lls/offline 24.27.0-bbbcfe5a → 24.27.0-d7760203

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,21 +1,3 @@
1
- // src/utils/stream.ts
2
- var parseRange = (range, size) => {
3
- const parts = range.replace("bytes=", "").split("-");
4
- let start = Number.parseInt(parts[0], 10);
5
- let end = Number.parseInt(parts[1], 10);
6
- if (isNaN(start)) {
7
- start = size - end;
8
- end = size - 1;
9
- } else if (isNaN(end)) {
10
- end = size - 1;
11
- }
12
- if (end > size - 1) {
13
- end = size - 1;
14
- }
15
- const chunkSize = end - start + 1;
16
- return { start, end, chunkSize };
17
- };
18
-
19
1
  // src/utils/worker.ts
20
2
  var makeSyncWorker = (offlineWorker2, methodNames, dbg) => {
21
3
  const dic = {};
@@ -38,18 +20,7 @@ var makeSyncWorker = (offlineWorker2, methodNames, dbg) => {
38
20
  return ({ ports, ...arg } = {}) => {
39
21
  return new Promise((resolve, reject) => {
40
22
  const eventId = `${methodName}:${Date.now()}-${Math.random().toFixed(5)}`;
41
- let resolved = false;
42
- const timeout = setTimeout(() => {
43
- console.warn("slow request for", methodName, arg);
44
- }, 3e3);
45
- const doResolve = (arg2) => {
46
- if (!resolved) {
47
- resolved = true;
48
- clearTimeout(timeout);
49
- resolve(arg2);
50
- }
51
- };
52
- dic[eventId] = { resolve: doResolve, reject };
23
+ dic[eventId] = { resolve, reject };
53
24
  offlineWorker2.postMessage({ eventId, methodName, arg }, ports);
54
25
  });
55
26
  };
@@ -106,7 +77,7 @@ var cocoreFetchPartialPageScreen = async (_ev, { offlineWorkerSync: offlineWorke
106
77
  const key = `gqls/${zipSlugName(variables.slugs[0] || "")}.json`;
107
78
  const entryId = knownLinks2.get(key);
108
79
  if (!entryId) {
109
- throw new Error(`slug not found ${key}, links size: ${knownLinks2.size}`);
80
+ throw new Error(`slug not found ${key}`);
110
81
  }
111
82
  const gqlPage = await offlineWorkerSync2.loadPageContent({ entryId });
112
83
  return { data: gqlPage };
@@ -231,90 +202,22 @@ var coreFetchPagesApi = async (ev, { offlineWorkerSync: offlineWorkerSync2, vari
231
202
  }
232
203
  }
233
204
  };
234
- var cocoreFetchPrimaryMethod = async (_ev, { offlineWorkerSync: offlineWorkerSync2, variables }) => {
235
- const uri = variables.uris?.[0];
236
- if (!uri) {
237
- throw new Error("invalid uri");
238
- }
239
- const method = await offlineWorkerSync2.readZipEntry({ bookId: uri, entryName: "gqls/method.json", asJson: true });
240
- return {
241
- data: method
242
- };
243
- };
244
- var cocoreCreateLexicalFlower = async (_ev, { variables }) => {
245
- const flower = variables.flower;
246
- if (!flower) {
247
- throw new Error("invalid flower");
248
- }
249
- const back = {
250
- viewer: {
251
- createLexicalFlower: {
252
- ...flower,
253
- id: Date.now(),
254
- user: null,
255
- createdAt: (/* @__PURE__ */ new Date()).toISOString()
256
- }
257
- }
258
- };
259
- return {
260
- data: back
261
- };
262
- };
263
- var cocoreUpdateLexicalFlower = async (_ev, { variables }) => {
264
- const flower = variables.flower;
265
- if (!flower) {
266
- throw new Error("invalid flower");
267
- }
268
- const back = {
269
- viewer: {
270
- updateLexicalFlower: {
271
- ...flower,
272
- updatedAt: (/* @__PURE__ */ new Date()).toISOString()
273
- }
274
- }
275
- };
276
- return {
277
- data: back
278
- };
279
- };
280
- var cocoreDeleteLexicalFlower = async (_ev, { variables }) => {
281
- const flower = variables.flower;
282
- if (!flower) {
283
- throw new Error("invalid flower");
284
- }
285
- const back = {
286
- viewer: {
287
- deleteLexicalFlower: flower
288
- }
289
- };
290
- return {
291
- data: back
292
- };
293
- };
294
205
  var handles = {
295
206
  coreFetchBookDrawerScreen,
296
207
  cocoreFetchBookScreen,
297
208
  coreFetchPagesApi,
298
209
  cocoreFetchPartialPageScreen,
299
- cocoreFetchPartialPageSiblingsScreen,
300
- cocoreFetchPrimaryMethod,
301
- cocoreCreateLexicalFlower,
302
- cocoreUpdateLexicalFlower,
303
- cocoreDeleteLexicalFlower
210
+ cocoreFetchPartialPageSiblingsScreen
304
211
  };
305
212
  var canHandleScreenCall = (url) => new RegExp(Object.keys(handles).join("|")).test(url);
306
213
  var handleScreenCall = async (ev, { offlineWorkerSync: offlineWorkerSync2, knownLinks: knownLinks2 }) => {
307
214
  try {
308
- let variables;
309
- const searchParamsVariables = new URLSearchParams(new URL(ev.request.url).search).get("variables");
310
- if (searchParamsVariables) {
311
- variables = JSON.parse(searchParamsVariables);
312
- } else {
313
- const body = await new Response(ev.request.body).json();
314
- variables = body.variables;
315
- }
215
+ const variables = (
216
+ // @ts-expect-error TODO: handle variables from body(stream) properly!!
217
+ ev.request.body?.variables || JSON.parse(new URLSearchParams(new URL(ev.request.url).search).get("variables") || "{}")
218
+ );
219
+ console.debug("variables are", variables, "vs", ev.request.body);
316
220
  const key = ev.request.url.match(Object.keys(handles).join("|"))?.[0];
317
- console.debug("screencall", key, "qs", variables, "vs body", ev.request.body);
318
221
  if (!key) {
319
222
  throw new Error("unknown ev");
320
223
  }
@@ -335,39 +238,17 @@ var setKnownLinks = (knownLinks2, { entryNames, bookId }) => {
335
238
  // src/worker/fetch-worker.ts
336
239
  var STORAGE = "cache";
337
240
  var CONF_ENV = "development";
338
- var fetchAsset = async (ev, { entryId, mimeType, offlineWorkerSync: offlineWorkerSync2 }) => {
241
+ var fetchAsset = async (_ev, { entryId, mimeType, offlineWorkerSync: offlineWorkerSync2 }) => {
339
242
  try {
340
- const [buf, maybeRangeHeaders] = await offlineWorkerSync2.readZipEntry(entryId).then((buf2) => {
341
- const range = ev.request.headers.get("Range");
342
- if (!ev.request.url.endsWith(".mp4") && !ev.request.url.endsWith(".webm")) {
343
- return [buf2, {}];
344
- }
345
- if (!range) {
346
- return [
347
- buf2,
348
- {
349
- "Accept-Ranges": "bytes",
350
- "Content-Range": `bytes ${0}-${buf2.byteLength}/${buf2.byteLength}`
351
- }
352
- ];
353
- }
354
- const { start, end, chunkSize } = parseRange(range, buf2.byteLength);
355
- const rangeHeaders = {
356
- "Content-Length": chunkSize,
357
- "Accept-Ranges": "bytes",
358
- "Content-Range": `bytes ${start}-${end}/${buf2.byteLength}`
359
- };
360
- return [buf2.slice(start, end + 1), rangeHeaders];
361
- });
243
+ const buf = await offlineWorkerSync2.readZipEntry(entryId);
362
244
  return new Response(buf, {
363
245
  headers: {
364
246
  "Cache-Control": "max-age=600, s-maxage=600, public, proxy-revalidate",
365
247
  "Content-Length": buf.byteLength,
366
- "Content-Type": mimeType,
367
- ...maybeRangeHeaders
248
+ "Content-Type": mimeType
368
249
  },
369
250
  // @ts-ignore: poor ts typing
370
- status: maybeRangeHeaders["Content-Range"] ? 206 : 200,
251
+ status: 200,
371
252
  statusText: "OK"
372
253
  });
373
254
  } catch (e) {
@@ -424,30 +305,23 @@ var putInCache = async (request, response) => {
424
305
  const cache = await openCache(CONF_ENV);
425
306
  await cache.put(request, response);
426
307
  };
427
- var tryOnline = async (request, event) => {
428
- const responseFromNetwork = await fetch(request);
429
- if (isValidZipName(request.url) && !isValidS3Zip(responseFromNetwork)) {
430
- throw new Error(`zip is invalid: got ${responseFromNetwork.headers.get("Content-Length")} bytes`);
431
- }
432
- const cached = request.method === "HEAD" ? Promise.resolve() : putInCache(request, responseFromNetwork.clone());
433
- if (request.url.endsWith(".zip")) {
434
- await cached;
435
- event.waitUntil(Promise.resolve());
436
- } else {
437
- event.waitUntil(cached);
438
- }
439
- return responseFromNetwork;
440
- };
441
- var tryOffline = async (request, _event) => {
442
- const over = /\/\?story=basic/.test(request.url) ? request.url.replace(/\/\?story=.*$/, "") : request;
443
- const responseFromCache = await caches.match(over);
444
- return responseFromCache;
445
- };
446
308
  var onlineFirst = async (request, event) => {
447
309
  try {
448
- return await tryOnline(request, event);
310
+ const responseFromNetwork = await fetch(request);
311
+ if (isValidZipName(request.url) && !isValidS3Zip(responseFromNetwork)) {
312
+ throw new Error(`zip is invalid: got ${responseFromNetwork.headers.get("Content-Length")} bytes`);
313
+ }
314
+ const cached = request.method === "HEAD" ? Promise.resolve() : putInCache(request, responseFromNetwork.clone());
315
+ if (request.url.endsWith(".zip")) {
316
+ await cached;
317
+ event.waitUntil(Promise.resolve());
318
+ } else {
319
+ event.waitUntil(cached);
320
+ }
321
+ return responseFromNetwork;
449
322
  } catch (e) {
450
- const responseFromCache = await tryOffline(request, event);
323
+ const over = /\/\?story=basic/.test(request.url) ? request.url.replace(/\/\?story=.*$/, "") : request;
324
+ const responseFromCache = await caches.match(over);
451
325
  if (!responseFromCache) {
452
326
  return new Response(
453
327
  `FAILED fetch ${e && typeof e === "object" && "message" in e ? e.message : e?.toString?.()}`,
@@ -469,23 +343,18 @@ swSelf.addEventListener("fetch", (ev) => {
469
343
  const extension = url.match(/\.[^.]+$/)?.[0];
470
344
  const mimeType = extension && extension in ACCEPTED_EXTENSIONS ? ACCEPTED_EXTENSIONS[extension] : "";
471
345
  const isValidScreenCall = canHandleScreenCall(url);
472
- if (url.endsWith(".zip")) {
473
- if (STORAGE === "cache") {
474
- return ev.respondWith(onlineFirst(ev.request, ev));
475
- }
346
+ if (STORAGE !== "cache" && url.endsWith(".zip")) {
476
347
  return;
477
348
  }
478
349
  if (!mimeType && !isValidScreenCall) {
479
- if (!/\.(css|tsx?|[mj]sx?|woff2|wasm|fr|(web)?manifest)(\??|$)|@(vite|react|id)|(:6019\/?$)/.test(url)) {
350
+ if (!/\.(css|tsx?|jsx?|woff2|fr|manifest)(\??|$)|@(vite|react|id)/.test(url)) {
480
351
  console.debug("no ext", extension || url);
481
352
  }
482
353
  return ev.respondWith(onlineFirst(ev.request, ev));
483
354
  }
484
- if (/http:\/\/localhost:\d+\/(favicon\.svg|assets\/)/.test(url)) {
485
- return;
486
- }
487
355
  const entryId = knownLinks.get(url.replace(/https:\/\/.*?\//, "")) || knownLinks.get(`medias/${url.replace(/https:\/\/.*?\//, "")}`);
488
356
  if (isValidScreenCall) {
357
+ console.debug("screencall!");
489
358
  return ev.respondWith(fetchScreenCall(ev, { offlineWorkerSync, knownLinks }));
490
359
  }
491
360
  if (entryId) {
@@ -494,7 +363,6 @@ swSelf.addEventListener("fetch", (ev) => {
494
363
  if (/lls|lelivrescolaire/.test(url)) {
495
364
  console.info("no link for", url.replace(/https:\/\/.*?\//, ""), `medias/${url.replace(/https:\/\/.*?\//, "")}`);
496
365
  }
497
- console.debug("unintercepted url", url);
498
366
  return;
499
367
  });
500
368
  swSelf.addEventListener("install", (_event) => {
@@ -515,10 +383,7 @@ var initChannel = async (__, { ports }) => {
515
383
  );
516
384
  offlineWorkerSync = sender;
517
385
  offlineWorker.onmessage = handler.handle;
518
- offlineWorkerSync.on("setKnownLinks", ({ entryNames, bookId, eventId }) => {
519
- setKnownLinks(knownLinks, { entryNames, bookId });
520
- offlineWorker.postMessage({ methodName: "setKnownLinks:back", eventId });
521
- });
386
+ offlineWorkerSync.on("setKnownLinks", setKnownLinks.bind(null, knownLinks));
522
387
  offlineWorker.postMessage({ methodName: "sendAppReady" });
523
388
  };
524
389
  var knownLinks = /* @__PURE__ */ new Map();
@@ -31,18 +31,7 @@ var makeSyncWorker = (offlineWorker, methodNames, dbg) => {
31
31
  return ({ ports, ...arg } = {}) => {
32
32
  return new Promise((resolve, reject) => {
33
33
  const eventId = `${methodName}:${Date.now()}-${Math.random().toFixed(5)}`;
34
- let resolved = false;
35
- const timeout = setTimeout(() => {
36
- console.warn("slow request for", methodName, arg);
37
- }, 3e3);
38
- const doResolve = (arg2) => {
39
- if (!resolved) {
40
- resolved = true;
41
- clearTimeout(timeout);
42
- resolve(arg2);
43
- }
44
- };
45
- dic[eventId] = { resolve: doResolve, reject };
34
+ dic[eventId] = { resolve, reject };
46
35
  offlineWorker.postMessage({ eventId, methodName, arg }, ports);
47
36
  });
48
37
  };
@@ -95,6 +84,16 @@ var combineHandlers = (...handlers) => {
95
84
  };
96
85
  };
97
86
  var openCache = async (mode) => caches.open(`LLS_OFFLINE_${mode}`);
87
+ var concatArrayBuffers = (buffers) => {
88
+ const totalLength = buffers.reduce((sum, buf) => sum + buf.byteLength, 0);
89
+ const concatenated = new Uint8Array(totalLength);
90
+ let offset = 0;
91
+ for (const buffer of buffers) {
92
+ concatenated.set(new Uint8Array(buffer), offset);
93
+ offset += buffer.byteLength;
94
+ }
95
+ return concatenated.buffer;
96
+ };
98
97
  var isStoryZip = (name) => /story-.*?\.zip/.test(name);
99
98
  var isValidZipName = (name) => {
100
99
  return /lecture-cp\.zip/.test(name) || isStoryZip(name);
@@ -171,72 +170,615 @@ var loadPreload = (json) => {
171
170
  });
172
171
  };
173
172
 
174
- // src/utils/zipDecoder.ts
175
- var getEOCDStart = (buf) => {
176
- for (let i = buf.length - 1; i > 0; --i) {
177
- if (buf[i] === 6) {
178
- if (buf[i - 1] === 5) {
179
- if (buf[i - 2] === 75) {
180
- if (buf[i - 3] === 80) {
181
- return i - 3;
182
- }
173
+ // ../../node_modules/.pnpm/fflate@0.8.2/node_modules/fflate/esm/browser.js
174
+ var u8 = Uint8Array;
175
+ var u16 = Uint16Array;
176
+ var i32 = Int32Array;
177
+ var fleb = new u8([
178
+ 0,
179
+ 0,
180
+ 0,
181
+ 0,
182
+ 0,
183
+ 0,
184
+ 0,
185
+ 0,
186
+ 1,
187
+ 1,
188
+ 1,
189
+ 1,
190
+ 2,
191
+ 2,
192
+ 2,
193
+ 2,
194
+ 3,
195
+ 3,
196
+ 3,
197
+ 3,
198
+ 4,
199
+ 4,
200
+ 4,
201
+ 4,
202
+ 5,
203
+ 5,
204
+ 5,
205
+ 5,
206
+ 0,
207
+ /* unused */
208
+ 0,
209
+ 0,
210
+ /* impossible */
211
+ 0
212
+ ]);
213
+ var fdeb = new u8([
214
+ 0,
215
+ 0,
216
+ 0,
217
+ 0,
218
+ 1,
219
+ 1,
220
+ 2,
221
+ 2,
222
+ 3,
223
+ 3,
224
+ 4,
225
+ 4,
226
+ 5,
227
+ 5,
228
+ 6,
229
+ 6,
230
+ 7,
231
+ 7,
232
+ 8,
233
+ 8,
234
+ 9,
235
+ 9,
236
+ 10,
237
+ 10,
238
+ 11,
239
+ 11,
240
+ 12,
241
+ 12,
242
+ 13,
243
+ 13,
244
+ /* unused */
245
+ 0,
246
+ 0
247
+ ]);
248
+ var clim = new u8([16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15]);
249
+ var freb = function(eb, start) {
250
+ var b = new u16(31);
251
+ for (var i = 0; i < 31; ++i) {
252
+ b[i] = start += 1 << eb[i - 1];
253
+ }
254
+ var r = new i32(b[30]);
255
+ for (var i = 1; i < 30; ++i) {
256
+ for (var j = b[i]; j < b[i + 1]; ++j) {
257
+ r[j] = j - b[i] << 5 | i;
258
+ }
259
+ }
260
+ return { b, r };
261
+ };
262
+ var _a = freb(fleb, 2);
263
+ var fl = _a.b;
264
+ var revfl = _a.r;
265
+ fl[28] = 258, revfl[258] = 28;
266
+ var _b = freb(fdeb, 0);
267
+ var fd = _b.b;
268
+ var revfd = _b.r;
269
+ var rev = new u16(32768);
270
+ for (i = 0; i < 32768; ++i) {
271
+ x = (i & 43690) >> 1 | (i & 21845) << 1;
272
+ x = (x & 52428) >> 2 | (x & 13107) << 2;
273
+ x = (x & 61680) >> 4 | (x & 3855) << 4;
274
+ rev[i] = ((x & 65280) >> 8 | (x & 255) << 8) >> 1;
275
+ }
276
+ var x;
277
+ var i;
278
+ var hMap = function(cd, mb, r) {
279
+ var s = cd.length;
280
+ var i = 0;
281
+ var l = new u16(mb);
282
+ for (; i < s; ++i) {
283
+ if (cd[i])
284
+ ++l[cd[i] - 1];
285
+ }
286
+ var le = new u16(mb);
287
+ for (i = 1; i < mb; ++i) {
288
+ le[i] = le[i - 1] + l[i - 1] << 1;
289
+ }
290
+ var co;
291
+ if (r) {
292
+ co = new u16(1 << mb);
293
+ var rvb = 15 - mb;
294
+ for (i = 0; i < s; ++i) {
295
+ if (cd[i]) {
296
+ var sv = i << 4 | cd[i];
297
+ var r_1 = mb - cd[i];
298
+ var v = le[cd[i] - 1]++ << r_1;
299
+ for (var m = v | (1 << r_1) - 1; v <= m; ++v) {
300
+ co[rev[v] >> rvb] = sv;
183
301
  }
184
302
  }
185
303
  }
304
+ } else {
305
+ co = new u16(s);
306
+ for (i = 0; i < s; ++i) {
307
+ if (cd[i]) {
308
+ co[i] = rev[le[cd[i] - 1]++] >> 15 - cd[i];
309
+ }
310
+ }
186
311
  }
187
- throw new Error("failed to read EOCDstart");
312
+ return co;
188
313
  };
189
- var readIndex = (buf, offset, nBytes) => {
190
- let idx = 0;
191
- for (let i = 0; i < nBytes; ++i) {
192
- const next = buf[offset + i] * 256 ** i;
193
- idx += next;
194
- }
195
- return idx;
196
- };
197
- var getSOCDStart = (buf, eocdIdx) => {
198
- return readIndex(buf, eocdIdx + 16, 4);
199
- };
200
- var readEntryNames = (buf, socdIdx, nRecords) => {
201
- const records = Array.from({ length: nRecords });
202
- for (let i = 0; i < nRecords; ++i) {
203
- const n = readIndex(buf, socdIdx + 28, 2);
204
- const m = readIndex(buf, socdIdx + 30, 2);
205
- const k = readIndex(buf, socdIdx + 32, 2);
206
- records[i] = {
207
- sofh: readIndex(buf, socdIdx + 42, 4),
208
- name: buf.slice(socdIdx + 46, socdIdx + 46 + n)
209
- };
210
- socdIdx += 46 + n + m + k;
314
+ var flt = new u8(288);
315
+ for (i = 0; i < 144; ++i)
316
+ flt[i] = 8;
317
+ var i;
318
+ for (i = 144; i < 256; ++i)
319
+ flt[i] = 9;
320
+ var i;
321
+ for (i = 256; i < 280; ++i)
322
+ flt[i] = 7;
323
+ var i;
324
+ for (i = 280; i < 288; ++i)
325
+ flt[i] = 8;
326
+ var i;
327
+ var fdt = new u8(32);
328
+ for (i = 0; i < 32; ++i)
329
+ fdt[i] = 5;
330
+ var i;
331
+ var flrm = /* @__PURE__ */ hMap(flt, 9, 1);
332
+ var fdrm = /* @__PURE__ */ hMap(fdt, 5, 1);
333
+ var max = function(a2) {
334
+ var m = a2[0];
335
+ for (var i = 1; i < a2.length; ++i) {
336
+ if (a2[i] > m)
337
+ m = a2[i];
211
338
  }
212
- return records;
339
+ return m;
340
+ };
341
+ var bits = function(d, p, m) {
342
+ var o = p / 8 | 0;
343
+ return (d[o] | d[o + 1] << 8) >> (p & 7) & m;
344
+ };
345
+ var bits16 = function(d, p) {
346
+ var o = p / 8 | 0;
347
+ return (d[o] | d[o + 1] << 8 | d[o + 2] << 16) >> (p & 7);
213
348
  };
214
- var readRecordData = (buf, { sofh }) => {
215
- const dataSize = readIndex(buf, sofh + 22, 4);
216
- const n = readIndex(buf, sofh + 26, 2);
217
- const m = readIndex(buf, sofh + 28, 2);
218
- return buf.slice(sofh + 30 + n + m, sofh + 30 + n + m + dataSize);
349
+ var shft = function(p) {
350
+ return (p + 7) / 8 | 0;
219
351
  };
220
- var getHeaders = (buf) => {
221
- const eocdIdx = getEOCDStart(buf);
222
- const nbRecords = readIndex(buf, eocdIdx + 10, 2);
223
- const socdIdx = getSOCDStart(buf, eocdIdx);
224
- const records = readEntryNames(buf, socdIdx, nbRecords);
225
- return records;
352
+ var slc = function(v, s, e) {
353
+ if (s == null || s < 0)
354
+ s = 0;
355
+ if (e == null || e > v.length)
356
+ e = v.length;
357
+ return new u8(v.subarray(s, e));
226
358
  };
359
+ var ec = [
360
+ "unexpected EOF",
361
+ "invalid block type",
362
+ "invalid length/literal",
363
+ "invalid distance",
364
+ "stream finished",
365
+ "no stream handler",
366
+ ,
367
+ "no callback",
368
+ "invalid UTF-8 data",
369
+ "extra field too long",
370
+ "date not in range 1980-2099",
371
+ "filename too long",
372
+ "stream finishing",
373
+ "invalid zip data"
374
+ // determined by unknown compression method
375
+ ];
376
+ var err = function(ind, msg, nt) {
377
+ var e = new Error(msg || ec[ind]);
378
+ e.code = ind;
379
+ if (Error.captureStackTrace)
380
+ Error.captureStackTrace(e, err);
381
+ if (!nt)
382
+ throw e;
383
+ return e;
384
+ };
385
+ var inflt = function(dat, st, buf, dict) {
386
+ var sl = dat.length, dl = dict ? dict.length : 0;
387
+ if (!sl || st.f && !st.l)
388
+ return buf || new u8(0);
389
+ var noBuf = !buf;
390
+ var resize = noBuf || st.i != 2;
391
+ var noSt = st.i;
392
+ if (noBuf)
393
+ buf = new u8(sl * 3);
394
+ var cbuf = function(l2) {
395
+ var bl = buf.length;
396
+ if (l2 > bl) {
397
+ var nbuf = new u8(Math.max(bl * 2, l2));
398
+ nbuf.set(buf);
399
+ buf = nbuf;
400
+ }
401
+ };
402
+ var final = st.f || 0, pos = st.p || 0, bt = st.b || 0, lm = st.l, dm = st.d, lbt = st.m, dbt = st.n;
403
+ var tbts = sl * 8;
404
+ do {
405
+ if (!lm) {
406
+ final = bits(dat, pos, 1);
407
+ var type = bits(dat, pos + 1, 3);
408
+ pos += 3;
409
+ if (!type) {
410
+ var s = shft(pos) + 4, l = dat[s - 4] | dat[s - 3] << 8, t = s + l;
411
+ if (t > sl) {
412
+ if (noSt)
413
+ err(0);
414
+ break;
415
+ }
416
+ if (resize)
417
+ cbuf(bt + l);
418
+ buf.set(dat.subarray(s, t), bt);
419
+ st.b = bt += l, st.p = pos = t * 8, st.f = final;
420
+ continue;
421
+ } else if (type == 1)
422
+ lm = flrm, dm = fdrm, lbt = 9, dbt = 5;
423
+ else if (type == 2) {
424
+ var hLit = bits(dat, pos, 31) + 257, hcLen = bits(dat, pos + 10, 15) + 4;
425
+ var tl = hLit + bits(dat, pos + 5, 31) + 1;
426
+ pos += 14;
427
+ var ldt = new u8(tl);
428
+ var clt = new u8(19);
429
+ for (var i = 0; i < hcLen; ++i) {
430
+ clt[clim[i]] = bits(dat, pos + i * 3, 7);
431
+ }
432
+ pos += hcLen * 3;
433
+ var clb = max(clt), clbmsk = (1 << clb) - 1;
434
+ var clm = hMap(clt, clb, 1);
435
+ for (var i = 0; i < tl; ) {
436
+ var r = clm[bits(dat, pos, clbmsk)];
437
+ pos += r & 15;
438
+ var s = r >> 4;
439
+ if (s < 16) {
440
+ ldt[i++] = s;
441
+ } else {
442
+ var c = 0, n = 0;
443
+ if (s == 16)
444
+ n = 3 + bits(dat, pos, 3), pos += 2, c = ldt[i - 1];
445
+ else if (s == 17)
446
+ n = 3 + bits(dat, pos, 7), pos += 3;
447
+ else if (s == 18)
448
+ n = 11 + bits(dat, pos, 127), pos += 7;
449
+ while (n--)
450
+ ldt[i++] = c;
451
+ }
452
+ }
453
+ var lt = ldt.subarray(0, hLit), dt = ldt.subarray(hLit);
454
+ lbt = max(lt);
455
+ dbt = max(dt);
456
+ lm = hMap(lt, lbt, 1);
457
+ dm = hMap(dt, dbt, 1);
458
+ } else
459
+ err(1);
460
+ if (pos > tbts) {
461
+ if (noSt)
462
+ err(0);
463
+ break;
464
+ }
465
+ }
466
+ if (resize)
467
+ cbuf(bt + 131072);
468
+ var lms = (1 << lbt) - 1, dms = (1 << dbt) - 1;
469
+ var lpos = pos;
470
+ for (; ; lpos = pos) {
471
+ var c = lm[bits16(dat, pos) & lms], sym = c >> 4;
472
+ pos += c & 15;
473
+ if (pos > tbts) {
474
+ if (noSt)
475
+ err(0);
476
+ break;
477
+ }
478
+ if (!c)
479
+ err(2);
480
+ if (sym < 256)
481
+ buf[bt++] = sym;
482
+ else if (sym == 256) {
483
+ lpos = pos, lm = null;
484
+ break;
485
+ } else {
486
+ var add = sym - 254;
487
+ if (sym > 264) {
488
+ var i = sym - 257, b = fleb[i];
489
+ add = bits(dat, pos, (1 << b) - 1) + fl[i];
490
+ pos += b;
491
+ }
492
+ var d = dm[bits16(dat, pos) & dms], dsym = d >> 4;
493
+ if (!d)
494
+ err(3);
495
+ pos += d & 15;
496
+ var dt = fd[dsym];
497
+ if (dsym > 3) {
498
+ var b = fdeb[dsym];
499
+ dt += bits16(dat, pos) & (1 << b) - 1, pos += b;
500
+ }
501
+ if (pos > tbts) {
502
+ if (noSt)
503
+ err(0);
504
+ break;
505
+ }
506
+ if (resize)
507
+ cbuf(bt + 131072);
508
+ var end = bt + add;
509
+ if (bt < dt) {
510
+ var shift = dl - dt, dend = Math.min(dt, end);
511
+ if (shift + bt < 0)
512
+ err(3);
513
+ for (; bt < dend; ++bt)
514
+ buf[bt] = dict[shift + bt];
515
+ }
516
+ for (; bt < end; ++bt)
517
+ buf[bt] = buf[bt - dt];
518
+ }
519
+ }
520
+ st.l = lm, st.p = lpos, st.b = bt, st.f = final;
521
+ if (lm)
522
+ final = 1, st.m = lbt, st.d = dm, st.n = dbt;
523
+ } while (!final);
524
+ return bt != buf.length && noBuf ? slc(buf, 0, bt) : buf.subarray(0, bt);
525
+ };
526
+ var et = /* @__PURE__ */ new u8(0);
527
+ var b2 = function(d, b) {
528
+ return d[b] | d[b + 1] << 8;
529
+ };
530
+ var b4 = function(d, b) {
531
+ return (d[b] | d[b + 1] << 8 | d[b + 2] << 16 | d[b + 3] << 24) >>> 0;
532
+ };
533
+ var b8 = function(d, b) {
534
+ return b4(d, b) + b4(d, b + 4) * 4294967296;
535
+ };
536
+ var Inflate = /* @__PURE__ */ function() {
537
+ function Inflate2(opts, cb) {
538
+ if (typeof opts == "function")
539
+ cb = opts, opts = {};
540
+ this.ondata = cb;
541
+ var dict = opts && opts.dictionary && opts.dictionary.subarray(-32768);
542
+ this.s = { i: 0, b: dict ? dict.length : 0 };
543
+ this.o = new u8(32768);
544
+ this.p = new u8(0);
545
+ if (dict)
546
+ this.o.set(dict);
547
+ }
548
+ Inflate2.prototype.e = function(c) {
549
+ if (!this.ondata)
550
+ err(5);
551
+ if (this.d)
552
+ err(4);
553
+ if (!this.p.length)
554
+ this.p = c;
555
+ else if (c.length) {
556
+ var n = new u8(this.p.length + c.length);
557
+ n.set(this.p), n.set(c, this.p.length), this.p = n;
558
+ }
559
+ };
560
+ Inflate2.prototype.c = function(final) {
561
+ this.s.i = +(this.d = final || false);
562
+ var bts = this.s.b;
563
+ var dt = inflt(this.p, this.s, this.o);
564
+ this.ondata(slc(dt, bts, this.s.b), this.d);
565
+ this.o = slc(dt, this.s.b - 32768), this.s.b = this.o.length;
566
+ this.p = slc(this.p, this.s.p / 8 | 0), this.s.p &= 7;
567
+ };
568
+ Inflate2.prototype.push = function(chunk, final) {
569
+ this.e(chunk), this.c(final);
570
+ };
571
+ return Inflate2;
572
+ }();
573
+ var td = typeof TextDecoder != "undefined" && /* @__PURE__ */ new TextDecoder();
574
+ var tds = 0;
575
+ try {
576
+ td.decode(et, { stream: true });
577
+ tds = 1;
578
+ } catch (e) {
579
+ }
580
+ var dutf8 = function(d) {
581
+ for (var r = "", i = 0; ; ) {
582
+ var c = d[i++];
583
+ var eb = (c > 127) + (c > 223) + (c > 239);
584
+ if (i + eb > d.length)
585
+ return { s: r, r: slc(d, i - 1) };
586
+ if (!eb)
587
+ r += String.fromCharCode(c);
588
+ else if (eb == 3) {
589
+ c = ((c & 15) << 18 | (d[i++] & 63) << 12 | (d[i++] & 63) << 6 | d[i++] & 63) - 65536, r += String.fromCharCode(55296 | c >> 10, 56320 | c & 1023);
590
+ } else if (eb & 1)
591
+ r += String.fromCharCode((c & 31) << 6 | d[i++] & 63);
592
+ else
593
+ r += String.fromCharCode((c & 15) << 12 | (d[i++] & 63) << 6 | d[i++] & 63);
594
+ }
595
+ };
596
+ function strFromU8(dat, latin1) {
597
+ if (latin1) {
598
+ var r = "";
599
+ for (var i = 0; i < dat.length; i += 16384)
600
+ r += String.fromCharCode.apply(null, dat.subarray(i, i + 16384));
601
+ return r;
602
+ } else if (td) {
603
+ return td.decode(dat);
604
+ } else {
605
+ var _a2 = dutf8(dat), s = _a2.s, r = _a2.r;
606
+ if (r.length)
607
+ err(8);
608
+ return s;
609
+ }
610
+ }
611
+ var z64e = function(d, b) {
612
+ for (; b2(d, b) != 1; b += 4 + b2(d, b + 2))
613
+ ;
614
+ return [b8(d, b + 12), b8(d, b + 4), b8(d, b + 20)];
615
+ };
616
+ var UnzipPassThrough = /* @__PURE__ */ function() {
617
+ function UnzipPassThrough2() {
618
+ }
619
+ UnzipPassThrough2.prototype.push = function(data, final) {
620
+ this.ondata(null, data, final);
621
+ };
622
+ UnzipPassThrough2.compression = 0;
623
+ return UnzipPassThrough2;
624
+ }();
625
+ var UnzipInflate = /* @__PURE__ */ function() {
626
+ function UnzipInflate2() {
627
+ var _this = this;
628
+ this.i = new Inflate(function(dat, final) {
629
+ _this.ondata(null, dat, final);
630
+ });
631
+ }
632
+ UnzipInflate2.prototype.push = function(data, final) {
633
+ try {
634
+ this.i.push(data, final);
635
+ } catch (e) {
636
+ this.ondata(e, null, final);
637
+ }
638
+ };
639
+ UnzipInflate2.compression = 8;
640
+ return UnzipInflate2;
641
+ }();
642
+ var Unzip = /* @__PURE__ */ function() {
643
+ function Unzip2(cb) {
644
+ this.onfile = cb;
645
+ this.k = [];
646
+ this.o = {
647
+ 0: UnzipPassThrough
648
+ };
649
+ this.p = et;
650
+ }
651
+ Unzip2.prototype.push = function(chunk, final) {
652
+ var _this = this;
653
+ if (!this.onfile)
654
+ err(5);
655
+ if (!this.p)
656
+ err(4);
657
+ if (this.c > 0) {
658
+ var len = Math.min(this.c, chunk.length);
659
+ var toAdd = chunk.subarray(0, len);
660
+ this.c -= len;
661
+ if (this.d)
662
+ this.d.push(toAdd, !this.c);
663
+ else
664
+ this.k[0].push(toAdd);
665
+ chunk = chunk.subarray(len);
666
+ if (chunk.length)
667
+ return this.push(chunk, final);
668
+ } else {
669
+ var f = 0, i = 0, is = void 0, buf = void 0;
670
+ if (!this.p.length)
671
+ buf = chunk;
672
+ else if (!chunk.length)
673
+ buf = this.p;
674
+ else {
675
+ buf = new u8(this.p.length + chunk.length);
676
+ buf.set(this.p), buf.set(chunk, this.p.length);
677
+ }
678
+ var l = buf.length, oc = this.c, add = oc && this.d;
679
+ var _loop_2 = function() {
680
+ var _a2;
681
+ var sig = b4(buf, i);
682
+ if (sig == 67324752) {
683
+ f = 1, is = i;
684
+ this_1.d = null;
685
+ this_1.c = 0;
686
+ var bf = b2(buf, i + 6), cmp_1 = b2(buf, i + 8), u = bf & 2048, dd = bf & 8, fnl = b2(buf, i + 26), es = b2(buf, i + 28);
687
+ if (l > i + 30 + fnl + es) {
688
+ var chks_3 = [];
689
+ this_1.k.unshift(chks_3);
690
+ f = 2;
691
+ var sc_1 = b4(buf, i + 18), su_1 = b4(buf, i + 22);
692
+ var fn_1 = strFromU8(buf.subarray(i + 30, i += 30 + fnl), !u);
693
+ if (sc_1 == 4294967295) {
694
+ _a2 = dd ? [-2] : z64e(buf, i), sc_1 = _a2[0], su_1 = _a2[1];
695
+ } else if (dd)
696
+ sc_1 = -1;
697
+ i += es;
698
+ this_1.c = sc_1;
699
+ var d_1;
700
+ var file_1 = {
701
+ name: fn_1,
702
+ compression: cmp_1,
703
+ start: function() {
704
+ if (!file_1.ondata)
705
+ err(5);
706
+ if (!sc_1)
707
+ file_1.ondata(null, et, true);
708
+ else {
709
+ var ctr = _this.o[cmp_1];
710
+ if (!ctr)
711
+ file_1.ondata(err(14, "unknown compression type " + cmp_1, 1), null, false);
712
+ d_1 = sc_1 < 0 ? new ctr(fn_1) : new ctr(fn_1, sc_1, su_1);
713
+ d_1.ondata = function(err2, dat3, final2) {
714
+ file_1.ondata(err2, dat3, final2);
715
+ };
716
+ for (var _i = 0, chks_4 = chks_3; _i < chks_4.length; _i++) {
717
+ var dat2 = chks_4[_i];
718
+ d_1.push(dat2, false);
719
+ }
720
+ if (_this.k[0] == chks_3 && _this.c)
721
+ _this.d = d_1;
722
+ else
723
+ d_1.push(et, true);
724
+ }
725
+ },
726
+ terminate: function() {
727
+ if (d_1 && d_1.terminate)
728
+ d_1.terminate();
729
+ }
730
+ };
731
+ if (sc_1 >= 0)
732
+ file_1.size = sc_1, file_1.originalSize = su_1;
733
+ this_1.onfile(file_1);
734
+ }
735
+ return "break";
736
+ } else if (oc) {
737
+ if (sig == 134695760) {
738
+ is = i += 12 + (oc == -2 && 8), f = 3, this_1.c = 0;
739
+ return "break";
740
+ } else if (sig == 33639248) {
741
+ is = i -= 4, f = 3, this_1.c = 0;
742
+ return "break";
743
+ }
744
+ }
745
+ };
746
+ var this_1 = this;
747
+ for (; i < l - 4; ++i) {
748
+ var state_1 = _loop_2();
749
+ if (state_1 === "break")
750
+ break;
751
+ }
752
+ this.p = et;
753
+ if (oc < 0) {
754
+ var dat = f ? buf.subarray(0, is - 12 - (oc == -2 && 8) - (b4(buf, is - 16) == 134695760 && 4)) : buf.subarray(0, i);
755
+ if (add)
756
+ add.push(dat, !!f);
757
+ else
758
+ this.k[+(f == 2)].push(dat);
759
+ }
760
+ if (f & 2)
761
+ return this.push(buf.subarray(i), final);
762
+ this.p = buf.subarray(i);
763
+ }
764
+ if (final) {
765
+ if (this.c)
766
+ err(13);
767
+ this.p = null;
768
+ }
769
+ };
770
+ Unzip2.prototype.register = function(decoder) {
771
+ this.o[decoder.compression] = decoder;
772
+ };
773
+ return Unzip2;
774
+ }();
227
775
 
228
776
  // src/worker/wwZip.ts
229
777
  var key = new Uint8Array([..."4c6520636f6e74656e7520646573206c".matchAll(/../g)].map(([c]) => Number(`0x${c}`)));
230
778
  var iv = new Uint8Array(16).fill(0);
231
779
  async function decryptData(encryptedData, key2, iv2) {
232
- const cryptoKey = await crypto.subtle.importKey("raw", key2.buffer, { name: "AES-CBC" }, false, [
233
- "decrypt"
234
- ]);
235
- const decryptedData = await crypto.subtle.decrypt(
236
- { name: "AES-CBC", iv: iv2.buffer },
237
- cryptoKey,
238
- encryptedData
239
- );
780
+ const cryptoKey = await crypto.subtle.importKey("raw", key2.buffer, { name: "AES-CBC" }, false, ["decrypt"]);
781
+ const decryptedData = await crypto.subtle.decrypt({ name: "AES-CBC", iv: iv2.buffer }, cryptoKey, encryptedData);
240
782
  return decryptedData;
241
783
  }
242
784
  var BOOKS = {};
@@ -260,14 +802,12 @@ var readZipEntry = async ({
260
802
  const originalName = manifest.medias[zipName];
261
803
  overridenName = `medias/${originalName}`;
262
804
  } else {
263
- if (entryName !== "manifest.json") {
264
- console.error("any media should exist in manifest", zipName, entryName, bookId);
265
- }
805
+ console.error("any media should exist in manifest", zipName, entryName, bookId);
266
806
  }
267
807
  }
268
808
  const bookEntry = BOOKS[bookId].map.get(overridenName);
269
809
  if (!bookEntry) {
270
- console.info("no bookEntry", entryName, "overridingName:", overridenName, "for book", bookId);
810
+ console.info("no bookEntry", entryName, "found", overridenName);
271
811
  return null;
272
812
  }
273
813
  if (!bookEntry.decoded) {
@@ -280,19 +820,43 @@ var hasZip = (bookId) => {
280
820
  };
281
821
  var loadZip = async (buf, bookId) => {
282
822
  const m = /* @__PURE__ */ new Map();
283
- const headers = getHeaders(buf);
284
- for (const header of headers) {
285
- const name = new TextDecoder().decode(header.name);
286
- if (!name.includes(".")) {
287
- continue;
823
+ const unzipper = new Unzip();
824
+ unzipper.register(UnzipInflate);
825
+ unzipper.onfile = (file) => {
826
+ if (!file.name.includes(".")) {
827
+ return;
288
828
  }
289
- m.set(name, {
829
+ m.set(file.name, {
290
830
  decoded: null,
291
831
  zipEntry: {
292
- getData: async () => readRecordData(buf, header).buffer
832
+ getData: () => {
833
+ return new Promise((resolve) => {
834
+ const buffers = [];
835
+ file.ondata = (err2, data, final) => {
836
+ if (err2) {
837
+ console.error("failed to read zip data", file.name, err2);
838
+ }
839
+ if (data.byteLength) {
840
+ buffers.push(data);
841
+ }
842
+ if (final) {
843
+ return resolve(concatArrayBuffers(buffers));
844
+ }
845
+ };
846
+ file.start();
847
+ });
848
+ }
293
849
  }
294
850
  });
851
+ };
852
+ const chunkSize = 32 * 1024 * 1024;
853
+ const nChunks = Math.max(1, Math.floor(buf.byteLength / chunkSize));
854
+ const sleep = new Promise((resolve) => setTimeout(resolve, 0));
855
+ for (let i = 0; i < nChunks - 1; ++i) {
856
+ unzipper.push(buf.slice(i * chunkSize, (i + 1) * chunkSize));
857
+ await sleep;
295
858
  }
859
+ unzipper.push(buf.slice((nChunks - 1) * chunkSize, buf.byteLength), true);
296
860
  BOOKS[bookId] = {
297
861
  map: m,
298
862
  manifest: null
@@ -322,8 +886,7 @@ var fetchZipFile = async (zipUrl, { forceRefresh } = {}) => {
322
886
  return back;
323
887
  }
324
888
  if (STORAGE === "cache") {
325
- const cache = await openCache(CONF_ENV);
326
- const response = await cache.match(zipUrl);
889
+ const response = await caches.match(zipUrl);
327
890
  if (!response) {
328
891
  throw new Error(`missing zip ${zipUrl}`);
329
892
  }
@@ -347,11 +910,7 @@ var fetchZipFile = async (zipUrl, { forceRefresh } = {}) => {
347
910
  const buf = await readArrayBuffer();
348
911
  if (CHECK_UPDATES) {
349
912
  const response = await fetch(zipUrl, { method: "HEAD" });
350
- let remoteSize = Number.parseInt(response.headers.get("content-length") ?? "");
351
- if (!remoteSize) {
352
- console.info("remoteSize not found. will skip update. Is the server up at", zipUrl);
353
- remoteSize = buf.byteLength;
354
- }
913
+ const remoteSize = Number.parseInt(response.headers.get("content-length") || "0", 10);
355
914
  if (remoteSize !== buf.byteLength) {
356
915
  const error = `new ${fileName} available, refetching (opfs:${buf.byteLength} vs remote:${remoteSize})`;
357
916
  console.debug(error);
@@ -359,7 +918,6 @@ var fetchZipFile = async (zipUrl, { forceRefresh } = {}) => {
359
918
  throw new Error(`new ${fileName} available, refetching`);
360
919
  }
361
920
  }
362
- self.postMessage({ methodName: "opfsProgress", arg: { total: buf.byteLength, bytes: buf.byteLength } });
363
921
  return buf;
364
922
  } catch (e) {
365
923
  if (e instanceof Error && e.message !== "forceRefresh" && !e.message.includes("refetching")) {
@@ -389,7 +947,6 @@ var fetchZipFile = async (zipUrl, { forceRefresh } = {}) => {
389
947
  self.postMessage({ methodName: "opfsProgress", arg: { total: contentLength, bytes: position } });
390
948
  }
391
949
  }
392
- console.debug("zip loaded:", arrayBuffer.byteLength);
393
950
  if (STORAGE === "native") {
394
951
  await sender.nativeWriteFile({ fname: fileName, buffer: arrayBuffer });
395
952
  } else if (STORAGE === "opfs") {
@@ -434,15 +991,8 @@ var loadBook2 = async ({ id: bookId, forceRefresh }) => {
434
991
  tryCatch(async () => {
435
992
  const buf = await fetchZipFile(`${ZIP_BASE_URL}/${bookId}.zip`, { forceRefresh });
436
993
  try {
437
- console.time("loadzip");
438
994
  const entryNames = await loadZip(new Uint8Array(buf), bookId);
439
- console.timeEnd("loadzip");
440
- const eventId = `setKnownLinks:${Date.now()}-${Math.random().toFixed(5)}`;
441
- const responseForEventId = new Promise((resolve, reject) => {
442
- dicFetchWorkerCallback[eventId] = { resolve, reject };
443
- });
444
- fetchWorker.postMessage({ methodName: "setKnownLinks", arg: { entryNames, bookId, eventId } });
445
- await responseForEventId;
995
+ fetchWorker.postMessage({ methodName: "setKnownLinks", arg: { entryNames, bookId } });
446
996
  if (isOldZip(bookId)) {
447
997
  const json = await readZipEntry({
448
998
  entryName: `preload/${bookId}.json`,
@@ -450,13 +1000,6 @@ var loadBook2 = async ({ id: bookId, forceRefresh }) => {
450
1000
  asJson: true
451
1001
  });
452
1002
  loadBook(json);
453
- } else {
454
- try {
455
- const { createdAt } = await readZipEntry({ bookId, entryName: "manifest.json", asJson: true });
456
- console.debug("zipversion", createdAt);
457
- } catch (e) {
458
- console.debug("failed to read manifest.json", e);
459
- }
460
1003
  }
461
1004
  return true;
462
1005
  } catch (e) {
@@ -486,14 +1029,6 @@ var loadPageContent2 = async ({
486
1029
  return await loadPageContent({ chapterId, json });
487
1030
  };
488
1031
  var fetchWorker;
489
- var dicFetchWorkerCallback = {};
490
- var handleFetchWorkerCallback = ({ data: { eventId } }) => {
491
- if (dicFetchWorkerCallback[eventId]) {
492
- dicFetchWorkerCallback[eventId].resolve();
493
- } else {
494
- console.debug("unknown eventId", eventId);
495
- }
496
- };
497
1032
  var initChannel = (__, { ports }) => {
498
1033
  fetchWorker = ports[0];
499
1034
  const { canHandle, handle } = makeSyncHandler(fetchWorker, {
@@ -508,14 +1043,6 @@ var initChannel = (__, { ports }) => {
508
1043
  self.postMessage({ methodName: "ready" });
509
1044
  return;
510
1045
  }
511
- if (dataObj.data?.methodName === "setKnownLinks:back") {
512
- if (typeof dataObj?.data?.eventId !== "string") {
513
- console.debug("missing eventId to get response back for setKnownLinks:back");
514
- return;
515
- }
516
- handleFetchWorkerCallback(dataObj);
517
- return;
518
- }
519
1046
  if (canHandle(dataObj.data?.methodName || "")) {
520
1047
  return handle(dataObj);
521
1048
  }
@@ -589,18 +1116,13 @@ var loadPreload2 = async () => {
589
1116
  console.error("failed to load preload", e);
590
1117
  }
591
1118
  };
592
- var reset = async () => {
593
- await (await navigator.storage.getDirectory()).remove({ recursive: true });
594
- console.info("opfs cleared");
595
- };
596
1119
  var mainHandle = makeSyncHandler(self, {
597
1120
  initChannel,
598
1121
  loadPreload: loadPreload2,
599
1122
  readZipEntry,
600
1123
  loadBooks,
601
1124
  loadBook: loadBook2,
602
- configure,
603
- reset
1125
+ configure
604
1126
  });
605
1127
  var { handler, ...sender } = makeSyncWorker(self, ["nativeWriteFile", "nativeReadFile", "nativeListZips"]);
606
1128
  self.onmessage = combineHandlers(mainHandle, handler);
package/lib/index.js CHANGED
@@ -31,18 +31,7 @@ var makeSyncWorker = (offlineWorker2, methodNames, dbg) => {
31
31
  return ({ ports, ...arg } = {}) => {
32
32
  return new Promise((resolve, reject) => {
33
33
  const eventId = `${methodName}:${Date.now()}-${Math.random().toFixed(5)}`;
34
- let resolved = false;
35
- const timeout = setTimeout(() => {
36
- console.warn("slow request for", methodName, arg);
37
- }, 3e3);
38
- const doResolve = (arg2) => {
39
- if (!resolved) {
40
- resolved = true;
41
- clearTimeout(timeout);
42
- resolve(arg2);
43
- }
44
- };
45
- dic[eventId] = { resolve: doResolve, reject };
34
+ dic[eventId] = { resolve, reject };
46
35
  offlineWorker2.postMessage({ eventId, methodName, arg }, ports);
47
36
  });
48
37
  };
@@ -93,14 +82,13 @@ var combineHandlers = (...handlers) => {
93
82
  console.error("no handlers matched", methodName);
94
83
  };
95
84
  };
96
- var clearCache = async (mode) => caches.delete(`LLS_OFFLINE_${mode}`);
97
85
 
98
86
  // src/hooks/useOfflineWorker.ts
99
87
  import { useCallback, useEffect, useState } from "react";
100
88
  var offlineWorker = new Worker("/src/worker/offline-worker.js", { type: "module" });
101
89
  var { handler, ...offlineWorkerSync } = makeSyncWorker(
102
90
  offlineWorker,
103
- ["initChannel", "readZipEntry", "configure", "loadPreload", "loadBooks", "loadBook", "reset"],
91
+ ["initChannel", "readZipEntry", "configure", "loadPreload", "loadBooks", "loadBook"],
104
92
  "app:offlineWorker"
105
93
  );
106
94
  var fetchWorkerPromise = new Promise(
@@ -172,7 +160,6 @@ var installWorker = async ({
172
160
  setBooksLoaded();
173
161
  };
174
162
  var useOfflineWorker_default = ({
175
- skipLoadBooks,
176
163
  primaryOnly = false,
177
164
  nativeReadFile,
178
165
  nativeWriteFile,
@@ -186,7 +173,6 @@ var useOfflineWorker_default = ({
186
173
  useEffect(() => {
187
174
  const fn = async () => {
188
175
  await installWorker({
189
- skipLoadBooks,
190
176
  primaryOnly,
191
177
  nativeReadFile,
192
178
  nativeWriteFile,
@@ -201,69 +187,19 @@ var useOfflineWorker_default = ({
201
187
  setReady(true);
202
188
  };
203
189
  fn();
204
- }, [
205
- skipLoadBooks,
206
- primaryOnly,
207
- nativeReadFile,
208
- nativeWriteFile,
209
- nativeListZips,
210
- storage,
211
- zipBaseUrl,
212
- checkUpdates,
213
- confEnv
214
- ]);
190
+ }, [primaryOnly, nativeReadFile, nativeWriteFile, nativeListZips, storage, zipBaseUrl, checkUpdates, confEnv]);
215
191
  const loadBook = useCallback(
216
- async ({ forceRefresh, ...idOrUri }, cbk) => {
217
- cbk && offlineWorkerSync.on("opfsProgress", cbk);
218
- return await offlineWorkerSync.loadBook({ id: "id" in idOrUri ? idOrUri.id : idOrUri.uri, forceRefresh });
192
+ async ({ id, forceRefresh }, cbk) => {
193
+ offlineWorkerSync.on("opfsProgress", cbk);
194
+ return await offlineWorkerSync.loadBook({ id, forceRefresh });
219
195
  },
220
196
  []
221
197
  );
222
- const reset = useCallback(async () => {
223
- await offlineWorkerSync.reset();
224
- await clearCache(confEnv || "development");
225
- console.debug("reset: keys:", await caches.keys());
226
- }, [confEnv]);
227
198
  return {
228
199
  ready,
229
- loadBook,
230
- reset
200
+ loadBook
231
201
  };
232
202
  };
233
-
234
- // src/store/index.ts
235
- import { persistReducer } from "redux-persist";
236
- var persistEntitiesReducer = (entitiesReducer, CONF_ENV) => {
237
- const getKey = (key) => `store:${CONF_ENV}:${key}`;
238
- return persistReducer(
239
- {
240
- key: "entities",
241
- storage: {
242
- getItem: async (key) => localStorage.getItem(getKey(key)) || "{}",
243
- setItem: async (key, item) => localStorage.setItem(getKey(key), item),
244
- removeItem: async (key) => localStorage.removeItem(getKey(key))
245
- },
246
- whitelist: ["lexicalFlowers"],
247
- version: 1,
248
- debug: true,
249
- throttle: 1e3
250
- // lexicalFlowers is small, we may persist it fast
251
- },
252
- entitiesReducer
253
- );
254
- };
255
-
256
- // src/store/offlinePersist.tsx
257
- import { persistStore } from "redux-persist";
258
- import { PersistGate } from "redux-persist/integration/react";
259
- import { useMemo } from "react";
260
- import { jsx } from "react/jsx-runtime";
261
- var OfflinePersist = ({ store, children }) => {
262
- const persistor = useMemo(() => persistStore(store), [store]);
263
- return /* @__PURE__ */ jsx(PersistGate, { loading: null, persistor, children });
264
- };
265
203
  export {
266
- OfflinePersist,
267
- persistEntitiesReducer,
268
204
  useOfflineWorker_default as useOfflineWorker
269
205
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lls/offline",
3
- "version": "24.27.0-bbbcfe5a",
3
+ "version": "24.27.0-d7760203",
4
4
  "description": "offline",
5
5
  "main": "./lib/index.js",
6
6
  "module": "./lib/index.js",
@@ -48,15 +48,14 @@
48
48
  "nock": "14.0.5",
49
49
  "react": "18.3.1",
50
50
  "react-dom": "18.3.1",
51
- "redux": "5.0.1",
52
51
  "typescript": "5.8.3",
53
52
  "vite": "7.0.7",
54
53
  "vite-tsconfig-paths": "5.1.4",
55
54
  "zod": "3.25.50",
56
- "@lls/vitescripts": "24.27.0-bbbcfe5a"
55
+ "@lls/vitescripts": "24.27.0-d7760203"
57
56
  },
58
57
  "dependencies": {
59
- "redux-persist": "6.0.0"
58
+ "fflate": "0.8.2"
60
59
  },
61
60
  "scripts": {
62
61
  "start": "pnpm ladle serve",