From 427b2243bcdfa187ba44d02ba19298c00fc086b7 Mon Sep 17 00:00:00 2001 From: Rama Priyanto Date: Sun, 20 Apr 2025 12:10:10 +0700 Subject: [PATCH] feat:subscription, fix:isPublish advertise --- components/landing/footer-new.tsx | 39 +- components/layout/sidebar/sidebar-mobile.tsx | 1 + components/layout/sidebar/sidebar.tsx | 1 + .../main/dashboard/dashboard-container.tsx | 4 +- .../table/advertise/advertise-table.tsx | 4 +- public/sw.js | 101 +- public/workbox-4754cb34.js | 1 - public/workbox-e43f5367.js | 2455 +++++++++++++++++ service/advertisement.ts | 1 + service/subscribe.ts | 17 + 10 files changed, 2610 insertions(+), 14 deletions(-) delete mode 100644 public/workbox-4754cb34.js create mode 100644 public/workbox-e43f5367.js create mode 100644 service/subscribe.ts diff --git a/components/landing/footer-new.tsx b/components/landing/footer-new.tsx index cad84bc..f141bf9 100644 --- a/components/landing/footer-new.tsx +++ b/components/landing/footer-new.tsx @@ -14,10 +14,31 @@ import Link from "next/link"; import { useTranslations } from "next-intl"; import { useEffect, useState } from "react"; import Image from "next/image"; +import { error, success } from "@/config/swal"; +import { subscription } from "@/service/subscribe"; export default function FooterNew(props: { margin?: boolean }) { - const t2 = useTranslations("Navbar"); - const t3 = useTranslations("LandingInformasiPublik"); + const [emailValue, setEmailValue] = useState(""); + + const doSubscribe = async () => { + const isValidEmail = (email: string): boolean => { + const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; + return emailRegex.test(email); + }; + + if (!isValidEmail(emailValue)) { + error("Email tidak valid"); + return false; + } + + const res = await subscription({ email: emailValue }); + if (res?.error) { + error(res?.message); + return false; + } + + success("Sukses"); + }; return (
- // } + value={emailValue} + onValueChange={setEmailValue} /> -
+ -
+
diff --git a/components/layout/sidebar/sidebar-mobile.tsx b/components/layout/sidebar/sidebar-mobile.tsx index efddecc..7b9e3cd 100644 --- a/components/layout/sidebar/sidebar-mobile.tsx +++ b/components/layout/sidebar/sidebar-mobile.tsx @@ -488,6 +488,7 @@ const SidebarMobile: React.FC = ({ updateSidebarData }) => { placement="right" delay={0} closeDelay={0} + key={list.name} >
= ({ updateSidebarData }) => { placement="right" delay={0} closeDelay={0} + key={list.name} >
{postCount?.map((list) => (
{list?.no}
diff --git a/components/table/advertise/advertise-table.tsx b/components/table/advertise/advertise-table.tsx index 7e9542a..edfc791 100644 --- a/components/table/advertise/advertise-table.tsx +++ b/components/table/advertise/advertise-table.tsx @@ -268,10 +268,10 @@ export default function AdvertiseTable(props: { triggerRefresh: boolean }) { return (
handleAdvertise(e, advertise?.id)} /> - {advertise?.isActive ? "Ya" : "Tidak"} + {advertise?.isPublish ? "Ya" : "Tidak"}
); case "actions": diff --git a/public/sw.js b/public/sw.js index 46db253..7a31e69 100644 --- a/public/sw.js +++ b/public/sw.js @@ -1 +1,100 @@ -if(!self.define){let a,e={};const s=(s,i)=>(s=new URL(s+".js",i).href,e[s]||new Promise((e=>{if("document"in self){const a=document.createElement("script");a.src=s,a.onload=e,document.head.appendChild(a)}else a=s,importScripts(s),e()})).then((()=>{let a=e[s];if(!a)throw new Error(`Module ${s} didn’t register its module`);return a})));self.define=(i,r)=>{const n=a||("document"in self?document.currentScript.src:"")||location.href;if(e[n])return;let d={};const t=a=>s(a,n),c={module:{uri:n},exports:d,require:t};e[n]=Promise.all(i.map((a=>c[a]||t(a)))).then((a=>(r(...a),d)))}}define(["./workbox-4754cb34"],(function(a){"use strict";importScripts(),self.skipWaiting(),a.clientsClaim(),a.precacheAndRoute([{url:"/Illustrasi.png",revision:"cb35551974802816c8bc42f489119ad4"},{url:"/Item.svg",revision:"e24aa05806c3a9e58681b9d3a2f53e3a"},{url:"/_next/app-build-manifest.json",revision:"fe482195872700a78d94907191ce5f81"},{url:"/_next/static/chunks/1007-fcf15a9998381377.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/1046-122e831f90d45e3f.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/1104.90d0017379ad08d1.js",revision:"90d0017379ad08d1"},{url:"/_next/static/chunks/1143.810fb67f71998cc9.js",revision:"810fb67f71998cc9"},{url:"/_next/static/chunks/1278-1f76e85fb9346bc0.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/1342-b620864d25484dd2.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/140-a0596c936eed11dd.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/1410-9cd4be24021a3f9c.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/1490-440c689a6e3faf5c.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/1529-fbafd7b0dcf2c89a.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/1549-851890b408d9023e.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/1684-01234881d7186cfe.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/1706-1d4a704541d74b1e.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/1765.84344952d5ca7dfc.js",revision:"84344952d5ca7dfc"},{url:"/_next/static/chunks/2113-6285d6d31a150c4d.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/2128-c9b6787b635b35a6.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/2170a4aa-8be2e1de3df20b60.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/2204-e276ff477a35af7f.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/2241-0b64c54f704209f8.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/2278-1a7feba0fc6b7236.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/2304-b0f320cbfe55c7cd.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/2321-fc76cc056a1c69e3.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/2520-864d3a51c95b60fb.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/2526-c6e23e0c2e318005.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/2648.7907112d2a4c17eb.js",revision:"7907112d2a4c17eb"},{url:"/_next/static/chunks/271-06ca290e7a4a3784.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/2733-fea77cea07bf3d6a.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/2808-c7a296ece4a93493.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/2843-ad179194fd6abf1d.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/2864-2493b46102dc3e9a.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/3063-30f9a7d933e4f2e9.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/3115-af724edaae8e930a.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/3170-2068171446544c7d.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/3186.a996ca17c77f1018.js",revision:"a996ca17c77f1018"},{url:"/_next/static/chunks/3254-3bffa7f85164ecc2.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/3324-68d7eec6c7130336.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/3441-2ba3daaa68c70233.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/3464-41b484c4b5989022.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/3541-6db5707bf42a3960.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/3733-c13e96788e581995.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/3975359d-73af23e4d98f35a7.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/3990-5e6797c163780540.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/3bcdfda6-f48911ef473ac942.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/4123-0798c46b76fef195.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/4182-3af1ce82a1d3433e.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/4184.4c95d1fbf0dbab83.js",revision:"4c95d1fbf0dbab83"},{url:"/_next/static/chunks/41ade5dc-3d190025e9e2053a.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/427-aa401a65441ae887.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/4289-78f7fe9fada6e8d2.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/431-616071255b7472ba.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/4369-e8c1fbaac08b2d33.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/4468-c5a4f8345e64091f.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/4611-5287e1b7a6c32816.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/472.04a8725c923ee78b.js",revision:"04a8725c923ee78b"},{url:"/_next/static/chunks/4725.2f2597d8c7c37f22.js",revision:"2f2597d8c7c37f22"},{url:"/_next/static/chunks/4896-4085e497ef2c4a69.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/4960.7c35cdc20d5f89ec.js",revision:"7c35cdc20d5f89ec"},{url:"/_next/static/chunks/4983-9e3fd380a35fa15f.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/4bd1b696-584b158465405ea8.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/5019-43e910923b9f34a2.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/5137-1808156dc8f1f1d1.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/5198-2fe6b590671cf237.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/5317-2dea525acccaf4c3.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/5421-bd370246137e7866.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/5550-54fe8e9194e3874e.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/5645-e690b6d216c3884e.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/5670.9cb3443723e82235.js",revision:"9cb3443723e82235"},{url:"/_next/static/chunks/5837-731374e5bec01dd5.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/6033-cee181ad8844f0db.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/6098-6ba897f3baad0721.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/6114-de8b94a24e04daf9.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/6288.8ac8bc3affe28602.js",revision:"8ac8bc3affe28602"},{url:"/_next/static/chunks/6344-0f61c4baeb2f7166.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/6348-78ca76fe4fd404d8.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/6357-59df8d5930ab6ebb.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/6399-a2244387428fda36.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/6460-b7a393c2778e4f20.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/6522-68d47ee93df68033.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/6636-ece2632a4b7401f0.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/6766-b7c05f0bac59a06c.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/679-ba0b32a662bbeaf8.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/6797-38e7697415ebd09b.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/6874-4fba9abb976a535e.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/6947-15a383fc14418b3c.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/6999-7c8efcc34f9570af.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/7003.94d785a8522c8bd9.js",revision:"94d785a8522c8bd9"},{url:"/_next/static/chunks/7081-1839f374c49585ad.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/7117.9723b61899d70d87.js",revision:"9723b61899d70d87"},{url:"/_next/static/chunks/7137-0c4998b06514d12e.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/7228-c4c40f4b951e1685.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/7361.c8aa9d0695082de6.js",revision:"c8aa9d0695082de6"},{url:"/_next/static/chunks/7364-0a14be9ee2247f29.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/7399.a7d3b7ca1de584ef.js",revision:"a7d3b7ca1de584ef"},{url:"/_next/static/chunks/7451-88047e691af44b5c.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/7646.cdca9fd63a5e1aca.js",revision:"cdca9fd63a5e1aca"},{url:"/_next/static/chunks/80-87cfe40bf4400ffe.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/8148-0df0de06a4993965.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/8155-73601a504ced1b88.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/8170-625d42e295f09cca.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/8187f03c-2b3e3652a3eb227c.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/833-9fd04f5a9b89f7c6.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/8514-8aaabe6b6b888e07.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/8519-4ce5abbdaa178488.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/8625-c83509ad1079a232.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/8651.3d0590f823986f14.js",revision:"3d0590f823986f14"},{url:"/_next/static/chunks/873-e743b9f974476012.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/8975-8e17e5a7ec26cff0.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/8988-8903744a038c1a52.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/9084-b2dd95c093f6d887.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/9146.efd439148ba91235.js",revision:"efd439148ba91235"},{url:"/_next/static/chunks/9153-118c556c87b0fb66.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/9341.d79f7549abcc5c7c.js",revision:"d79f7549abcc5c7c"},{url:"/_next/static/chunks/9373.4c9513aefc50f0e1.js",revision:"4c9513aefc50f0e1"},{url:"/_next/static/chunks/9404-88af3a69f478171f.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/9410-1f9a022ffbebb7ea.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/9468-7e4540f1a25758e7.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/9501-666c6f01a860e040.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/9523-41215f1f45cbdb51.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/9610-5347ca2815a64a2f.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/9632-aef72bc307c25b29.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/9895-4d4840828d87f6d5.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/992-0e0f55fb82c79e05.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/9999-683ce561bf3d6466.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/(admin)/admin/advertise/page-72a0c2e29b311fc5.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/(admin)/admin/article/create/page-20f5ef28c979fce6.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/(admin)/admin/article/detail/%5Bid%5D/page-dfb215fba881bafd.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/(admin)/admin/article/edit/%5Bid%5D/page-10ef1bb0718418b9.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/(admin)/admin/article/generate/edit/%5Bid%5D/page-c7bf87a25ec49b2a.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/(admin)/admin/article/generate/page-545c81fdc14d15c1.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/(admin)/admin/article/page-32d712146c90e717.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/(admin)/admin/comment/page-a52f229afbe2df8b.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/(admin)/admin/comment/review/%5Bid%5D/page-b9ebaa442cefefd4.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/(admin)/admin/dashboard/page-765f10d615b74f9e.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/(admin)/admin/feedbacks/page-59c03a34863db7d6.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/(admin)/admin/layout-36856d1bb0fcf78b.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/(admin)/admin/magazine/create/page-29ebc0876683667d.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/(admin)/admin/magazine/detail/%5Bid%5D/page-c13697c47453ded1.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/(admin)/admin/magazine/detail/page-04c2172a64bedce1.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/(admin)/admin/magazine/edit/%5Bid%5D/page-e51e953d4a7fad86.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/(admin)/admin/magazine/page-9114aa235b0a8570.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/(admin)/admin/master-category/page-ae5f3251adf51909.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/(admin)/admin/master-menu/create/page-7f0955c7025612e3.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/(admin)/admin/master-menu/page-f4b8f02b9bf979f6.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/(admin)/admin/master-module/create/page-1012335bc79241f3.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/(admin)/admin/master-module/page-d980774b6b4f4df3.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/(admin)/admin/master-role/create/page-a76628760b300dde.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/(admin)/admin/master-role/detail/%5Bid%5D/page-a44976a7d9e2ac37.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/(admin)/admin/master-role/page-51ff3ba2e3b52910.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/(admin)/admin/master-user-level/create/page-d43d7591516d22a9.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/(admin)/admin/master-user-level/page-e6002886b21c1487.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/(admin)/admin/master-user/create/page-02d2cd39102a76d9.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/(admin)/admin/master-user/edit/%5Bid%5D/page-5d3d1ad6f44ce30d.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/(admin)/admin/master-user/page-fcdb9cccb84568d0.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/(admin)/admin/page-63ab9a79629a38f0.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/(admin)/admin/static-page/create/page-0f2b4281af09c54d.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/(admin)/admin/static-page/edit/%5Bid%5D/page-c09323bdec0f8216.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/(admin)/admin/static-page/page-3559d138f83da4f2.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/(admin)/admin/user-level/create/page-3d622eb1573b7591.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/(admin)/admin/user-level/edit/%5Bid%5D/page-7bd2906ea676ccf0.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/(admin)/admin/user-level/page-84fba42d2eae11d8.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/(admin)/settings/layout-f6ef33186a3dab90.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/(admin)/settings/page-90130a991b05162b.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/_not-found/page-8406c5f012ec6cb8.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/auth/layout-1d5a01aec537c0c2.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/auth/page-1568ed40dc7fa048.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/blog/layout-9d8e58983d63bc03.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/blog/page-f02e296ad5e32297.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/docs/layout-60732e73ed9955f5.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/docs/page-53c9166eefeef010.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/e-majalah-polri/daftar-majalah/page-eff8dc9e3c85b1bd.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/e-majalah-polri/detail/%5Bid%5D/layout-b68c6e9d9195fffe.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/e-majalah-polri/detail/%5Bid%5D/page-d3b9b11df78a94e7.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/error-bddead6507bf794e.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/form-permohonan-informasi/layout-0ba5c94447261219.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/form-permohonan-informasi/page-8e4a126ec15e3cdd.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/gpr/page-dbb95c9dd81bda1d.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/kontak-kami/layout-08eaecba6c5bea84.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/kontak-kami/page-fdefd7cde3aa2767.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/layout-69d6dc1a27a1a8c4.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/news/all/layout-7002b5068173b105.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/news/all/page-2fde71766ef6b283.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/news/detail/%5Bid%5D/layout-aa1247500ff6b445.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/news/detail/%5Bid%5D/page-d27bd516e199971b.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/news/polda/%5Bname%5D/layout-0d0b23390aa57472.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/news/polda/%5Bname%5D/page-74fdb1b8327132ec.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/news/satker/%5Bname%5D/layout-aa5aa0fc26a855da.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/news/satker/%5Bname%5D/page-09a9bc8111bfa3b5.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/page-1248ecc44d415ba9.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/portal-ppid/admin/layout-fa8fa5a9a20f4cda.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/portal-ppid/admin/page-b23f85739fb8e5fe.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/portal-ppid/e-ppid-polda/layout-52009c0d8e40dc1b.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/portal-ppid/e-ppid-polda/page-dbb082e432712038.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/portal-ppid/e-ppid-satker/layout-289729d3a996d6fd.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/portal-ppid/e-ppid-satker/page-4c5556a53f7b9e54.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/portal-ppid/informasi-publik/informasi-berkala/page-6229ed7bbfa04992.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/portal-ppid/informasi-publik/informasi-dikecualikan/page-df8385b646372def.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/portal-ppid/informasi-publik/informasi-serta-merta/page-eebf2cf43e150b6e.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/portal-ppid/informasi-publik/informasi-setiap-saat/page-c625b096b0573581.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/portal-ppid/informasi-publik/layout-2f688c79218112a0.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/portal-ppid/informasi-publik/penerangan-satuan/page-4965770366fe258a.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/portal-ppid/informasi-publik/uu-dan-peraturan/page-48389bed014ce1d3.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/portal-ppid/layanan-informasi/layout-445ddda0e141cb86.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/portal-ppid/layanan-informasi/permohonan-informasi/page-9dc1ecec67f99589.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/portal-ppid/layanan-informasi/permohonan-keberatan/page-14fbbdcb09efb5ab.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/portal-ppid/layanan-informasi/ppid-laporan-tahunan/page-a31d585b2845ecb7.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/portal-ppid/layanan-informasi/registrasi-permohonan/page-dc87c9498117d672.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/portal-ppid/layanan-informasi/statistik-rekapitulasi/page-b5e2a8521ab64a80.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/portal-ppid/page-ceafb5100d5ba0a6.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/portal-ppid/polda/%5Bpolda-name%5D/informasi-publik/informasi-berkala/page-9d988b2401b0be11.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/portal-ppid/polda/%5Bpolda-name%5D/informasi-publik/informasi-dikecualikan/page-b3ddfc8c1704a874.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/portal-ppid/polda/%5Bpolda-name%5D/informasi-publik/informasi-serta-merta/page-ea5fcb56e70e4f0c.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/portal-ppid/polda/%5Bpolda-name%5D/informasi-publik/informasi-setiap-saat/page-39d99fcf134162c6.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/portal-ppid/polda/%5Bpolda-name%5D/informasi-publik/layout-cac98b1b831adf8e.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/portal-ppid/polda/%5Bpolda-name%5D/informasi-publik/penerangan-satuan/page-31d02a031abf3b83.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/portal-ppid/polda/%5Bpolda-name%5D/informasi-publik/uu-dan-peraturan/page-39819a3ac9c0cc8d.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/portal-ppid/polda/%5Bpolda-name%5D/layanan-informasi/layout-d72da09d629d24f5.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/portal-ppid/polda/%5Bpolda-name%5D/layanan-informasi/permohonan-informasi/page-c1676132c80cf7ae.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/portal-ppid/polda/%5Bpolda-name%5D/layanan-informasi/permohonan-keberatan/page-a28738c3be035a3d.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/portal-ppid/polda/%5Bpolda-name%5D/layanan-informasi/ppid-laporan-tahunan/page-f4b021dc0a202d14.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/portal-ppid/polda/%5Bpolda-name%5D/layanan-informasi/registrasi-permohonan/page-e185c01ab21f4604.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/portal-ppid/polda/%5Bpolda-name%5D/layanan-informasi/statistik-rekapitulasi/page-9f78a73d3ea1caab.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/portal-ppid/polda/%5Bpolda-name%5D/page-1985f21ba61c17b5.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/portal-ppid/polda/%5Bpolda-name%5D/profile/layout-6f4bc2dafe7d9f11.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/portal-ppid/polda/%5Bpolda-name%5D/profile/profile-singkat-ppid/page-3861f3073b96fe4d.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/portal-ppid/polda/%5Bpolda-name%5D/profile/sejarah-ppid-polri/page-909678b881a22bf2.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/portal-ppid/polda/%5Bpolda-name%5D/profile/struktur-ppid/page-8ffd0f323f64d136.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/portal-ppid/polda/%5Bpolda-name%5D/profile/tugas-dan-fungsi-ppid/page-5ab5360c58e1d5a4.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/portal-ppid/polda/%5Bpolda-name%5D/profile/visi-dan-misi-ppid/page-0ebc379221a28f20.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/portal-ppid/polda/%5Bpolda-name%5D/regulasi/layout-6aeebc47d0beaff1.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/portal-ppid/polda/%5Bpolda-name%5D/regulasi/page-d817b62994750e4f.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/portal-ppid/polda/%5Bpolda-name%5D/standar-layanan/alur-pelayanan-informasi-publik/page-6765bb617a609da4.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/portal-ppid/polda/%5Bpolda-name%5D/standar-layanan/layout-5ef21f23ee1f0014.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/portal-ppid/polda/%5Bpolda-name%5D/standar-layanan/maklumat-pelayanan/page-b67cb1439e251b9b.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/portal-ppid/polda/%5Bpolda-name%5D/standar-layanan/mekanisme-keberatan/page-9115b78a0eff3504.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/portal-ppid/polda/%5Bpolda-name%5D/standar-layanan/mekanisme-permohonan-penyelesaian-sengketa/page-1723b4f00ac16995.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/portal-ppid/polda/%5Bpolda-name%5D/standar-layanan/standar-biaya-pelayanan/page-9fdd9423c1689454.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/portal-ppid/polda/%5Bpolda-name%5D/standar-layanan/tata-cara-permohonan-informasi/page-c4a042855fb38a4f.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/portal-ppid/polda/%5Bpolda-name%5D/standar-layanan/waktu-pelayanan/page-bc835b5c9e22ada8.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/portal-ppid/profile/layout-e27bd4f58156d187.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/portal-ppid/profile/profile-singkat-ppid/page-7643b299a93dfc8a.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/portal-ppid/profile/sejarah-ppid-polri/page-e7b6513aa6369539.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/portal-ppid/profile/struktur-ppid/page-a5fc837f2e584bb3.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/portal-ppid/profile/tugas-dan-fungsi-ppid/page-1223201ff5e61623.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/portal-ppid/profile/visi-dan-misi-ppid/page-83efc082daa1ec5a.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/portal-ppid/regulasi/layout-45b284fa0f100a34.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/portal-ppid/regulasi/page-374ace5f4daf86db.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/portal-ppid/satuan-kerja/%5Bsatker-name%5D/informasi-publik/informasi-berkala/page-b5edcfe4bf53b5a0.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/portal-ppid/satuan-kerja/%5Bsatker-name%5D/informasi-publik/informasi-dikecualikan/page-12b5642c61974c07.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/portal-ppid/satuan-kerja/%5Bsatker-name%5D/informasi-publik/informasi-serta-merta/page-23d1b61f761a1f42.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/portal-ppid/satuan-kerja/%5Bsatker-name%5D/informasi-publik/informasi-setiap-saat/page-71ead10b728459ad.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/portal-ppid/satuan-kerja/%5Bsatker-name%5D/informasi-publik/layout-989beddb520ce35a.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/portal-ppid/satuan-kerja/%5Bsatker-name%5D/informasi-publik/penerangan-satuan/page-95dc860947c2dd82.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/portal-ppid/satuan-kerja/%5Bsatker-name%5D/informasi-publik/uu-dan-peraturan/page-3168637501126870.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/portal-ppid/satuan-kerja/%5Bsatker-name%5D/layanan-informasi/layout-9c7e96c859537881.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/portal-ppid/satuan-kerja/%5Bsatker-name%5D/layanan-informasi/permohonan-informasi/page-e34a7146def5baeb.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/portal-ppid/satuan-kerja/%5Bsatker-name%5D/layanan-informasi/permohonan-keberatan/page-df5df81b7ebf7512.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/portal-ppid/satuan-kerja/%5Bsatker-name%5D/layanan-informasi/ppid-laporan-tahunan/page-28b109114357c8d3.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/portal-ppid/satuan-kerja/%5Bsatker-name%5D/layanan-informasi/registrasi-permohonan/page-5aae80183837beaf.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/portal-ppid/satuan-kerja/%5Bsatker-name%5D/layanan-informasi/statistik-rekapitulasi/page-db3bd4d9182be0a8.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/portal-ppid/satuan-kerja/%5Bsatker-name%5D/page-4004d3f242429c8f.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/portal-ppid/satuan-kerja/%5Bsatker-name%5D/profile/layout-84f11b4c2cd9638b.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/portal-ppid/satuan-kerja/%5Bsatker-name%5D/profile/profile-singkat-ppid/page-a5d4e919880ed85d.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/portal-ppid/satuan-kerja/%5Bsatker-name%5D/profile/sejarah-ppid-polri/page-14b09048f6b7ebdd.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/portal-ppid/satuan-kerja/%5Bsatker-name%5D/profile/struktur-ppid/page-9e5d883870682070.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/portal-ppid/satuan-kerja/%5Bsatker-name%5D/profile/tugas-dan-fungsi-ppid/page-7399074e0188fb60.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/portal-ppid/satuan-kerja/%5Bsatker-name%5D/profile/visi-dan-misi-ppid/page-433ef0e160b466d0.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/portal-ppid/satuan-kerja/%5Bsatker-name%5D/regulasi/layout-4a8c97166829a32e.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/portal-ppid/satuan-kerja/%5Bsatker-name%5D/regulasi/page-64a0ccff72e657f6.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/portal-ppid/satuan-kerja/%5Bsatker-name%5D/standar-layanan/alur-pelayanan-informasi-publik/page-89431ecc1607fa97.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/portal-ppid/satuan-kerja/%5Bsatker-name%5D/standar-layanan/layout-f0acc6accc36d6ee.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/portal-ppid/satuan-kerja/%5Bsatker-name%5D/standar-layanan/maklumat-pelayanan/page-702ce6b853a7b839.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/portal-ppid/satuan-kerja/%5Bsatker-name%5D/standar-layanan/mekanisme-keberatan/page-4e39ac76b14c24b2.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/portal-ppid/satuan-kerja/%5Bsatker-name%5D/standar-layanan/mekanisme-permohonan-penyelesaian-sengketa/page-32c900322ca7d6d1.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/portal-ppid/satuan-kerja/%5Bsatker-name%5D/standar-layanan/standar-biaya-pelayanan/page-d3e2c9c9e098c8bc.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/portal-ppid/satuan-kerja/%5Bsatker-name%5D/standar-layanan/tata-cara-permohonan-informasi/page-68b0858f5c95e7a8.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/portal-ppid/satuan-kerja/%5Bsatker-name%5D/standar-layanan/waktu-pelayanan/page-2f7b8f1f0df58bfb.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/portal-ppid/standar-layanan/alur-pelayanan-informasi-publik/page-5029934210212e79.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/portal-ppid/standar-layanan/layout-e0e5936c6bb1ea1c.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/portal-ppid/standar-layanan/maklumat-pelayanan/page-7404e7dcc30377a6.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/portal-ppid/standar-layanan/mekanisme-keberatan/page-7cf25f55065a5e9f.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/portal-ppid/standar-layanan/mekanisme-permohonan-penyelesaian-sengketa/page-46bcbecae2399b9d.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/portal-ppid/standar-layanan/standar-biaya-pelayanan/page-32ff48ba78b8c8e7.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/portal-ppid/standar-layanan/tata-cara-permohonan-informasi/page-93fb374a857dc484.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/portal-ppid/standar-layanan/waktu-pelayanan/page-87c7bb4b38f10105.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/pricing/layout-51607dd7ce664c92.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/pricing/page-622778e127e0f31a.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/profile-pimpinan-polri/layout-2f81845fd57501d5.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/profile-pimpinan-polri/page-461276b43917f624.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/setup-password/layout-c6124595dcb2246e.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/setup-password/page-662aade801973edf.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/static/%5Bslug%5D/page-0fa107abad485652.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/struktur-organisasi/layout-148760c51895c06d.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/struktur-organisasi/page-a1c21a338213c268.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/tentang-humas-polri/layout-e21a0137c3b9db31.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/tentang-humas-polri/page-0006ee4bc5afb9f7.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/tugas-dan-fungsi/layout-74b8beddcb338ce9.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/tugas-dan-fungsi/page-cbaecb806c572cfe.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/visi-misi/layout-12287eb2c9b5daf9.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/app/visi-misi/page-027434481f5ce241.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/f31aec94-9f1e849e045067f8.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/framework-82b67a6346ddd02b.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/main-a358af6d67b39e87.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/main-app-0dca047f62991613.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/pages/_app-331fa7297b2eb4f0.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/pages/_error-babe95910633c05f.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/chunks/polyfills-42372ed130431b0a.js",revision:"846118c33b2c0e922d7b3a7676f81f6f"},{url:"/_next/static/chunks/webpack-cd69874041244cc2.js",revision:"uJJSXLFzrTs-dIf7_MZgj"},{url:"/_next/static/css/5c4826c56b72a529.css",revision:"5c4826c56b72a529"},{url:"/_next/static/css/772f6661360af590.css",revision:"772f6661360af590"},{url:"/_next/static/css/a22d73fa394be2b9.css",revision:"a22d73fa394be2b9"},{url:"/_next/static/css/b3cbcd051438d1d5.css",revision:"b3cbcd051438d1d5"},{url:"/_next/static/media/26a46d62cd723877-s.woff2",revision:"befd9c0fdfa3d8a645d5f95717ed6420"},{url:"/_next/static/media/55c55f0601d81cf3-s.woff2",revision:"43828e14271c77b87e3ed582dbff9f74"},{url:"/_next/static/media/581909926a08bbc8-s.woff2",revision:"f0b86e7c24f455280b8df606b89af891"},{url:"/_next/static/media/6d93bde91c0c2823-s.woff2",revision:"621a07228c8ccbfd647918f1021b4868"},{url:"/_next/static/media/97e0cb1ae144a2a9-s.woff2",revision:"e360c61c5bd8d90639fd4503c829c2dc"},{url:"/_next/static/media/a34f9d1faa5f3315-s.p.woff2",revision:"d4fe31e6a2aebc06b8d6e558c9141119"},{url:"/_next/static/media/df0a9ae256c0569c-s.woff2",revision:"d54db44de5ccb18886ece2fda72bdfe0"},{url:"/_next/static/uJJSXLFzrTs-dIf7_MZgj/_buildManifest.js",revision:"b697efbe2bb26b151c499e0515221d0b"},{url:"/_next/static/uJJSXLFzrTs-dIf7_MZgj/_ssgManifest.js",revision:"b6652df95db52feb4daf4eca35380933"},{url:"/account-category.jpg",revision:"5e29b1e756c097d5bbe3181d0484c5bf"},{url:"/al.png",revision:"81cc7daf73f0b348c3c9d6e37b1b90d6"},{url:"/alurpelayanan.png",revision:"f616b4caea35c8daedaf89d6ba46298c"},{url:"/ar.png",revision:"ef0449eb09331311303e7783154be5ba"},{url:"/assets/Footer.jpg",revision:"d45785a5dda9dc8a6c08a55d321ba465"},{url:"/assets/inp.png",revision:"bf13d57d21d2b6d596712c96c1dbfe84"},{url:"/assets/mediahub.png",revision:"f0d85858c3a4f69c4e7b137d6c965855"},{url:"/assets/polda/internasional.png",revision:"af0804dfd5981f36dbd0dce60a6a866d"},{url:"/assets/polda/internasional.svg",revision:"9da802205c92d4e90598766e3c36e5aa"},{url:"/assets/polda/polda-aceh.png",revision:"bb8ad60de1947da282d7473c6397b9ac"},{url:"/assets/polda/polda-aceh.svg",revision:"bba0653c03089698990277edd2f48982"},{url:"/assets/polda/polda-babel.png",revision:"b4f927bf1950de46984f161ebad513a3"},{url:"/assets/polda/polda-babel.svg",revision:"dc04ef14a0a25c9f2f1a3621d7451984"},{url:"/assets/polda/polda-bali.png",revision:"79965bfd52355e35af13fb4cd17e99e0"},{url:"/assets/polda/polda-bali.svg",revision:"61ec06afc88f5c56549eac5533798faf"},{url:"/assets/polda/polda-banten.png",revision:"660f2c987d3e46a58f1db1fac6ee4bcb"},{url:"/assets/polda/polda-banten.svg",revision:"78e5796cba4bcddd59ef648f212623fb"},{url:"/assets/polda/polda-bengkulu.png",revision:"3e784d4919b02a2259cc901131da6f23"},{url:"/assets/polda/polda-bengkulu.svg",revision:"edca26eaf2ece327657fb85db8bd77e1"},{url:"/assets/polda/polda-diy.png",revision:"64a79096b1172326937eff04a357b974"},{url:"/assets/polda/polda-diy.svg",revision:"01da0536e582f1da4b0c783beaf6ef87"},{url:"/assets/polda/polda-gorontalo.png",revision:"bef074368b443ebecbbc28986bf40b81"},{url:"/assets/polda/polda-gorontalo.svg",revision:"b9215c0a9b4069d9b7c4f83302948162"},{url:"/assets/polda/polda-jabar.png",revision:"29bc0cb3c0efccf391b213bcdd27d5c9"},{url:"/assets/polda/polda-jambi.png",revision:"c21a8da961ccff36dcf7179fa1c93866"},{url:"/assets/polda/polda-jambi.svg",revision:"714a0472a98edaea128b72b3faf3f80c"},{url:"/assets/polda/polda-jateng.png",revision:"014aa1f3772f3050e405d00595528b1d"},{url:"/assets/polda/polda-jateng.svg",revision:"2e16451eb135efbd5b08961cae4f40e4"},{url:"/assets/polda/polda-jatim.png",revision:"92b1a2ac3a1026e0b8de667b8cf8656d"},{url:"/assets/polda/polda-jatim.svg",revision:"59fcab5bc60c699a94d15ea386544ee9"},{url:"/assets/polda/polda-jawa-barat.svg",revision:"25c412505ebe23e1acd1ceec030ccc9a"},{url:"/assets/polda/polda-kalbar.png",revision:"657fc135252ab08ee6ed94af6b362be4"},{url:"/assets/polda/polda-kalbar.svg",revision:"f5877252c602c948bd0c018c10aee73d"},{url:"/assets/polda/polda-kalsel.png",revision:"9dcd129d427740ab2b91c77e549e25bd"},{url:"/assets/polda/polda-kalsel.svg",revision:"fcd5d5dbc71b0a1285926025ee071681"},{url:"/assets/polda/polda-kalteng.png",revision:"64bd23e617d1bd2379b7fd50443b1b6e"},{url:"/assets/polda/polda-kalteng.svg",revision:"7e48ec234f8e34ad5b522951d1e4a333"},{url:"/assets/polda/polda-kaltim.png",revision:"51c79e6fe6093f2ba1f8a2da1905438b"},{url:"/assets/polda/polda-kaltim.svg",revision:"970cf727481e56666ba9ce2c25ff4229"},{url:"/assets/polda/polda-kalut.png",revision:"a645f46feb81e9456a71f1b996669d5b"},{url:"/assets/polda/polda-kalut.svg",revision:"fc45074e64e8bc5972e87763e778ad69"},{url:"/assets/polda/polda-kepri.png",revision:"b9492ea7ccad0ac483077b4b160d0397"},{url:"/assets/polda/polda-kepri.svg",revision:"eeda2dede34a17e4ee50408ab4e26656"},{url:"/assets/polda/polda-lampung.png",revision:"3864db82a37101d3fcd5e4f6d24d3055"},{url:"/assets/polda/polda-lampung.svg",revision:"d7fb562d088d6cd02fdfc487501c4c72"},{url:"/assets/polda/polda-maluku.png",revision:"bdf12dcec6bf960994b1a6e0869e1aeb"},{url:"/assets/polda/polda-maluku.svg",revision:"1c8b09a2ea9b6aa2e5cb2b1f5dd24604"},{url:"/assets/polda/polda-malut.png",revision:"8a0dfec942971a503e99f7bcbbd3ee8b"},{url:"/assets/polda/polda-malut.svg",revision:"ae261498646de15886a83b415e9e88e6"},{url:"/assets/polda/polda-metro-jaya.svg",revision:"a880a990fd069da997a377480bf175cf"},{url:"/assets/polda/polda-metro.png",revision:"821e930848751f01c0c3e54c49409007"},{url:"/assets/polda/polda-ntb.svg",revision:"d908acd5de63e95169566bb63753cd20"},{url:"/assets/polda/polda-ntt.svg",revision:"d116cd045f6ee2d0c1d559c945ec6786"},{url:"/assets/polda/polda-papua.svg",revision:"15ba811886c5b18b2524bc9de4652858"},{url:"/assets/polda/polda-papuabarat.svg",revision:"3a0cefabe9e64f89a6c5c97d151f29d6"},{url:"/assets/polda/polda-riau.svg",revision:"96ac568bd85c01887edcbfb35097f13b"},{url:"/assets/polda/polda-satker.jpeg",revision:"2ea80fdf8262506625a8befd316c5cce"},{url:"/assets/polda/polda-sulawesi-utara.svg",revision:"acc7cf908de5208f28ec9a5b08d5abe4"},{url:"/assets/polda/polda-sulbar.svg",revision:"4763190f58f15cb5c488a41604b6df57"},{url:"/assets/polda/polda-sulsel.svg",revision:"fa459c7a23be222fba636fe2bd71946f"},{url:"/assets/polda/polda-sulteng.svg",revision:"8715732d6dc9c4a525316e29c2449a81"},{url:"/assets/polda/polda-sultenggara.svg",revision:"91bd56741848316336b38830a30d1182"},{url:"/assets/polda/polda-sumbar.svg",revision:"1aca63246b9b06532fe99b855c9ab735"},{url:"/assets/polda/polda-sumsel.svg",revision:"f46f9cf67a4a5f66539887e733c20f7e"},{url:"/assets/polda/polda-sumut.svg",revision:"f574b83f165e28e50b59b7bb91dc805b"},{url:"/assets/polri-tv.png",revision:"7a109eb73163695521948c658265b8af"},{url:"/assets/portal-humas.png",revision:"e726f07697c23f18266fd7c2c2241e15"},{url:"/assets/satker/EPPID.png",revision:"bbe56cc08e81751cd13d5985bc4b88a2"},{url:"/assets/satker/EPPID2.png",revision:"fc9c21693eccb8197099bacf28439ca8"},{url:"/assets/satker/PERBAIKAN MULTIPOOL.docx",revision:"9d197afb07d596f3a5dcf4c499fec154"},{url:"/assets/satker/akpol.svg",revision:"be20db3e1336af59349e9d3e7f401cc4"},{url:"/assets/satker/baharkam.svg",revision:"4491efb751c7dbd6722cccf0cdf969d8"},{url:"/assets/satker/baharkam2.svg",revision:"c8d68318cecf09ff681434484466716c"},{url:"/assets/satker/baintelkam.svg",revision:"cdd17d249acc5dc8ea550f9480e7bf0d"},{url:"/assets/satker/bareskrim.svg",revision:"b638b1b7c31ac34a4c5f03307c47f9e6"},{url:"/assets/satker/binmas.svg",revision:"958bb67b37ae0e9fbafd1e8f26c0e44e"},{url:"/assets/satker/brimob.svg",revision:"037e0abc930f51d0eb73a09d04c097bb"},{url:"/assets/satker/densus.svg",revision:"9c963eb7725603ca5e5aa06d9ce09d08"},{url:"/assets/satker/div-humas.svg",revision:"fffac8127bbb40f0d0c84a7657487b92"},{url:"/assets/satker/divhubinter.svg",revision:"b119a54de293b2ea1e9ee5fb9a9d7c95"},{url:"/assets/satker/divkum.svg",revision:"f577943ebb9b4359706ca2d3efc8643b"},{url:"/assets/satker/divtik.svg",revision:"5355f8e46443ec0b603d351ca0015554"},{url:"/assets/satker/e-ppid.png",revision:"e2728bfd786fd23e8e20ce2e64a9fa15"},{url:"/assets/satker/itwasum.svg",revision:"238aba9526ce9c7abd9490701285c7f1"},{url:"/assets/satker/korlantas.svg",revision:"635cf67f74ffa1ce3e4e0be30301e7d3"},{url:"/assets/satker/lemdiklat.svg",revision:"cb9ee8bcde1d579ec033f991125d8a99"},{url:"/assets/satker/polair.svg",revision:"70a0a41de50a766aae77d31961e02d03"},{url:"/assets/satker/polairud.svg",revision:"1535803ea14cb88a86dfd6c259411b40"},{url:"/assets/satker/poludara.svg",revision:"8a89f04b3e626a3574278115817db42d"},{url:"/assets/satker/propam.svg",revision:"4492145e156aad64e1c60d5427f96ac8"},{url:"/assets/satker/pusdokkes.svg",revision:"8940ee817a4dbaf059a45dc468b7feeb"},{url:"/assets/satker/pusiknas.svg",revision:"cdbd249fbd553bef3dc5124290875264"},{url:"/assets/satker/pusinafis.svg",revision:"f761e6a1d87adc56b4bcfdd95cc00515"},{url:"/assets/satker/pusjarah.svg",revision:"767532e96af2da26605cb10789263203"},{url:"/assets/satker/puskeu.svg",revision:"f6ff453b7325da7637f36741f1204de1"},{url:"/assets/satker/puslabfor.svg",revision:"fde6be1abf846e1ab16e5c583838358d"},{url:"/assets/satker/puslitbang.svg",revision:"9d3f93d94b1fd41b3f2c892af96a24f4"},{url:"/assets/satker/sahli-kapolri.svg",revision:"5502316708ecee615fc77f45831f645e"},{url:"/assets/satker/sespim.svg",revision:"cc7a6c308b3881924fec0b8eae5ec7d0"},{url:"/assets/satker/setum.svg",revision:"f6a849a8a5d5a282d63627aaa07cdc70"},{url:"/assets/satker/setupa.svg",revision:"4448f26cdbcc690e3af4d6ff16163db6"},{url:"/assets/satker/siber - Copy.svg",revision:"c80d2af0bd2a320b2d0b8dc303551331"},{url:"/assets/satker/siber.svg",revision:"c80d2af0bd2a320b2d0b8dc303551331"},{url:"/assets/satker/slog.svg",revision:"92e88b14a70aa497e88df61f1fe3c48b"},{url:"/assets/satker/sops.svg",revision:"623c0b04fa5724e605f996dd803613a1"},{url:"/assets/satker/spripim.svg",revision:"0caa2c525296df0a2bc1e2b691700443"},{url:"/assets/satker/srena.png",revision:"e8d74548c5a1f962e0032f3513e5551e"},{url:"/assets/satker/srena.svg",revision:"dad70d747c0b44bf77819c2b304bb040"},{url:"/assets/satker/ssdm.png",revision:"6f9584537f77ff464c8657097ad35a57"},{url:"/assets/satker/ssdm.svg",revision:"268786c0130761f4ae0235ea9cfa23c6"},{url:"/assets/satker/stik-ptik.png",revision:"e018e3c68b25d6e078ae8d0331fd7e31"},{url:"/assets/satker/stik-ptik.svg",revision:"275b26bf6425bcd1f614caeea3b9e892"},{url:"/assets/satker/yanma.png",revision:"3a8403758db81e47e2507e133bdbcabb"},{url:"/assets/satker2/akpol.svg",revision:"69fb211b8ee5f37dab00c04f34b6bebc"},{url:"/assets/satker2/baharkam.svg",revision:"be5f80a045d3cdd004de78da595f119f"},{url:"/assets/satker2/baintelkam.svg",revision:"114042dc8c505e844f2313f33613d13e"},{url:"/assets/satker2/bareskrim.svg",revision:"d08f1013aef81885346e5a4c2f39fce0"},{url:"/assets/satker2/binmas.svg",revision:"2c0d66e5ec1ec75249679763027bae08"},{url:"/assets/satker2/brimob.svg",revision:"f8d6fa6049f17f296b652a85cc9f0a4b"},{url:"/assets/satker2/densus88.svg",revision:"dc6d2b2abc449de83b8aa20fe75bef38"},{url:"/assets/satker2/divkum.svg",revision:"f7ce8bd67f86d0c4be84cbe41014d880"},{url:"/assets/satker2/divtik.svg",revision:"4a15c634ca717591d4664ac75d1aa501"},{url:"/assets/satker2/hubinter.svg",revision:"71708e9c2f56a23483c763118bab0450"},{url:"/assets/satker2/humas.svg",revision:"b7fe8715e9b37505d938c15a943d2b22"},{url:"/assets/satker2/itwasum.svg",revision:"05c64a364b2601d872712f2bbce9abd9"},{url:"/assets/satker2/korlantas.svg",revision:"1704e5b9e9cf8acfadcf4518c27bc99a"},{url:"/assets/satker2/lemdiklat.svg",revision:"4385d96c3f8c49dd2e10ff2c9f4c95a6"},{url:"/assets/satker2/polair.svg",revision:"c913c1b39b5b7dfd3a8cd809e5347584"},{url:"/assets/satker2/polairud.svg",revision:"d17c116b133533b2bb8bdae6a8f07ec7"},{url:"/assets/satker2/poludara.svg",revision:"c470a11ce0a3f374aea4cb19f06920eb"},{url:"/assets/satker2/propam.svg",revision:"800265d1bb845ff998dc17257b902a44"},{url:"/assets/satker2/pusdokes.svg",revision:"a1b325a81e592d05c081272fb9e155ee"},{url:"/assets/satker2/pusiknas.svg",revision:"dbf82265352d498b61718c10bee5c189"},{url:"/assets/satker2/pusinafis.svg",revision:"0beb9510d163c63e51fbe8af17e5a0f8"},{url:"/assets/satker2/pusjarah.svg",revision:"ae23812613cb7f1ce04e87de6b21af55"},{url:"/assets/satker2/puskeu.svg",revision:"3e5a085740ce2ca42c9939d6db69359d"},{url:"/assets/satker2/puslabfor.svg",revision:"4befd2b6864a69f3860fdb585867d9ed"},{url:"/assets/satker2/puslitbang.svg",revision:"4f968362ecb2be0cae20d87262c82a3b"},{url:"/assets/satker2/sabbaharkam.svg",revision:"a5a46f5ef2a454a34e8a1497cac6ff34"},{url:"/assets/satker2/sahlikapolri.svg",revision:"4eac27da3bb5ecc71fb8b56e63a1fce9"},{url:"/assets/satker2/sespim.svg",revision:"a021bd890ab8a575604263c7431f8dc9"},{url:"/assets/satker2/setum.svg",revision:"56c68867d13fe8a049ceee72b42b6a33"},{url:"/assets/satker2/setupa.svg",revision:"c142c72f2613b33f3519c3033e163c9e"},{url:"/assets/satker2/siber.svg",revision:"9608e4928cd3537cbaff59cc23c40c97"},{url:"/assets/satker2/slog.svg",revision:"90100dbed17233a122c8691bb00e4054"},{url:"/assets/satker2/sops.svg",revision:"013b8f2ed7e820ee0dedd625a44e3605"},{url:"/assets/satker2/spripim.svg",revision:"c30de613933baa2c7cd6b066947403fc"},{url:"/assets/satker2/srena.svg",revision:"2d9d16cc3dce906b44ea78dcb3b0cb4b"},{url:"/assets/satker2/ssdm.svg",revision:"b536c5d283c0650a991c3c93f3d0fdbd"},{url:"/assets/satker2/stik-ptik.svg",revision:"d39d88459e7c5f9cfda65613b7417b62"},{url:"/assets/satker2/yanma-icon.png",revision:"6593e95ef643cce23e28c6d601f557a9"},{url:"/assets/satker2/yanma.png",revision:"3a8403758db81e47e2507e133bdbcabb"},{url:"/assets/spit-blackline.png",revision:"0f80fec8bb0bd871c93e47d9826cc8d3"},{url:"/assets/spit.png",revision:"7884a29e197310ac608fb09ed392ac0a"},{url:"/assets/tb-news.png",revision:"be05ac2e178179b68dec23774cf997e3"},{url:"/at1.png",revision:"9ad70b556e247157facc09cb84d1a817"},{url:"/at10.png",revision:"869278a9f49b389fe2611fbb22a5f432"},{url:"/at11.png",revision:"281386a794e429d64fa932bd5b801330"},{url:"/at12.png",revision:"c3f2af47756bc2d5aa9fab48272a9ad7"},{url:"/at13.png",revision:"566532a09ab8143dbad94620708fd63a"},{url:"/at14.png",revision:"b6a3a2c05a06e423300e17a3a828ac41"},{url:"/at15.png",revision:"7ac07d69b46e8366c6f38103d04f4ec7"},{url:"/at16.png",revision:"69fea9e34c9773d815832c755f3b9f61"},{url:"/at17.png",revision:"30345b3523de46d5a44c6c212b92a3f5"},{url:"/at18.png",revision:"b8f99c692440319b8515e8a84e733090"},{url:"/at19.png",revision:"7593a20f1a91644e0340664b450b32f5"},{url:"/at2.png",revision:"9d50d3c23a06d6678d3e181d1f3babde"},{url:"/at3.png",revision:"6e0136312bf510d6fe8bdb9223be343f"},{url:"/at4.png",revision:"27a1cf3af5c08c302232780975cbd9a4"},{url:"/at5.png",revision:"fd56e35f9ba704fb5f8a32d42547b3c8"},{url:"/at6.png",revision:"0815a4ed56bae4567e7ccb5010f11d79"},{url:"/at7.png",revision:"94d4aaa4b781881cae7c49de73d8c1c3"},{url:"/at8.png",revision:"ba5bab715ba201ac128dca6d31359a9a"},{url:"/at9.png",revision:"c32d9b3b5e2dd78997e2d66bcbe91820"},{url:"/banner-ppid.png",revision:"a6bed0cf12904f93432d90cd2047661f"},{url:"/bannerppid.png",revision:"adf6a2492bd890f3320086696f40dfc1"},{url:"/bg1.jpg",revision:"e51dd6bd67533e4497137082c82772c0"},{url:"/bg2.jpg",revision:"fcc9c4084cb7575e7a0e3c90e931a0e7"},{url:"/biaya-pelayanan.png",revision:"4579a0b52dd23e69922dfe5611084adf"},{url:"/detail.png",revision:"892d37f3e21dcd285053e38bf9cd1b5b"},{url:"/detailmabes.png",revision:"9f02cdddea95f515b097637181603037"},{url:"/divhumas.png",revision:"8600bd1f7f0ee7ef3c381e4df4eeb63b"},{url:"/e-library.png",revision:"03586d5ce06724c4ac738617ac769416"},{url:"/e-ppid-permohonan-informasi.png",revision:"6f6ae2db4be59a73a45fcaf74ee86eda"},{url:"/e-ppid-polda.png",revision:"a96012db5163be8d9f1951b2bc8c8598"},{url:"/e-ppid-satker.png",revision:"719a81cdd3cbd11260e27bd1991d0fe9"},{url:"/e-ppid.png",revision:"e2728bfd786fd23e8e20ce2e64a9fa15"},{url:"/eksternal1.png",revision:"6b5fbe042379f1a8bd22646797151e90"},{url:"/eksternal2.png",revision:"2651795fd4e2128daf8043e16fecaa15"},{url:"/eksternal3.png",revision:"680f1504bfd7a12c4acdf7980da176cd"},{url:"/eksternal4.png",revision:"bfddefd4972e9b44e93158d378072b6f"},{url:"/eksternal5.png",revision:"d9edaa25bcd8dc510d3484e12155f5af"},{url:"/emagazine.jpeg",revision:"0f94ec8df811d18a1831a5cac8d8ba5d"},{url:"/favicon.ico",revision:"c30c7d42707a47a3f4591831641e50dc"},{url:"/fb.png",revision:"8132117b90ca09e03a3543ed1b88569b"},{url:"/files.png",revision:"bdbb48d2c6d4c85cfc75736ae0487744"},{url:"/footer.png",revision:"8f78ca504b5444d51c45312d673ea1b4"},{url:"/gprfooter.png",revision:"332bee5e304a41a9fb8085aebdf0a779"},{url:"/gprheader.png",revision:"e236449c9cf00e073e0be705da6c2cd9"},{url:"/headerbanner1.png",revision:"46e748c2fc5030831637db3672061c53"},{url:"/headerbannerpng.png",revision:"ff84a0df289a617105144a74c28862fd"},{url:"/headernews.png",revision:"0a6385216dba022f0be05783b079eba1"},{url:"/humas.png",revision:"c4827432bb20ebd315ddf7ce7b82dcfc"},{url:"/humas1.png",revision:"7a2f157b1ca795d90165ea502999464c"},{url:"/humas2.png",revision:"9eb026c09fc34f128251b88eaff5a0c2"},{url:"/humas3.png",revision:"477f7bf72d564d9b6a451b016c469724"},{url:"/humas4.png",revision:"6089278388de30560a73443b79a3c09e"},{url:"/humas5.png",revision:"bb344899623979a52419f26baf40fbc8"},{url:"/image404.png",revision:"459473d57a01295e6c02290787dfb906"},{url:"/indonesia-map.png",revision:"6352f6ebae7498e56f1fd79f69efe1ed"},{url:"/infopublik1.png",revision:"56c0e086da796797ba070a16cf8baaa9"},{url:"/infopublik2.png",revision:"2dc348da6841221a8d67008eb3437aa9"},{url:"/infopublik3.png",revision:"b9c6f2994fefbcbe968dc1b26bfb14e1"},{url:"/infopublik4.png",revision:"481c437fca1d8e306391bcbd1cb07af7"},{url:"/infopublik5.png",revision:"cb35551974802816c8bc42f489119ad4"},{url:"/infopublik6.png",revision:"940ec717ecd955f67b95227c9b355c2d"},{url:"/infopublik8.png",revision:"ca91304b348f5eecf705ff1d2bb37496"},{url:"/informasipublik7.png",revision:"95a9f8ef9804e890591bbbabeb9c4915"},{url:"/kadiv-humas.png",revision:"f74d450ab3548670eb123527ef9ccfad"},{url:"/kapolri.png",revision:"d4f38d62e89f743cd40f82a22d3e5331"},{url:"/keberatan.png",revision:"0015cd73c7b58af883cb582243a5a5ab"},{url:"/kritik-saran.png",revision:"1893c7b1250fc3c489c91eb08f76a75e"},{url:"/landing-1.jpg",revision:"02e5e2904b5836f48d746703f4fff00b"},{url:"/landing-2.jpg",revision:"8b81957abe6c8e08c4047111396e5ba6"},{url:"/landing-3.jpg",revision:"ce4d8349a40554abc9e44173255e768d"},{url:"/landing-4.jpg",revision:"41b3b59d085bd9f4c5409a485bd54a8b"},{url:"/landing-bos.png",revision:"31e4e15d939316877474a53d11d94da2"},{url:"/landing-dumas-presisi.png",revision:"80ced3a64b4630cc2bce571e652c6d3b"},{url:"/landing-e-avis.png",revision:"a29403cb094577fdeac887de20f86161"},{url:"/landing-e-ppsi.png",revision:"c14bedadc47fcaf6b4481173444990bb"},{url:"/landing-e-rikkes.png",revision:"7bbb00aa022eb8b96800c3e42e658380"},{url:"/landing-inp.png",revision:"eb991de3ad7c682fbe315a94b2b92816"},{url:"/landing-mediahub-polri.png",revision:"6f46aa4dfbee3b3605157f00171c45d1"},{url:"/landing-polisiku.png",revision:"ab0bcb34e3b2d98660d4fa35578f0de4"},{url:"/landing-polri-super-apps.png",revision:"11bc6cb9870d56d187d47bc211c9bf3b"},{url:"/landing-polri-tv.png",revision:"60a72c95a779cd5063f7c06797ffd360"},{url:"/landing-portal-humas.png",revision:"cde9aea714314155bec74b294fa325ee"},{url:"/landing-propam-presisi.png",revision:"4a5600d6b3b77171053cda55cd679e51"},{url:"/landing-sdm-polri.png",revision:"b44af759ea43a60938fd6d57817356b0"},{url:"/landing-signal.png",revision:"d204669a2c05b64e9fc1906b20e86644"},{url:"/landing-sinar.png",revision:"e3c13abe2ece1481034bc9204ccaff31"},{url:"/landing-skck.png",revision:"1da1eed6a7d2827306832d60bfdae355"},{url:"/landing-wbs.png",revision:"0822faacccbcdaa73b29dec08bd73955"},{url:"/lapor.png",revision:"f1b71750e5ec760e7c84d10348d7e1f5"},{url:"/linkedin.png",revision:"552ea2d5e251bb5dd28b4682e98c5b8f"},{url:"/login.png",revision:"01b1b42cb1c6deef6d2d139aaf533356"},{url:"/logo1.png",revision:"27a1cf3af5c08c302232780975cbd9a4"},{url:"/logohumas.ico",revision:"bbe5aa006591736e5561ada062866bee"},{url:"/logohumas.png",revision:"bbe5aa006591736e5561ada062866bee"},{url:"/logosatker.svg",revision:"d87932994a30a87ad9d540fb38a50a0b"},{url:"/mabes.png",revision:"ff619a19766bee4cd7006d5df8858d6c"},{url:"/manifest.json",revision:"9a9a2335befeb66876c00b493be17c81"},{url:"/maps.png",revision:"dde21653ca6ffba919523dc6af88a22a"},{url:"/mekanisme-keberatan.png",revision:"0b44169f9b81fbc110171d2c1e7f5459"},{url:"/news1.png",revision:"5d090e9e2a7fb49856563126bea739f7"},{url:"/news2.png",revision:"fa973c8d52e388f27def717e49bd90cb"},{url:"/news3.png",revision:"81b4ac5a941989cd5058cbfdf21745bc"},{url:"/news4.png",revision:"81b4ac5a941989cd5058cbfdf21745bc"},{url:"/news5.png",revision:"03cd8647544f04affcd327c55f65e771"},{url:"/news6.png",revision:"b55400a34053fbf6013d5f8d2f0ce9e5"},{url:"/news7.png",revision:"58fc6d0a9ae47b0fd484d17a6742811b"},{url:"/next.svg",revision:"8e061864f388b47f33a1c3780831193e"},{url:"/no-image.jpg",revision:"ae6dd4fa8eb7c9ddb11f686075038ec4"},{url:"/pelayanan-informasi-publik.png",revision:"524f1d53a2617b7493cfe4111c96aa16"},{url:"/pengaduan.png",revision:"d611a02b0ded8a9abf456da0d948aa10"},{url:"/permintaan-informasi.png",revision:"e11d907e0bbb7d97becd0c978ea6c4ea"},{url:"/pm10.png",revision:"30345b3523de46d5a44c6c212b92a3f5"},{url:"/pm11.png",revision:"869278a9f49b389fe2611fbb22a5f432"},{url:"/pm12.png",revision:"b8f99c692440319b8515e8a84e733090"},{url:"/pm2.png",revision:"87040ca405e752336c3565346f62f17e"},{url:"/pm3.png",revision:"7593a20f1a91644e0340664b450b32f5"},{url:"/pm4.png",revision:"ba5bab715ba201ac128dca6d31359a9a"},{url:"/pm5.png",revision:"c32d9b3b5e2dd78997e2d66bcbe91820"},{url:"/pm6.png",revision:"94d4aaa4b781881cae7c49de73d8c1c3"},{url:"/pm7.png",revision:"9a31fa774f5d96a15145159d203e9d81"},{url:"/pm8.png",revision:"c3f2af47756bc2d5aa9fab48272a9ad7"},{url:"/pm9.png",revision:"566532a09ab8143dbad94620708fd63a"},{url:"/polda.png",revision:"e57bcc71da6a9177160bca2556aa3da6"},{url:"/polres.png",revision:"de49ca6b86d34b67cf2713e005f06f75"},{url:"/polsek.png",revision:"4d2a1dc38947b76f70e801ad1cc64cb7"},{url:"/portal-humas.png",revision:"e2e1b889f8211f9b0019bb87eddb10a4"},{url:"/portal-humas1.png",revision:"c3012d126e8eb6b9cc888c52e5ddad1d"},{url:"/ppid-polri.png",revision:"b841aba7478e6463381ddb408bcbb1ba"},{url:"/presisi.png",revision:"bb83874bf3bdb16adc808ef555ded4e4"},{url:"/publikasi1.png",revision:"7af47d4d7032518abe581d187542f3ee"},{url:"/publikasi2.png",revision:"0a0b619f9ab6731858e0ba1402394668"},{url:"/publikasi3.png",revision:"f4be98796a72b0f675838c31bf6e10b3"},{url:"/publikasi4.png",revision:"5ee9526286aead8be265e3f8eeb10bd8"},{url:"/publikasi5.png",revision:"3753046a33fefeab330dda28a921d77d"},{url:"/publikasi6.png",revision:"6f773007262830ef28ecb2893e4c94d1"},{url:"/publikasi7.png",revision:"a7ed0a93e30b30fe6c90226730d0ff7e"},{url:"/publikasi8.png",revision:"03586d5ce06724c4ac738617ac769416"},{url:"/publikasi9.png",revision:"6f773007262830ef28ecb2893e4c94d1"},{url:"/qudoco.png",revision:"c9456ca197317545f5ddf58b87246f17"},{url:"/relatedNews.png",revision:"cf08047d81e96e1be74d887580f72355"},{url:"/sample-banner-2.png",revision:"47f065d7653158b7c61f33c8caeb8d90"},{url:"/sample-banner-3.jpg",revision:"a29ce2fd513969f8949d74847fac9a64"},{url:"/sample-banner.png",revision:"8dedec0f59d10731f3718e802a0a8686"},{url:"/satker.png",revision:"cc7a691c60855c8b00d198302f96d1de"},{url:"/sengketa1.png",revision:"372d42b45da85319f80496e5ab857ca5"},{url:"/sengketa2.png",revision:"f95d8105dac8fbc458284c2e2151c844"},{url:"/sengketa3.png",revision:"be3dcef567bc00dc159c73767447e074"},{url:"/sengketa4.png",revision:"03e2f03558c16dae6984252217036ac1"},{url:"/sertifikat-1.png",revision:"6dbe2cbab6bb6da2a3ffe6ff1e7dba1a"},{url:"/sertifikat.png",revision:"497f7cea9dcd9105cc1fb25e5f855949"},{url:"/service-time.png",revision:"f35cb2b78ebf0a196ae717c3b57ad4cb"},{url:"/sp2h.png",revision:"86875e37a1dda6aa82fbe7a4b12a1b48"},{url:"/spark.png",revision:"ac7cbbafd5da00fd8041f23b983c0ea4"},{url:"/sparklg.png",revision:"1efd7e905ed6f7160c75ab4d9856a21b"},{url:"/struktur-humas.png",revision:"16ff9c7f78b42d5bfde7d6904a8baec6"},{url:"/survey.png",revision:"2abb403ec56d0dc2b0cfd470d75930f9"},{url:"/tata-cara-permohonan-informasi.png",revision:"3b96c49e0f07c981bb18f7eaf081467c"},{url:"/temp/ar.svg",revision:"81c1c878f4fb318b1a9c98e32372e9a8"},{url:"/temp/arright.svg",revision:"dc78fda9706066341d2a816fdecc1495"},{url:"/temp/arrleft.svg",revision:"6bff33d4772b59e0fe61f50c07af78e5"},{url:"/temp/calender.svg",revision:"7cca0928737dd3641d5b77ef30bf5ce7"},{url:"/temp/checklist.svg",revision:"a02f3e32f4eea2671f3f22f02bdd3b11"},{url:"/temp/cs.svg",revision:"d7b449845aaabb0a747cb0fde3b52d33"},{url:"/temp/emagazine.png",revision:"9327de5c39438841142219431ae6261e"},{url:"/temp/eyeicon.svg",revision:"031ee3be1815bb0e12944005a612b0d7"},{url:"/temp/ficon.svg",revision:"a8b6299a1eac436682f86d7d556fd749"},{url:"/temp/foot.png",revision:"c03d8f428de91468277deaebf26867dd"},{url:"/temp/footer-desc.png",revision:"11d7593c3f285b4d3688ecffc421d417"},{url:"/temp/footer.jpeg",revision:"f243bdb8094aa8c94332d2ac449b4ea4"},{url:"/temp/headerbannerpng.png",revision:"ff84a0df289a617105144a74c28862fd"},{url:"/temp/hotline.svg",revision:"d7b449845aaabb0a747cb0fde3b52d33"},{url:"/temp/iconFB.svg",revision:"c13c6f2ed37538afc5c84b1f53a2ab53"},{url:"/temp/iconIG.svg",revision:"4ac44bc6fbb50af93f9db490c494e716"},{url:"/temp/iconX.svg",revision:"5ab17cffa8986eb90738d20a183872dd"},{url:"/temp/idnicon.svg",revision:"0132670a286538d9455e1d151bb26423"},{url:"/temp/igicon.svg",revision:"4c00dcc14c02688319050e064f09f8cb"},{url:"/temp/loc.svg",revision:"c9436a96b665cce6b3e95940967d7533"},{url:"/temp/mail.svg",revision:"4f06405708fb2c8537d7f78f9eb664e5"},{url:"/temp/mediahub1.png",revision:"2f428f5e1f3326e1ec2b8e6d01b12ed3"},{url:"/temp/mediahub2.png",revision:"679e874fcf1cdd508a25a0e97ef8a97e"},{url:"/temp/offical.svg",revision:"46817949173fecbd705e22b2308d7a3c"},{url:"/temp/panel.png",revision:"a4c0a19d4fca1d711fe7eea7c4eab206"},{url:"/temp/polda-banten.svg",revision:"e31c1eca98fd874fe379663b7868127e"},{url:"/temp/polda-jateng.svg",revision:"5e4fe32a6c711f93af61540355ed230d"},{url:"/temp/polda-jatim.svg",revision:"33f709f9685e10c9e1f5ee380fb32eaf"},{url:"/temp/polda-sumut.svg",revision:"7dfa8540a9e926b76f6786726081a3c4"},{url:"/temp/poldametro.svg",revision:"e591d71423b891a3bf7b6e5b16f8edd5"},{url:"/temp/send.svg",revision:"7e4e9794a06ecd2509f698da7015c86f"},{url:"/temp/share.svg",revision:"8038eb665c9c1efda7ead67923853ca6"},{url:"/temp/statistik.png",revision:"dda95503c9cd7ede71d05f21e5d53c10"},{url:"/temp/statistik2.png",revision:"b4f4e474fd887b8a186e3c7a4d1f583c"},{url:"/temp/tiktok.svg",revision:"9c726ca4415246466fddc12abeaceca9"},{url:"/temp/tticon.svg",revision:"5c2c73c31fdf0dc0ff133ebab10b6378"},{url:"/temp/underline.svg",revision:"2a4d6cad4651409f766f824f8b1b5553"},{url:"/temp/word.svg",revision:"58a211367ab2548557a7cd76921bf352"},{url:"/temp/yticon.svg",revision:"f60ddec2a03d2a4207e8c95386210419"},{url:"/tribrata.png",revision:"50d39346c49e1b98bc759aa1ebf9fea9"},{url:"/twitter.png",revision:"880f10daafb95905b476ffdc5b0a1011"},{url:"/vercel.svg",revision:"61c6b19abff40ea7acd577be818f3976"},{url:"/wa.png",revision:"6b148170d2ee288c79152ee26f9c1062"}],{ignoreURLParametersMatching:[]}),a.cleanupOutdatedCaches(),a.registerRoute("/",new a.NetworkFirst({cacheName:"start-url",plugins:[{cacheWillUpdate:async({request:a,response:e,event:s,state:i})=>e&&"opaqueredirect"===e.type?new Response(e.body,{status:200,statusText:"OK",headers:e.headers}):e}]}),"GET"),a.registerRoute(/^https:\/\/fonts\.(?:gstatic)\.com\/.*/i,new a.CacheFirst({cacheName:"google-fonts-webfonts",plugins:[new a.ExpirationPlugin({maxEntries:4,maxAgeSeconds:31536e3})]}),"GET"),a.registerRoute(/^https:\/\/fonts\.(?:googleapis)\.com\/.*/i,new a.StaleWhileRevalidate({cacheName:"google-fonts-stylesheets",plugins:[new a.ExpirationPlugin({maxEntries:4,maxAgeSeconds:604800})]}),"GET"),a.registerRoute(/\.(?:eot|otf|ttc|ttf|woff|woff2|font.css)$/i,new a.StaleWhileRevalidate({cacheName:"static-font-assets",plugins:[new a.ExpirationPlugin({maxEntries:4,maxAgeSeconds:604800})]}),"GET"),a.registerRoute(/\.(?:jpg|jpeg|gif|png|svg|ico|webp)$/i,new a.StaleWhileRevalidate({cacheName:"static-image-assets",plugins:[new a.ExpirationPlugin({maxEntries:64,maxAgeSeconds:86400})]}),"GET"),a.registerRoute(/\/_next\/image\?url=.+$/i,new a.StaleWhileRevalidate({cacheName:"next-image",plugins:[new a.ExpirationPlugin({maxEntries:64,maxAgeSeconds:86400})]}),"GET"),a.registerRoute(/\.(?:mp3|wav|ogg)$/i,new a.CacheFirst({cacheName:"static-audio-assets",plugins:[new a.RangeRequestsPlugin,new a.ExpirationPlugin({maxEntries:32,maxAgeSeconds:86400})]}),"GET"),a.registerRoute(/\.(?:mp4)$/i,new a.CacheFirst({cacheName:"static-video-assets",plugins:[new a.RangeRequestsPlugin,new a.ExpirationPlugin({maxEntries:32,maxAgeSeconds:86400})]}),"GET"),a.registerRoute(/\.(?:js)$/i,new a.StaleWhileRevalidate({cacheName:"static-js-assets",plugins:[new a.ExpirationPlugin({maxEntries:32,maxAgeSeconds:86400})]}),"GET"),a.registerRoute(/\.(?:css|less)$/i,new a.StaleWhileRevalidate({cacheName:"static-style-assets",plugins:[new a.ExpirationPlugin({maxEntries:32,maxAgeSeconds:86400})]}),"GET"),a.registerRoute(/\/_next\/data\/.+\/.+\.json$/i,new a.StaleWhileRevalidate({cacheName:"next-data",plugins:[new a.ExpirationPlugin({maxEntries:32,maxAgeSeconds:86400})]}),"GET"),a.registerRoute(/\.(?:json|xml|csv)$/i,new a.NetworkFirst({cacheName:"static-data-assets",plugins:[new a.ExpirationPlugin({maxEntries:32,maxAgeSeconds:86400})]}),"GET"),a.registerRoute((({url:a})=>{if(!(self.origin===a.origin))return!1;const e=a.pathname;return!e.startsWith("/api/auth/")&&!!e.startsWith("/api/")}),new a.NetworkFirst({cacheName:"apis",networkTimeoutSeconds:10,plugins:[new a.ExpirationPlugin({maxEntries:16,maxAgeSeconds:86400})]}),"GET"),a.registerRoute((({url:a})=>{if(!(self.origin===a.origin))return!1;return!a.pathname.startsWith("/api/")}),new a.NetworkFirst({cacheName:"others",networkTimeoutSeconds:10,plugins:[new a.ExpirationPlugin({maxEntries:32,maxAgeSeconds:86400})]}),"GET"),a.registerRoute((({url:a})=>!(self.origin===a.origin)),new a.NetworkFirst({cacheName:"cross-origin",networkTimeoutSeconds:10,plugins:[new a.ExpirationPlugin({maxEntries:32,maxAgeSeconds:3600})]}),"GET")})); +/** + * Copyright 2018 Google Inc. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// If the loader is already loaded, just stop. +if (!self.define) { + let registry = {}; + + // Used for `eval` and `importScripts` where we can't get script URL by other means. + // In both cases, it's safe to use a global var because those functions are synchronous. + let nextDefineUri; + + const singleRequire = (uri, parentUri) => { + uri = new URL(uri + ".js", parentUri).href; + return registry[uri] || ( + + new Promise(resolve => { + if ("document" in self) { + const script = document.createElement("script"); + script.src = uri; + script.onload = resolve; + document.head.appendChild(script); + } else { + nextDefineUri = uri; + importScripts(uri); + resolve(); + } + }) + + .then(() => { + let promise = registry[uri]; + if (!promise) { + throw new Error(`Module ${uri} didn’t register its module`); + } + return promise; + }) + ); + }; + + self.define = (depsNames, factory) => { + const uri = nextDefineUri || ("document" in self ? document.currentScript.src : "") || location.href; + if (registry[uri]) { + // Module is already loading or loaded. + return; + } + let exports = {}; + const require = depUri => singleRequire(depUri, uri); + const specialDeps = { + module: { uri }, + exports, + require + }; + registry[uri] = Promise.all(depsNames.map( + depName => specialDeps[depName] || require(depName) + )).then(deps => { + factory(...deps); + return exports; + }); + }; +} +define(['./workbox-e43f5367'], (function (workbox) { 'use strict'; + + importScripts(); + self.skipWaiting(); + workbox.clientsClaim(); + workbox.registerRoute("/", new workbox.NetworkFirst({ + "cacheName": "start-url", + plugins: [{ + cacheWillUpdate: async ({ + request, + response, + event, + state + }) => { + if (response && response.type === 'opaqueredirect') { + return new Response(response.body, { + status: 200, + statusText: 'OK', + headers: response.headers + }); + } + return response; + } + }] + }), 'GET'); + workbox.registerRoute(/.*/i, new workbox.NetworkOnly({ + "cacheName": "dev", + plugins: [] + }), 'GET'); + +})); diff --git a/public/workbox-4754cb34.js b/public/workbox-4754cb34.js deleted file mode 100644 index 5cd8247..0000000 --- a/public/workbox-4754cb34.js +++ /dev/null @@ -1 +0,0 @@ -define(["exports"],(function(t){"use strict";try{self["workbox:core:6.5.4"]&&_()}catch(t){}const e=(t,...e)=>{let s=t;return e.length>0&&(s+=` :: ${JSON.stringify(e)}`),s};class s extends Error{constructor(t,s){super(e(t,s)),this.name=t,this.details=s}}try{self["workbox:routing:6.5.4"]&&_()}catch(t){}const n=t=>t&&"object"==typeof t?t:{handle:t};class r{constructor(t,e,s="GET"){this.handler=n(e),this.match=t,this.method=s}setCatchHandler(t){this.catchHandler=n(t)}}class i extends r{constructor(t,e,s){super((({url:e})=>{const s=t.exec(e.href);if(s&&(e.origin===location.origin||0===s.index))return s.slice(1)}),e,s)}}class a{constructor(){this.t=new Map,this.i=new Map}get routes(){return this.t}addFetchListener(){self.addEventListener("fetch",(t=>{const{request:e}=t,s=this.handleRequest({request:e,event:t});s&&t.respondWith(s)}))}addCacheListener(){self.addEventListener("message",(t=>{if(t.data&&"CACHE_URLS"===t.data.type){const{payload:e}=t.data,s=Promise.all(e.urlsToCache.map((e=>{"string"==typeof e&&(e=[e]);const s=new Request(...e);return this.handleRequest({request:s,event:t})})));t.waitUntil(s),t.ports&&t.ports[0]&&s.then((()=>t.ports[0].postMessage(!0)))}}))}handleRequest({request:t,event:e}){const s=new URL(t.url,location.href);if(!s.protocol.startsWith("http"))return;const n=s.origin===location.origin,{params:r,route:i}=this.findMatchingRoute({event:e,request:t,sameOrigin:n,url:s});let a=i&&i.handler;const o=t.method;if(!a&&this.i.has(o)&&(a=this.i.get(o)),!a)return;let c;try{c=a.handle({url:s,request:t,event:e,params:r})}catch(t){c=Promise.reject(t)}const h=i&&i.catchHandler;return c instanceof Promise&&(this.o||h)&&(c=c.catch((async n=>{if(h)try{return await h.handle({url:s,request:t,event:e,params:r})}catch(t){t instanceof Error&&(n=t)}if(this.o)return this.o.handle({url:s,request:t,event:e});throw n}))),c}findMatchingRoute({url:t,sameOrigin:e,request:s,event:n}){const r=this.t.get(s.method)||[];for(const i of r){let r;const a=i.match({url:t,sameOrigin:e,request:s,event:n});if(a)return r=a,(Array.isArray(r)&&0===r.length||a.constructor===Object&&0===Object.keys(a).length||"boolean"==typeof a)&&(r=void 0),{route:i,params:r}}return{}}setDefaultHandler(t,e="GET"){this.i.set(e,n(t))}setCatchHandler(t){this.o=n(t)}registerRoute(t){this.t.has(t.method)||this.t.set(t.method,[]),this.t.get(t.method).push(t)}unregisterRoute(t){if(!this.t.has(t.method))throw new s("unregister-route-but-not-found-with-method",{method:t.method});const e=this.t.get(t.method).indexOf(t);if(!(e>-1))throw new s("unregister-route-route-not-registered");this.t.get(t.method).splice(e,1)}}let o;const c=()=>(o||(o=new a,o.addFetchListener(),o.addCacheListener()),o);function h(t,e,n){let a;if("string"==typeof t){const s=new URL(t,location.href);a=new r((({url:t})=>t.href===s.href),e,n)}else if(t instanceof RegExp)a=new i(t,e,n);else if("function"==typeof t)a=new r(t,e,n);else{if(!(t instanceof r))throw new s("unsupported-route-type",{moduleName:"workbox-routing",funcName:"registerRoute",paramName:"capture"});a=t}return c().registerRoute(a),a}try{self["workbox:strategies:6.5.4"]&&_()}catch(t){}const u={cacheWillUpdate:async({response:t})=>200===t.status||0===t.status?t:null},l={googleAnalytics:"googleAnalytics",precache:"precache-v2",prefix:"workbox",runtime:"runtime",suffix:"undefined"!=typeof registration?registration.scope:""},f=t=>[l.prefix,t,l.suffix].filter((t=>t&&t.length>0)).join("-"),w=t=>t||f(l.precache),d=t=>t||f(l.runtime);function p(t,e){const s=new URL(t);for(const t of e)s.searchParams.delete(t);return s.href}class y{constructor(){this.promise=new Promise(((t,e)=>{this.resolve=t,this.reject=e}))}}const g=new Set;function m(t){return"string"==typeof t?new Request(t):t}class v{constructor(t,e){this.h={},Object.assign(this,e),this.event=e.event,this.u=t,this.l=new y,this.p=[],this.m=[...t.plugins],this.v=new Map;for(const t of this.m)this.v.set(t,{});this.event.waitUntil(this.l.promise)}async fetch(t){const{event:e}=this;let n=m(t);if("navigate"===n.mode&&e instanceof FetchEvent&&e.preloadResponse){const t=await e.preloadResponse;if(t)return t}const r=this.hasCallback("fetchDidFail")?n.clone():null;try{for(const t of this.iterateCallbacks("requestWillFetch"))n=await t({request:n.clone(),event:e})}catch(t){if(t instanceof Error)throw new s("plugin-error-request-will-fetch",{thrownErrorMessage:t.message})}const i=n.clone();try{let t;t=await fetch(n,"navigate"===n.mode?void 0:this.u.fetchOptions);for(const s of this.iterateCallbacks("fetchDidSucceed"))t=await s({event:e,request:i,response:t});return t}catch(t){throw r&&await this.runCallbacks("fetchDidFail",{error:t,event:e,originalRequest:r.clone(),request:i.clone()}),t}}async fetchAndCachePut(t){const e=await this.fetch(t),s=e.clone();return this.waitUntil(this.cachePut(t,s)),e}async cacheMatch(t){const e=m(t);let s;const{cacheName:n,matchOptions:r}=this.u,i=await this.getCacheKey(e,"read"),a=Object.assign(Object.assign({},r),{cacheName:n});s=await caches.match(i,a);for(const t of this.iterateCallbacks("cachedResponseWillBeUsed"))s=await t({cacheName:n,matchOptions:r,cachedResponse:s,request:i,event:this.event})||void 0;return s}async cachePut(t,e){const n=m(t);var r;await(r=0,new Promise((t=>setTimeout(t,r))));const i=await this.getCacheKey(n,"write");if(!e)throw new s("cache-put-with-no-response",{url:(a=i.url,new URL(String(a),location.href).href.replace(new RegExp(`^${location.origin}`),""))});var a;const o=await this.R(e);if(!o)return!1;const{cacheName:c,matchOptions:h}=this.u,u=await self.caches.open(c),l=this.hasCallback("cacheDidUpdate"),f=l?await async function(t,e,s,n){const r=p(e.url,s);if(e.url===r)return t.match(e,n);const i=Object.assign(Object.assign({},n),{ignoreSearch:!0}),a=await t.keys(e,i);for(const e of a)if(r===p(e.url,s))return t.match(e,n)}(u,i.clone(),["__WB_REVISION__"],h):null;try{await u.put(i,l?o.clone():o)}catch(t){if(t instanceof Error)throw"QuotaExceededError"===t.name&&await async function(){for(const t of g)await t()}(),t}for(const t of this.iterateCallbacks("cacheDidUpdate"))await t({cacheName:c,oldResponse:f,newResponse:o.clone(),request:i,event:this.event});return!0}async getCacheKey(t,e){const s=`${t.url} | ${e}`;if(!this.h[s]){let n=t;for(const t of this.iterateCallbacks("cacheKeyWillBeUsed"))n=m(await t({mode:e,request:n,event:this.event,params:this.params}));this.h[s]=n}return this.h[s]}hasCallback(t){for(const e of this.u.plugins)if(t in e)return!0;return!1}async runCallbacks(t,e){for(const s of this.iterateCallbacks(t))await s(e)}*iterateCallbacks(t){for(const e of this.u.plugins)if("function"==typeof e[t]){const s=this.v.get(e),n=n=>{const r=Object.assign(Object.assign({},n),{state:s});return e[t](r)};yield n}}waitUntil(t){return this.p.push(t),t}async doneWaiting(){let t;for(;t=this.p.shift();)await t}destroy(){this.l.resolve(null)}async R(t){let e=t,s=!1;for(const t of this.iterateCallbacks("cacheWillUpdate"))if(e=await t({request:this.request,response:e,event:this.event})||void 0,s=!0,!e)break;return s||e&&200!==e.status&&(e=void 0),e}}class R{constructor(t={}){this.cacheName=d(t.cacheName),this.plugins=t.plugins||[],this.fetchOptions=t.fetchOptions,this.matchOptions=t.matchOptions}handle(t){const[e]=this.handleAll(t);return e}handleAll(t){t instanceof FetchEvent&&(t={event:t,request:t.request});const e=t.event,s="string"==typeof t.request?new Request(t.request):t.request,n="params"in t?t.params:void 0,r=new v(this,{event:e,request:s,params:n}),i=this.q(r,s,e);return[i,this.D(i,r,s,e)]}async q(t,e,n){let r;await t.runCallbacks("handlerWillStart",{event:n,request:e});try{if(r=await this.U(e,t),!r||"error"===r.type)throw new s("no-response",{url:e.url})}catch(s){if(s instanceof Error)for(const i of t.iterateCallbacks("handlerDidError"))if(r=await i({error:s,event:n,request:e}),r)break;if(!r)throw s}for(const s of t.iterateCallbacks("handlerWillRespond"))r=await s({event:n,request:e,response:r});return r}async D(t,e,s,n){let r,i;try{r=await t}catch(i){}try{await e.runCallbacks("handlerDidRespond",{event:n,request:s,response:r}),await e.doneWaiting()}catch(t){t instanceof Error&&(i=t)}if(await e.runCallbacks("handlerDidComplete",{event:n,request:s,response:r,error:i}),e.destroy(),i)throw i}}function b(t){t.then((()=>{}))}function q(){return q=Object.assign?Object.assign.bind():function(t){for(var e=1;e(t[e]=s,!0),has:(t,e)=>t instanceof IDBTransaction&&("done"===e||"store"===e)||e in t};function O(t){return t!==IDBDatabase.prototype.transaction||"objectStoreNames"in IDBTransaction.prototype?(U||(U=[IDBCursor.prototype.advance,IDBCursor.prototype.continue,IDBCursor.prototype.continuePrimaryKey])).includes(t)?function(...e){return t.apply(B(this),e),k(x.get(this))}:function(...e){return k(t.apply(B(this),e))}:function(e,...s){const n=t.call(B(this),e,...s);return I.set(n,e.sort?e.sort():[e]),k(n)}}function T(t){return"function"==typeof t?O(t):(t instanceof IDBTransaction&&function(t){if(L.has(t))return;const e=new Promise(((e,s)=>{const n=()=>{t.removeEventListener("complete",r),t.removeEventListener("error",i),t.removeEventListener("abort",i)},r=()=>{e(),n()},i=()=>{s(t.error||new DOMException("AbortError","AbortError")),n()};t.addEventListener("complete",r),t.addEventListener("error",i),t.addEventListener("abort",i)}));L.set(t,e)}(t),e=t,(D||(D=[IDBDatabase,IDBObjectStore,IDBIndex,IDBCursor,IDBTransaction])).some((t=>e instanceof t))?new Proxy(t,N):t);var e}function k(t){if(t instanceof IDBRequest)return function(t){const e=new Promise(((e,s)=>{const n=()=>{t.removeEventListener("success",r),t.removeEventListener("error",i)},r=()=>{e(k(t.result)),n()},i=()=>{s(t.error),n()};t.addEventListener("success",r),t.addEventListener("error",i)}));return e.then((e=>{e instanceof IDBCursor&&x.set(e,t)})).catch((()=>{})),E.set(e,t),e}(t);if(C.has(t))return C.get(t);const e=T(t);return e!==t&&(C.set(t,e),E.set(e,t)),e}const B=t=>E.get(t);const P=["get","getKey","getAll","getAllKeys","count"],M=["put","add","delete","clear"],W=new Map;function j(t,e){if(!(t instanceof IDBDatabase)||e in t||"string"!=typeof e)return;if(W.get(e))return W.get(e);const s=e.replace(/FromIndex$/,""),n=e!==s,r=M.includes(s);if(!(s in(n?IDBIndex:IDBObjectStore).prototype)||!r&&!P.includes(s))return;const i=async function(t,...e){const i=this.transaction(t,r?"readwrite":"readonly");let a=i.store;return n&&(a=a.index(e.shift())),(await Promise.all([a[s](...e),r&&i.done]))[0]};return W.set(e,i),i}N=(t=>q({},t,{get:(e,s,n)=>j(e,s)||t.get(e,s,n),has:(e,s)=>!!j(e,s)||t.has(e,s)}))(N);try{self["workbox:expiration:6.5.4"]&&_()}catch(t){}const S="cache-entries",K=t=>{const e=new URL(t,location.href);return e.hash="",e.href};class A{constructor(t){this._=null,this.L=t}I(t){const e=t.createObjectStore(S,{keyPath:"id"});e.createIndex("cacheName","cacheName",{unique:!1}),e.createIndex("timestamp","timestamp",{unique:!1})}C(t){this.I(t),this.L&&function(t,{blocked:e}={}){const s=indexedDB.deleteDatabase(t);e&&s.addEventListener("blocked",(t=>e(t.oldVersion,t))),k(s).then((()=>{}))}(this.L)}async setTimestamp(t,e){const s={url:t=K(t),timestamp:e,cacheName:this.L,id:this.N(t)},n=(await this.getDb()).transaction(S,"readwrite",{durability:"relaxed"});await n.store.put(s),await n.done}async getTimestamp(t){const e=await this.getDb(),s=await e.get(S,this.N(t));return null==s?void 0:s.timestamp}async expireEntries(t,e){const s=await this.getDb();let n=await s.transaction(S).store.index("timestamp").openCursor(null,"prev");const r=[];let i=0;for(;n;){const s=n.value;s.cacheName===this.L&&(t&&s.timestamp=e?r.push(n.value):i++),n=await n.continue()}const a=[];for(const t of r)await s.delete(S,t.id),a.push(t.url);return a}N(t){return this.L+"|"+K(t)}async getDb(){return this._||(this._=await function(t,e,{blocked:s,upgrade:n,blocking:r,terminated:i}={}){const a=indexedDB.open(t,e),o=k(a);return n&&a.addEventListener("upgradeneeded",(t=>{n(k(a.result),t.oldVersion,t.newVersion,k(a.transaction),t)})),s&&a.addEventListener("blocked",(t=>s(t.oldVersion,t.newVersion,t))),o.then((t=>{i&&t.addEventListener("close",(()=>i())),r&&t.addEventListener("versionchange",(t=>r(t.oldVersion,t.newVersion,t)))})).catch((()=>{})),o}("workbox-expiration",1,{upgrade:this.C.bind(this)})),this._}}class F{constructor(t,e={}){this.O=!1,this.T=!1,this.k=e.maxEntries,this.B=e.maxAgeSeconds,this.P=e.matchOptions,this.L=t,this.M=new A(t)}async expireEntries(){if(this.O)return void(this.T=!0);this.O=!0;const t=this.B?Date.now()-1e3*this.B:0,e=await this.M.expireEntries(t,this.k),s=await self.caches.open(this.L);for(const t of e)await s.delete(t,this.P);this.O=!1,this.T&&(this.T=!1,b(this.expireEntries()))}async updateTimestamp(t){await this.M.setTimestamp(t,Date.now())}async isURLExpired(t){if(this.B){const e=await this.M.getTimestamp(t),s=Date.now()-1e3*this.B;return void 0===e||er||e&&e<0)throw new s("range-not-satisfiable",{size:r,end:n,start:e});let i,a;return void 0!==e&&void 0!==n?(i=e,a=n+1):void 0!==e&&void 0===n?(i=e,a=r):void 0!==n&&void 0===e&&(i=r-n,a=r),{start:i,end:a}}(i,r.start,r.end),o=i.slice(a.start,a.end),c=o.size,h=new Response(o,{status:206,statusText:"Partial Content",headers:e.headers});return h.headers.set("Content-Length",String(c)),h.headers.set("Content-Range",`bytes ${a.start}-${a.end-1}/${i.size}`),h}catch(t){return new Response("",{status:416,statusText:"Range Not Satisfiable"})}}function $(t,e){const s=e();return t.waitUntil(s),s}try{self["workbox:precaching:6.5.4"]&&_()}catch(t){}function z(t){if(!t)throw new s("add-to-cache-list-unexpected-type",{entry:t});if("string"==typeof t){const e=new URL(t,location.href);return{cacheKey:e.href,url:e.href}}const{revision:e,url:n}=t;if(!n)throw new s("add-to-cache-list-unexpected-type",{entry:t});if(!e){const t=new URL(n,location.href);return{cacheKey:t.href,url:t.href}}const r=new URL(n,location.href),i=new URL(n,location.href);return r.searchParams.set("__WB_REVISION__",e),{cacheKey:r.href,url:i.href}}class G{constructor(){this.updatedURLs=[],this.notUpdatedURLs=[],this.handlerWillStart=async({request:t,state:e})=>{e&&(e.originalRequest=t)},this.cachedResponseWillBeUsed=async({event:t,state:e,cachedResponse:s})=>{if("install"===t.type&&e&&e.originalRequest&&e.originalRequest instanceof Request){const t=e.originalRequest.url;s?this.notUpdatedURLs.push(t):this.updatedURLs.push(t)}return s}}}class V{constructor({precacheController:t}){this.cacheKeyWillBeUsed=async({request:t,params:e})=>{const s=(null==e?void 0:e.cacheKey)||this.W.getCacheKeyForURL(t.url);return s?new Request(s,{headers:t.headers}):t},this.W=t}}let J,Q;async function X(t,e){let n=null;if(t.url){n=new URL(t.url).origin}if(n!==self.location.origin)throw new s("cross-origin-copy-response",{origin:n});const r=t.clone(),i={headers:new Headers(r.headers),status:r.status,statusText:r.statusText},a=e?e(i):i,o=function(){if(void 0===J){const t=new Response("");if("body"in t)try{new Response(t.body),J=!0}catch(t){J=!1}J=!1}return J}()?r.body:await r.blob();return new Response(o,a)}class Y extends R{constructor(t={}){t.cacheName=w(t.cacheName),super(t),this.j=!1!==t.fallbackToNetwork,this.plugins.push(Y.copyRedirectedCacheableResponsesPlugin)}async U(t,e){const s=await e.cacheMatch(t);return s||(e.event&&"install"===e.event.type?await this.S(t,e):await this.K(t,e))}async K(t,e){let n;const r=e.params||{};if(!this.j)throw new s("missing-precache-entry",{cacheName:this.cacheName,url:t.url});{const s=r.integrity,i=t.integrity,a=!i||i===s;n=await e.fetch(new Request(t,{integrity:"no-cors"!==t.mode?i||s:void 0})),s&&a&&"no-cors"!==t.mode&&(this.A(),await e.cachePut(t,n.clone()))}return n}async S(t,e){this.A();const n=await e.fetch(t);if(!await e.cachePut(t,n.clone()))throw new s("bad-precaching-response",{url:t.url,status:n.status});return n}A(){let t=null,e=0;for(const[s,n]of this.plugins.entries())n!==Y.copyRedirectedCacheableResponsesPlugin&&(n===Y.defaultPrecacheCacheabilityPlugin&&(t=s),n.cacheWillUpdate&&e++);0===e?this.plugins.push(Y.defaultPrecacheCacheabilityPlugin):e>1&&null!==t&&this.plugins.splice(t,1)}}Y.defaultPrecacheCacheabilityPlugin={cacheWillUpdate:async({response:t})=>!t||t.status>=400?null:t},Y.copyRedirectedCacheableResponsesPlugin={cacheWillUpdate:async({response:t})=>t.redirected?await X(t):t};class Z{constructor({cacheName:t,plugins:e=[],fallbackToNetwork:s=!0}={}){this.F=new Map,this.H=new Map,this.$=new Map,this.u=new Y({cacheName:w(t),plugins:[...e,new V({precacheController:this})],fallbackToNetwork:s}),this.install=this.install.bind(this),this.activate=this.activate.bind(this)}get strategy(){return this.u}precache(t){this.addToCacheList(t),this.G||(self.addEventListener("install",this.install),self.addEventListener("activate",this.activate),this.G=!0)}addToCacheList(t){const e=[];for(const n of t){"string"==typeof n?e.push(n):n&&void 0===n.revision&&e.push(n.url);const{cacheKey:t,url:r}=z(n),i="string"!=typeof n&&n.revision?"reload":"default";if(this.F.has(r)&&this.F.get(r)!==t)throw new s("add-to-cache-list-conflicting-entries",{firstEntry:this.F.get(r),secondEntry:t});if("string"!=typeof n&&n.integrity){if(this.$.has(t)&&this.$.get(t)!==n.integrity)throw new s("add-to-cache-list-conflicting-integrities",{url:r});this.$.set(t,n.integrity)}if(this.F.set(r,t),this.H.set(r,i),e.length>0){const t=`Workbox is precaching URLs without revision info: ${e.join(", ")}\nThis is generally NOT safe. Learn more at https://bit.ly/wb-precache`;console.warn(t)}}}install(t){return $(t,(async()=>{const e=new G;this.strategy.plugins.push(e);for(const[e,s]of this.F){const n=this.$.get(s),r=this.H.get(e),i=new Request(e,{integrity:n,cache:r,credentials:"same-origin"});await Promise.all(this.strategy.handleAll({params:{cacheKey:s},request:i,event:t}))}const{updatedURLs:s,notUpdatedURLs:n}=e;return{updatedURLs:s,notUpdatedURLs:n}}))}activate(t){return $(t,(async()=>{const t=await self.caches.open(this.strategy.cacheName),e=await t.keys(),s=new Set(this.F.values()),n=[];for(const r of e)s.has(r.url)||(await t.delete(r),n.push(r.url));return{deletedURLs:n}}))}getURLsToCacheKeys(){return this.F}getCachedURLs(){return[...this.F.keys()]}getCacheKeyForURL(t){const e=new URL(t,location.href);return this.F.get(e.href)}getIntegrityForCacheKey(t){return this.$.get(t)}async matchPrecache(t){const e=t instanceof Request?t.url:t,s=this.getCacheKeyForURL(e);if(s){return(await self.caches.open(this.strategy.cacheName)).match(s)}}createHandlerBoundToURL(t){const e=this.getCacheKeyForURL(t);if(!e)throw new s("non-precached-url",{url:t});return s=>(s.request=new Request(t),s.params=Object.assign({cacheKey:e},s.params),this.strategy.handle(s))}}const tt=()=>(Q||(Q=new Z),Q);class et extends r{constructor(t,e){super((({request:s})=>{const n=t.getURLsToCacheKeys();for(const r of function*(t,{ignoreURLParametersMatching:e=[/^utm_/,/^fbclid$/],directoryIndex:s="index.html",cleanURLs:n=!0,urlManipulation:r}={}){const i=new URL(t,location.href);i.hash="",yield i.href;const a=function(t,e=[]){for(const s of[...t.searchParams.keys()])e.some((t=>t.test(s)))&&t.searchParams.delete(s);return t}(i,e);if(yield a.href,s&&a.pathname.endsWith("/")){const t=new URL(a.href);t.pathname+=s,yield t.href}if(n){const t=new URL(a.href);t.pathname+=".html",yield t.href}if(r){const t=r({url:i});for(const e of t)yield e.href}}(s.url,e)){const e=n.get(r);if(e){return{cacheKey:e,integrity:t.getIntegrityForCacheKey(e)}}}}),t.strategy)}}t.CacheFirst=class extends R{async U(t,e){let n,r=await e.cacheMatch(t);if(!r)try{r=await e.fetchAndCachePut(t)}catch(t){t instanceof Error&&(n=t)}if(!r)throw new s("no-response",{url:t.url,error:n});return r}},t.ExpirationPlugin=class{constructor(t={}){this.cachedResponseWillBeUsed=async({event:t,request:e,cacheName:s,cachedResponse:n})=>{if(!n)return null;const r=this.V(n),i=this.J(s);b(i.expireEntries());const a=i.updateTimestamp(e.url);if(t)try{t.waitUntil(a)}catch(t){}return r?n:null},this.cacheDidUpdate=async({cacheName:t,request:e})=>{const s=this.J(t);await s.updateTimestamp(e.url),await s.expireEntries()},this.X=t,this.B=t.maxAgeSeconds,this.Y=new Map,t.purgeOnQuotaError&&function(t){g.add(t)}((()=>this.deleteCacheAndMetadata()))}J(t){if(t===d())throw new s("expire-custom-caches-only");let e=this.Y.get(t);return e||(e=new F(t,this.X),this.Y.set(t,e)),e}V(t){if(!this.B)return!0;const e=this.Z(t);if(null===e)return!0;return e>=Date.now()-1e3*this.B}Z(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 deleteCacheAndMetadata(){for(const[t,e]of this.Y)await self.caches.delete(t),await e.delete();this.Y=new Map}},t.NetworkFirst=class extends R{constructor(t={}){super(t),this.plugins.some((t=>"cacheWillUpdate"in t))||this.plugins.unshift(u),this.tt=t.networkTimeoutSeconds||0}async U(t,e){const n=[],r=[];let i;if(this.tt){const{id:s,promise:a}=this.et({request:t,logs:n,handler:e});i=s,r.push(a)}const a=this.st({timeoutId:i,request:t,logs:n,handler:e});r.push(a);const o=await e.waitUntil((async()=>await e.waitUntil(Promise.race(r))||await a)());if(!o)throw new s("no-response",{url:t.url});return o}et({request:t,logs:e,handler:s}){let n;return{promise:new Promise((e=>{n=setTimeout((async()=>{e(await s.cacheMatch(t))}),1e3*this.tt)})),id:n}}async st({timeoutId:t,request:e,logs:s,handler:n}){let r,i;try{i=await n.fetchAndCachePut(e)}catch(t){t instanceof Error&&(r=t)}return t&&clearTimeout(t),!r&&i||(i=await n.cacheMatch(e)),i}},t.RangeRequestsPlugin=class{constructor(){this.cachedResponseWillBeUsed=async({request:t,cachedResponse:e})=>e&&t.headers.has("range")?await H(t,e):e}},t.StaleWhileRevalidate=class extends R{constructor(t={}){super(t),this.plugins.some((t=>"cacheWillUpdate"in t))||this.plugins.unshift(u)}async U(t,e){const n=e.fetchAndCachePut(t).catch((()=>{}));e.waitUntil(n);let r,i=await e.cacheMatch(t);if(i);else try{i=await n}catch(t){t instanceof Error&&(r=t)}if(!i)throw new s("no-response",{url:t.url,error:r});return i}},t.cleanupOutdatedCaches=function(){self.addEventListener("activate",(t=>{const e=w();t.waitUntil((async(t,e="-precache-")=>{const s=(await self.caches.keys()).filter((s=>s.includes(e)&&s.includes(self.registration.scope)&&s!==t));return await Promise.all(s.map((t=>self.caches.delete(t)))),s})(e).then((t=>{})))}))},t.clientsClaim=function(){self.addEventListener("activate",(()=>self.clients.claim()))},t.precacheAndRoute=function(t,e){!function(t){tt().precache(t)}(t),function(t){const e=tt();h(new et(e,t))}(e)},t.registerRoute=h})); diff --git a/public/workbox-e43f5367.js b/public/workbox-e43f5367.js new file mode 100644 index 0000000..af939a8 --- /dev/null +++ b/public/workbox-e43f5367.js @@ -0,0 +1,2455 @@ +define(['exports'], (function (exports) { 'use strict'; + + // @ts-ignore + try { + self['workbox:core:6.5.4'] && _(); + } catch (e) {} + + /* + 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 = (() => { + // Don't overwrite this value if it's already set. + // See https://github.com/GoogleChrome/workbox/pull/2284#issuecomment-560470923 + if (!('__WB_DISABLE_DEV_LOGS' in globalThis)) { + self.__WB_DISABLE_DEV_LOGS = false; + } + let inGroup = false; + const methodToColorMap = { + debug: `#7f8c8d`, + log: `#2ecc71`, + warn: `#f39c12`, + error: `#c0392b`, + groupCollapsed: `#3498db`, + groupEnd: null // No colored prefix on groupEnd + }; + const print = function (method, args) { + if (self.__WB_DISABLE_DEV_LOGS) { + return; + } + 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; + } + }; + // eslint-disable-next-line @typescript-eslint/ban-types + const api = {}; + const loggerMethods = Object.keys(methodToColorMap); + for (const key of loggerMethods) { + const method = key; + api[method] = (...args) => { + print(method, args); + }; + } + return api; + })(); + + /* + 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 messages$1 = { + 'invalid-value': ({ + paramName, + validValueDescription, + value + }) => { + if (!paramName || !validValueDescription) { + throw new Error(`Unexpected input to 'invalid-value' error.`); + } + return `The '${paramName}' parameter was given a value with an ` + `unexpected value. ${validValueDescription} Received a value of ` + `${JSON.stringify(value)}.`; + }, + 'not-an-array': ({ + moduleName, + className, + funcName, + paramName + }) => { + if (!moduleName || !className || !funcName || !paramName) { + throw new Error(`Unexpected input to 'not-an-array' error.`); + } + return `The parameter '${paramName}' passed into ` + `'${moduleName}.${className}.${funcName}()' must be an array.`; + }, + 'incorrect-type': ({ + expectedType, + paramName, + moduleName, + className, + funcName + }) => { + if (!expectedType || !paramName || !moduleName || !funcName) { + throw new Error(`Unexpected input to 'incorrect-type' error.`); + } + const classNameStr = className ? `${className}.` : ''; + return `The parameter '${paramName}' passed into ` + `'${moduleName}.${classNameStr}` + `${funcName}()' must be of type ${expectedType}.`; + }, + 'incorrect-class': ({ + expectedClassName, + paramName, + moduleName, + className, + funcName, + isReturnValueProblem + }) => { + if (!expectedClassName || !moduleName || !funcName) { + throw new Error(`Unexpected input to 'incorrect-class' error.`); + } + const classNameStr = className ? `${className}.` : ''; + if (isReturnValueProblem) { + return `The return value from ` + `'${moduleName}.${classNameStr}${funcName}()' ` + `must be an instance of class ${expectedClassName}.`; + } + return `The parameter '${paramName}' passed into ` + `'${moduleName}.${classNameStr}${funcName}()' ` + `must be an instance of class ${expectedClassName}.`; + }, + 'missing-a-method': ({ + expectedMethod, + paramName, + moduleName, + className, + funcName + }) => { + if (!expectedMethod || !paramName || !moduleName || !className || !funcName) { + throw new Error(`Unexpected input to 'missing-a-method' error.`); + } + return `${moduleName}.${className}.${funcName}() expected the ` + `'${paramName}' parameter to expose a '${expectedMethod}' method.`; + }, + 'add-to-cache-list-unexpected-type': ({ + entry + }) => { + return `An unexpected entry was passed to ` + `'workbox-precaching.PrecacheController.addToCacheList()' The entry ` + `'${JSON.stringify(entry)}' isn't supported. You must supply an array of ` + `strings with one or more characters, objects with a url property or ` + `Request objects.`; + }, + 'add-to-cache-list-conflicting-entries': ({ + firstEntry, + secondEntry + }) => { + if (!firstEntry || !secondEntry) { + throw new Error(`Unexpected input to ` + `'add-to-cache-list-duplicate-entries' error.`); + } + return `Two of the entries passed to ` + `'workbox-precaching.PrecacheController.addToCacheList()' had the URL ` + `${firstEntry} but different revision details. Workbox is ` + `unable to cache and version the asset correctly. Please remove one ` + `of the entries.`; + }, + 'plugin-error-request-will-fetch': ({ + thrownErrorMessage + }) => { + if (!thrownErrorMessage) { + throw new Error(`Unexpected input to ` + `'plugin-error-request-will-fetch', error.`); + } + return `An error was thrown by a plugins 'requestWillFetch()' method. ` + `The thrown error message was: '${thrownErrorMessage}'.`; + }, + 'invalid-cache-name': ({ + cacheNameId, + value + }) => { + if (!cacheNameId) { + throw new Error(`Expected a 'cacheNameId' for error 'invalid-cache-name'`); + } + return `You must provide a name containing at least one character for ` + `setCacheDetails({${cacheNameId}: '...'}). Received a value of ` + `'${JSON.stringify(value)}'`; + }, + 'unregister-route-but-not-found-with-method': ({ + method + }) => { + if (!method) { + throw new Error(`Unexpected input to ` + `'unregister-route-but-not-found-with-method' error.`); + } + return `The route you're trying to unregister was not previously ` + `registered for the method type '${method}'.`; + }, + 'unregister-route-route-not-registered': () => { + return `The route you're trying to unregister was not previously ` + `registered.`; + }, + 'queue-replay-failed': ({ + name + }) => { + return `Replaying the background sync queue '${name}' failed.`; + }, + 'duplicate-queue-name': ({ + name + }) => { + return `The Queue name '${name}' is already being used. ` + `All instances of backgroundSync.Queue must be given unique names.`; + }, + 'expired-test-without-max-age': ({ + methodName, + paramName + }) => { + return `The '${methodName}()' method can only be used when the ` + `'${paramName}' is used in the constructor.`; + }, + 'unsupported-route-type': ({ + moduleName, + className, + funcName, + paramName + }) => { + return `The supplied '${paramName}' parameter was an unsupported type. ` + `Please check the docs for ${moduleName}.${className}.${funcName} for ` + `valid input types.`; + }, + 'not-array-of-class': ({ + value, + expectedClass, + moduleName, + className, + funcName, + paramName + }) => { + return `The supplied '${paramName}' parameter must be an array of ` + `'${expectedClass}' objects. Received '${JSON.stringify(value)},'. ` + `Please check the call to ${moduleName}.${className}.${funcName}() ` + `to fix the issue.`; + }, + 'max-entries-or-age-required': ({ + moduleName, + className, + funcName + }) => { + return `You must define either config.maxEntries or config.maxAgeSeconds` + `in ${moduleName}.${className}.${funcName}`; + }, + 'statuses-or-headers-required': ({ + moduleName, + className, + funcName + }) => { + return `You must define either config.statuses or config.headers` + `in ${moduleName}.${className}.${funcName}`; + }, + 'invalid-string': ({ + moduleName, + funcName, + paramName + }) => { + if (!paramName || !moduleName || !funcName) { + throw new Error(`Unexpected input to 'invalid-string' error.`); + } + return `When using strings, the '${paramName}' parameter must start with ` + `'http' (for cross-origin matches) or '/' (for same-origin matches). ` + `Please see the docs for ${moduleName}.${funcName}() for ` + `more info.`; + }, + 'channel-name-required': () => { + return `You must provide a channelName to construct a ` + `BroadcastCacheUpdate instance.`; + }, + 'invalid-responses-are-same-args': () => { + return `The arguments passed into responsesAreSame() appear to be ` + `invalid. Please ensure valid Responses are used.`; + }, + 'expire-custom-caches-only': () => { + return `You must provide a 'cacheName' property when using the ` + `expiration plugin with a runtime caching strategy.`; + }, + 'unit-must-be-bytes': ({ + normalizedRangeHeader + }) => { + if (!normalizedRangeHeader) { + throw new Error(`Unexpected input to 'unit-must-be-bytes' error.`); + } + return `The 'unit' portion of the Range header must be set to 'bytes'. ` + `The Range header provided was "${normalizedRangeHeader}"`; + }, + 'single-range-only': ({ + normalizedRangeHeader + }) => { + if (!normalizedRangeHeader) { + throw new Error(`Unexpected input to 'single-range-only' error.`); + } + return `Multiple ranges are not supported. Please use a single start ` + `value, and optional end value. The Range header provided was ` + `"${normalizedRangeHeader}"`; + }, + 'invalid-range-values': ({ + normalizedRangeHeader + }) => { + if (!normalizedRangeHeader) { + throw new Error(`Unexpected input to 'invalid-range-values' error.`); + } + return `The Range header is missing both start and end values. At least ` + `one of those values is needed. The Range header provided was ` + `"${normalizedRangeHeader}"`; + }, + 'no-range-header': () => { + return `No Range header was found in the Request provided.`; + }, + 'range-not-satisfiable': ({ + size, + start, + end + }) => { + return `The start (${start}) and end (${end}) values in the Range are ` + `not satisfiable by the cached response, which is ${size} bytes.`; + }, + 'attempt-to-cache-non-get-request': ({ + url, + method + }) => { + return `Unable to cache '${url}' because it is a '${method}' request and ` + `only 'GET' requests can be cached.`; + }, + 'cache-put-with-no-response': ({ + url + }) => { + return `There was an attempt to cache '${url}' but the response was not ` + `defined.`; + }, + 'no-response': ({ + url, + error + }) => { + let message = `The strategy could not generate a response for '${url}'.`; + if (error) { + message += ` The underlying error is ${error}.`; + } + return message; + }, + 'bad-precaching-response': ({ + url, + status + }) => { + return `The precaching request for '${url}' failed` + (status ? ` with an HTTP status of ${status}.` : `.`); + }, + 'non-precached-url': ({ + url + }) => { + return `createHandlerBoundToURL('${url}') was called, but that URL is ` + `not precached. Please pass in a URL that is precached instead.`; + }, + 'add-to-cache-list-conflicting-integrities': ({ + url + }) => { + return `Two of the entries passed to ` + `'workbox-precaching.PrecacheController.addToCacheList()' had the URL ` + `${url} with different integrity values. Please remove one of them.`; + }, + 'missing-precache-entry': ({ + cacheName, + url + }) => { + return `Unable to find a precached response in ${cacheName} for ${url}.`; + }, + 'cross-origin-copy-response': ({ + origin + }) => { + return `workbox-core.copyResponse() can only be used with same-origin ` + `responses. It was passed a response with origin ${origin}.`; + }, + 'opaque-streams-source': ({ + type + }) => { + const message = `One of the workbox-streams sources resulted in an ` + `'${type}' response.`; + if (type === 'opaqueredirect') { + return `${message} Please do not use a navigation request that results ` + `in a redirect as a source.`; + } + return `${message} Please ensure your sources are CORS-enabled.`; + } + }; + + /* + 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 generatorFunction = (code, details = {}) => { + const message = messages$1[code]; + if (!message) { + throw new Error(`Unable to find message for code '${code}'.`); + } + return message(details); + }; + const messageGenerator = generatorFunction; + + /* + 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. + */ + /** + * Workbox errors should be thrown with this class. + * This allows use to ensure the type easily in tests, + * helps developers identify errors from workbox + * easily and allows use to optimise error + * messages correctly. + * + * @private + */ + class WorkboxError extends Error { + /** + * + * @param {string} errorCode The error code that + * identifies this particular error. + * @param {Object=} details Any relevant arguments + * that will help developers identify issues should + * be added as a key on the context object. + */ + constructor(errorCode, details) { + const message = messageGenerator(errorCode, details); + super(message); + this.name = errorCode; + this.details = details; + } + } + + /* + 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 method throws if the supplied value is not an array. + * The destructed values are required to produce a meaningful error for users. + * The destructed and restructured object is so it's clear what is + * needed. + */ + const isArray = (value, details) => { + if (!Array.isArray(value)) { + throw new WorkboxError('not-an-array', details); + } + }; + const hasMethod = (object, expectedMethod, details) => { + const type = typeof object[expectedMethod]; + if (type !== 'function') { + details['expectedMethod'] = expectedMethod; + throw new WorkboxError('missing-a-method', details); + } + }; + const isType = (object, expectedType, details) => { + if (typeof object !== expectedType) { + details['expectedType'] = expectedType; + throw new WorkboxError('incorrect-type', details); + } + }; + const isInstance = (object, + // Need the general type to do the check later. + // eslint-disable-next-line @typescript-eslint/ban-types + expectedClass, details) => { + if (!(object instanceof expectedClass)) { + details['expectedClassName'] = expectedClass.name; + throw new WorkboxError('incorrect-class', details); + } + }; + const isOneOf = (value, validValues, details) => { + if (!validValues.includes(value)) { + details['validValueDescription'] = `Valid values are ${JSON.stringify(validValues)}.`; + throw new WorkboxError('invalid-value', details); + } + }; + const isArrayOfClass = (value, + // Need general type to do check later. + expectedClass, + // eslint-disable-line + details) => { + const error = new WorkboxError('not-array-of-class', details); + if (!Array.isArray(value)) { + throw error; + } + for (const item of value) { + if (!(item instanceof expectedClass)) { + throw error; + } + } + }; + const finalAssertExports = { + hasMethod, + isArray, + isInstance, + isOneOf, + isType, + isArrayOfClass + }; + + // @ts-ignore + try { + self['workbox:routing:6.5.4'] && _(); + } catch (e) {} + + /* + 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 default HTTP method, 'GET', used when there's no specific method + * configured for a route. + * + * @type {string} + * + * @private + */ + const defaultMethod = 'GET'; + /** + * The list of valid HTTP methods associated with requests that could be routed. + * + * @type {Array} + * + * @private + */ + const validMethods = ['DELETE', 'GET', 'HEAD', 'PATCH', 'POST', 'PUT']; + + /* + 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 {function()|Object} handler Either a function, or an object with a + * 'handle' method. + * @return {Object} An object with a handle method. + * + * @private + */ + const normalizeHandler = handler => { + if (handler && typeof handler === 'object') { + { + finalAssertExports.hasMethod(handler, 'handle', { + moduleName: 'workbox-routing', + className: 'Route', + funcName: 'constructor', + paramName: 'handler' + }); + } + return handler; + } else { + { + finalAssertExports.isType(handler, 'function', { + moduleName: 'workbox-routing', + className: 'Route', + funcName: 'constructor', + paramName: 'handler' + }); + } + return { + handle: handler + }; + } + }; + + /* + 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 `Route` consists of a pair of callback functions, "match" and "handler". + * The "match" callback determine if a route should be used to "handle" a + * request by returning a non-falsy value if it can. The "handler" callback + * is called when there is a match and should return a Promise that resolves + * to a `Response`. + * + * @memberof workbox-routing + */ + class Route { + /** + * Constructor for Route class. + * + * @param {workbox-routing~matchCallback} match + * A callback function that determines whether the route matches a given + * `fetch` event by returning a non-falsy value. + * @param {workbox-routing~handlerCallback} handler A callback + * function that returns a Promise resolving to a Response. + * @param {string} [method='GET'] The HTTP method to match the Route + * against. + */ + constructor(match, handler, method = defaultMethod) { + { + finalAssertExports.isType(match, 'function', { + moduleName: 'workbox-routing', + className: 'Route', + funcName: 'constructor', + paramName: 'match' + }); + if (method) { + finalAssertExports.isOneOf(method, validMethods, { + paramName: 'method' + }); + } + } + // These values are referenced directly by Router so cannot be + // altered by minificaton. + this.handler = normalizeHandler(handler); + this.match = match; + this.method = method; + } + /** + * + * @param {workbox-routing-handlerCallback} handler A callback + * function that returns a Promise resolving to a Response + */ + setCatchHandler(handler) { + this.catchHandler = normalizeHandler(handler); + } + } + + /* + 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. + */ + /** + * RegExpRoute makes it easy to create a regular expression based + * {@link workbox-routing.Route}. + * + * For same-origin requests the RegExp only needs to match part of the URL. For + * requests against third-party servers, you must define a RegExp that matches + * the start of the URL. + * + * @memberof workbox-routing + * @extends workbox-routing.Route + */ + class RegExpRoute extends Route { + /** + * If the regular expression contains + * [capture groups]{@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp#grouping-back-references}, + * the captured values will be passed to the + * {@link workbox-routing~handlerCallback} `params` + * argument. + * + * @param {RegExp} regExp The regular expression to match against URLs. + * @param {workbox-routing~handlerCallback} handler A callback + * function that returns a Promise resulting in a Response. + * @param {string} [method='GET'] The HTTP method to match the Route + * against. + */ + constructor(regExp, handler, method) { + { + finalAssertExports.isInstance(regExp, RegExp, { + moduleName: 'workbox-routing', + className: 'RegExpRoute', + funcName: 'constructor', + paramName: 'pattern' + }); + } + const match = ({ + url + }) => { + const result = regExp.exec(url.href); + // Return immediately if there's no match. + if (!result) { + return; + } + // Require that the match start at the first character in the URL string + // if it's a cross-origin request. + // See https://github.com/GoogleChrome/workbox/issues/281 for the context + // behind this behavior. + if (url.origin !== location.origin && result.index !== 0) { + { + logger.debug(`The regular expression '${regExp.toString()}' only partially matched ` + `against the cross-origin URL '${url.toString()}'. RegExpRoute's will only ` + `handle cross-origin requests if they match the entire URL.`); + } + return; + } + // If the route matches, but there aren't any capture groups defined, then + // this will return [], which is truthy and therefore sufficient to + // indicate a match. + // If there are capture groups, then it will return their values. + return result.slice(1); + }; + super(match, handler, method); + } + } + + /* + 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 getFriendlyURL = url => { + const urlObj = new URL(String(url), location.href); + // See https://github.com/GoogleChrome/workbox/issues/2323 + // We want to include everything, except for the origin if it's same-origin. + return urlObj.href.replace(new RegExp(`^${location.origin}`), ''); + }; + + /* + 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 Router can be used to process a `FetchEvent` using one or more + * {@link workbox-routing.Route}, responding with a `Response` if + * a matching route exists. + * + * If no route matches a given a request, the Router will use a "default" + * handler if one is defined. + * + * Should the matching Route throw an error, the Router will use a "catch" + * handler if one is defined to gracefully deal with issues and respond with a + * Request. + * + * If a request matches multiple routes, the **earliest** registered route will + * be used to respond to the request. + * + * @memberof workbox-routing + */ + class Router { + /** + * Initializes a new Router. + */ + constructor() { + this._routes = new Map(); + this._defaultHandlerMap = new Map(); + } + /** + * @return {Map>} routes A `Map` of HTTP + * method name ('GET', etc.) to an array of all the corresponding `Route` + * instances that are registered. + */ + get routes() { + return this._routes; + } + /** + * Adds a fetch event listener to respond to events when a route matches + * the event's request. + */ + addFetchListener() { + // See https://github.com/Microsoft/TypeScript/issues/28357#issuecomment-436484705 + self.addEventListener('fetch', event => { + const { + request + } = event; + const responsePromise = this.handleRequest({ + request, + event + }); + if (responsePromise) { + event.respondWith(responsePromise); + } + }); + } + /** + * Adds a message event listener for URLs to cache from the window. + * This is useful to cache resources loaded on the page prior to when the + * service worker started controlling it. + * + * The format of the message data sent from the window should be as follows. + * Where the `urlsToCache` array may consist of URL strings or an array of + * URL string + `requestInit` object (the same as you'd pass to `fetch()`). + * + * ``` + * { + * type: 'CACHE_URLS', + * payload: { + * urlsToCache: [ + * './script1.js', + * './script2.js', + * ['./script3.js', {mode: 'no-cors'}], + * ], + * }, + * } + * ``` + */ + addCacheListener() { + // See https://github.com/Microsoft/TypeScript/issues/28357#issuecomment-436484705 + self.addEventListener('message', event => { + // event.data is type 'any' + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access + if (event.data && event.data.type === 'CACHE_URLS') { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + const { + payload + } = event.data; + { + logger.debug(`Caching URLs from the window`, payload.urlsToCache); + } + const requestPromises = Promise.all(payload.urlsToCache.map(entry => { + if (typeof entry === 'string') { + entry = [entry]; + } + const request = new Request(...entry); + return this.handleRequest({ + request, + event + }); + // TODO(philipwalton): TypeScript errors without this typecast for + // some reason (probably a bug). The real type here should work but + // doesn't: `Array | undefined>`. + })); // TypeScript + event.waitUntil(requestPromises); + // If a MessageChannel was used, reply to the message on success. + if (event.ports && event.ports[0]) { + void requestPromises.then(() => event.ports[0].postMessage(true)); + } + } + }); + } + /** + * Apply the routing rules to a FetchEvent object to get a Response from an + * appropriate Route's handler. + * + * @param {Object} options + * @param {Request} options.request The request to handle. + * @param {ExtendableEvent} options.event The event that triggered the + * request. + * @return {Promise|undefined} A promise is returned if a + * registered route can handle the request. If there is no matching + * route and there's no `defaultHandler`, `undefined` is returned. + */ + handleRequest({ + request, + event + }) { + { + finalAssertExports.isInstance(request, Request, { + moduleName: 'workbox-routing', + className: 'Router', + funcName: 'handleRequest', + paramName: 'options.request' + }); + } + const url = new URL(request.url, location.href); + if (!url.protocol.startsWith('http')) { + { + logger.debug(`Workbox Router only supports URLs that start with 'http'.`); + } + return; + } + const sameOrigin = url.origin === location.origin; + const { + params, + route + } = this.findMatchingRoute({ + event, + request, + sameOrigin, + url + }); + let handler = route && route.handler; + const debugMessages = []; + { + if (handler) { + debugMessages.push([`Found a route to handle this request:`, route]); + if (params) { + debugMessages.push([`Passing the following params to the route's handler:`, params]); + } + } + } + // If we don't have a handler because there was no matching route, then + // fall back to defaultHandler if that's defined. + const method = request.method; + if (!handler && this._defaultHandlerMap.has(method)) { + { + debugMessages.push(`Failed to find a matching route. Falling ` + `back to the default handler for ${method}.`); + } + handler = this._defaultHandlerMap.get(method); + } + if (!handler) { + { + // No handler so Workbox will do nothing. If logs is set of debug + // i.e. verbose, we should print out this information. + logger.debug(`No route found for: ${getFriendlyURL(url)}`); + } + return; + } + { + // We have a handler, meaning Workbox is going to handle the route. + // print the routing details to the console. + logger.groupCollapsed(`Router is responding to: ${getFriendlyURL(url)}`); + debugMessages.forEach(msg => { + if (Array.isArray(msg)) { + logger.log(...msg); + } else { + logger.log(msg); + } + }); + logger.groupEnd(); + } + // Wrap in try and catch in case the handle method throws a synchronous + // error. It should still callback to the catch handler. + let responsePromise; + try { + responsePromise = handler.handle({ + url, + request, + event, + params + }); + } catch (err) { + responsePromise = Promise.reject(err); + } + // Get route's catch handler, if it exists + const catchHandler = route && route.catchHandler; + if (responsePromise instanceof Promise && (this._catchHandler || catchHandler)) { + responsePromise = responsePromise.catch(async err => { + // If there's a route catch handler, process that first + if (catchHandler) { + { + // Still include URL here as it will be async from the console group + // and may not make sense without the URL + logger.groupCollapsed(`Error thrown when responding to: ` + ` ${getFriendlyURL(url)}. Falling back to route's Catch Handler.`); + logger.error(`Error thrown by:`, route); + logger.error(err); + logger.groupEnd(); + } + try { + return await catchHandler.handle({ + url, + request, + event, + params + }); + } catch (catchErr) { + if (catchErr instanceof Error) { + err = catchErr; + } + } + } + if (this._catchHandler) { + { + // Still include URL here as it will be async from the console group + // and may not make sense without the URL + logger.groupCollapsed(`Error thrown when responding to: ` + ` ${getFriendlyURL(url)}. Falling back to global Catch Handler.`); + logger.error(`Error thrown by:`, route); + logger.error(err); + logger.groupEnd(); + } + return this._catchHandler.handle({ + url, + request, + event + }); + } + throw err; + }); + } + return responsePromise; + } + /** + * Checks a request and URL (and optionally an event) against the list of + * registered routes, and if there's a match, returns the corresponding + * route along with any params generated by the match. + * + * @param {Object} options + * @param {URL} options.url + * @param {boolean} options.sameOrigin The result of comparing `url.origin` + * against the current origin. + * @param {Request} options.request The request to match. + * @param {Event} options.event The corresponding event. + * @return {Object} An object with `route` and `params` properties. + * They are populated if a matching route was found or `undefined` + * otherwise. + */ + findMatchingRoute({ + url, + sameOrigin, + request, + event + }) { + const routes = this._routes.get(request.method) || []; + for (const route of routes) { + let params; + // route.match returns type any, not possible to change right now. + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + const matchResult = route.match({ + url, + sameOrigin, + request, + event + }); + if (matchResult) { + { + // Warn developers that using an async matchCallback is almost always + // not the right thing to do. + if (matchResult instanceof Promise) { + logger.warn(`While routing ${getFriendlyURL(url)}, an async ` + `matchCallback function was used. Please convert the ` + `following route to use a synchronous matchCallback function:`, route); + } + } + // See https://github.com/GoogleChrome/workbox/issues/2079 + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + params = matchResult; + if (Array.isArray(params) && params.length === 0) { + // Instead of passing an empty array in as params, use undefined. + params = undefined; + } else if (matchResult.constructor === Object && + // eslint-disable-line + Object.keys(matchResult).length === 0) { + // Instead of passing an empty object in as params, use undefined. + params = undefined; + } else if (typeof matchResult === 'boolean') { + // For the boolean value true (rather than just something truth-y), + // don't set params. + // See https://github.com/GoogleChrome/workbox/pull/2134#issuecomment-513924353 + params = undefined; + } + // Return early if have a match. + return { + route, + params + }; + } + } + // If no match was found above, return and empty object. + return {}; + } + /** + * Define a default `handler` that's called when no routes explicitly + * match the incoming request. + * + * Each HTTP method ('GET', 'POST', etc.) gets its own default handler. + * + * Without a default handler, unmatched requests will go against the + * network as if there were no service worker present. + * + * @param {workbox-routing~handlerCallback} handler A callback + * function that returns a Promise resulting in a Response. + * @param {string} [method='GET'] The HTTP method to associate with this + * default handler. Each method has its own default. + */ + setDefaultHandler(handler, method = defaultMethod) { + this._defaultHandlerMap.set(method, normalizeHandler(handler)); + } + /** + * If a Route throws an error while handling a request, this `handler` + * will be called and given a chance to provide a response. + * + * @param {workbox-routing~handlerCallback} handler A callback + * function that returns a Promise resulting in a Response. + */ + setCatchHandler(handler) { + this._catchHandler = normalizeHandler(handler); + } + /** + * Registers a route with the router. + * + * @param {workbox-routing.Route} route The route to register. + */ + registerRoute(route) { + { + finalAssertExports.isType(route, 'object', { + moduleName: 'workbox-routing', + className: 'Router', + funcName: 'registerRoute', + paramName: 'route' + }); + finalAssertExports.hasMethod(route, 'match', { + moduleName: 'workbox-routing', + className: 'Router', + funcName: 'registerRoute', + paramName: 'route' + }); + finalAssertExports.isType(route.handler, 'object', { + moduleName: 'workbox-routing', + className: 'Router', + funcName: 'registerRoute', + paramName: 'route' + }); + finalAssertExports.hasMethod(route.handler, 'handle', { + moduleName: 'workbox-routing', + className: 'Router', + funcName: 'registerRoute', + paramName: 'route.handler' + }); + finalAssertExports.isType(route.method, 'string', { + moduleName: 'workbox-routing', + className: 'Router', + funcName: 'registerRoute', + paramName: 'route.method' + }); + } + if (!this._routes.has(route.method)) { + this._routes.set(route.method, []); + } + // Give precedence to all of the earlier routes by adding this additional + // route to the end of the array. + this._routes.get(route.method).push(route); + } + /** + * Unregisters a route with the router. + * + * @param {workbox-routing.Route} route The route to unregister. + */ + unregisterRoute(route) { + if (!this._routes.has(route.method)) { + throw new WorkboxError('unregister-route-but-not-found-with-method', { + method: route.method + }); + } + const routeIndex = this._routes.get(route.method).indexOf(route); + if (routeIndex > -1) { + this._routes.get(route.method).splice(routeIndex, 1); + } else { + throw new WorkboxError('unregister-route-route-not-registered'); + } + } + } + + /* + 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 defaultRouter; + /** + * Creates a new, singleton Router instance if one does not exist. If one + * does already exist, that instance is returned. + * + * @private + * @return {Router} + */ + const getOrCreateDefaultRouter = () => { + if (!defaultRouter) { + defaultRouter = new Router(); + // The helpers that use the default Router assume these listeners exist. + defaultRouter.addFetchListener(); + defaultRouter.addCacheListener(); + } + return defaultRouter; + }; + + /* + 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. + */ + /** + * Easily register a RegExp, string, or function with a caching + * strategy to a singleton Router instance. + * + * This method will generate a Route for you if needed and + * call {@link workbox-routing.Router#registerRoute}. + * + * @param {RegExp|string|workbox-routing.Route~matchCallback|workbox-routing.Route} capture + * If the capture param is a `Route`, all other arguments will be ignored. + * @param {workbox-routing~handlerCallback} [handler] A callback + * function that returns a Promise resulting in a Response. This parameter + * is required if `capture` is not a `Route` object. + * @param {string} [method='GET'] The HTTP method to match the Route + * against. + * @return {workbox-routing.Route} The generated `Route`. + * + * @memberof workbox-routing + */ + function registerRoute(capture, handler, method) { + let route; + if (typeof capture === 'string') { + const captureUrl = new URL(capture, location.href); + { + if (!(capture.startsWith('/') || capture.startsWith('http'))) { + throw new WorkboxError('invalid-string', { + moduleName: 'workbox-routing', + funcName: 'registerRoute', + paramName: 'capture' + }); + } + // We want to check if Express-style wildcards are in the pathname only. + // TODO: Remove this log message in v4. + const valueToCheck = capture.startsWith('http') ? captureUrl.pathname : capture; + // See https://github.com/pillarjs/path-to-regexp#parameters + const wildcards = '[*:?+]'; + if (new RegExp(`${wildcards}`).exec(valueToCheck)) { + logger.debug(`The '$capture' parameter contains an Express-style wildcard ` + `character (${wildcards}). Strings are now always interpreted as ` + `exact matches; use a RegExp for partial or wildcard matches.`); + } + } + const matchCallback = ({ + url + }) => { + { + if (url.pathname === captureUrl.pathname && url.origin !== captureUrl.origin) { + logger.debug(`${capture} only partially matches the cross-origin URL ` + `${url.toString()}. This route will only handle cross-origin requests ` + `if they match the entire URL.`); + } + } + return url.href === captureUrl.href; + }; + // If `capture` is a string then `handler` and `method` must be present. + route = new Route(matchCallback, handler, method); + } else if (capture instanceof RegExp) { + // If `capture` is a `RegExp` then `handler` and `method` must be present. + route = new RegExpRoute(capture, handler, method); + } else if (typeof capture === 'function') { + // If `capture` is a function then `handler` and `method` must be present. + route = new Route(capture, handler, method); + } else if (capture instanceof Route) { + route = capture; + } else { + throw new WorkboxError('unsupported-route-type', { + moduleName: 'workbox-routing', + funcName: 'registerRoute', + paramName: 'capture' + }); + } + const defaultRouter = getOrCreateDefaultRouter(); + defaultRouter.registerRoute(route); + return route; + } + + // @ts-ignore + try { + self['workbox:strategies:6.5.4'] && _(); + } catch (e) {} + + /* + 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 cacheOkAndOpaquePlugin = { + /** + * Returns a valid response (to allow caching) if the status is 200 (OK) or + * 0 (opaque). + * + * @param {Object} options + * @param {Response} options.response + * @return {Response|null} + * + * @private + */ + cacheWillUpdate: async ({ + response + }) => { + if (response.status === 200 || response.status === 0) { + 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. + */ + const _cacheNameDetails = { + googleAnalytics: 'googleAnalytics', + precache: 'precache-v2', + prefix: 'workbox', + runtime: 'runtime', + suffix: typeof registration !== 'undefined' ? registration.scope : '' + }; + const _createCacheName = cacheName => { + return [_cacheNameDetails.prefix, cacheName, _cacheNameDetails.suffix].filter(value => value && value.length > 0).join('-'); + }; + const eachCacheNameDetail = fn => { + for (const key of Object.keys(_cacheNameDetails)) { + fn(key); + } + }; + const cacheNames = { + updateDetails: details => { + eachCacheNameDetail(key => { + if (typeof details[key] === 'string') { + _cacheNameDetails[key] = details[key]; + } + }); + }, + getGoogleAnalyticsName: userCacheName => { + return userCacheName || _createCacheName(_cacheNameDetails.googleAnalytics); + }, + getPrecacheName: userCacheName => { + return userCacheName || _createCacheName(_cacheNameDetails.precache); + }, + getPrefix: () => { + return _cacheNameDetails.prefix; + }, + getRuntimeName: userCacheName => { + return userCacheName || _createCacheName(_cacheNameDetails.runtime); + }, + getSuffix: () => { + return _cacheNameDetails.suffix; + } + }; + + /* + Copyright 2020 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. + */ + function stripParams(fullURL, ignoreParams) { + const strippedURL = new URL(fullURL); + for (const param of ignoreParams) { + strippedURL.searchParams.delete(param); + } + return strippedURL.href; + } + /** + * Matches an item in the cache, ignoring specific URL params. This is similar + * to the `ignoreSearch` option, but it allows you to ignore just specific + * params (while continuing to match on the others). + * + * @private + * @param {Cache} cache + * @param {Request} request + * @param {Object} matchOptions + * @param {Array} ignoreParams + * @return {Promise} + */ + async function cacheMatchIgnoreParams(cache, request, ignoreParams, matchOptions) { + const strippedRequestURL = stripParams(request.url, ignoreParams); + // If the request doesn't include any ignored params, match as normal. + if (request.url === strippedRequestURL) { + return cache.match(request, matchOptions); + } + // Otherwise, match by comparing keys + const keysOptions = Object.assign(Object.assign({}, matchOptions), { + ignoreSearch: true + }); + const cacheKeys = await cache.keys(request, keysOptions); + for (const cacheKey of cacheKeys) { + const strippedCacheKeyURL = stripParams(cacheKey.url, ignoreParams); + if (strippedRequestURL === strippedCacheKeyURL) { + return cache.match(cacheKey, matchOptions); + } + } + return; + } + + /* + 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 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. + */ + // Callbacks to be executed whenever there's a quota error. + // Can't change Function type right now. + // eslint-disable-next-line @typescript-eslint/ban-types + const quotaErrorCallbacks = new Set(); + + /* + 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. + */ + /** + * Runs all of the callback functions, one at a time sequentially, in the order + * in which they were registered. + * + * @memberof workbox-core + * @private + */ + async function executeQuotaErrorCallbacks() { + { + logger.log(`About to run ${quotaErrorCallbacks.size} ` + `callbacks to clean up caches.`); + } + for (const callback of quotaErrorCallbacks) { + await callback(); + { + logger.log(callback, 'is complete.'); + } + } + { + logger.log('Finished running callbacks.'); + } + } + + /* + 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 a promise that resolves and the passed number of milliseconds. + * This utility is an async/await-friendly version of `setTimeout`. + * + * @param {number} ms + * @return {Promise} + * @private + */ + function timeout(ms) { + return new Promise(resolve => setTimeout(resolve, ms)); + } + + /* + Copyright 2020 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. + */ + function toRequest(input) { + return typeof input === 'string' ? new Request(input) : input; + } + /** + * A class created every time a Strategy instance instance calls + * {@link workbox-strategies.Strategy~handle} or + * {@link workbox-strategies.Strategy~handleAll} that wraps all fetch and + * cache actions around plugin callbacks and keeps track of when the strategy + * is "done" (i.e. all added `event.waitUntil()` promises have resolved). + * + * @memberof workbox-strategies + */ + class StrategyHandler { + /** + * Creates a new instance associated with the passed strategy and event + * that's handling the request. + * + * The constructor also initializes the state that will be passed to each of + * the plugins handling this request. + * + * @param {workbox-strategies.Strategy} strategy + * @param {Object} options + * @param {Request|string} options.request A request to run this strategy for. + * @param {ExtendableEvent} options.event The event associated with the + * request. + * @param {URL} [options.url] + * @param {*} [options.params] The return value from the + * {@link workbox-routing~matchCallback} (if applicable). + */ + constructor(strategy, options) { + this._cacheKeys = {}; + /** + * The request the strategy is performing (passed to the strategy's + * `handle()` or `handleAll()` method). + * @name request + * @instance + * @type {Request} + * @memberof workbox-strategies.StrategyHandler + */ + /** + * The event associated with this request. + * @name event + * @instance + * @type {ExtendableEvent} + * @memberof workbox-strategies.StrategyHandler + */ + /** + * A `URL` instance of `request.url` (if passed to the strategy's + * `handle()` or `handleAll()` method). + * Note: the `url` param will be present if the strategy was invoked + * from a workbox `Route` object. + * @name url + * @instance + * @type {URL|undefined} + * @memberof workbox-strategies.StrategyHandler + */ + /** + * A `param` value (if passed to the strategy's + * `handle()` or `handleAll()` method). + * Note: the `param` param will be present if the strategy was invoked + * from a workbox `Route` object and the + * {@link workbox-routing~matchCallback} returned + * a truthy value (it will be that value). + * @name params + * @instance + * @type {*|undefined} + * @memberof workbox-strategies.StrategyHandler + */ + { + finalAssertExports.isInstance(options.event, ExtendableEvent, { + moduleName: 'workbox-strategies', + className: 'StrategyHandler', + funcName: 'constructor', + paramName: 'options.event' + }); + } + Object.assign(this, options); + this.event = options.event; + this._strategy = strategy; + this._handlerDeferred = new Deferred(); + this._extendLifetimePromises = []; + // Copy the plugins list (since it's mutable on the strategy), + // so any mutations don't affect this handler instance. + this._plugins = [...strategy.plugins]; + this._pluginStateMap = new Map(); + for (const plugin of this._plugins) { + this._pluginStateMap.set(plugin, {}); + } + this.event.waitUntil(this._handlerDeferred.promise); + } + /** + * Fetches a given request (and invokes any applicable plugin callback + * methods) using the `fetchOptions` (for non-navigation requests) and + * `plugins` defined on the `Strategy` object. + * + * The following plugin lifecycle methods are invoked when using this method: + * - `requestWillFetch()` + * - `fetchDidSucceed()` + * - `fetchDidFail()` + * + * @param {Request|string} input The URL or request to fetch. + * @return {Promise} + */ + async fetch(input) { + const { + event + } = this; + let request = toRequest(input); + if (request.mode === 'navigate' && event instanceof FetchEvent && event.preloadResponse) { + const possiblePreloadResponse = await event.preloadResponse; + if (possiblePreloadResponse) { + { + logger.log(`Using a preloaded navigation response for ` + `'${getFriendlyURL(request.url)}'`); + } + return possiblePreloadResponse; + } + } + // If there is a fetchDidFail plugin, we need to save a clone of the + // original request before it's either modified by a requestWillFetch + // plugin or before the original request's body is consumed via fetch(). + const originalRequest = this.hasCallback('fetchDidFail') ? request.clone() : null; + try { + for (const cb of this.iterateCallbacks('requestWillFetch')) { + request = await cb({ + request: request.clone(), + event + }); + } + } catch (err) { + if (err instanceof Error) { + throw new WorkboxError('plugin-error-request-will-fetch', { + thrownErrorMessage: err.message + }); + } + } + // The request can be altered by plugins with `requestWillFetch` making + // the original request (most likely from a `fetch` event) different + // from the Request we make. Pass both to `fetchDidFail` to aid debugging. + const pluginFilteredRequest = request.clone(); + try { + let fetchResponse; + // See https://github.com/GoogleChrome/workbox/issues/1796 + fetchResponse = await fetch(request, request.mode === 'navigate' ? undefined : this._strategy.fetchOptions); + if ("development" !== 'production') { + logger.debug(`Network request for ` + `'${getFriendlyURL(request.url)}' returned a response with ` + `status '${fetchResponse.status}'.`); + } + for (const callback of this.iterateCallbacks('fetchDidSucceed')) { + fetchResponse = await callback({ + event, + request: pluginFilteredRequest, + response: fetchResponse + }); + } + return fetchResponse; + } catch (error) { + { + logger.log(`Network request for ` + `'${getFriendlyURL(request.url)}' threw an error.`, error); + } + // `originalRequest` will only exist if a `fetchDidFail` callback + // is being used (see above). + if (originalRequest) { + await this.runCallbacks('fetchDidFail', { + error: error, + event, + originalRequest: originalRequest.clone(), + request: pluginFilteredRequest.clone() + }); + } + throw error; + } + } + /** + * Calls `this.fetch()` and (in the background) runs `this.cachePut()` on + * the response generated by `this.fetch()`. + * + * The call to `this.cachePut()` automatically invokes `this.waitUntil()`, + * so you do not have to manually call `waitUntil()` on the event. + * + * @param {Request|string} input The request or URL to fetch and cache. + * @return {Promise} + */ + async fetchAndCachePut(input) { + const response = await this.fetch(input); + const responseClone = response.clone(); + void this.waitUntil(this.cachePut(input, responseClone)); + return response; + } + /** + * Matches a request from the cache (and invokes any applicable plugin + * callback methods) using the `cacheName`, `matchOptions`, and `plugins` + * defined on the strategy object. + * + * The following plugin lifecycle methods are invoked when using this method: + * - cacheKeyWillByUsed() + * - cachedResponseWillByUsed() + * + * @param {Request|string} key The Request or URL to use as the cache key. + * @return {Promise} A matching response, if found. + */ + async cacheMatch(key) { + const request = toRequest(key); + let cachedResponse; + const { + cacheName, + matchOptions + } = this._strategy; + const effectiveRequest = await this.getCacheKey(request, 'read'); + const multiMatchOptions = Object.assign(Object.assign({}, matchOptions), { + cacheName + }); + cachedResponse = await caches.match(effectiveRequest, multiMatchOptions); + { + if (cachedResponse) { + logger.debug(`Found a cached response in '${cacheName}'.`); + } else { + logger.debug(`No cached response found in '${cacheName}'.`); + } + } + for (const callback of this.iterateCallbacks('cachedResponseWillBeUsed')) { + cachedResponse = (await callback({ + cacheName, + matchOptions, + cachedResponse, + request: effectiveRequest, + event: this.event + })) || undefined; + } + return cachedResponse; + } + /** + * Puts a request/response pair in the cache (and invokes any applicable + * plugin callback methods) using the `cacheName` and `plugins` defined on + * the strategy object. + * + * The following plugin lifecycle methods are invoked when using this method: + * - cacheKeyWillByUsed() + * - cacheWillUpdate() + * - cacheDidUpdate() + * + * @param {Request|string} key The request or URL to use as the cache key. + * @param {Response} response The response to cache. + * @return {Promise} `false` if a cacheWillUpdate caused the response + * not be cached, and `true` otherwise. + */ + async cachePut(key, response) { + const request = toRequest(key); + // Run in the next task to avoid blocking other cache reads. + // https://github.com/w3c/ServiceWorker/issues/1397 + await timeout(0); + const effectiveRequest = await this.getCacheKey(request, 'write'); + { + if (effectiveRequest.method && effectiveRequest.method !== 'GET') { + throw new WorkboxError('attempt-to-cache-non-get-request', { + url: getFriendlyURL(effectiveRequest.url), + method: effectiveRequest.method + }); + } + // See https://github.com/GoogleChrome/workbox/issues/2818 + const vary = response.headers.get('Vary'); + if (vary) { + logger.debug(`The response for ${getFriendlyURL(effectiveRequest.url)} ` + `has a 'Vary: ${vary}' header. ` + `Consider setting the {ignoreVary: true} option on your strategy ` + `to ensure cache matching and deletion works as expected.`); + } + } + if (!response) { + { + logger.error(`Cannot cache non-existent response for ` + `'${getFriendlyURL(effectiveRequest.url)}'.`); + } + throw new WorkboxError('cache-put-with-no-response', { + url: getFriendlyURL(effectiveRequest.url) + }); + } + const responseToCache = await this._ensureResponseSafeToCache(response); + if (!responseToCache) { + { + logger.debug(`Response '${getFriendlyURL(effectiveRequest.url)}' ` + `will not be cached.`, responseToCache); + } + return false; + } + const { + cacheName, + matchOptions + } = this._strategy; + const cache = await self.caches.open(cacheName); + const hasCacheUpdateCallback = this.hasCallback('cacheDidUpdate'); + const oldResponse = hasCacheUpdateCallback ? await cacheMatchIgnoreParams( + // TODO(philipwalton): the `__WB_REVISION__` param is a precaching + // feature. Consider into ways to only add this behavior if using + // precaching. + cache, effectiveRequest.clone(), ['__WB_REVISION__'], matchOptions) : null; + { + logger.debug(`Updating the '${cacheName}' cache with a new Response ` + `for ${getFriendlyURL(effectiveRequest.url)}.`); + } + try { + await cache.put(effectiveRequest, hasCacheUpdateCallback ? responseToCache.clone() : responseToCache); + } catch (error) { + if (error instanceof Error) { + // See https://developer.mozilla.org/en-US/docs/Web/API/DOMException#exception-QuotaExceededError + if (error.name === 'QuotaExceededError') { + await executeQuotaErrorCallbacks(); + } + throw error; + } + } + for (const callback of this.iterateCallbacks('cacheDidUpdate')) { + await callback({ + cacheName, + oldResponse, + newResponse: responseToCache.clone(), + request: effectiveRequest, + event: this.event + }); + } + return true; + } + /** + * Checks the list of plugins for the `cacheKeyWillBeUsed` callback, and + * executes any of those callbacks found in sequence. The final `Request` + * object returned by the last plugin is treated as the cache key for cache + * reads and/or writes. If no `cacheKeyWillBeUsed` plugin callbacks have + * been registered, the passed request is returned unmodified + * + * @param {Request} request + * @param {string} mode + * @return {Promise} + */ + async getCacheKey(request, mode) { + const key = `${request.url} | ${mode}`; + if (!this._cacheKeys[key]) { + let effectiveRequest = request; + for (const callback of this.iterateCallbacks('cacheKeyWillBeUsed')) { + effectiveRequest = toRequest(await callback({ + mode, + request: effectiveRequest, + event: this.event, + // params has a type any can't change right now. + params: this.params // eslint-disable-line + })); + } + this._cacheKeys[key] = effectiveRequest; + } + return this._cacheKeys[key]; + } + /** + * Returns true if the strategy has at least one plugin with the given + * callback. + * + * @param {string} name The name of the callback to check for. + * @return {boolean} + */ + hasCallback(name) { + for (const plugin of this._strategy.plugins) { + if (name in plugin) { + return true; + } + } + return false; + } + /** + * Runs all plugin callbacks matching the given name, in order, passing the + * given param object (merged ith the current plugin state) as the only + * argument. + * + * Note: since this method runs all plugins, it's not suitable for cases + * where the return value of a callback needs to be applied prior to calling + * the next callback. See + * {@link workbox-strategies.StrategyHandler#iterateCallbacks} + * below for how to handle that case. + * + * @param {string} name The name of the callback to run within each plugin. + * @param {Object} param The object to pass as the first (and only) param + * when executing each callback. This object will be merged with the + * current plugin state prior to callback execution. + */ + async runCallbacks(name, param) { + for (const callback of this.iterateCallbacks(name)) { + // TODO(philipwalton): not sure why `any` is needed. It seems like + // this should work with `as WorkboxPluginCallbackParam[C]`. + await callback(param); + } + } + /** + * Accepts a callback and returns an iterable of matching plugin callbacks, + * where each callback is wrapped with the current handler state (i.e. when + * you call each callback, whatever object parameter you pass it will + * be merged with the plugin's current state). + * + * @param {string} name The name fo the callback to run + * @return {Array} + */ + *iterateCallbacks(name) { + for (const plugin of this._strategy.plugins) { + if (typeof plugin[name] === 'function') { + const state = this._pluginStateMap.get(plugin); + const statefulCallback = param => { + const statefulParam = Object.assign(Object.assign({}, param), { + state + }); + // TODO(philipwalton): not sure why `any` is needed. It seems like + // this should work with `as WorkboxPluginCallbackParam[C]`. + return plugin[name](statefulParam); + }; + yield statefulCallback; + } + } + } + /** + * Adds a promise to the + * [extend lifetime promises]{@link https://w3c.github.io/ServiceWorker/#extendableevent-extend-lifetime-promises} + * of the event event associated with the request being handled (usually a + * `FetchEvent`). + * + * Note: you can await + * {@link workbox-strategies.StrategyHandler~doneWaiting} + * to know when all added promises have settled. + * + * @param {Promise} promise A promise to add to the extend lifetime promises + * of the event that triggered the request. + */ + waitUntil(promise) { + this._extendLifetimePromises.push(promise); + return promise; + } + /** + * Returns a promise that resolves once all promises passed to + * {@link workbox-strategies.StrategyHandler~waitUntil} + * have settled. + * + * Note: any work done after `doneWaiting()` settles should be manually + * passed to an event's `waitUntil()` method (not this handler's + * `waitUntil()` method), otherwise the service worker thread my be killed + * prior to your work completing. + */ + async doneWaiting() { + let promise; + while (promise = this._extendLifetimePromises.shift()) { + await promise; + } + } + /** + * Stops running the strategy and immediately resolves any pending + * `waitUntil()` promises. + */ + destroy() { + this._handlerDeferred.resolve(null); + } + /** + * This method will call cacheWillUpdate on the available plugins (or use + * status === 200) to determine if the Response is safe and valid to cache. + * + * @param {Request} options.request + * @param {Response} options.response + * @return {Promise} + * + * @private + */ + async _ensureResponseSafeToCache(response) { + let responseToCache = response; + let pluginsUsed = false; + for (const callback of this.iterateCallbacks('cacheWillUpdate')) { + responseToCache = (await callback({ + request: this.request, + response: responseToCache, + event: this.event + })) || undefined; + pluginsUsed = true; + if (!responseToCache) { + break; + } + } + if (!pluginsUsed) { + if (responseToCache && responseToCache.status !== 200) { + responseToCache = undefined; + } + { + if (responseToCache) { + if (responseToCache.status !== 200) { + if (responseToCache.status === 0) { + logger.warn(`The response for '${this.request.url}' ` + `is an opaque response. The caching strategy that you're ` + `using will not cache opaque responses by default.`); + } else { + logger.debug(`The response for '${this.request.url}' ` + `returned a status code of '${response.status}' and won't ` + `be cached as a result.`); + } + } + } + } + } + return responseToCache; + } + } + + /* + Copyright 2020 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. + */ + /** + * An abstract base class that all other strategy classes must extend from: + * + * @memberof workbox-strategies + */ + class Strategy { + /** + * Creates a new instance of the strategy and sets all documented option + * properties as public instance properties. + * + * Note: if a custom strategy class extends the base Strategy class and does + * not need more than these properties, it does not need to define its own + * constructor. + * + * @param {Object} [options] + * @param {string} [options.cacheName] Cache name to store and retrieve + * requests. Defaults to the cache names provided by + * {@link workbox-core.cacheNames}. + * @param {Array} [options.plugins] [Plugins]{@link https://developers.google.com/web/tools/workbox/guides/using-plugins} + * to use in conjunction with this caching strategy. + * @param {Object} [options.fetchOptions] Values passed along to the + * [`init`](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch#Parameters) + * of [non-navigation](https://github.com/GoogleChrome/workbox/issues/1796) + * `fetch()` requests made by this strategy. + * @param {Object} [options.matchOptions] The + * [`CacheQueryOptions`]{@link https://w3c.github.io/ServiceWorker/#dictdef-cachequeryoptions} + * for any `cache.match()` or `cache.put()` calls made by this strategy. + */ + constructor(options = {}) { + /** + * Cache name to store and retrieve + * requests. Defaults to the cache names provided by + * {@link workbox-core.cacheNames}. + * + * @type {string} + */ + this.cacheName = cacheNames.getRuntimeName(options.cacheName); + /** + * The list + * [Plugins]{@link https://developers.google.com/web/tools/workbox/guides/using-plugins} + * used by this strategy. + * + * @type {Array} + */ + this.plugins = options.plugins || []; + /** + * Values passed along to the + * [`init`]{@link https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch#Parameters} + * of all fetch() requests made by this strategy. + * + * @type {Object} + */ + this.fetchOptions = options.fetchOptions; + /** + * The + * [`CacheQueryOptions`]{@link https://w3c.github.io/ServiceWorker/#dictdef-cachequeryoptions} + * for any `cache.match()` or `cache.put()` calls made by this strategy. + * + * @type {Object} + */ + this.matchOptions = options.matchOptions; + } + /** + * Perform a request strategy and returns a `Promise` that will resolve with + * a `Response`, invoking all relevant plugin callbacks. + * + * When a strategy instance is registered with a Workbox + * {@link workbox-routing.Route}, this method is automatically + * called when the route matches. + * + * Alternatively, this method can be used in a standalone `FetchEvent` + * listener by passing it to `event.respondWith()`. + * + * @param {FetchEvent|Object} options A `FetchEvent` or an object with the + * properties listed below. + * @param {Request|string} options.request A request to run this strategy for. + * @param {ExtendableEvent} options.event The event associated with the + * request. + * @param {URL} [options.url] + * @param {*} [options.params] + */ + handle(options) { + const [responseDone] = this.handleAll(options); + return responseDone; + } + /** + * Similar to {@link workbox-strategies.Strategy~handle}, but + * instead of just returning a `Promise` that resolves to a `Response` it + * it will return an tuple of `[response, done]` promises, where the former + * (`response`) is equivalent to what `handle()` returns, and the latter is a + * Promise that will resolve once any promises that were added to + * `event.waitUntil()` as part of performing the strategy have completed. + * + * You can await the `done` promise to ensure any extra work performed by + * the strategy (usually caching responses) completes successfully. + * + * @param {FetchEvent|Object} options A `FetchEvent` or an object with the + * properties listed below. + * @param {Request|string} options.request A request to run this strategy for. + * @param {ExtendableEvent} options.event The event associated with the + * request. + * @param {URL} [options.url] + * @param {*} [options.params] + * @return {Array} A tuple of [response, done] + * promises that can be used to determine when the response resolves as + * well as when the handler has completed all its work. + */ + handleAll(options) { + // Allow for flexible options to be passed. + if (options instanceof FetchEvent) { + options = { + event: options, + request: options.request + }; + } + const event = options.event; + const request = typeof options.request === 'string' ? new Request(options.request) : options.request; + const params = 'params' in options ? options.params : undefined; + const handler = new StrategyHandler(this, { + event, + request, + params + }); + const responseDone = this._getResponse(handler, request, event); + const handlerDone = this._awaitComplete(responseDone, handler, request, event); + // Return an array of promises, suitable for use with Promise.all(). + return [responseDone, handlerDone]; + } + async _getResponse(handler, request, event) { + await handler.runCallbacks('handlerWillStart', { + event, + request + }); + let response = undefined; + try { + response = await this._handle(request, handler); + // The "official" Strategy subclasses all throw this error automatically, + // but in case a third-party Strategy doesn't, ensure that we have a + // consistent failure when there's no response or an error response. + if (!response || response.type === 'error') { + throw new WorkboxError('no-response', { + url: request.url + }); + } + } catch (error) { + if (error instanceof Error) { + for (const callback of handler.iterateCallbacks('handlerDidError')) { + response = await callback({ + error, + event, + request + }); + if (response) { + break; + } + } + } + if (!response) { + throw error; + } else { + logger.log(`While responding to '${getFriendlyURL(request.url)}', ` + `an ${error instanceof Error ? error.toString() : ''} error occurred. Using a fallback response provided by ` + `a handlerDidError plugin.`); + } + } + for (const callback of handler.iterateCallbacks('handlerWillRespond')) { + response = await callback({ + event, + request, + response + }); + } + return response; + } + async _awaitComplete(responseDone, handler, request, event) { + let response; + let error; + try { + response = await responseDone; + } catch (error) { + // Ignore errors, as response errors should be caught via the `response` + // promise above. The `done` promise will only throw for errors in + // promises passed to `handler.waitUntil()`. + } + try { + await handler.runCallbacks('handlerDidRespond', { + event, + request, + response + }); + await handler.doneWaiting(); + } catch (waitUntilError) { + if (waitUntilError instanceof Error) { + error = waitUntilError; + } + } + await handler.runCallbacks('handlerDidComplete', { + event, + request, + response, + error: error + }); + handler.destroy(); + if (error) { + throw error; + } + } + } + /** + * Classes extending the `Strategy` based class should implement this method, + * and leverage the {@link workbox-strategies.StrategyHandler} + * arg to perform all fetching and cache logic, which will ensure all relevant + * cache, cache options, fetch options and plugins are used (per the current + * strategy instance). + * + * @name _handle + * @instance + * @abstract + * @function + * @param {Request} request + * @param {workbox-strategies.StrategyHandler} handler + * @return {Promise} + * + * @memberof workbox-strategies.Strategy + */ + + /* + 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 messages = { + strategyStart: (strategyName, request) => `Using ${strategyName} to respond to '${getFriendlyURL(request.url)}'`, + printFinalResponse: response => { + if (response) { + logger.groupCollapsed(`View the final response here.`); + logger.log(response || '[No response returned]'); + 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. + */ + /** + * An implementation of a + * [network first](https://developer.chrome.com/docs/workbox/caching-strategies-overview/#network-first-falling-back-to-cache) + * request strategy. + * + * By default, this strategy will cache responses with a 200 status code as + * well as [opaque responses](https://developer.chrome.com/docs/workbox/caching-resources-during-runtime/#opaque-responses). + * Opaque responses are are cross-origin requests where the response doesn't + * support [CORS](https://enable-cors.org/). + * + * If the network request fails, and there is no cache match, this will throw + * a `WorkboxError` exception. + * + * @extends workbox-strategies.Strategy + * @memberof workbox-strategies + */ + class NetworkFirst extends Strategy { + /** + * @param {Object} [options] + * @param {string} [options.cacheName] Cache name to store and retrieve + * requests. Defaults to cache names provided by + * {@link workbox-core.cacheNames}. + * @param {Array} [options.plugins] [Plugins]{@link https://developers.google.com/web/tools/workbox/guides/using-plugins} + * to use in conjunction with this caching strategy. + * @param {Object} [options.fetchOptions] Values passed along to the + * [`init`](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch#Parameters) + * of [non-navigation](https://github.com/GoogleChrome/workbox/issues/1796) + * `fetch()` requests made by this strategy. + * @param {Object} [options.matchOptions] [`CacheQueryOptions`](https://w3c.github.io/ServiceWorker/#dictdef-cachequeryoptions) + * @param {number} [options.networkTimeoutSeconds] If set, any network requests + * that fail to respond within the timeout will fallback to the cache. + * + * This option can be used to combat + * "[lie-fi]{@link https://developers.google.com/web/fundamentals/performance/poor-connectivity/#lie-fi}" + * scenarios. + */ + constructor(options = {}) { + super(options); + // If this instance contains no plugins with a 'cacheWillUpdate' callback, + // prepend the `cacheOkAndOpaquePlugin` plugin to the plugins list. + if (!this.plugins.some(p => 'cacheWillUpdate' in p)) { + this.plugins.unshift(cacheOkAndOpaquePlugin); + } + this._networkTimeoutSeconds = options.networkTimeoutSeconds || 0; + { + if (this._networkTimeoutSeconds) { + finalAssertExports.isType(this._networkTimeoutSeconds, 'number', { + moduleName: 'workbox-strategies', + className: this.constructor.name, + funcName: 'constructor', + paramName: 'networkTimeoutSeconds' + }); + } + } + } + /** + * @private + * @param {Request|string} request A request to run this strategy for. + * @param {workbox-strategies.StrategyHandler} handler The event that + * triggered the request. + * @return {Promise} + */ + async _handle(request, handler) { + const logs = []; + { + finalAssertExports.isInstance(request, Request, { + moduleName: 'workbox-strategies', + className: this.constructor.name, + funcName: 'handle', + paramName: 'makeRequest' + }); + } + const promises = []; + let timeoutId; + if (this._networkTimeoutSeconds) { + const { + id, + promise + } = this._getTimeoutPromise({ + request, + logs, + handler + }); + timeoutId = id; + promises.push(promise); + } + const networkPromise = this._getNetworkPromise({ + timeoutId, + request, + logs, + handler + }); + promises.push(networkPromise); + const response = await handler.waitUntil((async () => { + // Promise.race() will resolve as soon as the first promise resolves. + return (await handler.waitUntil(Promise.race(promises))) || ( + // If Promise.race() resolved with null, it might be due to a network + // timeout + a cache miss. If that were to happen, we'd rather wait until + // the networkPromise resolves instead of returning null. + // Note that it's fine to await an already-resolved promise, so we don't + // have to check to see if it's still "in flight". + await networkPromise); + })()); + { + logger.groupCollapsed(messages.strategyStart(this.constructor.name, request)); + for (const log of logs) { + logger.log(log); + } + messages.printFinalResponse(response); + logger.groupEnd(); + } + if (!response) { + throw new WorkboxError('no-response', { + url: request.url + }); + } + return response; + } + /** + * @param {Object} options + * @param {Request} options.request + * @param {Array} options.logs A reference to the logs array + * @param {Event} options.event + * @return {Promise} + * + * @private + */ + _getTimeoutPromise({ + request, + logs, + handler + }) { + let timeoutId; + const timeoutPromise = new Promise(resolve => { + const onNetworkTimeout = async () => { + { + logs.push(`Timing out the network response at ` + `${this._networkTimeoutSeconds} seconds.`); + } + resolve(await handler.cacheMatch(request)); + }; + timeoutId = setTimeout(onNetworkTimeout, this._networkTimeoutSeconds * 1000); + }); + return { + promise: timeoutPromise, + id: timeoutId + }; + } + /** + * @param {Object} options + * @param {number|undefined} options.timeoutId + * @param {Request} options.request + * @param {Array} options.logs A reference to the logs Array. + * @param {Event} options.event + * @return {Promise} + * + * @private + */ + async _getNetworkPromise({ + timeoutId, + request, + logs, + handler + }) { + let error; + let response; + try { + response = await handler.fetchAndCachePut(request); + } catch (fetchError) { + if (fetchError instanceof Error) { + error = fetchError; + } + } + if (timeoutId) { + clearTimeout(timeoutId); + } + { + if (response) { + logs.push(`Got response from network.`); + } else { + logs.push(`Unable to get a response from the network. Will respond ` + `with a cached response.`); + } + } + if (error || !response) { + response = await handler.cacheMatch(request); + { + if (response) { + logs.push(`Found a cached response in the '${this.cacheName}'` + ` cache.`); + } else { + logs.push(`No response found in the '${this.cacheName}' cache.`); + } + } + } + return 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. + */ + /** + * An implementation of a + * [network-only](https://developer.chrome.com/docs/workbox/caching-strategies-overview/#network-only) + * request strategy. + * + * This class is useful if you want to take advantage of any + * [Workbox plugins](https://developer.chrome.com/docs/workbox/using-plugins/). + * + * If the network request fails, this will throw a `WorkboxError` exception. + * + * @extends workbox-strategies.Strategy + * @memberof workbox-strategies + */ + class NetworkOnly extends Strategy { + /** + * @param {Object} [options] + * @param {Array} [options.plugins] [Plugins]{@link https://developers.google.com/web/tools/workbox/guides/using-plugins} + * to use in conjunction with this caching strategy. + * @param {Object} [options.fetchOptions] Values passed along to the + * [`init`](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch#Parameters) + * of [non-navigation](https://github.com/GoogleChrome/workbox/issues/1796) + * `fetch()` requests made by this strategy. + * @param {number} [options.networkTimeoutSeconds] If set, any network requests + * that fail to respond within the timeout will result in a network error. + */ + constructor(options = {}) { + super(options); + this._networkTimeoutSeconds = options.networkTimeoutSeconds || 0; + } + /** + * @private + * @param {Request|string} request A request to run this strategy for. + * @param {workbox-strategies.StrategyHandler} handler The event that + * triggered the request. + * @return {Promise} + */ + async _handle(request, handler) { + { + finalAssertExports.isInstance(request, Request, { + moduleName: 'workbox-strategies', + className: this.constructor.name, + funcName: '_handle', + paramName: 'request' + }); + } + let error = undefined; + let response; + try { + const promises = [handler.fetch(request)]; + if (this._networkTimeoutSeconds) { + const timeoutPromise = timeout(this._networkTimeoutSeconds * 1000); + promises.push(timeoutPromise); + } + response = await Promise.race(promises); + if (!response) { + throw new Error(`Timed out the network response after ` + `${this._networkTimeoutSeconds} seconds.`); + } + } catch (err) { + if (err instanceof Error) { + error = err; + } + } + { + logger.groupCollapsed(messages.strategyStart(this.constructor.name, request)); + if (response) { + logger.log(`Got response from network.`); + } else { + logger.log(`Unable to get a response from the network.`); + } + messages.printFinalResponse(response); + logger.groupEnd(); + } + if (!response) { + throw new WorkboxError('no-response', { + url: request.url, + error + }); + } + return response; + } + } + + /* + 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. + */ + /** + * Claim any currently available clients once the service worker + * becomes active. This is normally used in conjunction with `skipWaiting()`. + * + * @memberof workbox-core + */ + function clientsClaim() { + self.addEventListener('activate', () => self.clients.claim()); + } + + exports.NetworkFirst = NetworkFirst; + exports.NetworkOnly = NetworkOnly; + exports.clientsClaim = clientsClaim; + exports.registerRoute = registerRoute; + +})); diff --git a/service/advertisement.ts b/service/advertisement.ts index a87e3c2..fe5fa69 100644 --- a/service/advertisement.ts +++ b/service/advertisement.ts @@ -53,6 +53,7 @@ export async function editAdvertise(data: any) { export async function editAdvertiseIsActive(data: any) { const headers = { "content-type": "application/json", + Authorization: `Bearer ${token}`, }; const pathUrl = `/advertisement/publish/${data?.id}?isPublish=${data?.isActive}`; return await httpPut(pathUrl, headers); diff --git a/service/subscribe.ts b/service/subscribe.ts new file mode 100644 index 0000000..094b94d --- /dev/null +++ b/service/subscribe.ts @@ -0,0 +1,17 @@ +import { + httpDeleteInterceptor, + httpGet, + httpPost, + httpPut, +} from "./http-config/axios-base-service"; +import Cookies from "js-cookie"; + +const token = Cookies.get("access_token"); + +export async function subscription(data: any) { + const headers = { + "content-type": "application/json", + }; + const pathUrl = `/subscription`; + return await httpPost(pathUrl, headers, data); +}