@vite-pwa/workbox-window 8.0.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/LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright 2018 Google LLC
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,80 @@
1
+ <h1 align='center'>
2
+ ESM build of <a href='https://www.npmjs.com/package/workbox-window' target="__blank">workbox-window</a>
3
+ </h1>
4
+ <p align='center'>
5
+ <a href='https://www.npmjs.com/package/@vite-pwa/workbox-window' target="__blank">
6
+ <img src='https://img.shields.io/npm/v/@vite-pwa/workbox-window?color=33A6B8&label=' alt="NPM version">
7
+ </a>
8
+ <a href="https://www.npmjs.com/package/@vite-pwa/workbox-window" target="__blank">
9
+ <img alt="NPM Downloads" src="https://img.shields.io/npm/dm/@vite-pwa/workbox-window?color=476582&label=">
10
+ </a>
11
+ <a href="https://developers.google.com/web/tools/workbox/modules/workbox-window" target="__blank">
12
+ <img src="https://img.shields.io/static/v1?label=&message=docs%20%26%20guides&color=2e859c" alt="Docs & Guides">
13
+ </a>
14
+ <br>
15
+ <a href="https://github.com/vite-pwa/workbox-window-es" target="__blank">
16
+ <img alt="GitHub stars" src="https://img.shields.io/github/stars/vite-pwa/workbox-window-es?style=social">
17
+ </a>
18
+ </p>
19
+
20
+ <br>
21
+
22
+ <p align="center">
23
+ <a href="https://cdn.jsdelivr.net/gh/antfu/static/sponsors.svg">
24
+ <img src='https://cdn.jsdelivr.net/gh/antfu/static/sponsors.svg'/>
25
+ </a>
26
+ </p>
27
+
28
+
29
+ ## ๐Ÿš€ Features
30
+
31
+ - ๐Ÿ“– [**Documentation & guides**](https://vite-pwa-org.netlify.app/)
32
+ - ๐Ÿ‘Œ **Zero-Config**: sensible built-in default configs for common use cases
33
+ - ๐Ÿ”ฉ **Extensible**: expose the full ability to customize the behavior of the plugin
34
+ - ๐Ÿฆพ **Type Strong**: written in [TypeScript](https://www.typescriptlang.org/)
35
+ - ๐Ÿ”Œ **Offline Support**: generate service worker with offline support (via Workbox)
36
+ - โšก **Fully tree shakable**: auto-inject Web App Manifest
37
+ - ๐Ÿ’ฌ **Prompt for new content**: built-in support for Vanilla JavaScript, Vue 3, React, Svelte, SolidJS and Preact
38
+ - โš™๏ธ **Stale-while-revalidate**: automatic reload when new content is available
39
+ - โœจ **Static assets handling**: configure static assets for offline support
40
+ - ๐Ÿž **Development Support**: debug your custom service worker logic as you develop your application
41
+ - ๐Ÿ› ๏ธ **Versatile**: integration with meta-frameworks: [รฎles](https://github.com/ElMassimo/iles), [SvelteKit](https://github.com/sveltejs/kit), [VitePress](https://github.com/vuejs/vitepress), [Astro](https://github.com/withastro/astro), and [Nuxt 3](https://github.com/nuxt/nuxt)
42
+ - ๐Ÿ’ฅ **PWA Assets Generator**: generate all the PWA assets from a single command and a single source image
43
+
44
+ ## ๐Ÿ› ๏ธ @vite-pwa/workbox-window
45
+
46
+ ESM build of [workbox-window](https://www.npmjs.com/package/workbox-window).
47
+
48
+ This module's documentation can be found at https://developers.google.com/web/tools/workbox/modules/workbox-window.
49
+
50
+ `@vite-pwa/workbox-window` includes missing `installing` event in `Workbox` class.
51
+
52
+ ## ๐Ÿ“ฆ Install
53
+
54
+ ```sh
55
+ # pnpm
56
+ pnpm add @vite-pwa/workbox-window
57
+
58
+ # npm
59
+ npm i @vite-pwa/workbox-window
60
+
61
+ # yarn
62
+ yarn add @vite-pwa/workbox-window
63
+ ```
64
+
65
+ ## ๐Ÿฆ„ Usage
66
+
67
+ ```js
68
+ // ESM
69
+ import { Workbox } from '@vite-pwa/workbox-window'
70
+ ```
71
+
72
+ ```js
73
+ // CommonJS
74
+ const { Workbox } = require('@vite-pwa/workbox-window')
75
+ ```
76
+
77
+ ## ๐Ÿ“„ License
78
+
79
+ [MIT](./LICENSE)
80
+
package/dist/index.cjs ADDED
@@ -0,0 +1,583 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var src_exports = {};
22
+ __export(src_exports, {
23
+ Workbox: () => Workbox,
24
+ WorkboxEvent: () => WorkboxEvent,
25
+ messageSW: () => messageSW
26
+ });
27
+ module.exports = __toCommonJS(src_exports);
28
+
29
+ // src/messageSW.ts
30
+ function messageSW(sw, data) {
31
+ return new Promise((resolve) => {
32
+ const messageChannel = new MessageChannel();
33
+ messageChannel.port1.onmessage = (event) => {
34
+ resolve(event.data);
35
+ };
36
+ sw.postMessage(data, [messageChannel.port2]);
37
+ });
38
+ }
39
+
40
+ // src/utils/dontWaitFor.ts
41
+ function dontWaitFor(promise) {
42
+ void promise.then(() => {
43
+ });
44
+ }
45
+
46
+ // src/utils/logger.ts
47
+ var logger = process.env.NODE_ENV === "production" ? null : (() => {
48
+ if (!("__WB_DISABLE_DEV_LOGS" in globalThis))
49
+ self.__WB_DISABLE_DEV_LOGS = false;
50
+ let inGroup = false;
51
+ const methodToColorMap = {
52
+ debug: "#7f8c8d",
53
+ // Gray
54
+ log: "#2ecc71",
55
+ // Green
56
+ warn: "#f39c12",
57
+ // Yellow
58
+ error: "#c0392b",
59
+ // Red
60
+ groupCollapsed: "#3498db",
61
+ // Blue
62
+ groupEnd: null
63
+ // No colored prefix on groupEnd
64
+ };
65
+ const print = function(method, args) {
66
+ if (self.__WB_DISABLE_DEV_LOGS)
67
+ return;
68
+ if (method === "groupCollapsed") {
69
+ if (typeof navigator !== "undefined" && /^((?!chrome|android).)*safari/i.test(navigator.userAgent)) {
70
+ console[method](...args);
71
+ return;
72
+ }
73
+ }
74
+ const styles = [
75
+ `background: ${methodToColorMap[method]}`,
76
+ "border-radius: 0.5em",
77
+ "color: white",
78
+ "font-weight: bold",
79
+ "padding: 2px 0.5em"
80
+ ];
81
+ const logPrefix = inGroup ? [] : ["%c@vite-pwa/workbox-window", styles.join(";")];
82
+ console[method](...logPrefix, ...args);
83
+ if (method === "groupCollapsed")
84
+ inGroup = true;
85
+ if (method === "groupEnd")
86
+ inGroup = false;
87
+ };
88
+ const api = {};
89
+ const loggerMethods = Object.keys(methodToColorMap);
90
+ for (const key of loggerMethods) {
91
+ const method = key;
92
+ api[method] = (...args) => {
93
+ print(method, args);
94
+ };
95
+ }
96
+ return api;
97
+ })();
98
+
99
+ // src/utils/Deferred.ts
100
+ var Deferred = class {
101
+ promise;
102
+ resolve;
103
+ reject;
104
+ /**
105
+ * Creates a promise and exposes its resolve and reject functions as methods.
106
+ */
107
+ constructor() {
108
+ this.promise = new Promise((resolve, reject) => {
109
+ this.resolve = resolve;
110
+ this.reject = reject;
111
+ });
112
+ }
113
+ };
114
+
115
+ // src/utils/WorkboxEventTarget.ts
116
+ var WorkboxEventTarget = class {
117
+ _eventListenerRegistry = /* @__PURE__ */ new Map();
118
+ /**
119
+ * @param {string} type
120
+ * @param {Function} listener
121
+ * @private
122
+ */
123
+ addEventListener(type, listener) {
124
+ const foo = this._getEventListenersByType(type);
125
+ foo.add(listener);
126
+ }
127
+ /**
128
+ * @param {string} type
129
+ * @param {Function} listener
130
+ * @private
131
+ */
132
+ removeEventListener(type, listener) {
133
+ this._getEventListenersByType(type).delete(listener);
134
+ }
135
+ /**
136
+ * @param {object} event
137
+ * @private
138
+ */
139
+ dispatchEvent(event) {
140
+ event.target = this;
141
+ const listeners = this._getEventListenersByType(event.type);
142
+ for (const listener of listeners)
143
+ listener(event);
144
+ }
145
+ /**
146
+ * Returns a Set of listeners associated with the passed event type.
147
+ * If no handlers have been registered, an empty Set is returned.
148
+ *
149
+ * @param {string} type The event type.
150
+ * @return {Set<ListenerCallback>} An array of handler functions.
151
+ * @private
152
+ */
153
+ _getEventListenersByType(type) {
154
+ if (!this._eventListenerRegistry.has(type))
155
+ this._eventListenerRegistry.set(type, /* @__PURE__ */ new Set());
156
+ return this._eventListenerRegistry.get(type);
157
+ }
158
+ };
159
+
160
+ // src/utils/urlsMatch.ts
161
+ function urlsMatch(url1, url2) {
162
+ const { href } = location;
163
+ return new URL(url1, href).href === new URL(url2, href).href;
164
+ }
165
+
166
+ // src/utils/WorkboxEvent.ts
167
+ var WorkboxEvent = class {
168
+ constructor(type, props) {
169
+ this.type = type;
170
+ Object.assign(this, props);
171
+ }
172
+ target;
173
+ sw;
174
+ originalEvent;
175
+ isExternal;
176
+ };
177
+
178
+ // src/Workbox.ts
179
+ var WAITING_TIMEOUT_DURATION = 200;
180
+ var REGISTRATION_TIMEOUT_DURATION = 6e4;
181
+ var SKIP_WAITING_MESSAGE = { type: "SKIP_WAITING" };
182
+ var Workbox = class extends WorkboxEventTarget {
183
+ _scriptURL;
184
+ _registerOptions = {};
185
+ _updateFoundCount = 0;
186
+ // Deferreds we can resolve later.
187
+ _swDeferred = new Deferred();
188
+ _activeDeferred = new Deferred();
189
+ _controllingDeferred = new Deferred();
190
+ _registrationTime = 0;
191
+ _isUpdate;
192
+ _compatibleControllingSW;
193
+ _registration;
194
+ _sw;
195
+ _ownSWs = /* @__PURE__ */ new Set();
196
+ _externalSW;
197
+ _waitingTimeout;
198
+ /**
199
+ * Creates a new Workbox instance with a script URL and service worker
200
+ * options. The script URL and options are the same as those used when
201
+ * calling [navigator.serviceWorker.register(scriptURL, options)](https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerContainer/register).
202
+ *
203
+ * @param {string|TrustedScriptURL} scriptURL The service worker script
204
+ * associated with this instance. Using a
205
+ * [`TrustedScriptURL`](https://web.dev/trusted-types/) is supported.
206
+ * @param {object} [registerOptions] The service worker options associated
207
+ * with this instance.
208
+ */
209
+ // eslint-disable-next-line @typescript-eslint/ban-types
210
+ constructor(scriptURL, registerOptions = {}) {
211
+ super();
212
+ this._scriptURL = scriptURL;
213
+ this._registerOptions = registerOptions;
214
+ navigator.serviceWorker.addEventListener("message", this._onMessage);
215
+ }
216
+ /**
217
+ * Registers a service worker for this instances script URL and service
218
+ * worker options. By default this method delays registration until after
219
+ * the window has loaded.
220
+ *
221
+ * @param {object} [options]
222
+ * @param {Function} [options.immediate] Setting this to true will
223
+ * register the service worker immediately, even if the window has
224
+ * not loaded (not recommended).
225
+ */
226
+ async register({ immediate = false } = {}) {
227
+ if (process.env.NODE_ENV !== "production") {
228
+ if (this._registrationTime) {
229
+ logger.error(
230
+ "Cannot re-register a Workbox instance after it has been registered. Create a new instance instead."
231
+ );
232
+ return;
233
+ }
234
+ }
235
+ if (!immediate && document.readyState !== "complete")
236
+ await new Promise((resolve) => window.addEventListener("load", resolve));
237
+ this._isUpdate = Boolean(navigator.serviceWorker.controller);
238
+ this._compatibleControllingSW = this._getControllingSWIfCompatible();
239
+ this._registration = await this._registerScript();
240
+ if (this._compatibleControllingSW) {
241
+ this._sw = this._compatibleControllingSW;
242
+ this._activeDeferred.resolve(this._compatibleControllingSW);
243
+ this._controllingDeferred.resolve(this._compatibleControllingSW);
244
+ this._compatibleControllingSW.addEventListener(
245
+ "statechange",
246
+ this._onStateChange,
247
+ { once: true }
248
+ );
249
+ }
250
+ const waitingSW = this._registration.waiting;
251
+ if (waitingSW && urlsMatch(waitingSW.scriptURL, this._scriptURL.toString())) {
252
+ this._sw = waitingSW;
253
+ dontWaitFor(
254
+ Promise.resolve().then(() => {
255
+ this.dispatchEvent(
256
+ new WorkboxEvent("waiting", {
257
+ sw: waitingSW,
258
+ wasWaitingBeforeRegister: true
259
+ })
260
+ );
261
+ if (process.env.NODE_ENV !== "production") {
262
+ logger.warn(
263
+ "A service worker was already waiting to activate before this script was registered..."
264
+ );
265
+ }
266
+ })
267
+ );
268
+ }
269
+ if (this._sw) {
270
+ this._swDeferred.resolve(this._sw);
271
+ this._ownSWs.add(this._sw);
272
+ }
273
+ if (process.env.NODE_ENV !== "production") {
274
+ logger.log(
275
+ "Successfully registered service worker.",
276
+ this._scriptURL.toString()
277
+ );
278
+ if (navigator.serviceWorker.controller) {
279
+ if (this._compatibleControllingSW) {
280
+ logger.debug(
281
+ "A service worker with the same script URL is already controlling this page."
282
+ );
283
+ } else {
284
+ logger.debug(
285
+ "A service worker with a different script URL is currently controlling the page. The browser is now fetching the new script now..."
286
+ );
287
+ }
288
+ }
289
+ const currentPageIsOutOfScope = () => {
290
+ const scopeURL = new URL(
291
+ this._registerOptions.scope || this._scriptURL.toString(),
292
+ document.baseURI
293
+ );
294
+ const scopeURLBasePath = new URL("./", scopeURL.href).pathname;
295
+ return !location.pathname.startsWith(scopeURLBasePath);
296
+ };
297
+ if (currentPageIsOutOfScope()) {
298
+ logger.warn(
299
+ "The current page is not in scope for the registered service worker. Was this a mistake?"
300
+ );
301
+ }
302
+ }
303
+ this._registration.addEventListener("updatefound", this._onUpdateFound);
304
+ navigator.serviceWorker.addEventListener(
305
+ "controllerchange",
306
+ this._onControllerChange
307
+ );
308
+ return this._registration;
309
+ }
310
+ /**
311
+ * Checks for updates of the registered service worker.
312
+ */
313
+ async update() {
314
+ if (!this._registration) {
315
+ if (process.env.NODE_ENV !== "production") {
316
+ logger.error(
317
+ "Cannot update a Workbox instance without being registered. Register the Workbox instance first."
318
+ );
319
+ }
320
+ return;
321
+ }
322
+ await this._registration.update();
323
+ }
324
+ /**
325
+ * Resolves to the service worker registered by this instance as soon as it
326
+ * is active. If a service worker was already controlling at registration
327
+ * time then it will resolve to that if the script URLs (and optionally
328
+ * script versions) match, otherwise it will wait until an update is found
329
+ * and activates.
330
+ *
331
+ * @return {Promise<ServiceWorker>}
332
+ */
333
+ get active() {
334
+ return this._activeDeferred.promise;
335
+ }
336
+ /**
337
+ * Resolves to the service worker registered by this instance as soon as it
338
+ * is controlling the page. If a service worker was already controlling at
339
+ * registration time then it will resolve to that if the script URLs (and
340
+ * optionally script versions) match, otherwise it will wait until an update
341
+ * is found and starts controlling the page.
342
+ * Note: the first time a service worker is installed it will active but
343
+ * not start controlling the page unless `clients.claim()` is called in the
344
+ * service worker.
345
+ *
346
+ * @return {Promise<ServiceWorker>}
347
+ */
348
+ get controlling() {
349
+ return this._controllingDeferred.promise;
350
+ }
351
+ /**
352
+ * Resolves with a reference to a service worker that matches the script URL
353
+ * of this instance, as soon as it's available.
354
+ *
355
+ * If, at registration time, there's already an active or waiting service
356
+ * worker with a matching script URL, it will be used (with the waiting
357
+ * service worker taking precedence over the active service worker if both
358
+ * match, since the waiting service worker would have been registered more
359
+ * recently).
360
+ * If there's no matching active or waiting service worker at registration
361
+ * time then the promise will not resolve until an update is found and starts
362
+ * installing, at which point the installing service worker is used.
363
+ *
364
+ * @return {Promise<ServiceWorker>}
365
+ */
366
+ getSW() {
367
+ return this._sw !== void 0 ? Promise.resolve(this._sw) : this._swDeferred.promise;
368
+ }
369
+ /**
370
+ * Sends the passed data object to the service worker registered by this
371
+ * instance (via {@link workbox-window.Workbox#getSW}) and resolves
372
+ * with a response (if any).
373
+ *
374
+ * A response can be set in a message handler in the service worker by
375
+ * calling `event.ports[0].postMessage(...)`, which will resolve the promise
376
+ * returned by `messageSW()`. If no response is set, the promise will never
377
+ * resolve.
378
+ *
379
+ * @param {object} data An object to send to the service worker
380
+ * @return {Promise<object>}
381
+ */
382
+ // We might be able to change the 'data' type to Record<string, unknown> in the future.
383
+ async messageSW(data) {
384
+ const sw = await this.getSW();
385
+ return messageSW(sw, data);
386
+ }
387
+ /**
388
+ * Sends a `{type: 'SKIP_WAITING'}` message to the service worker that's
389
+ * currently in the `waiting` state associated with the current registration.
390
+ *
391
+ * If there is no current registration or no service worker is `waiting`,
392
+ * calling this will have no effect.
393
+ */
394
+ messageSkipWaiting() {
395
+ if (this._registration && this._registration.waiting)
396
+ void messageSW(this._registration.waiting, SKIP_WAITING_MESSAGE);
397
+ }
398
+ /**
399
+ * Checks for a service worker already controlling the page and returns
400
+ * it if its script URL matches.
401
+ *
402
+ * @private
403
+ * @return {ServiceWorker|undefined}
404
+ */
405
+ _getControllingSWIfCompatible() {
406
+ const controller = navigator.serviceWorker.controller;
407
+ if (controller && urlsMatch(controller.scriptURL, this._scriptURL.toString()))
408
+ return controller;
409
+ else
410
+ return void 0;
411
+ }
412
+ /**
413
+ * Registers a service worker for this instances script URL and register
414
+ * options and tracks the time registration was complete.
415
+ *
416
+ * @private
417
+ */
418
+ async _registerScript() {
419
+ try {
420
+ const reg = await navigator.serviceWorker.register(
421
+ this._scriptURL,
422
+ this._registerOptions
423
+ );
424
+ this._registrationTime = performance.now();
425
+ return reg;
426
+ } catch (error) {
427
+ if (process.env.NODE_ENV !== "production")
428
+ logger.error(error);
429
+ throw error;
430
+ }
431
+ }
432
+ /**
433
+ * @private
434
+ */
435
+ _onUpdateFound = (originalEvent) => {
436
+ const registration = this._registration;
437
+ const installingSW = registration.installing;
438
+ const updateLikelyTriggeredExternally = !!(this._updateFoundCount > 0 || !urlsMatch(installingSW.scriptURL, this._scriptURL.toString()) || performance.now() > this._registrationTime + REGISTRATION_TIMEOUT_DURATION);
439
+ if (updateLikelyTriggeredExternally) {
440
+ this._externalSW = installingSW;
441
+ registration.removeEventListener("updatefound", this._onUpdateFound);
442
+ } else {
443
+ this._sw = installingSW;
444
+ this._ownSWs.add(installingSW);
445
+ this._swDeferred.resolve(installingSW);
446
+ if (process.env.NODE_ENV !== "production") {
447
+ if (navigator.serviceWorker.controller)
448
+ logger.log("Updated service worker found. Installing now...");
449
+ else
450
+ logger.log("Service worker is installing...");
451
+ }
452
+ }
453
+ this.dispatchEvent(
454
+ new WorkboxEvent("installing", {
455
+ sw: installingSW,
456
+ originalEvent,
457
+ isExternal: updateLikelyTriggeredExternally,
458
+ isUpdate: this._isUpdate
459
+ })
460
+ );
461
+ ++this._updateFoundCount;
462
+ installingSW.addEventListener("statechange", this._onStateChange);
463
+ };
464
+ /**
465
+ * @private
466
+ * @param {Event} originalEvent
467
+ */
468
+ _onStateChange = (originalEvent) => {
469
+ const registration = this._registration;
470
+ const sw = originalEvent.target;
471
+ const { state } = sw;
472
+ const isExternal = sw === this._externalSW;
473
+ const eventProps = {
474
+ sw,
475
+ isExternal,
476
+ originalEvent
477
+ };
478
+ if (!isExternal && this._isUpdate)
479
+ eventProps.isUpdate = true;
480
+ this.dispatchEvent(
481
+ new WorkboxEvent(state, eventProps)
482
+ );
483
+ if (state === "installed") {
484
+ this._waitingTimeout = self.setTimeout(() => {
485
+ if (state === "installed" && registration.waiting === sw) {
486
+ this.dispatchEvent(new WorkboxEvent("waiting", eventProps));
487
+ if (process.env.NODE_ENV !== "production") {
488
+ if (isExternal) {
489
+ logger.warn(
490
+ "An external service worker has installed but is waiting for this client to close before activating..."
491
+ );
492
+ } else {
493
+ logger.warn(
494
+ "The service worker has installed but is waiting for existing clients to close before activating..."
495
+ );
496
+ }
497
+ }
498
+ }
499
+ }, WAITING_TIMEOUT_DURATION);
500
+ } else if (state === "activating") {
501
+ clearTimeout(this._waitingTimeout);
502
+ if (!isExternal)
503
+ this._activeDeferred.resolve(sw);
504
+ }
505
+ if (process.env.NODE_ENV !== "production") {
506
+ switch (state) {
507
+ case "installed":
508
+ if (isExternal) {
509
+ logger.warn(
510
+ "An external service worker has installed. You may want to suggest users reload this page."
511
+ );
512
+ } else {
513
+ logger.log("Registered service worker installed.");
514
+ }
515
+ break;
516
+ case "activated":
517
+ if (isExternal) {
518
+ logger.warn("An external service worker has activated.");
519
+ } else {
520
+ logger.log("Registered service worker activated.");
521
+ if (sw !== navigator.serviceWorker.controller) {
522
+ logger.warn(
523
+ "The registered service worker is active but not yet controlling the page. Reload or run `clients.claim()` in the service worker."
524
+ );
525
+ }
526
+ }
527
+ break;
528
+ case "redundant":
529
+ if (sw === this._compatibleControllingSW)
530
+ logger.log("Previously controlling service worker now redundant!");
531
+ else if (!isExternal)
532
+ logger.log("Registered service worker now redundant!");
533
+ break;
534
+ }
535
+ }
536
+ };
537
+ /**
538
+ * @private
539
+ * @param {Event} originalEvent
540
+ */
541
+ _onControllerChange = (originalEvent) => {
542
+ const sw = this._sw;
543
+ const isExternal = sw !== navigator.serviceWorker.controller;
544
+ this.dispatchEvent(
545
+ new WorkboxEvent("controlling", {
546
+ isExternal,
547
+ originalEvent,
548
+ sw,
549
+ isUpdate: this._isUpdate
550
+ })
551
+ );
552
+ if (!isExternal) {
553
+ if (process.env.NODE_ENV !== "production")
554
+ logger.log("Registered service worker now controlling this page.");
555
+ this._controllingDeferred.resolve(sw);
556
+ }
557
+ };
558
+ /**
559
+ * @private
560
+ * @param {Event} originalEvent
561
+ */
562
+ _onMessage = async (originalEvent) => {
563
+ const { data, ports, source } = originalEvent;
564
+ await this.getSW();
565
+ if (this._ownSWs.has(source)) {
566
+ this.dispatchEvent(
567
+ new WorkboxEvent("message", {
568
+ // Can't change type 'any' of data.
569
+ data,
570
+ originalEvent,
571
+ ports,
572
+ sw: source
573
+ })
574
+ );
575
+ }
576
+ };
577
+ };
578
+ // Annotate the CommonJS export names for ESM import in node:
579
+ 0 && (module.exports = {
580
+ Workbox,
581
+ WorkboxEvent,
582
+ messageSW
583
+ });