UNPKG

@angular/service-worker

Version:

Angular - service worker tooling!

382 lines (363 loc) 17.4 kB
/** * @license Angular v7.0.2 * (c) 2010-2018 Google, Inc. https://angular.io/ * License: MIT */ (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('rxjs'), require('rxjs/operators'), require('@angular/core'), require('@angular/common')) : typeof define === 'function' && define.amd ? define('@angular/service-worker', ['exports', 'rxjs', 'rxjs/operators', '@angular/core', '@angular/common'], factory) : (factory((global.ng = global.ng || {}, global.ng.serviceWorker = {}),global.rxjs,global.rxjs.operators,global.ng.core,global.ng.common)); }(this, (function (exports,rxjs,operators,core,common) { 'use strict'; /*! ***************************************************************************** Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT. See the Apache Version 2.0 License for specific language governing permissions and limitations under the License. ***************************************************************************** */ var __assign = function() { __assign = Object.assign || function __assign(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; function __decorate(decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; } function __metadata(metadataKey, metadataValue) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(metadataKey, metadataValue); } /** * @license * Copyright Google Inc. All Rights Reserved. * * Use of this source code is governed by an MIT-style license that can be * found in the LICENSE file at https://angular.io/license */ var ERR_SW_NOT_SUPPORTED = 'Service workers are disabled or not supported by this browser'; function errorObservable(message) { return rxjs.defer(function () { return rxjs.throwError(new Error(message)); }); } /** * @publicApi */ var NgswCommChannel = /** @class */ (function () { function NgswCommChannel(serviceWorker) { this.serviceWorker = serviceWorker; if (!serviceWorker) { this.worker = this.events = this.registration = errorObservable(ERR_SW_NOT_SUPPORTED); } else { var controllerChangeEvents = rxjs.fromEvent(serviceWorker, 'controllerchange'); var controllerChanges = controllerChangeEvents.pipe(operators.map(function () { return serviceWorker.controller; })); var currentController = rxjs.defer(function () { return rxjs.of(serviceWorker.controller); }); var controllerWithChanges = rxjs.concat(currentController, controllerChanges); this.worker = controllerWithChanges.pipe(operators.filter(function (c) { return !!c; })); this.registration = (this.worker.pipe(operators.switchMap(function () { return serviceWorker.getRegistration(); }))); var rawEvents = rxjs.fromEvent(serviceWorker, 'message'); var rawEventPayload = rawEvents.pipe(operators.map(function (event) { return event.data; })); var eventsUnconnected = rawEventPayload.pipe(operators.filter(function (event) { return event && event.type; })); var events = eventsUnconnected.pipe(operators.publish()); events.connect(); this.events = events; } } NgswCommChannel.prototype.postMessage = function (action, payload) { return this.worker .pipe(operators.take(1), operators.tap(function (sw) { sw.postMessage(__assign({ action: action }, payload)); })) .toPromise() .then(function () { return undefined; }); }; NgswCommChannel.prototype.postMessageWithStatus = function (type, payload, nonce) { var waitForStatus = this.waitForStatus(nonce); var postMessage = this.postMessage(type, payload); return Promise.all([waitForStatus, postMessage]).then(function () { return undefined; }); }; NgswCommChannel.prototype.generateNonce = function () { return Math.round(Math.random() * 10000000); }; NgswCommChannel.prototype.eventsOfType = function (type) { var filterFn = function (event) { return event.type === type; }; return this.events.pipe(operators.filter(filterFn)); }; NgswCommChannel.prototype.nextEventOfType = function (type) { return this.eventsOfType(type).pipe(operators.take(1)); }; NgswCommChannel.prototype.waitForStatus = function (nonce) { return this.eventsOfType('STATUS') .pipe(operators.filter(function (event) { return event.nonce === nonce; }), operators.take(1), operators.map(function (event) { if (event.status) { return undefined; } throw new Error(event.error); })) .toPromise(); }; Object.defineProperty(NgswCommChannel.prototype, "isEnabled", { get: function () { return !!this.serviceWorker; }, enumerable: true, configurable: true }); return NgswCommChannel; }()); /** * @license * Copyright Google Inc. All Rights Reserved. * * Use of this source code is governed by an MIT-style license that can be * found in the LICENSE file at https://angular.io/license */ /** * Subscribe and listen to push notifications from the Service Worker. * * @publicApi */ var SwPush = /** @class */ (function () { function SwPush(sw) { this.sw = sw; this.subscriptionChanges = new rxjs.Subject(); if (!sw.isEnabled) { this.messages = rxjs.NEVER; this.subscription = rxjs.NEVER; return; } this.messages = this.sw.eventsOfType('PUSH').pipe(operators.map(function (message) { return message.data; })); this.pushManager = this.sw.registration.pipe(operators.map(function (registration) { return registration.pushManager; })); var workerDrivenSubscriptions = this.pushManager.pipe(operators.switchMap(function (pm) { return pm.getSubscription(); })); this.subscription = rxjs.merge(workerDrivenSubscriptions, this.subscriptionChanges); } Object.defineProperty(SwPush.prototype, "isEnabled", { /** * True if the Service Worker is enabled (supported by the browser and enabled via * `ServiceWorkerModule`). */ get: function () { return this.sw.isEnabled; }, enumerable: true, configurable: true }); SwPush.prototype.requestSubscription = function (options) { var _this = this; if (!this.sw.isEnabled) { return Promise.reject(new Error(ERR_SW_NOT_SUPPORTED)); } var pushOptions = { userVisibleOnly: true }; var key = this.decodeBase64(options.serverPublicKey.replace(/_/g, '/').replace(/-/g, '+')); var applicationServerKey = new Uint8Array(new ArrayBuffer(key.length)); for (var i = 0; i < key.length; i++) { applicationServerKey[i] = key.charCodeAt(i); } pushOptions.applicationServerKey = applicationServerKey; return this.pushManager.pipe(operators.switchMap(function (pm) { return pm.subscribe(pushOptions); }), operators.take(1)) .toPromise() .then(function (sub) { _this.subscriptionChanges.next(sub); return sub; }); }; SwPush.prototype.unsubscribe = function () { var _this = this; if (!this.sw.isEnabled) { return Promise.reject(new Error(ERR_SW_NOT_SUPPORTED)); } var doUnsubscribe = function (sub) { if (sub === null) { throw new Error('Not subscribed to push notifications.'); } return sub.unsubscribe().then(function (success) { if (!success) { throw new Error('Unsubscribe failed!'); } _this.subscriptionChanges.next(null); }); }; return this.subscription.pipe(operators.take(1), operators.switchMap(doUnsubscribe)).toPromise(); }; SwPush.prototype.decodeBase64 = function (input) { return atob(input); }; SwPush = __decorate([ core.Injectable(), __metadata("design:paramtypes", [NgswCommChannel]) ], SwPush); return SwPush; }()); /** * @license * Copyright Google Inc. All Rights Reserved. * * Use of this source code is governed by an MIT-style license that can be * found in the LICENSE file at https://angular.io/license */ /** * Subscribe to update notifications from the Service Worker, trigger update * checks, and forcibly activate updates. * * @publicApi */ var SwUpdate = /** @class */ (function () { function SwUpdate(sw) { this.sw = sw; if (!sw.isEnabled) { this.available = rxjs.NEVER; this.activated = rxjs.NEVER; return; } this.available = this.sw.eventsOfType('UPDATE_AVAILABLE'); this.activated = this.sw.eventsOfType('UPDATE_ACTIVATED'); } Object.defineProperty(SwUpdate.prototype, "isEnabled", { /** * True if the Service Worker is enabled (supported by the browser and enabled via * `ServiceWorkerModule`). */ get: function () { return this.sw.isEnabled; }, enumerable: true, configurable: true }); SwUpdate.prototype.checkForUpdate = function () { if (!this.sw.isEnabled) { return Promise.reject(new Error(ERR_SW_NOT_SUPPORTED)); } var statusNonce = this.sw.generateNonce(); return this.sw.postMessageWithStatus('CHECK_FOR_UPDATES', { statusNonce: statusNonce }, statusNonce); }; SwUpdate.prototype.activateUpdate = function () { if (!this.sw.isEnabled) { return Promise.reject(new Error(ERR_SW_NOT_SUPPORTED)); } var statusNonce = this.sw.generateNonce(); return this.sw.postMessageWithStatus('ACTIVATE_UPDATE', { statusNonce: statusNonce }, statusNonce); }; SwUpdate = __decorate([ core.Injectable(), __metadata("design:paramtypes", [NgswCommChannel]) ], SwUpdate); return SwUpdate; }()); /** * @license * Copyright Google Inc. All Rights Reserved. * * Use of this source code is governed by an MIT-style license that can be * found in the LICENSE file at https://angular.io/license */ var RegistrationOptions = /** @class */ (function () { function RegistrationOptions() { } return RegistrationOptions; }()); var SCRIPT = new core.InjectionToken('NGSW_REGISTER_SCRIPT'); function ngswAppInitializer(injector, script, options, platformId) { var initializer = function () { var app = injector.get(core.ApplicationRef); if (!(common.isPlatformBrowser(platformId) && ('serviceWorker' in navigator) && options.enabled !== false)) { return; } var whenStable = app.isStable.pipe(operators.filter(function (stable) { return !!stable; }), operators.take(1)).toPromise(); // Wait for service worker controller changes, and fire an INITIALIZE action when a new SW // becomes active. This allows the SW to initialize itself even if there is no application // traffic. navigator.serviceWorker.addEventListener('controllerchange', function () { if (navigator.serviceWorker.controller !== null) { navigator.serviceWorker.controller.postMessage({ action: 'INITIALIZE' }); } }); // Don't return the Promise, as that will block the application until the SW is registered, and // cause a crash if the SW registration fails. whenStable.then(function () { return navigator.serviceWorker.register(script, { scope: options.scope }); }); }; return initializer; } function ngswCommChannelFactory(opts, platformId) { return new NgswCommChannel(common.isPlatformBrowser(platformId) && opts.enabled !== false ? navigator.serviceWorker : undefined); } /** * @publicApi */ var ServiceWorkerModule = /** @class */ (function () { function ServiceWorkerModule() { } ServiceWorkerModule_1 = ServiceWorkerModule; /** * Register the given Angular Service Worker script. * * If `enabled` is set to `false` in the given options, the module will behave as if service * workers are not supported by the browser, and the service worker will not be registered. */ ServiceWorkerModule.register = function (script, opts) { if (opts === void 0) { opts = {}; } return { ngModule: ServiceWorkerModule_1, providers: [ { provide: SCRIPT, useValue: script }, { provide: RegistrationOptions, useValue: opts }, { provide: NgswCommChannel, useFactory: ngswCommChannelFactory, deps: [RegistrationOptions, core.PLATFORM_ID] }, { provide: core.APP_INITIALIZER, useFactory: ngswAppInitializer, deps: [core.Injector, SCRIPT, RegistrationOptions, core.PLATFORM_ID], multi: true, }, ], }; }; var ServiceWorkerModule_1; ServiceWorkerModule = ServiceWorkerModule_1 = __decorate([ core.NgModule({ providers: [SwPush, SwUpdate], }) ], ServiceWorkerModule); return ServiceWorkerModule; }()); /** * @license * Copyright Google Inc. All Rights Reserved. * * Use of this source code is governed by an MIT-style license that can be * found in the LICENSE file at https://angular.io/license */ /** * @license * Copyright Google Inc. All Rights Reserved. * * Use of this source code is governed by an MIT-style license that can be * found in the LICENSE file at https://angular.io/license */ // This file only reexports content of the `src` folder. Keep it that way. /** * @license * Copyright Google Inc. All Rights Reserved. * * Use of this source code is governed by an MIT-style license that can be * found in the LICENSE file at https://angular.io/license */ /** * Generated bundle index. Do not edit. */ exports.ɵangular_packages_service_worker_service_worker_a = NgswCommChannel; exports.ɵangular_packages_service_worker_service_worker_b = RegistrationOptions; exports.ɵangular_packages_service_worker_service_worker_c = SCRIPT; exports.ɵangular_packages_service_worker_service_worker_d = ngswAppInitializer; exports.ɵangular_packages_service_worker_service_worker_e = ngswCommChannelFactory; exports.ServiceWorkerModule = ServiceWorkerModule; exports.SwPush = SwPush; exports.SwUpdate = SwUpdate; Object.defineProperty(exports, '__esModule', { value: true }); }))); //# sourceMappingURL=service-worker.umd.js.map