@angular/service-worker 21.0.0-next.8 → 21.0.0-rc.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/fesm2022/config.mjs +185 -203
- package/fesm2022/config.mjs.map +1 -1
- package/fesm2022/service-worker.mjs +379 -636
- package/fesm2022/service-worker.mjs.map +1 -1
- package/ngsw-worker.js +1 -1
- package/package.json +2 -2
- package/types/config.d.ts +1 -1
- package/types/service-worker.d.ts +8 -9
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @license Angular v21.0.0-
|
|
2
|
+
* @license Angular v21.0.0-rc.0
|
|
3
3
|
* (c) 2010-2025 Google LLC. https://angular.dev/
|
|
4
4
|
* License: MIT
|
|
5
5
|
*/
|
|
@@ -10,682 +10,425 @@ import { Observable, Subject, NEVER } from 'rxjs';
|
|
|
10
10
|
import { switchMap, take, filter, map } from 'rxjs/operators';
|
|
11
11
|
|
|
12
12
|
const ERR_SW_NOT_SUPPORTED = 'Service workers are disabled or not supported by this browser';
|
|
13
|
-
/**
|
|
14
|
-
* @publicApi
|
|
15
|
-
*/
|
|
16
13
|
class NgswCommChannel {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
14
|
+
serviceWorker;
|
|
15
|
+
worker;
|
|
16
|
+
registration;
|
|
17
|
+
events;
|
|
18
|
+
constructor(serviceWorker, injector) {
|
|
19
|
+
this.serviceWorker = serviceWorker;
|
|
20
|
+
if (!serviceWorker) {
|
|
21
|
+
this.worker = this.events = this.registration = new Observable(subscriber => subscriber.error(new _RuntimeError(5601, (typeof ngDevMode === 'undefined' || ngDevMode) && ERR_SW_NOT_SUPPORTED)));
|
|
22
|
+
} else {
|
|
23
|
+
let currentWorker = null;
|
|
24
|
+
const workerSubject = new Subject();
|
|
25
|
+
this.worker = new Observable(subscriber => {
|
|
26
|
+
if (currentWorker !== null) {
|
|
27
|
+
subscriber.next(currentWorker);
|
|
28
28
|
}
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
});
|
|
38
|
-
const updateController = () => {
|
|
39
|
-
const { controller } = serviceWorker;
|
|
40
|
-
if (controller === null) {
|
|
41
|
-
return;
|
|
42
|
-
}
|
|
43
|
-
currentWorker = controller;
|
|
44
|
-
workerSubject.next(currentWorker);
|
|
45
|
-
};
|
|
46
|
-
serviceWorker.addEventListener('controllerchange', updateController);
|
|
47
|
-
updateController();
|
|
48
|
-
this.registration = this.worker.pipe(switchMap(() => serviceWorker.getRegistration().then((registration) => {
|
|
49
|
-
// The `getRegistration()` method may return undefined in
|
|
50
|
-
// non-secure contexts or incognito mode, where service worker
|
|
51
|
-
// registration might not be allowed.
|
|
52
|
-
if (!registration) {
|
|
53
|
-
throw new _RuntimeError(5601 /* RuntimeErrorCode.SERVICE_WORKER_DISABLED_OR_NOT_SUPPORTED_BY_THIS_BROWSER */, (typeof ngDevMode === 'undefined' || ngDevMode) && ERR_SW_NOT_SUPPORTED);
|
|
54
|
-
}
|
|
55
|
-
return registration;
|
|
56
|
-
})));
|
|
57
|
-
const _events = new Subject();
|
|
58
|
-
this.events = _events.asObservable();
|
|
59
|
-
const messageListener = (event) => {
|
|
60
|
-
const { data } = event;
|
|
61
|
-
if (data?.type) {
|
|
62
|
-
_events.next(data);
|
|
63
|
-
}
|
|
64
|
-
};
|
|
65
|
-
serviceWorker.addEventListener('message', messageListener);
|
|
66
|
-
// The injector is optional to avoid breaking changes.
|
|
67
|
-
const appRef = injector?.get(ApplicationRef, null, { optional: true });
|
|
68
|
-
appRef?.onDestroy(() => {
|
|
69
|
-
serviceWorker.removeEventListener('controllerchange', updateController);
|
|
70
|
-
serviceWorker.removeEventListener('message', messageListener);
|
|
71
|
-
});
|
|
29
|
+
return workerSubject.subscribe(v => subscriber.next(v));
|
|
30
|
+
});
|
|
31
|
+
const updateController = () => {
|
|
32
|
+
const {
|
|
33
|
+
controller
|
|
34
|
+
} = serviceWorker;
|
|
35
|
+
if (controller === null) {
|
|
36
|
+
return;
|
|
72
37
|
}
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
resolve();
|
|
82
|
-
});
|
|
83
|
-
});
|
|
84
|
-
}
|
|
85
|
-
postMessageWithOperation(type, payload, operationNonce) {
|
|
86
|
-
const waitForOperationCompleted = this.waitForOperationCompleted(operationNonce);
|
|
87
|
-
const postMessage = this.postMessage(type, payload);
|
|
88
|
-
return Promise.all([postMessage, waitForOperationCompleted]).then(([, result]) => result);
|
|
89
|
-
}
|
|
90
|
-
generateNonce() {
|
|
91
|
-
return Math.round(Math.random() * 10000000);
|
|
92
|
-
}
|
|
93
|
-
eventsOfType(type) {
|
|
94
|
-
let filterFn;
|
|
95
|
-
if (typeof type === 'string') {
|
|
96
|
-
filterFn = (event) => event.type === type;
|
|
38
|
+
currentWorker = controller;
|
|
39
|
+
workerSubject.next(currentWorker);
|
|
40
|
+
};
|
|
41
|
+
serviceWorker.addEventListener('controllerchange', updateController);
|
|
42
|
+
updateController();
|
|
43
|
+
this.registration = this.worker.pipe(switchMap(() => serviceWorker.getRegistration().then(registration => {
|
|
44
|
+
if (!registration) {
|
|
45
|
+
throw new _RuntimeError(5601, (typeof ngDevMode === 'undefined' || ngDevMode) && ERR_SW_NOT_SUPPORTED);
|
|
97
46
|
}
|
|
98
|
-
|
|
99
|
-
|
|
47
|
+
return registration;
|
|
48
|
+
})));
|
|
49
|
+
const _events = new Subject();
|
|
50
|
+
this.events = _events.asObservable();
|
|
51
|
+
const messageListener = event => {
|
|
52
|
+
const {
|
|
53
|
+
data
|
|
54
|
+
} = event;
|
|
55
|
+
if (data?.type) {
|
|
56
|
+
_events.next(data);
|
|
100
57
|
}
|
|
101
|
-
|
|
58
|
+
};
|
|
59
|
+
serviceWorker.addEventListener('message', messageListener);
|
|
60
|
+
const appRef = injector?.get(ApplicationRef, null, {
|
|
61
|
+
optional: true
|
|
62
|
+
});
|
|
63
|
+
appRef?.onDestroy(() => {
|
|
64
|
+
serviceWorker.removeEventListener('controllerchange', updateController);
|
|
65
|
+
serviceWorker.removeEventListener('message', messageListener);
|
|
66
|
+
});
|
|
102
67
|
}
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
if (event.result !== undefined) {
|
|
111
|
-
return event.result;
|
|
112
|
-
}
|
|
113
|
-
throw new Error(event.error);
|
|
114
|
-
}))
|
|
115
|
-
.subscribe({
|
|
116
|
-
next: resolve,
|
|
117
|
-
error: reject,
|
|
118
|
-
});
|
|
68
|
+
}
|
|
69
|
+
postMessage(action, payload) {
|
|
70
|
+
return new Promise(resolve => {
|
|
71
|
+
this.worker.pipe(take(1)).subscribe(sw => {
|
|
72
|
+
sw.postMessage({
|
|
73
|
+
action,
|
|
74
|
+
...payload
|
|
119
75
|
});
|
|
76
|
+
resolve();
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
postMessageWithOperation(type, payload, operationNonce) {
|
|
81
|
+
const waitForOperationCompleted = this.waitForOperationCompleted(operationNonce);
|
|
82
|
+
const postMessage = this.postMessage(type, payload);
|
|
83
|
+
return Promise.all([postMessage, waitForOperationCompleted]).then(([, result]) => result);
|
|
84
|
+
}
|
|
85
|
+
generateNonce() {
|
|
86
|
+
return Math.round(Math.random() * 10000000);
|
|
87
|
+
}
|
|
88
|
+
eventsOfType(type) {
|
|
89
|
+
let filterFn;
|
|
90
|
+
if (typeof type === 'string') {
|
|
91
|
+
filterFn = event => event.type === type;
|
|
92
|
+
} else {
|
|
93
|
+
filterFn = event => type.includes(event.type);
|
|
120
94
|
}
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
95
|
+
return this.events.pipe(filter(filterFn));
|
|
96
|
+
}
|
|
97
|
+
nextEventOfType(type) {
|
|
98
|
+
return this.eventsOfType(type).pipe(take(1));
|
|
99
|
+
}
|
|
100
|
+
waitForOperationCompleted(nonce) {
|
|
101
|
+
return new Promise((resolve, reject) => {
|
|
102
|
+
this.eventsOfType('OPERATION_COMPLETED').pipe(filter(event => event.nonce === nonce), take(1), map(event => {
|
|
103
|
+
if (event.result !== undefined) {
|
|
104
|
+
return event.result;
|
|
105
|
+
}
|
|
106
|
+
throw new Error(event.error);
|
|
107
|
+
})).subscribe({
|
|
108
|
+
next: resolve,
|
|
109
|
+
error: reject
|
|
110
|
+
});
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
get isEnabled() {
|
|
114
|
+
return !!this.serviceWorker;
|
|
115
|
+
}
|
|
124
116
|
}
|
|
125
117
|
|
|
126
|
-
/**
|
|
127
|
-
* Subscribe and listen to
|
|
128
|
-
* [Web Push
|
|
129
|
-
* Notifications](https://developer.mozilla.org/en-US/docs/Web/API/Push_API/Best_Practices) through
|
|
130
|
-
* Angular Service Worker.
|
|
131
|
-
*
|
|
132
|
-
* @usageNotes
|
|
133
|
-
*
|
|
134
|
-
* You can inject a `SwPush` instance into any component or service
|
|
135
|
-
* as a dependency.
|
|
136
|
-
*
|
|
137
|
-
* <code-example path="service-worker/push/module.ts" region="inject-sw-push"
|
|
138
|
-
* header="app.component.ts"></code-example>
|
|
139
|
-
*
|
|
140
|
-
* To subscribe, call `SwPush.requestSubscription()`, which asks the user for permission.
|
|
141
|
-
* The call returns a `Promise` with a new
|
|
142
|
-
* [`PushSubscription`](https://developer.mozilla.org/en-US/docs/Web/API/PushSubscription)
|
|
143
|
-
* instance.
|
|
144
|
-
*
|
|
145
|
-
* <code-example path="service-worker/push/module.ts" region="subscribe-to-push"
|
|
146
|
-
* header="app.component.ts"></code-example>
|
|
147
|
-
*
|
|
148
|
-
* A request is rejected if the user denies permission, or if the browser
|
|
149
|
-
* blocks or does not support the Push API or ServiceWorkers.
|
|
150
|
-
* Check `SwPush.isEnabled` to confirm status.
|
|
151
|
-
*
|
|
152
|
-
* Invoke Push Notifications by pushing a message with the following payload.
|
|
153
|
-
*
|
|
154
|
-
* ```ts
|
|
155
|
-
* {
|
|
156
|
-
* "notification": {
|
|
157
|
-
* "actions": NotificationAction[],
|
|
158
|
-
* "badge": USVString,
|
|
159
|
-
* "body": DOMString,
|
|
160
|
-
* "data": any,
|
|
161
|
-
* "dir": "auto"|"ltr"|"rtl",
|
|
162
|
-
* "icon": USVString,
|
|
163
|
-
* "image": USVString,
|
|
164
|
-
* "lang": DOMString,
|
|
165
|
-
* "renotify": boolean,
|
|
166
|
-
* "requireInteraction": boolean,
|
|
167
|
-
* "silent": boolean,
|
|
168
|
-
* "tag": DOMString,
|
|
169
|
-
* "timestamp": DOMTimeStamp,
|
|
170
|
-
* "title": DOMString,
|
|
171
|
-
* "vibrate": number[]
|
|
172
|
-
* }
|
|
173
|
-
* }
|
|
174
|
-
* ```
|
|
175
|
-
*
|
|
176
|
-
* Only `title` is required. See `Notification`
|
|
177
|
-
* [instance
|
|
178
|
-
* properties](https://developer.mozilla.org/en-US/docs/Web/API/Notification#Instance_properties).
|
|
179
|
-
*
|
|
180
|
-
* While the subscription is active, Service Worker listens for
|
|
181
|
-
* [PushEvent](https://developer.mozilla.org/en-US/docs/Web/API/PushEvent)
|
|
182
|
-
* occurrences and creates
|
|
183
|
-
* [Notification](https://developer.mozilla.org/en-US/docs/Web/API/Notification)
|
|
184
|
-
* instances in response.
|
|
185
|
-
*
|
|
186
|
-
* Unsubscribe using `SwPush.unsubscribe()`.
|
|
187
|
-
*
|
|
188
|
-
* An application can subscribe to `SwPush.notificationClicks` observable to be notified when a user
|
|
189
|
-
* clicks on a notification. For example:
|
|
190
|
-
*
|
|
191
|
-
* <code-example path="service-worker/push/module.ts" region="subscribe-to-notification-clicks"
|
|
192
|
-
* header="app.component.ts"></code-example>
|
|
193
|
-
*
|
|
194
|
-
* You can read more on handling notification clicks in the [Service worker notifications
|
|
195
|
-
* guide](ecosystem/service-workers/push-notifications).
|
|
196
|
-
*
|
|
197
|
-
* @see [Push Notifications](https://developers.google.com/web/fundamentals/codelabs/push-notifications/)
|
|
198
|
-
* @see [Angular Push Notifications](https://blog.angular-university.io/angular-push-notifications/)
|
|
199
|
-
* @see [MDN: Push API](https://developer.mozilla.org/en-US/docs/Web/API/Push_API)
|
|
200
|
-
* @see [MDN: Notifications API](https://developer.mozilla.org/en-US/docs/Web/API/Notifications_API)
|
|
201
|
-
* @see [MDN: Web Push API Notifications best practices](https://developer.mozilla.org/en-US/docs/Web/API/Push_API/Best_Practices)
|
|
202
|
-
*
|
|
203
|
-
* @publicApi
|
|
204
|
-
*/
|
|
205
118
|
class SwPush {
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
* an empty string `''`.
|
|
227
|
-
*
|
|
228
|
-
* Note that the `notification` property does **not** contain a
|
|
229
|
-
* [Notification][Mozilla Notification] object but rather a
|
|
230
|
-
* [NotificationOptions](https://notifications.spec.whatwg.org/#dictdef-notificationoptions)
|
|
231
|
-
* object that also includes the `title` of the [Notification][Mozilla Notification] object.
|
|
232
|
-
*
|
|
233
|
-
* [Mozilla Notification]: https://developer.mozilla.org/en-US/docs/Web/API/Notification
|
|
234
|
-
*/
|
|
235
|
-
notificationCloses;
|
|
236
|
-
/**
|
|
237
|
-
* Emits updates to the push subscription, including both the previous (`oldSubscription`)
|
|
238
|
-
* and current (`newSubscription`) values. Either subscription may be `null`, depending on
|
|
239
|
-
* the context:
|
|
240
|
-
*
|
|
241
|
-
* - `oldSubscription` is `null` if no previous subscription existed.
|
|
242
|
-
* - `newSubscription` is `null` if the subscription was invalidated and not replaced.
|
|
243
|
-
*
|
|
244
|
-
* This stream allows clients to react to automatic changes in push subscriptions,
|
|
245
|
-
* such as those triggered by browser expiration or key rotation.
|
|
246
|
-
*
|
|
247
|
-
* [Push API]: https://w3c.github.io/push-api
|
|
248
|
-
*/
|
|
249
|
-
pushSubscriptionChanges;
|
|
250
|
-
/**
|
|
251
|
-
* Emits the currently active
|
|
252
|
-
* [PushSubscription](https://developer.mozilla.org/en-US/docs/Web/API/PushSubscription)
|
|
253
|
-
* associated to the Service Worker registration or `null` if there is no subscription.
|
|
254
|
-
*/
|
|
255
|
-
subscription;
|
|
256
|
-
/**
|
|
257
|
-
* True if the Service Worker is enabled (supported by the browser and enabled via
|
|
258
|
-
* `ServiceWorkerModule`).
|
|
259
|
-
*/
|
|
260
|
-
get isEnabled() {
|
|
261
|
-
return this.sw.isEnabled;
|
|
119
|
+
sw;
|
|
120
|
+
messages;
|
|
121
|
+
notificationClicks;
|
|
122
|
+
notificationCloses;
|
|
123
|
+
pushSubscriptionChanges;
|
|
124
|
+
subscription;
|
|
125
|
+
get isEnabled() {
|
|
126
|
+
return this.sw.isEnabled;
|
|
127
|
+
}
|
|
128
|
+
pushManager = null;
|
|
129
|
+
subscriptionChanges = new Subject();
|
|
130
|
+
constructor(sw) {
|
|
131
|
+
this.sw = sw;
|
|
132
|
+
if (!sw.isEnabled) {
|
|
133
|
+
this.messages = NEVER;
|
|
134
|
+
this.notificationClicks = NEVER;
|
|
135
|
+
this.notificationCloses = NEVER;
|
|
136
|
+
this.pushSubscriptionChanges = NEVER;
|
|
137
|
+
this.subscription = NEVER;
|
|
138
|
+
return;
|
|
262
139
|
}
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
.pipe(map((message) => message.data));
|
|
282
|
-
this.pushSubscriptionChanges = this.sw
|
|
283
|
-
.eventsOfType('PUSH_SUBSCRIPTION_CHANGE')
|
|
284
|
-
.pipe(map((message) => message.data));
|
|
285
|
-
this.pushManager = this.sw.registration.pipe(map((registration) => registration.pushManager));
|
|
286
|
-
const workerDrivenSubscriptions = this.pushManager.pipe(switchMap((pm) => pm.getSubscription()));
|
|
287
|
-
this.subscription = new Observable((subscriber) => {
|
|
288
|
-
const workerDrivenSubscription = workerDrivenSubscriptions.subscribe(subscriber);
|
|
289
|
-
const subscriptionChanges = this.subscriptionChanges.subscribe(subscriber);
|
|
290
|
-
return () => {
|
|
291
|
-
workerDrivenSubscription.unsubscribe();
|
|
292
|
-
subscriptionChanges.unsubscribe();
|
|
293
|
-
};
|
|
294
|
-
});
|
|
140
|
+
this.messages = this.sw.eventsOfType('PUSH').pipe(map(message => message.data));
|
|
141
|
+
this.notificationClicks = this.sw.eventsOfType('NOTIFICATION_CLICK').pipe(map(message => message.data));
|
|
142
|
+
this.notificationCloses = this.sw.eventsOfType('NOTIFICATION_CLOSE').pipe(map(message => message.data));
|
|
143
|
+
this.pushSubscriptionChanges = this.sw.eventsOfType('PUSH_SUBSCRIPTION_CHANGE').pipe(map(message => message.data));
|
|
144
|
+
this.pushManager = this.sw.registration.pipe(map(registration => registration.pushManager));
|
|
145
|
+
const workerDrivenSubscriptions = this.pushManager.pipe(switchMap(pm => pm.getSubscription()));
|
|
146
|
+
this.subscription = new Observable(subscriber => {
|
|
147
|
+
const workerDrivenSubscription = workerDrivenSubscriptions.subscribe(subscriber);
|
|
148
|
+
const subscriptionChanges = this.subscriptionChanges.subscribe(subscriber);
|
|
149
|
+
return () => {
|
|
150
|
+
workerDrivenSubscription.unsubscribe();
|
|
151
|
+
subscriptionChanges.unsubscribe();
|
|
152
|
+
};
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
requestSubscription(options) {
|
|
156
|
+
if (!this.sw.isEnabled || this.pushManager === null) {
|
|
157
|
+
return Promise.reject(new Error(ERR_SW_NOT_SUPPORTED));
|
|
295
158
|
}
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
requestSubscription(options) {
|
|
304
|
-
if (!this.sw.isEnabled || this.pushManager === null) {
|
|
305
|
-
return Promise.reject(new Error(ERR_SW_NOT_SUPPORTED));
|
|
306
|
-
}
|
|
307
|
-
const pushOptions = { userVisibleOnly: true };
|
|
308
|
-
let key = this.decodeBase64(options.serverPublicKey.replace(/_/g, '/').replace(/-/g, '+'));
|
|
309
|
-
let applicationServerKey = new Uint8Array(new ArrayBuffer(key.length));
|
|
310
|
-
for (let i = 0; i < key.length; i++) {
|
|
311
|
-
applicationServerKey[i] = key.charCodeAt(i);
|
|
312
|
-
}
|
|
313
|
-
pushOptions.applicationServerKey = applicationServerKey;
|
|
314
|
-
return new Promise((resolve, reject) => {
|
|
315
|
-
this.pushManager.pipe(switchMap((pm) => pm.subscribe(pushOptions)), take(1)).subscribe({
|
|
316
|
-
next: (sub) => {
|
|
317
|
-
this.subscriptionChanges.next(sub);
|
|
318
|
-
resolve(sub);
|
|
319
|
-
},
|
|
320
|
-
error: reject,
|
|
321
|
-
});
|
|
322
|
-
});
|
|
159
|
+
const pushOptions = {
|
|
160
|
+
userVisibleOnly: true
|
|
161
|
+
};
|
|
162
|
+
let key = this.decodeBase64(options.serverPublicKey.replace(/_/g, '/').replace(/-/g, '+'));
|
|
163
|
+
let applicationServerKey = new Uint8Array(new ArrayBuffer(key.length));
|
|
164
|
+
for (let i = 0; i < key.length; i++) {
|
|
165
|
+
applicationServerKey[i] = key.charCodeAt(i);
|
|
323
166
|
}
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
}
|
|
339
|
-
return sub.unsubscribe().then((success) => {
|
|
340
|
-
if (!success) {
|
|
341
|
-
throw new _RuntimeError(5603 /* RuntimeErrorCode.PUSH_SUBSCRIPTION_UNSUBSCRIBE_FAILED */, (typeof ngDevMode === 'undefined' || ngDevMode) && 'Unsubscribe failed!');
|
|
342
|
-
}
|
|
343
|
-
this.subscriptionChanges.next(null);
|
|
344
|
-
});
|
|
345
|
-
};
|
|
346
|
-
return new Promise((resolve, reject) => {
|
|
347
|
-
this.subscription
|
|
348
|
-
.pipe(take(1), switchMap(doUnsubscribe))
|
|
349
|
-
.subscribe({ next: resolve, error: reject });
|
|
350
|
-
});
|
|
351
|
-
}
|
|
352
|
-
decodeBase64(input) {
|
|
353
|
-
return atob(input);
|
|
167
|
+
pushOptions.applicationServerKey = applicationServerKey;
|
|
168
|
+
return new Promise((resolve, reject) => {
|
|
169
|
+
this.pushManager.pipe(switchMap(pm => pm.subscribe(pushOptions)), take(1)).subscribe({
|
|
170
|
+
next: sub => {
|
|
171
|
+
this.subscriptionChanges.next(sub);
|
|
172
|
+
resolve(sub);
|
|
173
|
+
},
|
|
174
|
+
error: reject
|
|
175
|
+
});
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
unsubscribe() {
|
|
179
|
+
if (!this.sw.isEnabled) {
|
|
180
|
+
return Promise.reject(new Error(ERR_SW_NOT_SUPPORTED));
|
|
354
181
|
}
|
|
355
|
-
|
|
356
|
-
|
|
182
|
+
const doUnsubscribe = sub => {
|
|
183
|
+
if (sub === null) {
|
|
184
|
+
throw new _RuntimeError(5602, (typeof ngDevMode === 'undefined' || ngDevMode) && 'Not subscribed to push notifications.');
|
|
185
|
+
}
|
|
186
|
+
return sub.unsubscribe().then(success => {
|
|
187
|
+
if (!success) {
|
|
188
|
+
throw new _RuntimeError(5603, (typeof ngDevMode === 'undefined' || ngDevMode) && 'Unsubscribe failed!');
|
|
189
|
+
}
|
|
190
|
+
this.subscriptionChanges.next(null);
|
|
191
|
+
});
|
|
192
|
+
};
|
|
193
|
+
return new Promise((resolve, reject) => {
|
|
194
|
+
this.subscription.pipe(take(1), switchMap(doUnsubscribe)).subscribe({
|
|
195
|
+
next: resolve,
|
|
196
|
+
error: reject
|
|
197
|
+
});
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
decodeBase64(input) {
|
|
201
|
+
return atob(input);
|
|
202
|
+
}
|
|
203
|
+
static ɵfac = i0.ɵɵngDeclareFactory({
|
|
204
|
+
minVersion: "12.0.0",
|
|
205
|
+
version: "21.0.0-rc.0",
|
|
206
|
+
ngImport: i0,
|
|
207
|
+
type: SwPush,
|
|
208
|
+
deps: [{
|
|
209
|
+
token: NgswCommChannel
|
|
210
|
+
}],
|
|
211
|
+
target: i0.ɵɵFactoryTarget.Injectable
|
|
212
|
+
});
|
|
213
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({
|
|
214
|
+
minVersion: "12.0.0",
|
|
215
|
+
version: "21.0.0-rc.0",
|
|
216
|
+
ngImport: i0,
|
|
217
|
+
type: SwPush
|
|
218
|
+
});
|
|
357
219
|
}
|
|
358
|
-
i0.ɵɵngDeclareClassMetadata({
|
|
359
|
-
|
|
360
|
-
|
|
220
|
+
i0.ɵɵngDeclareClassMetadata({
|
|
221
|
+
minVersion: "12.0.0",
|
|
222
|
+
version: "21.0.0-rc.0",
|
|
223
|
+
ngImport: i0,
|
|
224
|
+
type: SwPush,
|
|
225
|
+
decorators: [{
|
|
226
|
+
type: Injectable
|
|
227
|
+
}],
|
|
228
|
+
ctorParameters: () => [{
|
|
229
|
+
type: NgswCommChannel
|
|
230
|
+
}]
|
|
231
|
+
});
|
|
361
232
|
|
|
362
|
-
/**
|
|
363
|
-
* Subscribe to update notifications from the Service Worker, trigger update
|
|
364
|
-
* checks, and forcibly activate updates.
|
|
365
|
-
*
|
|
366
|
-
* @see {@link /ecosystem/service-workers/communications Service Worker Communication Guide}
|
|
367
|
-
*
|
|
368
|
-
* @publicApi
|
|
369
|
-
*/
|
|
370
233
|
class SwUpdate {
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
* worker to serve this client is in a broken state that cannot be recovered from without a full
|
|
385
|
-
* page reload.
|
|
386
|
-
*/
|
|
387
|
-
unrecoverable;
|
|
388
|
-
/**
|
|
389
|
-
* True if the Service Worker is enabled (supported by the browser and enabled via
|
|
390
|
-
* `ServiceWorkerModule`).
|
|
391
|
-
*/
|
|
392
|
-
get isEnabled() {
|
|
393
|
-
return this.sw.isEnabled;
|
|
234
|
+
sw;
|
|
235
|
+
versionUpdates;
|
|
236
|
+
unrecoverable;
|
|
237
|
+
get isEnabled() {
|
|
238
|
+
return this.sw.isEnabled;
|
|
239
|
+
}
|
|
240
|
+
ongoingCheckForUpdate = null;
|
|
241
|
+
constructor(sw) {
|
|
242
|
+
this.sw = sw;
|
|
243
|
+
if (!sw.isEnabled) {
|
|
244
|
+
this.versionUpdates = NEVER;
|
|
245
|
+
this.unrecoverable = NEVER;
|
|
246
|
+
return;
|
|
394
247
|
}
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
return;
|
|
402
|
-
}
|
|
403
|
-
this.versionUpdates = this.sw.eventsOfType([
|
|
404
|
-
'VERSION_DETECTED',
|
|
405
|
-
'VERSION_INSTALLATION_FAILED',
|
|
406
|
-
'VERSION_READY',
|
|
407
|
-
'NO_NEW_VERSION_DETECTED',
|
|
408
|
-
'VERSION_FAILED',
|
|
409
|
-
]);
|
|
410
|
-
this.unrecoverable = this.sw.eventsOfType('UNRECOVERABLE_STATE');
|
|
248
|
+
this.versionUpdates = this.sw.eventsOfType(['VERSION_DETECTED', 'VERSION_INSTALLATION_FAILED', 'VERSION_READY', 'NO_NEW_VERSION_DETECTED', 'VERSION_FAILED']);
|
|
249
|
+
this.unrecoverable = this.sw.eventsOfType('UNRECOVERABLE_STATE');
|
|
250
|
+
}
|
|
251
|
+
checkForUpdate() {
|
|
252
|
+
if (!this.sw.isEnabled) {
|
|
253
|
+
return Promise.reject(new Error(ERR_SW_NOT_SUPPORTED));
|
|
411
254
|
}
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
* for activation.
|
|
415
|
-
*
|
|
416
|
-
* @returns a promise that
|
|
417
|
-
* - resolves to `true` if a new version was found and is ready to be activated.
|
|
418
|
-
* - resolves to `false` if no new version was found
|
|
419
|
-
* - rejects if any error occurs
|
|
420
|
-
*/
|
|
421
|
-
checkForUpdate() {
|
|
422
|
-
if (!this.sw.isEnabled) {
|
|
423
|
-
return Promise.reject(new Error(ERR_SW_NOT_SUPPORTED));
|
|
424
|
-
}
|
|
425
|
-
if (this.ongoingCheckForUpdate) {
|
|
426
|
-
return this.ongoingCheckForUpdate;
|
|
427
|
-
}
|
|
428
|
-
const nonce = this.sw.generateNonce();
|
|
429
|
-
this.ongoingCheckForUpdate = this.sw
|
|
430
|
-
.postMessageWithOperation('CHECK_FOR_UPDATES', { nonce }, nonce)
|
|
431
|
-
.finally(() => {
|
|
432
|
-
this.ongoingCheckForUpdate = null;
|
|
433
|
-
});
|
|
434
|
-
return this.ongoingCheckForUpdate;
|
|
255
|
+
if (this.ongoingCheckForUpdate) {
|
|
256
|
+
return this.ongoingCheckForUpdate;
|
|
435
257
|
}
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
* such as lazy-loaded chunks, whose filenames may change between
|
|
448
|
-
* versions.
|
|
449
|
-
*
|
|
450
|
-
* Only use this method, if you are certain it is safe for your specific use case.
|
|
451
|
-
*
|
|
452
|
-
* </div>
|
|
453
|
-
*
|
|
454
|
-
* @returns a promise that
|
|
455
|
-
* - resolves to `true` if an update was activated successfully
|
|
456
|
-
* - resolves to `false` if no update was available (for example, the client was already on the
|
|
457
|
-
* latest version).
|
|
458
|
-
* - rejects if any error occurs
|
|
459
|
-
*/
|
|
460
|
-
activateUpdate() {
|
|
461
|
-
if (!this.sw.isEnabled) {
|
|
462
|
-
return Promise.reject(new _RuntimeError(5601 /* RuntimeErrorCode.SERVICE_WORKER_DISABLED_OR_NOT_SUPPORTED_BY_THIS_BROWSER */, (typeof ngDevMode === 'undefined' || ngDevMode) && ERR_SW_NOT_SUPPORTED));
|
|
463
|
-
}
|
|
464
|
-
const nonce = this.sw.generateNonce();
|
|
465
|
-
return this.sw.postMessageWithOperation('ACTIVATE_UPDATE', { nonce }, nonce);
|
|
258
|
+
const nonce = this.sw.generateNonce();
|
|
259
|
+
this.ongoingCheckForUpdate = this.sw.postMessageWithOperation('CHECK_FOR_UPDATES', {
|
|
260
|
+
nonce
|
|
261
|
+
}, nonce).finally(() => {
|
|
262
|
+
this.ongoingCheckForUpdate = null;
|
|
263
|
+
});
|
|
264
|
+
return this.ongoingCheckForUpdate;
|
|
265
|
+
}
|
|
266
|
+
activateUpdate() {
|
|
267
|
+
if (!this.sw.isEnabled) {
|
|
268
|
+
return Promise.reject(new _RuntimeError(5601, (typeof ngDevMode === 'undefined' || ngDevMode) && ERR_SW_NOT_SUPPORTED));
|
|
466
269
|
}
|
|
467
|
-
|
|
468
|
-
|
|
270
|
+
const nonce = this.sw.generateNonce();
|
|
271
|
+
return this.sw.postMessageWithOperation('ACTIVATE_UPDATE', {
|
|
272
|
+
nonce
|
|
273
|
+
}, nonce);
|
|
274
|
+
}
|
|
275
|
+
static ɵfac = i0.ɵɵngDeclareFactory({
|
|
276
|
+
minVersion: "12.0.0",
|
|
277
|
+
version: "21.0.0-rc.0",
|
|
278
|
+
ngImport: i0,
|
|
279
|
+
type: SwUpdate,
|
|
280
|
+
deps: [{
|
|
281
|
+
token: NgswCommChannel
|
|
282
|
+
}],
|
|
283
|
+
target: i0.ɵɵFactoryTarget.Injectable
|
|
284
|
+
});
|
|
285
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({
|
|
286
|
+
minVersion: "12.0.0",
|
|
287
|
+
version: "21.0.0-rc.0",
|
|
288
|
+
ngImport: i0,
|
|
289
|
+
type: SwUpdate
|
|
290
|
+
});
|
|
469
291
|
}
|
|
470
|
-
i0.ɵɵngDeclareClassMetadata({
|
|
471
|
-
|
|
472
|
-
|
|
292
|
+
i0.ɵɵngDeclareClassMetadata({
|
|
293
|
+
minVersion: "12.0.0",
|
|
294
|
+
version: "21.0.0-rc.0",
|
|
295
|
+
ngImport: i0,
|
|
296
|
+
type: SwUpdate,
|
|
297
|
+
decorators: [{
|
|
298
|
+
type: Injectable
|
|
299
|
+
}],
|
|
300
|
+
ctorParameters: () => [{
|
|
301
|
+
type: NgswCommChannel
|
|
302
|
+
}]
|
|
303
|
+
});
|
|
473
304
|
|
|
474
|
-
/*!
|
|
475
|
-
* @license
|
|
476
|
-
* Copyright Google LLC All Rights Reserved.
|
|
477
|
-
*
|
|
478
|
-
* Use of this source code is governed by an MIT-style license that can be
|
|
479
|
-
* found in the LICENSE file at https://angular.dev/license
|
|
480
|
-
*/
|
|
481
305
|
const SCRIPT = new InjectionToken(typeof ngDevMode !== undefined && ngDevMode ? 'NGSW_REGISTER_SCRIPT' : '');
|
|
482
306
|
function ngswAppInitializer() {
|
|
483
|
-
|
|
484
|
-
|
|
307
|
+
if (typeof ngServerMode !== 'undefined' && ngServerMode) {
|
|
308
|
+
return;
|
|
309
|
+
}
|
|
310
|
+
const options = inject(SwRegistrationOptions);
|
|
311
|
+
if (!('serviceWorker' in navigator && options.enabled !== false)) {
|
|
312
|
+
return;
|
|
313
|
+
}
|
|
314
|
+
const script = inject(SCRIPT);
|
|
315
|
+
const ngZone = inject(NgZone);
|
|
316
|
+
const appRef = inject(ApplicationRef);
|
|
317
|
+
ngZone.runOutsideAngular(() => {
|
|
318
|
+
const sw = navigator.serviceWorker;
|
|
319
|
+
const onControllerChange = () => sw.controller?.postMessage({
|
|
320
|
+
action: 'INITIALIZE'
|
|
321
|
+
});
|
|
322
|
+
sw.addEventListener('controllerchange', onControllerChange);
|
|
323
|
+
appRef.onDestroy(() => {
|
|
324
|
+
sw.removeEventListener('controllerchange', onControllerChange);
|
|
325
|
+
});
|
|
326
|
+
});
|
|
327
|
+
ngZone.runOutsideAngular(() => {
|
|
328
|
+
let readyToRegister;
|
|
329
|
+
const {
|
|
330
|
+
registrationStrategy
|
|
331
|
+
} = options;
|
|
332
|
+
if (typeof registrationStrategy === 'function') {
|
|
333
|
+
readyToRegister = new Promise(resolve => registrationStrategy().subscribe(() => resolve()));
|
|
334
|
+
} else {
|
|
335
|
+
const [strategy, ...args] = (registrationStrategy || 'registerWhenStable:30000').split(':');
|
|
336
|
+
switch (strategy) {
|
|
337
|
+
case 'registerImmediately':
|
|
338
|
+
readyToRegister = Promise.resolve();
|
|
339
|
+
break;
|
|
340
|
+
case 'registerWithDelay':
|
|
341
|
+
readyToRegister = delayWithTimeout(+args[0] || 0);
|
|
342
|
+
break;
|
|
343
|
+
case 'registerWhenStable':
|
|
344
|
+
readyToRegister = Promise.race([appRef.whenStable(), delayWithTimeout(+args[0])]);
|
|
345
|
+
break;
|
|
346
|
+
default:
|
|
347
|
+
throw new _RuntimeError(5600, (typeof ngDevMode === 'undefined' || ngDevMode) && `Unknown ServiceWorker registration strategy: ${options.registrationStrategy}`);
|
|
348
|
+
}
|
|
485
349
|
}
|
|
486
|
-
|
|
487
|
-
|
|
350
|
+
readyToRegister.then(() => {
|
|
351
|
+
if (appRef.destroyed) {
|
|
488
352
|
return;
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
// as this event has no impact on view updates.
|
|
496
|
-
ngZone.runOutsideAngular(() => {
|
|
497
|
-
// Wait for service worker controller changes, and fire an INITIALIZE action when a new SW
|
|
498
|
-
// becomes active. This allows the SW to initialize itself even if there is no application
|
|
499
|
-
// traffic.
|
|
500
|
-
const sw = navigator.serviceWorker;
|
|
501
|
-
const onControllerChange = () => sw.controller?.postMessage({ action: 'INITIALIZE' });
|
|
502
|
-
sw.addEventListener('controllerchange', onControllerChange);
|
|
503
|
-
appRef.onDestroy(() => {
|
|
504
|
-
sw.removeEventListener('controllerchange', onControllerChange);
|
|
505
|
-
});
|
|
506
|
-
});
|
|
507
|
-
// Run outside the Angular zone to avoid preventing the app from stabilizing (especially
|
|
508
|
-
// given that some registration strategies wait for the app to stabilize).
|
|
509
|
-
ngZone.runOutsideAngular(() => {
|
|
510
|
-
let readyToRegister;
|
|
511
|
-
const { registrationStrategy } = options;
|
|
512
|
-
if (typeof registrationStrategy === 'function') {
|
|
513
|
-
readyToRegister = new Promise((resolve) => registrationStrategy().subscribe(() => resolve()));
|
|
514
|
-
}
|
|
515
|
-
else {
|
|
516
|
-
const [strategy, ...args] = (registrationStrategy || 'registerWhenStable:30000').split(':');
|
|
517
|
-
switch (strategy) {
|
|
518
|
-
case 'registerImmediately':
|
|
519
|
-
readyToRegister = Promise.resolve();
|
|
520
|
-
break;
|
|
521
|
-
case 'registerWithDelay':
|
|
522
|
-
readyToRegister = delayWithTimeout(+args[0] || 0);
|
|
523
|
-
break;
|
|
524
|
-
case 'registerWhenStable':
|
|
525
|
-
readyToRegister = Promise.race([appRef.whenStable(), delayWithTimeout(+args[0])]);
|
|
526
|
-
break;
|
|
527
|
-
default:
|
|
528
|
-
// Unknown strategy.
|
|
529
|
-
throw new _RuntimeError(5600 /* RuntimeErrorCode.UNKNOWN_REGISTRATION_STRATEGY */, (typeof ngDevMode === 'undefined' || ngDevMode) &&
|
|
530
|
-
`Unknown ServiceWorker registration strategy: ${options.registrationStrategy}`);
|
|
531
|
-
}
|
|
532
|
-
}
|
|
533
|
-
// Don't return anything to avoid blocking the application until the SW is registered.
|
|
534
|
-
// Catch and log the error if SW registration fails to avoid uncaught rejection warning.
|
|
535
|
-
readyToRegister.then(() => {
|
|
536
|
-
// If the registration strategy has resolved after the application has
|
|
537
|
-
// been explicitly destroyed by the user (e.g., by navigating away to
|
|
538
|
-
// another application), we simply should not register the worker.
|
|
539
|
-
if (appRef.destroyed) {
|
|
540
|
-
return;
|
|
541
|
-
}
|
|
542
|
-
navigator.serviceWorker
|
|
543
|
-
.register(script, {
|
|
544
|
-
scope: options.scope,
|
|
545
|
-
updateViaCache: options.updateViaCache,
|
|
546
|
-
type: options.type,
|
|
547
|
-
})
|
|
548
|
-
.catch((err) => console.error(_formatRuntimeError(5604 /* RuntimeErrorCode.SERVICE_WORKER_REGISTRATION_FAILED */, (typeof ngDevMode === 'undefined' || ngDevMode) &&
|
|
549
|
-
'Service worker registration failed with: ' + err)));
|
|
550
|
-
});
|
|
353
|
+
}
|
|
354
|
+
navigator.serviceWorker.register(script, {
|
|
355
|
+
scope: options.scope,
|
|
356
|
+
updateViaCache: options.updateViaCache,
|
|
357
|
+
type: options.type
|
|
358
|
+
}).catch(err => console.error(_formatRuntimeError(5604, (typeof ngDevMode === 'undefined' || ngDevMode) && 'Service worker registration failed with: ' + err)));
|
|
551
359
|
});
|
|
360
|
+
});
|
|
552
361
|
}
|
|
553
362
|
function delayWithTimeout(timeout) {
|
|
554
|
-
|
|
363
|
+
return new Promise(resolve => setTimeout(resolve, timeout));
|
|
555
364
|
}
|
|
556
365
|
function ngswCommChannelFactory() {
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
366
|
+
const opts = inject(SwRegistrationOptions);
|
|
367
|
+
const injector = inject(Injector);
|
|
368
|
+
const isBrowser = !(typeof ngServerMode !== 'undefined' && ngServerMode);
|
|
369
|
+
return new NgswCommChannel(isBrowser && opts.enabled !== false ? navigator.serviceWorker : undefined, injector);
|
|
561
370
|
}
|
|
562
|
-
/**
|
|
563
|
-
* Token that can be used to provide options for `ServiceWorkerModule` outside of
|
|
564
|
-
* `ServiceWorkerModule.register()`.
|
|
565
|
-
*
|
|
566
|
-
* You can use this token to define a provider that generates the registration options at runtime,
|
|
567
|
-
* for example via a function call:
|
|
568
|
-
*
|
|
569
|
-
* {@example service-worker/registration-options/module.ts region="registration-options"
|
|
570
|
-
* header="app.module.ts"}
|
|
571
|
-
*
|
|
572
|
-
* @publicApi
|
|
573
|
-
*/
|
|
574
371
|
class SwRegistrationOptions {
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
*/
|
|
581
|
-
enabled;
|
|
582
|
-
/**
|
|
583
|
-
* The value of the setting used to determine the circumstances in which the browser
|
|
584
|
-
* will consult the HTTP cache when it tries to update the service worker or any scripts that are imported via importScripts().
|
|
585
|
-
* [ServiceWorkerRegistration.updateViaCache](https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerRegistration/updateViaCache)
|
|
586
|
-
*/
|
|
587
|
-
updateViaCache;
|
|
588
|
-
/**
|
|
589
|
-
* The type of the ServiceWorker script to register.
|
|
590
|
-
* [ServiceWorkerRegistration#type](https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerContainer/register#type)
|
|
591
|
-
* - `classic`: Registers the script as a classic worker. ES module features such as `import` and `export` are NOT allowed in the script.
|
|
592
|
-
* - `module`: Registers the script as an ES module. Allows use of `import`/`export` syntax and module features.
|
|
593
|
-
*
|
|
594
|
-
* @default 'classic'
|
|
595
|
-
*/
|
|
596
|
-
type;
|
|
597
|
-
/**
|
|
598
|
-
* A URL that defines the ServiceWorker's registration scope; that is, what range of URLs it can
|
|
599
|
-
* control. It will be used when calling
|
|
600
|
-
* [ServiceWorkerContainer#register()](https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerContainer/register).
|
|
601
|
-
*/
|
|
602
|
-
scope;
|
|
603
|
-
/**
|
|
604
|
-
* Defines the ServiceWorker registration strategy, which determines when it will be registered
|
|
605
|
-
* with the browser.
|
|
606
|
-
*
|
|
607
|
-
* The default behavior of registering once the application stabilizes (i.e. as soon as there are
|
|
608
|
-
* no pending micro- and macro-tasks) is designed to register the ServiceWorker as soon as
|
|
609
|
-
* possible but without affecting the application's first time load.
|
|
610
|
-
*
|
|
611
|
-
* Still, there might be cases where you want more control over when the ServiceWorker is
|
|
612
|
-
* registered (for example, there might be a long-running timeout or polling interval, preventing
|
|
613
|
-
* the app from stabilizing). The available option are:
|
|
614
|
-
*
|
|
615
|
-
* - `registerWhenStable:<timeout>`: Register as soon as the application stabilizes (no pending
|
|
616
|
-
* micro-/macro-tasks) but no later than `<timeout>` milliseconds. If the app hasn't
|
|
617
|
-
* stabilized after `<timeout>` milliseconds (for example, due to a recurrent asynchronous
|
|
618
|
-
* task), the ServiceWorker will be registered anyway.
|
|
619
|
-
* If `<timeout>` is omitted, the ServiceWorker will only be registered once the app
|
|
620
|
-
* stabilizes.
|
|
621
|
-
* - `registerImmediately`: Register immediately.
|
|
622
|
-
* - `registerWithDelay:<timeout>`: Register with a delay of `<timeout>` milliseconds. For
|
|
623
|
-
* example, use `registerWithDelay:5000` to register the ServiceWorker after 5 seconds. If
|
|
624
|
-
* `<timeout>` is omitted, is defaults to `0`, which will register the ServiceWorker as soon
|
|
625
|
-
* as possible but still asynchronously, once all pending micro-tasks are completed.
|
|
626
|
-
* - An Observable factory function: A function that returns an `Observable`.
|
|
627
|
-
* The function will be used at runtime to obtain and subscribe to the `Observable` and the
|
|
628
|
-
* ServiceWorker will be registered as soon as the first value is emitted.
|
|
629
|
-
*
|
|
630
|
-
* Default: 'registerWhenStable:30000'
|
|
631
|
-
*/
|
|
632
|
-
registrationStrategy;
|
|
372
|
+
enabled;
|
|
373
|
+
updateViaCache;
|
|
374
|
+
type;
|
|
375
|
+
scope;
|
|
376
|
+
registrationStrategy;
|
|
633
377
|
}
|
|
634
|
-
/**
|
|
635
|
-
* @publicApi
|
|
636
|
-
*
|
|
637
|
-
* Sets up providers to register the given Angular Service Worker script.
|
|
638
|
-
*
|
|
639
|
-
* If `enabled` is set to `false` in the given options, the module will behave as if service
|
|
640
|
-
* workers are not supported by the browser, and the service worker will not be registered.
|
|
641
|
-
*
|
|
642
|
-
* Example usage:
|
|
643
|
-
* ```ts
|
|
644
|
-
* bootstrapApplication(AppComponent, {
|
|
645
|
-
* providers: [
|
|
646
|
-
* provideServiceWorker('ngsw-worker.js')
|
|
647
|
-
* ],
|
|
648
|
-
* });
|
|
649
|
-
* ```
|
|
650
|
-
*/
|
|
651
378
|
function provideServiceWorker(script, options = {}) {
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
]);
|
|
379
|
+
return makeEnvironmentProviders([SwPush, SwUpdate, {
|
|
380
|
+
provide: SCRIPT,
|
|
381
|
+
useValue: script
|
|
382
|
+
}, {
|
|
383
|
+
provide: SwRegistrationOptions,
|
|
384
|
+
useValue: options
|
|
385
|
+
}, {
|
|
386
|
+
provide: NgswCommChannel,
|
|
387
|
+
useFactory: ngswCommChannelFactory
|
|
388
|
+
}, provideAppInitializer(ngswAppInitializer)]);
|
|
663
389
|
}
|
|
664
390
|
|
|
665
|
-
/**
|
|
666
|
-
* @publicApi
|
|
667
|
-
*/
|
|
668
391
|
class ServiceWorkerModule {
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
392
|
+
static register(script, options = {}) {
|
|
393
|
+
return {
|
|
394
|
+
ngModule: ServiceWorkerModule,
|
|
395
|
+
providers: [provideServiceWorker(script, options)]
|
|
396
|
+
};
|
|
397
|
+
}
|
|
398
|
+
static ɵfac = i0.ɵɵngDeclareFactory({
|
|
399
|
+
minVersion: "12.0.0",
|
|
400
|
+
version: "21.0.0-rc.0",
|
|
401
|
+
ngImport: i0,
|
|
402
|
+
type: ServiceWorkerModule,
|
|
403
|
+
deps: [],
|
|
404
|
+
target: i0.ɵɵFactoryTarget.NgModule
|
|
405
|
+
});
|
|
406
|
+
static ɵmod = i0.ɵɵngDeclareNgModule({
|
|
407
|
+
minVersion: "14.0.0",
|
|
408
|
+
version: "21.0.0-rc.0",
|
|
409
|
+
ngImport: i0,
|
|
410
|
+
type: ServiceWorkerModule
|
|
411
|
+
});
|
|
412
|
+
static ɵinj = i0.ɵɵngDeclareInjector({
|
|
413
|
+
minVersion: "12.0.0",
|
|
414
|
+
version: "21.0.0-rc.0",
|
|
415
|
+
ngImport: i0,
|
|
416
|
+
type: ServiceWorkerModule,
|
|
417
|
+
providers: [SwPush, SwUpdate]
|
|
418
|
+
});
|
|
684
419
|
}
|
|
685
|
-
i0.ɵɵngDeclareClassMetadata({
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
420
|
+
i0.ɵɵngDeclareClassMetadata({
|
|
421
|
+
minVersion: "12.0.0",
|
|
422
|
+
version: "21.0.0-rc.0",
|
|
423
|
+
ngImport: i0,
|
|
424
|
+
type: ServiceWorkerModule,
|
|
425
|
+
decorators: [{
|
|
426
|
+
type: NgModule,
|
|
427
|
+
args: [{
|
|
428
|
+
providers: [SwPush, SwUpdate]
|
|
429
|
+
}]
|
|
430
|
+
}]
|
|
431
|
+
});
|
|
689
432
|
|
|
690
433
|
export { ServiceWorkerModule, SwPush, SwRegistrationOptions, SwUpdate, provideServiceWorker };
|
|
691
434
|
//# sourceMappingURL=service-worker.mjs.map
|