source: frontend/node_modules/workbox-strategies/src/Strategy.ts

Last change on this file was 9af201e, checked in by MBK <marija.karapandzova@…>, 13 days ago

Fix frontend appearance

  • Property mode set to 100644
File size: 9.4 KB
Line 
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
9import {cacheNames} from 'workbox-core/_private/cacheNames.js';
10import {WorkboxError} from 'workbox-core/_private/WorkboxError.js';
11import {logger} from 'workbox-core/_private/logger.js';
12import {getFriendlyURL} from 'workbox-core/_private/getFriendlyURL.js';
13import {
14 HandlerCallbackOptions,
15 RouteHandlerObject,
16 WorkboxPlugin,
17} from 'workbox-core/types.js';
18
19import {StrategyHandler} from './StrategyHandler.js';
20
21import './_version.js';
22
23export interface StrategyOptions {
24 cacheName?: string;
25 plugins?: WorkboxPlugin[];
26 fetchOptions?: RequestInit;
27 matchOptions?: CacheQueryOptions;
28}
29
30/**
31 * An abstract base class that all other strategy classes must extend from:
32 *
33 * @memberof workbox-strategies
34 */
35abstract class Strategy implements RouteHandlerObject {
36 cacheName: string;
37 plugins: WorkboxPlugin[];
38 fetchOptions?: RequestInit;
39 matchOptions?: CacheQueryOptions;
40
41 protected abstract _handle(
42 request: Request,
43 handler: StrategyHandler,
44 ): Promise<Response | undefined>;
45
46 /**
47 * Creates a new instance of the strategy and sets all documented option
48 * properties as public instance properties.
49 *
50 * Note: if a custom strategy class extends the base Strategy class and does
51 * not need more than these properties, it does not need to define its own
52 * constructor.
53 *
54 * @param {Object} [options]
55 * @param {string} [options.cacheName] Cache name to store and retrieve
56 * requests. Defaults to the cache names provided by
57 * {@link workbox-core.cacheNames}.
58 * @param {Array<Object>} [options.plugins] [Plugins]{@link https://developers.google.com/web/tools/workbox/guides/using-plugins}
59 * to use in conjunction with this caching strategy.
60 * @param {Object} [options.fetchOptions] Values passed along to the
61 * [`init`](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch#Parameters)
62 * of [non-navigation](https://github.com/GoogleChrome/workbox/issues/1796)
63 * `fetch()` requests made by this strategy.
64 * @param {Object} [options.matchOptions] The
65 * [`CacheQueryOptions`]{@link https://w3c.github.io/ServiceWorker/#dictdef-cachequeryoptions}
66 * for any `cache.match()` or `cache.put()` calls made by this strategy.
67 */
68 constructor(options: StrategyOptions = {}) {
69 /**
70 * Cache name to store and retrieve
71 * requests. Defaults to the cache names provided by
72 * {@link workbox-core.cacheNames}.
73 *
74 * @type {string}
75 */
76 this.cacheName = cacheNames.getRuntimeName(options.cacheName);
77 /**
78 * The list
79 * [Plugins]{@link https://developers.google.com/web/tools/workbox/guides/using-plugins}
80 * used by this strategy.
81 *
82 * @type {Array<Object>}
83 */
84 this.plugins = options.plugins || [];
85 /**
86 * Values passed along to the
87 * [`init`]{@link https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch#Parameters}
88 * of all fetch() requests made by this strategy.
89 *
90 * @type {Object}
91 */
92 this.fetchOptions = options.fetchOptions;
93 /**
94 * The
95 * [`CacheQueryOptions`]{@link https://w3c.github.io/ServiceWorker/#dictdef-cachequeryoptions}
96 * for any `cache.match()` or `cache.put()` calls made by this strategy.
97 *
98 * @type {Object}
99 */
100 this.matchOptions = options.matchOptions;
101 }
102
103 /**
104 * Perform a request strategy and returns a `Promise` that will resolve with
105 * a `Response`, invoking all relevant plugin callbacks.
106 *
107 * When a strategy instance is registered with a Workbox
108 * {@link workbox-routing.Route}, this method is automatically
109 * called when the route matches.
110 *
111 * Alternatively, this method can be used in a standalone `FetchEvent`
112 * listener by passing it to `event.respondWith()`.
113 *
114 * @param {FetchEvent|Object} options A `FetchEvent` or an object with the
115 * properties listed below.
116 * @param {Request|string} options.request A request to run this strategy for.
117 * @param {ExtendableEvent} options.event The event associated with the
118 * request.
119 * @param {URL} [options.url]
120 * @param {*} [options.params]
121 */
122 handle(options: FetchEvent | HandlerCallbackOptions): Promise<Response> {
123 const [responseDone] = this.handleAll(options);
124 return responseDone;
125 }
126
127 /**
128 * Similar to {@link workbox-strategies.Strategy~handle}, but
129 * instead of just returning a `Promise` that resolves to a `Response` it
130 * it will return an tuple of `[response, done]` promises, where the former
131 * (`response`) is equivalent to what `handle()` returns, and the latter is a
132 * Promise that will resolve once any promises that were added to
133 * `event.waitUntil()` as part of performing the strategy have completed.
134 *
135 * You can await the `done` promise to ensure any extra work performed by
136 * the strategy (usually caching responses) completes successfully.
137 *
138 * @param {FetchEvent|Object} options A `FetchEvent` or an object with the
139 * properties listed below.
140 * @param {Request|string} options.request A request to run this strategy for.
141 * @param {ExtendableEvent} options.event The event associated with the
142 * request.
143 * @param {URL} [options.url]
144 * @param {*} [options.params]
145 * @return {Array<Promise>} A tuple of [response, done]
146 * promises that can be used to determine when the response resolves as
147 * well as when the handler has completed all its work.
148 */
149 handleAll(
150 options: FetchEvent | HandlerCallbackOptions,
151 ): [Promise<Response>, Promise<void>] {
152 // Allow for flexible options to be passed.
153 if (options instanceof FetchEvent) {
154 options = {
155 event: options,
156 request: options.request,
157 };
158 }
159
160 const event = options.event;
161 const request =
162 typeof options.request === 'string'
163 ? new Request(options.request)
164 : options.request;
165 const params = 'params' in options ? options.params : undefined;
166
167 const handler = new StrategyHandler(this, {event, request, params});
168
169 const responseDone = this._getResponse(handler, request, event);
170 const handlerDone = this._awaitComplete(
171 responseDone,
172 handler,
173 request,
174 event,
175 );
176
177 // Return an array of promises, suitable for use with Promise.all().
178 return [responseDone, handlerDone];
179 }
180
181 async _getResponse(
182 handler: StrategyHandler,
183 request: Request,
184 event: ExtendableEvent,
185 ): Promise<Response> {
186 await handler.runCallbacks('handlerWillStart', {event, request});
187
188 let response: Response | undefined = undefined;
189 try {
190 response = await this._handle(request, handler);
191 // The "official" Strategy subclasses all throw this error automatically,
192 // but in case a third-party Strategy doesn't, ensure that we have a
193 // consistent failure when there's no response or an error response.
194 if (!response || response.type === 'error') {
195 throw new WorkboxError('no-response', {url: request.url});
196 }
197 } catch (error) {
198 if (error instanceof Error) {
199 for (const callback of handler.iterateCallbacks('handlerDidError')) {
200 response = await callback({error, event, request});
201 if (response) {
202 break;
203 }
204 }
205 }
206
207 if (!response) {
208 throw error;
209 } else if (process.env.NODE_ENV !== 'production') {
210 logger.log(
211 `While responding to '${getFriendlyURL(request.url)}', ` +
212 `an ${
213 error instanceof Error ? error.toString() : ''
214 } error occurred. Using a fallback response provided by ` +
215 `a handlerDidError plugin.`,
216 );
217 }
218 }
219
220 for (const callback of handler.iterateCallbacks('handlerWillRespond')) {
221 response = await callback({event, request, response});
222 }
223
224 return response;
225 }
226
227 async _awaitComplete(
228 responseDone: Promise<Response>,
229 handler: StrategyHandler,
230 request: Request,
231 event: ExtendableEvent,
232 ): Promise<void> {
233 let response;
234 let error;
235
236 try {
237 response = await responseDone;
238 } catch (error) {
239 // Ignore errors, as response errors should be caught via the `response`
240 // promise above. The `done` promise will only throw for errors in
241 // promises passed to `handler.waitUntil()`.
242 }
243
244 try {
245 await handler.runCallbacks('handlerDidRespond', {
246 event,
247 request,
248 response,
249 });
250 await handler.doneWaiting();
251 } catch (waitUntilError) {
252 if (waitUntilError instanceof Error) {
253 error = waitUntilError;
254 }
255 }
256
257 await handler.runCallbacks('handlerDidComplete', {
258 event,
259 request,
260 response,
261 error: error as Error,
262 });
263 handler.destroy();
264
265 if (error) {
266 throw error;
267 }
268 }
269}
270
271export {Strategy};
272
273/**
274 * Classes extending the `Strategy` based class should implement this method,
275 * and leverage the {@link workbox-strategies.StrategyHandler}
276 * arg to perform all fetching and cache logic, which will ensure all relevant
277 * cache, cache options, fetch options and plugins are used (per the current
278 * strategy instance).
279 *
280 * @name _handle
281 * @instance
282 * @abstract
283 * @function
284 * @param {Request} request
285 * @param {workbox-strategies.StrategyHandler} handler
286 * @return {Promise<Response>}
287 *
288 * @memberof workbox-strategies.Strategy
289 */
Note: See TracBrowser for help on using the repository browser.