@lls/offline 24.27.0-9f297e77 → 24.27.0-a35fd1df
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.
- package/lib/assets/fetch-worker.js +10 -67
- package/lib/assets/offline-worker.js +5 -42
- package/lib/index.js +4 -16
- package/package.json +2 -2
|
@@ -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 = {};
|
|
@@ -95,7 +77,7 @@ var cocoreFetchPartialPageScreen = async (_ev, { offlineWorkerSync: offlineWorke
|
|
|
95
77
|
const key = `gqls/${zipSlugName(variables.slugs[0] || "")}.json`;
|
|
96
78
|
const entryId = knownLinks2.get(key);
|
|
97
79
|
if (!entryId) {
|
|
98
|
-
throw new Error(`slug not found ${key}
|
|
80
|
+
throw new Error(`slug not found ${key}`);
|
|
99
81
|
}
|
|
100
82
|
const gqlPage = await offlineWorkerSync2.loadPageContent({ entryId });
|
|
101
83
|
return { data: gqlPage };
|
|
@@ -220,23 +202,12 @@ var coreFetchPagesApi = async (ev, { offlineWorkerSync: offlineWorkerSync2, vari
|
|
|
220
202
|
}
|
|
221
203
|
}
|
|
222
204
|
};
|
|
223
|
-
var cocoreFetchPrimaryMethod = async (_ev, { offlineWorkerSync: offlineWorkerSync2, variables }) => {
|
|
224
|
-
const uri = variables.uris?.[0];
|
|
225
|
-
if (!uri) {
|
|
226
|
-
throw new Error("invalid uri");
|
|
227
|
-
}
|
|
228
|
-
const method = await offlineWorkerSync2.readZipEntry({ bookId: uri, entryName: "gqls/method.json", asJson: true });
|
|
229
|
-
return {
|
|
230
|
-
data: method
|
|
231
|
-
};
|
|
232
|
-
};
|
|
233
205
|
var handles = {
|
|
234
206
|
coreFetchBookDrawerScreen,
|
|
235
207
|
cocoreFetchBookScreen,
|
|
236
208
|
coreFetchPagesApi,
|
|
237
209
|
cocoreFetchPartialPageScreen,
|
|
238
|
-
cocoreFetchPartialPageSiblingsScreen
|
|
239
|
-
cocoreFetchPrimaryMethod
|
|
210
|
+
cocoreFetchPartialPageSiblingsScreen
|
|
240
211
|
};
|
|
241
212
|
var canHandleScreenCall = (url) => new RegExp(Object.keys(handles).join("|")).test(url);
|
|
242
213
|
var handleScreenCall = async (ev, { offlineWorkerSync: offlineWorkerSync2, knownLinks: knownLinks2 }) => {
|
|
@@ -245,8 +216,8 @@ var handleScreenCall = async (ev, { offlineWorkerSync: offlineWorkerSync2, known
|
|
|
245
216
|
// @ts-expect-error TODO: handle variables from body(stream) properly!!
|
|
246
217
|
ev.request.body?.variables || JSON.parse(new URLSearchParams(new URL(ev.request.url).search).get("variables") || "{}")
|
|
247
218
|
);
|
|
219
|
+
console.debug("variables are", variables, "vs", ev.request.body);
|
|
248
220
|
const key = ev.request.url.match(Object.keys(handles).join("|"))?.[0];
|
|
249
|
-
console.debug("screencall", key, "qs", variables, "vs body", ev.request.body);
|
|
250
221
|
if (!key) {
|
|
251
222
|
throw new Error("unknown ev");
|
|
252
223
|
}
|
|
@@ -267,39 +238,17 @@ var setKnownLinks = (knownLinks2, { entryNames, bookId }) => {
|
|
|
267
238
|
// src/worker/fetch-worker.ts
|
|
268
239
|
var STORAGE = "cache";
|
|
269
240
|
var CONF_ENV = "development";
|
|
270
|
-
var fetchAsset = async (
|
|
241
|
+
var fetchAsset = async (_ev, { entryId, mimeType, offlineWorkerSync: offlineWorkerSync2 }) => {
|
|
271
242
|
try {
|
|
272
|
-
const
|
|
273
|
-
const range = ev.request.headers.get("Range");
|
|
274
|
-
if (!ev.request.url.endsWith(".mp4") && !ev.request.url.endsWith(".webm")) {
|
|
275
|
-
return [buf2, {}];
|
|
276
|
-
}
|
|
277
|
-
if (!range) {
|
|
278
|
-
return [
|
|
279
|
-
buf2,
|
|
280
|
-
{
|
|
281
|
-
"Accept-Ranges": "bytes",
|
|
282
|
-
"Content-Range": `bytes ${0}-${buf2.byteLength}/${buf2.byteLength}`
|
|
283
|
-
}
|
|
284
|
-
];
|
|
285
|
-
}
|
|
286
|
-
const { start, end, chunkSize } = parseRange(range, buf2.byteLength);
|
|
287
|
-
const rangeHeaders = {
|
|
288
|
-
"Content-Length": chunkSize,
|
|
289
|
-
"Accept-Ranges": "bytes",
|
|
290
|
-
"Content-Range": `bytes ${start}-${end}/${buf2.byteLength}`
|
|
291
|
-
};
|
|
292
|
-
return [buf2.slice(start, end + 1), rangeHeaders];
|
|
293
|
-
});
|
|
243
|
+
const buf = await offlineWorkerSync2.readZipEntry(entryId);
|
|
294
244
|
return new Response(buf, {
|
|
295
245
|
headers: {
|
|
296
246
|
"Cache-Control": "max-age=600, s-maxage=600, public, proxy-revalidate",
|
|
297
247
|
"Content-Length": buf.byteLength,
|
|
298
|
-
"Content-Type": mimeType
|
|
299
|
-
...maybeRangeHeaders
|
|
248
|
+
"Content-Type": mimeType
|
|
300
249
|
},
|
|
301
250
|
// @ts-ignore: poor ts typing
|
|
302
|
-
status:
|
|
251
|
+
status: 200,
|
|
303
252
|
statusText: "OK"
|
|
304
253
|
});
|
|
305
254
|
} catch (e) {
|
|
@@ -398,16 +347,14 @@ swSelf.addEventListener("fetch", (ev) => {
|
|
|
398
347
|
return;
|
|
399
348
|
}
|
|
400
349
|
if (!mimeType && !isValidScreenCall) {
|
|
401
|
-
if (!/\.(css|tsx?|
|
|
350
|
+
if (!/\.(css|tsx?|jsx?|woff2|fr|manifest)(\??|$)|@(vite|react|id)/.test(url)) {
|
|
402
351
|
console.debug("no ext", extension || url);
|
|
403
352
|
}
|
|
404
353
|
return ev.respondWith(onlineFirst(ev.request, ev));
|
|
405
354
|
}
|
|
406
|
-
if (/http:\/\/localhost:\d+\/(favicon\.svg|assets\/)/.test(url)) {
|
|
407
|
-
return;
|
|
408
|
-
}
|
|
409
355
|
const entryId = knownLinks.get(url.replace(/https:\/\/.*?\//, "")) || knownLinks.get(`medias/${url.replace(/https:\/\/.*?\//, "")}`);
|
|
410
356
|
if (isValidScreenCall) {
|
|
357
|
+
console.debug("screencall!");
|
|
411
358
|
return ev.respondWith(fetchScreenCall(ev, { offlineWorkerSync, knownLinks }));
|
|
412
359
|
}
|
|
413
360
|
if (entryId) {
|
|
@@ -416,7 +363,6 @@ swSelf.addEventListener("fetch", (ev) => {
|
|
|
416
363
|
if (/lls|lelivrescolaire/.test(url)) {
|
|
417
364
|
console.info("no link for", url.replace(/https:\/\/.*?\//, ""), `medias/${url.replace(/https:\/\/.*?\//, "")}`);
|
|
418
365
|
}
|
|
419
|
-
console.debug("unintercepted url", url);
|
|
420
366
|
return;
|
|
421
367
|
});
|
|
422
368
|
swSelf.addEventListener("install", (_event) => {
|
|
@@ -437,10 +383,7 @@ var initChannel = async (__, { ports }) => {
|
|
|
437
383
|
);
|
|
438
384
|
offlineWorkerSync = sender;
|
|
439
385
|
offlineWorker.onmessage = handler.handle;
|
|
440
|
-
offlineWorkerSync.on("setKnownLinks", (
|
|
441
|
-
setKnownLinks(knownLinks, { entryNames, bookId });
|
|
442
|
-
offlineWorker.postMessage({ methodName: "setKnownLinks:back", eventId });
|
|
443
|
-
});
|
|
386
|
+
offlineWorkerSync.on("setKnownLinks", setKnownLinks.bind(null, knownLinks));
|
|
444
387
|
offlineWorker.postMessage({ methodName: "sendAppReady" });
|
|
445
388
|
};
|
|
446
389
|
var knownLinks = /* @__PURE__ */ new Map();
|
|
@@ -802,14 +802,12 @@ var readZipEntry = async ({
|
|
|
802
802
|
const originalName = manifest.medias[zipName];
|
|
803
803
|
overridenName = `medias/${originalName}`;
|
|
804
804
|
} else {
|
|
805
|
-
|
|
806
|
-
console.error("any media should exist in manifest", zipName, entryName, bookId);
|
|
807
|
-
}
|
|
805
|
+
console.error("any media should exist in manifest", zipName, entryName, bookId);
|
|
808
806
|
}
|
|
809
807
|
}
|
|
810
808
|
const bookEntry = BOOKS[bookId].map.get(overridenName);
|
|
811
809
|
if (!bookEntry) {
|
|
812
|
-
console.info("no bookEntry", entryName, "
|
|
810
|
+
console.info("no bookEntry", entryName, "found", overridenName);
|
|
813
811
|
return null;
|
|
814
812
|
}
|
|
815
813
|
if (!bookEntry.decoded) {
|
|
@@ -888,8 +886,7 @@ var fetchZipFile = async (zipUrl, { forceRefresh } = {}) => {
|
|
|
888
886
|
return back;
|
|
889
887
|
}
|
|
890
888
|
if (STORAGE === "cache") {
|
|
891
|
-
const
|
|
892
|
-
const response = await cache.match(zipUrl);
|
|
889
|
+
const response = await caches.match(zipUrl);
|
|
893
890
|
if (!response) {
|
|
894
891
|
throw new Error(`missing zip ${zipUrl}`);
|
|
895
892
|
}
|
|
@@ -913,11 +910,7 @@ var fetchZipFile = async (zipUrl, { forceRefresh } = {}) => {
|
|
|
913
910
|
const buf = await readArrayBuffer();
|
|
914
911
|
if (CHECK_UPDATES) {
|
|
915
912
|
const response = await fetch(zipUrl, { method: "HEAD" });
|
|
916
|
-
|
|
917
|
-
if (!remoteSize) {
|
|
918
|
-
console.info("remoteSize not found. will skip update. Is the server up at", zipUrl);
|
|
919
|
-
remoteSize = buf.byteLength;
|
|
920
|
-
}
|
|
913
|
+
const remoteSize = Number.parseInt(response.headers.get("content-length") || "0", 10);
|
|
921
914
|
if (remoteSize !== buf.byteLength) {
|
|
922
915
|
const error = `new ${fileName} available, refetching (opfs:${buf.byteLength} vs remote:${remoteSize})`;
|
|
923
916
|
console.debug(error);
|
|
@@ -925,7 +918,6 @@ var fetchZipFile = async (zipUrl, { forceRefresh } = {}) => {
|
|
|
925
918
|
throw new Error(`new ${fileName} available, refetching`);
|
|
926
919
|
}
|
|
927
920
|
}
|
|
928
|
-
self.postMessage({ methodName: "opfsProgress", arg: { total: buf.byteLength, bytes: buf.byteLength } });
|
|
929
921
|
return buf;
|
|
930
922
|
} catch (e) {
|
|
931
923
|
if (e instanceof Error && e.message !== "forceRefresh" && !e.message.includes("refetching")) {
|
|
@@ -955,7 +947,6 @@ var fetchZipFile = async (zipUrl, { forceRefresh } = {}) => {
|
|
|
955
947
|
self.postMessage({ methodName: "opfsProgress", arg: { total: contentLength, bytes: position } });
|
|
956
948
|
}
|
|
957
949
|
}
|
|
958
|
-
console.debug("zip loaded:", arrayBuffer.byteLength);
|
|
959
950
|
if (STORAGE === "native") {
|
|
960
951
|
await sender.nativeWriteFile({ fname: fileName, buffer: arrayBuffer });
|
|
961
952
|
} else if (STORAGE === "opfs") {
|
|
@@ -1001,12 +992,7 @@ var loadBook2 = async ({ id: bookId, forceRefresh }) => {
|
|
|
1001
992
|
const buf = await fetchZipFile(`${ZIP_BASE_URL}/${bookId}.zip`, { forceRefresh });
|
|
1002
993
|
try {
|
|
1003
994
|
const entryNames = await loadZip(new Uint8Array(buf), bookId);
|
|
1004
|
-
|
|
1005
|
-
const responseForEventId = new Promise((resolve, reject) => {
|
|
1006
|
-
dicFetchWorkerCallback[eventId] = { resolve, reject };
|
|
1007
|
-
});
|
|
1008
|
-
fetchWorker.postMessage({ methodName: "setKnownLinks", arg: { entryNames, bookId, eventId } });
|
|
1009
|
-
await responseForEventId;
|
|
995
|
+
fetchWorker.postMessage({ methodName: "setKnownLinks", arg: { entryNames, bookId } });
|
|
1010
996
|
if (isOldZip(bookId)) {
|
|
1011
997
|
const json = await readZipEntry({
|
|
1012
998
|
entryName: `preload/${bookId}.json`,
|
|
@@ -1014,13 +1000,6 @@ var loadBook2 = async ({ id: bookId, forceRefresh }) => {
|
|
|
1014
1000
|
asJson: true
|
|
1015
1001
|
});
|
|
1016
1002
|
loadBook(json);
|
|
1017
|
-
} else {
|
|
1018
|
-
try {
|
|
1019
|
-
const { createdAt } = await readZipEntry({ bookId, entryName: "manifest.json", asJson: true });
|
|
1020
|
-
console.debug("zipversion", createdAt);
|
|
1021
|
-
} catch (e) {
|
|
1022
|
-
console.debug("failed to read manifest.json", e);
|
|
1023
|
-
}
|
|
1024
1003
|
}
|
|
1025
1004
|
return true;
|
|
1026
1005
|
} catch (e) {
|
|
@@ -1050,14 +1029,6 @@ var loadPageContent2 = async ({
|
|
|
1050
1029
|
return await loadPageContent({ chapterId, json });
|
|
1051
1030
|
};
|
|
1052
1031
|
var fetchWorker;
|
|
1053
|
-
var dicFetchWorkerCallback = {};
|
|
1054
|
-
var handleFetchWorkerCallback = ({ data: { eventId } }) => {
|
|
1055
|
-
if (dicFetchWorkerCallback[eventId]) {
|
|
1056
|
-
dicFetchWorkerCallback[eventId].resolve();
|
|
1057
|
-
} else {
|
|
1058
|
-
console.debug("unknown eventId", eventId);
|
|
1059
|
-
}
|
|
1060
|
-
};
|
|
1061
1032
|
var initChannel = (__, { ports }) => {
|
|
1062
1033
|
fetchWorker = ports[0];
|
|
1063
1034
|
const { canHandle, handle } = makeSyncHandler(fetchWorker, {
|
|
@@ -1072,14 +1043,6 @@ var initChannel = (__, { ports }) => {
|
|
|
1072
1043
|
self.postMessage({ methodName: "ready" });
|
|
1073
1044
|
return;
|
|
1074
1045
|
}
|
|
1075
|
-
if (dataObj.data?.methodName === "setKnownLinks:back") {
|
|
1076
|
-
if (typeof dataObj?.data?.eventId !== "string") {
|
|
1077
|
-
console.debug("missing eventId to get response back for setKnownLinks:back");
|
|
1078
|
-
return;
|
|
1079
|
-
}
|
|
1080
|
-
handleFetchWorkerCallback(dataObj);
|
|
1081
|
-
return;
|
|
1082
|
-
}
|
|
1083
1046
|
if (canHandle(dataObj.data?.methodName || "")) {
|
|
1084
1047
|
return handle(dataObj);
|
|
1085
1048
|
}
|
package/lib/index.js
CHANGED
|
@@ -161,7 +161,6 @@ var installWorker = async ({
|
|
|
161
161
|
setBooksLoaded();
|
|
162
162
|
};
|
|
163
163
|
var useOfflineWorker_default = ({
|
|
164
|
-
skipLoadBooks,
|
|
165
164
|
primaryOnly = false,
|
|
166
165
|
nativeReadFile,
|
|
167
166
|
nativeWriteFile,
|
|
@@ -175,7 +174,6 @@ var useOfflineWorker_default = ({
|
|
|
175
174
|
useEffect(() => {
|
|
176
175
|
const fn = async () => {
|
|
177
176
|
await installWorker({
|
|
178
|
-
skipLoadBooks,
|
|
179
177
|
primaryOnly,
|
|
180
178
|
nativeReadFile,
|
|
181
179
|
nativeWriteFile,
|
|
@@ -190,21 +188,11 @@ var useOfflineWorker_default = ({
|
|
|
190
188
|
setReady(true);
|
|
191
189
|
};
|
|
192
190
|
fn();
|
|
193
|
-
}, [
|
|
194
|
-
skipLoadBooks,
|
|
195
|
-
primaryOnly,
|
|
196
|
-
nativeReadFile,
|
|
197
|
-
nativeWriteFile,
|
|
198
|
-
nativeListZips,
|
|
199
|
-
storage,
|
|
200
|
-
zipBaseUrl,
|
|
201
|
-
checkUpdates,
|
|
202
|
-
confEnv
|
|
203
|
-
]);
|
|
191
|
+
}, [primaryOnly, nativeReadFile, nativeWriteFile, nativeListZips, storage, zipBaseUrl, checkUpdates, confEnv]);
|
|
204
192
|
const loadBook = useCallback(
|
|
205
|
-
async ({
|
|
206
|
-
|
|
207
|
-
return await offlineWorkerSync.loadBook({ id
|
|
193
|
+
async ({ id, forceRefresh }, cbk) => {
|
|
194
|
+
offlineWorkerSync.on("opfsProgress", cbk);
|
|
195
|
+
return await offlineWorkerSync.loadBook({ id, forceRefresh });
|
|
208
196
|
},
|
|
209
197
|
[]
|
|
210
198
|
);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lls/offline",
|
|
3
|
-
"version": "24.27.0-
|
|
3
|
+
"version": "24.27.0-a35fd1df",
|
|
4
4
|
"description": "offline",
|
|
5
5
|
"main": "./lib/index.js",
|
|
6
6
|
"module": "./lib/index.js",
|
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
"vite": "7.0.7",
|
|
53
53
|
"vite-tsconfig-paths": "5.1.4",
|
|
54
54
|
"zod": "3.25.50",
|
|
55
|
-
"@lls/vitescripts": "24.27.0-
|
|
55
|
+
"@lls/vitescripts": "24.27.0-a35fd1df"
|
|
56
56
|
},
|
|
57
57
|
"dependencies": {
|
|
58
58
|
"fflate": "0.8.2"
|