@b9g/platform 0.1.12 → 0.1.14-beta.0
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/package.json +25 -17
- package/src/config.d.ts +24 -0
- package/src/config.js +29 -0
- package/src/globals.d.ts +119 -0
- package/src/index.d.ts +167 -114
- package/src/index.js +176 -291
- package/src/runtime.d.ts +372 -72
- package/src/runtime.js +469 -181
- package/chunk-P57PW2II.js +0 -11
- package/src/worker.d.ts +0 -39
- package/src/worker.js +0 -285
package/src/runtime.js
CHANGED
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
/// <reference types="./runtime.d.ts" />
|
|
2
|
-
import "../chunk-P57PW2II.js";
|
|
3
|
-
|
|
4
2
|
// src/runtime.ts
|
|
5
3
|
import { AsyncContext } from "@b9g/async-context";
|
|
4
|
+
import { getLogger, getConsoleSink } from "@logtape/logtape";
|
|
5
|
+
import { CustomDirectoryStorage } from "@b9g/filesystem";
|
|
6
|
+
import { CustomCacheStorage } from "@b9g/cache";
|
|
7
|
+
import { handleCacheResponse, PostMessageCache } from "@b9g/cache/postmessage";
|
|
6
8
|
import {
|
|
7
9
|
configure
|
|
8
10
|
} from "@logtape/logtape";
|
|
11
|
+
import { Database } from "@b9g/zen";
|
|
9
12
|
function parseCookieHeader(cookieHeader) {
|
|
10
13
|
const cookies = /* @__PURE__ */ new Map();
|
|
11
|
-
if (!cookieHeader)
|
|
12
|
-
return cookies;
|
|
14
|
+
if (!cookieHeader) return cookies;
|
|
13
15
|
const pairs = cookieHeader.split(/;\s*/);
|
|
14
16
|
for (const pair of pairs) {
|
|
15
17
|
const [name, ...valueParts] = pair.split("=");
|
|
@@ -114,8 +116,7 @@ var RequestCookieStore = class extends EventTarget {
|
|
|
114
116
|
}
|
|
115
117
|
if (this.#changes.has(name)) {
|
|
116
118
|
const change = this.#changes.get(name);
|
|
117
|
-
if (change === null || change === void 0)
|
|
118
|
-
return null;
|
|
119
|
+
if (change === null || change === void 0) return null;
|
|
119
120
|
return {
|
|
120
121
|
name: change.name,
|
|
121
122
|
value: change.value,
|
|
@@ -136,8 +137,7 @@ var RequestCookieStore = class extends EventTarget {
|
|
|
136
137
|
...this.#changes.keys()
|
|
137
138
|
]);
|
|
138
139
|
for (const cookieName of allNames) {
|
|
139
|
-
if (name && cookieName !== name)
|
|
140
|
-
continue;
|
|
140
|
+
if (name && cookieName !== name) continue;
|
|
141
141
|
if (this.#changes.has(cookieName) && this.#changes.get(cookieName) === null) {
|
|
142
142
|
continue;
|
|
143
143
|
}
|
|
@@ -216,10 +216,122 @@ var CustomLoggerStorage = class {
|
|
|
216
216
|
constructor(factory) {
|
|
217
217
|
this.#factory = factory;
|
|
218
218
|
}
|
|
219
|
-
|
|
220
|
-
return this.#factory(
|
|
219
|
+
get(categories) {
|
|
220
|
+
return this.#factory(categories);
|
|
221
|
+
}
|
|
222
|
+
};
|
|
223
|
+
var CustomDatabaseStorage = class {
|
|
224
|
+
#factory;
|
|
225
|
+
#databases;
|
|
226
|
+
#closers;
|
|
227
|
+
#pending;
|
|
228
|
+
constructor(factory) {
|
|
229
|
+
this.#factory = factory;
|
|
230
|
+
this.#databases = /* @__PURE__ */ new Map();
|
|
231
|
+
this.#closers = /* @__PURE__ */ new Map();
|
|
232
|
+
this.#pending = /* @__PURE__ */ new Map();
|
|
233
|
+
}
|
|
234
|
+
async open(name, version, onUpgrade) {
|
|
235
|
+
const existing = this.#databases.get(name);
|
|
236
|
+
if (existing) {
|
|
237
|
+
return existing;
|
|
238
|
+
}
|
|
239
|
+
const pending = this.#pending.get(name);
|
|
240
|
+
if (pending) {
|
|
241
|
+
return pending;
|
|
242
|
+
}
|
|
243
|
+
const promise = (async () => {
|
|
244
|
+
const { db, close } = await this.#factory(name);
|
|
245
|
+
if (onUpgrade) {
|
|
246
|
+
db.addEventListener("upgradeneeded", (e) => {
|
|
247
|
+
const event = e;
|
|
248
|
+
onUpgrade({
|
|
249
|
+
db,
|
|
250
|
+
oldVersion: event.oldVersion,
|
|
251
|
+
newVersion: event.newVersion,
|
|
252
|
+
waitUntil: (p) => event.waitUntil(p)
|
|
253
|
+
});
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
try {
|
|
257
|
+
await db.open(version);
|
|
258
|
+
} catch (err) {
|
|
259
|
+
await close();
|
|
260
|
+
throw err;
|
|
261
|
+
}
|
|
262
|
+
this.#databases.set(name, db);
|
|
263
|
+
this.#closers.set(name, close);
|
|
264
|
+
return db;
|
|
265
|
+
})().finally(() => {
|
|
266
|
+
this.#pending.delete(name);
|
|
267
|
+
});
|
|
268
|
+
this.#pending.set(name, promise);
|
|
269
|
+
return promise;
|
|
270
|
+
}
|
|
271
|
+
get(name) {
|
|
272
|
+
const db = this.#databases.get(name);
|
|
273
|
+
if (!db) {
|
|
274
|
+
throw new Error(
|
|
275
|
+
`Database "${name}" has not been opened. Call self.databases.open("${name}", version) in your activate handler first.`
|
|
276
|
+
);
|
|
277
|
+
}
|
|
278
|
+
return db;
|
|
279
|
+
}
|
|
280
|
+
async close(name) {
|
|
281
|
+
const pending = this.#pending.get(name);
|
|
282
|
+
if (pending) {
|
|
283
|
+
try {
|
|
284
|
+
await pending;
|
|
285
|
+
} catch (_err) {
|
|
286
|
+
return;
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
const closer = this.#closers.get(name);
|
|
290
|
+
if (closer) {
|
|
291
|
+
await closer();
|
|
292
|
+
this.#databases.delete(name);
|
|
293
|
+
this.#closers.delete(name);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
async closeAll() {
|
|
297
|
+
if (this.#pending.size > 0) {
|
|
298
|
+
await Promise.allSettled(this.#pending.values());
|
|
299
|
+
}
|
|
300
|
+
const promises = Array.from(this.#databases.keys()).map(
|
|
301
|
+
(name) => this.close(name)
|
|
302
|
+
);
|
|
303
|
+
await Promise.allSettled(promises);
|
|
221
304
|
}
|
|
222
305
|
};
|
|
306
|
+
function createDatabaseFactory(configs) {
|
|
307
|
+
return async (name) => {
|
|
308
|
+
const config = configs[name];
|
|
309
|
+
if (!config) {
|
|
310
|
+
throw new Error(
|
|
311
|
+
`Database "${name}" is not configured. Available databases: ${Object.keys(configs).join(", ") || "(none)"}`
|
|
312
|
+
);
|
|
313
|
+
}
|
|
314
|
+
const { impl, url, ...driverOptions } = config;
|
|
315
|
+
if (!impl) {
|
|
316
|
+
throw new Error(
|
|
317
|
+
`Database "${name}" has no impl. Ensure the database module is configured in shovel.json.`
|
|
318
|
+
);
|
|
319
|
+
}
|
|
320
|
+
if (!url) {
|
|
321
|
+
throw new Error(
|
|
322
|
+
`Database "${name}" has no url. Ensure the database URL is configured.`
|
|
323
|
+
);
|
|
324
|
+
}
|
|
325
|
+
const driver = new impl(url, driverOptions);
|
|
326
|
+
const db = new Database(driver);
|
|
327
|
+
return {
|
|
328
|
+
db,
|
|
329
|
+
close: async () => {
|
|
330
|
+
await driver.close();
|
|
331
|
+
}
|
|
332
|
+
};
|
|
333
|
+
};
|
|
334
|
+
}
|
|
223
335
|
var SERVICE_WORKER_EVENTS = ["fetch", "install", "activate"];
|
|
224
336
|
function isServiceWorkerEvent(type) {
|
|
225
337
|
return SERVICE_WORKER_EVENTS.includes(type);
|
|
@@ -235,6 +347,7 @@ var PATCHED_KEYS = [
|
|
|
235
347
|
"fetch",
|
|
236
348
|
"caches",
|
|
237
349
|
"directories",
|
|
350
|
+
"databases",
|
|
238
351
|
"loggers",
|
|
239
352
|
"registration",
|
|
240
353
|
"clients",
|
|
@@ -254,9 +367,9 @@ function promiseWithTimeout(promise, timeoutMs, errorMessage) {
|
|
|
254
367
|
)
|
|
255
368
|
]);
|
|
256
369
|
}
|
|
257
|
-
var kEndDispatchPhase = Symbol.for("shovel.endDispatchPhase");
|
|
258
|
-
var kCanExtend = Symbol.for("shovel.canExtend");
|
|
259
|
-
var
|
|
370
|
+
var kEndDispatchPhase = /* @__PURE__ */ Symbol.for("shovel.endDispatchPhase");
|
|
371
|
+
var kCanExtend = /* @__PURE__ */ Symbol.for("shovel.canExtend");
|
|
372
|
+
var ShovelExtendableEvent = class extends Event {
|
|
260
373
|
#promises;
|
|
261
374
|
#dispatchPhase;
|
|
262
375
|
#pendingCount;
|
|
@@ -293,17 +406,33 @@ var ExtendableEvent = class extends Event {
|
|
|
293
406
|
return this.#dispatchPhase || this.#pendingCount > 0;
|
|
294
407
|
}
|
|
295
408
|
};
|
|
296
|
-
var
|
|
409
|
+
var ShovelFetchEvent = class extends ShovelExtendableEvent {
|
|
297
410
|
request;
|
|
298
411
|
cookieStore;
|
|
412
|
+
clientId;
|
|
413
|
+
handled;
|
|
414
|
+
preloadResponse;
|
|
415
|
+
resultingClientId;
|
|
299
416
|
#responsePromise;
|
|
300
417
|
#responded;
|
|
301
|
-
|
|
302
|
-
|
|
418
|
+
#platformWaitUntil;
|
|
419
|
+
constructor(request, options) {
|
|
420
|
+
super("fetch", options);
|
|
303
421
|
this.request = request;
|
|
304
422
|
this.cookieStore = new RequestCookieStore(request);
|
|
423
|
+
this.clientId = "";
|
|
424
|
+
this.handled = Promise.resolve(void 0);
|
|
425
|
+
this.preloadResponse = Promise.resolve(void 0);
|
|
426
|
+
this.resultingClientId = "";
|
|
305
427
|
this.#responsePromise = null;
|
|
306
428
|
this.#responded = false;
|
|
429
|
+
this.#platformWaitUntil = options?.platformWaitUntil;
|
|
430
|
+
}
|
|
431
|
+
waitUntil(promise) {
|
|
432
|
+
if (this.#platformWaitUntil) {
|
|
433
|
+
this.#platformWaitUntil(promise);
|
|
434
|
+
}
|
|
435
|
+
super.waitUntil(promise);
|
|
307
436
|
}
|
|
308
437
|
respondWith(response) {
|
|
309
438
|
if (this.#responded) {
|
|
@@ -325,13 +454,17 @@ var FetchEvent = class extends ExtendableEvent {
|
|
|
325
454
|
hasResponded() {
|
|
326
455
|
return this.#responded;
|
|
327
456
|
}
|
|
457
|
+
/** The URL of the request (convenience property) */
|
|
458
|
+
get url() {
|
|
459
|
+
return this.request.url;
|
|
460
|
+
}
|
|
328
461
|
};
|
|
329
|
-
var
|
|
462
|
+
var ShovelInstallEvent = class extends ShovelExtendableEvent {
|
|
330
463
|
constructor(eventInitDict) {
|
|
331
464
|
super("install", eventInitDict);
|
|
332
465
|
}
|
|
333
466
|
};
|
|
334
|
-
var
|
|
467
|
+
var ShovelActivateEvent = class extends ShovelExtendableEvent {
|
|
335
468
|
constructor(eventInitDict) {
|
|
336
469
|
super("activate", eventInitDict);
|
|
337
470
|
}
|
|
@@ -383,7 +516,7 @@ var ShovelClients = class {
|
|
|
383
516
|
return null;
|
|
384
517
|
}
|
|
385
518
|
};
|
|
386
|
-
var ExtendableMessageEvent = class extends
|
|
519
|
+
var ExtendableMessageEvent = class extends ShovelExtendableEvent {
|
|
387
520
|
data;
|
|
388
521
|
origin;
|
|
389
522
|
lastEventId;
|
|
@@ -435,12 +568,16 @@ var ShovelNavigationPreloadManager = class {
|
|
|
435
568
|
async setHeaderValue(_value) {
|
|
436
569
|
}
|
|
437
570
|
};
|
|
571
|
+
var kServiceWorker = /* @__PURE__ */ Symbol("serviceWorker");
|
|
572
|
+
var kDispatchInstall = /* @__PURE__ */ Symbol("dispatchInstall");
|
|
573
|
+
var kDispatchActivate = /* @__PURE__ */ Symbol("dispatchActivate");
|
|
574
|
+
var kHandleRequest = /* @__PURE__ */ Symbol("handleRequest");
|
|
438
575
|
var ShovelServiceWorkerRegistration = class extends EventTarget {
|
|
439
576
|
scope;
|
|
440
577
|
updateViaCache;
|
|
441
578
|
navigationPreload;
|
|
442
|
-
// ServiceWorker
|
|
443
|
-
|
|
579
|
+
// Internal ServiceWorker instance (accessed via symbol for lifecycle management)
|
|
580
|
+
[kServiceWorker];
|
|
444
581
|
// Web API properties (not supported in server context, but required by interface)
|
|
445
582
|
cookies;
|
|
446
583
|
pushManager;
|
|
@@ -450,20 +587,20 @@ var ShovelServiceWorkerRegistration = class extends EventTarget {
|
|
|
450
587
|
this.scope = scope;
|
|
451
588
|
this.updateViaCache = "imports";
|
|
452
589
|
this.navigationPreload = new ShovelNavigationPreloadManager();
|
|
453
|
-
this
|
|
590
|
+
this[kServiceWorker] = new ShovelServiceWorker(scriptURL, "parsed");
|
|
454
591
|
this.cookies = null;
|
|
455
592
|
this.pushManager = null;
|
|
456
593
|
this.onupdatefound = null;
|
|
457
594
|
}
|
|
458
595
|
// Standard ServiceWorkerRegistration properties
|
|
459
596
|
get active() {
|
|
460
|
-
return this.
|
|
597
|
+
return this[kServiceWorker].state === "activated" ? this[kServiceWorker] : null;
|
|
461
598
|
}
|
|
462
599
|
get installing() {
|
|
463
|
-
return this.
|
|
600
|
+
return this[kServiceWorker].state === "installing" ? this[kServiceWorker] : null;
|
|
464
601
|
}
|
|
465
602
|
get waiting() {
|
|
466
|
-
return this.
|
|
603
|
+
return this[kServiceWorker].state === "installed" ? this[kServiceWorker] : null;
|
|
467
604
|
}
|
|
468
605
|
// Standard ServiceWorkerRegistration methods
|
|
469
606
|
async getNotifications(_options) {
|
|
@@ -480,16 +617,16 @@ var ShovelServiceWorkerRegistration = class extends EventTarget {
|
|
|
480
617
|
async update() {
|
|
481
618
|
return this;
|
|
482
619
|
}
|
|
483
|
-
//
|
|
620
|
+
// Internal lifecycle methods (accessed via symbols by runLifecycle)
|
|
484
621
|
/**
|
|
485
|
-
*
|
|
622
|
+
* Dispatch the install lifecycle event
|
|
623
|
+
* @internal Use runLifecycle() instead of calling this directly
|
|
486
624
|
*/
|
|
487
|
-
async
|
|
488
|
-
if (this.
|
|
489
|
-
|
|
490
|
-
this._serviceWorker._setState("installing");
|
|
625
|
+
async [kDispatchInstall]() {
|
|
626
|
+
if (this[kServiceWorker].state !== "parsed") return;
|
|
627
|
+
this[kServiceWorker]._setState("installing");
|
|
491
628
|
return new Promise((resolve, reject) => {
|
|
492
|
-
const event = new
|
|
629
|
+
const event = new ShovelInstallEvent();
|
|
493
630
|
process.nextTick(() => {
|
|
494
631
|
try {
|
|
495
632
|
this.dispatchEvent(event);
|
|
@@ -500,7 +637,7 @@ var ShovelServiceWorkerRegistration = class extends EventTarget {
|
|
|
500
637
|
}
|
|
501
638
|
const promises = event.getPromises();
|
|
502
639
|
if (promises.length === 0) {
|
|
503
|
-
this.
|
|
640
|
+
this[kServiceWorker]._setState("installed");
|
|
504
641
|
resolve();
|
|
505
642
|
} else {
|
|
506
643
|
promiseWithTimeout(
|
|
@@ -508,7 +645,7 @@ var ShovelServiceWorkerRegistration = class extends EventTarget {
|
|
|
508
645
|
3e4,
|
|
509
646
|
"ServiceWorker install event timed out after 30s - waitUntil promises did not resolve"
|
|
510
647
|
).then(() => {
|
|
511
|
-
this.
|
|
648
|
+
this[kServiceWorker]._setState("installed");
|
|
512
649
|
resolve();
|
|
513
650
|
}).catch(reject);
|
|
514
651
|
}
|
|
@@ -516,15 +653,16 @@ var ShovelServiceWorkerRegistration = class extends EventTarget {
|
|
|
516
653
|
});
|
|
517
654
|
}
|
|
518
655
|
/**
|
|
519
|
-
*
|
|
656
|
+
* Dispatch the activate lifecycle event
|
|
657
|
+
* @internal Use runLifecycle() instead of calling this directly
|
|
520
658
|
*/
|
|
521
|
-
async
|
|
522
|
-
if (this.
|
|
659
|
+
async [kDispatchActivate]() {
|
|
660
|
+
if (this[kServiceWorker].state !== "installed") {
|
|
523
661
|
throw new Error("ServiceWorker must be installed before activation");
|
|
524
662
|
}
|
|
525
|
-
this.
|
|
663
|
+
this[kServiceWorker]._setState("activating");
|
|
526
664
|
return new Promise((resolve, reject) => {
|
|
527
|
-
const event = new
|
|
665
|
+
const event = new ShovelActivateEvent();
|
|
528
666
|
process.nextTick(() => {
|
|
529
667
|
try {
|
|
530
668
|
this.dispatchEvent(event);
|
|
@@ -535,7 +673,7 @@ var ShovelServiceWorkerRegistration = class extends EventTarget {
|
|
|
535
673
|
}
|
|
536
674
|
const promises = event.getPromises();
|
|
537
675
|
if (promises.length === 0) {
|
|
538
|
-
this.
|
|
676
|
+
this[kServiceWorker]._setState("activated");
|
|
539
677
|
resolve();
|
|
540
678
|
} else {
|
|
541
679
|
promiseWithTimeout(
|
|
@@ -543,7 +681,7 @@ var ShovelServiceWorkerRegistration = class extends EventTarget {
|
|
|
543
681
|
3e4,
|
|
544
682
|
"ServiceWorker activate event timed out after 30s - waitUntil promises did not resolve"
|
|
545
683
|
).then(() => {
|
|
546
|
-
this.
|
|
684
|
+
this[kServiceWorker]._setState("activated");
|
|
547
685
|
resolve();
|
|
548
686
|
}).catch(reject);
|
|
549
687
|
}
|
|
@@ -551,13 +689,18 @@ var ShovelServiceWorkerRegistration = class extends EventTarget {
|
|
|
551
689
|
});
|
|
552
690
|
}
|
|
553
691
|
/**
|
|
554
|
-
* Handle a fetch request
|
|
692
|
+
* Handle a fetch request
|
|
693
|
+
* @internal Use the kHandleRequest symbol to access this method
|
|
694
|
+
*
|
|
695
|
+
* Platforms create a ShovelFetchEvent (or subclass) with platform-specific
|
|
696
|
+
* properties and hooks, then pass it to this method for dispatching.
|
|
697
|
+
*
|
|
698
|
+
* @param event - The fetch event to handle (created by platform adapter)
|
|
555
699
|
*/
|
|
556
|
-
async
|
|
557
|
-
if (this.
|
|
700
|
+
async [kHandleRequest](event) {
|
|
701
|
+
if (this[kServiceWorker].state !== "activated") {
|
|
558
702
|
throw new Error("ServiceWorker not activated");
|
|
559
703
|
}
|
|
560
|
-
const event = new FetchEvent(request);
|
|
561
704
|
return cookieStoreStorage.run(event.cookieStore, async () => {
|
|
562
705
|
this.dispatchEvent(event);
|
|
563
706
|
event[kEndDispatchPhase]();
|
|
@@ -567,12 +710,6 @@ var ShovelServiceWorkerRegistration = class extends EventTarget {
|
|
|
567
710
|
);
|
|
568
711
|
}
|
|
569
712
|
const response = await event.getResponse();
|
|
570
|
-
const promises = event.getPromises();
|
|
571
|
-
if (promises.length > 0) {
|
|
572
|
-
Promise.allSettled(promises).catch(
|
|
573
|
-
(err) => self.loggers.open("platform").error`waitUntil error: ${err}`
|
|
574
|
-
);
|
|
575
|
-
}
|
|
576
713
|
if (event.cookieStore.hasChanges()) {
|
|
577
714
|
const setCookieHeaders = event.cookieStore.getSetCookieHeaders();
|
|
578
715
|
const headers = new Headers(response.headers);
|
|
@@ -592,10 +729,20 @@ var ShovelServiceWorkerRegistration = class extends EventTarget {
|
|
|
592
729
|
* Check if ready to handle requests (Shovel extension)
|
|
593
730
|
*/
|
|
594
731
|
get ready() {
|
|
595
|
-
return this.
|
|
732
|
+
return this[kServiceWorker].state === "activated";
|
|
596
733
|
}
|
|
597
734
|
// Events: updatefound (standard), plus Shovel lifecycle events
|
|
598
735
|
};
|
|
736
|
+
async function runLifecycle(registration, stage = "activate") {
|
|
737
|
+
await registration[kDispatchInstall]();
|
|
738
|
+
if (stage === "activate") {
|
|
739
|
+
await registration[kDispatchActivate]();
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
async function dispatchRequest(registration, requestOrEvent) {
|
|
743
|
+
const event = requestOrEvent instanceof ShovelFetchEvent ? requestOrEvent : new ShovelFetchEvent(requestOrEvent);
|
|
744
|
+
return registration[kHandleRequest](event);
|
|
745
|
+
}
|
|
599
746
|
var ShovelServiceWorkerContainer = class extends EventTarget {
|
|
600
747
|
#registrations;
|
|
601
748
|
controller;
|
|
@@ -635,8 +782,8 @@ var ShovelServiceWorkerContainer = class extends EventTarget {
|
|
|
635
782
|
const scope = this.#normalizeScope(options?.scope || "/");
|
|
636
783
|
let registration = this.#registrations.get(scope);
|
|
637
784
|
if (registration) {
|
|
638
|
-
registration.
|
|
639
|
-
registration.
|
|
785
|
+
registration[kServiceWorker].scriptURL = url;
|
|
786
|
+
registration[kServiceWorker]._setState("parsed");
|
|
640
787
|
} else {
|
|
641
788
|
registration = new ShovelServiceWorkerRegistration(scope, url);
|
|
642
789
|
this.#registrations.set(scope, registration);
|
|
@@ -656,29 +803,13 @@ var ShovelServiceWorkerContainer = class extends EventTarget {
|
|
|
656
803
|
}
|
|
657
804
|
return false;
|
|
658
805
|
}
|
|
659
|
-
/**
|
|
660
|
-
* Route a request to the appropriate registration based on scope matching
|
|
661
|
-
*/
|
|
662
|
-
async handleRequest(request) {
|
|
663
|
-
const url = new URL(request.url);
|
|
664
|
-
const pathname = url.pathname;
|
|
665
|
-
const matchingScope = this.#findMatchingScope(pathname);
|
|
666
|
-
if (matchingScope) {
|
|
667
|
-
const registration = this.#registrations.get(matchingScope);
|
|
668
|
-
if (registration && registration.ready) {
|
|
669
|
-
return await registration.handleRequest(request);
|
|
670
|
-
}
|
|
671
|
-
}
|
|
672
|
-
return null;
|
|
673
|
-
}
|
|
674
806
|
/**
|
|
675
807
|
* Install and activate all registrations
|
|
676
808
|
*/
|
|
677
809
|
async installAll() {
|
|
678
810
|
const installations = Array.from(this.#registrations.values()).map(
|
|
679
811
|
async (registration) => {
|
|
680
|
-
await registration
|
|
681
|
-
await registration.activate();
|
|
812
|
+
await runLifecycle(registration);
|
|
682
813
|
}
|
|
683
814
|
);
|
|
684
815
|
await promiseWithTimeout(
|
|
@@ -707,19 +838,6 @@ var ShovelServiceWorkerContainer = class extends EventTarget {
|
|
|
707
838
|
}
|
|
708
839
|
return scope;
|
|
709
840
|
}
|
|
710
|
-
/**
|
|
711
|
-
* Find the most specific scope that matches a pathname
|
|
712
|
-
*/
|
|
713
|
-
#findMatchingScope(pathname) {
|
|
714
|
-
const scopes = Array.from(this.#registrations.keys());
|
|
715
|
-
scopes.sort((a, b) => b.length - a.length);
|
|
716
|
-
for (const scope of scopes) {
|
|
717
|
-
if (pathname.startsWith(scope === "/" ? "/" : scope)) {
|
|
718
|
-
return scope;
|
|
719
|
-
}
|
|
720
|
-
}
|
|
721
|
-
return null;
|
|
722
|
-
}
|
|
723
841
|
// Events: controllerchange, message, messageerror, updatefound
|
|
724
842
|
};
|
|
725
843
|
var Notification = class extends EventTarget {
|
|
@@ -775,7 +893,7 @@ var Notification = class extends EventTarget {
|
|
|
775
893
|
// Events: click, close, error, show
|
|
776
894
|
};
|
|
777
895
|
Notification.permission = "denied";
|
|
778
|
-
var NotificationEvent = class extends
|
|
896
|
+
var NotificationEvent = class extends ShovelExtendableEvent {
|
|
779
897
|
action;
|
|
780
898
|
notification;
|
|
781
899
|
reply;
|
|
@@ -786,7 +904,7 @@ var NotificationEvent = class extends ExtendableEvent {
|
|
|
786
904
|
this.reply = eventInitDict.reply ?? null;
|
|
787
905
|
}
|
|
788
906
|
};
|
|
789
|
-
var PushEvent = class extends
|
|
907
|
+
var PushEvent = class extends ShovelExtendableEvent {
|
|
790
908
|
data;
|
|
791
909
|
constructor(type, eventInitDict) {
|
|
792
910
|
super(type, eventInitDict);
|
|
@@ -819,7 +937,7 @@ var ShovelPushMessageData = class {
|
|
|
819
937
|
return new TextDecoder().decode(this._data);
|
|
820
938
|
}
|
|
821
939
|
};
|
|
822
|
-
var SyncEvent = class extends
|
|
940
|
+
var SyncEvent = class extends ShovelExtendableEvent {
|
|
823
941
|
tag;
|
|
824
942
|
lastChance;
|
|
825
943
|
constructor(type, eventInitDict) {
|
|
@@ -842,6 +960,7 @@ var ServiceWorkerGlobals = class {
|
|
|
842
960
|
// Storage APIs
|
|
843
961
|
caches;
|
|
844
962
|
directories;
|
|
963
|
+
databases;
|
|
845
964
|
loggers;
|
|
846
965
|
// Clients API
|
|
847
966
|
// Our custom Clients implementation provides core functionality compatible with the Web API
|
|
@@ -903,14 +1022,17 @@ var ServiceWorkerGlobals = class {
|
|
|
903
1022
|
}
|
|
904
1023
|
const request = new Request(new URL(urlString, "http://localhost"), init);
|
|
905
1024
|
return fetchDepthStorage.run(currentDepth + 1, () => {
|
|
906
|
-
return
|
|
1025
|
+
return dispatchRequest(
|
|
1026
|
+
this.registration,
|
|
1027
|
+
request
|
|
1028
|
+
);
|
|
907
1029
|
});
|
|
908
1030
|
}
|
|
909
1031
|
queueMicrotask(callback) {
|
|
910
1032
|
globalThis.queueMicrotask(callback);
|
|
911
1033
|
}
|
|
912
1034
|
reportError(e) {
|
|
913
|
-
|
|
1035
|
+
getLogger(["shovel", "platform"]).error`reportError: ${e}`;
|
|
914
1036
|
}
|
|
915
1037
|
setInterval(handler, timeout, ...args) {
|
|
916
1038
|
return globalThis.setInterval(handler, timeout, ...args);
|
|
@@ -951,6 +1073,7 @@ var ServiceWorkerGlobals = class {
|
|
|
951
1073
|
this.registration = options.registration;
|
|
952
1074
|
this.caches = options.caches;
|
|
953
1075
|
this.directories = options.directories;
|
|
1076
|
+
this.databases = options.databases;
|
|
954
1077
|
this.loggers = options.loggers;
|
|
955
1078
|
this.#isDevelopment = options.isDevelopment ?? false;
|
|
956
1079
|
this.clients = this.#createClientsAPI();
|
|
@@ -987,9 +1110,11 @@ var ServiceWorkerGlobals = class {
|
|
|
987
1110
|
* Allows the ServiceWorker to activate immediately
|
|
988
1111
|
*/
|
|
989
1112
|
async skipWaiting() {
|
|
990
|
-
|
|
1113
|
+
getLogger(["shovel", "platform"]).debug("skipWaiting() called");
|
|
991
1114
|
if (!this.#isDevelopment) {
|
|
992
|
-
|
|
1115
|
+
getLogger(["shovel", "platform"]).debug(
|
|
1116
|
+
"skipWaiting() - production graceful restart not implemented"
|
|
1117
|
+
);
|
|
993
1118
|
}
|
|
994
1119
|
}
|
|
995
1120
|
/**
|
|
@@ -997,8 +1122,7 @@ var ServiceWorkerGlobals = class {
|
|
|
997
1122
|
* other events (like "message" for worker threads) go to native handler
|
|
998
1123
|
*/
|
|
999
1124
|
addEventListener(type, listener, options) {
|
|
1000
|
-
if (!listener)
|
|
1001
|
-
return;
|
|
1125
|
+
if (!listener) return;
|
|
1002
1126
|
if (isServiceWorkerEvent(type)) {
|
|
1003
1127
|
this.registration.addEventListener(type, listener, options);
|
|
1004
1128
|
} else {
|
|
@@ -1009,8 +1133,7 @@ var ServiceWorkerGlobals = class {
|
|
|
1009
1133
|
}
|
|
1010
1134
|
}
|
|
1011
1135
|
removeEventListener(type, listener, options) {
|
|
1012
|
-
if (!listener)
|
|
1013
|
-
return;
|
|
1136
|
+
if (!listener) return;
|
|
1014
1137
|
if (isServiceWorkerEvent(type)) {
|
|
1015
1138
|
this.registration.removeEventListener(type, listener, options);
|
|
1016
1139
|
} else {
|
|
@@ -1053,6 +1176,9 @@ var ServiceWorkerGlobals = class {
|
|
|
1053
1176
|
g.dispatchEvent = this.dispatchEvent.bind(this);
|
|
1054
1177
|
g.caches = this.caches;
|
|
1055
1178
|
g.directories = this.directories;
|
|
1179
|
+
if (this.databases) {
|
|
1180
|
+
g.databases = this.databases;
|
|
1181
|
+
}
|
|
1056
1182
|
g.loggers = this.loggers;
|
|
1057
1183
|
g.registration = this.registration;
|
|
1058
1184
|
g.skipWaiting = this.skipWaiting.bind(this);
|
|
@@ -1079,117 +1205,269 @@ var ServiceWorkerGlobals = class {
|
|
|
1079
1205
|
}
|
|
1080
1206
|
}
|
|
1081
1207
|
};
|
|
1082
|
-
|
|
1083
|
-
"
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1208
|
+
function isClass(fn) {
|
|
1209
|
+
return typeof fn === "function" && fn.prototype !== void 0;
|
|
1210
|
+
}
|
|
1211
|
+
function createDirectoryFactory(configs) {
|
|
1212
|
+
return async (name) => {
|
|
1213
|
+
const config = configs[name];
|
|
1214
|
+
if (!config) {
|
|
1215
|
+
throw new Error(
|
|
1216
|
+
`Directory "${name}" is not configured. Available directories: ${Object.keys(configs).join(", ") || "(none)"}`
|
|
1217
|
+
);
|
|
1218
|
+
}
|
|
1219
|
+
const { impl, ...dirOptions } = config;
|
|
1220
|
+
if (!impl) {
|
|
1221
|
+
throw new Error(
|
|
1222
|
+
`Directory "${name}" has no impl. Ensure the directory module is configured.`
|
|
1223
|
+
);
|
|
1224
|
+
}
|
|
1225
|
+
if (isClass(impl)) {
|
|
1226
|
+
return new impl(name, dirOptions);
|
|
1227
|
+
} else {
|
|
1228
|
+
return impl(name, dirOptions);
|
|
1229
|
+
}
|
|
1230
|
+
};
|
|
1231
|
+
}
|
|
1232
|
+
function createCacheFactory(options) {
|
|
1233
|
+
const { configs, usePostMessage = false } = options;
|
|
1234
|
+
return async (name) => {
|
|
1235
|
+
if (usePostMessage) {
|
|
1236
|
+
return new PostMessageCache(name);
|
|
1237
|
+
}
|
|
1238
|
+
const config = configs[name];
|
|
1239
|
+
if (!config) {
|
|
1240
|
+
throw new Error(
|
|
1241
|
+
`Cache "${name}" is not configured. Available caches: ${Object.keys(configs).join(", ") || "(none)"}`
|
|
1242
|
+
);
|
|
1243
|
+
}
|
|
1244
|
+
const { impl, ...cacheOptions } = config;
|
|
1245
|
+
if (!impl) {
|
|
1246
|
+
throw new Error(
|
|
1247
|
+
`Cache "${name}" has no impl. Ensure the cache module is configured.`
|
|
1248
|
+
);
|
|
1249
|
+
}
|
|
1250
|
+
if (isClass(impl)) {
|
|
1251
|
+
return new impl(name, cacheOptions);
|
|
1252
|
+
} else {
|
|
1253
|
+
return impl(name, cacheOptions);
|
|
1254
|
+
}
|
|
1255
|
+
};
|
|
1256
|
+
}
|
|
1257
|
+
async function initWorkerRuntime(options) {
|
|
1258
|
+
const { config } = options;
|
|
1259
|
+
const runtimeLogger = getLogger(["shovel", "platform"]);
|
|
1260
|
+
if (config?.logging) {
|
|
1261
|
+
await configureLogging(config.logging);
|
|
1262
|
+
}
|
|
1263
|
+
runtimeLogger.debug("Initializing worker runtime");
|
|
1264
|
+
const caches = new CustomCacheStorage(
|
|
1265
|
+
createCacheFactory({
|
|
1266
|
+
configs: config?.caches ?? {},
|
|
1267
|
+
usePostMessage: true
|
|
1268
|
+
})
|
|
1269
|
+
);
|
|
1270
|
+
const directories = new CustomDirectoryStorage(
|
|
1271
|
+
createDirectoryFactory(config?.directories ?? {})
|
|
1272
|
+
);
|
|
1273
|
+
let databases;
|
|
1274
|
+
if (config?.databases && Object.keys(config.databases).length > 0) {
|
|
1275
|
+
const factory = createDatabaseFactory(config.databases);
|
|
1276
|
+
databases = new CustomDatabaseStorage(factory);
|
|
1277
|
+
}
|
|
1278
|
+
const loggers = new CustomLoggerStorage(
|
|
1279
|
+
(categories) => getLogger(categories)
|
|
1280
|
+
);
|
|
1281
|
+
const registration = new ShovelServiceWorkerRegistration();
|
|
1282
|
+
const scope = new ServiceWorkerGlobals({
|
|
1283
|
+
registration,
|
|
1284
|
+
caches,
|
|
1285
|
+
directories,
|
|
1286
|
+
databases,
|
|
1287
|
+
loggers
|
|
1288
|
+
});
|
|
1289
|
+
scope.install();
|
|
1290
|
+
runtimeLogger.debug("Worker runtime initialized");
|
|
1291
|
+
return { registration, scope, caches, directories, databases, loggers };
|
|
1126
1292
|
}
|
|
1127
|
-
|
|
1128
|
-
const
|
|
1129
|
-
const
|
|
1130
|
-
const
|
|
1131
|
-
const
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1293
|
+
function startWorkerMessageLoop(options) {
|
|
1294
|
+
const registration = options instanceof ShovelServiceWorkerRegistration ? options : options.registration;
|
|
1295
|
+
const databases = options instanceof ShovelServiceWorkerRegistration ? void 0 : options.databases;
|
|
1296
|
+
const messageLogger = getLogger(["shovel", "platform"]);
|
|
1297
|
+
const workerId = Math.random().toString(36).substring(2, 8);
|
|
1298
|
+
function sendMessage(message, transfer) {
|
|
1299
|
+
if (transfer && transfer.length > 0) {
|
|
1300
|
+
postMessage(message, transfer);
|
|
1301
|
+
} else {
|
|
1302
|
+
postMessage(message);
|
|
1137
1303
|
}
|
|
1138
1304
|
}
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1305
|
+
async function handleFetchRequest(message) {
|
|
1306
|
+
try {
|
|
1307
|
+
const request = new Request(message.request.url, {
|
|
1308
|
+
method: message.request.method,
|
|
1309
|
+
headers: message.request.headers,
|
|
1310
|
+
body: message.request.body
|
|
1311
|
+
});
|
|
1312
|
+
const response = await dispatchRequest(registration, request);
|
|
1313
|
+
const body = await response.arrayBuffer();
|
|
1314
|
+
const headers = Object.fromEntries(response.headers.entries());
|
|
1315
|
+
if (!headers["Content-Type"] && !headers["content-type"]) {
|
|
1316
|
+
headers["Content-Type"] = "text/plain; charset=utf-8";
|
|
1146
1317
|
}
|
|
1318
|
+
const responseMsg = {
|
|
1319
|
+
type: "response",
|
|
1320
|
+
response: {
|
|
1321
|
+
status: response.status,
|
|
1322
|
+
statusText: response.statusText,
|
|
1323
|
+
headers,
|
|
1324
|
+
body
|
|
1325
|
+
},
|
|
1326
|
+
requestID: message.requestID
|
|
1327
|
+
};
|
|
1328
|
+
sendMessage(responseMsg, [body]);
|
|
1329
|
+
} catch (error) {
|
|
1330
|
+
messageLogger.error(`[Worker-${workerId}] Request failed: {error}`, {
|
|
1331
|
+
error
|
|
1332
|
+
});
|
|
1333
|
+
const errorMsg = {
|
|
1334
|
+
type: "error",
|
|
1335
|
+
error: error instanceof Error ? error.message : String(error),
|
|
1336
|
+
stack: error instanceof Error ? error.stack : void 0,
|
|
1337
|
+
requestID: message.requestID
|
|
1338
|
+
};
|
|
1339
|
+
sendMessage(errorMsg);
|
|
1147
1340
|
}
|
|
1148
1341
|
}
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1342
|
+
function handleMessage(event) {
|
|
1343
|
+
const message = event.data;
|
|
1344
|
+
if (message?.type === "cache:response" || message?.type === "cache:error") {
|
|
1345
|
+
messageLogger.debug(`[Worker-${workerId}] Forwarding cache message`, {
|
|
1346
|
+
type: message.type,
|
|
1347
|
+
requestID: message.requestID
|
|
1348
|
+
});
|
|
1349
|
+
handleCacheResponse(message);
|
|
1350
|
+
return;
|
|
1351
|
+
}
|
|
1352
|
+
if (message?.type === "request") {
|
|
1353
|
+
handleFetchRequest(message).catch((error) => {
|
|
1354
|
+
messageLogger.error(`[Worker-${workerId}] Unhandled error: {error}`, {
|
|
1355
|
+
error
|
|
1356
|
+
});
|
|
1357
|
+
});
|
|
1358
|
+
return;
|
|
1359
|
+
}
|
|
1360
|
+
if (message?.type === "shutdown") {
|
|
1361
|
+
messageLogger.debug(`[Worker-${workerId}] Received shutdown signal`);
|
|
1362
|
+
(async () => {
|
|
1363
|
+
try {
|
|
1364
|
+
if (databases) {
|
|
1365
|
+
await databases.closeAll();
|
|
1366
|
+
messageLogger.debug(`[Worker-${workerId}] Databases closed`);
|
|
1367
|
+
}
|
|
1368
|
+
sendMessage({ type: "shutdown-complete" });
|
|
1369
|
+
messageLogger.debug(`[Worker-${workerId}] Shutdown complete`);
|
|
1370
|
+
} catch (error) {
|
|
1371
|
+
messageLogger.error(`[Worker-${workerId}] Shutdown error: {error}`, {
|
|
1372
|
+
error
|
|
1373
|
+
});
|
|
1374
|
+
sendMessage({ type: "shutdown-complete" });
|
|
1375
|
+
}
|
|
1376
|
+
})();
|
|
1377
|
+
return;
|
|
1378
|
+
}
|
|
1379
|
+
if (message?.type) {
|
|
1380
|
+
messageLogger.debug(`[Worker-${workerId}] Unknown message type`, {
|
|
1381
|
+
type: message.type
|
|
1382
|
+
});
|
|
1383
|
+
}
|
|
1152
1384
|
}
|
|
1153
|
-
|
|
1154
|
-
|
|
1385
|
+
self.addEventListener("message", handleMessage);
|
|
1386
|
+
sendMessage({ type: "ready" });
|
|
1387
|
+
messageLogger.debug(`[Worker-${workerId}] Message loop started`);
|
|
1388
|
+
}
|
|
1389
|
+
var SHOVEL_DEFAULT_LOGGERS = [
|
|
1390
|
+
{ category: ["shovel"], level: "info", sinks: ["console"] },
|
|
1391
|
+
{ category: ["logtape", "meta"], level: "warning", sinks: ["console"] }
|
|
1392
|
+
];
|
|
1393
|
+
async function createSink(config) {
|
|
1394
|
+
const {
|
|
1395
|
+
impl,
|
|
1396
|
+
path,
|
|
1397
|
+
// Extract path for file-based sinks
|
|
1398
|
+
...sinkOptions
|
|
1399
|
+
} = config;
|
|
1400
|
+
if (!impl) {
|
|
1401
|
+
throw new Error(
|
|
1402
|
+
`Sink has no impl. Ensure the sink module is configured in shovel.json.`
|
|
1403
|
+
);
|
|
1404
|
+
}
|
|
1405
|
+
if (path !== void 0) {
|
|
1406
|
+
return impl(path, sinkOptions);
|
|
1407
|
+
} else if (Object.keys(sinkOptions).length > 0) {
|
|
1408
|
+
return impl(sinkOptions);
|
|
1409
|
+
} else {
|
|
1410
|
+
return impl();
|
|
1411
|
+
}
|
|
1412
|
+
}
|
|
1413
|
+
function normalizeCategory(category) {
|
|
1414
|
+
return typeof category === "string" ? [category] : category;
|
|
1415
|
+
}
|
|
1416
|
+
async function configureLogging(loggingConfig) {
|
|
1417
|
+
const userSinks = loggingConfig.sinks || {};
|
|
1418
|
+
const userLoggers = loggingConfig.loggers || [];
|
|
1419
|
+
const sinks = {
|
|
1420
|
+
console: getConsoleSink()
|
|
1155
1421
|
};
|
|
1156
|
-
const
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1422
|
+
for (const [name, config] of Object.entries(userSinks)) {
|
|
1423
|
+
sinks[name] = await createSink(config);
|
|
1424
|
+
}
|
|
1425
|
+
const userCategoryKeys = new Set(
|
|
1426
|
+
userLoggers.map((l) => JSON.stringify(normalizeCategory(l.category)))
|
|
1427
|
+
);
|
|
1428
|
+
const mergedLoggers = [
|
|
1429
|
+
// Shovel defaults (unless overridden by user)
|
|
1430
|
+
...SHOVEL_DEFAULT_LOGGERS.filter(
|
|
1431
|
+
(l) => !userCategoryKeys.has(JSON.stringify(normalizeCategory(l.category)))
|
|
1432
|
+
),
|
|
1433
|
+
// User loggers
|
|
1434
|
+
...userLoggers
|
|
1435
|
+
];
|
|
1436
|
+
const loggers = mergedLoggers.map((loggerConfig) => {
|
|
1437
|
+
const result = {
|
|
1438
|
+
category: normalizeCategory(loggerConfig.category)
|
|
1165
1439
|
};
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1440
|
+
if (loggerConfig.level) {
|
|
1441
|
+
result.lowestLevel = loggerConfig.level;
|
|
1442
|
+
}
|
|
1443
|
+
result.sinks = loggerConfig.sinks ?? ["console"];
|
|
1444
|
+
if (loggerConfig.parentSinks) {
|
|
1445
|
+
result.parentSinks = loggerConfig.parentSinks;
|
|
1446
|
+
}
|
|
1447
|
+
return result;
|
|
1171
1448
|
});
|
|
1172
1449
|
await configure({
|
|
1173
|
-
reset,
|
|
1450
|
+
reset: true,
|
|
1174
1451
|
sinks,
|
|
1175
1452
|
loggers
|
|
1176
1453
|
});
|
|
1177
1454
|
}
|
|
1178
1455
|
export {
|
|
1179
|
-
|
|
1456
|
+
CustomDatabaseStorage,
|
|
1180
1457
|
CustomLoggerStorage,
|
|
1181
1458
|
DedicatedWorkerGlobalScope,
|
|
1182
|
-
ExtendableEvent,
|
|
1183
1459
|
ExtendableMessageEvent,
|
|
1184
|
-
FetchEvent,
|
|
1185
|
-
InstallEvent,
|
|
1186
1460
|
Notification,
|
|
1187
1461
|
NotificationEvent,
|
|
1188
1462
|
PushEvent,
|
|
1189
1463
|
RequestCookieStore,
|
|
1190
1464
|
ServiceWorkerGlobals,
|
|
1465
|
+
ShovelActivateEvent,
|
|
1191
1466
|
ShovelClient,
|
|
1192
1467
|
ShovelClients,
|
|
1468
|
+
ShovelExtendableEvent,
|
|
1469
|
+
ShovelFetchEvent,
|
|
1470
|
+
ShovelInstallEvent,
|
|
1193
1471
|
ShovelNavigationPreloadManager,
|
|
1194
1472
|
ShovelPushMessageData,
|
|
1195
1473
|
ShovelServiceWorker,
|
|
@@ -1199,7 +1477,17 @@ export {
|
|
|
1199
1477
|
SyncEvent,
|
|
1200
1478
|
WorkerGlobalScope,
|
|
1201
1479
|
configureLogging,
|
|
1480
|
+
createCacheFactory,
|
|
1481
|
+
createDatabaseFactory,
|
|
1482
|
+
createDirectoryFactory,
|
|
1483
|
+
dispatchRequest,
|
|
1484
|
+
initWorkerRuntime,
|
|
1485
|
+
kDispatchActivate,
|
|
1486
|
+
kDispatchInstall,
|
|
1487
|
+
kServiceWorker,
|
|
1202
1488
|
parseCookieHeader,
|
|
1203
1489
|
parseSetCookieHeader,
|
|
1204
|
-
|
|
1490
|
+
runLifecycle,
|
|
1491
|
+
serializeCookie,
|
|
1492
|
+
startWorkerMessageLoop
|
|
1205
1493
|
};
|