@serwist/sw
Advanced tools
Comparing version 9.0.0-preview.19 to 9.0.0-preview.20
@@ -9,11 +9,9 @@ import { type GoogleAnalyticsInitializeOptions } from "../plugins/googleAnalytics/initialize.js"; | ||
/** | ||
* The precache controller that will be used to perform efficient | ||
* precaching of assets. | ||
* @see https://serwist.pages.dev/docs/sw/precaching | ||
* An optional `PrecacheController` instance. If not provided, the singleton | ||
* `PrecacheController` will be used. | ||
*/ | ||
precacheController?: PrecacheController; | ||
/** | ||
* The router that will be used to process a `FetchEvent`, responding | ||
* with a `Response` if a matching route exists. | ||
* @see https://serwist.pages.dev/docs/sw/routing | ||
* An optional `Router` instance. If not provided, the singleton `Router` | ||
* will be used. | ||
*/ | ||
@@ -83,4 +81,4 @@ router?: Router; | ||
constructor({ precacheController, router }?: SerwistOptions); | ||
install({ precacheEntries, precacheOptions, cleanupOutdatedCaches, navigateFallback, navigateFallbackAllowlist, navigateFallbackDenylist, skipWaiting, importScripts, navigationPreload, cacheId, clientsClaim, runtimeCaching, offlineAnalyticsConfig, disableDevLogs, fallbacks, }: SerwistInstallOptions): void; | ||
install({ precacheEntries, precacheOptions, cleanupOutdatedCaches, navigateFallback, navigateFallbackAllowlist, navigateFallbackDenylist, skipWaiting, importScripts, navigationPreload, cacheId, clientsClaim, runtimeCaching, offlineAnalyticsConfig, disableDevLogs, fallbacks, }?: SerwistInstallOptions): void; | ||
} | ||
//# sourceMappingURL=Serwist.d.ts.map |
import { assert, logger } from '@serwist/core/internal'; | ||
import { R as Route } from './registerRoute.js'; | ||
import { R as Route } from './singletonRouter.js'; | ||
@@ -4,0 +4,0 @@ class NavigationRoute extends Route { |
import { logger, getFriendlyURL, privateCacheNames } from '@serwist/core/internal'; | ||
import { g as getOrCreatePrecacheController } from './getOrCreatePrecacheController.js'; | ||
import { R as Route, r as registerRoute } from './registerRoute.js'; | ||
import { g as getSingletonPrecacheController } from './singletonPrecacheController.js'; | ||
import { r as registerRoute } from './registerRoute.js'; | ||
import { R as Route } from './singletonRouter.js'; | ||
@@ -92,3 +93,3 @@ function removeIgnoredSearchParams(urlObject, ignoreURLParametersMatching = []) { | ||
const createHandlerBoundToURL = (url)=>{ | ||
const precacheController = getOrCreatePrecacheController(); | ||
const precacheController = getSingletonPrecacheController(); | ||
return precacheController.createHandlerBoundToURL(url); | ||
@@ -98,3 +99,3 @@ }; | ||
const addRoute = (options)=>{ | ||
const precacheController = getOrCreatePrecacheController(); | ||
const precacheController = getSingletonPrecacheController(); | ||
const precacheRoute = new PrecacheRoute(precacheController, options); | ||
@@ -105,3 +106,3 @@ registerRoute(precacheRoute); | ||
const precache = (entries)=>{ | ||
const precacheController = getOrCreatePrecacheController(); | ||
const precacheController = getSingletonPrecacheController(); | ||
precacheController.precache(entries); | ||
@@ -108,0 +109,0 @@ }; |
import { assert, SerwistError, logger, getFriendlyURL, privateCacheNames } from '@serwist/core/internal'; | ||
import { r as registerRoute, R as Route } from './registerRoute.js'; | ||
import { g as getSingletonRouter, R as Route } from './singletonRouter.js'; | ||
import { N as NetworkOnly, a as NetworkFirst } from './NetworkOnly.js'; | ||
import { openDB } from 'idb'; | ||
import { g as getOrCreatePrecacheController } from './getOrCreatePrecacheController.js'; | ||
import { g as getSingletonPrecacheController } from './singletonPrecacheController.js'; | ||
@@ -531,4 +531,4 @@ const DB_VERSION = 3; | ||
}; | ||
const initialize = (options = {})=>{ | ||
const cacheName = privateCacheNames.getGoogleAnalyticsName(options.cacheName); | ||
const initialize = ({ cacheName, router = getSingletonRouter(), ...options } = {})=>{ | ||
const resolvedCacheName = privateCacheNames.getGoogleAnalyticsName(cacheName); | ||
const bgSyncPlugin = new BackgroundSyncPlugin(QUEUE_NAME, { | ||
@@ -539,9 +539,9 @@ maxRetentionTime: MAX_RETENTION_TIME, | ||
const routes = [ | ||
createGtmJsRoute(cacheName), | ||
createAnalyticsJsRoute(cacheName), | ||
createGtagJsRoute(cacheName), | ||
createGtmJsRoute(resolvedCacheName), | ||
createAnalyticsJsRoute(resolvedCacheName), | ||
createGtagJsRoute(resolvedCacheName), | ||
...createCollectRoutes(bgSyncPlugin) | ||
]; | ||
for (const route of routes){ | ||
registerRoute(route); | ||
router.registerRoute(route); | ||
} | ||
@@ -555,3 +555,3 @@ }; | ||
this._fallbackUrls = fallbackUrls; | ||
this._precacheController = precacheController || getOrCreatePrecacheController(); | ||
this._precacheController = precacheController || getSingletonPrecacheController(); | ||
} | ||
@@ -558,0 +558,0 @@ async handlerDidError(param) { |
@@ -1,408 +0,7 @@ | ||
import { assert, logger, getFriendlyURL, SerwistError } from '@serwist/core/internal'; | ||
import { g as getSingletonRouter } from './singletonRouter.js'; | ||
const defaultMethod = "GET"; | ||
const validMethods = [ | ||
"DELETE", | ||
"GET", | ||
"HEAD", | ||
"PATCH", | ||
"POST", | ||
"PUT" | ||
]; | ||
const normalizeHandler = (handler)=>{ | ||
if (handler && typeof handler === "object") { | ||
if (process.env.NODE_ENV !== "production") { | ||
assert.hasMethod(handler, "handle", { | ||
moduleName: "@serwist/routing", | ||
className: "Route", | ||
funcName: "constructor", | ||
paramName: "handler" | ||
}); | ||
} | ||
return handler; | ||
} | ||
if (process.env.NODE_ENV !== "production") { | ||
assert.isType(handler, "function", { | ||
moduleName: "@serwist/routing", | ||
className: "Route", | ||
funcName: "constructor", | ||
paramName: "handler" | ||
}); | ||
} | ||
return { | ||
handle: handler | ||
}; | ||
}; | ||
class Route { | ||
handler; | ||
match; | ||
method; | ||
catchHandler; | ||
constructor(match, handler, method = defaultMethod){ | ||
if (process.env.NODE_ENV !== "production") { | ||
assert.isType(match, "function", { | ||
moduleName: "@serwist/routing", | ||
className: "Route", | ||
funcName: "constructor", | ||
paramName: "match" | ||
}); | ||
if (method) { | ||
assert.isOneOf(method, validMethods, { | ||
paramName: "method" | ||
}); | ||
} | ||
} | ||
this.handler = normalizeHandler(handler); | ||
this.match = match; | ||
this.method = method; | ||
} | ||
setCatchHandler(handler) { | ||
this.catchHandler = normalizeHandler(handler); | ||
} | ||
} | ||
class Router { | ||
_routes; | ||
_defaultHandlerMap; | ||
_catchHandler; | ||
constructor(){ | ||
this._routes = new Map(); | ||
this._defaultHandlerMap = new Map(); | ||
} | ||
get routes() { | ||
return this._routes; | ||
} | ||
addFetchListener() { | ||
self.addEventListener("fetch", (event)=>{ | ||
const { request } = event; | ||
const responsePromise = this.handleRequest({ | ||
request, | ||
event | ||
}); | ||
if (responsePromise) { | ||
event.respondWith(responsePromise); | ||
} | ||
}); | ||
} | ||
addCacheListener() { | ||
self.addEventListener("message", (event)=>{ | ||
if (event.data && event.data.type === "CACHE_URLS") { | ||
const { payload } = event.data; | ||
if (process.env.NODE_ENV !== "production") { | ||
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 | ||
}); | ||
})); | ||
event.waitUntil(requestPromises); | ||
if (event.ports?.[0]) { | ||
void requestPromises.then(()=>event.ports[0].postMessage(true)); | ||
} | ||
} | ||
}); | ||
} | ||
handleRequest({ request, event }) { | ||
if (process.env.NODE_ENV !== "production") { | ||
assert.isInstance(request, Request, { | ||
moduleName: "@serwist/routing", | ||
className: "Router", | ||
funcName: "handleRequest", | ||
paramName: "options.request" | ||
}); | ||
} | ||
const url = new URL(request.url, location.href); | ||
if (!url.protocol.startsWith("http")) { | ||
if (process.env.NODE_ENV !== "production") { | ||
logger.debug("The Serwist 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?.handler; | ||
const debugMessages = []; | ||
if (process.env.NODE_ENV !== "production") { | ||
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 | ||
]); | ||
} | ||
} | ||
} | ||
const method = request.method; | ||
if (!handler && this._defaultHandlerMap.has(method)) { | ||
if (process.env.NODE_ENV !== "production") { | ||
debugMessages.push(`Failed to find a matching route. Falling back to the default handler for ${method}.`); | ||
} | ||
handler = this._defaultHandlerMap.get(method); | ||
} | ||
if (!handler) { | ||
if (process.env.NODE_ENV !== "production") { | ||
logger.debug(`No route found for: ${getFriendlyURL(url)}`); | ||
} | ||
return; | ||
} | ||
if (process.env.NODE_ENV !== "production") { | ||
logger.groupCollapsed(`Router is responding to: ${getFriendlyURL(url)}`); | ||
for (const msg of debugMessages){ | ||
if (Array.isArray(msg)) { | ||
logger.log(...msg); | ||
} else { | ||
logger.log(msg); | ||
} | ||
} | ||
logger.groupEnd(); | ||
} | ||
let responsePromise; | ||
try { | ||
responsePromise = handler.handle({ | ||
url, | ||
request, | ||
event, | ||
params | ||
}); | ||
} catch (err) { | ||
responsePromise = Promise.reject(err); | ||
} | ||
const catchHandler = route?.catchHandler; | ||
if (responsePromise instanceof Promise && (this._catchHandler || catchHandler)) { | ||
responsePromise = responsePromise.catch(async (err)=>{ | ||
if (catchHandler) { | ||
if (process.env.NODE_ENV !== "production") { | ||
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) { | ||
if (process.env.NODE_ENV !== "production") { | ||
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; | ||
} | ||
findMatchingRoute({ url, sameOrigin, request, event }) { | ||
const routes = this._routes.get(request.method) || []; | ||
for (const route of routes){ | ||
let params; | ||
const matchResult = route.match({ | ||
url, | ||
sameOrigin, | ||
request, | ||
event | ||
}); | ||
if (matchResult) { | ||
if (process.env.NODE_ENV !== "production") { | ||
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); | ||
} | ||
} | ||
params = matchResult; | ||
if (Array.isArray(params) && params.length === 0) { | ||
params = undefined; | ||
} else if (matchResult.constructor === Object && Object.keys(matchResult).length === 0) { | ||
params = undefined; | ||
} else if (typeof matchResult === "boolean") { | ||
params = undefined; | ||
} | ||
return { | ||
route, | ||
params | ||
}; | ||
} | ||
} | ||
return {}; | ||
} | ||
setDefaultHandler(handler, method = defaultMethod) { | ||
this._defaultHandlerMap.set(method, normalizeHandler(handler)); | ||
} | ||
setCatchHandler(handler) { | ||
this._catchHandler = normalizeHandler(handler); | ||
} | ||
registerRoute(route) { | ||
if (process.env.NODE_ENV !== "production") { | ||
assert.isType(route, "object", { | ||
moduleName: "@serwist/routing", | ||
className: "Router", | ||
funcName: "registerRoute", | ||
paramName: "route" | ||
}); | ||
assert.hasMethod(route, "match", { | ||
moduleName: "@serwist/routing", | ||
className: "Router", | ||
funcName: "registerRoute", | ||
paramName: "route" | ||
}); | ||
assert.isType(route.handler, "object", { | ||
moduleName: "@serwist/routing", | ||
className: "Router", | ||
funcName: "registerRoute", | ||
paramName: "route" | ||
}); | ||
assert.hasMethod(route.handler, "handle", { | ||
moduleName: "@serwist/routing", | ||
className: "Router", | ||
funcName: "registerRoute", | ||
paramName: "route.handler" | ||
}); | ||
assert.isType(route.method, "string", { | ||
moduleName: "@serwist/routing", | ||
className: "Router", | ||
funcName: "registerRoute", | ||
paramName: "route.method" | ||
}); | ||
} | ||
if (!this._routes.has(route.method)) { | ||
this._routes.set(route.method, []); | ||
} | ||
this._routes.get(route.method).push(route); | ||
} | ||
unregisterRoute(route) { | ||
if (!this._routes.has(route.method)) { | ||
throw new SerwistError("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 SerwistError("unregister-route-route-not-registered"); | ||
} | ||
} | ||
} | ||
let defaultRouter; | ||
const getOrCreateDefaultRouter = ()=>{ | ||
if (!defaultRouter) { | ||
defaultRouter = new Router(); | ||
defaultRouter.addFetchListener(); | ||
defaultRouter.addCacheListener(); | ||
} | ||
return defaultRouter; | ||
}; | ||
class RegExpRoute extends Route { | ||
constructor(regExp, handler, method){ | ||
if (process.env.NODE_ENV !== "production") { | ||
assert.isInstance(regExp, RegExp, { | ||
moduleName: "@serwist/routing", | ||
className: "RegExpRoute", | ||
funcName: "constructor", | ||
paramName: "pattern" | ||
}); | ||
} | ||
const match = ({ url })=>{ | ||
const result = regExp.exec(url.href); | ||
if (!result) { | ||
return; | ||
} | ||
if (url.origin !== location.origin && result.index !== 0) { | ||
if (process.env.NODE_ENV !== "production") { | ||
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; | ||
} | ||
return result.slice(1); | ||
}; | ||
super(match, handler, method); | ||
} | ||
} | ||
const parseRoute = (capture, handler, method)=>{ | ||
let route; | ||
if (typeof capture === "string") { | ||
const captureUrl = new URL(capture, location.href); | ||
if (process.env.NODE_ENV !== "production") { | ||
if (!(capture.startsWith("/") || capture.startsWith("http"))) { | ||
throw new SerwistError("invalid-string", { | ||
moduleName: "@serwist/routing", | ||
funcName: "registerRoute", | ||
paramName: "capture" | ||
}); | ||
} | ||
const valueToCheck = capture.startsWith("http") ? captureUrl.pathname : capture; | ||
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 (process.env.NODE_ENV !== "production") { | ||
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; | ||
}; | ||
route = new Route(matchCallback, handler, method); | ||
} else if (capture instanceof RegExp) { | ||
route = new RegExpRoute(capture, handler, method); | ||
} else if (typeof capture === "function") { | ||
route = new Route(capture, handler, method); | ||
} else if (capture instanceof Route) { | ||
route = capture; | ||
} else { | ||
throw new SerwistError("unsupported-route-type", { | ||
moduleName: "@serwist/routing", | ||
funcName: "registerRoute", | ||
paramName: "capture" | ||
}); | ||
} | ||
return route; | ||
}; | ||
const registerRoute = (capture, handler, method)=>{ | ||
const route = parseRoute(capture, handler, method); | ||
const defaultRouter = getOrCreateDefaultRouter(); | ||
defaultRouter.registerRoute(route); | ||
return route; | ||
return getSingletonRouter().registerCapture(capture, handler, method); | ||
}; | ||
export { Route as R, RegExpRoute as a, Router as b, getOrCreateDefaultRouter as g, parseRoute as p, registerRoute as r }; | ||
export { registerRoute as r }; |
import { setCacheNameDetails, clientsClaim } from '@serwist/core'; | ||
import { P as PrecacheFallbackPlugin, i as initialize } from './chunks/PrecacheFallbackPlugin.js'; | ||
import { p as precacheAndRoute, P as PrecacheRoute, c as cleanupOutdatedCaches, a as createHandlerBoundToURL } from './chunks/precacheAndRoute.js'; | ||
import { g as getOrCreatePrecacheController } from './chunks/getOrCreatePrecacheController.js'; | ||
import { g as getSingletonPrecacheController } from './chunks/singletonPrecacheController.js'; | ||
import { N as NavigationRoute } from './chunks/NavigationRoute.js'; | ||
import { g as getOrCreateDefaultRouter, p as parseRoute, r as registerRoute } from './chunks/registerRoute.js'; | ||
import { g as getSingletonRouter, p as parseRoute } from './chunks/singletonRouter.js'; | ||
import { S as Strategy } from './chunks/Strategy.js'; | ||
import { logger } from '@serwist/core/internal'; | ||
import { r as registerRoute } from './chunks/registerRoute.js'; | ||
import './chunks/NetworkOnly.js'; | ||
@@ -71,6 +72,6 @@ import 'idb'; | ||
constructor({ precacheController, router } = {}){ | ||
this._precacheController = precacheController || getOrCreatePrecacheController(); | ||
this._router = router || getOrCreateDefaultRouter(); | ||
this._precacheController = precacheController || getSingletonPrecacheController(); | ||
this._router = router || getSingletonRouter(); | ||
} | ||
install({ precacheEntries, precacheOptions, cleanupOutdatedCaches: cleanupOutdatedCaches$1, navigateFallback, navigateFallbackAllowlist, navigateFallbackDenylist, skipWaiting = false, importScripts, navigationPreload = false, cacheId, clientsClaim: clientsClaim$1 = false, runtimeCaching, offlineAnalyticsConfig, disableDevLogs: disableDevLogs$1 = false, fallbacks: fallbacks$1 }) { | ||
install({ precacheEntries, precacheOptions, cleanupOutdatedCaches: cleanupOutdatedCaches$1, navigateFallback, navigateFallbackAllowlist, navigateFallbackDenylist, skipWaiting = false, importScripts, navigationPreload = false, cacheId, clientsClaim: clientsClaim$1 = false, runtimeCaching, offlineAnalyticsConfig, disableDevLogs: disableDevLogs$1 = false, fallbacks: fallbacks$1 } = {}) { | ||
if (!!importScripts && importScripts.length > 0) self.importScripts(...importScripts); | ||
@@ -144,4 +145,4 @@ if (navigationPreload) enableNavigationPreload(); | ||
const serwist = new Serwist({ | ||
precacheController: getOrCreatePrecacheController(), | ||
router: getOrCreateDefaultRouter() | ||
precacheController: getSingletonPrecacheController(), | ||
router: getSingletonRouter() | ||
}); | ||
@@ -148,0 +149,0 @@ serwist.install(options); |
@@ -5,6 +5,6 @@ export { B as BackgroundSyncPlugin, Q as BackgroundSyncQueue, a as BackgroundSyncQueueStore, P as PrecacheFallbackPlugin, S as StorableRequest, i as initializeGoogleAnalytics } from './chunks/PrecacheFallbackPlugin.js'; | ||
import { registerQuotaErrorCallback } from '@serwist/core'; | ||
import './chunks/registerRoute.js'; | ||
import './chunks/singletonRouter.js'; | ||
import './chunks/NetworkOnly.js'; | ||
import './chunks/Strategy.js'; | ||
import './chunks/getOrCreatePrecacheController.js'; | ||
import './chunks/singletonPrecacheController.js'; | ||
@@ -11,0 +11,0 @@ const CACHE_UPDATED_MESSAGE_TYPE = "CACHE_UPDATED"; |
@@ -12,2 +12,3 @@ import { PrecacheController } from "./precaching/PrecacheController.js"; | ||
import { precacheAndRoute } from "./precaching/precacheAndRoute.js"; | ||
import { getSingletonPrecacheController, setSingletonPrecacheController } from "./precaching/singletonPrecacheController.js"; | ||
/** | ||
@@ -23,4 +24,4 @@ * Most consumers of this module will want to use the | ||
*/ | ||
export { addPlugins, addRoute, cleanupOutdatedCaches, createHandlerBoundToURL, getCacheKeyForURL, matchPrecache, precache, precacheAndRoute, PrecacheController, PrecacheRoute, PrecacheStrategy, }; | ||
export { addPlugins, addRoute, cleanupOutdatedCaches, createHandlerBoundToURL, getCacheKeyForURL, matchPrecache, precache, precacheAndRoute, PrecacheController, PrecacheRoute, PrecacheStrategy, getSingletonPrecacheController, setSingletonPrecacheController, }; | ||
export type * from "./precaching/types.js"; | ||
//# sourceMappingURL=index.precaching.d.ts.map |
@@ -1,3 +0,3 @@ | ||
import { g as getOrCreatePrecacheController } from './chunks/getOrCreatePrecacheController.js'; | ||
export { P as PrecacheController, a as PrecacheStrategy } from './chunks/getOrCreatePrecacheController.js'; | ||
import { g as getSingletonPrecacheController } from './chunks/singletonPrecacheController.js'; | ||
export { P as PrecacheController, a as PrecacheStrategy, s as setSingletonPrecacheController } from './chunks/singletonPrecacheController.js'; | ||
export { P as PrecacheRoute, b as addRoute, c as cleanupOutdatedCaches, a as createHandlerBoundToURL, d as precache, p as precacheAndRoute } from './chunks/precacheAndRoute.js'; | ||
@@ -8,5 +8,6 @@ import '@serwist/core/internal'; | ||
import './chunks/registerRoute.js'; | ||
import './chunks/singletonRouter.js'; | ||
const addPlugins = (plugins)=>{ | ||
const precacheController = getOrCreatePrecacheController(); | ||
const precacheController = getSingletonPrecacheController(); | ||
precacheController.strategy.plugins.push(...plugins); | ||
@@ -16,3 +17,3 @@ }; | ||
function getCacheKeyForURL(url) { | ||
const precacheController = getOrCreatePrecacheController(); | ||
const precacheController = getSingletonPrecacheController(); | ||
return precacheController.getCacheKeyForURL(url); | ||
@@ -22,6 +23,5 @@ } | ||
const matchPrecache = (request)=>{ | ||
const precacheController = getOrCreatePrecacheController(); | ||
return precacheController.matchPrecache(request); | ||
return getSingletonPrecacheController().matchPrecache(request); | ||
}; | ||
export { addPlugins, getCacheKeyForURL, matchPrecache }; | ||
export { addPlugins, getCacheKeyForURL, getSingletonPrecacheController, matchPrecache }; |
@@ -6,9 +6,11 @@ import type { NavigationRouteMatchOptions } from "./routing/NavigationRoute.js"; | ||
import { Router } from "./routing/Router.js"; | ||
import { parseRoute } from "./routing/parseRoute.js"; | ||
import { registerRoute } from "./routing/registerRoute.js"; | ||
import { setCatchHandler } from "./routing/setCatchHandler.js"; | ||
import { setDefaultHandler } from "./routing/setDefaultHandler.js"; | ||
import { getSingletonRouter, setSingletonRouter } from "./routing/singletonRouter.js"; | ||
import { unregisterRoute } from "./routing/unregisterRoute.js"; | ||
import type { HTTPMethod } from "./routing/utils/constants.js"; | ||
export { NavigationRoute, RegExpRoute, registerRoute, Route, Router, setCatchHandler, setDefaultHandler, unregisterRoute }; | ||
export { NavigationRoute, RegExpRoute, parseRoute, registerRoute, Route, Router, setCatchHandler, setDefaultHandler, getSingletonRouter, setSingletonRouter, unregisterRoute, }; | ||
export type { HTTPMethod, NavigationRouteMatchOptions }; | ||
//# sourceMappingURL=index.routing.d.ts.map |
export { N as NavigationRoute } from './chunks/NavigationRoute.js'; | ||
import { g as getOrCreateDefaultRouter } from './chunks/registerRoute.js'; | ||
export { a as RegExpRoute, R as Route, b as Router, r as registerRoute } from './chunks/registerRoute.js'; | ||
import { g as getSingletonRouter } from './chunks/singletonRouter.js'; | ||
export { a as RegExpRoute, R as Route, b as Router, p as parseRoute, s as setSingletonRouter } from './chunks/singletonRouter.js'; | ||
export { r as registerRoute } from './chunks/registerRoute.js'; | ||
import '@serwist/core/internal'; | ||
const setCatchHandler = (handler)=>{ | ||
const defaultRouter = getOrCreateDefaultRouter(); | ||
defaultRouter.setCatchHandler(handler); | ||
getSingletonRouter().setCatchHandler(handler); | ||
}; | ||
const setDefaultHandler = (handler)=>{ | ||
const defaultRouter = getOrCreateDefaultRouter(); | ||
defaultRouter.setDefaultHandler(handler); | ||
getSingletonRouter().setDefaultHandler(handler); | ||
}; | ||
const unregisterRoute = (route)=>{ | ||
const defaultRouter = getOrCreateDefaultRouter(); | ||
defaultRouter.unregisterRoute(route); | ||
getSingletonRouter().unregisterRoute(route); | ||
}; | ||
export { setCatchHandler, setDefaultHandler, unregisterRoute }; | ||
export { getSingletonRouter, setCatchHandler, setDefaultHandler, unregisterRoute }; |
@@ -0,3 +1,9 @@ | ||
import type { Router } from "../../routing/Router.js"; | ||
export interface GoogleAnalyticsInitializeOptions { | ||
/** | ||
* An optional `Router` instance. If not provided, the singleton `Router` | ||
* will be used. | ||
*/ | ||
router?: Router; | ||
/** | ||
* The cache name to store and retrieve analytics.js. Defaults to the cache names provided by `@serwist/core`. | ||
@@ -23,5 +29,7 @@ */ | ||
/** | ||
* Initialize Serwist's offline Google Analytics v3 support. | ||
* | ||
* @param options | ||
*/ | ||
export declare const initialize: (options?: GoogleAnalyticsInitializeOptions) => void; | ||
export declare const initialize: ({ cacheName, router, ...options }?: GoogleAnalyticsInitializeOptions) => void; | ||
//# sourceMappingURL=initialize.d.ts.map |
@@ -5,6 +5,6 @@ import type { RouteHandler } from "@serwist/core"; | ||
/** | ||
* RegExpRoute makes it easy to create a regular expression based on a `@serwist/routing` Route. | ||
* `RegExpRoute` makes it easy to create a regular expression based on a `@serwist/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 | ||
* 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. | ||
@@ -11,0 +11,0 @@ */ |
@@ -5,12 +5,12 @@ import type { RouteHandler, RouteMatchCallback } from "@serwist/core"; | ||
/** | ||
* Registers a RegExp, string, or function with a caching | ||
* strategy to a singleton Router instance. | ||
* Registers a `RegExp`, string, or function with a caching | ||
* strategy to a singleton `Router` instance. | ||
* | ||
* @param capture If the capture param is a `Route`, all other arguments will be ignored. | ||
* @param handler A callback function that returns a Promise resulting in a Response. | ||
* @param handler A callback function that returns a `Promise` resulting in a `Response`. | ||
* This parameter is required if `capture` is not a `Route` object. | ||
* @param method The HTTP method to match the Route against. Defaults to GET. | ||
* @returns The generated `Route`. | ||
* @param method The HTTP method to match the `Route` against. Defaults to `'GET'`. | ||
* @returns The generated `Route`, which can then be provided to `unregisterRoute` if needed. | ||
*/ | ||
export declare const registerRoute: (capture: RegExp | string | RouteMatchCallback | Route, handler?: RouteHandler, method?: HTTPMethod) => Route; | ||
//# sourceMappingURL=registerRoute.d.ts.map |
@@ -1,15 +0,14 @@ | ||
import type { RouteHandler, RouteHandlerCallbackOptions, RouteMatchCallbackOptions } from "@serwist/core"; | ||
import type { RouteHandler, RouteHandlerCallbackOptions, RouteMatchCallback, RouteMatchCallbackOptions } from "@serwist/core"; | ||
import type { Route } from "./Route.js"; | ||
import type { HTTPMethod } from "./utils/constants.js"; | ||
/** | ||
* The Router can be used to process a `FetchEvent` using one or more `@serwist/routing` Route(s), | ||
* responding with a `Response` if a matching route exists. | ||
* `Router` can be used to process a `FetchEvent` using one or more `Route`(s), 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. | ||
* If no `Route` matches given a `Request`, the `Router` will use the 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. | ||
* Should the matching Route throw an error, the Router will use the 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. | ||
* If a `Request` matches multiple routes, the earliest registered route will be used to respond to the `Request`. | ||
*/ | ||
@@ -19,2 +18,4 @@ export declare class Router { | ||
private readonly _defaultHandlerMap; | ||
private _fetchListenerHandler; | ||
private _cacheListenerHandler; | ||
private _catchHandler?; | ||
@@ -26,3 +27,3 @@ /** | ||
/** | ||
* @returns routes A `Map` of HTTP method name ('GET', etc.) to an array of all the corresponding `Route` | ||
* @returns routes A `Map` of HTTP method name (`'GET'`, etc.) to an array of all the corresponding `Route` | ||
* instances that are registered. | ||
@@ -32,10 +33,18 @@ */ | ||
/** | ||
* Adds a fetch event listener to respond to events when a route matches | ||
* the event's request. | ||
* Adds a `fetch` event listener to respond to events when a `Route` matches | ||
* the event's request. Effectively no-op if `addFEtchListener` has been | ||
* called, but `removeFetchListener` has not. | ||
*/ | ||
addFetchListener(): void; | ||
/** | ||
* Adds a message event listener for URLs to cache from the window. | ||
* Removes `fetch` event listener added by `addFetchListener`. | ||
* Effectively no-op if either `addFetchListener` has not been called or, | ||
* if it has, so has `removeFetchListener`. | ||
*/ | ||
removeFetchListener(): void; | ||
/** | ||
* 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. | ||
* service worker started controlling it. Effectively no-op if `addCacheListener` | ||
* has been called, but `removeCacheListener` hasn't. | ||
* | ||
@@ -61,4 +70,10 @@ * The format of the message data sent from the window should be as follows. | ||
/** | ||
* Apply the routing rules to a FetchEvent object to get a Response from an | ||
* appropriate Route's handler. | ||
* Removes the `message` event listener added by `addCacheListener`. | ||
* Effectively no-op if either `addCacheListener` has not been called or, | ||
* if it has, so has `removeCacheListener`. | ||
*/ | ||
removeCacheListener(): void; | ||
/** | ||
* Apply the routing rules to a `FetchEvent` object to get a `Response` from an | ||
* appropriate `Route`'s handler. | ||
* | ||
@@ -97,3 +112,3 @@ * @param options | ||
* | ||
* Each HTTP method ('GET', 'POST', etc.) gets its own default handler. | ||
* Each HTTP method (`'GET'`, `'POST'`, etc.) gets its own default handler. | ||
* | ||
@@ -103,9 +118,9 @@ * Without a default handler, unmatched requests will go against the | ||
* | ||
* @param handler A callback function that returns a Promise resulting in a Response. | ||
* @param handler A callback function that returns a `Promise` resulting in a `Response`. | ||
* @param method The HTTP method to associate with this default handler. Each method | ||
* has its own default. Defaults to GET. | ||
* has its own default. Defaults to `'GET'`. | ||
*/ | ||
setDefaultHandler(handler: RouteHandler, method?: HTTPMethod): void; | ||
/** | ||
* If a Route throws an error while handling a request, this `handler` | ||
* If a `Route` throws an error while handling a request, this `handler` | ||
* will be called and given a chance to provide a response. | ||
@@ -118,11 +133,22 @@ * | ||
/** | ||
* Registers a route with the router. | ||
* Registers a `RegExp`, string, or function with a caching | ||
* strategy to the `Router`. | ||
* | ||
* @param route The route to register. | ||
* @param capture If the capture param is a `Route`, all other arguments will be ignored. | ||
* @param handler A callback function that returns a `Promise` resulting in a `Response`. | ||
* This parameter is required if `capture` is not a `Route` object. | ||
* @param method The HTTP method to match the Route against. Defaults to `'GET'`. | ||
* @returns The generated `Route`. | ||
*/ | ||
registerCapture(capture: RegExp | string | RouteMatchCallback | Route, handler?: RouteHandler, method?: HTTPMethod): Route; | ||
/** | ||
* Registers a `Route` with the router. | ||
* | ||
* @param route The `Route` to register. | ||
*/ | ||
registerRoute(route: Route): void; | ||
/** | ||
* Unregisters a route with the router. | ||
* Unregisters a `Route` with the `Router`. | ||
* | ||
* @param route The route to unregister. | ||
* @param route The `Route` to unregister. | ||
*/ | ||
@@ -129,0 +155,0 @@ unregisterRoute(route: Route): void; |
import type { RouteHandler } from "@serwist/core"; | ||
/** | ||
* If a Route throws an error while handling a request, this `handler` | ||
* If a `Route` throws an error while handling a request, this `handler` | ||
* will be called and given a chance to provide a response. | ||
@@ -5,0 +5,0 @@ * |
@@ -6,3 +6,3 @@ import type { RouteHandler } from "@serwist/core"; | ||
* | ||
* Without a default handler, unmatched requests will go against the | ||
* Without a default `handler`, unmatched requests will go against the | ||
* network as if there were no service worker present. | ||
@@ -9,0 +9,0 @@ * |
import type { Route } from "./Route.js"; | ||
/** | ||
* Unregisters a route from the singleton Router instance. | ||
* Unregisters a route from the singleton `Router` instance. | ||
* | ||
@@ -5,0 +5,0 @@ * @param route The route to unregister. |
{ | ||
"name": "@serwist/sw", | ||
"version": "9.0.0-preview.19", | ||
"version": "9.0.0-preview.20", | ||
"type": "module", | ||
@@ -64,3 +64,3 @@ "description": "A service worker helper module.", | ||
"idb": "8.0.0", | ||
"@serwist/core": "9.0.0-preview.19" | ||
"@serwist/core": "9.0.0-preview.20" | ||
}, | ||
@@ -70,4 +70,4 @@ "devDependencies": { | ||
"typescript": "5.5.0-dev.20240323", | ||
"@serwist/constants": "9.0.0-preview.19", | ||
"@serwist/utils": "9.0.0-preview.19" | ||
"@serwist/constants": "9.0.0-preview.20", | ||
"@serwist/utils": "9.0.0-preview.20" | ||
}, | ||
@@ -74,0 +74,0 @@ "peerDependencies": { |
import { logger } from "@serwist/core/internal"; | ||
import { getOrCreatePrecacheController } from "../precaching/utils/getOrCreatePrecacheController.js"; | ||
import { getOrCreateDefaultRouter } from "../routing/utils/getOrCreateDefaultRouter.js"; | ||
import { getSingletonPrecacheController } from "../precaching/singletonPrecacheController.js"; | ||
import { getSingletonRouter } from "../routing/singletonRouter.js"; | ||
import { Serwist, type SerwistInstallOptions } from "./Serwist.js"; | ||
@@ -24,6 +24,6 @@ | ||
const serwist = new Serwist({ | ||
precacheController: getOrCreatePrecacheController(), | ||
router: getOrCreateDefaultRouter(), | ||
precacheController: getSingletonPrecacheController(), | ||
router: getSingletonRouter(), | ||
}); | ||
serwist.install(options); | ||
}; |
@@ -7,7 +7,7 @@ import { clientsClaim as clientsClaimImpl, setCacheNameDetails } from "@serwist/core"; | ||
import { createHandlerBoundToURL } from "../precaching/createHandlerBoundToURL.js"; | ||
import { getOrCreatePrecacheController } from "../precaching/utils/getOrCreatePrecacheController.js"; | ||
import { getSingletonPrecacheController } from "../precaching/singletonPrecacheController.js"; | ||
import { NavigationRoute } from "../routing/NavigationRoute.js"; | ||
import { Router } from "../routing/Router.js"; | ||
import { getOrCreateDefaultRouter } from "../routing/utils/getOrCreateDefaultRouter.js"; | ||
import { parseRoute } from "../routing/utils/parseRoute.js"; | ||
import { parseRoute } from "../routing/parseRoute.js"; | ||
import { getSingletonRouter } from "../routing/singletonRouter.js"; | ||
import { disableDevLogs as disableDevLogsImpl } from "./disableDevLogs.js"; | ||
@@ -24,11 +24,9 @@ import { fallbacks as fallbacksImpl } from "./fallbacks.js"; | ||
/** | ||
* The precache controller that will be used to perform efficient | ||
* precaching of assets. | ||
* @see https://serwist.pages.dev/docs/sw/precaching | ||
* An optional `PrecacheController` instance. If not provided, the singleton | ||
* `PrecacheController` will be used. | ||
*/ | ||
precacheController?: PrecacheController; | ||
/** | ||
* The router that will be used to process a `FetchEvent`, responding | ||
* with a `Response` if a matching route exists. | ||
* @see https://serwist.pages.dev/docs/sw/routing | ||
* An optional `Router` instance. If not provided, the singleton `Router` | ||
* will be used. | ||
*/ | ||
@@ -100,4 +98,4 @@ router?: Router; | ||
constructor({ precacheController, router }: SerwistOptions = {}) { | ||
this._precacheController = precacheController || getOrCreatePrecacheController(); | ||
this._router = router || getOrCreateDefaultRouter(); | ||
this._precacheController = precacheController || getSingletonPrecacheController(); | ||
this._router = router || getSingletonRouter(); | ||
} | ||
@@ -120,3 +118,3 @@ install({ | ||
fallbacks, | ||
}: SerwistInstallOptions) { | ||
}: SerwistInstallOptions = {}) { | ||
if (!!importScripts && importScripts.length > 0) self.importScripts(...importScripts); | ||
@@ -123,0 +121,0 @@ |
@@ -12,2 +12,3 @@ import { PrecacheController } from "./precaching/PrecacheController.js"; | ||
import { precacheAndRoute } from "./precaching/precacheAndRoute.js"; | ||
import { getSingletonPrecacheController, setSingletonPrecacheController } from "./precaching/singletonPrecacheController.js"; | ||
@@ -37,4 +38,6 @@ /** | ||
PrecacheStrategy, | ||
getSingletonPrecacheController, | ||
setSingletonPrecacheController, | ||
}; | ||
export type * from "./precaching/types.js"; |
@@ -6,10 +6,24 @@ import type { NavigationRouteMatchOptions } from "./routing/NavigationRoute.js"; | ||
import { Router } from "./routing/Router.js"; | ||
import { parseRoute } from "./routing/parseRoute.js"; | ||
import { registerRoute } from "./routing/registerRoute.js"; | ||
import { setCatchHandler } from "./routing/setCatchHandler.js"; | ||
import { setDefaultHandler } from "./routing/setDefaultHandler.js"; | ||
import { getSingletonRouter, setSingletonRouter } from "./routing/singletonRouter.js"; | ||
import { unregisterRoute } from "./routing/unregisterRoute.js"; | ||
import type { HTTPMethod } from "./routing/utils/constants.js"; | ||
export { NavigationRoute, RegExpRoute, registerRoute, Route, Router, setCatchHandler, setDefaultHandler, unregisterRoute }; | ||
export { | ||
NavigationRoute, | ||
RegExpRoute, | ||
parseRoute, | ||
registerRoute, | ||
Route, | ||
Router, | ||
setCatchHandler, | ||
setDefaultHandler, | ||
getSingletonRouter, | ||
setSingletonRouter, | ||
unregisterRoute, | ||
}; | ||
export type { HTTPMethod, NavigationRouteMatchOptions }; |
@@ -12,3 +12,2 @@ /* | ||
import { Route } from "../../routing/Route.js"; | ||
import { registerRoute } from "../../routing/registerRoute.js"; | ||
import { NetworkFirst } from "../../strategies/NetworkFirst.js"; | ||
@@ -19,2 +18,4 @@ import { NetworkOnly } from "../../strategies/NetworkOnly.js"; | ||
import type { Router } from "../../routing/Router.js"; | ||
import { getSingletonRouter } from "../../routing/singletonRouter.js"; | ||
import { | ||
@@ -33,2 +34,7 @@ ANALYTICS_JS_PATH, | ||
/** | ||
* An optional `Router` instance. If not provided, the singleton `Router` | ||
* will be used. | ||
*/ | ||
router?: Router; | ||
/** | ||
* The cache name to store and retrieve analytics.js. Defaults to the cache names provided by `@serwist/core`. | ||
@@ -62,3 +68,3 @@ */ | ||
*/ | ||
const createOnSyncCallback = (config: GoogleAnalyticsInitializeOptions) => { | ||
const createOnSyncCallback = (config: Pick<GoogleAnalyticsInitializeOptions, "parameterOverrides" | "hitFilter">) => { | ||
return async ({ queue }: { queue: Queue }) => { | ||
@@ -189,6 +195,8 @@ let entry: QueueEntry | undefined = undefined; | ||
/** | ||
* Initialize Serwist's offline Google Analytics v3 support. | ||
* | ||
* @param options | ||
*/ | ||
export const initialize = (options: GoogleAnalyticsInitializeOptions = {}): void => { | ||
const cacheName = privateCacheNames.getGoogleAnalyticsName(options.cacheName); | ||
export const initialize = ({ cacheName, router = getSingletonRouter(), ...options }: GoogleAnalyticsInitializeOptions = {}): void => { | ||
const resolvedCacheName = privateCacheNames.getGoogleAnalyticsName(cacheName); | ||
@@ -200,7 +208,12 @@ const bgSyncPlugin = new BackgroundSyncPlugin(QUEUE_NAME, { | ||
const routes = [createGtmJsRoute(cacheName), createAnalyticsJsRoute(cacheName), createGtagJsRoute(cacheName), ...createCollectRoutes(bgSyncPlugin)]; | ||
const routes = [ | ||
createGtmJsRoute(resolvedCacheName), | ||
createAnalyticsJsRoute(resolvedCacheName), | ||
createGtagJsRoute(resolvedCacheName), | ||
...createCollectRoutes(bgSyncPlugin), | ||
]; | ||
for (const route of routes) { | ||
registerRoute(route); | ||
router.registerRoute(route); | ||
} | ||
}; |
@@ -12,3 +12,3 @@ /* | ||
import type { PrecacheController } from "../../precaching/PrecacheController.js"; | ||
import { getOrCreatePrecacheController } from "../../precaching/utils/getOrCreatePrecacheController.js"; | ||
import { getSingletonPrecacheController } from "../../precaching/singletonPrecacheController.js"; | ||
@@ -63,3 +63,3 @@ export interface PrecacheFallbackEntry { | ||
this._fallbackUrls = fallbackUrls; | ||
this._precacheController = precacheController || getOrCreatePrecacheController(); | ||
this._precacheController = precacheController || getSingletonPrecacheController(); | ||
} | ||
@@ -66,0 +66,0 @@ |
@@ -11,3 +11,3 @@ /* | ||
import { getOrCreatePrecacheController } from "./utils/getOrCreatePrecacheController.js"; | ||
import { getSingletonPrecacheController } from "./singletonPrecacheController.js"; | ||
@@ -20,4 +20,4 @@ /** | ||
export const addPlugins = (plugins: SerwistPlugin[]): void => { | ||
const precacheController = getOrCreatePrecacheController(); | ||
const precacheController = getSingletonPrecacheController(); | ||
precacheController.strategy.plugins.push(...plugins); | ||
}; |
@@ -10,4 +10,4 @@ /* | ||
import { PrecacheRoute } from "./PrecacheRoute.js"; | ||
import { getSingletonPrecacheController } from "./singletonPrecacheController.js"; | ||
import type { PrecacheRouteOptions } from "./types.js"; | ||
import { getOrCreatePrecacheController } from "./utils/getOrCreatePrecacheController.js"; | ||
@@ -27,3 +27,3 @@ /** | ||
export const addRoute = (options?: PrecacheRouteOptions): void => { | ||
const precacheController = getOrCreatePrecacheController(); | ||
const precacheController = getSingletonPrecacheController(); | ||
@@ -30,0 +30,0 @@ const precacheRoute = new PrecacheRoute(precacheController, options); |
@@ -11,3 +11,3 @@ /* | ||
import { getOrCreatePrecacheController } from "./utils/getOrCreatePrecacheController.js"; | ||
import { getSingletonPrecacheController } from "./singletonPrecacheController.js"; | ||
@@ -29,4 +29,4 @@ /** | ||
export const createHandlerBoundToURL = (url: string): RouteHandlerCallback => { | ||
const precacheController = getOrCreatePrecacheController(); | ||
const precacheController = getSingletonPrecacheController(); | ||
return precacheController.createHandlerBoundToURL(url); | ||
}; |
@@ -9,3 +9,3 @@ /* | ||
import { getOrCreatePrecacheController } from "./utils/getOrCreatePrecacheController.js"; | ||
import { getSingletonPrecacheController } from "./singletonPrecacheController.js"; | ||
@@ -30,3 +30,3 @@ /** | ||
function getCacheKeyForURL(url: string): string | undefined { | ||
const precacheController = getOrCreatePrecacheController(); | ||
const precacheController = getSingletonPrecacheController(); | ||
return precacheController.getCacheKeyForURL(url); | ||
@@ -33,0 +33,0 @@ } |
@@ -9,3 +9,3 @@ /* | ||
import { getOrCreatePrecacheController } from "./utils/getOrCreatePrecacheController.js"; | ||
import { getSingletonPrecacheController } from "./singletonPrecacheController.js"; | ||
@@ -25,4 +25,3 @@ /** | ||
export const matchPrecache = (request: string | Request): Promise<Response | undefined> => { | ||
const precacheController = getOrCreatePrecacheController(); | ||
return precacheController.matchPrecache(request); | ||
return getSingletonPrecacheController().matchPrecache(request); | ||
}; |
@@ -9,4 +9,4 @@ /* | ||
import { getSingletonPrecacheController } from "./singletonPrecacheController.js"; | ||
import type { PrecacheEntry } from "./types.js"; | ||
import { getOrCreatePrecacheController } from "./utils/getOrCreatePrecacheController.js"; | ||
@@ -30,4 +30,4 @@ /** | ||
export const precache = (entries: (PrecacheEntry | string)[]): void => { | ||
const precacheController = getOrCreatePrecacheController(); | ||
const precacheController = getSingletonPrecacheController(); | ||
precacheController.precache(entries); | ||
}; |
@@ -9,5 +9,5 @@ /* | ||
import { getSingletonPrecacheController } from "../singletonPrecacheController.js"; | ||
import type { PrecacheRouteOptions } from "../types.js"; | ||
import { generateURLVariations } from "./generateURLVariations.js"; | ||
import { getOrCreatePrecacheController } from "./getOrCreatePrecacheController.js"; | ||
@@ -26,3 +26,3 @@ /** | ||
export const getCacheKeyForURL = (url: string, options: PrecacheRouteOptions): string | undefined => { | ||
const precacheController = getOrCreatePrecacheController(); | ||
const precacheController = getSingletonPrecacheController(); | ||
@@ -29,0 +29,0 @@ const urlsToCacheKeys = precacheController.getURLsToCacheKeys(); |
@@ -16,6 +16,6 @@ /* | ||
/** | ||
* RegExpRoute makes it easy to create a regular expression based on a `@serwist/routing` Route. | ||
* `RegExpRoute` makes it easy to create a regular expression based on a `@serwist/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 | ||
* 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. | ||
@@ -22,0 +22,0 @@ */ |
@@ -12,23 +12,17 @@ /* | ||
import { Route } from "./Route.js"; | ||
import { getSingletonRouter } from "./singletonRouter.js"; | ||
import type { HTTPMethod } from "./utils/constants.js"; | ||
import { getOrCreateDefaultRouter } from "./utils/getOrCreateDefaultRouter.js"; | ||
import { parseRoute } from "./utils/parseRoute.js"; | ||
/** | ||
* Registers a RegExp, string, or function with a caching | ||
* strategy to a singleton Router instance. | ||
* Registers a `RegExp`, string, or function with a caching | ||
* strategy to a singleton `Router` instance. | ||
* | ||
* @param capture If the capture param is a `Route`, all other arguments will be ignored. | ||
* @param handler A callback function that returns a Promise resulting in a Response. | ||
* @param handler A callback function that returns a `Promise` resulting in a `Response`. | ||
* This parameter is required if `capture` is not a `Route` object. | ||
* @param method The HTTP method to match the Route against. Defaults to GET. | ||
* @returns The generated `Route`. | ||
* @param method The HTTP method to match the `Route` against. Defaults to `'GET'`. | ||
* @returns The generated `Route`, which can then be provided to `unregisterRoute` if needed. | ||
*/ | ||
export const registerRoute = (capture: RegExp | string | RouteMatchCallback | Route, handler?: RouteHandler, method?: HTTPMethod): Route => { | ||
const route = parseRoute(capture, handler, method); | ||
const defaultRouter = getOrCreateDefaultRouter(); | ||
defaultRouter.registerRoute(route); | ||
return route; | ||
return getSingletonRouter().registerCapture(capture, handler, method); | ||
}; |
@@ -9,6 +9,7 @@ /* | ||
import type { RouteHandler, RouteHandlerCallbackOptions, RouteHandlerObject, RouteMatchCallbackOptions } from "@serwist/core"; | ||
import type { RouteHandler, RouteHandlerCallbackOptions, RouteHandlerObject, RouteMatchCallback, RouteMatchCallbackOptions } from "@serwist/core"; | ||
import { assert, SerwistError, getFriendlyURL, logger } from "@serwist/core/internal"; | ||
import type { Route } from "./Route.js"; | ||
import { parseRoute } from "./parseRoute.js"; | ||
import type { HTTPMethod } from "./utils/constants.js"; | ||
@@ -30,12 +31,11 @@ import { defaultMethod } from "./utils/constants.js"; | ||
/** | ||
* The Router can be used to process a `FetchEvent` using one or more `@serwist/routing` Route(s), | ||
* responding with a `Response` if a matching route exists. | ||
* `Router` can be used to process a `FetchEvent` using one or more `Route`(s), 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. | ||
* If no `Route` matches given a `Request`, the `Router` will use the 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. | ||
* Should the matching Route throw an error, the Router will use the 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. | ||
* If a `Request` matches multiple routes, the earliest registered route will be used to respond to the `Request`. | ||
*/ | ||
@@ -45,2 +45,4 @@ export class Router { | ||
private readonly _defaultHandlerMap: Map<HTTPMethod, RouteHandlerObject>; | ||
private _fetchListenerHandler: ((ev: FetchEvent) => void) | null = null; | ||
private _cacheListenerHandler: ((ev: ExtendableMessageEvent) => void) | null = null; | ||
private _catchHandler?: RouteHandlerObject; | ||
@@ -57,3 +59,3 @@ | ||
/** | ||
* @returns routes A `Map` of HTTP method name ('GET', etc.) to an array of all the corresponding `Route` | ||
* @returns routes A `Map` of HTTP method name (`'GET'`, etc.) to an array of all the corresponding `Route` | ||
* instances that are registered. | ||
@@ -66,19 +68,36 @@ */ | ||
/** | ||
* Adds a fetch event listener to respond to events when a route matches | ||
* the event's request. | ||
* Adds a `fetch` event listener to respond to events when a `Route` matches | ||
* the event's request. Effectively no-op if `addFEtchListener` has been | ||
* called, but `removeFetchListener` has not. | ||
*/ | ||
addFetchListener(): void { | ||
self.addEventListener("fetch", (event) => { | ||
const { request } = event; | ||
const responsePromise = this.handleRequest({ request, event }); | ||
if (responsePromise) { | ||
event.respondWith(responsePromise); | ||
} | ||
}); | ||
if (!this._fetchListenerHandler) { | ||
this._fetchListenerHandler = (event) => { | ||
const { request } = event; | ||
const responsePromise = this.handleRequest({ request, event }); | ||
if (responsePromise) { | ||
event.respondWith(responsePromise); | ||
} | ||
}; | ||
self.addEventListener("fetch", this._fetchListenerHandler); | ||
} | ||
} | ||
/** | ||
* Adds a message event listener for URLs to cache from the window. | ||
* Removes `fetch` event listener added by `addFetchListener`. | ||
* Effectively no-op if either `addFetchListener` has not been called or, | ||
* if it has, so has `removeFetchListener`. | ||
*/ | ||
removeFetchListener(): void { | ||
if (this._fetchListenerHandler) { | ||
self.removeEventListener("fetch", this._fetchListenerHandler); | ||
this._fetchListenerHandler = null; | ||
} | ||
} | ||
/** | ||
* 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. | ||
* service worker started controlling it. Effectively no-op if `addCacheListener` | ||
* has been called, but `removeCacheListener` hasn't. | ||
* | ||
@@ -103,34 +122,48 @@ * The format of the message data sent from the window should be as follows. | ||
addCacheListener(): void { | ||
self.addEventListener("message", (event) => { | ||
if (event.data && event.data.type === "CACHE_URLS") { | ||
const { payload }: CacheURLsMessageData = event.data; | ||
if (!this._cacheListenerHandler) { | ||
this._cacheListenerHandler = (event) => { | ||
if (event.data && event.data.type === "CACHE_URLS") { | ||
const { payload }: CacheURLsMessageData = event.data; | ||
if (process.env.NODE_ENV !== "production") { | ||
logger.debug("Caching URLs from the window", payload.urlsToCache); | ||
} | ||
if (process.env.NODE_ENV !== "production") { | ||
logger.debug("Caching URLs from the window", payload.urlsToCache); | ||
} | ||
const requestPromises = Promise.all( | ||
payload.urlsToCache.map((entry: string | [string, RequestInit?]) => { | ||
if (typeof entry === "string") { | ||
entry = [entry]; | ||
} | ||
const requestPromises = Promise.all( | ||
payload.urlsToCache.map((entry: string | [string, RequestInit?]) => { | ||
if (typeof entry === "string") { | ||
entry = [entry]; | ||
} | ||
const request = new Request(...entry); | ||
return this.handleRequest({ request, event }); | ||
}), | ||
); | ||
const request = new Request(...entry); | ||
return this.handleRequest({ request, event }); | ||
}), | ||
); | ||
event.waitUntil(requestPromises); | ||
event.waitUntil(requestPromises); | ||
// If a MessageChannel was used, reply to the message on success. | ||
if (event.ports?.[0]) { | ||
void requestPromises.then(() => event.ports[0].postMessage(true)); | ||
// If a MessageChannel was used, reply to the message on success. | ||
if (event.ports?.[0]) { | ||
void requestPromises.then(() => event.ports[0].postMessage(true)); | ||
} | ||
} | ||
} | ||
}); | ||
}; | ||
self.addEventListener("message", this._cacheListenerHandler); | ||
} | ||
} | ||
/** | ||
* Apply the routing rules to a FetchEvent object to get a Response from an | ||
* appropriate Route's handler. | ||
* Removes the `message` event listener added by `addCacheListener`. | ||
* Effectively no-op if either `addCacheListener` has not been called or, | ||
* if it has, so has `removeCacheListener`. | ||
*/ | ||
removeCacheListener(): void { | ||
if (this._cacheListenerHandler) { | ||
self.removeEventListener("message", this._cacheListenerHandler); | ||
} | ||
} | ||
/** | ||
* Apply the routing rules to a `FetchEvent` object to get a `Response` from an | ||
* appropriate `Route`'s handler. | ||
* | ||
@@ -167,3 +200,3 @@ * @param options | ||
if (process.env.NODE_ENV !== "production") { | ||
logger.debug("The Serwist router only supports URLs that start with 'http'."); | ||
logger.debug("Router only supports URLs that start with 'http'."); | ||
} | ||
@@ -344,3 +377,3 @@ return; | ||
* | ||
* Each HTTP method ('GET', 'POST', etc.) gets its own default handler. | ||
* Each HTTP method (`'GET'`, `'POST'`, etc.) gets its own default handler. | ||
* | ||
@@ -350,5 +383,5 @@ * Without a default handler, unmatched requests will go against the | ||
* | ||
* @param handler A callback function that returns a Promise resulting in a Response. | ||
* @param handler A callback function that returns a `Promise` resulting in a `Response`. | ||
* @param method The HTTP method to associate with this default handler. Each method | ||
* has its own default. Defaults to GET. | ||
* has its own default. Defaults to `'GET'`. | ||
*/ | ||
@@ -360,3 +393,3 @@ setDefaultHandler(handler: RouteHandler, method: HTTPMethod = defaultMethod): void { | ||
/** | ||
* If a Route throws an error while handling a request, this `handler` | ||
* If a `Route` throws an error while handling a request, this `handler` | ||
* will be called and given a chance to provide a response. | ||
@@ -372,6 +405,22 @@ * | ||
/** | ||
* Registers a route with the router. | ||
* Registers a `RegExp`, string, or function with a caching | ||
* strategy to the `Router`. | ||
* | ||
* @param route The route to register. | ||
* @param capture If the capture param is a `Route`, all other arguments will be ignored. | ||
* @param handler A callback function that returns a `Promise` resulting in a `Response`. | ||
* This parameter is required if `capture` is not a `Route` object. | ||
* @param method The HTTP method to match the Route against. Defaults to `'GET'`. | ||
* @returns The generated `Route`. | ||
*/ | ||
registerCapture(capture: RegExp | string | RouteMatchCallback | Route, handler?: RouteHandler, method?: HTTPMethod): Route { | ||
const route = parseRoute(capture, handler, method); | ||
this.registerRoute(route); | ||
return route; | ||
} | ||
/** | ||
* Registers a `Route` with the router. | ||
* | ||
* @param route The `Route` to register. | ||
*/ | ||
registerRoute(route: Route): void { | ||
@@ -425,5 +474,5 @@ if (process.env.NODE_ENV !== "production") { | ||
/** | ||
* Unregisters a route with the router. | ||
* Unregisters a `Route` with the `Router`. | ||
* | ||
* @param route The route to unregister. | ||
* @param route The `Route` to unregister. | ||
*/ | ||
@@ -430,0 +479,0 @@ unregisterRoute(route: Route): void { |
@@ -11,6 +11,6 @@ /* | ||
import { getOrCreateDefaultRouter } from "./utils/getOrCreateDefaultRouter.js"; | ||
import { getSingletonRouter } from "./singletonRouter.js"; | ||
/** | ||
* If a Route throws an error while handling a request, this `handler` | ||
* If a `Route` throws an error while handling a request, this `handler` | ||
* will be called and given a chance to provide a response. | ||
@@ -21,4 +21,3 @@ * | ||
export const setCatchHandler = (handler: RouteHandler): void => { | ||
const defaultRouter = getOrCreateDefaultRouter(); | ||
defaultRouter.setCatchHandler(handler); | ||
getSingletonRouter().setCatchHandler(handler); | ||
}; |
@@ -11,3 +11,3 @@ /* | ||
import { getOrCreateDefaultRouter } from "./utils/getOrCreateDefaultRouter.js"; | ||
import { getSingletonRouter } from "./singletonRouter.js"; | ||
@@ -18,3 +18,3 @@ /** | ||
* | ||
* Without a default handler, unmatched requests will go against the | ||
* Without a default `handler`, unmatched requests will go against the | ||
* network as if there were no service worker present. | ||
@@ -25,4 +25,3 @@ * | ||
export const setDefaultHandler = (handler: RouteHandler): void => { | ||
const defaultRouter = getOrCreateDefaultRouter(); | ||
defaultRouter.setDefaultHandler(handler); | ||
getSingletonRouter().setDefaultHandler(handler); | ||
}; |
import type { Route } from "./Route.js"; | ||
import { getOrCreateDefaultRouter } from "./utils/getOrCreateDefaultRouter.js"; | ||
import { getSingletonRouter } from "./singletonRouter.js"; | ||
/** | ||
* Unregisters a route from the singleton Router instance. | ||
* Unregisters a route from the singleton `Router` instance. | ||
* | ||
@@ -10,4 +10,3 @@ * @param route The route to unregister. | ||
export const unregisterRoute = (route: Route): void => { | ||
const defaultRouter = getOrCreateDefaultRouter(); | ||
defaultRouter.unregisterRoute(route); | ||
getSingletonRouter().unregisterRoute(route); | ||
}; |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Unidentified License
License(Experimental) Something that seems like a license was found, but its contents could not be matched with a known license.
Found 5 instances in 1 package
Unidentified License
License(Experimental) Something that seems like a license was found, but its contents could not be matched with a known license.
Found 5 instances in 1 package
513794
250
12160
+ Added@serwist/core@9.0.0-preview.20(transitive)
- Removed@serwist/core@9.0.0-preview.19(transitive)