This commit is contained in:
thinkinggis 2019-11-05 17:57:30 +08:00
commit 678c6dbfdf
120 changed files with 11811 additions and 0 deletions

47
404.html Normal file

File diff suppressed because one or more lines are too long

47
404/index.html Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

1
chunk-map.json Normal file
View File

@ -0,0 +1 @@
{"app":["/app-51e70f8e1fb75adb779d.js"]}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

47
en/index.html Normal file

File diff suppressed because one or more lines are too long

BIN
icons/icon-144x144.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

BIN
icons/icon-192x192.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

BIN
icons/icon-256x256.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

BIN
icons/icon-384x384.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

BIN
icons/icon-48x48.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

BIN
icons/icon-512x512.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

BIN
icons/icon-72x72.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

BIN
icons/icon-96x96.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

1
idb-keyval-iife.min.js vendored Normal file
View File

@ -0,0 +1 @@
var idbKeyval=function(e){"use strict";class t{constructor(e="keyval-store",t="keyval"){this.storeName=t,this._dbp=new Promise((r,n)=>{const o=indexedDB.open(e,1);o.onerror=(()=>n(o.error)),o.onsuccess=(()=>r(o.result)),o.onupgradeneeded=(()=>{o.result.createObjectStore(t)})})}_withIDBStore(e,t){return this._dbp.then(r=>new Promise((n,o)=>{const s=r.transaction(this.storeName,e);s.oncomplete=(()=>n()),s.onabort=s.onerror=(()=>o(s.error)),t(s.objectStore(this.storeName))}))}}let r;function n(){return r||(r=new t),r}return e.Store=t,e.get=function(e,t=n()){let r;return t._withIDBStore("readonly",t=>{r=t.get(e)}).then(()=>r.result)},e.set=function(e,t,r=n()){return r._withIDBStore("readwrite",r=>{r.put(t,e)})},e.del=function(e,t=n()){return t._withIDBStore("readwrite",t=>{t.delete(e)})},e.clear=function(e=n()){return e._withIDBStore("readwrite",e=>{e.clear()})},e.keys=function(e=n()){const t=[];return e._withIDBStore("readonly",e=>{(e.openKeyCursor||e.openCursor).call(e).onsuccess=function(){this.result&&(t.push(this.result.key),this.result.continue())}}).then(()=>t)},e}({});

47
index.html Normal file

File diff suppressed because one or more lines are too long

1
manifest.webmanifest Normal file
View File

@ -0,0 +1 @@
{"name":"gatsby-starter-default","short_name":"starter","start_url":"/","background_color":"#722ED1","theme_color":"#722ED1","display":"minimal-ui","icons":[{"src":"icons/icon-48x48.png?v=40b8872b4d87c3cdc6162b11ecf88dc1","sizes":"48x48","type":"image/png"},{"src":"icons/icon-72x72.png?v=40b8872b4d87c3cdc6162b11ecf88dc1","sizes":"72x72","type":"image/png"},{"src":"icons/icon-96x96.png?v=40b8872b4d87c3cdc6162b11ecf88dc1","sizes":"96x96","type":"image/png"},{"src":"icons/icon-144x144.png?v=40b8872b4d87c3cdc6162b11ecf88dc1","sizes":"144x144","type":"image/png"},{"src":"icons/icon-192x192.png?v=40b8872b4d87c3cdc6162b11ecf88dc1","sizes":"192x192","type":"image/png"},{"src":"icons/icon-256x256.png?v=40b8872b4d87c3cdc6162b11ecf88dc1","sizes":"256x256","type":"image/png"},{"src":"icons/icon-384x384.png?v=40b8872b4d87c3cdc6162b11ecf88dc1","sizes":"384x384","type":"image/png"},{"src":"icons/icon-512x512.png?v=40b8872b4d87c3cdc6162b11ecf88dc1","sizes":"512x512","type":"image/png"}]}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
{"componentChunkName":"component---node-modules-antv-gatsby-theme-antv-site-pages-404-tsx","path":"/404.html","result":{"pageContext":{"isCreatedByStatefulCreatePages":true,"slug":"/404/","langKey":"zh"}}}

View File

@ -0,0 +1 @@
{"componentChunkName":"component---node-modules-antv-gatsby-theme-antv-site-pages-404-tsx","path":"/404","result":{"pageContext":{"isCreatedByStatefulCreatePages":true,"slug":"/404/","langKey":"zh"}}}

1
page-data/app-data.json Normal file
View File

@ -0,0 +1 @@
{"webpackCompilationHash":"7bfb4d1a12c65b5c3447"}

View File

@ -0,0 +1 @@
{"componentChunkName":"component---site-pages-index-en-ts","path":"/en","result":{"pageContext":{"isCreatedByStatefulCreatePages":true,"slug":"/en/","langKey":"en"}}}

View File

@ -0,0 +1 @@
{"componentChunkName":"component---node-modules-antv-gatsby-theme-antv-site-pages-index-tsx","path":"/","result":{"pageContext":{"isCreatedByStatefulCreatePages":true,"slug":"/","langKey":"zh"}}}

View File

@ -0,0 +1 @@
{"componentChunkName":"component---node-modules-gatsby-plugin-offline-app-shell-js","path":"/offline-plugin-app-shell-fallback","result":{"pageContext":{"isCreatedByStatefulCreatePages":false}}}

View File

@ -0,0 +1 @@
{"componentChunkName":"component---node-modules-antv-gatsby-theme-antv-site-templates-document-tsx","path":"/zh/docs/API/L7","result":{"data":{"site":{"siteMetadata":{"title":"L7","githubUrl":"https://github.com/antvis/antvis.github.io","docs":[{"slug":"specification","title":{"zh":"简介","en":"introduction"},"order":null},{"slug":"manual/tutorial","title":{"zh":"教程","en":"tutorial"},"order":null},{"slug":"API/L7.md","title":{"zh":"简介","en":"intro"},"order":1},{"slug":"API/component","title":{"zh":"组件","en":"Component"},"order":1}]},"pathPrefix":"/gatsby-theme-antv"},"markdownRemark":{"html":"","tableOfContents":"","fields":{"slug":"/zh/docs/API/L7","readingTime":{"text":"0 min read","time":0}},"frontmatter":{"title":"简介"},"parent":{"__typename":"File","relativePath":"API/L7.md"}},"allMarkdownRemark":{"edges":[{"node":{"fields":{"slug":"/zh/docs/manual/tutorial/quickStart"},"frontmatter":{"title":"快速上手"}}},{"node":{"fields":{"slug":"/zh/docs/API/L7"},"frontmatter":{"title":"简介"}}},{"node":{"fields":{"slug":"/zh/docs/API/component/popup"},"frontmatter":{"title":"地图信息框"}}},{"node":{"fields":{"slug":"/zh/docs/API/component/marker"},"frontmatter":{"title":"地图标注"}}},{"node":{"fields":{"slug":"/zh/examples/point/basic"},"frontmatter":{"title":"气泡图"}}},{"node":{"fields":{"slug":"/zh/docs/manual/tutorial/data"},"frontmatter":{"title":"数据"}}},{"node":{"fields":{"slug":"/zh/docs/API/component/control"},"frontmatter":{"title":"地图组件"}}},{"node":{"fields":{"slug":"/zh/docs/specification/introduction"},"frontmatter":{"title":"简介"}}}]}},"pageContext":{"isCreatedByStatefulCreatePages":false,"prev":{"fields":{"slug":"/zh/docs/manual/tutorial/quickStart"}},"next":{"fields":{"slug":"/zh/docs/manual/tutorial/data"}}}}}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
{"componentChunkName":"component---node-modules-antv-gatsby-theme-antv-site-templates-document-tsx","path":"/zh/docs/manual/tutorial/quickStart","result":{"data":{"site":{"siteMetadata":{"title":"L7","githubUrl":"https://github.com/antvis/antvis.github.io","docs":[{"slug":"specification","title":{"zh":"简介","en":"introduction"},"order":null},{"slug":"manual/tutorial","title":{"zh":"教程","en":"tutorial"},"order":null},{"slug":"API/L7.md","title":{"zh":"简介","en":"intro"},"order":1},{"slug":"API/component","title":{"zh":"组件","en":"Component"},"order":1}]},"pathPrefix":"/gatsby-theme-antv"},"markdownRemark":{"html":"<p>内容</p>","tableOfContents":"","fields":{"slug":"/zh/docs/manual/tutorial/quickStart","readingTime":{"text":"1 min read","time":300}},"frontmatter":{"title":"快速上手"},"parent":{"__typename":"File","relativePath":"manual/tutorial/quickStart.md"}},"allMarkdownRemark":{"edges":[{"node":{"fields":{"slug":"/zh/docs/manual/tutorial/quickStart"},"frontmatter":{"title":"快速上手"}}},{"node":{"fields":{"slug":"/zh/docs/API/L7"},"frontmatter":{"title":"简介"}}},{"node":{"fields":{"slug":"/zh/docs/API/component/popup"},"frontmatter":{"title":"地图信息框"}}},{"node":{"fields":{"slug":"/zh/docs/API/component/marker"},"frontmatter":{"title":"地图标注"}}},{"node":{"fields":{"slug":"/zh/examples/point/basic"},"frontmatter":{"title":"气泡图"}}},{"node":{"fields":{"slug":"/zh/docs/manual/tutorial/data"},"frontmatter":{"title":"数据"}}},{"node":{"fields":{"slug":"/zh/docs/API/component/control"},"frontmatter":{"title":"地图组件"}}},{"node":{"fields":{"slug":"/zh/docs/specification/introduction"},"frontmatter":{"title":"简介"}}}]}},"pageContext":{"isCreatedByStatefulCreatePages":false,"prev":null,"next":{"fields":{"slug":"/zh/docs/API/L7"}}}}}

View File

@ -0,0 +1 @@
{"componentChunkName":"component---node-modules-antv-gatsby-theme-antv-site-templates-document-tsx","path":"/zh/docs/specification/introduction","result":{"data":{"site":{"siteMetadata":{"title":"L7","githubUrl":"https://github.com/antvis/antvis.github.io","docs":[{"slug":"specification","title":{"zh":"简介","en":"introduction"},"order":null},{"slug":"manual/tutorial","title":{"zh":"教程","en":"tutorial"},"order":null},{"slug":"API/L7.md","title":{"zh":"简介","en":"intro"},"order":1},{"slug":"API/component","title":{"zh":"组件","en":"Component"},"order":1}]},"pathPrefix":"/gatsby-theme-antv"},"markdownRemark":{"html":"<p>L7 地理空间可视化设计语言</p>","tableOfContents":"","fields":{"slug":"/zh/docs/specification/introduction","readingTime":{"text":"1 min read","time":600}},"frontmatter":{"title":"简介"},"parent":{"__typename":"File","relativePath":"specification/introduction.md"}},"allMarkdownRemark":{"edges":[{"node":{"fields":{"slug":"/zh/docs/manual/tutorial/quickStart"},"frontmatter":{"title":"快速上手"}}},{"node":{"fields":{"slug":"/zh/docs/API/L7"},"frontmatter":{"title":"简介"}}},{"node":{"fields":{"slug":"/zh/docs/API/component/popup"},"frontmatter":{"title":"地图信息框"}}},{"node":{"fields":{"slug":"/zh/docs/API/component/marker"},"frontmatter":{"title":"地图标注"}}},{"node":{"fields":{"slug":"/zh/examples/point/basic"},"frontmatter":{"title":"气泡图"}}},{"node":{"fields":{"slug":"/zh/docs/manual/tutorial/data"},"frontmatter":{"title":"数据"}}},{"node":{"fields":{"slug":"/zh/docs/API/component/control"},"frontmatter":{"title":"地图组件"}}},{"node":{"fields":{"slug":"/zh/docs/specification/introduction"},"frontmatter":{"title":"简介"}}}]}},"pageContext":{"isCreatedByStatefulCreatePages":false,"prev":{"fields":{"slug":"/zh/docs/API/component/control"}},"next":{"fields":{"slug":"/zh/docs/API/component/popup"}}}}}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
{"componentChunkName":"component---site-pages-index-zh-ts","path":"/zh","result":{"pageContext":{"isCreatedByStatefulCreatePages":true,"slug":"/zh/","langKey":"zh"}}}

1
static/d/2969191536.json Normal file
View File

@ -0,0 +1 @@
{"data":{"placeholderImage":null}}

1
static/d/3147659733.json Normal file
View File

@ -0,0 +1 @@
{"data":{"site":{"siteMetadata":{"title":"L7","githubUrl":"https://github.com/antvis/antvis.github.io","navs":[{"slug":"docs/specification","title":{"zh":"设计语言","en":"Specification"},"target":null},{"slug":"docs/API","title":{"zh":"文档","en":"document"},"target":null},{"slug":"docs/tutorial","title":{"zh":"教程","en":"tutorial"},"target":null},{"slug":"examples","title":{"zh":"图表演示","en":"Examples"},"target":null}]}}}}

1
static/d/3978990474.json Normal file
View File

@ -0,0 +1 @@
{"data":{"site":{"siteMetadata":{"title":"L7","description":"Large-scale WebGL-powered Geospatial data visualization analysis framework"}}}}

View File

@ -0,0 +1,2 @@
(window.webpackJsonp=window.webpackJsonp||[]).push([[2],{"3GoW":function(o,n,e){o.exports={input:"Search-module--input--lOvOF"}},"44il":function(o,n,e){o.exports={container:"PlayGrounds-module--container--17Tai",cards:"PlayGrounds-module--cards--3hJak",card:"PlayGrounds-module--card--3Vq_o",current:"PlayGrounds-module--current--2cQLr"}},"49qf":function(o,n,e){},6488:function(o,n,e){},"7H9b":function(o,n,e){},"8nl2":function(o,n,e){},"9d8Q":function(o,n,e){},FPB1:function(o,n,e){o.exports={header:"Header-module--header--hrdnh",left:"Header-module--left--1dVXS",divider:"Header-module--divider--2qNp3",subProduceName:"Header-module--subProduceName--NMLtC",nav:"Header-module--nav--2_Knj",menu:"Header-module--menu--3hWNx",activeItem:"Header-module--activeItem--2xNW-",githubCorner:"Header-module--githubCorner--14Csh"}},"FoS+":function(o,n,e){},"G3+4":function(o,n,e){},GiSQ:function(o,n,e){o.exports={article:"Article-module--article--1-Z4k"}},HYfu:function(o,n,e){o.exports={markdown:"markdown-module--markdown--1TLJm",editOnGtiHubButton:"markdown-module--editOnGtiHubButton--1hV6y",main:"markdown-module--main--1VRvj",toc:"markdown-module--toc--3a23c",sider:"markdown-module--sider--26riA",menuIcon:"markdown-module--menuIcon--hTGH6",layout:"markdown-module--layout--20GIh"}},IDGY:function(o,n,e){},"Ibq+":function(o,n,e){},"L/94":function(o,n,e){},Lk4S:function(o,n,e){o.exports={products:"Product-module--products--wZmFW",product:"Product-module--product--1pyvr",productContent:"Product-module--productContent--3xt59",productDescription:"Product-module--productDescription--3dOob",productLinks:"Product-module--productLinks--2gCa8"}},OwP9:function(o,n,e){},Svq7:function(o,n,e){},VEUW:function(o,n,e){},Wfs9:function(o,n,e){},XJbt:function(o,n,e){},YCql:function(o,n,e){},e0s7:function(o,n,e){},fcTV:function(o,n,e){},"h+Wa":function(o,n,e){},hEgN:function(o,n,e){},m7UV:function(o,n,e){o.exports={playground:"PlayGround-module--playground--20RTt",preview:"PlayGround-module--preview--6whqA",editor:"PlayGround-module--editor--1HTqe",toolbar:"PlayGround-module--toolbar--2i0SG",codemirror:"PlayGround-module--codemirror--nEJBa"}},mo9N:function(o,n,e){o.exports={tabs:"Tabs-module--tabs--3WFbV",active:"Tabs-module--active--2GIM4"}},"p77/":function(o,n,e){},slaK:function(o,n,e){o.exports={footer:"Footer-module--footer--1oDCB"}},vLCf:function(o,n,e){},zP18:function(o,n,e){o.exports={main:"layout-module--main--2k9yj"}}}]);
//# sourceMappingURL=styles-5d5ac81f3c32d0998151.js.map

View File

@ -0,0 +1 @@
{"version":3,"sources":["webpack:///./node_modules/@antv/gatsby-theme-antv/site/components/Search.module.less","webpack:///./node_modules/@antv/gatsby-theme-antv/site/components/PlayGrounds.module.less","webpack:///./node_modules/@antv/gatsby-theme-antv/site/components/Header.module.less","webpack:///./node_modules/@antv/gatsby-theme-antv/site/components/Article.module.less","webpack:///./node_modules/@antv/gatsby-theme-antv/site/templates/markdown.module.less","webpack:///./node_modules/@antv/gatsby-theme-antv/site/components/Product.module.less","webpack:///./node_modules/@antv/gatsby-theme-antv/site/components/PlayGround.module.less","webpack:///./node_modules/@antv/gatsby-theme-antv/site/components/Tabs.module.less","webpack:///./node_modules/@antv/gatsby-theme-antv/site/components/Footer.module.less","webpack:///./node_modules/@antv/gatsby-theme-antv/site/layouts/layout.module.less"],"names":["module","exports"],"mappings":"gFACAA,EAAOC,QAAU,CAAC,MAAQ,gC,uBCA1BD,EAAOC,QAAU,CAAC,UAAY,uCAAuC,MAAQ,mCAAmC,KAAO,kCAAkC,QAAU,uC,gJCAnKD,EAAOC,QAAU,CAAC,OAAS,+BAA+B,KAAO,6BAA6B,QAAU,gCAAgC,eAAiB,uCAAuC,IAAM,4BAA4B,KAAO,6BAA6B,WAAa,mCAAmC,aAAe,uC,uECArUD,EAAOC,QAAU,CAAC,QAAU,mC,qBCA5BD,EAAOC,QAAU,CAAC,SAAW,mCAAmC,mBAAqB,6CAA6C,KAAO,+BAA+B,IAAM,8BAA8B,MAAQ,gCAAgC,SAAW,mCAAmC,OAAS,mC,8FCA3SD,EAAOC,QAAU,CAAC,SAAW,kCAAkC,QAAU,iCAAiC,eAAiB,wCAAwC,mBAAqB,4CAA4C,aAAe,wC,6PCAnPD,EAAOC,QAAU,CAAC,WAAa,uCAAuC,QAAU,oCAAoC,OAAS,mCAAmC,QAAU,oCAAoC,WAAa,yC,qBCA3ND,EAAOC,QAAU,CAAC,KAAO,2BAA2B,OAAS,+B,8CCA7DD,EAAOC,QAAU,CAAC,OAAS,iC,4CCA3BD,EAAOC,QAAU,CAAC,KAAO","file":"styles-5d5ac81f3c32d0998151.js","sourcesContent":["// extracted by mini-css-extract-plugin\nmodule.exports = {\"input\":\"Search-module--input--lOvOF\"};","// extracted by mini-css-extract-plugin\nmodule.exports = {\"container\":\"PlayGrounds-module--container--17Tai\",\"cards\":\"PlayGrounds-module--cards--3hJak\",\"card\":\"PlayGrounds-module--card--3Vq_o\",\"current\":\"PlayGrounds-module--current--2cQLr\"};","// extracted by mini-css-extract-plugin\nmodule.exports = {\"header\":\"Header-module--header--hrdnh\",\"left\":\"Header-module--left--1dVXS\",\"divider\":\"Header-module--divider--2qNp3\",\"subProduceName\":\"Header-module--subProduceName--NMLtC\",\"nav\":\"Header-module--nav--2_Knj\",\"menu\":\"Header-module--menu--3hWNx\",\"activeItem\":\"Header-module--activeItem--2xNW-\",\"githubCorner\":\"Header-module--githubCorner--14Csh\"};","// extracted by mini-css-extract-plugin\nmodule.exports = {\"article\":\"Article-module--article--1-Z4k\"};","// extracted by mini-css-extract-plugin\nmodule.exports = {\"markdown\":\"markdown-module--markdown--1TLJm\",\"editOnGtiHubButton\":\"markdown-module--editOnGtiHubButton--1hV6y\",\"main\":\"markdown-module--main--1VRvj\",\"toc\":\"markdown-module--toc--3a23c\",\"sider\":\"markdown-module--sider--26riA\",\"menuIcon\":\"markdown-module--menuIcon--hTGH6\",\"layout\":\"markdown-module--layout--20GIh\"};","// extracted by mini-css-extract-plugin\nmodule.exports = {\"products\":\"Product-module--products--wZmFW\",\"product\":\"Product-module--product--1pyvr\",\"productContent\":\"Product-module--productContent--3xt59\",\"productDescription\":\"Product-module--productDescription--3dOob\",\"productLinks\":\"Product-module--productLinks--2gCa8\"};","// extracted by mini-css-extract-plugin\nmodule.exports = {\"playground\":\"PlayGround-module--playground--20RTt\",\"preview\":\"PlayGround-module--preview--6whqA\",\"editor\":\"PlayGround-module--editor--1HTqe\",\"toolbar\":\"PlayGround-module--toolbar--2i0SG\",\"codemirror\":\"PlayGround-module--codemirror--nEJBa\"};","// extracted by mini-css-extract-plugin\nmodule.exports = {\"tabs\":\"Tabs-module--tabs--3WFbV\",\"active\":\"Tabs-module--active--2GIM4\"};","// extracted by mini-css-extract-plugin\nmodule.exports = {\"footer\":\"Footer-module--footer--1oDCB\"};","// extracted by mini-css-extract-plugin\nmodule.exports = {\"main\":\"layout-module--main--2k9yj\"};"],"sourceRoot":""}

File diff suppressed because one or more lines are too long

165
sw.js Normal file
View File

@ -0,0 +1,165 @@
/**
* Welcome to your Workbox-powered service worker!
*
* You'll need to register this file in your web app and you should
* disable HTTP caching for this file too.
* See https://goo.gl/nhQhGp
*
* The rest of the code is auto-generated. Please don't update this file
* directly; instead, make changes to your Workbox build configuration
* and re-run your build process.
* See https://goo.gl/2aRDsh
*/
importScripts("workbox-v4.3.1/workbox-sw.js");
workbox.setConfig({modulePathPrefix: "workbox-v4.3.1"});
workbox.core.setCacheNameDetails({prefix: "gatsby-plugin-offline"});
workbox.core.skipWaiting();
workbox.core.clientsClaim();
/**
* The workboxSW.precacheAndRoute() method efficiently caches and responds to
* requests for URLs in the manifest.
* See https://goo.gl/S9QRab
*/
self.__precacheManifest = [
{
"url": "webpack-runtime-c93a82d3addc73eb1b52.js"
},
{
"url": "styles.e32956506dacddf17950.css"
},
{
"url": "styles-5d5ac81f3c32d0998151.js"
},
{
"url": "commons-f6783ede68f8c7ff9b6d.js"
},
{
"url": "offline-plugin-app-shell-fallback/index.html",
"revision": "3bb6e989197b330c20e203bdea194e49"
},
{
"url": "page-data/offline-plugin-app-shell-fallback/page-data.json",
"revision": "5636d5ab217f85530a92b2939e270518"
},
{
"url": "manifest.webmanifest",
"revision": "123daa3226c4e9bd715f027dfb4e03ab"
}
].concat(self.__precacheManifest || []);
workbox.precaching.precacheAndRoute(self.__precacheManifest, {});
workbox.routing.registerRoute(/(\.js$|\.css$|static\/)/, new workbox.strategies.CacheFirst(), 'GET');
workbox.routing.registerRoute(/^https?:.*\page-data\/.*\/page-data\.json/, new workbox.strategies.NetworkFirst(), 'GET');
workbox.routing.registerRoute(/^https?:.*\.(png|jpg|jpeg|webp|svg|gif|tiff|js|woff|woff2|json|css)$/, new workbox.strategies.StaleWhileRevalidate(), 'GET');
workbox.routing.registerRoute(/^https?:\/\/fonts\.googleapis\.com\/css/, new workbox.strategies.StaleWhileRevalidate(), 'GET');
/* global importScripts, workbox, idbKeyval */
importScripts(`idb-keyval-iife.min.js`)
const { NavigationRoute } = workbox.routing
let lastNavigationRequest = null
let offlineShellEnabled = true
// prefer standard object syntax to support more browsers
const MessageAPI = {
setPathResources: (event, { path, resources }) => {
event.waitUntil(idbKeyval.set(`resources:${path}`, resources))
},
clearPathResources: event => {
event.waitUntil(idbKeyval.clear())
},
enableOfflineShell: () => {
offlineShellEnabled = true
},
disableOfflineShell: () => {
offlineShellEnabled = false
},
}
self.addEventListener(`message`, event => {
const { gatsbyApi: api } = event.data
if (api) MessageAPI[api](event, event.data)
})
function handleAPIRequest({ event }) {
const { pathname } = new URL(event.request.url)
const params = pathname.match(/:(.+)/)[1]
const data = {}
if (params.indexOf(`=`) !== -1) {
params.split(`&`).forEach(param => {
const [key, val] = param.split(`=`)
data[key] = val
})
} else {
data.api = params
}
if (MessageAPI[data.api] !== undefined) {
MessageAPI[data.api]()
}
if (!data.redirect) {
return new Response()
}
return new Response(null, {
status: 302,
headers: {
Location: lastNavigationRequest,
},
})
}
const navigationRoute = new NavigationRoute(async ({ event }) => {
// handle API requests separately to normal navigation requests, so do this
// check first
if (event.request.url.match(/\/.gatsby-plugin-offline:.+/)) {
return handleAPIRequest({ event })
}
if (!offlineShellEnabled) {
return await fetch(event.request)
}
lastNavigationRequest = event.request.url
let { pathname } = new URL(event.request.url)
pathname = pathname.replace(new RegExp(`^/gatsby-theme-antv`), ``)
// Check for resources + the app bundle
// The latter may not exist if the SW is updating to a new version
const resources = await idbKeyval.get(`resources:${pathname}`)
if (!resources || !(await caches.match(`/gatsby-theme-antv/app-51e70f8e1fb75adb779d.js`))) {
return await fetch(event.request)
}
for (const resource of resources) {
// As soon as we detect a failed resource, fetch the entire page from
// network - that way we won't risk being in an inconsistent state with
// some parts of the page failing.
if (!(await caches.match(resource))) {
return await fetch(event.request)
}
}
const offlineShell = `/gatsby-theme-antv/offline-plugin-app-shell-fallback/index.html`
const offlineShellWithKey = workbox.precaching.getCacheKeyForURL(offlineShell)
return await caches.match(offlineShellWithKey)
})
workbox.routing.registerRoute(navigationRoute)
// this route is used when performing a non-navigation request (e.g. fetch)
workbox.routing.registerRoute(/\/.gatsby-plugin-offline:.+/, handleAPIRequest)

View File

@ -0,0 +1,2 @@
!function(e){function r(r){for(var n,l,a=r[0],f=r[1],i=r[2],c=0,s=[];c<a.length;c++)l=a[c],Object.prototype.hasOwnProperty.call(o,l)&&o[l]&&s.push(o[l][0]),o[l]=0;for(n in f)Object.prototype.hasOwnProperty.call(f,n)&&(e[n]=f[n]);for(p&&p(r);s.length;)s.shift()();return u.push.apply(u,i||[]),t()}function t(){for(var e,r=0;r<u.length;r++){for(var t=u[r],n=!0,a=1;a<t.length;a++){var f=t[a];0!==o[f]&&(n=!1)}n&&(u.splice(r--,1),e=l(l.s=t[0]))}return e}var n={},o={3:0},u=[];function l(r){if(n[r])return n[r].exports;var t=n[r]={i:r,l:!1,exports:{}};return e[r].call(t.exports,t,t.exports,l),t.l=!0,t.exports}l.m=e,l.c=n,l.d=function(e,r,t){l.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},l.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},l.t=function(e,r){if(1&r&&(e=l(e)),8&r)return e;if(4&r&&"object"==typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(l.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&r&&"string"!=typeof e)for(var n in e)l.d(t,n,function(r){return e[r]}.bind(null,n));return t},l.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return l.d(r,"a",r),r},l.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},l.p="/gatsby-theme-antv/";var a=window.webpackJsonp=window.webpackJsonp||[],f=a.push.bind(a);a.push=r,a=a.slice();for(var i=0;i<a.length;i++)r(a[i]);var p=f;t()}([]);
//# sourceMappingURL=webpack-runtime-c93a82d3addc73eb1b52.js.map

File diff suppressed because one or more lines are too long

1
webpack.stats.json Normal file
View File

@ -0,0 +1 @@
{"errors":[],"warnings":[],"namedChunkGroups":{"app":{"chunks":[3,2,1,0],"assets":["webpack-runtime-c93a82d3addc73eb1b52.js","webpack-runtime-c93a82d3addc73eb1b52.js.map","styles.e32956506dacddf17950.css","styles-5d5ac81f3c32d0998151.js","styles-5d5ac81f3c32d0998151.js.map","commons-f6783ede68f8c7ff9b6d.js","commons-f6783ede68f8c7ff9b6d.js.map","app-51e70f8e1fb75adb779d.js","app-51e70f8e1fb75adb779d.js.map"],"children":{},"childAssets":{}}},"assetsByChunkName":{"app":["webpack-runtime-c93a82d3addc73eb1b52.js","styles.e32956506dacddf17950.css","styles-5d5ac81f3c32d0998151.js","commons-f6783ede68f8c7ff9b6d.js","app-51e70f8e1fb75adb779d.js"]}}

View File

@ -0,0 +1,822 @@
this.workbox = this.workbox || {};
this.workbox.backgroundSync = (function (exports, WorkboxError_mjs, logger_mjs, assert_mjs, getFriendlyURL_mjs, DBWrapper_mjs) {
'use strict';
try {
self['workbox:background-sync:4.3.1'] && _();
} catch (e) {} // eslint-disable-line
/*
Copyright 2018 Google LLC
Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.
*/
const DB_VERSION = 3;
const DB_NAME = 'workbox-background-sync';
const OBJECT_STORE_NAME = 'requests';
const INDEXED_PROP = 'queueName';
/**
* A class to manage storing requests from a Queue in IndexedbDB,
* indexed by their queue name for easier access.
*
* @private
*/
class QueueStore {
/**
* Associates this instance with a Queue instance, so entries added can be
* identified by their queue name.
*
* @param {string} queueName
* @private
*/
constructor(queueName) {
this._queueName = queueName;
this._db = new DBWrapper_mjs.DBWrapper(DB_NAME, DB_VERSION, {
onupgradeneeded: this._upgradeDb
});
}
/**
* Append an entry last in the queue.
*
* @param {Object} entry
* @param {Object} entry.requestData
* @param {number} [entry.timestamp]
* @param {Object} [entry.metadata]
* @private
*/
async pushEntry(entry) {
{
assert_mjs.assert.isType(entry, 'object', {
moduleName: 'workbox-background-sync',
className: 'QueueStore',
funcName: 'pushEntry',
paramName: 'entry'
});
assert_mjs.assert.isType(entry.requestData, 'object', {
moduleName: 'workbox-background-sync',
className: 'QueueStore',
funcName: 'pushEntry',
paramName: 'entry.requestData'
});
} // Don't specify an ID since one is automatically generated.
delete entry.id;
entry.queueName = this._queueName;
await this._db.add(OBJECT_STORE_NAME, entry);
}
/**
* Preppend an entry first in the queue.
*
* @param {Object} entry
* @param {Object} entry.requestData
* @param {number} [entry.timestamp]
* @param {Object} [entry.metadata]
* @private
*/
async unshiftEntry(entry) {
{
assert_mjs.assert.isType(entry, 'object', {
moduleName: 'workbox-background-sync',
className: 'QueueStore',
funcName: 'unshiftEntry',
paramName: 'entry'
});
assert_mjs.assert.isType(entry.requestData, 'object', {
moduleName: 'workbox-background-sync',
className: 'QueueStore',
funcName: 'unshiftEntry',
paramName: 'entry.requestData'
});
}
const [firstEntry] = await this._db.getAllMatching(OBJECT_STORE_NAME, {
count: 1
});
if (firstEntry) {
// Pick an ID one less than the lowest ID in the object store.
entry.id = firstEntry.id - 1;
} else {
// Otherwise let the auto-incrementor assign the ID.
delete entry.id;
}
entry.queueName = this._queueName;
await this._db.add(OBJECT_STORE_NAME, entry);
}
/**
* Removes and returns the last entry in the queue matching the `queueName`.
*
* @return {Promise<Object>}
* @private
*/
async popEntry() {
return this._removeEntry({
direction: 'prev'
});
}
/**
* Removes and returns the first entry in the queue matching the `queueName`.
*
* @return {Promise<Object>}
* @private
*/
async shiftEntry() {
return this._removeEntry({
direction: 'next'
});
}
/**
* Returns all entries in the store matching the `queueName`.
*
* @param {Object} options See workbox.backgroundSync.Queue~getAll}
* @return {Promise<Array<Object>>}
* @private
*/
async getAll() {
return await this._db.getAllMatching(OBJECT_STORE_NAME, {
index: INDEXED_PROP,
query: IDBKeyRange.only(this._queueName)
});
}
/**
* Deletes the entry for the given ID.
*
* WARNING: this method does not ensure the deleted enry belongs to this
* queue (i.e. matches the `queueName`). But this limitation is acceptable
* as this class is not publicly exposed. An additional check would make
* this method slower than it needs to be.
*
* @private
* @param {number} id
*/
async deleteEntry(id) {
await this._db.delete(OBJECT_STORE_NAME, id);
}
/**
* Removes and returns the first or last entry in the queue (based on the
* `direction` argument) matching the `queueName`.
*
* @return {Promise<Object>}
* @private
*/
async _removeEntry({
direction
}) {
const [entry] = await this._db.getAllMatching(OBJECT_STORE_NAME, {
direction,
index: INDEXED_PROP,
query: IDBKeyRange.only(this._queueName),
count: 1
});
if (entry) {
await this.deleteEntry(entry.id);
return entry;
}
}
/**
* Upgrades the database given an `upgradeneeded` event.
*
* @param {Event} event
* @private
*/
_upgradeDb(event) {
const db = event.target.result;
if (event.oldVersion > 0 && event.oldVersion < DB_VERSION) {
if (db.objectStoreNames.contains(OBJECT_STORE_NAME)) {
db.deleteObjectStore(OBJECT_STORE_NAME);
}
}
const objStore = db.createObjectStore(OBJECT_STORE_NAME, {
autoIncrement: true,
keyPath: 'id'
});
objStore.createIndex(INDEXED_PROP, INDEXED_PROP, {
unique: false
});
}
}
/*
Copyright 2018 Google LLC
Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.
*/
const serializableProperties = ['method', 'referrer', 'referrerPolicy', 'mode', 'credentials', 'cache', 'redirect', 'integrity', 'keepalive'];
/**
* A class to make it easier to serialize and de-serialize requests so they
* can be stored in IndexedDB.
*
* @private
*/
class StorableRequest {
/**
* Converts a Request object to a plain object that can be structured
* cloned or JSON-stringified.
*
* @param {Request} request
* @return {Promise<StorableRequest>}
*
* @private
*/
static async fromRequest(request) {
const requestData = {
url: request.url,
headers: {}
}; // Set the body if present.
if (request.method !== 'GET') {
// Use ArrayBuffer to support non-text request bodies.
// NOTE: we can't use Blobs becuse Safari doesn't support storing
// Blobs in IndexedDB in some cases:
// https://github.com/dfahlander/Dexie.js/issues/618#issuecomment-398348457
requestData.body = await request.clone().arrayBuffer();
} // Convert the headers from an iterable to an object.
for (const [key, value] of request.headers.entries()) {
requestData.headers[key] = value;
} // Add all other serializable request properties
for (const prop of serializableProperties) {
if (request[prop] !== undefined) {
requestData[prop] = request[prop];
}
}
return new StorableRequest(requestData);
}
/**
* Accepts an object of request data that can be used to construct a
* `Request` but can also be stored in IndexedDB.
*
* @param {Object} requestData An object of request data that includes the
* `url` plus any relevant properties of
* [requestInit]{@link https://fetch.spec.whatwg.org/#requestinit}.
* @private
*/
constructor(requestData) {
{
assert_mjs.assert.isType(requestData, 'object', {
moduleName: 'workbox-background-sync',
className: 'StorableRequest',
funcName: 'constructor',
paramName: 'requestData'
});
assert_mjs.assert.isType(requestData.url, 'string', {
moduleName: 'workbox-background-sync',
className: 'StorableRequest',
funcName: 'constructor',
paramName: 'requestData.url'
});
} // If the request's mode is `navigate`, convert it to `same-origin` since
// navigation requests can't be constructed via script.
if (requestData.mode === 'navigate') {
requestData.mode = 'same-origin';
}
this._requestData = requestData;
}
/**
* Returns a deep clone of the instances `_requestData` object.
*
* @return {Object}
*
* @private
*/
toObject() {
const requestData = Object.assign({}, this._requestData);
requestData.headers = Object.assign({}, this._requestData.headers);
if (requestData.body) {
requestData.body = requestData.body.slice(0);
}
return requestData;
}
/**
* Converts this instance to a Request.
*
* @return {Request}
*
* @private
*/
toRequest() {
return new Request(this._requestData.url, this._requestData);
}
/**
* Creates and returns a deep clone of the instance.
*
* @return {StorableRequest}
*
* @private
*/
clone() {
return new StorableRequest(this.toObject());
}
}
/*
Copyright 2018 Google LLC
Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.
*/
const TAG_PREFIX = 'workbox-background-sync';
const MAX_RETENTION_TIME = 60 * 24 * 7; // 7 days in minutes
const queueNames = new Set();
/**
* A class to manage storing failed requests in IndexedDB and retrying them
* later. All parts of the storing and replaying process are observable via
* callbacks.
*
* @memberof workbox.backgroundSync
*/
class Queue {
/**
* Creates an instance of Queue with the given options
*
* @param {string} name The unique name for this queue. This name must be
* unique as it's used to register sync events and store requests
* in IndexedDB specific to this instance. An error will be thrown if
* a duplicate name is detected.
* @param {Object} [options]
* @param {Function} [options.onSync] A function that gets invoked whenever
* the 'sync' event fires. The function is invoked with an object
* containing the `queue` property (referencing this instance), and you
* can use the callback to customize the replay behavior of the queue.
* When not set the `replayRequests()` method is called.
* Note: if the replay fails after a sync event, make sure you throw an
* error, so the browser knows to retry the sync event later.
* @param {number} [options.maxRetentionTime=7 days] The amount of time (in
* minutes) a request may be retried. After this amount of time has
* passed, the request will be deleted from the queue.
*/
constructor(name, {
onSync,
maxRetentionTime
} = {}) {
// Ensure the store name is not already being used
if (queueNames.has(name)) {
throw new WorkboxError_mjs.WorkboxError('duplicate-queue-name', {
name
});
} else {
queueNames.add(name);
}
this._name = name;
this._onSync = onSync || this.replayRequests;
this._maxRetentionTime = maxRetentionTime || MAX_RETENTION_TIME;
this._queueStore = new QueueStore(this._name);
this._addSyncListener();
}
/**
* @return {string}
*/
get name() {
return this._name;
}
/**
* Stores the passed request in IndexedDB (with its timestamp and any
* metadata) at the end of the queue.
*
* @param {Object} entry
* @param {Request} entry.request The request to store in the queue.
* @param {Object} [entry.metadata] Any metadata you want associated with the
* stored request. When requests are replayed you'll have access to this
* metadata object in case you need to modify the request beforehand.
* @param {number} [entry.timestamp] The timestamp (Epoch time in
* milliseconds) when the request was first added to the queue. This is
* used along with `maxRetentionTime` to remove outdated requests. In
* general you don't need to set this value, as it's automatically set
* for you (defaulting to `Date.now()`), but you can update it if you
* don't want particular requests to expire.
*/
async pushRequest(entry) {
{
assert_mjs.assert.isType(entry, 'object', {
moduleName: 'workbox-background-sync',
className: 'Queue',
funcName: 'pushRequest',
paramName: 'entry'
});
assert_mjs.assert.isInstance(entry.request, Request, {
moduleName: 'workbox-background-sync',
className: 'Queue',
funcName: 'pushRequest',
paramName: 'entry.request'
});
}
await this._addRequest(entry, 'push');
}
/**
* Stores the passed request in IndexedDB (with its timestamp and any
* metadata) at the beginning of the queue.
*
* @param {Object} entry
* @param {Request} entry.request The request to store in the queue.
* @param {Object} [entry.metadata] Any metadata you want associated with the
* stored request. When requests are replayed you'll have access to this
* metadata object in case you need to modify the request beforehand.
* @param {number} [entry.timestamp] The timestamp (Epoch time in
* milliseconds) when the request was first added to the queue. This is
* used along with `maxRetentionTime` to remove outdated requests. In
* general you don't need to set this value, as it's automatically set
* for you (defaulting to `Date.now()`), but you can update it if you
* don't want particular requests to expire.
*/
async unshiftRequest(entry) {
{
assert_mjs.assert.isType(entry, 'object', {
moduleName: 'workbox-background-sync',
className: 'Queue',
funcName: 'unshiftRequest',
paramName: 'entry'
});
assert_mjs.assert.isInstance(entry.request, Request, {
moduleName: 'workbox-background-sync',
className: 'Queue',
funcName: 'unshiftRequest',
paramName: 'entry.request'
});
}
await this._addRequest(entry, 'unshift');
}
/**
* Removes and returns the last request in the queue (along with its
* timestamp and any metadata). The returned object takes the form:
* `{request, timestamp, metadata}`.
*
* @return {Promise<Object>}
*/
async popRequest() {
return this._removeRequest('pop');
}
/**
* Removes and returns the first request in the queue (along with its
* timestamp and any metadata). The returned object takes the form:
* `{request, timestamp, metadata}`.
*
* @return {Promise<Object>}
*/
async shiftRequest() {
return this._removeRequest('shift');
}
/**
* Returns all the entries that have not expired (per `maxRetentionTime`).
* Any expired entries are removed from the queue.
*
* @return {Promise<Array<Object>>}
*/
async getAll() {
const allEntries = await this._queueStore.getAll();
const now = Date.now();
const unexpiredEntries = [];
for (const entry of allEntries) {
// Ignore requests older than maxRetentionTime. Call this function
// recursively until an unexpired request is found.
const maxRetentionTimeInMs = this._maxRetentionTime * 60 * 1000;
if (now - entry.timestamp > maxRetentionTimeInMs) {
await this._queueStore.deleteEntry(entry.id);
} else {
unexpiredEntries.push(convertEntry(entry));
}
}
return unexpiredEntries;
}
/**
* Adds the entry to the QueueStore and registers for a sync event.
*
* @param {Object} entry
* @param {Request} entry.request
* @param {Object} [entry.metadata]
* @param {number} [entry.timestamp=Date.now()]
* @param {string} operation ('push' or 'unshift')
* @private
*/
async _addRequest({
request,
metadata,
timestamp = Date.now()
}, operation) {
const storableRequest = await StorableRequest.fromRequest(request.clone());
const entry = {
requestData: storableRequest.toObject(),
timestamp
}; // Only include metadata if it's present.
if (metadata) {
entry.metadata = metadata;
}
await this._queueStore[`${operation}Entry`](entry);
{
logger_mjs.logger.log(`Request for '${getFriendlyURL_mjs.getFriendlyURL(request.url)}' has ` + `been added to background sync queue '${this._name}'.`);
} // Don't register for a sync if we're in the middle of a sync. Instead,
// we wait until the sync is complete and call register if
// `this._requestsAddedDuringSync` is true.
if (this._syncInProgress) {
this._requestsAddedDuringSync = true;
} else {
await this.registerSync();
}
}
/**
* Removes and returns the first or last (depending on `operation`) entry
* from the QueueStore that's not older than the `maxRetentionTime`.
*
* @param {string} operation ('pop' or 'shift')
* @return {Object|undefined}
* @private
*/
async _removeRequest(operation) {
const now = Date.now();
const entry = await this._queueStore[`${operation}Entry`]();
if (entry) {
// Ignore requests older than maxRetentionTime. Call this function
// recursively until an unexpired request is found.
const maxRetentionTimeInMs = this._maxRetentionTime * 60 * 1000;
if (now - entry.timestamp > maxRetentionTimeInMs) {
return this._removeRequest(operation);
}
return convertEntry(entry);
}
}
/**
* Loops through each request in the queue and attempts to re-fetch it.
* If any request fails to re-fetch, it's put back in the same position in
* the queue (which registers a retry for the next sync event).
*/
async replayRequests() {
let entry;
while (entry = await this.shiftRequest()) {
try {
await fetch(entry.request.clone());
{
logger_mjs.logger.log(`Request for '${getFriendlyURL_mjs.getFriendlyURL(entry.request.url)}'` + `has been replayed in queue '${this._name}'`);
}
} catch (error) {
await this.unshiftRequest(entry);
{
logger_mjs.logger.log(`Request for '${getFriendlyURL_mjs.getFriendlyURL(entry.request.url)}'` + `failed to replay, putting it back in queue '${this._name}'`);
}
throw new WorkboxError_mjs.WorkboxError('queue-replay-failed', {
name: this._name
});
}
}
{
logger_mjs.logger.log(`All requests in queue '${this.name}' have successfully ` + `replayed; the queue is now empty!`);
}
}
/**
* Registers a sync event with a tag unique to this instance.
*/
async registerSync() {
if ('sync' in registration) {
try {
await registration.sync.register(`${TAG_PREFIX}:${this._name}`);
} catch (err) {
// This means the registration failed for some reason, possibly due to
// the user disabling it.
{
logger_mjs.logger.warn(`Unable to register sync event for '${this._name}'.`, err);
}
}
}
}
/**
* In sync-supporting browsers, this adds a listener for the sync event.
* In non-sync-supporting browsers, this will retry the queue on service
* worker startup.
*
* @private
*/
_addSyncListener() {
if ('sync' in registration) {
self.addEventListener('sync', event => {
if (event.tag === `${TAG_PREFIX}:${this._name}`) {
{
logger_mjs.logger.log(`Background sync for tag '${event.tag}'` + `has been received`);
}
const syncComplete = async () => {
this._syncInProgress = true;
let syncError;
try {
await this._onSync({
queue: this
});
} catch (error) {
syncError = error; // Rethrow the error. Note: the logic in the finally clause
// will run before this gets rethrown.
throw syncError;
} finally {
// New items may have been added to the queue during the sync,
// so we need to register for a new sync if that's happened...
// Unless there was an error during the sync, in which
// case the browser will automatically retry later, as long
// as `event.lastChance` is not true.
if (this._requestsAddedDuringSync && !(syncError && !event.lastChance)) {
await this.registerSync();
}
this._syncInProgress = false;
this._requestsAddedDuringSync = false;
}
};
event.waitUntil(syncComplete());
}
});
} else {
{
logger_mjs.logger.log(`Background sync replaying without background sync event`);
} // If the browser doesn't support background sync, retry
// every time the service worker starts up as a fallback.
this._onSync({
queue: this
});
}
}
/**
* Returns the set of queue names. This is primarily used to reset the list
* of queue names in tests.
*
* @return {Set}
*
* @private
*/
static get _queueNames() {
return queueNames;
}
}
/**
* Converts a QueueStore entry into the format exposed by Queue. This entails
* converting the request data into a real request and omitting the `id` and
* `queueName` properties.
*
* @param {Object} queueStoreEntry
* @return {Object}
* @private
*/
const convertEntry = queueStoreEntry => {
const queueEntry = {
request: new StorableRequest(queueStoreEntry.requestData).toRequest(),
timestamp: queueStoreEntry.timestamp
};
if (queueStoreEntry.metadata) {
queueEntry.metadata = queueStoreEntry.metadata;
}
return queueEntry;
};
/*
Copyright 2018 Google LLC
Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.
*/
/**
* A class implementing the `fetchDidFail` lifecycle callback. This makes it
* easier to add failed requests to a background sync Queue.
*
* @memberof workbox.backgroundSync
*/
class Plugin {
/**
* @param {...*} queueArgs Args to forward to the composed Queue instance.
* See the [Queue]{@link workbox.backgroundSync.Queue} documentation for
* parameter details.
*/
constructor(...queueArgs) {
this._queue = new Queue(...queueArgs);
this.fetchDidFail = this.fetchDidFail.bind(this);
}
/**
* @param {Object} options
* @param {Request} options.request
* @private
*/
async fetchDidFail({
request
}) {
await this._queue.pushRequest({
request
});
}
}
/*
Copyright 2018 Google LLC
Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.
*/
exports.Queue = Queue;
exports.Plugin = Plugin;
return exports;
}({}, workbox.core._private, workbox.core._private, workbox.core._private, workbox.core._private, workbox.core._private));
//# sourceMappingURL=workbox-background-sync.dev.js.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,2 @@
this.workbox=this.workbox||{},this.workbox.backgroundSync=function(t,e,s){"use strict";try{self["workbox:background-sync:4.3.1"]&&_()}catch(t){}const i=3,n="workbox-background-sync",a="requests",r="queueName";class c{constructor(t){this.t=t,this.s=new s.DBWrapper(n,i,{onupgradeneeded:this.i})}async pushEntry(t){delete t.id,t.queueName=this.t,await this.s.add(a,t)}async unshiftEntry(t){const[e]=await this.s.getAllMatching(a,{count:1});e?t.id=e.id-1:delete t.id,t.queueName=this.t,await this.s.add(a,t)}async popEntry(){return this.h({direction:"prev"})}async shiftEntry(){return this.h({direction:"next"})}async getAll(){return await this.s.getAllMatching(a,{index:r,query:IDBKeyRange.only(this.t)})}async deleteEntry(t){await this.s.delete(a,t)}async h({direction:t}){const[e]=await this.s.getAllMatching(a,{direction:t,index:r,query:IDBKeyRange.only(this.t),count:1});if(e)return await this.deleteEntry(e.id),e}i(t){const e=t.target.result;t.oldVersion>0&&t.oldVersion<i&&e.objectStoreNames.contains(a)&&e.deleteObjectStore(a),e.createObjectStore(a,{autoIncrement:!0,keyPath:"id"}).createIndex(r,r,{unique:!1})}}const h=["method","referrer","referrerPolicy","mode","credentials","cache","redirect","integrity","keepalive"];class o{static async fromRequest(t){const e={url:t.url,headers:{}};"GET"!==t.method&&(e.body=await t.clone().arrayBuffer());for(const[s,i]of t.headers.entries())e.headers[s]=i;for(const s of h)void 0!==t[s]&&(e[s]=t[s]);return new o(e)}constructor(t){"navigate"===t.mode&&(t.mode="same-origin"),this.o=t}toObject(){const t=Object.assign({},this.o);return t.headers=Object.assign({},this.o.headers),t.body&&(t.body=t.body.slice(0)),t}toRequest(){return new Request(this.o.url,this.o)}clone(){return new o(this.toObject())}}const u="workbox-background-sync",y=10080,w=new Set;class d{constructor(t,{onSync:s,maxRetentionTime:i}={}){if(w.has(t))throw new e.WorkboxError("duplicate-queue-name",{name:t});w.add(t),this.u=t,this.l=s||this.replayRequests,this.q=i||y,this.m=new c(this.u),this.p()}get name(){return this.u}async pushRequest(t){await this.g(t,"push")}async unshiftRequest(t){await this.g(t,"unshift")}async popRequest(){return this.R("pop")}async shiftRequest(){return this.R("shift")}async getAll(){const t=await this.m.getAll(),e=Date.now(),s=[];for(const i of t){const t=60*this.q*1e3;e-i.timestamp>t?await this.m.deleteEntry(i.id):s.push(f(i))}return s}async g({request:t,metadata:e,timestamp:s=Date.now()},i){const n={requestData:(await o.fromRequest(t.clone())).toObject(),timestamp:s};e&&(n.metadata=e),await this.m[`${i}Entry`](n),this.k?this.D=!0:await this.registerSync()}async R(t){const e=Date.now(),s=await this.m[`${t}Entry`]();if(s){const i=60*this.q*1e3;return e-s.timestamp>i?this.R(t):f(s)}}async replayRequests(){let t;for(;t=await this.shiftRequest();)try{await fetch(t.request.clone())}catch(s){throw await this.unshiftRequest(t),new e.WorkboxError("queue-replay-failed",{name:this.u})}}async registerSync(){if("sync"in registration)try{await registration.sync.register(`${u}:${this.u}`)}catch(t){}}p(){"sync"in registration?self.addEventListener("sync",t=>{if(t.tag===`${u}:${this.u}`){const e=async()=>{let e;this.k=!0;try{await this.l({queue:this})}catch(t){throw e=t}finally{!this.D||e&&!t.lastChance||await this.registerSync(),this.k=!1,this.D=!1}};t.waitUntil(e())}}):this.l({queue:this})}static get _(){return w}}const f=t=>{const e={request:new o(t.requestData).toRequest(),timestamp:t.timestamp};return t.metadata&&(e.metadata=t.metadata),e};return t.Queue=d,t.Plugin=class{constructor(...t){this.v=new d(...t),this.fetchDidFail=this.fetchDidFail.bind(this)}async fetchDidFail({request:t}){await this.v.pushRequest({request:t})}},t}({},workbox.core._private,workbox.core._private);
//# sourceMappingURL=workbox-background-sync.prod.js.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,496 @@
this.workbox = this.workbox || {};
this.workbox.broadcastUpdate = (function (exports, assert_mjs, getFriendlyURL_mjs, logger_mjs, Deferred_mjs, WorkboxError_mjs) {
'use strict';
try {
self['workbox:broadcast-update:4.3.1'] && _();
} catch (e) {} // eslint-disable-line
/*
Copyright 2018 Google LLC
Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.
*/
/**
* Given two `Response's`, compares several header values to see if they are
* the same or not.
*
* @param {Response} firstResponse
* @param {Response} secondResponse
* @param {Array<string>} headersToCheck
* @return {boolean}
*
* @memberof workbox.broadcastUpdate
* @private
*/
const responsesAreSame = (firstResponse, secondResponse, headersToCheck) => {
{
if (!(firstResponse instanceof Response && secondResponse instanceof Response)) {
throw new WorkboxError_mjs.WorkboxError('invalid-responses-are-same-args');
}
}
const atLeastOneHeaderAvailable = headersToCheck.some(header => {
return firstResponse.headers.has(header) && secondResponse.headers.has(header);
});
if (!atLeastOneHeaderAvailable) {
{
logger_mjs.logger.warn(`Unable to determine where the response has been updated ` + `because none of the headers that would be checked are present.`);
logger_mjs.logger.debug(`Attempting to compare the following: `, firstResponse, secondResponse, headersToCheck);
} // Just return true, indicating the that responses are the same, since we
// can't determine otherwise.
return true;
}
return headersToCheck.every(header => {
const headerStateComparison = firstResponse.headers.has(header) === secondResponse.headers.has(header);
const headerValueComparison = firstResponse.headers.get(header) === secondResponse.headers.get(header);
return headerStateComparison && headerValueComparison;
});
};
/*
Copyright 2018 Google LLC
Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.
*/
const CACHE_UPDATED_MESSAGE_TYPE = 'CACHE_UPDATED';
const CACHE_UPDATED_MESSAGE_META = 'workbox-broadcast-update';
const DEFAULT_BROADCAST_CHANNEL_NAME = 'workbox';
const DEFAULT_DEFER_NOTIFICATION_TIMEOUT = 10000;
const DEFAULT_HEADERS_TO_CHECK = ['content-length', 'etag', 'last-modified'];
/*
Copyright 2018 Google LLC
Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.
*/
/**
* You would not normally call this method directly; it's called automatically
* by an instance of the {@link BroadcastCacheUpdate} class. It's exposed here
* for the benefit of developers who would rather not use the full
* `BroadcastCacheUpdate` implementation.
*
* Calling this will dispatch a message on the provided
* {@link https://developers.google.com/web/updates/2016/09/broadcastchannel|Broadcast Channel}
* to notify interested subscribers about a change to a cached resource.
*
* The message that's posted has a formation inspired by the
* [Flux standard action](https://github.com/acdlite/flux-standard-action#introduction)
* format like so:
*
* ```
* {
* type: 'CACHE_UPDATED',
* meta: 'workbox-broadcast-update',
* payload: {
* cacheName: 'the-cache-name',
* updatedURL: 'https://example.com/'
* }
* }
* ```
*
* (Usage of [Flux](https://facebook.github.io/flux/) itself is not at
* all required.)
*
* @param {Object} options
* @param {string} options.cacheName The name of the cache in which the updated
* `Response` was stored.
* @param {string} options.url The URL associated with the updated `Response`.
* @param {BroadcastChannel} [options.channel] The `BroadcastChannel` to use.
* If no channel is set or the browser doesn't support the BroadcastChannel
* api, then an attempt will be made to `postMessage` each window client.
*
* @memberof workbox.broadcastUpdate
*/
const broadcastUpdate = async ({
channel,
cacheName,
url
}) => {
{
assert_mjs.assert.isType(cacheName, 'string', {
moduleName: 'workbox-broadcast-update',
className: '~',
funcName: 'broadcastUpdate',
paramName: 'cacheName'
});
assert_mjs.assert.isType(url, 'string', {
moduleName: 'workbox-broadcast-update',
className: '~',
funcName: 'broadcastUpdate',
paramName: 'url'
});
}
const data = {
type: CACHE_UPDATED_MESSAGE_TYPE,
meta: CACHE_UPDATED_MESSAGE_META,
payload: {
cacheName: cacheName,
updatedURL: url
}
};
if (channel) {
channel.postMessage(data);
} else {
const windows = await clients.matchAll({
type: 'window'
});
for (const win of windows) {
win.postMessage(data);
}
}
};
/*
Copyright 2018 Google LLC
Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.
*/
/**
* Uses the [Broadcast Channel API]{@link https://developers.google.com/web/updates/2016/09/broadcastchannel}
* to notify interested parties when a cached response has been updated.
* In browsers that do not support the Broadcast Channel API, the instance
* falls back to sending the update via `postMessage()` to all window clients.
*
* For efficiency's sake, the underlying response bodies are not compared;
* only specific response headers are checked.
*
* @memberof workbox.broadcastUpdate
*/
class BroadcastCacheUpdate {
/**
* Construct a BroadcastCacheUpdate instance with a specific `channelName` to
* broadcast messages on
*
* @param {Object} options
* @param {Array<string>}
* [options.headersToCheck=['content-length', 'etag', 'last-modified']]
* A list of headers that will be used to determine whether the responses
* differ.
* @param {string} [options.channelName='workbox'] The name that will be used
*. when creating the `BroadcastChannel`, which defaults to 'workbox' (the
* channel name used by the `workbox-window` package).
* @param {string} [options.deferNoticationTimeout=10000] The amount of time
* to wait for a ready message from the window on navigation requests
* before sending the update.
*/
constructor({
headersToCheck,
channelName,
deferNoticationTimeout
} = {}) {
this._headersToCheck = headersToCheck || DEFAULT_HEADERS_TO_CHECK;
this._channelName = channelName || DEFAULT_BROADCAST_CHANNEL_NAME;
this._deferNoticationTimeout = deferNoticationTimeout || DEFAULT_DEFER_NOTIFICATION_TIMEOUT;
{
assert_mjs.assert.isType(this._channelName, 'string', {
moduleName: 'workbox-broadcast-update',
className: 'BroadcastCacheUpdate',
funcName: 'constructor',
paramName: 'channelName'
});
assert_mjs.assert.isArray(this._headersToCheck, {
moduleName: 'workbox-broadcast-update',
className: 'BroadcastCacheUpdate',
funcName: 'constructor',
paramName: 'headersToCheck'
});
}
this._initWindowReadyDeferreds();
}
/**
* Compare two [Responses](https://developer.mozilla.org/en-US/docs/Web/API/Response)
* and send a message via the
* {@link https://developers.google.com/web/updates/2016/09/broadcastchannel|Broadcast Channel API}
* if they differ.
*
* Neither of the Responses can be {@link http://stackoverflow.com/questions/39109789|opaque}.
*
* @param {Object} options
* @param {Response} options.oldResponse Cached response to compare.
* @param {Response} options.newResponse Possibly updated response to compare.
* @param {string} options.url The URL of the request.
* @param {string} options.cacheName Name of the cache the responses belong
* to. This is included in the broadcast message.
* @param {Event} [options.event] event An optional event that triggered
* this possible cache update.
* @return {Promise} Resolves once the update is sent.
*/
notifyIfUpdated({
oldResponse,
newResponse,
url,
cacheName,
event
}) {
if (!responsesAreSame(oldResponse, newResponse, this._headersToCheck)) {
{
logger_mjs.logger.log(`Newer response found (and cached) for:`, url);
}
const sendUpdate = async () => {
// In the case of a navigation request, the requesting page will likely
// not have loaded its JavaScript in time to recevied the update
// notification, so we defer it until ready (or we timeout waiting).
if (event && event.request && event.request.mode === 'navigate') {
{
logger_mjs.logger.debug(`Original request was a navigation request, ` + `waiting for a ready message from the window`, event.request);
}
await this._windowReadyOrTimeout(event);
}
await this._broadcastUpdate({
channel: this._getChannel(),
cacheName,
url
});
}; // Send the update and ensure the SW stays alive until it's sent.
const done = sendUpdate();
if (event) {
try {
event.waitUntil(done);
} catch (error) {
{
logger_mjs.logger.warn(`Unable to ensure service worker stays alive ` + `when broadcasting cache update for ` + `${getFriendlyURL_mjs.getFriendlyURL(event.request.url)}'.`);
}
}
}
return done;
}
}
/**
* NOTE: this is exposed on the instance primarily so it can be spied on
* in tests.
*
* @param {Object} opts
* @private
*/
async _broadcastUpdate(opts) {
await broadcastUpdate(opts);
}
/**
* @return {BroadcastChannel|undefined} The BroadcastChannel instance used for
* broadcasting updates, or undefined if the browser doesn't support the
* Broadcast Channel API.
*
* @private
*/
_getChannel() {
if ('BroadcastChannel' in self && !this._channel) {
this._channel = new BroadcastChannel(this._channelName);
}
return this._channel;
}
/**
* Waits for a message from the window indicating that it's capable of
* receiving broadcasts. By default, this will only wait for the amount of
* time specified via the `deferNoticationTimeout` option.
*
* @param {Event} event The navigation fetch event.
* @return {Promise}
* @private
*/
_windowReadyOrTimeout(event) {
if (!this._navigationEventsDeferreds.has(event)) {
const deferred = new Deferred_mjs.Deferred(); // Set the deferred on the `_navigationEventsDeferreds` map so it will
// be resolved when the next ready message event comes.
this._navigationEventsDeferreds.set(event, deferred); // But don't wait too long for the message since it may never come.
const timeout = setTimeout(() => {
{
logger_mjs.logger.debug(`Timed out after ${this._deferNoticationTimeout}` + `ms waiting for message from window`);
}
deferred.resolve();
}, this._deferNoticationTimeout); // Ensure the timeout is cleared if the deferred promise is resolved.
deferred.promise.then(() => clearTimeout(timeout));
}
return this._navigationEventsDeferreds.get(event).promise;
}
/**
* Creates a mapping between navigation fetch events and deferreds, and adds
* a listener for message events from the window. When message events arrive,
* all deferreds in the mapping are resolved.
*
* Note: it would be easier if we could only resolve the deferred of
* navigation fetch event whose client ID matched the source ID of the
* message event, but currently client IDs are not exposed on navigation
* fetch events: https://www.chromestatus.com/feature/4846038800138240
*
* @private
*/
_initWindowReadyDeferreds() {
// A mapping between navigation events and their deferreds.
this._navigationEventsDeferreds = new Map(); // The message listener needs to be added in the initial run of the
// service worker, but since we don't actually need to be listening for
// messages until the cache updates, we only invoke the callback if set.
self.addEventListener('message', event => {
if (event.data.type === 'WINDOW_READY' && event.data.meta === 'workbox-window' && this._navigationEventsDeferreds.size > 0) {
{
logger_mjs.logger.debug(`Received WINDOW_READY event: `, event);
} // Resolve any pending deferreds.
for (const deferred of this._navigationEventsDeferreds.values()) {
deferred.resolve();
}
this._navigationEventsDeferreds.clear();
}
});
}
}
/*
Copyright 2018 Google LLC
Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.
*/
/**
* This plugin will automatically broadcast a message whenever a cached response
* is updated.
*
* @memberof workbox.broadcastUpdate
*/
class Plugin {
/**
* Construct a BroadcastCacheUpdate instance with the passed options and
* calls its `notifyIfUpdated()` method whenever the plugin's
* `cacheDidUpdate` callback is invoked.
*
* @param {Object} options
* @param {Array<string>}
* [options.headersToCheck=['content-length', 'etag', 'last-modified']]
* A list of headers that will be used to determine whether the responses
* differ.
* @param {string} [options.channelName='workbox'] The name that will be used
*. when creating the `BroadcastChannel`, which defaults to 'workbox' (the
* channel name used by the `workbox-window` package).
* @param {string} [options.deferNoticationTimeout=10000] The amount of time
* to wait for a ready message from the window on navigation requests
* before sending the update.
*/
constructor(options) {
this._broadcastUpdate = new BroadcastCacheUpdate(options);
}
/**
* A "lifecycle" callback that will be triggered automatically by the
* `workbox-sw` and `workbox-runtime-caching` handlers when an entry is
* added to a cache.
*
* @private
* @param {Object} options The input object to this function.
* @param {string} options.cacheName Name of the cache being updated.
* @param {Response} [options.oldResponse] The previous cached value, if any.
* @param {Response} options.newResponse The new value in the cache.
* @param {Request} options.request The request that triggered the udpate.
* @param {Request} [options.event] The event that triggered the update.
*/
cacheDidUpdate({
cacheName,
oldResponse,
newResponse,
request,
event
}) {
{
assert_mjs.assert.isType(cacheName, 'string', {
moduleName: 'workbox-broadcast-update',
className: 'Plugin',
funcName: 'cacheDidUpdate',
paramName: 'cacheName'
});
assert_mjs.assert.isInstance(newResponse, Response, {
moduleName: 'workbox-broadcast-update',
className: 'Plugin',
funcName: 'cacheDidUpdate',
paramName: 'newResponse'
});
assert_mjs.assert.isInstance(request, Request, {
moduleName: 'workbox-broadcast-update',
className: 'Plugin',
funcName: 'cacheDidUpdate',
paramName: 'request'
});
}
if (!oldResponse) {
// Without a two responses there is nothing to compare.
return;
}
this._broadcastUpdate.notifyIfUpdated({
cacheName,
oldResponse,
newResponse,
event,
url: request.url
});
}
}
/*
Copyright 2018 Google LLC
Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.
*/
exports.BroadcastCacheUpdate = BroadcastCacheUpdate;
exports.Plugin = Plugin;
exports.broadcastUpdate = broadcastUpdate;
exports.responsesAreSame = responsesAreSame;
return exports;
}({}, workbox.core._private, workbox.core._private, workbox.core._private, workbox.core._private, workbox.core._private));
//# sourceMappingURL=workbox-broadcast-update.dev.js.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,2 @@
this.workbox=this.workbox||{},this.workbox.broadcastUpdate=function(e,t){"use strict";try{self["workbox:broadcast-update:4.3.1"]&&_()}catch(e){}const s=(e,t,s)=>{return!s.some(s=>e.headers.has(s)&&t.headers.has(s))||s.every(s=>{const n=e.headers.has(s)===t.headers.has(s),a=e.headers.get(s)===t.headers.get(s);return n&&a})},n="workbox",a=1e4,i=["content-length","etag","last-modified"],o=async({channel:e,cacheName:t,url:s})=>{const n={type:"CACHE_UPDATED",meta:"workbox-broadcast-update",payload:{cacheName:t,updatedURL:s}};if(e)e.postMessage(n);else{const e=await clients.matchAll({type:"window"});for(const t of e)t.postMessage(n)}};class c{constructor({headersToCheck:e,channelName:t,deferNoticationTimeout:s}={}){this.t=e||i,this.s=t||n,this.i=s||a,this.o()}notifyIfUpdated({oldResponse:e,newResponse:t,url:n,cacheName:a,event:i}){if(!s(e,t,this.t)){const e=(async()=>{i&&i.request&&"navigate"===i.request.mode&&await this.h(i),await this.l({channel:this.u(),cacheName:a,url:n})})();if(i)try{i.waitUntil(e)}catch(e){}return e}}async l(e){await o(e)}u(){return"BroadcastChannel"in self&&!this.p&&(this.p=new BroadcastChannel(this.s)),this.p}h(e){if(!this.m.has(e)){const s=new t.Deferred;this.m.set(e,s);const n=setTimeout(()=>{s.resolve()},this.i);s.promise.then(()=>clearTimeout(n))}return this.m.get(e).promise}o(){this.m=new Map,self.addEventListener("message",e=>{if("WINDOW_READY"===e.data.type&&"workbox-window"===e.data.meta&&this.m.size>0){for(const e of this.m.values())e.resolve();this.m.clear()}})}}return e.BroadcastCacheUpdate=c,e.Plugin=class{constructor(e){this.l=new c(e)}cacheDidUpdate({cacheName:e,oldResponse:t,newResponse:s,request:n,event:a}){t&&this.l.notifyIfUpdated({cacheName:e,oldResponse:t,newResponse:s,event:a,url:n.url})}},e.broadcastUpdate=o,e.responsesAreSame=s,e}({},workbox.core._private);
//# sourceMappingURL=workbox-broadcast-update.prod.js.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,200 @@
this.workbox = this.workbox || {};
this.workbox.cacheableResponse = (function (exports, WorkboxError_mjs, assert_mjs, getFriendlyURL_mjs, logger_mjs) {
'use strict';
try {
self['workbox:cacheable-response:4.3.1'] && _();
} catch (e) {} // eslint-disable-line
/*
Copyright 2018 Google LLC
Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.
*/
/**
* This class allows you to set up rules determining what
* status codes and/or headers need to be present in order for a
* [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response)
* to be considered cacheable.
*
* @memberof workbox.cacheableResponse
*/
class CacheableResponse {
/**
* To construct a new CacheableResponse instance you must provide at least
* one of the `config` properties.
*
* If both `statuses` and `headers` are specified, then both conditions must
* be met for the `Response` to be considered cacheable.
*
* @param {Object} config
* @param {Array<number>} [config.statuses] One or more status codes that a
* `Response` can have and be considered cacheable.
* @param {Object<string,string>} [config.headers] A mapping of header names
* and expected values that a `Response` can have and be considered cacheable.
* If multiple headers are provided, only one needs to be present.
*/
constructor(config = {}) {
{
if (!(config.statuses || config.headers)) {
throw new WorkboxError_mjs.WorkboxError('statuses-or-headers-required', {
moduleName: 'workbox-cacheable-response',
className: 'CacheableResponse',
funcName: 'constructor'
});
}
if (config.statuses) {
assert_mjs.assert.isArray(config.statuses, {
moduleName: 'workbox-cacheable-response',
className: 'CacheableResponse',
funcName: 'constructor',
paramName: 'config.statuses'
});
}
if (config.headers) {
assert_mjs.assert.isType(config.headers, 'object', {
moduleName: 'workbox-cacheable-response',
className: 'CacheableResponse',
funcName: 'constructor',
paramName: 'config.headers'
});
}
}
this._statuses = config.statuses;
this._headers = config.headers;
}
/**
* Checks a response to see whether it's cacheable or not, based on this
* object's configuration.
*
* @param {Response} response The response whose cacheability is being
* checked.
* @return {boolean} `true` if the `Response` is cacheable, and `false`
* otherwise.
*/
isResponseCacheable(response) {
{
assert_mjs.assert.isInstance(response, Response, {
moduleName: 'workbox-cacheable-response',
className: 'CacheableResponse',
funcName: 'isResponseCacheable',
paramName: 'response'
});
}
let cacheable = true;
if (this._statuses) {
cacheable = this._statuses.includes(response.status);
}
if (this._headers && cacheable) {
cacheable = Object.keys(this._headers).some(headerName => {
return response.headers.get(headerName) === this._headers[headerName];
});
}
{
if (!cacheable) {
logger_mjs.logger.groupCollapsed(`The request for ` + `'${getFriendlyURL_mjs.getFriendlyURL(response.url)}' returned a response that does ` + `not meet the criteria for being cached.`);
logger_mjs.logger.groupCollapsed(`View cacheability criteria here.`);
logger_mjs.logger.log(`Cacheable statuses: ` + JSON.stringify(this._statuses));
logger_mjs.logger.log(`Cacheable headers: ` + JSON.stringify(this._headers, null, 2));
logger_mjs.logger.groupEnd();
const logFriendlyHeaders = {};
response.headers.forEach((value, key) => {
logFriendlyHeaders[key] = value;
});
logger_mjs.logger.groupCollapsed(`View response status and headers here.`);
logger_mjs.logger.log(`Response status: ` + response.status);
logger_mjs.logger.log(`Response headers: ` + JSON.stringify(logFriendlyHeaders, null, 2));
logger_mjs.logger.groupEnd();
logger_mjs.logger.groupCollapsed(`View full response details here.`);
logger_mjs.logger.log(response.headers);
logger_mjs.logger.log(response);
logger_mjs.logger.groupEnd();
logger_mjs.logger.groupEnd();
}
}
return cacheable;
}
}
/*
Copyright 2018 Google LLC
Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.
*/
/**
* A class implementing the `cacheWillUpdate` lifecycle callback. This makes it
* easier to add in cacheability checks to requests made via Workbox's built-in
* strategies.
*
* @memberof workbox.cacheableResponse
*/
class Plugin {
/**
* To construct a new cacheable response Plugin instance you must provide at
* least one of the `config` properties.
*
* If both `statuses` and `headers` are specified, then both conditions must
* be met for the `Response` to be considered cacheable.
*
* @param {Object} config
* @param {Array<number>} [config.statuses] One or more status codes that a
* `Response` can have and be considered cacheable.
* @param {Object<string,string>} [config.headers] A mapping of header names
* and expected values that a `Response` can have and be considered cacheable.
* If multiple headers are provided, only one needs to be present.
*/
constructor(config) {
this._cacheableResponse = new CacheableResponse(config);
}
/**
* @param {Object} options
* @param {Response} options.response
* @return {boolean}
* @private
*/
cacheWillUpdate({
response
}) {
if (this._cacheableResponse.isResponseCacheable(response)) {
return response;
}
return null;
}
}
/*
Copyright 2018 Google LLC
Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.
*/
exports.CacheableResponse = CacheableResponse;
exports.Plugin = Plugin;
return exports;
}({}, workbox.core._private, workbox.core._private, workbox.core._private, workbox.core._private));
//# sourceMappingURL=workbox-cacheable-response.dev.js.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,2 @@
this.workbox=this.workbox||{},this.workbox.cacheableResponse=function(t){"use strict";try{self["workbox:cacheable-response:4.3.1"]&&_()}catch(t){}class s{constructor(t={}){this.t=t.statuses,this.s=t.headers}isResponseCacheable(t){let s=!0;return this.t&&(s=this.t.includes(t.status)),this.s&&s&&(s=Object.keys(this.s).some(s=>t.headers.get(s)===this.s[s])),s}}return t.CacheableResponse=s,t.Plugin=class{constructor(t){this.i=new s(t)}cacheWillUpdate({response:t}){return this.i.isResponseCacheable(t)?t:null}},t}({});
//# sourceMappingURL=workbox-cacheable-response.prod.js.map

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,652 @@
this.workbox = this.workbox || {};
this.workbox.expiration = (function (exports, DBWrapper_mjs, deleteDatabase_mjs, WorkboxError_mjs, assert_mjs, logger_mjs, cacheNames_mjs, getFriendlyURL_mjs, registerQuotaErrorCallback_mjs) {
'use strict';
try {
self['workbox:expiration:4.3.1'] && _();
} catch (e) {} // eslint-disable-line
/*
Copyright 2018 Google LLC
Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.
*/
const DB_NAME = 'workbox-expiration';
const OBJECT_STORE_NAME = 'cache-entries';
const normalizeURL = unNormalizedUrl => {
const url = new URL(unNormalizedUrl, location);
url.hash = '';
return url.href;
};
/**
* Returns the timestamp model.
*
* @private
*/
class CacheTimestampsModel {
/**
*
* @param {string} cacheName
*
* @private
*/
constructor(cacheName) {
this._cacheName = cacheName;
this._db = new DBWrapper_mjs.DBWrapper(DB_NAME, 1, {
onupgradeneeded: event => this._handleUpgrade(event)
});
}
/**
* Should perform an upgrade of indexedDB.
*
* @param {Event} event
*
* @private
*/
_handleUpgrade(event) {
const db = event.target.result; // TODO(philipwalton): EdgeHTML doesn't support arrays as a keyPath, so we
// have to use the `id` keyPath here and create our own values (a
// concatenation of `url + cacheName`) instead of simply using
// `keyPath: ['url', 'cacheName']`, which is supported in other browsers.
const objStore = db.createObjectStore(OBJECT_STORE_NAME, {
keyPath: 'id'
}); // TODO(philipwalton): once we don't have to support EdgeHTML, we can
// create a single index with the keyPath `['cacheName', 'timestamp']`
// instead of doing both these indexes.
objStore.createIndex('cacheName', 'cacheName', {
unique: false
});
objStore.createIndex('timestamp', 'timestamp', {
unique: false
}); // Previous versions of `workbox-expiration` used `this._cacheName`
// as the IDBDatabase name.
deleteDatabase_mjs.deleteDatabase(this._cacheName);
}
/**
* @param {string} url
* @param {number} timestamp
*
* @private
*/
async setTimestamp(url, timestamp) {
url = normalizeURL(url);
await this._db.put(OBJECT_STORE_NAME, {
url,
timestamp,
cacheName: this._cacheName,
// Creating an ID from the URL and cache name won't be necessary once
// Edge switches to Chromium and all browsers we support work with
// array keyPaths.
id: this._getId(url)
});
}
/**
* Returns the timestamp stored for a given URL.
*
* @param {string} url
* @return {number}
*
* @private
*/
async getTimestamp(url) {
const entry = await this._db.get(OBJECT_STORE_NAME, this._getId(url));
return entry.timestamp;
}
/**
* Iterates through all the entries in the object store (from newest to
* oldest) and removes entries once either `maxCount` is reached or the
* entry's timestamp is less than `minTimestamp`.
*
* @param {number} minTimestamp
* @param {number} maxCount
*
* @private
*/
async expireEntries(minTimestamp, maxCount) {
const entriesToDelete = await this._db.transaction(OBJECT_STORE_NAME, 'readwrite', (txn, done) => {
const store = txn.objectStore(OBJECT_STORE_NAME);
const entriesToDelete = [];
let entriesNotDeletedCount = 0;
store.index('timestamp').openCursor(null, 'prev').onsuccess = ({
target
}) => {
const cursor = target.result;
if (cursor) {
const result = cursor.value; // TODO(philipwalton): once we can use a multi-key index, we
// won't have to check `cacheName` here.
if (result.cacheName === this._cacheName) {
// Delete an entry if it's older than the max age or
// if we already have the max number allowed.
if (minTimestamp && result.timestamp < minTimestamp || maxCount && entriesNotDeletedCount >= maxCount) {
// TODO(philipwalton): we should be able to delete the
// entry right here, but doing so causes an iteration
// bug in Safari stable (fixed in TP). Instead we can
// store the keys of the entries to delete, and then
// delete the separate transactions.
// https://github.com/GoogleChrome/workbox/issues/1978
// cursor.delete();
// We only need to return the URL, not the whole entry.
entriesToDelete.push(cursor.value);
} else {
entriesNotDeletedCount++;
}
}
cursor.continue();
} else {
done(entriesToDelete);
}
};
}); // TODO(philipwalton): once the Safari bug in the following issue is fixed,
// we should be able to remove this loop and do the entry deletion in the
// cursor loop above:
// https://github.com/GoogleChrome/workbox/issues/1978
const urlsDeleted = [];
for (const entry of entriesToDelete) {
await this._db.delete(OBJECT_STORE_NAME, entry.id);
urlsDeleted.push(entry.url);
}
return urlsDeleted;
}
/**
* Takes a URL and returns an ID that will be unique in the object store.
*
* @param {string} url
* @return {string}
*
* @private
*/
_getId(url) {
// Creating an ID from the URL and cache name won't be necessary once
// Edge switches to Chromium and all browsers we support work with
// array keyPaths.
return this._cacheName + '|' + normalizeURL(url);
}
}
/*
Copyright 2018 Google LLC
Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.
*/
/**
* The `CacheExpiration` class allows you define an expiration and / or
* limit on the number of responses stored in a
* [`Cache`](https://developer.mozilla.org/en-US/docs/Web/API/Cache).
*
* @memberof workbox.expiration
*/
class CacheExpiration {
/**
* To construct a new CacheExpiration instance you must provide at least
* one of the `config` properties.
*
* @param {string} cacheName Name of the cache to apply restrictions to.
* @param {Object} config
* @param {number} [config.maxEntries] The maximum number of entries to cache.
* Entries used the least will be removed as the maximum is reached.
* @param {number} [config.maxAgeSeconds] The maximum age of an entry before
* it's treated as stale and removed.
*/
constructor(cacheName, config = {}) {
{
assert_mjs.assert.isType(cacheName, 'string', {
moduleName: 'workbox-expiration',
className: 'CacheExpiration',
funcName: 'constructor',
paramName: 'cacheName'
});
if (!(config.maxEntries || config.maxAgeSeconds)) {
throw new WorkboxError_mjs.WorkboxError('max-entries-or-age-required', {
moduleName: 'workbox-expiration',
className: 'CacheExpiration',
funcName: 'constructor'
});
}
if (config.maxEntries) {
assert_mjs.assert.isType(config.maxEntries, 'number', {
moduleName: 'workbox-expiration',
className: 'CacheExpiration',
funcName: 'constructor',
paramName: 'config.maxEntries'
}); // TODO: Assert is positive
}
if (config.maxAgeSeconds) {
assert_mjs.assert.isType(config.maxAgeSeconds, 'number', {
moduleName: 'workbox-expiration',
className: 'CacheExpiration',
funcName: 'constructor',
paramName: 'config.maxAgeSeconds'
}); // TODO: Assert is positive
}
}
this._isRunning = false;
this._rerunRequested = false;
this._maxEntries = config.maxEntries;
this._maxAgeSeconds = config.maxAgeSeconds;
this._cacheName = cacheName;
this._timestampModel = new CacheTimestampsModel(cacheName);
}
/**
* Expires entries for the given cache and given criteria.
*/
async expireEntries() {
if (this._isRunning) {
this._rerunRequested = true;
return;
}
this._isRunning = true;
const minTimestamp = this._maxAgeSeconds ? Date.now() - this._maxAgeSeconds * 1000 : undefined;
const urlsExpired = await this._timestampModel.expireEntries(minTimestamp, this._maxEntries); // Delete URLs from the cache
const cache = await caches.open(this._cacheName);
for (const url of urlsExpired) {
await cache.delete(url);
}
{
if (urlsExpired.length > 0) {
logger_mjs.logger.groupCollapsed(`Expired ${urlsExpired.length} ` + `${urlsExpired.length === 1 ? 'entry' : 'entries'} and removed ` + `${urlsExpired.length === 1 ? 'it' : 'them'} from the ` + `'${this._cacheName}' cache.`);
logger_mjs.logger.log(`Expired the following ${urlsExpired.length === 1 ? 'URL' : 'URLs'}:`);
urlsExpired.forEach(url => logger_mjs.logger.log(` ${url}`));
logger_mjs.logger.groupEnd();
} else {
logger_mjs.logger.debug(`Cache expiration ran and found no entries to remove.`);
}
}
this._isRunning = false;
if (this._rerunRequested) {
this._rerunRequested = false;
this.expireEntries();
}
}
/**
* Update the timestamp for the given URL. This ensures the when
* removing entries based on maximum entries, most recently used
* is accurate or when expiring, the timestamp is up-to-date.
*
* @param {string} url
*/
async updateTimestamp(url) {
{
assert_mjs.assert.isType(url, 'string', {
moduleName: 'workbox-expiration',
className: 'CacheExpiration',
funcName: 'updateTimestamp',
paramName: 'url'
});
}
await this._timestampModel.setTimestamp(url, Date.now());
}
/**
* Can be used to check if a URL has expired or not before it's used.
*
* This requires a look up from IndexedDB, so can be slow.
*
* Note: This method will not remove the cached entry, call
* `expireEntries()` to remove indexedDB and Cache entries.
*
* @param {string} url
* @return {boolean}
*/
async isURLExpired(url) {
{
if (!this._maxAgeSeconds) {
throw new WorkboxError_mjs.WorkboxError(`expired-test-without-max-age`, {
methodName: 'isURLExpired',
paramName: 'maxAgeSeconds'
});
}
}
const timestamp = await this._timestampModel.getTimestamp(url);
const expireOlderThan = Date.now() - this._maxAgeSeconds * 1000;
return timestamp < expireOlderThan;
}
/**
* Removes the IndexedDB object store used to keep track of cache expiration
* metadata.
*/
async delete() {
// Make sure we don't attempt another rerun if we're called in the middle of
// a cache expiration.
this._rerunRequested = false;
await this._timestampModel.expireEntries(Infinity); // Expires all.
}
}
/*
Copyright 2018 Google LLC
Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.
*/
/**
* This plugin can be used in the Workbox APIs to regularly enforce a
* limit on the age and / or the number of cached requests.
*
* Whenever a cached request is used or updated, this plugin will look
* at the used Cache and remove any old or extra requests.
*
* When using `maxAgeSeconds`, requests may be used *once* after expiring
* because the expiration clean up will not have occurred until *after* the
* cached request has been used. If the request has a "Date" header, then
* a light weight expiration check is performed and the request will not be
* used immediately.
*
* When using `maxEntries`, the entry least-recently requested will be removed from the cache first.
*
* @memberof workbox.expiration
*/
class Plugin {
/**
* @param {Object} config
* @param {number} [config.maxEntries] The maximum number of entries to cache.
* Entries used the least will be removed as the maximum is reached.
* @param {number} [config.maxAgeSeconds] The maximum age of an entry before
* it's treated as stale and removed.
* @param {boolean} [config.purgeOnQuotaError] Whether to opt this cache in to
* automatic deletion if the available storage quota has been exceeded.
*/
constructor(config = {}) {
{
if (!(config.maxEntries || config.maxAgeSeconds)) {
throw new WorkboxError_mjs.WorkboxError('max-entries-or-age-required', {
moduleName: 'workbox-expiration',
className: 'Plugin',
funcName: 'constructor'
});
}
if (config.maxEntries) {
assert_mjs.assert.isType(config.maxEntries, 'number', {
moduleName: 'workbox-expiration',
className: 'Plugin',
funcName: 'constructor',
paramName: 'config.maxEntries'
});
}
if (config.maxAgeSeconds) {
assert_mjs.assert.isType(config.maxAgeSeconds, 'number', {
moduleName: 'workbox-expiration',
className: 'Plugin',
funcName: 'constructor',
paramName: 'config.maxAgeSeconds'
});
}
}
this._config = config;
this._maxAgeSeconds = config.maxAgeSeconds;
this._cacheExpirations = new Map();
if (config.purgeOnQuotaError) {
registerQuotaErrorCallback_mjs.registerQuotaErrorCallback(() => this.deleteCacheAndMetadata());
}
}
/**
* A simple helper method to return a CacheExpiration instance for a given
* cache name.
*
* @param {string} cacheName
* @return {CacheExpiration}
*
* @private
*/
_getCacheExpiration(cacheName) {
if (cacheName === cacheNames_mjs.cacheNames.getRuntimeName()) {
throw new WorkboxError_mjs.WorkboxError('expire-custom-caches-only');
}
let cacheExpiration = this._cacheExpirations.get(cacheName);
if (!cacheExpiration) {
cacheExpiration = new CacheExpiration(cacheName, this._config);
this._cacheExpirations.set(cacheName, cacheExpiration);
}
return cacheExpiration;
}
/**
* A "lifecycle" callback that will be triggered automatically by the
* `workbox.strategies` handlers when a `Response` is about to be returned
* from a [Cache](https://developer.mozilla.org/en-US/docs/Web/API/Cache) to
* the handler. It allows the `Response` to be inspected for freshness and
* prevents it from being used if the `Response`'s `Date` header value is
* older than the configured `maxAgeSeconds`.
*
* @param {Object} options
* @param {string} options.cacheName Name of the cache the response is in.
* @param {Response} options.cachedResponse The `Response` object that's been
* read from a cache and whose freshness should be checked.
* @return {Response} Either the `cachedResponse`, if it's
* fresh, or `null` if the `Response` is older than `maxAgeSeconds`.
*
* @private
*/
cachedResponseWillBeUsed({
event,
request,
cacheName,
cachedResponse
}) {
if (!cachedResponse) {
return null;
}
let isFresh = this._isResponseDateFresh(cachedResponse); // Expire entries to ensure that even if the expiration date has
// expired, it'll only be used once.
const cacheExpiration = this._getCacheExpiration(cacheName);
cacheExpiration.expireEntries(); // Update the metadata for the request URL to the current timestamp,
// but don't `await` it as we don't want to block the response.
const updateTimestampDone = cacheExpiration.updateTimestamp(request.url);
if (event) {
try {
event.waitUntil(updateTimestampDone);
} catch (error) {
{
logger_mjs.logger.warn(`Unable to ensure service worker stays alive when ` + `updating cache entry for '${getFriendlyURL_mjs.getFriendlyURL(event.request.url)}'.`);
}
}
}
return isFresh ? cachedResponse : null;
}
/**
* @param {Response} cachedResponse
* @return {boolean}
*
* @private
*/
_isResponseDateFresh(cachedResponse) {
if (!this._maxAgeSeconds) {
// We aren't expiring by age, so return true, it's fresh
return true;
} // Check if the 'date' header will suffice a quick expiration check.
// See https://github.com/GoogleChromeLabs/sw-toolbox/issues/164 for
// discussion.
const dateHeaderTimestamp = this._getDateHeaderTimestamp(cachedResponse);
if (dateHeaderTimestamp === null) {
// Unable to parse date, so assume it's fresh.
return true;
} // If we have a valid headerTime, then our response is fresh iff the
// headerTime plus maxAgeSeconds is greater than the current time.
const now = Date.now();
return dateHeaderTimestamp >= now - this._maxAgeSeconds * 1000;
}
/**
* This method will extract the data header and parse it into a useful
* value.
*
* @param {Response} cachedResponse
* @return {number}
*
* @private
*/
_getDateHeaderTimestamp(cachedResponse) {
if (!cachedResponse.headers.has('date')) {
return null;
}
const dateHeader = cachedResponse.headers.get('date');
const parsedDate = new Date(dateHeader);
const headerTime = parsedDate.getTime(); // If the Date header was invalid for some reason, parsedDate.getTime()
// will return NaN.
if (isNaN(headerTime)) {
return null;
}
return headerTime;
}
/**
* A "lifecycle" callback that will be triggered automatically by the
* `workbox.strategies` handlers when an entry is added to a cache.
*
* @param {Object} options
* @param {string} options.cacheName Name of the cache that was updated.
* @param {string} options.request The Request for the cached entry.
*
* @private
*/
async cacheDidUpdate({
cacheName,
request
}) {
{
assert_mjs.assert.isType(cacheName, 'string', {
moduleName: 'workbox-expiration',
className: 'Plugin',
funcName: 'cacheDidUpdate',
paramName: 'cacheName'
});
assert_mjs.assert.isInstance(request, Request, {
moduleName: 'workbox-expiration',
className: 'Plugin',
funcName: 'cacheDidUpdate',
paramName: 'request'
});
}
const cacheExpiration = this._getCacheExpiration(cacheName);
await cacheExpiration.updateTimestamp(request.url);
await cacheExpiration.expireEntries();
}
/**
* This is a helper method that performs two operations:
*
* - Deletes *all* the underlying Cache instances associated with this plugin
* instance, by calling caches.delete() on your behalf.
* - Deletes the metadata from IndexedDB used to keep track of expiration
* details for each Cache instance.
*
* When using cache expiration, calling this method is preferable to calling
* `caches.delete()` directly, since this will ensure that the IndexedDB
* metadata is also cleanly removed and open IndexedDB instances are deleted.
*
* Note that if you're *not* using cache expiration for a given cache, calling
* `caches.delete()` and passing in the cache's name should be sufficient.
* There is no Workbox-specific method needed for cleanup in that case.
*/
async deleteCacheAndMetadata() {
// Do this one at a time instead of all at once via `Promise.all()` to
// reduce the chance of inconsistency if a promise rejects.
for (const [cacheName, cacheExpiration] of this._cacheExpirations) {
await caches.delete(cacheName);
await cacheExpiration.delete();
} // Reset this._cacheExpirations to its initial state.
this._cacheExpirations = new Map();
}
}
/*
Copyright 2018 Google LLC
Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.
*/
exports.CacheExpiration = CacheExpiration;
exports.Plugin = Plugin;
return exports;
}({}, workbox.core._private, workbox.core._private, workbox.core._private, workbox.core._private, workbox.core._private, workbox.core._private, workbox.core._private, workbox.core));
//# sourceMappingURL=workbox-expiration.dev.js.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,2 @@
this.workbox=this.workbox||{},this.workbox.expiration=function(t,e,s,i,a,n){"use strict";try{self["workbox:expiration:4.3.1"]&&_()}catch(t){}const h="workbox-expiration",c="cache-entries",r=t=>{const e=new URL(t,location);return e.hash="",e.href};class o{constructor(t){this.t=t,this.s=new e.DBWrapper(h,1,{onupgradeneeded:t=>this.i(t)})}i(t){const e=t.target.result.createObjectStore(c,{keyPath:"id"});e.createIndex("cacheName","cacheName",{unique:!1}),e.createIndex("timestamp","timestamp",{unique:!1}),s.deleteDatabase(this.t)}async setTimestamp(t,e){t=r(t),await this.s.put(c,{url:t,timestamp:e,cacheName:this.t,id:this.h(t)})}async getTimestamp(t){return(await this.s.get(c,this.h(t))).timestamp}async expireEntries(t,e){const s=await this.s.transaction(c,"readwrite",(s,i)=>{const a=s.objectStore(c),n=[];let h=0;a.index("timestamp").openCursor(null,"prev").onsuccess=(({target:s})=>{const a=s.result;if(a){const s=a.value;s.cacheName===this.t&&(t&&s.timestamp<t||e&&h>=e?n.push(a.value):h++),a.continue()}else i(n)})}),i=[];for(const t of s)await this.s.delete(c,t.id),i.push(t.url);return i}h(t){return this.t+"|"+r(t)}}class u{constructor(t,e={}){this.o=!1,this.u=!1,this.l=e.maxEntries,this.p=e.maxAgeSeconds,this.t=t,this.m=new o(t)}async expireEntries(){if(this.o)return void(this.u=!0);this.o=!0;const t=this.p?Date.now()-1e3*this.p:void 0,e=await this.m.expireEntries(t,this.l),s=await caches.open(this.t);for(const t of e)await s.delete(t);this.o=!1,this.u&&(this.u=!1,this.expireEntries())}async updateTimestamp(t){await this.m.setTimestamp(t,Date.now())}async isURLExpired(t){return await this.m.getTimestamp(t)<Date.now()-1e3*this.p}async delete(){this.u=!1,await this.m.expireEntries(1/0)}}return t.CacheExpiration=u,t.Plugin=class{constructor(t={}){this.D=t,this.p=t.maxAgeSeconds,this.g=new Map,t.purgeOnQuotaError&&n.registerQuotaErrorCallback(()=>this.deleteCacheAndMetadata())}k(t){if(t===a.cacheNames.getRuntimeName())throw new i.WorkboxError("expire-custom-caches-only");let e=this.g.get(t);return e||(e=new u(t,this.D),this.g.set(t,e)),e}cachedResponseWillBeUsed({event:t,request:e,cacheName:s,cachedResponse:i}){if(!i)return null;let a=this.N(i);const n=this.k(s);n.expireEntries();const h=n.updateTimestamp(e.url);if(t)try{t.waitUntil(h)}catch(t){}return a?i:null}N(t){if(!this.p)return!0;const e=this._(t);return null===e||e>=Date.now()-1e3*this.p}_(t){if(!t.headers.has("date"))return null;const e=t.headers.get("date"),s=new Date(e).getTime();return isNaN(s)?null:s}async cacheDidUpdate({cacheName:t,request:e}){const s=this.k(t);await s.updateTimestamp(e.url),await s.expireEntries()}async deleteCacheAndMetadata(){for(const[t,e]of this.g)await caches.delete(t),await e.delete();this.g=new Map}},t}({},workbox.core._private,workbox.core._private,workbox.core._private,workbox.core._private,workbox.core);
//# sourceMappingURL=workbox-expiration.prod.js.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,110 @@
this.workbox = this.workbox || {};
this.workbox.navigationPreload = (function (exports, logger_mjs) {
'use strict';
try {
self['workbox:navigation-preload:4.3.1'] && _();
} catch (e) {} // eslint-disable-line
/*
Copyright 2018 Google LLC
Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.
*/
/**
* @return {boolean} Whether or not the current browser supports enabling
* navigation preload.
*
* @memberof workbox.navigationPreload
*/
function isSupported() {
return Boolean(self.registration && self.registration.navigationPreload);
}
/*
Copyright 2018 Google LLC
Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.
*/
/**
* If the browser supports Navigation Preload, then this will disable it.
*
* @memberof workbox.navigationPreload
*/
function disable() {
if (isSupported()) {
self.addEventListener('activate', event => {
event.waitUntil(self.registration.navigationPreload.disable().then(() => {
{
logger_mjs.logger.log(`Navigation preload is disabled.`);
}
}));
});
} else {
{
logger_mjs.logger.log(`Navigation preload is not supported in this browser.`);
}
}
}
/*
Copyright 2018 Google LLC
Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.
*/
/**
* If the browser supports Navigation Preload, then this will enable it.
*
* @param {string} [headerValue] Optionally, allows developers to
* [override](https://developers.google.com/web/updates/2017/02/navigation-preload#changing_the_header)
* the value of the `Service-Worker-Navigation-Preload` header which will be
* sent to the server when making the navigation request.
*
* @memberof workbox.navigationPreload
*/
function enable(headerValue) {
if (isSupported()) {
self.addEventListener('activate', event => {
event.waitUntil(self.registration.navigationPreload.enable().then(() => {
// Defaults to Service-Worker-Navigation-Preload: true if not set.
if (headerValue) {
self.registration.navigationPreload.setHeaderValue(headerValue);
}
{
logger_mjs.logger.log(`Navigation preload is enabled.`);
}
}));
});
} else {
{
logger_mjs.logger.log(`Navigation preload is not supported in this browser.`);
}
}
}
/*
Copyright 2018 Google LLC
Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.
*/
exports.disable = disable;
exports.enable = enable;
exports.isSupported = isSupported;
return exports;
}({}, workbox.core._private));
//# sourceMappingURL=workbox-navigation-preload.dev.js.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,2 @@
this.workbox=this.workbox||{},this.workbox.navigationPreload=function(t){"use strict";try{self["workbox:navigation-preload:4.3.1"]&&_()}catch(t){}function e(){return Boolean(self.registration&&self.registration.navigationPreload)}return t.disable=function(){e()&&self.addEventListener("activate",t=>{t.waitUntil(self.registration.navigationPreload.disable().then(()=>{}))})},t.enable=function(t){e()&&self.addEventListener("activate",e=>{e.waitUntil(self.registration.navigationPreload.enable().then(()=>{t&&self.registration.navigationPreload.setHeaderValue(t)}))})},t.isSupported=e,t}({});
//# sourceMappingURL=workbox-navigation-preload.prod.js.map

View File

@ -0,0 +1 @@
{"version":3,"file":"workbox-navigation-preload.prod.js","sources":["../_version.mjs","../isSupported.mjs","../disable.mjs","../enable.mjs"],"sourcesContent":["try{self['workbox:navigation-preload:4.3.1']&&_()}catch(e){}// eslint-disable-line","/*\n Copyright 2018 Google LLC\n\n Use of this source code is governed by an MIT-style\n license that can be found in the LICENSE file or at\n https://opensource.org/licenses/MIT.\n*/\n\nimport './_version.mjs';\n\n/**\n * @return {boolean} Whether or not the current browser supports enabling\n * navigation preload.\n *\n * @memberof workbox.navigationPreload\n */\nfunction isSupported() {\n return Boolean(self.registration && self.registration.navigationPreload);\n}\n\nexport {isSupported};\n","/*\n Copyright 2018 Google LLC\n\n Use of this source code is governed by an MIT-style\n license that can be found in the LICENSE file or at\n https://opensource.org/licenses/MIT.\n*/\n\nimport {logger} from 'workbox-core/_private/logger.mjs';\n\nimport {isSupported} from './isSupported.mjs';\n\nimport './_version.mjs';\n\n/**\n * If the browser supports Navigation Preload, then this will disable it.\n *\n * @memberof workbox.navigationPreload\n */\nfunction disable() {\n if (isSupported()) {\n self.addEventListener('activate', (event) => {\n event.waitUntil(\n self.registration.navigationPreload.disable().then(() => {\n if (process.env.NODE_ENV !== 'production') {\n logger.log(`Navigation preload is disabled.`);\n }\n })\n );\n });\n } else {\n if (process.env.NODE_ENV !== 'production') {\n logger.log(`Navigation preload is not supported in this browser.`);\n }\n }\n}\n\nexport {disable};\n","/*\n Copyright 2018 Google LLC\n\n Use of this source code is governed by an MIT-style\n license that can be found in the LICENSE file or at\n https://opensource.org/licenses/MIT.\n*/\n\nimport {logger} from 'workbox-core/_private/logger.mjs';\n\nimport {isSupported} from './isSupported.mjs';\n\nimport './_version.mjs';\n\n/**\n * If the browser supports Navigation Preload, then this will enable it.\n *\n * @param {string} [headerValue] Optionally, allows developers to\n * [override](https://developers.google.com/web/updates/2017/02/navigation-preload#changing_the_header)\n * the value of the `Service-Worker-Navigation-Preload` header which will be\n * sent to the server when making the navigation request.\n *\n * @memberof workbox.navigationPreload\n */\nfunction enable(headerValue) {\n if (isSupported()) {\n self.addEventListener('activate', (event) => {\n event.waitUntil(\n self.registration.navigationPreload.enable().then(() => {\n // Defaults to Service-Worker-Navigation-Preload: true if not set.\n if (headerValue) {\n self.registration.navigationPreload.setHeaderValue(headerValue);\n }\n\n if (process.env.NODE_ENV !== 'production') {\n logger.log(`Navigation preload is enabled.`);\n }\n })\n );\n });\n } else {\n if (process.env.NODE_ENV !== 'production') {\n logger.log(`Navigation preload is not supported in this browser.`);\n }\n }\n}\n\nexport {enable};\n"],"names":["self","_","e","isSupported","Boolean","registration","navigationPreload","addEventListener","event","waitUntil","disable","then","headerValue","enable","setHeaderValue"],"mappings":"sFAAA,IAAIA,KAAK,qCAAqCC,IAAI,MAAMC,ICgBxD,SAASC,WACAC,QAAQJ,KAAKK,cAAgBL,KAAKK,aAAaC,oCCExD,WACMH,KACFH,KAAKO,iBAAiB,WAAaC,IACjCA,EAAMC,UACFT,KAAKK,aAAaC,kBAAkBI,UAAUC,KAAK,qBCC7D,SAAgBC,GACVT,KACFH,KAAKO,iBAAiB,WAAaC,IACjCA,EAAMC,UACFT,KAAKK,aAAaC,kBAAkBO,SAASF,KAAK,KAE5CC,GACFZ,KAAKK,aAAaC,kBAAkBQ,eAAeF"}

View File

@ -0,0 +1,243 @@
this.workbox = this.workbox || {};
this.workbox.googleAnalytics = (function (exports, Plugin_mjs, cacheNames_mjs, getFriendlyURL_mjs, logger_mjs, Route_mjs, Router_mjs, NetworkFirst_mjs, NetworkOnly_mjs) {
'use strict';
try {
self['workbox:google-analytics:4.3.1'] && _();
} catch (e) {} // eslint-disable-line
/*
Copyright 2018 Google LLC
Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.
*/
const QUEUE_NAME = 'workbox-google-analytics';
const MAX_RETENTION_TIME = 60 * 48; // Two days in minutes
const GOOGLE_ANALYTICS_HOST = 'www.google-analytics.com';
const GTM_HOST = 'www.googletagmanager.com';
const ANALYTICS_JS_PATH = '/analytics.js';
const GTAG_JS_PATH = '/gtag/js';
const GTM_JS_PATH = '/gtm.js';
// endpoints. Most of the time the default path (/collect) is used, but
// occasionally an experimental endpoint is used when testing new features,
// (e.g. /r/collect or /j/collect)
const COLLECT_PATHS_REGEX = /^\/(\w+\/)?collect/;
/*
Copyright 2018 Google LLC
Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.
*/
/**
* Creates the requestWillDequeue callback to be used with the background
* sync queue plugin. The callback takes the failed request and adds the
* `qt` param based on the current time, as well as applies any other
* user-defined hit modifications.
*
* @param {Object} config See workbox.googleAnalytics.initialize.
* @return {Function} The requestWillDequeu callback function.
*
* @private
*/
const createOnSyncCallback = config => {
return async ({
queue
}) => {
let entry;
while (entry = await queue.shiftRequest()) {
const {
request,
timestamp
} = entry;
const url = new URL(request.url);
try {
// Measurement protocol requests can set their payload parameters in
// either the URL query string (for GET requests) or the POST body.
const params = request.method === 'POST' ? new URLSearchParams((await request.clone().text())) : url.searchParams; // Calculate the qt param, accounting for the fact that an existing
// qt param may be present and should be updated rather than replaced.
const originalHitTime = timestamp - (Number(params.get('qt')) || 0);
const queueTime = Date.now() - originalHitTime; // Set the qt param prior to applying hitFilter or parameterOverrides.
params.set('qt', queueTime); // Apply `paramterOverrideds`, if set.
if (config.parameterOverrides) {
for (const param of Object.keys(config.parameterOverrides)) {
const value = config.parameterOverrides[param];
params.set(param, value);
}
} // Apply `hitFilter`, if set.
if (typeof config.hitFilter === 'function') {
config.hitFilter.call(null, params);
} // Retry the fetch. Ignore URL search params from the URL as they're
// now in the post body.
await fetch(new Request(url.origin + url.pathname, {
body: params.toString(),
method: 'POST',
mode: 'cors',
credentials: 'omit',
headers: {
'Content-Type': 'text/plain'
}
}));
{
logger_mjs.logger.log(`Request for '${getFriendlyURL_mjs.getFriendlyURL(url.href)}'` + `has been replayed`);
}
} catch (err) {
await queue.unshiftRequest(entry);
{
logger_mjs.logger.log(`Request for '${getFriendlyURL_mjs.getFriendlyURL(url.href)}'` + `failed to replay, putting it back in the queue.`);
}
throw err;
}
}
{
logger_mjs.logger.log(`All Google Analytics request successfully replayed; ` + `the queue is now empty!`);
}
};
};
/**
* Creates GET and POST routes to catch failed Measurement Protocol hits.
*
* @param {Plugin} queuePlugin
* @return {Array<Route>} The created routes.
*
* @private
*/
const createCollectRoutes = queuePlugin => {
const match = ({
url
}) => url.hostname === GOOGLE_ANALYTICS_HOST && COLLECT_PATHS_REGEX.test(url.pathname);
const handler = new NetworkOnly_mjs.NetworkOnly({
plugins: [queuePlugin]
});
return [new Route_mjs.Route(match, handler, 'GET'), new Route_mjs.Route(match, handler, 'POST')];
};
/**
* Creates a route with a network first strategy for the analytics.js script.
*
* @param {string} cacheName
* @return {Route} The created route.
*
* @private
*/
const createAnalyticsJsRoute = cacheName => {
const match = ({
url
}) => url.hostname === GOOGLE_ANALYTICS_HOST && url.pathname === ANALYTICS_JS_PATH;
const handler = new NetworkFirst_mjs.NetworkFirst({
cacheName
});
return new Route_mjs.Route(match, handler, 'GET');
};
/**
* Creates a route with a network first strategy for the gtag.js script.
*
* @param {string} cacheName
* @return {Route} The created route.
*
* @private
*/
const createGtagJsRoute = cacheName => {
const match = ({
url
}) => url.hostname === GTM_HOST && url.pathname === GTAG_JS_PATH;
const handler = new NetworkFirst_mjs.NetworkFirst({
cacheName
});
return new Route_mjs.Route(match, handler, 'GET');
};
/**
* Creates a route with a network first strategy for the gtm.js script.
*
* @param {string} cacheName
* @return {Route} The created route.
*
* @private
*/
const createGtmJsRoute = cacheName => {
const match = ({
url
}) => url.hostname === GTM_HOST && url.pathname === GTM_JS_PATH;
const handler = new NetworkFirst_mjs.NetworkFirst({
cacheName
});
return new Route_mjs.Route(match, handler, 'GET');
};
/**
* @param {Object=} [options]
* @param {Object} [options.cacheName] The cache name to store and retrieve
* analytics.js. Defaults to the cache names provided by `workbox-core`.
* @param {Object} [options.parameterOverrides]
* [Measurement Protocol parameters](https://developers.google.com/analytics/devguides/collection/protocol/v1/parameters),
* expressed as key/value pairs, to be added to replayed Google Analytics
* requests. This can be used to, e.g., set a custom dimension indicating
* that the request was replayed.
* @param {Function} [options.hitFilter] A function that allows you to modify
* the hit parameters prior to replaying
* the hit. The function is invoked with the original hit's URLSearchParams
* object as its only argument.
*
* @memberof workbox.googleAnalytics
*/
const initialize = (options = {}) => {
const cacheName = cacheNames_mjs.cacheNames.getGoogleAnalyticsName(options.cacheName);
const queuePlugin = new Plugin_mjs.Plugin(QUEUE_NAME, {
maxRetentionTime: MAX_RETENTION_TIME,
onSync: createOnSyncCallback(options)
});
const routes = [createGtmJsRoute(cacheName), createAnalyticsJsRoute(cacheName), createGtagJsRoute(cacheName), ...createCollectRoutes(queuePlugin)];
const router = new Router_mjs.Router();
for (const route of routes) {
router.registerRoute(route);
}
router.addFetchListener();
};
/*
Copyright 2018 Google LLC
Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.
*/
exports.initialize = initialize;
return exports;
}({}, workbox.backgroundSync, workbox.core._private, workbox.core._private, workbox.core._private, workbox.routing, workbox.routing, workbox.strategies, workbox.strategies));
//# sourceMappingURL=workbox-offline-ga.dev.js.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,2 @@
this.workbox=this.workbox||{},this.workbox.googleAnalytics=function(e,t,o,n,a,c,w){"use strict";try{self["workbox:google-analytics:4.3.1"]&&_()}catch(e){}const r=/^\/(\w+\/)?collect/,s=e=>async({queue:t})=>{let o;for(;o=await t.shiftRequest();){const{request:n,timestamp:a}=o,c=new URL(n.url);try{const w="POST"===n.method?new URLSearchParams(await n.clone().text()):c.searchParams,r=a-(Number(w.get("qt"))||0),s=Date.now()-r;if(w.set("qt",s),e.parameterOverrides)for(const t of Object.keys(e.parameterOverrides)){const o=e.parameterOverrides[t];w.set(t,o)}"function"==typeof e.hitFilter&&e.hitFilter.call(null,w),await fetch(new Request(c.origin+c.pathname,{body:w.toString(),method:"POST",mode:"cors",credentials:"omit",headers:{"Content-Type":"text/plain"}}))}catch(e){throw await t.unshiftRequest(o),e}}},i=e=>{const t=({url:e})=>"www.google-analytics.com"===e.hostname&&r.test(e.pathname),o=new w.NetworkOnly({plugins:[e]});return[new n.Route(t,o,"GET"),new n.Route(t,o,"POST")]},l=e=>{const t=new c.NetworkFirst({cacheName:e});return new n.Route(({url:e})=>"www.google-analytics.com"===e.hostname&&"/analytics.js"===e.pathname,t,"GET")},m=e=>{const t=new c.NetworkFirst({cacheName:e});return new n.Route(({url:e})=>"www.googletagmanager.com"===e.hostname&&"/gtag/js"===e.pathname,t,"GET")},u=e=>{const t=new c.NetworkFirst({cacheName:e});return new n.Route(({url:e})=>"www.googletagmanager.com"===e.hostname&&"/gtm.js"===e.pathname,t,"GET")};return e.initialize=((e={})=>{const n=o.cacheNames.getGoogleAnalyticsName(e.cacheName),c=new t.Plugin("workbox-google-analytics",{maxRetentionTime:2880,onSync:s(e)}),w=[u(n),l(n),m(n),...i(c)],r=new a.Router;for(const e of w)r.registerRoute(e);r.addFetchListener()}),e}({},workbox.backgroundSync,workbox.core._private,workbox.routing,workbox.routing,workbox.strategies,workbox.strategies);
//# sourceMappingURL=workbox-offline-ga.prod.js.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,989 @@
this.workbox = this.workbox || {};
this.workbox.precaching = (function (exports, assert_mjs, cacheNames_mjs, getFriendlyURL_mjs, logger_mjs, cacheWrapper_mjs, fetchWrapper_mjs, WorkboxError_mjs) {
'use strict';
try {
self['workbox:precaching:4.3.1'] && _();
} catch (e) {} // eslint-disable-line
/*
Copyright 2019 Google LLC
Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.
*/
const plugins = [];
const precachePlugins = {
/*
* @return {Array}
* @private
*/
get() {
return plugins;
},
/*
* @param {Array} newPlugins
* @private
*/
add(newPlugins) {
plugins.push(...newPlugins);
}
};
/*
Copyright 2019 Google LLC
Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.
*/
/**
* Adds plugins to precaching.
*
* @param {Array<Object>} newPlugins
*
* @alias workbox.precaching.addPlugins
*/
const addPlugins = newPlugins => {
precachePlugins.add(newPlugins);
};
/*
Copyright 2018 Google LLC
Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.
*/
/**
* @param {Response} response
* @return {Response}
*
* @private
* @memberof module:workbox-precaching
*/
async function cleanRedirect(response) {
const clonedResponse = response.clone(); // Not all browsers support the Response.body stream, so fall back
// to reading the entire body into memory as a blob.
const bodyPromise = 'body' in clonedResponse ? Promise.resolve(clonedResponse.body) : clonedResponse.blob();
const body = await bodyPromise; // new Response() is happy when passed either a stream or a Blob.
return new Response(body, {
headers: clonedResponse.headers,
status: clonedResponse.status,
statusText: clonedResponse.statusText
});
}
/*
Copyright 2018 Google LLC
Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.
*/
const REVISION_SEARCH_PARAM = '__WB_REVISION__';
/**
* Converts a manifest entry into a versioned URL suitable for precaching.
*
* @param {Object} entry
* @return {string} A URL with versioning info.
*
* @private
* @memberof module:workbox-precaching
*/
function createCacheKey(entry) {
if (!entry) {
throw new WorkboxError_mjs.WorkboxError('add-to-cache-list-unexpected-type', {
entry
});
} // If a precache manifest entry is a string, it's assumed to be a versioned
// URL, like '/app.abcd1234.js'. Return as-is.
if (typeof entry === 'string') {
const urlObject = new URL(entry, location);
return {
cacheKey: urlObject.href,
url: urlObject.href
};
}
const {
revision,
url
} = entry;
if (!url) {
throw new WorkboxError_mjs.WorkboxError('add-to-cache-list-unexpected-type', {
entry
});
} // If there's just a URL and no revision, then it's also assumed to be a
// versioned URL.
if (!revision) {
const urlObject = new URL(url, location);
return {
cacheKey: urlObject.href,
url: urlObject.href
};
} // Otherwise, construct a properly versioned URL using the custom Workbox
// search parameter along with the revision info.
const originalURL = new URL(url, location);
const cacheKeyURL = new URL(url, location);
cacheKeyURL.searchParams.set(REVISION_SEARCH_PARAM, revision);
return {
cacheKey: cacheKeyURL.href,
url: originalURL.href
};
}
/*
Copyright 2018 Google LLC
Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.
*/
const logGroup = (groupTitle, deletedURLs) => {
logger_mjs.logger.groupCollapsed(groupTitle);
for (const url of deletedURLs) {
logger_mjs.logger.log(url);
}
logger_mjs.logger.groupEnd();
};
/**
* @param {Array<string>} deletedURLs
*
* @private
* @memberof module:workbox-precaching
*/
function printCleanupDetails(deletedURLs) {
const deletionCount = deletedURLs.length;
if (deletionCount > 0) {
logger_mjs.logger.groupCollapsed(`During precaching cleanup, ` + `${deletionCount} cached ` + `request${deletionCount === 1 ? ' was' : 's were'} deleted.`);
logGroup('Deleted Cache Requests', deletedURLs);
logger_mjs.logger.groupEnd();
}
}
/*
Copyright 2018 Google LLC
Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.
*/
/**
* @param {string} groupTitle
* @param {Array<string>} urls
*
* @private
*/
function _nestedGroup(groupTitle, urls) {
if (urls.length === 0) {
return;
}
logger_mjs.logger.groupCollapsed(groupTitle);
for (const url of urls) {
logger_mjs.logger.log(url);
}
logger_mjs.logger.groupEnd();
}
/**
* @param {Array<string>} urlsToPrecache
* @param {Array<string>} urlsAlreadyPrecached
*
* @private
* @memberof module:workbox-precaching
*/
function printInstallDetails(urlsToPrecache, urlsAlreadyPrecached) {
const precachedCount = urlsToPrecache.length;
const alreadyPrecachedCount = urlsAlreadyPrecached.length;
if (precachedCount || alreadyPrecachedCount) {
let message = `Precaching ${precachedCount} file${precachedCount === 1 ? '' : 's'}.`;
if (alreadyPrecachedCount > 0) {
message += ` ${alreadyPrecachedCount} ` + `file${alreadyPrecachedCount === 1 ? ' is' : 's are'} already cached.`;
}
logger_mjs.logger.groupCollapsed(message);
_nestedGroup(`View newly precached URLs.`, urlsToPrecache);
_nestedGroup(`View previously precached URLs.`, urlsAlreadyPrecached);
logger_mjs.logger.groupEnd();
}
}
/*
Copyright 2018 Google LLC
Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.
*/
/**
* Performs efficient precaching of assets.
*
* @memberof module:workbox-precaching
*/
class PrecacheController {
/**
* Create a new PrecacheController.
*
* @param {string} [cacheName] An optional name for the cache, to override
* the default precache name.
*/
constructor(cacheName) {
this._cacheName = cacheNames_mjs.cacheNames.getPrecacheName(cacheName);
this._urlsToCacheKeys = new Map();
}
/**
* This method will add items to the precache list, removing duplicates
* and ensuring the information is valid.
*
* @param {
* Array<module:workbox-precaching.PrecacheController.PrecacheEntry|string>
* } entries Array of entries to precache.
*/
addToCacheList(entries) {
{
assert_mjs.assert.isArray(entries, {
moduleName: 'workbox-precaching',
className: 'PrecacheController',
funcName: 'addToCacheList',
paramName: 'entries'
});
}
for (const entry of entries) {
const {
cacheKey,
url
} = createCacheKey(entry);
if (this._urlsToCacheKeys.has(url) && this._urlsToCacheKeys.get(url) !== cacheKey) {
throw new WorkboxError_mjs.WorkboxError('add-to-cache-list-conflicting-entries', {
firstEntry: this._urlsToCacheKeys.get(url),
secondEntry: cacheKey
});
}
this._urlsToCacheKeys.set(url, cacheKey);
}
}
/**
* Precaches new and updated assets. Call this method from the service worker
* install event.
*
* @param {Object} options
* @param {Event} [options.event] The install event (if needed).
* @param {Array<Object>} [options.plugins] Plugins to be used for fetching
* and caching during install.
* @return {Promise<workbox.precaching.InstallResult>}
*/
async install({
event,
plugins
} = {}) {
{
if (plugins) {
assert_mjs.assert.isArray(plugins, {
moduleName: 'workbox-precaching',
className: 'PrecacheController',
funcName: 'install',
paramName: 'plugins'
});
}
}
const urlsToPrecache = [];
const urlsAlreadyPrecached = [];
const cache = await caches.open(this._cacheName);
const alreadyCachedRequests = await cache.keys();
const alreadyCachedURLs = new Set(alreadyCachedRequests.map(request => request.url));
for (const cacheKey of this._urlsToCacheKeys.values()) {
if (alreadyCachedURLs.has(cacheKey)) {
urlsAlreadyPrecached.push(cacheKey);
} else {
urlsToPrecache.push(cacheKey);
}
}
const precacheRequests = urlsToPrecache.map(url => {
return this._addURLToCache({
event,
plugins,
url
});
});
await Promise.all(precacheRequests);
{
printInstallDetails(urlsToPrecache, urlsAlreadyPrecached);
}
return {
updatedURLs: urlsToPrecache,
notUpdatedURLs: urlsAlreadyPrecached
};
}
/**
* Deletes assets that are no longer present in the current precache manifest.
* Call this method from the service worker activate event.
*
* @return {Promise<workbox.precaching.CleanupResult>}
*/
async activate() {
const cache = await caches.open(this._cacheName);
const currentlyCachedRequests = await cache.keys();
const expectedCacheKeys = new Set(this._urlsToCacheKeys.values());
const deletedURLs = [];
for (const request of currentlyCachedRequests) {
if (!expectedCacheKeys.has(request.url)) {
await cache.delete(request);
deletedURLs.push(request.url);
}
}
{
printCleanupDetails(deletedURLs);
}
return {
deletedURLs
};
}
/**
* Requests the entry and saves it to the cache if the response is valid.
* By default, any response with a status code of less than 400 (including
* opaque responses) is considered valid.
*
* If you need to use custom criteria to determine what's valid and what
* isn't, then pass in an item in `options.plugins` that implements the
* `cacheWillUpdate()` lifecycle event.
*
* @private
* @param {Object} options
* @param {string} options.url The URL to fetch and cache.
* @param {Event} [options.event] The install event (if passed).
* @param {Array<Object>} [options.plugins] An array of plugins to apply to
* fetch and caching.
*/
async _addURLToCache({
url,
event,
plugins
}) {
const request = new Request(url, {
credentials: 'same-origin'
});
let response = await fetchWrapper_mjs.fetchWrapper.fetch({
event,
plugins,
request
}); // Allow developers to override the default logic about what is and isn't
// valid by passing in a plugin implementing cacheWillUpdate(), e.g.
// a workbox.cacheableResponse.Plugin instance.
let cacheWillUpdateCallback;
for (const plugin of plugins || []) {
if ('cacheWillUpdate' in plugin) {
cacheWillUpdateCallback = plugin.cacheWillUpdate.bind(plugin);
}
}
const isValidResponse = cacheWillUpdateCallback ? // Use a callback if provided. It returns a truthy value if valid.
cacheWillUpdateCallback({
event,
request,
response
}) : // Otherwise, default to considering any response status under 400 valid.
// This includes, by default, considering opaque responses valid.
response.status < 400; // Consider this a failure, leading to the `install` handler failing, if
// we get back an invalid response.
if (!isValidResponse) {
throw new WorkboxError_mjs.WorkboxError('bad-precaching-response', {
url,
status: response.status
});
}
if (response.redirected) {
response = await cleanRedirect(response);
}
await cacheWrapper_mjs.cacheWrapper.put({
event,
plugins,
request,
response,
cacheName: this._cacheName,
matchOptions: {
ignoreSearch: true
}
});
}
/**
* Returns a mapping of a precached URL to the corresponding cache key, taking
* into account the revision information for the URL.
*
* @return {Map<string, string>} A URL to cache key mapping.
*/
getURLsToCacheKeys() {
return this._urlsToCacheKeys;
}
/**
* Returns a list of all the URLs that have been precached by the current
* service worker.
*
* @return {Array<string>} The precached URLs.
*/
getCachedURLs() {
return [...this._urlsToCacheKeys.keys()];
}
/**
* Returns the cache key used for storing a given URL. If that URL is
* unversioned, like `/index.html', then the cache key will be the original
* URL with a search parameter appended to it.
*
* @param {string} url A URL whose cache key you want to look up.
* @return {string} The versioned URL that corresponds to a cache key
* for the original URL, or undefined if that URL isn't precached.
*/
getCacheKeyForURL(url) {
const urlObject = new URL(url, location);
return this._urlsToCacheKeys.get(urlObject.href);
}
}
/*
Copyright 2019 Google LLC
Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.
*/
let precacheController;
/**
* @return {PrecacheController}
* @private
*/
const getOrCreatePrecacheController = () => {
if (!precacheController) {
precacheController = new PrecacheController();
}
return precacheController;
};
/*
Copyright 2018 Google LLC
Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.
*/
/**
* Removes any URL search parameters that should be ignored.
*
* @param {URL} urlObject The original URL.
* @param {Array<RegExp>} ignoreURLParametersMatching RegExps to test against
* each search parameter name. Matches mean that the search parameter should be
* ignored.
* @return {URL} The URL with any ignored search parameters removed.
*
* @private
* @memberof module:workbox-precaching
*/
function removeIgnoredSearchParams(urlObject, ignoreURLParametersMatching) {
// Convert the iterable into an array at the start of the loop to make sure
// deletion doesn't mess up iteration.
for (const paramName of [...urlObject.searchParams.keys()]) {
if (ignoreURLParametersMatching.some(regExp => regExp.test(paramName))) {
urlObject.searchParams.delete(paramName);
}
}
return urlObject;
}
/*
Copyright 2019 Google LLC
Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.
*/
/**
* Generator function that yields possible variations on the original URL to
* check, one at a time.
*
* @param {string} url
* @param {Object} options
*
* @private
* @memberof module:workbox-precaching
*/
function* generateURLVariations(url, {
ignoreURLParametersMatching,
directoryIndex,
cleanURLs,
urlManipulation
} = {}) {
const urlObject = new URL(url, location);
urlObject.hash = '';
yield urlObject.href;
const urlWithoutIgnoredParams = removeIgnoredSearchParams(urlObject, ignoreURLParametersMatching);
yield urlWithoutIgnoredParams.href;
if (directoryIndex && urlWithoutIgnoredParams.pathname.endsWith('/')) {
const directoryURL = new URL(urlWithoutIgnoredParams);
directoryURL.pathname += directoryIndex;
yield directoryURL.href;
}
if (cleanURLs) {
const cleanURL = new URL(urlWithoutIgnoredParams);
cleanURL.pathname += '.html';
yield cleanURL.href;
}
if (urlManipulation) {
const additionalURLs = urlManipulation({
url: urlObject
});
for (const urlToAttempt of additionalURLs) {
yield urlToAttempt.href;
}
}
}
/*
Copyright 2019 Google LLC
Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.
*/
/**
* This function will take the request URL and manipulate it based on the
* configuration options.
*
* @param {string} url
* @param {Object} options
* @return {string} Returns the URL in the cache that matches the request,
* if possible.
*
* @private
*/
const getCacheKeyForURL = (url, options) => {
const precacheController = getOrCreatePrecacheController();
const urlsToCacheKeys = precacheController.getURLsToCacheKeys();
for (const possibleURL of generateURLVariations(url, options)) {
const possibleCacheKey = urlsToCacheKeys.get(possibleURL);
if (possibleCacheKey) {
return possibleCacheKey;
}
}
};
/*
Copyright 2019 Google LLC
Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.
*/
/**
* Adds a `fetch` listener to the service worker that will
* respond to
* [network requests]{@link https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API/Using_Service_Workers#Custom_responses_to_requests}
* with precached assets.
*
* Requests for assets that aren't precached, the `FetchEvent` will not be
* responded to, allowing the event to fall through to other `fetch` event
* listeners.
*
* NOTE: when called more than once this method will replace the previously set
* configuration options. Calling it more than once is not recommended outside
* of tests.
*
* @private
* @param {Object} options
* @param {string} [options.directoryIndex=index.html] The `directoryIndex` will
* check cache entries for a URLs ending with '/' to see if there is a hit when
* appending the `directoryIndex` value.
* @param {Array<RegExp>} [options.ignoreURLParametersMatching=[/^utm_/]] An
* array of regex's to remove search params when looking for a cache match.
* @param {boolean} [options.cleanURLs=true] The `cleanURLs` option will
* check the cache for the URL with a `.html` added to the end of the end.
* @param {workbox.precaching~urlManipulation} [options.urlManipulation]
* This is a function that should take a URL and return an array of
* alternative URL's that should be checked for precache matches.
*/
const addFetchListener = ({
ignoreURLParametersMatching = [/^utm_/],
directoryIndex = 'index.html',
cleanURLs = true,
urlManipulation = null
} = {}) => {
const cacheName = cacheNames_mjs.cacheNames.getPrecacheName();
addEventListener('fetch', event => {
const precachedURL = getCacheKeyForURL(event.request.url, {
cleanURLs,
directoryIndex,
ignoreURLParametersMatching,
urlManipulation
});
if (!precachedURL) {
{
logger_mjs.logger.debug(`Precaching did not find a match for ` + getFriendlyURL_mjs.getFriendlyURL(event.request.url));
}
return;
}
let responsePromise = caches.open(cacheName).then(cache => {
return cache.match(precachedURL);
}).then(cachedResponse => {
if (cachedResponse) {
return cachedResponse;
} // Fall back to the network if we don't have a cached response
// (perhaps due to manual cache cleanup).
{
logger_mjs.logger.warn(`The precached response for ` + `${getFriendlyURL_mjs.getFriendlyURL(precachedURL)} in ${cacheName} was not found. ` + `Falling back to the network instead.`);
}
return fetch(precachedURL);
});
{
responsePromise = responsePromise.then(response => {
// Workbox is going to handle the route.
// print the routing details to the console.
logger_mjs.logger.groupCollapsed(`Precaching is responding to: ` + getFriendlyURL_mjs.getFriendlyURL(event.request.url));
logger_mjs.logger.log(`Serving the precached url: ${precachedURL}`);
logger_mjs.logger.groupCollapsed(`View request details here.`);
logger_mjs.logger.log(event.request);
logger_mjs.logger.groupEnd();
logger_mjs.logger.groupCollapsed(`View response details here.`);
logger_mjs.logger.log(response);
logger_mjs.logger.groupEnd();
logger_mjs.logger.groupEnd();
return response;
});
}
event.respondWith(responsePromise);
});
};
/*
Copyright 2019 Google LLC
Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.
*/
let listenerAdded = false;
/**
* Add a `fetch` listener to the service worker that will
* respond to
* [network requests]{@link https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API/Using_Service_Workers#Custom_responses_to_requests}
* with precached assets.
*
* Requests for assets that aren't precached, the `FetchEvent` will not be
* responded to, allowing the event to fall through to other `fetch` event
* listeners.
*
* @param {Object} options
* @param {string} [options.directoryIndex=index.html] The `directoryIndex` will
* check cache entries for a URLs ending with '/' to see if there is a hit when
* appending the `directoryIndex` value.
* @param {Array<RegExp>} [options.ignoreURLParametersMatching=[/^utm_/]] An
* array of regex's to remove search params when looking for a cache match.
* @param {boolean} [options.cleanURLs=true] The `cleanURLs` option will
* check the cache for the URL with a `.html` added to the end of the end.
* @param {workbox.precaching~urlManipulation} [options.urlManipulation]
* This is a function that should take a URL and return an array of
* alternative URL's that should be checked for precache matches.
*
* @alias workbox.precaching.addRoute
*/
const addRoute = options => {
if (!listenerAdded) {
addFetchListener(options);
listenerAdded = true;
}
};
/*
Copyright 2018 Google LLC
Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.
*/
const SUBSTRING_TO_FIND = '-precache-';
/**
* Cleans up incompatible precaches that were created by older versions of
* Workbox, by a service worker registered under the current scope.
*
* This is meant to be called as part of the `activate` event.
*
* This should be safe to use as long as you don't include `substringToFind`
* (defaulting to `-precache-`) in your non-precache cache names.
*
* @param {string} currentPrecacheName The cache name currently in use for
* precaching. This cache won't be deleted.
* @param {string} [substringToFind='-precache-'] Cache names which include this
* substring will be deleted (excluding `currentPrecacheName`).
* @return {Array<string>} A list of all the cache names that were deleted.
*
* @private
* @memberof module:workbox-precaching
*/
const deleteOutdatedCaches = async (currentPrecacheName, substringToFind = SUBSTRING_TO_FIND) => {
const cacheNames = await caches.keys();
const cacheNamesToDelete = cacheNames.filter(cacheName => {
return cacheName.includes(substringToFind) && cacheName.includes(self.registration.scope) && cacheName !== currentPrecacheName;
});
await Promise.all(cacheNamesToDelete.map(cacheName => caches.delete(cacheName)));
return cacheNamesToDelete;
};
/*
Copyright 2019 Google LLC
Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.
*/
/**
* Adds an `activate` event listener which will clean up incompatible
* precaches that were created by older versions of Workbox.
*
* @alias workbox.precaching.cleanupOutdatedCaches
*/
const cleanupOutdatedCaches = () => {
addEventListener('activate', event => {
const cacheName = cacheNames_mjs.cacheNames.getPrecacheName();
event.waitUntil(deleteOutdatedCaches(cacheName).then(cachesDeleted => {
{
if (cachesDeleted.length > 0) {
logger_mjs.logger.log(`The following out-of-date precaches were cleaned up ` + `automatically:`, cachesDeleted);
}
}
}));
});
};
/*
Copyright 2019 Google LLC
Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.
*/
/**
* Takes in a URL, and returns the corresponding URL that could be used to
* lookup the entry in the precache.
*
* If a relative URL is provided, the location of the service worker file will
* be used as the base.
*
* For precached entries without revision information, the cache key will be the
* same as the original URL.
*
* For precached entries with revision information, the cache key will be the
* original URL with the addition of a query parameter used for keeping track of
* the revision info.
*
* @param {string} url The URL whose cache key to look up.
* @return {string} The cache key that corresponds to that URL.
*
* @alias workbox.precaching.getCacheKeyForURL
*/
const getCacheKeyForURL$1 = url => {
const precacheController = getOrCreatePrecacheController();
return precacheController.getCacheKeyForURL(url);
};
/*
Copyright 2019 Google LLC
Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.
*/
const installListener = event => {
const precacheController = getOrCreatePrecacheController();
const plugins = precachePlugins.get();
event.waitUntil(precacheController.install({
event,
plugins
}).catch(error => {
{
logger_mjs.logger.error(`Service worker installation failed. It will ` + `be retried automatically during the next navigation.`);
} // Re-throw the error to ensure installation fails.
throw error;
}));
};
const activateListener = event => {
const precacheController = getOrCreatePrecacheController();
const plugins = precachePlugins.get();
event.waitUntil(precacheController.activate({
event,
plugins
}));
};
/**
* Adds items to the precache list, removing any duplicates and
* stores the files in the
* ["precache cache"]{@link module:workbox-core.cacheNames} when the service
* worker installs.
*
* This method can be called multiple times.
*
* Please note: This method **will not** serve any of the cached files for you.
* It only precaches files. To respond to a network request you call
* [addRoute()]{@link module:workbox-precaching.addRoute}.
*
* If you have a single array of files to precache, you can just call
* [precacheAndRoute()]{@link module:workbox-precaching.precacheAndRoute}.
*
* @param {Array<Object|string>} entries Array of entries to precache.
*
* @alias workbox.precaching.precache
*/
const precache = entries => {
const precacheController = getOrCreatePrecacheController();
precacheController.addToCacheList(entries);
if (entries.length > 0) {
// NOTE: these listeners will only be added once (even if the `precache()`
// method is called multiple times) because event listeners are implemented
// as a set, where each listener must be unique.
addEventListener('install', installListener);
addEventListener('activate', activateListener);
}
};
/*
Copyright 2019 Google LLC
Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.
*/
/**
* This method will add entries to the precache list and add a route to
* respond to fetch events.
*
* This is a convenience method that will call
* [precache()]{@link module:workbox-precaching.precache} and
* [addRoute()]{@link module:workbox-precaching.addRoute} in a single call.
*
* @param {Array<Object|string>} entries Array of entries to precache.
* @param {Object} options See
* [addRoute() options]{@link module:workbox-precaching.addRoute}.
*
* @alias workbox.precaching.precacheAndRoute
*/
const precacheAndRoute = (entries, options) => {
precache(entries);
addRoute(options);
};
/*
Copyright 2018 Google LLC
Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.
*/
{
assert_mjs.assert.isSWEnv('workbox-precaching');
}
exports.addPlugins = addPlugins;
exports.addRoute = addRoute;
exports.cleanupOutdatedCaches = cleanupOutdatedCaches;
exports.getCacheKeyForURL = getCacheKeyForURL$1;
exports.precache = precache;
exports.precacheAndRoute = precacheAndRoute;
exports.PrecacheController = PrecacheController;
return exports;
}({}, workbox.core._private, workbox.core._private, workbox.core._private, workbox.core._private, workbox.core._private, workbox.core._private, workbox.core._private));
//# sourceMappingURL=workbox-precaching.dev.js.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,2 @@
this.workbox=this.workbox||{},this.workbox.precaching=function(t,e,n,s,c){"use strict";try{self["workbox:precaching:4.3.1"]&&_()}catch(t){}const o=[],i={get:()=>o,add(t){o.push(...t)}};const a="__WB_REVISION__";function r(t){if(!t)throw new c.WorkboxError("add-to-cache-list-unexpected-type",{entry:t});if("string"==typeof t){const e=new URL(t,location);return{cacheKey:e.href,url:e.href}}const{revision:e,url:n}=t;if(!n)throw new c.WorkboxError("add-to-cache-list-unexpected-type",{entry:t});if(!e){const t=new URL(n,location);return{cacheKey:t.href,url:t.href}}const s=new URL(n,location),o=new URL(n,location);return o.searchParams.set(a,e),{cacheKey:o.href,url:s.href}}class l{constructor(t){this.t=e.cacheNames.getPrecacheName(t),this.s=new Map}addToCacheList(t){for(const e of t){const{cacheKey:t,url:n}=r(e);if(this.s.has(n)&&this.s.get(n)!==t)throw new c.WorkboxError("add-to-cache-list-conflicting-entries",{firstEntry:this.s.get(n),secondEntry:t});this.s.set(n,t)}}async install({event:t,plugins:e}={}){const n=[],s=[],c=await caches.open(this.t),o=await c.keys(),i=new Set(o.map(t=>t.url));for(const t of this.s.values())i.has(t)?s.push(t):n.push(t);const a=n.map(n=>this.o({event:t,plugins:e,url:n}));return await Promise.all(a),{updatedURLs:n,notUpdatedURLs:s}}async activate(){const t=await caches.open(this.t),e=await t.keys(),n=new Set(this.s.values()),s=[];for(const c of e)n.has(c.url)||(await t.delete(c),s.push(c.url));return{deletedURLs:s}}async o({url:t,event:e,plugins:o}){const i=new Request(t,{credentials:"same-origin"});let a,r=await s.fetchWrapper.fetch({event:e,plugins:o,request:i});for(const t of o||[])"cacheWillUpdate"in t&&(a=t.cacheWillUpdate.bind(t));if(!(a?a({event:e,request:i,response:r}):r.status<400))throw new c.WorkboxError("bad-precaching-response",{url:t,status:r.status});r.redirected&&(r=await async function(t){const e=t.clone(),n="body"in e?Promise.resolve(e.body):e.blob(),s=await n;return new Response(s,{headers:e.headers,status:e.status,statusText:e.statusText})}(r)),await n.cacheWrapper.put({event:e,plugins:o,request:i,response:r,cacheName:this.t,matchOptions:{ignoreSearch:!0}})}getURLsToCacheKeys(){return this.s}getCachedURLs(){return[...this.s.keys()]}getCacheKeyForURL(t){const e=new URL(t,location);return this.s.get(e.href)}}let u;const h=()=>(u||(u=new l),u);const d=(t,e)=>{const n=h().getURLsToCacheKeys();for(const s of function*(t,{ignoreURLParametersMatching:e,directoryIndex:n,cleanURLs:s,urlManipulation:c}={}){const o=new URL(t,location);o.hash="",yield o.href;const i=function(t,e){for(const n of[...t.searchParams.keys()])e.some(t=>t.test(n))&&t.searchParams.delete(n);return t}(o,e);if(yield i.href,n&&i.pathname.endsWith("/")){const t=new URL(i);t.pathname+=n,yield t.href}if(s){const t=new URL(i);t.pathname+=".html",yield t.href}if(c){const t=c({url:o});for(const e of t)yield e.href}}(t,e)){const t=n.get(s);if(t)return t}};let w=!1;const f=t=>{w||((({ignoreURLParametersMatching:t=[/^utm_/],directoryIndex:n="index.html",cleanURLs:s=!0,urlManipulation:c=null}={})=>{const o=e.cacheNames.getPrecacheName();addEventListener("fetch",e=>{const i=d(e.request.url,{cleanURLs:s,directoryIndex:n,ignoreURLParametersMatching:t,urlManipulation:c});if(!i)return;let a=caches.open(o).then(t=>t.match(i)).then(t=>t||fetch(i));e.respondWith(a)})})(t),w=!0)},y=t=>{const e=h(),n=i.get();t.waitUntil(e.install({event:t,plugins:n}).catch(t=>{throw t}))},p=t=>{const e=h(),n=i.get();t.waitUntil(e.activate({event:t,plugins:n}))},L=t=>{h().addToCacheList(t),t.length>0&&(addEventListener("install",y),addEventListener("activate",p))};return t.addPlugins=(t=>{i.add(t)}),t.addRoute=f,t.cleanupOutdatedCaches=(()=>{addEventListener("activate",t=>{const n=e.cacheNames.getPrecacheName();t.waitUntil((async(t,e="-precache-")=>{const n=(await caches.keys()).filter(n=>n.includes(e)&&n.includes(self.registration.scope)&&n!==t);return await Promise.all(n.map(t=>caches.delete(t))),n})(n).then(t=>{}))})}),t.getCacheKeyForURL=(t=>{return h().getCacheKeyForURL(t)}),t.precache=L,t.precacheAndRoute=((t,e)=>{L(t),f(e)}),t.PrecacheController=l,t}({},workbox.core._private,workbox.core._private,workbox.core._private,workbox.core._private);
//# sourceMappingURL=workbox-precaching.prod.js.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,268 @@
this.workbox = this.workbox || {};
this.workbox.rangeRequests = (function (exports, WorkboxError_mjs, assert_mjs, logger_mjs) {
'use strict';
try {
self['workbox:range-requests:4.3.1'] && _();
} catch (e) {} // eslint-disable-line
/*
Copyright 2018 Google LLC
Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.
*/
/**
* @param {Blob} blob A source blob.
* @param {number|null} start The offset to use as the start of the
* slice.
* @param {number|null} end The offset to use as the end of the slice.
* @return {Object} An object with `start` and `end` properties, reflecting
* the effective boundaries to use given the size of the blob.
*
* @private
*/
function calculateEffectiveBoundaries(blob, start, end) {
{
assert_mjs.assert.isInstance(blob, Blob, {
moduleName: 'workbox-range-requests',
funcName: 'calculateEffectiveBoundaries',
paramName: 'blob'
});
}
const blobSize = blob.size;
if (end > blobSize || start < 0) {
throw new WorkboxError_mjs.WorkboxError('range-not-satisfiable', {
size: blobSize,
end,
start
});
}
let effectiveStart;
let effectiveEnd;
if (start === null) {
effectiveStart = blobSize - end;
effectiveEnd = blobSize;
} else if (end === null) {
effectiveStart = start;
effectiveEnd = blobSize;
} else {
effectiveStart = start; // Range values are inclusive, so add 1 to the value.
effectiveEnd = end + 1;
}
return {
start: effectiveStart,
end: effectiveEnd
};
}
/*
Copyright 2018 Google LLC
Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.
*/
/**
* @param {string} rangeHeader A Range: header value.
* @return {Object} An object with `start` and `end` properties, reflecting
* the parsed value of the Range: header. If either the `start` or `end` are
* omitted, then `null` will be returned.
*
* @private
*/
function parseRangeHeader(rangeHeader) {
{
assert_mjs.assert.isType(rangeHeader, 'string', {
moduleName: 'workbox-range-requests',
funcName: 'parseRangeHeader',
paramName: 'rangeHeader'
});
}
const normalizedRangeHeader = rangeHeader.trim().toLowerCase();
if (!normalizedRangeHeader.startsWith('bytes=')) {
throw new WorkboxError_mjs.WorkboxError('unit-must-be-bytes', {
normalizedRangeHeader
});
} // Specifying multiple ranges separate by commas is valid syntax, but this
// library only attempts to handle a single, contiguous sequence of bytes.
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Range#Syntax
if (normalizedRangeHeader.includes(',')) {
throw new WorkboxError_mjs.WorkboxError('single-range-only', {
normalizedRangeHeader
});
}
const rangeParts = /(\d*)-(\d*)/.exec(normalizedRangeHeader); // We need either at least one of the start or end values.
if (rangeParts === null || !(rangeParts[1] || rangeParts[2])) {
throw new WorkboxError_mjs.WorkboxError('invalid-range-values', {
normalizedRangeHeader
});
}
return {
start: rangeParts[1] === '' ? null : Number(rangeParts[1]),
end: rangeParts[2] === '' ? null : Number(rangeParts[2])
};
}
/*
Copyright 2018 Google LLC
Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.
*/
/**
* Given a `Request` and `Response` objects as input, this will return a
* promise for a new `Response`.
*
* If the original `Response` already contains partial content (i.e. it has
* a status of 206), then this assumes it already fulfills the `Range:`
* requirements, and will return it as-is.
*
* @param {Request} request A request, which should contain a Range:
* header.
* @param {Response} originalResponse A response.
* @return {Promise<Response>} Either a `206 Partial Content` response, with
* the response body set to the slice of content specified by the request's
* `Range:` header, or a `416 Range Not Satisfiable` response if the
* conditions of the `Range:` header can't be met.
*
* @memberof workbox.rangeRequests
*/
async function createPartialResponse(request, originalResponse) {
try {
{
assert_mjs.assert.isInstance(request, Request, {
moduleName: 'workbox-range-requests',
funcName: 'createPartialResponse',
paramName: 'request'
});
assert_mjs.assert.isInstance(originalResponse, Response, {
moduleName: 'workbox-range-requests',
funcName: 'createPartialResponse',
paramName: 'originalResponse'
});
}
if (originalResponse.status === 206) {
// If we already have a 206, then just pass it through as-is;
// see https://github.com/GoogleChrome/workbox/issues/1720
return originalResponse;
}
const rangeHeader = request.headers.get('range');
if (!rangeHeader) {
throw new WorkboxError_mjs.WorkboxError('no-range-header');
}
const boundaries = parseRangeHeader(rangeHeader);
const originalBlob = await originalResponse.blob();
const effectiveBoundaries = calculateEffectiveBoundaries(originalBlob, boundaries.start, boundaries.end);
const slicedBlob = originalBlob.slice(effectiveBoundaries.start, effectiveBoundaries.end);
const slicedBlobSize = slicedBlob.size;
const slicedResponse = new Response(slicedBlob, {
// Status code 206 is for a Partial Content response.
// See https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/206
status: 206,
statusText: 'Partial Content',
headers: originalResponse.headers
});
slicedResponse.headers.set('Content-Length', slicedBlobSize);
slicedResponse.headers.set('Content-Range', `bytes ${effectiveBoundaries.start}-${effectiveBoundaries.end - 1}/` + originalBlob.size);
return slicedResponse;
} catch (error) {
{
logger_mjs.logger.warn(`Unable to construct a partial response; returning a ` + `416 Range Not Satisfiable response instead.`);
logger_mjs.logger.groupCollapsed(`View details here.`);
logger_mjs.logger.log(error);
logger_mjs.logger.log(request);
logger_mjs.logger.log(originalResponse);
logger_mjs.logger.groupEnd();
}
return new Response('', {
status: 416,
statusText: 'Range Not Satisfiable'
});
}
}
/*
Copyright 2018 Google LLC
Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.
*/
/**
* The range request plugin makes it easy for a request with a 'Range' header to
* be fulfilled by a cached response.
*
* It does this by intercepting the `cachedResponseWillBeUsed` plugin callback
* and returning the appropriate subset of the cached response body.
*
* @memberof workbox.rangeRequests
*/
class Plugin {
/**
* @param {Object} options
* @param {Request} options.request The original request, which may or may not
* contain a Range: header.
* @param {Response} options.cachedResponse The complete cached response.
* @return {Promise<Response>} If request contains a 'Range' header, then a
* new response with status 206 whose body is a subset of `cachedResponse` is
* returned. Otherwise, `cachedResponse` is returned as-is.
*
* @private
*/
async cachedResponseWillBeUsed({
request,
cachedResponse
}) {
// Only return a sliced response if there's something valid in the cache,
// and there's a Range: header in the request.
if (cachedResponse && request.headers.has('range')) {
return await createPartialResponse(request, cachedResponse);
} // If there was no Range: header, or if cachedResponse wasn't valid, just
// pass it through as-is.
return cachedResponse;
}
}
/*
Copyright 2018 Google LLC
Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.
*/
exports.createPartialResponse = createPartialResponse;
exports.Plugin = Plugin;
return exports;
}({}, workbox.core._private, workbox.core._private, workbox.core._private));
//# sourceMappingURL=workbox-range-requests.dev.js.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,2 @@
this.workbox=this.workbox||{},this.workbox.rangeRequests=function(e,n){"use strict";try{self["workbox:range-requests:4.3.1"]&&_()}catch(e){}async function t(e,t){try{if(206===t.status)return t;const s=e.headers.get("range");if(!s)throw new n.WorkboxError("no-range-header");const a=function(e){const t=e.trim().toLowerCase();if(!t.startsWith("bytes="))throw new n.WorkboxError("unit-must-be-bytes",{normalizedRangeHeader:t});if(t.includes(","))throw new n.WorkboxError("single-range-only",{normalizedRangeHeader:t});const s=/(\d*)-(\d*)/.exec(t);if(null===s||!s[1]&&!s[2])throw new n.WorkboxError("invalid-range-values",{normalizedRangeHeader:t});return{start:""===s[1]?null:Number(s[1]),end:""===s[2]?null:Number(s[2])}}(s),r=await t.blob(),i=function(e,t,s){const a=e.size;if(s>a||t<0)throw new n.WorkboxError("range-not-satisfiable",{size:a,end:s,start:t});let r,i;return null===t?(r=a-s,i=a):null===s?(r=t,i=a):(r=t,i=s+1),{start:r,end:i}}(r,a.start,a.end),o=r.slice(i.start,i.end),u=o.size,l=new Response(o,{status:206,statusText:"Partial Content",headers:t.headers});return l.headers.set("Content-Length",u),l.headers.set("Content-Range",`bytes ${i.start}-${i.end-1}/`+r.size),l}catch(e){return new Response("",{status:416,statusText:"Range Not Satisfiable"})}}return e.createPartialResponse=t,e.Plugin=class{async cachedResponseWillBeUsed({request:e,cachedResponse:n}){return n&&e.headers.has("range")?await t(e,n):n}},e}({},workbox.core._private);
//# sourceMappingURL=workbox-range-requests.prod.js.map

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,2 @@
this.workbox=this.workbox||{},this.workbox.routing=function(t,e,r){"use strict";try{self["workbox:routing:4.3.1"]&&_()}catch(t){}const s="GET",n=t=>t&&"object"==typeof t?t:{handle:t};class o{constructor(t,e,r){this.handler=n(e),this.match=t,this.method=r||s}}class i extends o{constructor(t,{whitelist:e=[/./],blacklist:r=[]}={}){super(t=>this.t(t),t),this.s=e,this.o=r}t({url:t,request:e}){if("navigate"!==e.mode)return!1;const r=t.pathname+t.search;for(const t of this.o)if(t.test(r))return!1;return!!this.s.some(t=>t.test(r))}}class u extends o{constructor(t,e,r){super(({url:e})=>{const r=t.exec(e.href);return r?e.origin!==location.origin&&0!==r.index?null:r.slice(1):null},e,r)}}class c{constructor(){this.i=new Map}get routes(){return this.i}addFetchListener(){self.addEventListener("fetch",t=>{const{request:e}=t,r=this.handleRequest({request:e,event:t});r&&t.respondWith(r)})}addCacheListener(){self.addEventListener("message",async t=>{if(t.data&&"CACHE_URLS"===t.data.type){const{payload:e}=t.data,r=Promise.all(e.urlsToCache.map(t=>{"string"==typeof t&&(t=[t]);const e=new Request(...t);return this.handleRequest({request:e})}));t.waitUntil(r),t.ports&&t.ports[0]&&(await r,t.ports[0].postMessage(!0))}})}handleRequest({request:t,event:e}){const r=new URL(t.url,location);if(!r.protocol.startsWith("http"))return;let s,{params:n,route:o}=this.findMatchingRoute({url:r,request:t,event:e}),i=o&&o.handler;if(!i&&this.u&&(i=this.u),i){try{s=i.handle({url:r,request:t,event:e,params:n})}catch(t){s=Promise.reject(t)}return s&&this.h&&(s=s.catch(t=>this.h.handle({url:r,event:e,err:t}))),s}}findMatchingRoute({url:t,request:e,event:r}){const s=this.i.get(e.method)||[];for(const n of s){let s,o=n.match({url:t,request:e,event:r});if(o)return Array.isArray(o)&&o.length>0?s=o:o.constructor===Object&&Object.keys(o).length>0&&(s=o),{route:n,params:s}}return{}}setDefaultHandler(t){this.u=n(t)}setCatchHandler(t){this.h=n(t)}registerRoute(t){this.i.has(t.method)||this.i.set(t.method,[]),this.i.get(t.method).push(t)}unregisterRoute(t){if(!this.i.has(t.method))throw new r.WorkboxError("unregister-route-but-not-found-with-method",{method:t.method});const e=this.i.get(t.method).indexOf(t);if(!(e>-1))throw new r.WorkboxError("unregister-route-route-not-registered");this.i.get(t.method).splice(e,1)}}let a;const h=()=>(a||((a=new c).addFetchListener(),a.addCacheListener()),a);return t.NavigationRoute=i,t.RegExpRoute=u,t.registerNavigationRoute=((t,r={})=>{const s=e.cacheNames.getPrecacheName(r.cacheName),n=new i(async()=>{try{const e=await caches.match(t,{cacheName:s});if(e)return e;throw new Error(`The cache ${s} did not have an entry for `+`${t}.`)}catch(e){return fetch(t)}},{whitelist:r.whitelist,blacklist:r.blacklist});return h().registerRoute(n),n}),t.registerRoute=((t,e,s="GET")=>{let n;if("string"==typeof t){const r=new URL(t,location);n=new o(({url:t})=>t.href===r.href,e,s)}else if(t instanceof RegExp)n=new u(t,e,s);else if("function"==typeof t)n=new o(t,e,s);else{if(!(t instanceof o))throw new r.WorkboxError("unsupported-route-type",{moduleName:"workbox-routing",funcName:"registerRoute",paramName:"capture"});n=t}return h().registerRoute(n),n}),t.Route=o,t.Router=c,t.setCatchHandler=(t=>{h().setCatchHandler(t)}),t.setDefaultHandler=(t=>{h().setDefaultHandler(t)}),t}({},workbox.core._private,workbox.core._private);
//# sourceMappingURL=workbox-routing.prod.js.map

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,2 @@
this.workbox=this.workbox||{},this.workbox.strategies=function(e,t,s,n,r){"use strict";try{self["workbox:strategies:4.3.1"]&&_()}catch(e){}class i{constructor(e={}){this.t=t.cacheNames.getRuntimeName(e.cacheName),this.s=e.plugins||[],this.i=e.fetchOptions||null,this.h=e.matchOptions||null}async handle({event:e,request:t}){return this.makeRequest({event:e,request:t||e.request})}async makeRequest({event:e,request:t}){"string"==typeof t&&(t=new Request(t));let n,i=await s.cacheWrapper.match({cacheName:this.t,request:t,event:e,matchOptions:this.h,plugins:this.s});if(!i)try{i=await this.u(t,e)}catch(e){n=e}if(!i)throw new r.WorkboxError("no-response",{url:t.url,error:n});return i}async u(e,t){const r=await n.fetchWrapper.fetch({request:e,event:t,fetchOptions:this.i,plugins:this.s}),i=r.clone(),h=s.cacheWrapper.put({cacheName:this.t,request:e,response:i,event:t,plugins:this.s});if(t)try{t.waitUntil(h)}catch(e){}return r}}class h{constructor(e={}){this.t=t.cacheNames.getRuntimeName(e.cacheName),this.s=e.plugins||[],this.h=e.matchOptions||null}async handle({event:e,request:t}){return this.makeRequest({event:e,request:t||e.request})}async makeRequest({event:e,request:t}){"string"==typeof t&&(t=new Request(t));const n=await s.cacheWrapper.match({cacheName:this.t,request:t,event:e,matchOptions:this.h,plugins:this.s});if(!n)throw new r.WorkboxError("no-response",{url:t.url});return n}}const u={cacheWillUpdate:({response:e})=>200===e.status||0===e.status?e:null};class a{constructor(e={}){if(this.t=t.cacheNames.getRuntimeName(e.cacheName),e.plugins){let t=e.plugins.some(e=>!!e.cacheWillUpdate);this.s=t?e.plugins:[u,...e.plugins]}else this.s=[u];this.o=e.networkTimeoutSeconds,this.i=e.fetchOptions||null,this.h=e.matchOptions||null}async handle({event:e,request:t}){return this.makeRequest({event:e,request:t||e.request})}async makeRequest({event:e,request:t}){const s=[];"string"==typeof t&&(t=new Request(t));const n=[];let i;if(this.o){const{id:r,promise:h}=this.l({request:t,event:e,logs:s});i=r,n.push(h)}const h=this.q({timeoutId:i,request:t,event:e,logs:s});n.push(h);let u=await Promise.race(n);if(u||(u=await h),!u)throw new r.WorkboxError("no-response",{url:t.url});return u}l({request:e,logs:t,event:s}){let n;return{promise:new Promise(t=>{n=setTimeout(async()=>{t(await this.p({request:e,event:s}))},1e3*this.o)}),id:n}}async q({timeoutId:e,request:t,logs:r,event:i}){let h,u;try{u=await n.fetchWrapper.fetch({request:t,event:i,fetchOptions:this.i,plugins:this.s})}catch(e){h=e}if(e&&clearTimeout(e),h||!u)u=await this.p({request:t,event:i});else{const e=u.clone(),n=s.cacheWrapper.put({cacheName:this.t,request:t,response:e,event:i,plugins:this.s});if(i)try{i.waitUntil(n)}catch(e){}}return u}p({event:e,request:t}){return s.cacheWrapper.match({cacheName:this.t,request:t,event:e,matchOptions:this.h,plugins:this.s})}}class c{constructor(e={}){this.t=t.cacheNames.getRuntimeName(e.cacheName),this.s=e.plugins||[],this.i=e.fetchOptions||null}async handle({event:e,request:t}){return this.makeRequest({event:e,request:t||e.request})}async makeRequest({event:e,request:t}){let s,i;"string"==typeof t&&(t=new Request(t));try{i=await n.fetchWrapper.fetch({request:t,event:e,fetchOptions:this.i,plugins:this.s})}catch(e){s=e}if(!i)throw new r.WorkboxError("no-response",{url:t.url,error:s});return i}}class o{constructor(e={}){if(this.t=t.cacheNames.getRuntimeName(e.cacheName),this.s=e.plugins||[],e.plugins){let t=e.plugins.some(e=>!!e.cacheWillUpdate);this.s=t?e.plugins:[u,...e.plugins]}else this.s=[u];this.i=e.fetchOptions||null,this.h=e.matchOptions||null}async handle({event:e,request:t}){return this.makeRequest({event:e,request:t||e.request})}async makeRequest({event:e,request:t}){"string"==typeof t&&(t=new Request(t));const n=this.u({request:t,event:e});let i,h=await s.cacheWrapper.match({cacheName:this.t,request:t,event:e,matchOptions:this.h,plugins:this.s});if(h){if(e)try{e.waitUntil(n)}catch(i){}}else try{h=await n}catch(e){i=e}if(!h)throw new r.WorkboxError("no-response",{url:t.url,error:i});return h}async u({request:e,event:t}){const r=await n.fetchWrapper.fetch({request:e,event:t,fetchOptions:this.i,plugins:this.s}),i=s.cacheWrapper.put({cacheName:this.t,request:e,response:r.clone(),event:t,plugins:this.s});if(t)try{t.waitUntil(i)}catch(e){}return r}}const l={cacheFirst:i,cacheOnly:h,networkFirst:a,networkOnly:c,staleWhileRevalidate:o},q=e=>{const t=l[e];return e=>new t(e)},w=q("cacheFirst"),p=q("cacheOnly"),v=q("networkFirst"),y=q("networkOnly"),m=q("staleWhileRevalidate");return e.CacheFirst=i,e.CacheOnly=h,e.NetworkFirst=a,e.NetworkOnly=c,e.StaleWhileRevalidate=o,e.cacheFirst=w,e.cacheOnly=p,e.networkFirst=v,e.networkOnly=y,e.staleWhileRevalidate=m,e}({},workbox.core._private,workbox.core._private,workbox.core._private,workbox.core._private);
//# sourceMappingURL=workbox-strategies.prod.js.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,337 @@
this.workbox = this.workbox || {};
this.workbox.streams = (function (exports, logger_mjs, assert_mjs) {
'use strict';
try {
self['workbox:streams:4.3.1'] && _();
} catch (e) {} // eslint-disable-line
/*
Copyright 2018 Google LLC
Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.
*/
/**
* Takes either a Response, a ReadableStream, or a
* [BodyInit](https://fetch.spec.whatwg.org/#bodyinit) and returns the
* ReadableStreamReader object associated with it.
*
* @param {workbox.streams.StreamSource} source
* @return {ReadableStreamReader}
* @private
*/
function _getReaderFromSource(source) {
if (source.body && source.body.getReader) {
return source.body.getReader();
}
if (source.getReader) {
return source.getReader();
} // TODO: This should be possible to do by constructing a ReadableStream, but
// I can't get it to work. As a hack, construct a new Response, and use the
// reader associated with its body.
return new Response(source).body.getReader();
}
/**
* Takes multiple source Promises, each of which could resolve to a Response, a
* ReadableStream, or a [BodyInit](https://fetch.spec.whatwg.org/#bodyinit).
*
* Returns an object exposing a ReadableStream with each individual stream's
* data returned in sequence, along with a Promise which signals when the
* stream is finished (useful for passing to a FetchEvent's waitUntil()).
*
* @param {Array<Promise<workbox.streams.StreamSource>>} sourcePromises
* @return {Object<{done: Promise, stream: ReadableStream}>}
*
* @memberof workbox.streams
*/
function concatenate(sourcePromises) {
{
assert_mjs.assert.isArray(sourcePromises, {
moduleName: 'workbox-streams',
funcName: 'concatenate',
paramName: 'sourcePromises'
});
}
const readerPromises = sourcePromises.map(sourcePromise => {
return Promise.resolve(sourcePromise).then(source => {
return _getReaderFromSource(source);
});
});
let fullyStreamedResolve;
let fullyStreamedReject;
const done = new Promise((resolve, reject) => {
fullyStreamedResolve = resolve;
fullyStreamedReject = reject;
});
let i = 0;
const logMessages = [];
const stream = new ReadableStream({
pull(controller) {
return readerPromises[i].then(reader => reader.read()).then(result => {
if (result.done) {
{
logMessages.push(['Reached the end of source:', sourcePromises[i]]);
}
i++;
if (i >= readerPromises.length) {
// Log all the messages in the group at once in a single group.
{
logger_mjs.logger.groupCollapsed(`Concatenating ${readerPromises.length} sources.`);
for (const message of logMessages) {
if (Array.isArray(message)) {
logger_mjs.logger.log(...message);
} else {
logger_mjs.logger.log(message);
}
}
logger_mjs.logger.log('Finished reading all sources.');
logger_mjs.logger.groupEnd();
}
controller.close();
fullyStreamedResolve();
return;
}
return this.pull(controller);
} else {
controller.enqueue(result.value);
}
}).catch(error => {
{
logger_mjs.logger.error('An error occurred:', error);
}
fullyStreamedReject(error);
throw error;
});
},
cancel() {
{
logger_mjs.logger.warn('The ReadableStream was cancelled.');
}
fullyStreamedResolve();
}
});
return {
done,
stream
};
}
/*
Copyright 2018 Google LLC
Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.
*/
/**
* This is a utility method that determines whether the current browser supports
* the features required to create streamed responses. Currently, it checks if
* [`ReadableStream`](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream/ReadableStream)
* is available.
*
* @param {HeadersInit} [headersInit] If there's no `Content-Type` specified,
* `'text/html'` will be used by default.
* @return {boolean} `true`, if the current browser meets the requirements for
* streaming responses, and `false` otherwise.
*
* @memberof workbox.streams
*/
function createHeaders(headersInit = {}) {
// See https://github.com/GoogleChrome/workbox/issues/1461
const headers = new Headers(headersInit);
if (!headers.has('content-type')) {
headers.set('content-type', 'text/html');
}
return headers;
}
/*
Copyright 2018 Google LLC
Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.
*/
/**
* Takes multiple source Promises, each of which could resolve to a Response, a
* ReadableStream, or a [BodyInit](https://fetch.spec.whatwg.org/#bodyinit),
* along with a
* [HeadersInit](https://fetch.spec.whatwg.org/#typedefdef-headersinit).
*
* Returns an object exposing a Response whose body consists of each individual
* stream's data returned in sequence, along with a Promise which signals when
* the stream is finished (useful for passing to a FetchEvent's waitUntil()).
*
* @param {Array<Promise<workbox.streams.StreamSource>>} sourcePromises
* @param {HeadersInit} [headersInit] If there's no `Content-Type` specified,
* `'text/html'` will be used by default.
* @return {Object<{done: Promise, response: Response}>}
*
* @memberof workbox.streams
*/
function concatenateToResponse(sourcePromises, headersInit) {
const {
done,
stream
} = concatenate(sourcePromises);
const headers = createHeaders(headersInit);
const response = new Response(stream, {
headers
});
return {
done,
response
};
}
/*
Copyright 2018 Google LLC
Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.
*/
let cachedIsSupported = undefined;
/**
* This is a utility method that determines whether the current browser supports
* the features required to create streamed responses. Currently, it checks if
* [`ReadableStream`](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream/ReadableStream)
* can be created.
*
* @return {boolean} `true`, if the current browser meets the requirements for
* streaming responses, and `false` otherwise.
*
* @memberof workbox.streams
*/
function isSupported() {
if (cachedIsSupported === undefined) {
// See https://github.com/GoogleChrome/workbox/issues/1473
try {
new ReadableStream({
start() {}
});
cachedIsSupported = true;
} catch (error) {
cachedIsSupported = false;
}
}
return cachedIsSupported;
}
/*
Copyright 2018 Google LLC
Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.
*/
/**
* A shortcut to create a strategy that could be dropped-in to Workbox's router.
*
* On browsers that do not support constructing new `ReadableStream`s, this
* strategy will automatically wait for all the `sourceFunctions` to complete,
* and create a final response that concatenates their values together.
*
* @param {
* Array<function(workbox.routing.Route~handlerCallback)>} sourceFunctions
* Each function should return a {@link workbox.streams.StreamSource} (or a
* Promise which resolves to one).
* @param {HeadersInit} [headersInit] If there's no `Content-Type` specified,
* `'text/html'` will be used by default.
* @return {workbox.routing.Route~handlerCallback}
*
* @memberof workbox.streams
*/
function strategy(sourceFunctions, headersInit) {
return async ({
event,
url,
params
}) => {
if (isSupported()) {
const {
done,
response
} = concatenateToResponse(sourceFunctions.map(fn => fn({
event,
url,
params
})), headersInit);
event.waitUntil(done);
return response;
}
{
logger_mjs.logger.log(`The current browser doesn't support creating response ` + `streams. Falling back to non-streaming response instead.`);
} // Fallback to waiting for everything to finish, and concatenating the
// responses.
const parts = await Promise.all(sourceFunctions.map(sourceFunction => sourceFunction({
event,
url,
params
})).map(async responsePromise => {
const response = await responsePromise;
if (response instanceof Response) {
return response.blob();
} // Otherwise, assume it's something like a string which can be used
// as-is when constructing the final composite blob.
return response;
}));
const headers = createHeaders(headersInit); // Constructing a new Response from a Blob source is well-supported.
// So is constructing a new Blob from multiple source Blobs or strings.
return new Response(new Blob(parts), {
headers
});
};
}
/*
Copyright 2018 Google LLC
Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.
*/
exports.concatenate = concatenate;
exports.concatenateToResponse = concatenateToResponse;
exports.isSupported = isSupported;
exports.strategy = strategy;
return exports;
}({}, workbox.core._private, workbox.core._private));
//# sourceMappingURL=workbox-streams.dev.js.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,2 @@
this.workbox=this.workbox||{},this.workbox.streams=function(e){"use strict";try{self["workbox:streams:4.3.1"]&&_()}catch(e){}function n(e){const n=e.map(e=>Promise.resolve(e).then(e=>(function(e){return e.body&&e.body.getReader?e.body.getReader():e.getReader?e.getReader():new Response(e).body.getReader()})(e)));let t,r;const s=new Promise((e,n)=>{t=e,r=n});let o=0;return{done:s,stream:new ReadableStream({pull(e){return n[o].then(e=>e.read()).then(r=>{if(r.done)return++o>=n.length?(e.close(),void t()):this.pull(e);e.enqueue(r.value)}).catch(e=>{throw r(e),e})},cancel(){t()}})}}function t(e={}){const n=new Headers(e);return n.has("content-type")||n.set("content-type","text/html"),n}function r(e,r){const{done:s,stream:o}=n(e),a=t(r);return{done:s,response:new Response(o,{headers:a})}}let s=void 0;function o(){if(void 0===s)try{new ReadableStream({start(){}}),s=!0}catch(e){s=!1}return s}return e.concatenate=n,e.concatenateToResponse=r,e.isSupported=o,e.strategy=function(e,n){return async({event:s,url:a,params:c})=>{if(o()){const{done:t,response:o}=r(e.map(e=>e({event:s,url:a,params:c})),n);return s.waitUntil(t),o}const i=await Promise.all(e.map(e=>e({event:s,url:a,params:c})).map(async e=>{const n=await e;return n instanceof Response?n.blob():n})),u=t(n);return new Response(new Blob(i),{headers:u})}},e}({});
//# sourceMappingURL=workbox-streams.prod.js.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,2 @@
!function(){"use strict";try{self["workbox:sw:4.3.1"]&&_()}catch(t){}const t="https://storage.googleapis.com/workbox-cdn/releases/4.3.1",e={backgroundSync:"background-sync",broadcastUpdate:"broadcast-update",cacheableResponse:"cacheable-response",core:"core",expiration:"expiration",googleAnalytics:"offline-ga",navigationPreload:"navigation-preload",precaching:"precaching",rangeRequests:"range-requests",routing:"routing",strategies:"strategies",streams:"streams"};self.workbox=new class{constructor(){return this.v={},this.t={debug:"localhost"===self.location.hostname,modulePathPrefix:null,modulePathCb:null},this.s=this.t.debug?"dev":"prod",this.o=!1,new Proxy(this,{get(t,s){if(t[s])return t[s];const o=e[s];return o&&t.loadModule(`workbox-${o}`),t[s]}})}setConfig(t={}){if(this.o)throw new Error("Config must be set before accessing workbox.* modules");Object.assign(this.t,t),this.s=this.t.debug?"dev":"prod"}loadModule(t){const e=this.i(t);try{importScripts(e),this.o=!0}catch(s){throw console.error(`Unable to import module '${t}' from '${e}'.`),s}}i(e){if(this.t.modulePathCb)return this.t.modulePathCb(e,this.t.debug);let s=[t];const o=`${e}.${this.s}.js`,r=this.t.modulePathPrefix;return r&&""===(s=r.split("/"))[s.length-1]&&s.splice(s.length-1,1),s.push(o),s.join("/")}}}();
//# sourceMappingURL=workbox-sw.js.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,885 @@
try {
self['workbox:window:4.3.1'] && _();
} catch (e) {} // eslint-disable-line
/*
Copyright 2019 Google LLC
Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.
*/
/**
* Sends a data object to a service worker via `postMessage` and resolves with
* a response (if any).
*
* A response can be set in a message handler in the service worker by
* calling `event.ports[0].postMessage(...)`, which will resolve the promise
* returned by `messageSW()`. If no response is set, the promise will not
* resolve.
*
* @param {ServiceWorker} sw The service worker to send the message to.
* @param {Object} data An object to send to the service worker.
* @return {Promise<Object|undefined>}
*
* @memberof module:workbox-window
*/
var messageSW = function messageSW(sw, data) {
return new Promise(function (resolve) {
var messageChannel = new MessageChannel();
messageChannel.port1.onmessage = function (evt) {
return resolve(evt.data);
};
sw.postMessage(data, [messageChannel.port2]);
});
};
function _defineProperties(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
descriptor.enumerable = descriptor.enumerable || false;
descriptor.configurable = true;
if ("value" in descriptor) descriptor.writable = true;
Object.defineProperty(target, descriptor.key, descriptor);
}
}
function _createClass(Constructor, protoProps, staticProps) {
if (protoProps) _defineProperties(Constructor.prototype, protoProps);
if (staticProps) _defineProperties(Constructor, staticProps);
return Constructor;
}
function _inheritsLoose(subClass, superClass) {
subClass.prototype = Object.create(superClass.prototype);
subClass.prototype.constructor = subClass;
subClass.__proto__ = superClass;
}
function _assertThisInitialized(self) {
if (self === void 0) {
throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
}
return self;
}
try {
self['workbox:core:4.3.1'] && _();
} catch (e) {} // eslint-disable-line
/*
Copyright 2018 Google LLC
Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.
*/
/**
* The Deferred class composes Promises in a way that allows for them to be
* resolved or rejected from outside the constructor. In most cases promises
* should be used directly, but Deferreds can be necessary when the logic to
* resolve a promise must be separate.
*
* @private
*/
var Deferred =
/**
* Creates a promise and exposes its resolve and reject functions as methods.
*/
function Deferred() {
var _this = this;
this.promise = new Promise(function (resolve, reject) {
_this.resolve = resolve;
_this.reject = reject;
});
};
/*
Copyright 2019 Google LLC
Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.
*/
var logger = function () {
var inGroup = false;
var methodToColorMap = {
debug: "#7f8c8d",
// Gray
log: "#2ecc71",
// Green
warn: "#f39c12",
// Yellow
error: "#c0392b",
// Red
groupCollapsed: "#3498db",
// Blue
groupEnd: null // No colored prefix on groupEnd
};
var print = function print(method, args) {
var _console2;
if (method === 'groupCollapsed') {
// Safari doesn't print all console.groupCollapsed() arguments:
// https://bugs.webkit.org/show_bug.cgi?id=182754
if (/^((?!chrome|android).)*safari/i.test(navigator.userAgent)) {
var _console;
(_console = console)[method].apply(_console, args);
return;
}
}
var styles = ["background: " + methodToColorMap[method], "border-radius: 0.5em", "color: white", "font-weight: bold", "padding: 2px 0.5em"]; // When in a group, the workbox prefix is not displayed.
var logPrefix = inGroup ? [] : ['%cworkbox', styles.join(';')];
(_console2 = console)[method].apply(_console2, logPrefix.concat(args));
if (method === 'groupCollapsed') {
inGroup = true;
}
if (method === 'groupEnd') {
inGroup = false;
}
};
var api = {};
var _arr = Object.keys(methodToColorMap);
var _loop = function _loop() {
var method = _arr[_i];
api[method] = function () {
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
print(method, args);
};
};
for (var _i = 0; _i < _arr.length; _i++) {
_loop();
}
return api;
}();
/*
Copyright 2019 Google LLC
Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.
*/
/**
* A minimal `EventTarget` shim.
* This is necessary because not all browsers support constructable
* `EventTarget`, so using a real `EventTarget` will error.
* @private
*/
var EventTargetShim =
/*#__PURE__*/
function () {
/**
* Creates an event listener registry
*
* @private
*/
function EventTargetShim() {
// A registry of event types to listeners.
this._eventListenerRegistry = {};
}
/**
* @param {string} type
* @param {Function} listener
* @private
*/
var _proto = EventTargetShim.prototype;
_proto.addEventListener = function addEventListener(type, listener) {
this._getEventListenersByType(type).add(listener);
};
/**
* @param {string} type
* @param {Function} listener
* @private
*/
_proto.removeEventListener = function removeEventListener(type, listener) {
this._getEventListenersByType(type).delete(listener);
};
/**
* @param {Event} event
* @private
*/
_proto.dispatchEvent = function dispatchEvent(event) {
event.target = this;
this._getEventListenersByType(event.type).forEach(function (listener) {
return listener(event);
});
};
/**
* Returns a Set of listeners associated with the passed event type.
* If no handlers have been registered, an empty Set is returned.
*
* @param {string} type The event type.
* @return {Set} An array of handler functions.
* @private
*/
_proto._getEventListenersByType = function _getEventListenersByType(type) {
return this._eventListenerRegistry[type] = this._eventListenerRegistry[type] || new Set();
};
return EventTargetShim;
}();
/*
Copyright 2019 Google LLC
Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.
*/
/**
* Returns true if two URLs have the same `.href` property. The URLS can be
* relative, and if they are the current location href is used to resolve URLs.
*
* @private
* @param {string} url1
* @param {string} url2
* @return {boolean}
*/
var urlsMatch = function urlsMatch(url1, url2) {
return new URL(url1, location).href === new URL(url2, location).href;
};
/*
Copyright 2019 Google LLC
Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.
*/
/**
* A minimal `Event` subclass shim.
* This doesn't *actually* subclass `Event` because not all browsers support
* constructable `EventTarget`, and using a real `Event` will error.
* @private
*/
var WorkboxEvent =
/**
* @param {string} type
* @param {Object} props
*/
function WorkboxEvent(type, props) {
Object.assign(this, props, {
type: type
});
};
function _catch(body, recover) {
try {
var result = body();
} catch (e) {
return recover(e);
}
if (result && result.then) {
return result.then(void 0, recover);
}
return result;
}
function _async(f) {
return function () {
for (var args = [], i = 0; i < arguments.length; i++) {
args[i] = arguments[i];
}
try {
return Promise.resolve(f.apply(this, args));
} catch (e) {
return Promise.reject(e);
}
};
}
function _invoke(body, then) {
var result = body();
if (result && result.then) {
return result.then(then);
}
return then(result);
}
function _await(value, then, direct) {
if (direct) {
return then ? then(value) : value;
}
if (!value || !value.then) {
value = Promise.resolve(value);
}
return then ? value.then(then) : value;
}
function _awaitIgnored(value, direct) {
if (!direct) {
return value && value.then ? value.then(_empty) : Promise.resolve();
}
}
function _empty() {}
// `skipWaiting()` wasn't called. This 200 amount wasn't scientifically
// chosen, but it seems to avoid false positives in my testing.
var WAITING_TIMEOUT_DURATION = 200; // The amount of time after a registration that we can reasonably conclude
// that the registration didn't trigger an update.
var REGISTRATION_TIMEOUT_DURATION = 60000;
/**
* A class to aid in handling service worker registration, updates, and
* reacting to service worker lifecycle events.
*
* @fires [message]{@link module:workbox-window.Workbox#message}
* @fires [installed]{@link module:workbox-window.Workbox#installed}
* @fires [waiting]{@link module:workbox-window.Workbox#waiting}
* @fires [controlling]{@link module:workbox-window.Workbox#controlling}
* @fires [activated]{@link module:workbox-window.Workbox#activated}
* @fires [redundant]{@link module:workbox-window.Workbox#redundant}
* @fires [externalinstalled]{@link module:workbox-window.Workbox#externalinstalled}
* @fires [externalwaiting]{@link module:workbox-window.Workbox#externalwaiting}
* @fires [externalactivated]{@link module:workbox-window.Workbox#externalactivated}
*
* @memberof module:workbox-window
*/
var Workbox =
/*#__PURE__*/
function (_EventTargetShim) {
_inheritsLoose(Workbox, _EventTargetShim);
/**
* Creates a new Workbox instance with a script URL and service worker
* options. The script URL and options are the same as those used when
* calling `navigator.serviceWorker.register(scriptURL, options)`. See:
* https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerContainer/register
*
* @param {string} scriptURL The service worker script associated with this
* instance.
* @param {Object} [registerOptions] The service worker options associated
* with this instance.
*/
function Workbox(scriptURL, registerOptions) {
var _this;
if (registerOptions === void 0) {
registerOptions = {};
}
_this = _EventTargetShim.call(this) || this;
_this._scriptURL = scriptURL;
_this._registerOptions = registerOptions;
_this._updateFoundCount = 0; // Deferreds we can resolve later.
_this._swDeferred = new Deferred();
_this._activeDeferred = new Deferred();
_this._controllingDeferred = new Deferred(); // Bind event handler callbacks.
_this._onMessage = _this._onMessage.bind(_assertThisInitialized(_assertThisInitialized(_this)));
_this._onStateChange = _this._onStateChange.bind(_assertThisInitialized(_assertThisInitialized(_this)));
_this._onUpdateFound = _this._onUpdateFound.bind(_assertThisInitialized(_assertThisInitialized(_this)));
_this._onControllerChange = _this._onControllerChange.bind(_assertThisInitialized(_assertThisInitialized(_this)));
return _this;
}
/**
* Registers a service worker for this instances script URL and service
* worker options. By default this method delays registration until after
* the window has loaded.
*
* @param {Object} [options]
* @param {Function} [options.immediate=false] Setting this to true will
* register the service worker immediately, even if the window has
* not loaded (not recommended).
*/
var _proto = Workbox.prototype;
_proto.register = _async(function (_temp) {
var _this2 = this;
var _ref = _temp === void 0 ? {} : _temp,
_ref$immediate = _ref.immediate,
immediate = _ref$immediate === void 0 ? false : _ref$immediate;
{
if (_this2._registrationTime) {
logger.error('Cannot re-register a Workbox instance after it has ' + 'been registered. Create a new instance instead.');
return;
}
}
return _invoke(function () {
if (!immediate && document.readyState !== 'complete') {
return _awaitIgnored(new Promise(function (res) {
return addEventListener('load', res);
}));
}
}, function () {
// Set this flag to true if any service worker was controlling the page
// at registration time.
_this2._isUpdate = Boolean(navigator.serviceWorker.controller); // Before registering, attempt to determine if a SW is already controlling
// the page, and if that SW script (and version, if specified) matches this
// instance's script.
_this2._compatibleControllingSW = _this2._getControllingSWIfCompatible();
return _await(_this2._registerScript(), function (_this2$_registerScrip) {
_this2._registration = _this2$_registerScrip;
// If we have a compatible controller, store the controller as the "own"
// SW, resolve active/controlling deferreds and add necessary listeners.
if (_this2._compatibleControllingSW) {
_this2._sw = _this2._compatibleControllingSW;
_this2._activeDeferred.resolve(_this2._compatibleControllingSW);
_this2._controllingDeferred.resolve(_this2._compatibleControllingSW);
_this2._reportWindowReady(_this2._compatibleControllingSW);
_this2._compatibleControllingSW.addEventListener('statechange', _this2._onStateChange, {
once: true
});
} // If there's a waiting service worker with a matching URL before the
// `updatefound` event fires, it likely means that this site is open
// in another tab, or the user refreshed the page (and thus the prevoius
// page wasn't fully unloaded before this page started loading).
// https://developers.google.com/web/fundamentals/primers/service-workers/lifecycle#waiting
var waitingSW = _this2._registration.waiting;
if (waitingSW && urlsMatch(waitingSW.scriptURL, _this2._scriptURL)) {
// Store the waiting SW as the "own" Sw, even if it means overwriting
// a compatible controller.
_this2._sw = waitingSW; // Run this in the next microtask, so any code that adds an event
// listener after awaiting `register()` will get this event.
Promise.resolve().then(function () {
_this2.dispatchEvent(new WorkboxEvent('waiting', {
sw: waitingSW,
wasWaitingBeforeRegister: true
}));
{
logger.warn('A service worker was already waiting to activate ' + 'before this script was registered...');
}
});
} // If an "own" SW is already set, resolve the deferred.
if (_this2._sw) {
_this2._swDeferred.resolve(_this2._sw);
}
{
logger.log('Successfully registered service worker.', _this2._scriptURL);
if (navigator.serviceWorker.controller) {
if (_this2._compatibleControllingSW) {
logger.debug('A service worker with the same script URL ' + 'is already controlling this page.');
} else {
logger.debug('A service worker with a different script URL is ' + 'currently controlling the page. The browser is now fetching ' + 'the new script now...');
}
}
var currentPageIsOutOfScope = function currentPageIsOutOfScope() {
var scopeURL = new URL(_this2._registerOptions.scope || _this2._scriptURL, document.baseURI);
var scopeURLBasePath = new URL('./', scopeURL.href).pathname;
return !location.pathname.startsWith(scopeURLBasePath);
};
if (currentPageIsOutOfScope()) {
logger.warn('The current page is not in scope for the registered ' + 'service worker. Was this a mistake?');
}
}
_this2._registration.addEventListener('updatefound', _this2._onUpdateFound);
navigator.serviceWorker.addEventListener('controllerchange', _this2._onControllerChange, {
once: true
}); // Add message listeners.
if ('BroadcastChannel' in self) {
_this2._broadcastChannel = new BroadcastChannel('workbox');
_this2._broadcastChannel.addEventListener('message', _this2._onMessage);
}
navigator.serviceWorker.addEventListener('message', _this2._onMessage);
return _this2._registration;
});
});
});
/**
* Resolves to the service worker registered by this instance as soon as it
* is active. If a service worker was already controlling at registration
* time then it will resolve to that if the script URLs (and optionally
* script versions) match, otherwise it will wait until an update is found
* and activates.
*
* @return {Promise<ServiceWorker>}
*/
/**
* Resolves with a reference to a service worker that matches the script URL
* of this instance, as soon as it's available.
*
* If, at registration time, there's already an active or waiting service
* worker with a matching script URL, it will be used (with the waiting
* service worker taking precedence over the active service worker if both
* match, since the waiting service worker would have been registered more
* recently).
* If there's no matching active or waiting service worker at registration
* time then the promise will not resolve until an update is found and starts
* installing, at which point the installing service worker is used.
*
* @return {Promise<ServiceWorker>}
*/
_proto.getSW = _async(function () {
var _this3 = this;
// If `this._sw` is set, resolve with that as we want `getSW()` to
// return the correct (new) service worker if an update is found.
return _this3._sw || _this3._swDeferred.promise;
});
/**
* Sends the passed data object to the service worker registered by this
* instance (via [`getSW()`]{@link module:workbox-window.Workbox#getSW}) and resolves
* with a response (if any).
*
* A response can be set in a message handler in the service worker by
* calling `event.ports[0].postMessage(...)`, which will resolve the promise
* returned by `messageSW()`. If no response is set, the promise will never
* resolve.
*
* @param {Object} data An object to send to the service worker
* @return {Promise<Object>}
*/
_proto.messageSW = _async(function (data) {
var _this4 = this;
return _await(_this4.getSW(), function (sw) {
return messageSW(sw, data);
});
});
/**
* Checks for a service worker already controlling the page and returns
* it if its script URL matchs.
*
* @private
* @return {ServiceWorker|undefined}
*/
_proto._getControllingSWIfCompatible = function _getControllingSWIfCompatible() {
var controller = navigator.serviceWorker.controller;
if (controller && urlsMatch(controller.scriptURL, this._scriptURL)) {
return controller;
}
};
/**
* Registers a service worker for this instances script URL and register
* options and tracks the time registration was complete.
*
* @private
*/
_proto._registerScript = _async(function () {
var _this5 = this;
return _catch(function () {
return _await(navigator.serviceWorker.register(_this5._scriptURL, _this5._registerOptions), function (reg) {
// Keep track of when registration happened, so it can be used in the
// `this._onUpdateFound` heuristic. Also use the presence of this
// property as a way to see if `.register()` has been called.
_this5._registrationTime = performance.now();
return reg;
});
}, function (error) {
{
logger.error(error);
} // Re-throw the error.
throw error;
});
});
/**
* Sends a message to the passed service worker that the window is ready.
*
* @param {ServiceWorker} sw
* @private
*/
_proto._reportWindowReady = function _reportWindowReady(sw) {
messageSW(sw, {
type: 'WINDOW_READY',
meta: 'workbox-window'
});
};
/**
* @private
*/
_proto._onUpdateFound = function _onUpdateFound() {
var installingSW = this._registration.installing; // If the script URL passed to `navigator.serviceWorker.register()` is
// different from the current controlling SW's script URL, we know any
// successful registration calls will trigger an `updatefound` event.
// But if the registered script URL is the same as the current controlling
// SW's script URL, we'll only get an `updatefound` event if the file
// changed since it was last registered. This can be a problem if the user
// opens up the same page in a different tab, and that page registers
// a SW that triggers an update. It's a problem because this page has no
// good way of knowing whether the `updatefound` event came from the SW
// script it registered or from a registration attempt made by a newer
// version of the page running in another tab.
// To minimize the possibility of a false positive, we use the logic here:
var updateLikelyTriggeredExternally = // Since we enforce only calling `register()` once, and since we don't
// add the `updatefound` event listener until the `register()` call, if
// `_updateFoundCount` is > 0 then it means this method has already
// been called, thus this SW must be external
this._updateFoundCount > 0 || // If the script URL of the installing SW is different from this
// instance's script URL, we know it's definitely not from our
// registration.
!urlsMatch(installingSW.scriptURL, this._scriptURL) || // If all of the above are false, then we use a time-based heuristic:
// Any `updatefound` event that occurs long after our registration is
// assumed to be external.
performance.now() > this._registrationTime + REGISTRATION_TIMEOUT_DURATION ? // If any of the above are not true, we assume the update was
// triggered by this instance.
true : false;
if (updateLikelyTriggeredExternally) {
this._externalSW = installingSW;
this._registration.removeEventListener('updatefound', this._onUpdateFound);
} else {
// If the update was not triggered externally we know the installing
// SW is the one we registered, so we set it.
this._sw = installingSW;
this._swDeferred.resolve(installingSW); // The `installing` state isn't something we have a dedicated
// callback for, but we do log messages for it in development.
{
if (navigator.serviceWorker.controller) {
logger.log('Updated service worker found. Installing now...');
} else {
logger.log('Service worker is installing...');
}
}
} // Increment the `updatefound` count, so future invocations of this
// method can be sure they were triggered externally.
++this._updateFoundCount; // Add a `statechange` listener regardless of whether this update was
// triggered externally, since we have callbacks for both.
installingSW.addEventListener('statechange', this._onStateChange);
};
/**
* @private
* @param {Event} originalEvent
*/
_proto._onStateChange = function _onStateChange(originalEvent) {
var _this6 = this;
var sw = originalEvent.target;
var state = sw.state;
var isExternal = sw === this._externalSW;
var eventPrefix = isExternal ? 'external' : '';
var eventProps = {
sw: sw,
originalEvent: originalEvent
};
if (!isExternal && this._isUpdate) {
eventProps.isUpdate = true;
}
this.dispatchEvent(new WorkboxEvent(eventPrefix + state, eventProps));
if (state === 'installed') {
// This timeout is used to ignore cases where the service worker calls
// `skipWaiting()` in the install event, thus moving it directly in the
// activating state. (Since all service workers *must* go through the
// waiting phase, the only way to detect `skipWaiting()` called in the
// install event is to observe that the time spent in the waiting phase
// is very short.)
// NOTE: we don't need separate timeouts for the own and external SWs
// since they can't go through these phases at the same time.
this._waitingTimeout = setTimeout(function () {
// Ensure the SW is still waiting (it may now be redundant).
if (state === 'installed' && _this6._registration.waiting === sw) {
_this6.dispatchEvent(new WorkboxEvent(eventPrefix + 'waiting', eventProps));
{
if (isExternal) {
logger.warn('An external service worker has installed but is ' + 'waiting for this client to close before activating...');
} else {
logger.warn('The service worker has installed but is waiting ' + 'for existing clients to close before activating...');
}
}
}
}, WAITING_TIMEOUT_DURATION);
} else if (state === 'activating') {
clearTimeout(this._waitingTimeout);
if (!isExternal) {
this._activeDeferred.resolve(sw);
}
}
{
switch (state) {
case 'installed':
if (isExternal) {
logger.warn('An external service worker has installed. ' + 'You may want to suggest users reload this page.');
} else {
logger.log('Registered service worker installed.');
}
break;
case 'activated':
if (isExternal) {
logger.warn('An external service worker has activated.');
} else {
logger.log('Registered service worker activated.');
if (sw !== navigator.serviceWorker.controller) {
logger.warn('The registered service worker is active but ' + 'not yet controlling the page. Reload or run ' + '`clients.claim()` in the service worker.');
}
}
break;
case 'redundant':
if (sw === this._compatibleControllingSW) {
logger.log('Previously controlling service worker now redundant!');
} else if (!isExternal) {
logger.log('Registered service worker now redundant!');
}
break;
}
}
};
/**
* @private
* @param {Event} originalEvent
*/
_proto._onControllerChange = function _onControllerChange(originalEvent) {
var sw = this._sw;
if (sw === navigator.serviceWorker.controller) {
this.dispatchEvent(new WorkboxEvent('controlling', {
sw: sw,
originalEvent: originalEvent
}));
{
logger.log('Registered service worker now controlling this page.');
}
this._controllingDeferred.resolve(sw);
}
};
/**
* @private
* @param {Event} originalEvent
*/
_proto._onMessage = function _onMessage(originalEvent) {
var data = originalEvent.data;
this.dispatchEvent(new WorkboxEvent('message', {
data: data,
originalEvent: originalEvent
}));
};
_createClass(Workbox, [{
key: "active",
get: function get() {
return this._activeDeferred.promise;
}
/**
* Resolves to the service worker registered by this instance as soon as it
* is controlling the page. If a service worker was already controlling at
* registration time then it will resolve to that if the script URLs (and
* optionally script versions) match, otherwise it will wait until an update
* is found and starts controlling the page.
* Note: the first time a service worker is installed it will active but
* not start controlling the page unless `clients.claim()` is called in the
* service worker.
*
* @return {Promise<ServiceWorker>}
*/
}, {
key: "controlling",
get: function get() {
return this._controllingDeferred.promise;
}
}]);
return Workbox;
}(EventTargetShim); // The jsdoc comments below outline the events this instance may dispatch:
/*
Copyright 2019 Google LLC
Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.
*/
export { Workbox, messageSW };
//# sourceMappingURL=workbox-window.dev.es5.mjs.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,751 @@
try {
self['workbox:window:4.3.1'] && _();
} catch (e) {} // eslint-disable-line
/*
Copyright 2019 Google LLC
Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.
*/
/**
* Sends a data object to a service worker via `postMessage` and resolves with
* a response (if any).
*
* A response can be set in a message handler in the service worker by
* calling `event.ports[0].postMessage(...)`, which will resolve the promise
* returned by `messageSW()`. If no response is set, the promise will not
* resolve.
*
* @param {ServiceWorker} sw The service worker to send the message to.
* @param {Object} data An object to send to the service worker.
* @return {Promise<Object|undefined>}
*
* @memberof module:workbox-window
*/
const messageSW = (sw, data) => {
return new Promise(resolve => {
let messageChannel = new MessageChannel();
messageChannel.port1.onmessage = evt => resolve(evt.data);
sw.postMessage(data, [messageChannel.port2]);
});
};
try {
self['workbox:core:4.3.1'] && _();
} catch (e) {} // eslint-disable-line
/*
Copyright 2018 Google LLC
Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.
*/
/**
* The Deferred class composes Promises in a way that allows for them to be
* resolved or rejected from outside the constructor. In most cases promises
* should be used directly, but Deferreds can be necessary when the logic to
* resolve a promise must be separate.
*
* @private
*/
class Deferred {
/**
* Creates a promise and exposes its resolve and reject functions as methods.
*/
constructor() {
this.promise = new Promise((resolve, reject) => {
this.resolve = resolve;
this.reject = reject;
});
}
}
/*
Copyright 2019 Google LLC
Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.
*/
const logger = (() => {
let inGroup = false;
const methodToColorMap = {
debug: `#7f8c8d`,
// Gray
log: `#2ecc71`,
// Green
warn: `#f39c12`,
// Yellow
error: `#c0392b`,
// Red
groupCollapsed: `#3498db`,
// Blue
groupEnd: null // No colored prefix on groupEnd
};
const print = function (method, args) {
if (method === 'groupCollapsed') {
// Safari doesn't print all console.groupCollapsed() arguments:
// https://bugs.webkit.org/show_bug.cgi?id=182754
if (/^((?!chrome|android).)*safari/i.test(navigator.userAgent)) {
console[method](...args);
return;
}
}
const styles = [`background: ${methodToColorMap[method]}`, `border-radius: 0.5em`, `color: white`, `font-weight: bold`, `padding: 2px 0.5em`]; // When in a group, the workbox prefix is not displayed.
const logPrefix = inGroup ? [] : ['%cworkbox', styles.join(';')];
console[method](...logPrefix, ...args);
if (method === 'groupCollapsed') {
inGroup = true;
}
if (method === 'groupEnd') {
inGroup = false;
}
};
const api = {};
for (const method of Object.keys(methodToColorMap)) {
api[method] = (...args) => {
print(method, args);
};
}
return api;
})();
/*
Copyright 2019 Google LLC
Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.
*/
/**
* A minimal `EventTarget` shim.
* This is necessary because not all browsers support constructable
* `EventTarget`, so using a real `EventTarget` will error.
* @private
*/
class EventTargetShim {
/**
* Creates an event listener registry
*
* @private
*/
constructor() {
// A registry of event types to listeners.
this._eventListenerRegistry = {};
}
/**
* @param {string} type
* @param {Function} listener
* @private
*/
addEventListener(type, listener) {
this._getEventListenersByType(type).add(listener);
}
/**
* @param {string} type
* @param {Function} listener
* @private
*/
removeEventListener(type, listener) {
this._getEventListenersByType(type).delete(listener);
}
/**
* @param {Event} event
* @private
*/
dispatchEvent(event) {
event.target = this;
this._getEventListenersByType(event.type).forEach(listener => listener(event));
}
/**
* Returns a Set of listeners associated with the passed event type.
* If no handlers have been registered, an empty Set is returned.
*
* @param {string} type The event type.
* @return {Set} An array of handler functions.
* @private
*/
_getEventListenersByType(type) {
return this._eventListenerRegistry[type] = this._eventListenerRegistry[type] || new Set();
}
}
/*
Copyright 2019 Google LLC
Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.
*/
/**
* Returns true if two URLs have the same `.href` property. The URLS can be
* relative, and if they are the current location href is used to resolve URLs.
*
* @private
* @param {string} url1
* @param {string} url2
* @return {boolean}
*/
const urlsMatch = (url1, url2) => {
return new URL(url1, location).href === new URL(url2, location).href;
};
/*
Copyright 2019 Google LLC
Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.
*/
/**
* A minimal `Event` subclass shim.
* This doesn't *actually* subclass `Event` because not all browsers support
* constructable `EventTarget`, and using a real `Event` will error.
* @private
*/
class WorkboxEvent {
/**
* @param {string} type
* @param {Object} props
*/
constructor(type, props) {
Object.assign(this, props, {
type
});
}
}
/*
Copyright 2019 Google LLC
Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.
*/
// `skipWaiting()` wasn't called. This 200 amount wasn't scientifically
// chosen, but it seems to avoid false positives in my testing.
const WAITING_TIMEOUT_DURATION = 200; // The amount of time after a registration that we can reasonably conclude
// that the registration didn't trigger an update.
const REGISTRATION_TIMEOUT_DURATION = 60000;
/**
* A class to aid in handling service worker registration, updates, and
* reacting to service worker lifecycle events.
*
* @fires [message]{@link module:workbox-window.Workbox#message}
* @fires [installed]{@link module:workbox-window.Workbox#installed}
* @fires [waiting]{@link module:workbox-window.Workbox#waiting}
* @fires [controlling]{@link module:workbox-window.Workbox#controlling}
* @fires [activated]{@link module:workbox-window.Workbox#activated}
* @fires [redundant]{@link module:workbox-window.Workbox#redundant}
* @fires [externalinstalled]{@link module:workbox-window.Workbox#externalinstalled}
* @fires [externalwaiting]{@link module:workbox-window.Workbox#externalwaiting}
* @fires [externalactivated]{@link module:workbox-window.Workbox#externalactivated}
*
* @memberof module:workbox-window
*/
class Workbox extends EventTargetShim {
/**
* Creates a new Workbox instance with a script URL and service worker
* options. The script URL and options are the same as those used when
* calling `navigator.serviceWorker.register(scriptURL, options)`. See:
* https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerContainer/register
*
* @param {string} scriptURL The service worker script associated with this
* instance.
* @param {Object} [registerOptions] The service worker options associated
* with this instance.
*/
constructor(scriptURL, registerOptions = {}) {
super();
this._scriptURL = scriptURL;
this._registerOptions = registerOptions;
this._updateFoundCount = 0; // Deferreds we can resolve later.
this._swDeferred = new Deferred();
this._activeDeferred = new Deferred();
this._controllingDeferred = new Deferred(); // Bind event handler callbacks.
this._onMessage = this._onMessage.bind(this);
this._onStateChange = this._onStateChange.bind(this);
this._onUpdateFound = this._onUpdateFound.bind(this);
this._onControllerChange = this._onControllerChange.bind(this);
}
/**
* Registers a service worker for this instances script URL and service
* worker options. By default this method delays registration until after
* the window has loaded.
*
* @param {Object} [options]
* @param {Function} [options.immediate=false] Setting this to true will
* register the service worker immediately, even if the window has
* not loaded (not recommended).
*/
async register({
immediate = false
} = {}) {
{
if (this._registrationTime) {
logger.error('Cannot re-register a Workbox instance after it has ' + 'been registered. Create a new instance instead.');
return;
}
}
if (!immediate && document.readyState !== 'complete') {
await new Promise(res => addEventListener('load', res));
} // Set this flag to true if any service worker was controlling the page
// at registration time.
this._isUpdate = Boolean(navigator.serviceWorker.controller); // Before registering, attempt to determine if a SW is already controlling
// the page, and if that SW script (and version, if specified) matches this
// instance's script.
this._compatibleControllingSW = this._getControllingSWIfCompatible();
this._registration = await this._registerScript(); // If we have a compatible controller, store the controller as the "own"
// SW, resolve active/controlling deferreds and add necessary listeners.
if (this._compatibleControllingSW) {
this._sw = this._compatibleControllingSW;
this._activeDeferred.resolve(this._compatibleControllingSW);
this._controllingDeferred.resolve(this._compatibleControllingSW);
this._reportWindowReady(this._compatibleControllingSW);
this._compatibleControllingSW.addEventListener('statechange', this._onStateChange, {
once: true
});
} // If there's a waiting service worker with a matching URL before the
// `updatefound` event fires, it likely means that this site is open
// in another tab, or the user refreshed the page (and thus the prevoius
// page wasn't fully unloaded before this page started loading).
// https://developers.google.com/web/fundamentals/primers/service-workers/lifecycle#waiting
const waitingSW = this._registration.waiting;
if (waitingSW && urlsMatch(waitingSW.scriptURL, this._scriptURL)) {
// Store the waiting SW as the "own" Sw, even if it means overwriting
// a compatible controller.
this._sw = waitingSW; // Run this in the next microtask, so any code that adds an event
// listener after awaiting `register()` will get this event.
Promise.resolve().then(() => {
this.dispatchEvent(new WorkboxEvent('waiting', {
sw: waitingSW,
wasWaitingBeforeRegister: true
}));
{
logger.warn('A service worker was already waiting to activate ' + 'before this script was registered...');
}
});
} // If an "own" SW is already set, resolve the deferred.
if (this._sw) {
this._swDeferred.resolve(this._sw);
}
{
logger.log('Successfully registered service worker.', this._scriptURL);
if (navigator.serviceWorker.controller) {
if (this._compatibleControllingSW) {
logger.debug('A service worker with the same script URL ' + 'is already controlling this page.');
} else {
logger.debug('A service worker with a different script URL is ' + 'currently controlling the page. The browser is now fetching ' + 'the new script now...');
}
}
const currentPageIsOutOfScope = () => {
const scopeURL = new URL(this._registerOptions.scope || this._scriptURL, document.baseURI);
const scopeURLBasePath = new URL('./', scopeURL.href).pathname;
return !location.pathname.startsWith(scopeURLBasePath);
};
if (currentPageIsOutOfScope()) {
logger.warn('The current page is not in scope for the registered ' + 'service worker. Was this a mistake?');
}
}
this._registration.addEventListener('updatefound', this._onUpdateFound);
navigator.serviceWorker.addEventListener('controllerchange', this._onControllerChange, {
once: true
}); // Add message listeners.
if ('BroadcastChannel' in self) {
this._broadcastChannel = new BroadcastChannel('workbox');
this._broadcastChannel.addEventListener('message', this._onMessage);
}
navigator.serviceWorker.addEventListener('message', this._onMessage);
return this._registration;
}
/**
* Resolves to the service worker registered by this instance as soon as it
* is active. If a service worker was already controlling at registration
* time then it will resolve to that if the script URLs (and optionally
* script versions) match, otherwise it will wait until an update is found
* and activates.
*
* @return {Promise<ServiceWorker>}
*/
get active() {
return this._activeDeferred.promise;
}
/**
* Resolves to the service worker registered by this instance as soon as it
* is controlling the page. If a service worker was already controlling at
* registration time then it will resolve to that if the script URLs (and
* optionally script versions) match, otherwise it will wait until an update
* is found and starts controlling the page.
* Note: the first time a service worker is installed it will active but
* not start controlling the page unless `clients.claim()` is called in the
* service worker.
*
* @return {Promise<ServiceWorker>}
*/
get controlling() {
return this._controllingDeferred.promise;
}
/**
* Resolves with a reference to a service worker that matches the script URL
* of this instance, as soon as it's available.
*
* If, at registration time, there's already an active or waiting service
* worker with a matching script URL, it will be used (with the waiting
* service worker taking precedence over the active service worker if both
* match, since the waiting service worker would have been registered more
* recently).
* If there's no matching active or waiting service worker at registration
* time then the promise will not resolve until an update is found and starts
* installing, at which point the installing service worker is used.
*
* @return {Promise<ServiceWorker>}
*/
async getSW() {
// If `this._sw` is set, resolve with that as we want `getSW()` to
// return the correct (new) service worker if an update is found.
return this._sw || this._swDeferred.promise;
}
/**
* Sends the passed data object to the service worker registered by this
* instance (via [`getSW()`]{@link module:workbox-window.Workbox#getSW}) and resolves
* with a response (if any).
*
* A response can be set in a message handler in the service worker by
* calling `event.ports[0].postMessage(...)`, which will resolve the promise
* returned by `messageSW()`. If no response is set, the promise will never
* resolve.
*
* @param {Object} data An object to send to the service worker
* @return {Promise<Object>}
*/
async messageSW(data) {
const sw = await this.getSW();
return messageSW(sw, data);
}
/**
* Checks for a service worker already controlling the page and returns
* it if its script URL matchs.
*
* @private
* @return {ServiceWorker|undefined}
*/
_getControllingSWIfCompatible() {
const controller = navigator.serviceWorker.controller;
if (controller && urlsMatch(controller.scriptURL, this._scriptURL)) {
return controller;
}
}
/**
* Registers a service worker for this instances script URL and register
* options and tracks the time registration was complete.
*
* @private
*/
async _registerScript() {
try {
const reg = await navigator.serviceWorker.register(this._scriptURL, this._registerOptions); // Keep track of when registration happened, so it can be used in the
// `this._onUpdateFound` heuristic. Also use the presence of this
// property as a way to see if `.register()` has been called.
this._registrationTime = performance.now();
return reg;
} catch (error) {
{
logger.error(error);
} // Re-throw the error.
throw error;
}
}
/**
* Sends a message to the passed service worker that the window is ready.
*
* @param {ServiceWorker} sw
* @private
*/
_reportWindowReady(sw) {
messageSW(sw, {
type: 'WINDOW_READY',
meta: 'workbox-window'
});
}
/**
* @private
*/
_onUpdateFound() {
const installingSW = this._registration.installing; // If the script URL passed to `navigator.serviceWorker.register()` is
// different from the current controlling SW's script URL, we know any
// successful registration calls will trigger an `updatefound` event.
// But if the registered script URL is the same as the current controlling
// SW's script URL, we'll only get an `updatefound` event if the file
// changed since it was last registered. This can be a problem if the user
// opens up the same page in a different tab, and that page registers
// a SW that triggers an update. It's a problem because this page has no
// good way of knowing whether the `updatefound` event came from the SW
// script it registered or from a registration attempt made by a newer
// version of the page running in another tab.
// To minimize the possibility of a false positive, we use the logic here:
let updateLikelyTriggeredExternally = // Since we enforce only calling `register()` once, and since we don't
// add the `updatefound` event listener until the `register()` call, if
// `_updateFoundCount` is > 0 then it means this method has already
// been called, thus this SW must be external
this._updateFoundCount > 0 || // If the script URL of the installing SW is different from this
// instance's script URL, we know it's definitely not from our
// registration.
!urlsMatch(installingSW.scriptURL, this._scriptURL) || // If all of the above are false, then we use a time-based heuristic:
// Any `updatefound` event that occurs long after our registration is
// assumed to be external.
performance.now() > this._registrationTime + REGISTRATION_TIMEOUT_DURATION ? // If any of the above are not true, we assume the update was
// triggered by this instance.
true : false;
if (updateLikelyTriggeredExternally) {
this._externalSW = installingSW;
this._registration.removeEventListener('updatefound', this._onUpdateFound);
} else {
// If the update was not triggered externally we know the installing
// SW is the one we registered, so we set it.
this._sw = installingSW;
this._swDeferred.resolve(installingSW); // The `installing` state isn't something we have a dedicated
// callback for, but we do log messages for it in development.
{
if (navigator.serviceWorker.controller) {
logger.log('Updated service worker found. Installing now...');
} else {
logger.log('Service worker is installing...');
}
}
} // Increment the `updatefound` count, so future invocations of this
// method can be sure they were triggered externally.
++this._updateFoundCount; // Add a `statechange` listener regardless of whether this update was
// triggered externally, since we have callbacks for both.
installingSW.addEventListener('statechange', this._onStateChange);
}
/**
* @private
* @param {Event} originalEvent
*/
_onStateChange(originalEvent) {
const sw = originalEvent.target;
const {
state
} = sw;
const isExternal = sw === this._externalSW;
const eventPrefix = isExternal ? 'external' : '';
const eventProps = {
sw,
originalEvent
};
if (!isExternal && this._isUpdate) {
eventProps.isUpdate = true;
}
this.dispatchEvent(new WorkboxEvent(eventPrefix + state, eventProps));
if (state === 'installed') {
// This timeout is used to ignore cases where the service worker calls
// `skipWaiting()` in the install event, thus moving it directly in the
// activating state. (Since all service workers *must* go through the
// waiting phase, the only way to detect `skipWaiting()` called in the
// install event is to observe that the time spent in the waiting phase
// is very short.)
// NOTE: we don't need separate timeouts for the own and external SWs
// since they can't go through these phases at the same time.
this._waitingTimeout = setTimeout(() => {
// Ensure the SW is still waiting (it may now be redundant).
if (state === 'installed' && this._registration.waiting === sw) {
this.dispatchEvent(new WorkboxEvent(eventPrefix + 'waiting', eventProps));
{
if (isExternal) {
logger.warn('An external service worker has installed but is ' + 'waiting for this client to close before activating...');
} else {
logger.warn('The service worker has installed but is waiting ' + 'for existing clients to close before activating...');
}
}
}
}, WAITING_TIMEOUT_DURATION);
} else if (state === 'activating') {
clearTimeout(this._waitingTimeout);
if (!isExternal) {
this._activeDeferred.resolve(sw);
}
}
{
switch (state) {
case 'installed':
if (isExternal) {
logger.warn('An external service worker has installed. ' + 'You may want to suggest users reload this page.');
} else {
logger.log('Registered service worker installed.');
}
break;
case 'activated':
if (isExternal) {
logger.warn('An external service worker has activated.');
} else {
logger.log('Registered service worker activated.');
if (sw !== navigator.serviceWorker.controller) {
logger.warn('The registered service worker is active but ' + 'not yet controlling the page. Reload or run ' + '`clients.claim()` in the service worker.');
}
}
break;
case 'redundant':
if (sw === this._compatibleControllingSW) {
logger.log('Previously controlling service worker now redundant!');
} else if (!isExternal) {
logger.log('Registered service worker now redundant!');
}
break;
}
}
}
/**
* @private
* @param {Event} originalEvent
*/
_onControllerChange(originalEvent) {
const sw = this._sw;
if (sw === navigator.serviceWorker.controller) {
this.dispatchEvent(new WorkboxEvent('controlling', {
sw,
originalEvent
}));
{
logger.log('Registered service worker now controlling this page.');
}
this._controllingDeferred.resolve(sw);
}
}
/**
* @private
* @param {Event} originalEvent
*/
_onMessage(originalEvent) {
const {
data
} = originalEvent;
this.dispatchEvent(new WorkboxEvent('message', {
data,
originalEvent
}));
}
} // The jsdoc comments below outline the events this instance may dispatch:
/*
Copyright 2019 Google LLC
Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.
*/
export { Workbox, messageSW };
//# sourceMappingURL=workbox-window.dev.mjs.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,896 @@
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
typeof define === 'function' && define.amd ? define(['exports'], factory) :
(global = global || self, factory(global.workbox = {}));
}(this, function (exports) { 'use strict';
try {
self['workbox:window:4.3.1'] && _();
} catch (e) {} // eslint-disable-line
/*
Copyright 2019 Google LLC
Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.
*/
/**
* Sends a data object to a service worker via `postMessage` and resolves with
* a response (if any).
*
* A response can be set in a message handler in the service worker by
* calling `event.ports[0].postMessage(...)`, which will resolve the promise
* returned by `messageSW()`. If no response is set, the promise will not
* resolve.
*
* @param {ServiceWorker} sw The service worker to send the message to.
* @param {Object} data An object to send to the service worker.
* @return {Promise<Object|undefined>}
*
* @memberof module:workbox-window
*/
var messageSW = function messageSW(sw, data) {
return new Promise(function (resolve) {
var messageChannel = new MessageChannel();
messageChannel.port1.onmessage = function (evt) {
return resolve(evt.data);
};
sw.postMessage(data, [messageChannel.port2]);
});
};
function _defineProperties(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
descriptor.enumerable = descriptor.enumerable || false;
descriptor.configurable = true;
if ("value" in descriptor) descriptor.writable = true;
Object.defineProperty(target, descriptor.key, descriptor);
}
}
function _createClass(Constructor, protoProps, staticProps) {
if (protoProps) _defineProperties(Constructor.prototype, protoProps);
if (staticProps) _defineProperties(Constructor, staticProps);
return Constructor;
}
function _inheritsLoose(subClass, superClass) {
subClass.prototype = Object.create(superClass.prototype);
subClass.prototype.constructor = subClass;
subClass.__proto__ = superClass;
}
function _assertThisInitialized(self) {
if (self === void 0) {
throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
}
return self;
}
try {
self['workbox:core:4.3.1'] && _();
} catch (e) {} // eslint-disable-line
/*
Copyright 2018 Google LLC
Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.
*/
/**
* The Deferred class composes Promises in a way that allows for them to be
* resolved or rejected from outside the constructor. In most cases promises
* should be used directly, but Deferreds can be necessary when the logic to
* resolve a promise must be separate.
*
* @private
*/
var Deferred =
/**
* Creates a promise and exposes its resolve and reject functions as methods.
*/
function Deferred() {
var _this = this;
this.promise = new Promise(function (resolve, reject) {
_this.resolve = resolve;
_this.reject = reject;
});
};
/*
Copyright 2019 Google LLC
Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.
*/
var logger = function () {
var inGroup = false;
var methodToColorMap = {
debug: "#7f8c8d",
// Gray
log: "#2ecc71",
// Green
warn: "#f39c12",
// Yellow
error: "#c0392b",
// Red
groupCollapsed: "#3498db",
// Blue
groupEnd: null // No colored prefix on groupEnd
};
var print = function print(method, args) {
var _console2;
if (method === 'groupCollapsed') {
// Safari doesn't print all console.groupCollapsed() arguments:
// https://bugs.webkit.org/show_bug.cgi?id=182754
if (/^((?!chrome|android).)*safari/i.test(navigator.userAgent)) {
var _console;
(_console = console)[method].apply(_console, args);
return;
}
}
var styles = ["background: " + methodToColorMap[method], "border-radius: 0.5em", "color: white", "font-weight: bold", "padding: 2px 0.5em"]; // When in a group, the workbox prefix is not displayed.
var logPrefix = inGroup ? [] : ['%cworkbox', styles.join(';')];
(_console2 = console)[method].apply(_console2, logPrefix.concat(args));
if (method === 'groupCollapsed') {
inGroup = true;
}
if (method === 'groupEnd') {
inGroup = false;
}
};
var api = {};
var _arr = Object.keys(methodToColorMap);
var _loop = function _loop() {
var method = _arr[_i];
api[method] = function () {
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
print(method, args);
};
};
for (var _i = 0; _i < _arr.length; _i++) {
_loop();
}
return api;
}();
/*
Copyright 2019 Google LLC
Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.
*/
/**
* A minimal `EventTarget` shim.
* This is necessary because not all browsers support constructable
* `EventTarget`, so using a real `EventTarget` will error.
* @private
*/
var EventTargetShim =
/*#__PURE__*/
function () {
/**
* Creates an event listener registry
*
* @private
*/
function EventTargetShim() {
// A registry of event types to listeners.
this._eventListenerRegistry = {};
}
/**
* @param {string} type
* @param {Function} listener
* @private
*/
var _proto = EventTargetShim.prototype;
_proto.addEventListener = function addEventListener(type, listener) {
this._getEventListenersByType(type).add(listener);
};
/**
* @param {string} type
* @param {Function} listener
* @private
*/
_proto.removeEventListener = function removeEventListener(type, listener) {
this._getEventListenersByType(type).delete(listener);
};
/**
* @param {Event} event
* @private
*/
_proto.dispatchEvent = function dispatchEvent(event) {
event.target = this;
this._getEventListenersByType(event.type).forEach(function (listener) {
return listener(event);
});
};
/**
* Returns a Set of listeners associated with the passed event type.
* If no handlers have been registered, an empty Set is returned.
*
* @param {string} type The event type.
* @return {Set} An array of handler functions.
* @private
*/
_proto._getEventListenersByType = function _getEventListenersByType(type) {
return this._eventListenerRegistry[type] = this._eventListenerRegistry[type] || new Set();
};
return EventTargetShim;
}();
/*
Copyright 2019 Google LLC
Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.
*/
/**
* Returns true if two URLs have the same `.href` property. The URLS can be
* relative, and if they are the current location href is used to resolve URLs.
*
* @private
* @param {string} url1
* @param {string} url2
* @return {boolean}
*/
var urlsMatch = function urlsMatch(url1, url2) {
return new URL(url1, location).href === new URL(url2, location).href;
};
/*
Copyright 2019 Google LLC
Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.
*/
/**
* A minimal `Event` subclass shim.
* This doesn't *actually* subclass `Event` because not all browsers support
* constructable `EventTarget`, and using a real `Event` will error.
* @private
*/
var WorkboxEvent =
/**
* @param {string} type
* @param {Object} props
*/
function WorkboxEvent(type, props) {
Object.assign(this, props, {
type: type
});
};
function _catch(body, recover) {
try {
var result = body();
} catch (e) {
return recover(e);
}
if (result && result.then) {
return result.then(void 0, recover);
}
return result;
}
function _async(f) {
return function () {
for (var args = [], i = 0; i < arguments.length; i++) {
args[i] = arguments[i];
}
try {
return Promise.resolve(f.apply(this, args));
} catch (e) {
return Promise.reject(e);
}
};
}
function _invoke(body, then) {
var result = body();
if (result && result.then) {
return result.then(then);
}
return then(result);
}
function _await(value, then, direct) {
if (direct) {
return then ? then(value) : value;
}
if (!value || !value.then) {
value = Promise.resolve(value);
}
return then ? value.then(then) : value;
}
function _awaitIgnored(value, direct) {
if (!direct) {
return value && value.then ? value.then(_empty) : Promise.resolve();
}
}
function _empty() {}
// `skipWaiting()` wasn't called. This 200 amount wasn't scientifically
// chosen, but it seems to avoid false positives in my testing.
var WAITING_TIMEOUT_DURATION = 200; // The amount of time after a registration that we can reasonably conclude
// that the registration didn't trigger an update.
var REGISTRATION_TIMEOUT_DURATION = 60000;
/**
* A class to aid in handling service worker registration, updates, and
* reacting to service worker lifecycle events.
*
* @fires [message]{@link module:workbox-window.Workbox#message}
* @fires [installed]{@link module:workbox-window.Workbox#installed}
* @fires [waiting]{@link module:workbox-window.Workbox#waiting}
* @fires [controlling]{@link module:workbox-window.Workbox#controlling}
* @fires [activated]{@link module:workbox-window.Workbox#activated}
* @fires [redundant]{@link module:workbox-window.Workbox#redundant}
* @fires [externalinstalled]{@link module:workbox-window.Workbox#externalinstalled}
* @fires [externalwaiting]{@link module:workbox-window.Workbox#externalwaiting}
* @fires [externalactivated]{@link module:workbox-window.Workbox#externalactivated}
*
* @memberof module:workbox-window
*/
var Workbox =
/*#__PURE__*/
function (_EventTargetShim) {
_inheritsLoose(Workbox, _EventTargetShim);
/**
* Creates a new Workbox instance with a script URL and service worker
* options. The script URL and options are the same as those used when
* calling `navigator.serviceWorker.register(scriptURL, options)`. See:
* https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerContainer/register
*
* @param {string} scriptURL The service worker script associated with this
* instance.
* @param {Object} [registerOptions] The service worker options associated
* with this instance.
*/
function Workbox(scriptURL, registerOptions) {
var _this;
if (registerOptions === void 0) {
registerOptions = {};
}
_this = _EventTargetShim.call(this) || this;
_this._scriptURL = scriptURL;
_this._registerOptions = registerOptions;
_this._updateFoundCount = 0; // Deferreds we can resolve later.
_this._swDeferred = new Deferred();
_this._activeDeferred = new Deferred();
_this._controllingDeferred = new Deferred(); // Bind event handler callbacks.
_this._onMessage = _this._onMessage.bind(_assertThisInitialized(_assertThisInitialized(_this)));
_this._onStateChange = _this._onStateChange.bind(_assertThisInitialized(_assertThisInitialized(_this)));
_this._onUpdateFound = _this._onUpdateFound.bind(_assertThisInitialized(_assertThisInitialized(_this)));
_this._onControllerChange = _this._onControllerChange.bind(_assertThisInitialized(_assertThisInitialized(_this)));
return _this;
}
/**
* Registers a service worker for this instances script URL and service
* worker options. By default this method delays registration until after
* the window has loaded.
*
* @param {Object} [options]
* @param {Function} [options.immediate=false] Setting this to true will
* register the service worker immediately, even if the window has
* not loaded (not recommended).
*/
var _proto = Workbox.prototype;
_proto.register = _async(function (_temp) {
var _this2 = this;
var _ref = _temp === void 0 ? {} : _temp,
_ref$immediate = _ref.immediate,
immediate = _ref$immediate === void 0 ? false : _ref$immediate;
{
if (_this2._registrationTime) {
logger.error('Cannot re-register a Workbox instance after it has ' + 'been registered. Create a new instance instead.');
return;
}
}
return _invoke(function () {
if (!immediate && document.readyState !== 'complete') {
return _awaitIgnored(new Promise(function (res) {
return addEventListener('load', res);
}));
}
}, function () {
// Set this flag to true if any service worker was controlling the page
// at registration time.
_this2._isUpdate = Boolean(navigator.serviceWorker.controller); // Before registering, attempt to determine if a SW is already controlling
// the page, and if that SW script (and version, if specified) matches this
// instance's script.
_this2._compatibleControllingSW = _this2._getControllingSWIfCompatible();
return _await(_this2._registerScript(), function (_this2$_registerScrip) {
_this2._registration = _this2$_registerScrip;
// If we have a compatible controller, store the controller as the "own"
// SW, resolve active/controlling deferreds and add necessary listeners.
if (_this2._compatibleControllingSW) {
_this2._sw = _this2._compatibleControllingSW;
_this2._activeDeferred.resolve(_this2._compatibleControllingSW);
_this2._controllingDeferred.resolve(_this2._compatibleControllingSW);
_this2._reportWindowReady(_this2._compatibleControllingSW);
_this2._compatibleControllingSW.addEventListener('statechange', _this2._onStateChange, {
once: true
});
} // If there's a waiting service worker with a matching URL before the
// `updatefound` event fires, it likely means that this site is open
// in another tab, or the user refreshed the page (and thus the prevoius
// page wasn't fully unloaded before this page started loading).
// https://developers.google.com/web/fundamentals/primers/service-workers/lifecycle#waiting
var waitingSW = _this2._registration.waiting;
if (waitingSW && urlsMatch(waitingSW.scriptURL, _this2._scriptURL)) {
// Store the waiting SW as the "own" Sw, even if it means overwriting
// a compatible controller.
_this2._sw = waitingSW; // Run this in the next microtask, so any code that adds an event
// listener after awaiting `register()` will get this event.
Promise.resolve().then(function () {
_this2.dispatchEvent(new WorkboxEvent('waiting', {
sw: waitingSW,
wasWaitingBeforeRegister: true
}));
{
logger.warn('A service worker was already waiting to activate ' + 'before this script was registered...');
}
});
} // If an "own" SW is already set, resolve the deferred.
if (_this2._sw) {
_this2._swDeferred.resolve(_this2._sw);
}
{
logger.log('Successfully registered service worker.', _this2._scriptURL);
if (navigator.serviceWorker.controller) {
if (_this2._compatibleControllingSW) {
logger.debug('A service worker with the same script URL ' + 'is already controlling this page.');
} else {
logger.debug('A service worker with a different script URL is ' + 'currently controlling the page. The browser is now fetching ' + 'the new script now...');
}
}
var currentPageIsOutOfScope = function currentPageIsOutOfScope() {
var scopeURL = new URL(_this2._registerOptions.scope || _this2._scriptURL, document.baseURI);
var scopeURLBasePath = new URL('./', scopeURL.href).pathname;
return !location.pathname.startsWith(scopeURLBasePath);
};
if (currentPageIsOutOfScope()) {
logger.warn('The current page is not in scope for the registered ' + 'service worker. Was this a mistake?');
}
}
_this2._registration.addEventListener('updatefound', _this2._onUpdateFound);
navigator.serviceWorker.addEventListener('controllerchange', _this2._onControllerChange, {
once: true
}); // Add message listeners.
if ('BroadcastChannel' in self) {
_this2._broadcastChannel = new BroadcastChannel('workbox');
_this2._broadcastChannel.addEventListener('message', _this2._onMessage);
}
navigator.serviceWorker.addEventListener('message', _this2._onMessage);
return _this2._registration;
});
});
});
/**
* Resolves to the service worker registered by this instance as soon as it
* is active. If a service worker was already controlling at registration
* time then it will resolve to that if the script URLs (and optionally
* script versions) match, otherwise it will wait until an update is found
* and activates.
*
* @return {Promise<ServiceWorker>}
*/
/**
* Resolves with a reference to a service worker that matches the script URL
* of this instance, as soon as it's available.
*
* If, at registration time, there's already an active or waiting service
* worker with a matching script URL, it will be used (with the waiting
* service worker taking precedence over the active service worker if both
* match, since the waiting service worker would have been registered more
* recently).
* If there's no matching active or waiting service worker at registration
* time then the promise will not resolve until an update is found and starts
* installing, at which point the installing service worker is used.
*
* @return {Promise<ServiceWorker>}
*/
_proto.getSW = _async(function () {
var _this3 = this;
// If `this._sw` is set, resolve with that as we want `getSW()` to
// return the correct (new) service worker if an update is found.
return _this3._sw || _this3._swDeferred.promise;
});
/**
* Sends the passed data object to the service worker registered by this
* instance (via [`getSW()`]{@link module:workbox-window.Workbox#getSW}) and resolves
* with a response (if any).
*
* A response can be set in a message handler in the service worker by
* calling `event.ports[0].postMessage(...)`, which will resolve the promise
* returned by `messageSW()`. If no response is set, the promise will never
* resolve.
*
* @param {Object} data An object to send to the service worker
* @return {Promise<Object>}
*/
_proto.messageSW = _async(function (data) {
var _this4 = this;
return _await(_this4.getSW(), function (sw) {
return messageSW(sw, data);
});
});
/**
* Checks for a service worker already controlling the page and returns
* it if its script URL matchs.
*
* @private
* @return {ServiceWorker|undefined}
*/
_proto._getControllingSWIfCompatible = function _getControllingSWIfCompatible() {
var controller = navigator.serviceWorker.controller;
if (controller && urlsMatch(controller.scriptURL, this._scriptURL)) {
return controller;
}
};
/**
* Registers a service worker for this instances script URL and register
* options and tracks the time registration was complete.
*
* @private
*/
_proto._registerScript = _async(function () {
var _this5 = this;
return _catch(function () {
return _await(navigator.serviceWorker.register(_this5._scriptURL, _this5._registerOptions), function (reg) {
// Keep track of when registration happened, so it can be used in the
// `this._onUpdateFound` heuristic. Also use the presence of this
// property as a way to see if `.register()` has been called.
_this5._registrationTime = performance.now();
return reg;
});
}, function (error) {
{
logger.error(error);
} // Re-throw the error.
throw error;
});
});
/**
* Sends a message to the passed service worker that the window is ready.
*
* @param {ServiceWorker} sw
* @private
*/
_proto._reportWindowReady = function _reportWindowReady(sw) {
messageSW(sw, {
type: 'WINDOW_READY',
meta: 'workbox-window'
});
};
/**
* @private
*/
_proto._onUpdateFound = function _onUpdateFound() {
var installingSW = this._registration.installing; // If the script URL passed to `navigator.serviceWorker.register()` is
// different from the current controlling SW's script URL, we know any
// successful registration calls will trigger an `updatefound` event.
// But if the registered script URL is the same as the current controlling
// SW's script URL, we'll only get an `updatefound` event if the file
// changed since it was last registered. This can be a problem if the user
// opens up the same page in a different tab, and that page registers
// a SW that triggers an update. It's a problem because this page has no
// good way of knowing whether the `updatefound` event came from the SW
// script it registered or from a registration attempt made by a newer
// version of the page running in another tab.
// To minimize the possibility of a false positive, we use the logic here:
var updateLikelyTriggeredExternally = // Since we enforce only calling `register()` once, and since we don't
// add the `updatefound` event listener until the `register()` call, if
// `_updateFoundCount` is > 0 then it means this method has already
// been called, thus this SW must be external
this._updateFoundCount > 0 || // If the script URL of the installing SW is different from this
// instance's script URL, we know it's definitely not from our
// registration.
!urlsMatch(installingSW.scriptURL, this._scriptURL) || // If all of the above are false, then we use a time-based heuristic:
// Any `updatefound` event that occurs long after our registration is
// assumed to be external.
performance.now() > this._registrationTime + REGISTRATION_TIMEOUT_DURATION ? // If any of the above are not true, we assume the update was
// triggered by this instance.
true : false;
if (updateLikelyTriggeredExternally) {
this._externalSW = installingSW;
this._registration.removeEventListener('updatefound', this._onUpdateFound);
} else {
// If the update was not triggered externally we know the installing
// SW is the one we registered, so we set it.
this._sw = installingSW;
this._swDeferred.resolve(installingSW); // The `installing` state isn't something we have a dedicated
// callback for, but we do log messages for it in development.
{
if (navigator.serviceWorker.controller) {
logger.log('Updated service worker found. Installing now...');
} else {
logger.log('Service worker is installing...');
}
}
} // Increment the `updatefound` count, so future invocations of this
// method can be sure they were triggered externally.
++this._updateFoundCount; // Add a `statechange` listener regardless of whether this update was
// triggered externally, since we have callbacks for both.
installingSW.addEventListener('statechange', this._onStateChange);
};
/**
* @private
* @param {Event} originalEvent
*/
_proto._onStateChange = function _onStateChange(originalEvent) {
var _this6 = this;
var sw = originalEvent.target;
var state = sw.state;
var isExternal = sw === this._externalSW;
var eventPrefix = isExternal ? 'external' : '';
var eventProps = {
sw: sw,
originalEvent: originalEvent
};
if (!isExternal && this._isUpdate) {
eventProps.isUpdate = true;
}
this.dispatchEvent(new WorkboxEvent(eventPrefix + state, eventProps));
if (state === 'installed') {
// This timeout is used to ignore cases where the service worker calls
// `skipWaiting()` in the install event, thus moving it directly in the
// activating state. (Since all service workers *must* go through the
// waiting phase, the only way to detect `skipWaiting()` called in the
// install event is to observe that the time spent in the waiting phase
// is very short.)
// NOTE: we don't need separate timeouts for the own and external SWs
// since they can't go through these phases at the same time.
this._waitingTimeout = setTimeout(function () {
// Ensure the SW is still waiting (it may now be redundant).
if (state === 'installed' && _this6._registration.waiting === sw) {
_this6.dispatchEvent(new WorkboxEvent(eventPrefix + 'waiting', eventProps));
{
if (isExternal) {
logger.warn('An external service worker has installed but is ' + 'waiting for this client to close before activating...');
} else {
logger.warn('The service worker has installed but is waiting ' + 'for existing clients to close before activating...');
}
}
}
}, WAITING_TIMEOUT_DURATION);
} else if (state === 'activating') {
clearTimeout(this._waitingTimeout);
if (!isExternal) {
this._activeDeferred.resolve(sw);
}
}
{
switch (state) {
case 'installed':
if (isExternal) {
logger.warn('An external service worker has installed. ' + 'You may want to suggest users reload this page.');
} else {
logger.log('Registered service worker installed.');
}
break;
case 'activated':
if (isExternal) {
logger.warn('An external service worker has activated.');
} else {
logger.log('Registered service worker activated.');
if (sw !== navigator.serviceWorker.controller) {
logger.warn('The registered service worker is active but ' + 'not yet controlling the page. Reload or run ' + '`clients.claim()` in the service worker.');
}
}
break;
case 'redundant':
if (sw === this._compatibleControllingSW) {
logger.log('Previously controlling service worker now redundant!');
} else if (!isExternal) {
logger.log('Registered service worker now redundant!');
}
break;
}
}
};
/**
* @private
* @param {Event} originalEvent
*/
_proto._onControllerChange = function _onControllerChange(originalEvent) {
var sw = this._sw;
if (sw === navigator.serviceWorker.controller) {
this.dispatchEvent(new WorkboxEvent('controlling', {
sw: sw,
originalEvent: originalEvent
}));
{
logger.log('Registered service worker now controlling this page.');
}
this._controllingDeferred.resolve(sw);
}
};
/**
* @private
* @param {Event} originalEvent
*/
_proto._onMessage = function _onMessage(originalEvent) {
var data = originalEvent.data;
this.dispatchEvent(new WorkboxEvent('message', {
data: data,
originalEvent: originalEvent
}));
};
_createClass(Workbox, [{
key: "active",
get: function get() {
return this._activeDeferred.promise;
}
/**
* Resolves to the service worker registered by this instance as soon as it
* is controlling the page. If a service worker was already controlling at
* registration time then it will resolve to that if the script URLs (and
* optionally script versions) match, otherwise it will wait until an update
* is found and starts controlling the page.
* Note: the first time a service worker is installed it will active but
* not start controlling the page unless `clients.claim()` is called in the
* service worker.
*
* @return {Promise<ServiceWorker>}
*/
}, {
key: "controlling",
get: function get() {
return this._controllingDeferred.promise;
}
}]);
return Workbox;
}(EventTargetShim); // The jsdoc comments below outline the events this instance may dispatch:
/*
Copyright 2019 Google LLC
Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.
*/
exports.Workbox = Workbox;
exports.messageSW = messageSW;
Object.defineProperty(exports, '__esModule', { value: true });
}));
//# sourceMappingURL=workbox-window.dev.umd.js.map

Some files were not shown because too many files have changed in this diff Show More