@serwist/strategies 9.0.0-preview.2 → 9.0.0-preview.21

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.
package/src/Strategy.ts DELETED
@@ -1,205 +0,0 @@
1
- /*
2
- Copyright 2020 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 type { HandlerCallbackOptions, RouteHandlerObject, SerwistPlugin } from "@serwist/core";
10
- import { SerwistError, getFriendlyURL, logger, privateCacheNames } from "@serwist/core/internal";
11
-
12
- import { StrategyHandler } from "./StrategyHandler.js";
13
-
14
- export interface StrategyOptions {
15
- /**
16
- * Cache name to store and retrieve requests. Defaults to cache names provided by `@serwist/core`.
17
- */
18
- cacheName?: string;
19
- /**
20
- * [Plugins](https://developers.google.com/web/tools/workbox/guides/using-plugins)
21
- * to use in conjunction with this caching strategy.
22
- */
23
- plugins?: SerwistPlugin[];
24
- /**
25
- * Values passed along to the [`init`](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch#Parameters)
26
- * of [non-navigation](https://github.com/GoogleChrome/workbox/issues/1796) `fetch()` requests made by this strategy.
27
- */
28
- fetchOptions?: RequestInit;
29
- /**
30
- * The [`CacheQueryOptions`](https://w3c.github.io/ServiceWorker/#dictdef-cachequeryoptions)
31
- * for any `cache.match()` or `cache.put()` calls made by this strategy.
32
- */
33
- matchOptions?: CacheQueryOptions;
34
- }
35
-
36
- /**
37
- * Classes extending the `Strategy` based class should implement this method,
38
- * and leverage `@serwist/strategies`'s `StrategyHandler` arg to perform all
39
- * fetching and cache logic, which will ensure all relevant cache, cache options,
40
- * fetch options and plugins are used (per the current strategy instance).
41
- */
42
- abstract class Strategy implements RouteHandlerObject {
43
- cacheName: string;
44
- plugins: SerwistPlugin[];
45
- fetchOptions?: RequestInit;
46
- matchOptions?: CacheQueryOptions;
47
-
48
- protected abstract _handle(request: Request, handler: StrategyHandler): Promise<Response | undefined>;
49
-
50
- /**
51
- * Creates a new instance of the strategy and sets all documented option
52
- * properties as public instance properties.
53
- *
54
- * Note: if a custom strategy class extends the base Strategy class and does
55
- * not need more than these properties, it does not need to define its own
56
- * constructor.
57
- *
58
- * @param options
59
- */
60
- constructor(options: StrategyOptions = {}) {
61
- this.cacheName = privateCacheNames.getRuntimeName(options.cacheName);
62
- this.plugins = options.plugins || [];
63
- this.fetchOptions = options.fetchOptions;
64
- this.matchOptions = options.matchOptions;
65
- }
66
-
67
- /**
68
- * Perform a request strategy and returns a `Promise` that will resolve with
69
- * a `Response`, invoking all relevant plugin callbacks.
70
- *
71
- * When a strategy instance is registered with a `@serwist/routing` Route, this method is automatically
72
- * called when the route matches.
73
- *
74
- * Alternatively, this method can be used in a standalone `FetchEvent`
75
- * listener by passing it to `event.respondWith()`.
76
- *
77
- * @param options A `FetchEvent` or an object with the properties listed below.
78
- * @param options.request A request to run this strategy for.
79
- * @param options.event The event associated with the request.
80
- * @param options.url
81
- * @param options.params
82
- */
83
- handle(options: FetchEvent | HandlerCallbackOptions): Promise<Response> {
84
- const [responseDone] = this.handleAll(options);
85
- return responseDone;
86
- }
87
-
88
- /**
89
- * Similar to `@serwist/strategies`'s `Strategy.handle`, but
90
- * instead of just returning a `Promise` that resolves to a `Response` it
91
- * it will return an tuple of `[response, done]` promises, where the former
92
- * (`response`) is equivalent to what `handle()` returns, and the latter is a
93
- * Promise that will resolve once any promises that were added to
94
- * `event.waitUntil()` as part of performing the strategy have completed.
95
- *
96
- * You can await the `done` promise to ensure any extra work performed by
97
- * the strategy (usually caching responses) completes successfully.
98
- *
99
- * @param options A `FetchEvent` or `HandlerCallbackOptions` object.
100
- * @returns A tuple of [response, done] promises that can be used to determine when the response resolves as
101
- * well as when the handler has completed all its work.
102
- */
103
- handleAll(options: FetchEvent | HandlerCallbackOptions): [Promise<Response>, Promise<void>] {
104
- // Allow for flexible options to be passed.
105
- if (options instanceof FetchEvent) {
106
- options = {
107
- event: options,
108
- request: options.request,
109
- };
110
- }
111
-
112
- const event = options.event;
113
- const request = typeof options.request === "string" ? new Request(options.request) : options.request;
114
- const params = "params" in options ? options.params : undefined;
115
-
116
- const handler = new StrategyHandler(this, { event, request, params });
117
-
118
- const responseDone = this._getResponse(handler, request, event);
119
- const handlerDone = this._awaitComplete(responseDone, handler, request, event);
120
-
121
- // Return an array of promises, suitable for use with Promise.all().
122
- return [responseDone, handlerDone];
123
- }
124
-
125
- async _getResponse(handler: StrategyHandler, request: Request, event: ExtendableEvent): Promise<Response> {
126
- await handler.runCallbacks("handlerWillStart", { event, request });
127
-
128
- let response: Response | undefined = undefined;
129
- try {
130
- response = await this._handle(request, handler);
131
- // The "official" Strategy subclasses all throw this error automatically,
132
- // but in case a third-party Strategy doesn't, ensure that we have a
133
- // consistent failure when there's no response or an error response.
134
- if (response === undefined || response.type === "error") {
135
- throw new SerwistError("no-response", { url: request.url });
136
- }
137
- } catch (error) {
138
- if (error instanceof Error) {
139
- for (const callback of handler.iterateCallbacks("handlerDidError")) {
140
- response = await callback({ error, event, request });
141
- if (response !== undefined) {
142
- break;
143
- }
144
- }
145
- }
146
-
147
- if (!response) {
148
- throw error;
149
- }
150
- if (process.env.NODE_ENV !== "production") {
151
- throw logger.log(
152
- `While responding to '${getFriendlyURL(request.url)}', an ${
153
- error instanceof Error ? error.toString() : ""
154
- } error occurred. Using a fallback response provided by a handlerDidError plugin.`,
155
- );
156
- }
157
- }
158
-
159
- for (const callback of handler.iterateCallbacks("handlerWillRespond")) {
160
- response = (await callback({ event, request, response })) as Response;
161
- }
162
-
163
- return response;
164
- }
165
-
166
- async _awaitComplete(responseDone: Promise<Response>, handler: StrategyHandler, request: Request, event: ExtendableEvent): Promise<void> {
167
- let response: Response | undefined = undefined;
168
- let error: Error | undefined = undefined;
169
-
170
- try {
171
- response = await responseDone;
172
- } catch (error) {
173
- // Ignore errors, as response errors should be caught via the `response`
174
- // promise above. The `done` promise will only throw for errors in
175
- // promises passed to `handler.waitUntil()`.
176
- }
177
-
178
- try {
179
- await handler.runCallbacks("handlerDidRespond", {
180
- event,
181
- request,
182
- response,
183
- });
184
- await handler.doneWaiting();
185
- } catch (waitUntilError) {
186
- if (waitUntilError instanceof Error) {
187
- error = waitUntilError;
188
- }
189
- }
190
-
191
- await handler.runCallbacks("handlerDidComplete", {
192
- event,
193
- request,
194
- response,
195
- error,
196
- });
197
- handler.destroy();
198
-
199
- if (error) {
200
- throw error;
201
- }
202
- }
203
- }
204
-
205
- export { Strategy };