@serwist/sw 9.0.0-preview.19 → 9.0.0-preview.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/dist/abstractions/Serwist.d.ts +5 -7
  2. package/dist/abstractions/Serwist.d.ts.map +1 -1
  3. package/dist/chunks/NavigationRoute.js +1 -1
  4. package/dist/chunks/PrecacheFallbackPlugin.js +9 -9
  5. package/dist/chunks/precacheAndRoute.js +6 -5
  6. package/dist/chunks/registerRoute.js +3 -404
  7. package/dist/chunks/{getOrCreatePrecacheController.js → singletonPrecacheController.js} +10 -6
  8. package/dist/chunks/singletonRouter.js +435 -0
  9. package/dist/index.js +8 -7
  10. package/dist/index.plugins.js +2 -2
  11. package/dist/index.precaching.d.ts +2 -1
  12. package/dist/index.precaching.d.ts.map +1 -1
  13. package/dist/index.precaching.js +7 -7
  14. package/dist/index.routing.d.ts +3 -1
  15. package/dist/index.routing.d.ts.map +1 -1
  16. package/dist/index.routing.js +7 -9
  17. package/dist/plugins/googleAnalytics/initialize.d.ts +9 -1
  18. package/dist/plugins/googleAnalytics/initialize.d.ts.map +1 -1
  19. package/dist/precaching/addRoute.d.ts.map +1 -1
  20. package/dist/precaching/matchPrecache.d.ts.map +1 -1
  21. package/dist/precaching/precache.d.ts.map +1 -1
  22. package/dist/precaching/singletonPrecacheController.d.ts +38 -0
  23. package/dist/precaching/singletonPrecacheController.d.ts.map +1 -0
  24. package/dist/precaching/utils/getCacheKeyForURL.d.ts.map +1 -1
  25. package/dist/routing/RegExpRoute.d.ts +3 -3
  26. package/dist/routing/Router.d.ts +49 -23
  27. package/dist/routing/Router.d.ts.map +1 -1
  28. package/dist/routing/parseRoute.d.ts +16 -0
  29. package/dist/routing/parseRoute.d.ts.map +1 -0
  30. package/dist/routing/registerRoute.d.ts +5 -5
  31. package/dist/routing/registerRoute.d.ts.map +1 -1
  32. package/dist/routing/setCatchHandler.d.ts +1 -1
  33. package/dist/routing/setCatchHandler.d.ts.map +1 -1
  34. package/dist/routing/setDefaultHandler.d.ts +1 -1
  35. package/dist/routing/setDefaultHandler.d.ts.map +1 -1
  36. package/dist/routing/singletonRouter.d.ts +47 -0
  37. package/dist/routing/singletonRouter.d.ts.map +1 -0
  38. package/dist/routing/unregisterRoute.d.ts +1 -1
  39. package/dist/routing/unregisterRoute.d.ts.map +1 -1
  40. package/package.json +4 -4
  41. package/src/abstractions/Serwist.ts +10 -12
  42. package/src/abstractions/installSerwist.ts +4 -4
  43. package/src/index.precaching.ts +3 -0
  44. package/src/index.routing.ts +15 -1
  45. package/src/plugins/googleAnalytics/initialize.ts +19 -6
  46. package/src/plugins/precaching/PrecacheFallbackPlugin.ts +2 -2
  47. package/src/precaching/addPlugins.ts +2 -2
  48. package/src/precaching/addRoute.ts +2 -2
  49. package/src/precaching/createHandlerBoundToURL.ts +2 -2
  50. package/src/precaching/getCacheKeyForURL.ts +2 -2
  51. package/src/precaching/matchPrecache.ts +2 -3
  52. package/src/precaching/precache.ts +2 -2
  53. package/src/precaching/singletonPrecacheController.ts +57 -0
  54. package/src/precaching/utils/getCacheKeyForURL.ts +2 -2
  55. package/src/routing/RegExpRoute.ts +3 -3
  56. package/src/routing/Router.ts +101 -52
  57. package/src/routing/{utils/parseRoute.ts → parseRoute.ts} +14 -3
  58. package/src/routing/registerRoute.ts +7 -13
  59. package/src/routing/setCatchHandler.ts +3 -4
  60. package/src/routing/setDefaultHandler.ts +3 -4
  61. package/src/routing/singletonRouter.ts +76 -0
  62. package/src/routing/unregisterRoute.ts +3 -4
  63. package/dist/precaching/utils/getOrCreatePrecacheController.d.ts +0 -7
  64. package/dist/precaching/utils/getOrCreatePrecacheController.d.ts.map +0 -1
  65. package/dist/routing/utils/getOrCreateDefaultRouter.d.ts +0 -10
  66. package/dist/routing/utils/getOrCreateDefaultRouter.d.ts.map +0 -1
  67. package/dist/routing/utils/parseRoute.d.ts +0 -5
  68. package/dist/routing/utils/parseRoute.d.ts.map +0 -1
  69. package/src/precaching/utils/getOrCreatePrecacheController.ts +0 -22
  70. package/src/routing/utils/getOrCreateDefaultRouter.ts +0 -29
@@ -8,7 +8,7 @@
8
8
 
9
9
  import type { RouteHandlerCallback } from "@serwist/core";
10
10
 
11
- import { getOrCreatePrecacheController } from "./utils/getOrCreatePrecacheController.js";
11
+ import { getSingletonPrecacheController } from "./singletonPrecacheController.js";
12
12
 
13
13
  /**
14
14
  * Helper function that calls `PrecacheController#createHandlerBoundToURL`
@@ -25,6 +25,6 @@ import { getOrCreatePrecacheController } from "./utils/getOrCreatePrecacheContro
25
25
  * @return
26
26
  */
27
27
  export const createHandlerBoundToURL = (url: string): RouteHandlerCallback => {
28
- const precacheController = getOrCreatePrecacheController();
28
+ const precacheController = getSingletonPrecacheController();
29
29
  return precacheController.createHandlerBoundToURL(url);
30
30
  };
@@ -6,7 +6,7 @@
6
6
  https://opensource.org/licenses/MIT.
7
7
  */
8
8
 
9
- import { getOrCreatePrecacheController } from "./utils/getOrCreatePrecacheController.js";
9
+ import { getSingletonPrecacheController } from "./singletonPrecacheController.js";
10
10
 
11
11
  /**
12
12
  * Takes in a URL, and returns the corresponding URL that could be used to
@@ -26,7 +26,7 @@ import { getOrCreatePrecacheController } from "./utils/getOrCreatePrecacheContro
26
26
  * @returns The cache key that corresponds to that URL.
27
27
  */
28
28
  function getCacheKeyForURL(url: string): string | undefined {
29
- const precacheController = getOrCreatePrecacheController();
29
+ const precacheController = getSingletonPrecacheController();
30
30
  return precacheController.getCacheKeyForURL(url);
31
31
  }
32
32
 
@@ -6,7 +6,7 @@
6
6
  https://opensource.org/licenses/MIT.
7
7
  */
8
8
 
9
- import { getOrCreatePrecacheController } from "./utils/getOrCreatePrecacheController.js";
9
+ import { getSingletonPrecacheController } from "./singletonPrecacheController.js";
10
10
 
11
11
  /**
12
12
  * Helper function that calls `PrecacheController#matchPrecache`
@@ -21,6 +21,5 @@ import { getOrCreatePrecacheController } from "./utils/getOrCreatePrecacheContro
21
21
  * @returns
22
22
  */
23
23
  export const matchPrecache = (request: string | Request): Promise<Response | undefined> => {
24
- const precacheController = getOrCreatePrecacheController();
25
- return precacheController.matchPrecache(request);
24
+ return getSingletonPrecacheController().matchPrecache(request);
26
25
  };
@@ -6,8 +6,8 @@
6
6
  https://opensource.org/licenses/MIT.
7
7
  */
8
8
 
9
+ import { getSingletonPrecacheController } from "./singletonPrecacheController.js";
9
10
  import type { PrecacheEntry } from "./types.js";
10
- import { getOrCreatePrecacheController } from "./utils/getOrCreatePrecacheController.js";
11
11
 
12
12
  /**
13
13
  * Adds items to the precache list, removing any duplicates and
@@ -26,6 +26,6 @@ import { getOrCreatePrecacheController } from "./utils/getOrCreatePrecacheContro
26
26
  * @param entries Array of entries to precache.
27
27
  */
28
28
  export const precache = (entries: (PrecacheEntry | string)[]): void => {
29
- const precacheController = getOrCreatePrecacheController();
29
+ const precacheController = getSingletonPrecacheController();
30
30
  precacheController.precache(entries);
31
31
  };
@@ -0,0 +1,57 @@
1
+ /*
2
+ Copyright 2019 Google LLC
3
+
4
+ Use of this source code is governed by an MIT-style
5
+ license that can be found in the LICENSE file or at
6
+ https://opensource.org/licenses/MIT.
7
+ */
8
+
9
+ import { PrecacheController } from "./PrecacheController.js";
10
+
11
+ let defaultPrecacheController: PrecacheController | undefined = undefined;
12
+
13
+ /**
14
+ * Creates a new, singleton `PrecacheController` if one does not exist. If one does
15
+ * already exist, that instance is returned. This instance is used by Serwist's
16
+ * `PrecacheController`-dependent functions and classes unless you provide a different
17
+ * `Router` to them.
18
+ *
19
+ * @returns The singleton `PrecacheController`.
20
+ */
21
+ export const getSingletonPrecacheController = (): PrecacheController => {
22
+ if (!defaultPrecacheController) {
23
+ defaultPrecacheController = new PrecacheController();
24
+ }
25
+ return defaultPrecacheController;
26
+ };
27
+
28
+ /**
29
+ * Changes the singleton `PrecacheController` to a different instance. This is meant for when you do not
30
+ * want to pass your own `PrecacheController` to every one of Serwist's `PrecacheController`-dependent
31
+ * functions and classes.
32
+ *
33
+ * It is highly recommended that you call this before anything else, if you plan on doing so.
34
+ *
35
+ * @example
36
+ * ```js
37
+ * import { PrecacheController, setSingletonPrecacheController } from "@serwist/sw/precaching";
38
+ *
39
+ * const controller = new PrecacheController();
40
+ *
41
+ * setSingletonPrecacheController(controller);
42
+ *
43
+ * // Do something with your controller...
44
+ *
45
+ * // This class now automatically picks up your `PrecacheController`! Without `setSingletonPrecacheController`,
46
+ * // you'd need to write this instead: `new Serwist({ controller })`
47
+ * const serwist = new Serwist();
48
+ *
49
+ * serwist.install();
50
+ * ```
51
+ * @param router
52
+ * @returns The new singleton `PrecacheController`.
53
+ */
54
+ export const setSingletonPrecacheController = (precacheController: PrecacheController): PrecacheController => {
55
+ defaultPrecacheController = precacheController;
56
+ return defaultPrecacheController;
57
+ };
@@ -6,9 +6,9 @@
6
6
  https://opensource.org/licenses/MIT.
7
7
  */
8
8
 
9
+ import { getSingletonPrecacheController } from "../singletonPrecacheController.js";
9
10
  import type { PrecacheRouteOptions } from "../types.js";
10
11
  import { generateURLVariations } from "./generateURLVariations.js";
11
- import { getOrCreatePrecacheController } from "./getOrCreatePrecacheController.js";
12
12
 
13
13
  /**
14
14
  * This function will take the request URL and manipulate it based on the
@@ -22,7 +22,7 @@ import { getOrCreatePrecacheController } from "./getOrCreatePrecacheController.j
22
22
  * @private
23
23
  */
24
24
  export const getCacheKeyForURL = (url: string, options: PrecacheRouteOptions): string | undefined => {
25
- const precacheController = getOrCreatePrecacheController();
25
+ const precacheController = getSingletonPrecacheController();
26
26
 
27
27
  const urlsToCacheKeys = precacheController.getURLsToCacheKeys();
28
28
  for (const possibleURL of generateURLVariations(url, options)) {
@@ -13,10 +13,10 @@ import { Route } from "./Route.js";
13
13
  import type { HTTPMethod } from "./utils/constants.js";
14
14
 
15
15
  /**
16
- * RegExpRoute makes it easy to create a regular expression based on a `@serwist/routing` Route.
16
+ * `RegExpRoute` makes it easy to create a regular expression based on a `@serwist/routing` Route.
17
17
  *
18
- * For same-origin requests the RegExp only needs to match part of the URL. For
19
- * requests against third-party servers, you must define a RegExp that matches
18
+ * For same-origin requests the `RegExp` only needs to match part of the URL. For
19
+ * requests against third-party servers, you must define a `RegExp` that matches
20
20
  * the start of the URL.
21
21
  */
22
22
  export class RegExpRoute extends Route {
@@ -6,10 +6,11 @@
6
6
  https://opensource.org/licenses/MIT.
7
7
  */
8
8
 
9
- import type { RouteHandler, RouteHandlerCallbackOptions, RouteHandlerObject, RouteMatchCallbackOptions } from "@serwist/core";
9
+ import type { RouteHandler, RouteHandlerCallbackOptions, RouteHandlerObject, RouteMatchCallback, RouteMatchCallbackOptions } from "@serwist/core";
10
10
  import { assert, SerwistError, getFriendlyURL, logger } from "@serwist/core/internal";
11
11
 
12
12
  import type { Route } from "./Route.js";
13
+ import { parseRoute } from "./parseRoute.js";
13
14
  import type { HTTPMethod } from "./utils/constants.js";
14
15
  import { defaultMethod } from "./utils/constants.js";
15
16
  import { normalizeHandler } from "./utils/normalizeHandler.js";
@@ -26,20 +27,21 @@ interface CacheURLsMessageData {
26
27
  }
27
28
 
28
29
  /**
29
- * The Router can be used to process a `FetchEvent` using one or more `@serwist/routing` Route(s),
30
- * responding with a `Response` if a matching route exists.
30
+ * `Router` can be used to process a `FetchEvent` using one or more `Route`(s), responding with a `Response`
31
+ * if a matching route exists.
31
32
  *
32
- * If no route matches a given a request, the Router will use a "default" handler if one is defined.
33
+ * If no `Route` matches given a `Request`, the `Router` will use the default handler if one is defined.
33
34
  *
34
- * Should the matching Route throw an error, the Router will use a "catch" handler if one is defined to
35
- * gracefully deal with issues and respond with a Request.
35
+ * Should the matching Route throw an error, the Router will use the catch handler if one is defined to
36
+ * gracefully deal with issues and respond with a `Request`.
36
37
  *
37
- * If a request matches multiple routes, the **earliest** registered route will
38
- * be used to respond to the request.
38
+ * If a `Request` matches multiple routes, the earliest registered route will be used to respond to the `Request`.
39
39
  */
40
40
  export class Router {
41
41
  private readonly _routes: Map<HTTPMethod, Route[]>;
42
42
  private readonly _defaultHandlerMap: Map<HTTPMethod, RouteHandlerObject>;
43
+ private _fetchListenerHandler: ((ev: FetchEvent) => void) | null = null;
44
+ private _cacheListenerHandler: ((ev: ExtendableMessageEvent) => void) | null = null;
43
45
  private _catchHandler?: RouteHandlerObject;
44
46
 
45
47
  /**
@@ -51,7 +53,7 @@ export class Router {
51
53
  }
52
54
 
53
55
  /**
54
- * @returns routes A `Map` of HTTP method name ('GET', etc.) to an array of all the corresponding `Route`
56
+ * @returns routes A `Map` of HTTP method name (`'GET'`, etc.) to an array of all the corresponding `Route`
55
57
  * instances that are registered.
56
58
  */
57
59
  get routes(): Map<HTTPMethod, Route[]> {
@@ -59,23 +61,40 @@ export class Router {
59
61
  }
60
62
 
61
63
  /**
62
- * Adds a fetch event listener to respond to events when a route matches
63
- * the event's request.
64
+ * Adds a `fetch` event listener to respond to events when a `Route` matches
65
+ * the event's request. Effectively no-op if `addFEtchListener` has been
66
+ * called, but `removeFetchListener` has not.
64
67
  */
65
68
  addFetchListener(): void {
66
- self.addEventListener("fetch", (event) => {
67
- const { request } = event;
68
- const responsePromise = this.handleRequest({ request, event });
69
- if (responsePromise) {
70
- event.respondWith(responsePromise);
71
- }
72
- });
69
+ if (!this._fetchListenerHandler) {
70
+ this._fetchListenerHandler = (event) => {
71
+ const { request } = event;
72
+ const responsePromise = this.handleRequest({ request, event });
73
+ if (responsePromise) {
74
+ event.respondWith(responsePromise);
75
+ }
76
+ };
77
+ self.addEventListener("fetch", this._fetchListenerHandler);
78
+ }
79
+ }
80
+
81
+ /**
82
+ * Removes `fetch` event listener added by `addFetchListener`.
83
+ * Effectively no-op if either `addFetchListener` has not been called or,
84
+ * if it has, so has `removeFetchListener`.
85
+ */
86
+ removeFetchListener(): void {
87
+ if (this._fetchListenerHandler) {
88
+ self.removeEventListener("fetch", this._fetchListenerHandler);
89
+ this._fetchListenerHandler = null;
90
+ }
73
91
  }
74
92
 
75
93
  /**
76
- * Adds a message event listener for URLs to cache from the window.
94
+ * Adds a `message` event listener for URLs to cache from the window.
77
95
  * This is useful to cache resources loaded on the page prior to when the
78
- * service worker started controlling it.
96
+ * service worker started controlling it. Effectively no-op if `addCacheListener`
97
+ * has been called, but `removeCacheListener` hasn't.
79
98
  *
80
99
  * The format of the message data sent from the window should be as follows.
81
100
  * Where the `urlsToCache` array may consist of URL strings or an array of
@@ -95,38 +114,52 @@ export class Router {
95
114
  * ```
96
115
  */
97
116
  addCacheListener(): void {
98
- self.addEventListener("message", (event) => {
99
- if (event.data && event.data.type === "CACHE_URLS") {
100
- const { payload }: CacheURLsMessageData = event.data;
117
+ if (!this._cacheListenerHandler) {
118
+ this._cacheListenerHandler = (event) => {
119
+ if (event.data && event.data.type === "CACHE_URLS") {
120
+ const { payload }: CacheURLsMessageData = event.data;
101
121
 
102
- if (process.env.NODE_ENV !== "production") {
103
- logger.debug("Caching URLs from the window", payload.urlsToCache);
104
- }
122
+ if (process.env.NODE_ENV !== "production") {
123
+ logger.debug("Caching URLs from the window", payload.urlsToCache);
124
+ }
105
125
 
106
- const requestPromises = Promise.all(
107
- payload.urlsToCache.map((entry: string | [string, RequestInit?]) => {
108
- if (typeof entry === "string") {
109
- entry = [entry];
110
- }
126
+ const requestPromises = Promise.all(
127
+ payload.urlsToCache.map((entry: string | [string, RequestInit?]) => {
128
+ if (typeof entry === "string") {
129
+ entry = [entry];
130
+ }
111
131
 
112
- const request = new Request(...entry);
113
- return this.handleRequest({ request, event });
114
- }),
115
- );
132
+ const request = new Request(...entry);
133
+ return this.handleRequest({ request, event });
134
+ }),
135
+ );
116
136
 
117
- event.waitUntil(requestPromises);
137
+ event.waitUntil(requestPromises);
118
138
 
119
- // If a MessageChannel was used, reply to the message on success.
120
- if (event.ports?.[0]) {
121
- void requestPromises.then(() => event.ports[0].postMessage(true));
139
+ // If a MessageChannel was used, reply to the message on success.
140
+ if (event.ports?.[0]) {
141
+ void requestPromises.then(() => event.ports[0].postMessage(true));
142
+ }
122
143
  }
123
- }
124
- });
144
+ };
145
+ self.addEventListener("message", this._cacheListenerHandler);
146
+ }
147
+ }
148
+
149
+ /**
150
+ * Removes the `message` event listener added by `addCacheListener`.
151
+ * Effectively no-op if either `addCacheListener` has not been called or,
152
+ * if it has, so has `removeCacheListener`.
153
+ */
154
+ removeCacheListener(): void {
155
+ if (this._cacheListenerHandler) {
156
+ self.removeEventListener("message", this._cacheListenerHandler);
157
+ }
125
158
  }
126
159
 
127
160
  /**
128
- * Apply the routing rules to a FetchEvent object to get a Response from an
129
- * appropriate Route's handler.
161
+ * Apply the routing rules to a `FetchEvent` object to get a `Response` from an
162
+ * appropriate `Route`'s handler.
130
163
  *
131
164
  * @param options
132
165
  * @returns A promise is returned if a registered route can handle the request.
@@ -158,7 +191,7 @@ export class Router {
158
191
  const url = new URL(request.url, location.href);
159
192
  if (!url.protocol.startsWith("http")) {
160
193
  if (process.env.NODE_ENV !== "production") {
161
- logger.debug("The Serwist router only supports URLs that start with 'http'.");
194
+ logger.debug("Router only supports URLs that start with 'http'.");
162
195
  }
163
196
  return;
164
197
  }
@@ -334,21 +367,21 @@ export class Router {
334
367
  * Define a default `handler` that's called when no routes explicitly
335
368
  * match the incoming request.
336
369
  *
337
- * Each HTTP method ('GET', 'POST', etc.) gets its own default handler.
370
+ * Each HTTP method (`'GET'`, `'POST'`, etc.) gets its own default handler.
338
371
  *
339
372
  * Without a default handler, unmatched requests will go against the
340
373
  * network as if there were no service worker present.
341
374
  *
342
- * @param handler A callback function that returns a Promise resulting in a Response.
375
+ * @param handler A callback function that returns a `Promise` resulting in a `Response`.
343
376
  * @param method The HTTP method to associate with this default handler. Each method
344
- * has its own default. Defaults to GET.
377
+ * has its own default. Defaults to `'GET'`.
345
378
  */
346
379
  setDefaultHandler(handler: RouteHandler, method: HTTPMethod = defaultMethod): void {
347
380
  this._defaultHandlerMap.set(method, normalizeHandler(handler));
348
381
  }
349
382
 
350
383
  /**
351
- * If a Route throws an error while handling a request, this `handler`
384
+ * If a `Route` throws an error while handling a request, this `handler`
352
385
  * will be called and given a chance to provide a response.
353
386
  *
354
387
  * @param handler A callback function that returns a Promise resulting
@@ -359,9 +392,25 @@ export class Router {
359
392
  }
360
393
 
361
394
  /**
362
- * Registers a route with the router.
395
+ * Registers a `RegExp`, string, or function with a caching
396
+ * strategy to the `Router`.
397
+ *
398
+ * @param capture If the capture param is a `Route`, all other arguments will be ignored.
399
+ * @param handler A callback function that returns a `Promise` resulting in a `Response`.
400
+ * This parameter is required if `capture` is not a `Route` object.
401
+ * @param method The HTTP method to match the Route against. Defaults to `'GET'`.
402
+ * @returns The generated `Route`.
403
+ */
404
+ registerCapture(capture: RegExp | string | RouteMatchCallback | Route, handler?: RouteHandler, method?: HTTPMethod): Route {
405
+ const route = parseRoute(capture, handler, method);
406
+ this.registerRoute(route);
407
+ return route;
408
+ }
409
+
410
+ /**
411
+ * Registers a `Route` with the router.
363
412
  *
364
- * @param route The route to register.
413
+ * @param route The `Route` to register.
365
414
  */
366
415
  registerRoute(route: Route): void {
367
416
  if (process.env.NODE_ENV !== "production") {
@@ -411,9 +460,9 @@ export class Router {
411
460
  }
412
461
 
413
462
  /**
414
- * Unregisters a route with the router.
463
+ * Unregisters a `Route` with the `Router`.
415
464
  *
416
- * @param route The route to unregister.
465
+ * @param route The `Route` to unregister.
417
466
  */
418
467
  unregisterRoute(route: Route): void {
419
468
  if (!this._routes.has(route.method)) {
@@ -1,10 +1,21 @@
1
1
  import type { RouteHandler, RouteMatchCallback } from "@serwist/core";
2
2
  import { SerwistError, logger } from "@serwist/core/internal";
3
3
 
4
- import { RegExpRoute } from "../RegExpRoute.js";
5
- import { Route } from "../Route.js";
6
- import type { HTTPMethod } from "./constants.js";
4
+ import { RegExpRoute } from "./RegExpRoute.js";
5
+ import { Route } from "./Route.js";
6
+ import type { HTTPMethod } from "./utils/constants.js";
7
7
 
8
+ /**
9
+ * Parses a `RegExp`, string, or function with a caching strategy into a `Route`. This is for
10
+ * when you want to create a `Route`, but you don't want to register it just yet: sometimes
11
+ * you want to call `setCatchHandler` first, for example.
12
+ *
13
+ * @param capture If the capture param is a `Route`, all other arguments will be ignored.
14
+ * @param handler A callback function that returns a `Promise` resulting in a `Response`.
15
+ * This parameter is required if `capture` is not a `Route` object.
16
+ * @param method The HTTP method to match the `Route` against. Defaults to `'GET'`.
17
+ * @returns The generated `Route`.
18
+ */
8
19
  export const parseRoute = (capture: RegExp | string | RouteMatchCallback | Route, handler?: RouteHandler, method?: HTTPMethod): Route => {
9
20
  let route: Route;
10
21
 
@@ -9,25 +9,19 @@
9
9
  import type { RouteHandler, RouteMatchCallback } from "@serwist/core";
10
10
 
11
11
  import { Route } from "./Route.js";
12
+ import { getSingletonRouter } from "./singletonRouter.js";
12
13
  import type { HTTPMethod } from "./utils/constants.js";
13
- import { getOrCreateDefaultRouter } from "./utils/getOrCreateDefaultRouter.js";
14
- import { parseRoute } from "./utils/parseRoute.js";
15
14
 
16
15
  /**
17
- * Registers a RegExp, string, or function with a caching
18
- * strategy to a singleton Router instance.
16
+ * Registers a `RegExp`, string, or function with a caching
17
+ * strategy to a singleton `Router` instance.
19
18
  *
20
19
  * @param capture If the capture param is a `Route`, all other arguments will be ignored.
21
- * @param handler A callback function that returns a Promise resulting in a Response.
20
+ * @param handler A callback function that returns a `Promise` resulting in a `Response`.
22
21
  * This parameter is required if `capture` is not a `Route` object.
23
- * @param method The HTTP method to match the Route against. Defaults to GET.
24
- * @returns The generated `Route`.
22
+ * @param method The HTTP method to match the `Route` against. Defaults to `'GET'`.
23
+ * @returns The generated `Route`, which can then be provided to `unregisterRoute` if needed.
25
24
  */
26
25
  export const registerRoute = (capture: RegExp | string | RouteMatchCallback | Route, handler?: RouteHandler, method?: HTTPMethod): Route => {
27
- const route = parseRoute(capture, handler, method);
28
-
29
- const defaultRouter = getOrCreateDefaultRouter();
30
- defaultRouter.registerRoute(route);
31
-
32
- return route;
26
+ return getSingletonRouter().registerCapture(capture, handler, method);
33
27
  };
@@ -8,15 +8,14 @@
8
8
 
9
9
  import type { RouteHandler } from "@serwist/core";
10
10
 
11
- import { getOrCreateDefaultRouter } from "./utils/getOrCreateDefaultRouter.js";
11
+ import { getSingletonRouter } from "./singletonRouter.js";
12
12
 
13
13
  /**
14
- * If a Route throws an error while handling a request, this `handler`
14
+ * If a `Route` throws an error while handling a request, this `handler`
15
15
  * will be called and given a chance to provide a response.
16
16
  *
17
17
  * @param handler A callback function that returns a Promise resulting in a Response.
18
18
  */
19
19
  export const setCatchHandler = (handler: RouteHandler): void => {
20
- const defaultRouter = getOrCreateDefaultRouter();
21
- defaultRouter.setCatchHandler(handler);
20
+ getSingletonRouter().setCatchHandler(handler);
22
21
  };
@@ -8,18 +8,17 @@
8
8
 
9
9
  import type { RouteHandler } from "@serwist/core";
10
10
 
11
- import { getOrCreateDefaultRouter } from "./utils/getOrCreateDefaultRouter.js";
11
+ import { getSingletonRouter } from "./singletonRouter.js";
12
12
 
13
13
  /**
14
14
  * Defines a default `handler` that's called when no routes explicitly
15
15
  * match the incoming request.
16
16
  *
17
- * Without a default handler, unmatched requests will go against the
17
+ * Without a default `handler`, unmatched requests will go against the
18
18
  * network as if there were no service worker present.
19
19
  *
20
20
  * @param handler A callback function that returns a Promise resulting in a Response.
21
21
  */
22
22
  export const setDefaultHandler = (handler: RouteHandler): void => {
23
- const defaultRouter = getOrCreateDefaultRouter();
24
- defaultRouter.setDefaultHandler(handler);
23
+ getSingletonRouter().setDefaultHandler(handler);
25
24
  };
@@ -0,0 +1,76 @@
1
+ /*
2
+ Copyright 2019 Google LLC
3
+
4
+ Use of this source code is governed by an MIT-style
5
+ license that can be found in the LICENSE file or at
6
+ https://opensource.org/licenses/MIT.
7
+ */
8
+
9
+ import { Router } from "./Router.js";
10
+
11
+ let defaultRouter: Router | undefined = undefined;
12
+
13
+ /**
14
+ * Creates a new, singleton `Router` if one does not exist. If one does
15
+ * already exist, that instance is returned. This instance is used by
16
+ * Serwist's `Router`-dependent functions and classes unless you provide
17
+ * a different `Router` to them.
18
+ *
19
+ * @returns The singleton `Router`.
20
+ */
21
+ export const getSingletonRouter = (): Router => {
22
+ if (!defaultRouter) {
23
+ defaultRouter = new Router();
24
+
25
+ // The helpers that use the default Router assume these listeners exist.
26
+ defaultRouter.addFetchListener();
27
+ defaultRouter.addCacheListener();
28
+ }
29
+ return defaultRouter;
30
+ };
31
+
32
+ /**
33
+ * Changes the singleton `Router` to a different instance. This is meant for when you do not
34
+ * want to pass your own `Router` to every one of Serwist's `Router`-dependent functions and classes.
35
+ * If this or `getSingletonRouter` has been called before, it removes the listeners of the
36
+ * previous singleton `Router`. It also adds those of the new one, so you need not do that yourself.
37
+ *
38
+ * It is highly recommended that you call this before anything else, if you plan on doing so.
39
+ *
40
+ * @example
41
+ * ```js
42
+ * import { Router, setSingletonRouter } from "@serwist/sw/routing";
43
+ *
44
+ * const router = new Router();
45
+ *
46
+ * setSingletonRouter(router);
47
+ *
48
+ * router.registerRoute(
49
+ * new Route(
50
+ * /\/api\/.*\/*.json/,
51
+ * new NetworkOnly({
52
+ * plugins: [backgroundSync],
53
+ * }),
54
+ * "POST",
55
+ * ),
56
+ * );
57
+ *
58
+ * // This class now automatically picks up your `Router`! Without `setSingletonRouter`, you'd need to
59
+ * // write this instead: `new Serwist({ router })`
60
+ * const serwist = new Serwist();
61
+ *
62
+ * serwist.install();
63
+ * ```
64
+ * @param router
65
+ * @returns The new singleton `Router`.
66
+ */
67
+ export const setSingletonRouter = (router: Router): Router => {
68
+ if (defaultRouter) {
69
+ defaultRouter.removeFetchListener();
70
+ defaultRouter.removeCacheListener();
71
+ }
72
+ defaultRouter = router;
73
+ defaultRouter.addFetchListener();
74
+ defaultRouter.addCacheListener();
75
+ return defaultRouter;
76
+ };
@@ -1,12 +1,11 @@
1
1
  import type { Route } from "./Route.js";
2
- import { getOrCreateDefaultRouter } from "./utils/getOrCreateDefaultRouter.js";
2
+ import { getSingletonRouter } from "./singletonRouter.js";
3
3
 
4
4
  /**
5
- * Unregisters a route from the singleton Router instance.
5
+ * Unregisters a route from the singleton `Router` instance.
6
6
  *
7
7
  * @param route The route to unregister.
8
8
  */
9
9
  export const unregisterRoute = (route: Route): void => {
10
- const defaultRouter = getOrCreateDefaultRouter();
11
- defaultRouter.unregisterRoute(route);
10
+ getSingletonRouter().unregisterRoute(route);
12
11
  };
@@ -1,7 +0,0 @@
1
- import { PrecacheController } from "../PrecacheController.js";
2
- /**
3
- * @returns
4
- * @private
5
- */
6
- export declare const getOrCreatePrecacheController: () => PrecacheController;
7
- //# sourceMappingURL=getOrCreatePrecacheController.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"getOrCreatePrecacheController.d.ts","sourceRoot":"","sources":["../../../src/precaching/utils/getOrCreatePrecacheController.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAI9D;;;GAGG;AACH,eAAO,MAAM,6BAA6B,QAAO,kBAKhD,CAAC"}
@@ -1,10 +0,0 @@
1
- import { Router } from "../Router.js";
2
- /**
3
- * Creates a new, singleton Router instance if one does not exist. If one
4
- * does already exist, that instance is returned.
5
- *
6
- * @private
7
- * @returns
8
- */
9
- export declare const getOrCreateDefaultRouter: () => Router;
10
- //# sourceMappingURL=getOrCreateDefaultRouter.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"getOrCreateDefaultRouter.d.ts","sourceRoot":"","sources":["../../../src/routing/utils/getOrCreateDefaultRouter.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAItC;;;;;;GAMG;AACH,eAAO,MAAM,wBAAwB,QAAO,MAS3C,CAAC"}
@@ -1,5 +0,0 @@
1
- import type { RouteHandler, RouteMatchCallback } from "@serwist/core";
2
- import { Route } from "../Route.js";
3
- import type { HTTPMethod } from "./constants.js";
4
- export declare const parseRoute: (capture: RegExp | string | RouteMatchCallback | Route, handler?: RouteHandler, method?: HTTPMethod) => Route;
5
- //# sourceMappingURL=parseRoute.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"parseRoute.d.ts","sourceRoot":"","sources":["../../../src/routing/utils/parseRoute.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAItE,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AACpC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAEjD,eAAO,MAAM,UAAU,YAAa,MAAM,GAAG,MAAM,GAAG,kBAAkB,GAAG,KAAK,YAAY,YAAY,WAAW,UAAU,KAAG,KA2D/H,CAAC"}