@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.
- package/dist/abstractions/Serwist.d.ts +5 -7
- package/dist/abstractions/Serwist.d.ts.map +1 -1
- package/dist/chunks/NavigationRoute.js +1 -1
- package/dist/chunks/PrecacheFallbackPlugin.js +9 -9
- package/dist/chunks/precacheAndRoute.js +6 -5
- package/dist/chunks/registerRoute.js +3 -404
- package/dist/chunks/{getOrCreatePrecacheController.js → singletonPrecacheController.js} +10 -6
- package/dist/chunks/singletonRouter.js +435 -0
- package/dist/index.js +8 -7
- package/dist/index.plugins.js +2 -2
- package/dist/index.precaching.d.ts +2 -1
- package/dist/index.precaching.d.ts.map +1 -1
- package/dist/index.precaching.js +7 -7
- package/dist/index.routing.d.ts +3 -1
- package/dist/index.routing.d.ts.map +1 -1
- package/dist/index.routing.js +7 -9
- package/dist/plugins/googleAnalytics/initialize.d.ts +9 -1
- package/dist/plugins/googleAnalytics/initialize.d.ts.map +1 -1
- package/dist/precaching/addRoute.d.ts.map +1 -1
- package/dist/precaching/matchPrecache.d.ts.map +1 -1
- package/dist/precaching/precache.d.ts.map +1 -1
- package/dist/precaching/singletonPrecacheController.d.ts +38 -0
- package/dist/precaching/singletonPrecacheController.d.ts.map +1 -0
- package/dist/precaching/utils/getCacheKeyForURL.d.ts.map +1 -1
- package/dist/routing/RegExpRoute.d.ts +3 -3
- package/dist/routing/Router.d.ts +49 -23
- package/dist/routing/Router.d.ts.map +1 -1
- package/dist/routing/parseRoute.d.ts +16 -0
- package/dist/routing/parseRoute.d.ts.map +1 -0
- package/dist/routing/registerRoute.d.ts +5 -5
- package/dist/routing/registerRoute.d.ts.map +1 -1
- package/dist/routing/setCatchHandler.d.ts +1 -1
- package/dist/routing/setCatchHandler.d.ts.map +1 -1
- package/dist/routing/setDefaultHandler.d.ts +1 -1
- package/dist/routing/setDefaultHandler.d.ts.map +1 -1
- package/dist/routing/singletonRouter.d.ts +47 -0
- package/dist/routing/singletonRouter.d.ts.map +1 -0
- package/dist/routing/unregisterRoute.d.ts +1 -1
- package/dist/routing/unregisterRoute.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/abstractions/Serwist.ts +10 -12
- package/src/abstractions/installSerwist.ts +4 -4
- package/src/index.precaching.ts +3 -0
- package/src/index.routing.ts +15 -1
- package/src/plugins/googleAnalytics/initialize.ts +19 -6
- package/src/plugins/precaching/PrecacheFallbackPlugin.ts +2 -2
- package/src/precaching/addPlugins.ts +2 -2
- package/src/precaching/addRoute.ts +2 -2
- package/src/precaching/createHandlerBoundToURL.ts +2 -2
- package/src/precaching/getCacheKeyForURL.ts +2 -2
- package/src/precaching/matchPrecache.ts +2 -3
- package/src/precaching/precache.ts +2 -2
- package/src/precaching/singletonPrecacheController.ts +57 -0
- package/src/precaching/utils/getCacheKeyForURL.ts +2 -2
- package/src/routing/RegExpRoute.ts +3 -3
- package/src/routing/Router.ts +101 -52
- package/src/routing/{utils/parseRoute.ts → parseRoute.ts} +14 -3
- package/src/routing/registerRoute.ts +7 -13
- package/src/routing/setCatchHandler.ts +3 -4
- package/src/routing/setDefaultHandler.ts +3 -4
- package/src/routing/singletonRouter.ts +76 -0
- package/src/routing/unregisterRoute.ts +3 -4
- package/dist/precaching/utils/getOrCreatePrecacheController.d.ts +0 -7
- package/dist/precaching/utils/getOrCreatePrecacheController.d.ts.map +0 -1
- package/dist/routing/utils/getOrCreateDefaultRouter.d.ts +0 -10
- package/dist/routing/utils/getOrCreateDefaultRouter.d.ts.map +0 -1
- package/dist/routing/utils/parseRoute.d.ts +0 -5
- package/dist/routing/utils/parseRoute.d.ts.map +0 -1
- package/src/precaching/utils/getOrCreatePrecacheController.ts +0 -22
- package/src/routing/utils/getOrCreateDefaultRouter.ts +0 -29
|
@@ -0,0 +1,435 @@
|
|
|
1
|
+
import { assert, logger, SerwistError, getFriendlyURL } from '@serwist/core/internal';
|
|
2
|
+
|
|
3
|
+
const defaultMethod = "GET";
|
|
4
|
+
const validMethods = [
|
|
5
|
+
"DELETE",
|
|
6
|
+
"GET",
|
|
7
|
+
"HEAD",
|
|
8
|
+
"PATCH",
|
|
9
|
+
"POST",
|
|
10
|
+
"PUT"
|
|
11
|
+
];
|
|
12
|
+
|
|
13
|
+
const normalizeHandler = (handler)=>{
|
|
14
|
+
if (handler && typeof handler === "object") {
|
|
15
|
+
if (process.env.NODE_ENV !== "production") {
|
|
16
|
+
assert.hasMethod(handler, "handle", {
|
|
17
|
+
moduleName: "@serwist/routing",
|
|
18
|
+
className: "Route",
|
|
19
|
+
funcName: "constructor",
|
|
20
|
+
paramName: "handler"
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
return handler;
|
|
24
|
+
}
|
|
25
|
+
if (process.env.NODE_ENV !== "production") {
|
|
26
|
+
assert.isType(handler, "function", {
|
|
27
|
+
moduleName: "@serwist/routing",
|
|
28
|
+
className: "Route",
|
|
29
|
+
funcName: "constructor",
|
|
30
|
+
paramName: "handler"
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
return {
|
|
34
|
+
handle: handler
|
|
35
|
+
};
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
class Route {
|
|
39
|
+
handler;
|
|
40
|
+
match;
|
|
41
|
+
method;
|
|
42
|
+
catchHandler;
|
|
43
|
+
constructor(match, handler, method = defaultMethod){
|
|
44
|
+
if (process.env.NODE_ENV !== "production") {
|
|
45
|
+
assert.isType(match, "function", {
|
|
46
|
+
moduleName: "@serwist/routing",
|
|
47
|
+
className: "Route",
|
|
48
|
+
funcName: "constructor",
|
|
49
|
+
paramName: "match"
|
|
50
|
+
});
|
|
51
|
+
if (method) {
|
|
52
|
+
assert.isOneOf(method, validMethods, {
|
|
53
|
+
paramName: "method"
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
this.handler = normalizeHandler(handler);
|
|
58
|
+
this.match = match;
|
|
59
|
+
this.method = method;
|
|
60
|
+
}
|
|
61
|
+
setCatchHandler(handler) {
|
|
62
|
+
this.catchHandler = normalizeHandler(handler);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
class RegExpRoute extends Route {
|
|
67
|
+
constructor(regExp, handler, method){
|
|
68
|
+
if (process.env.NODE_ENV !== "production") {
|
|
69
|
+
assert.isInstance(regExp, RegExp, {
|
|
70
|
+
moduleName: "@serwist/routing",
|
|
71
|
+
className: "RegExpRoute",
|
|
72
|
+
funcName: "constructor",
|
|
73
|
+
paramName: "pattern"
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
const match = ({ url })=>{
|
|
77
|
+
const result = regExp.exec(url.href);
|
|
78
|
+
if (!result) {
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
if (url.origin !== location.origin && result.index !== 0) {
|
|
82
|
+
if (process.env.NODE_ENV !== "production") {
|
|
83
|
+
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.`);
|
|
84
|
+
}
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
return result.slice(1);
|
|
88
|
+
};
|
|
89
|
+
super(match, handler, method);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const parseRoute = (capture, handler, method)=>{
|
|
94
|
+
let route;
|
|
95
|
+
if (typeof capture === "string") {
|
|
96
|
+
const captureUrl = new URL(capture, location.href);
|
|
97
|
+
if (process.env.NODE_ENV !== "production") {
|
|
98
|
+
if (!(capture.startsWith("/") || capture.startsWith("http"))) {
|
|
99
|
+
throw new SerwistError("invalid-string", {
|
|
100
|
+
moduleName: "@serwist/routing",
|
|
101
|
+
funcName: "registerRoute",
|
|
102
|
+
paramName: "capture"
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
const valueToCheck = capture.startsWith("http") ? captureUrl.pathname : capture;
|
|
106
|
+
const wildcards = "[*:?+]";
|
|
107
|
+
if (new RegExp(`${wildcards}`).exec(valueToCheck)) {
|
|
108
|
+
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.`);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
const matchCallback = ({ url })=>{
|
|
112
|
+
if (process.env.NODE_ENV !== "production") {
|
|
113
|
+
if (url.pathname === captureUrl.pathname && url.origin !== captureUrl.origin) {
|
|
114
|
+
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.`);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
return url.href === captureUrl.href;
|
|
118
|
+
};
|
|
119
|
+
route = new Route(matchCallback, handler, method);
|
|
120
|
+
} else if (capture instanceof RegExp) {
|
|
121
|
+
route = new RegExpRoute(capture, handler, method);
|
|
122
|
+
} else if (typeof capture === "function") {
|
|
123
|
+
route = new Route(capture, handler, method);
|
|
124
|
+
} else if (capture instanceof Route) {
|
|
125
|
+
route = capture;
|
|
126
|
+
} else {
|
|
127
|
+
throw new SerwistError("unsupported-route-type", {
|
|
128
|
+
moduleName: "@serwist/routing",
|
|
129
|
+
funcName: "registerRoute",
|
|
130
|
+
paramName: "capture"
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
return route;
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
class Router {
|
|
137
|
+
_routes;
|
|
138
|
+
_defaultHandlerMap;
|
|
139
|
+
_fetchListenerHandler = null;
|
|
140
|
+
_cacheListenerHandler = null;
|
|
141
|
+
_catchHandler;
|
|
142
|
+
constructor(){
|
|
143
|
+
this._routes = new Map();
|
|
144
|
+
this._defaultHandlerMap = new Map();
|
|
145
|
+
}
|
|
146
|
+
get routes() {
|
|
147
|
+
return this._routes;
|
|
148
|
+
}
|
|
149
|
+
addFetchListener() {
|
|
150
|
+
if (!this._fetchListenerHandler) {
|
|
151
|
+
this._fetchListenerHandler = (event)=>{
|
|
152
|
+
const { request } = event;
|
|
153
|
+
const responsePromise = this.handleRequest({
|
|
154
|
+
request,
|
|
155
|
+
event
|
|
156
|
+
});
|
|
157
|
+
if (responsePromise) {
|
|
158
|
+
event.respondWith(responsePromise);
|
|
159
|
+
}
|
|
160
|
+
};
|
|
161
|
+
self.addEventListener("fetch", this._fetchListenerHandler);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
removeFetchListener() {
|
|
165
|
+
if (this._fetchListenerHandler) {
|
|
166
|
+
self.removeEventListener("fetch", this._fetchListenerHandler);
|
|
167
|
+
this._fetchListenerHandler = null;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
addCacheListener() {
|
|
171
|
+
if (!this._cacheListenerHandler) {
|
|
172
|
+
this._cacheListenerHandler = (event)=>{
|
|
173
|
+
if (event.data && event.data.type === "CACHE_URLS") {
|
|
174
|
+
const { payload } = event.data;
|
|
175
|
+
if (process.env.NODE_ENV !== "production") {
|
|
176
|
+
logger.debug("Caching URLs from the window", payload.urlsToCache);
|
|
177
|
+
}
|
|
178
|
+
const requestPromises = Promise.all(payload.urlsToCache.map((entry)=>{
|
|
179
|
+
if (typeof entry === "string") {
|
|
180
|
+
entry = [
|
|
181
|
+
entry
|
|
182
|
+
];
|
|
183
|
+
}
|
|
184
|
+
const request = new Request(...entry);
|
|
185
|
+
return this.handleRequest({
|
|
186
|
+
request,
|
|
187
|
+
event
|
|
188
|
+
});
|
|
189
|
+
}));
|
|
190
|
+
event.waitUntil(requestPromises);
|
|
191
|
+
if (event.ports?.[0]) {
|
|
192
|
+
void requestPromises.then(()=>event.ports[0].postMessage(true));
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
};
|
|
196
|
+
self.addEventListener("message", this._cacheListenerHandler);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
removeCacheListener() {
|
|
200
|
+
if (this._cacheListenerHandler) {
|
|
201
|
+
self.removeEventListener("message", this._cacheListenerHandler);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
handleRequest({ request, event }) {
|
|
205
|
+
if (process.env.NODE_ENV !== "production") {
|
|
206
|
+
assert.isInstance(request, Request, {
|
|
207
|
+
moduleName: "@serwist/routing",
|
|
208
|
+
className: "Router",
|
|
209
|
+
funcName: "handleRequest",
|
|
210
|
+
paramName: "options.request"
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
const url = new URL(request.url, location.href);
|
|
214
|
+
if (!url.protocol.startsWith("http")) {
|
|
215
|
+
if (process.env.NODE_ENV !== "production") {
|
|
216
|
+
logger.debug("Router only supports URLs that start with 'http'.");
|
|
217
|
+
}
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
const sameOrigin = url.origin === location.origin;
|
|
221
|
+
const { params, route } = this.findMatchingRoute({
|
|
222
|
+
event,
|
|
223
|
+
request,
|
|
224
|
+
sameOrigin,
|
|
225
|
+
url
|
|
226
|
+
});
|
|
227
|
+
let handler = route?.handler;
|
|
228
|
+
const debugMessages = [];
|
|
229
|
+
if (process.env.NODE_ENV !== "production") {
|
|
230
|
+
if (handler) {
|
|
231
|
+
debugMessages.push([
|
|
232
|
+
"Found a route to handle this request:",
|
|
233
|
+
route
|
|
234
|
+
]);
|
|
235
|
+
if (params) {
|
|
236
|
+
debugMessages.push([
|
|
237
|
+
`Passing the following params to the route's handler:`,
|
|
238
|
+
params
|
|
239
|
+
]);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
const method = request.method;
|
|
244
|
+
if (!handler && this._defaultHandlerMap.has(method)) {
|
|
245
|
+
if (process.env.NODE_ENV !== "production") {
|
|
246
|
+
debugMessages.push(`Failed to find a matching route. Falling back to the default handler for ${method}.`);
|
|
247
|
+
}
|
|
248
|
+
handler = this._defaultHandlerMap.get(method);
|
|
249
|
+
}
|
|
250
|
+
if (!handler) {
|
|
251
|
+
if (process.env.NODE_ENV !== "production") {
|
|
252
|
+
logger.debug(`No route found for: ${getFriendlyURL(url)}`);
|
|
253
|
+
}
|
|
254
|
+
return;
|
|
255
|
+
}
|
|
256
|
+
if (process.env.NODE_ENV !== "production") {
|
|
257
|
+
logger.groupCollapsed(`Router is responding to: ${getFriendlyURL(url)}`);
|
|
258
|
+
for (const msg of debugMessages){
|
|
259
|
+
if (Array.isArray(msg)) {
|
|
260
|
+
logger.log(...msg);
|
|
261
|
+
} else {
|
|
262
|
+
logger.log(msg);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
logger.groupEnd();
|
|
266
|
+
}
|
|
267
|
+
let responsePromise;
|
|
268
|
+
try {
|
|
269
|
+
responsePromise = handler.handle({
|
|
270
|
+
url,
|
|
271
|
+
request,
|
|
272
|
+
event,
|
|
273
|
+
params
|
|
274
|
+
});
|
|
275
|
+
} catch (err) {
|
|
276
|
+
responsePromise = Promise.reject(err);
|
|
277
|
+
}
|
|
278
|
+
const catchHandler = route?.catchHandler;
|
|
279
|
+
if (responsePromise instanceof Promise && (this._catchHandler || catchHandler)) {
|
|
280
|
+
responsePromise = responsePromise.catch(async (err)=>{
|
|
281
|
+
if (catchHandler) {
|
|
282
|
+
if (process.env.NODE_ENV !== "production") {
|
|
283
|
+
logger.groupCollapsed(`Error thrown when responding to: ${getFriendlyURL(url)}. Falling back to route's Catch Handler.`);
|
|
284
|
+
logger.error("Error thrown by:", route);
|
|
285
|
+
logger.error(err);
|
|
286
|
+
logger.groupEnd();
|
|
287
|
+
}
|
|
288
|
+
try {
|
|
289
|
+
return await catchHandler.handle({
|
|
290
|
+
url,
|
|
291
|
+
request,
|
|
292
|
+
event,
|
|
293
|
+
params
|
|
294
|
+
});
|
|
295
|
+
} catch (catchErr) {
|
|
296
|
+
if (catchErr instanceof Error) {
|
|
297
|
+
err = catchErr;
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
if (this._catchHandler) {
|
|
302
|
+
if (process.env.NODE_ENV !== "production") {
|
|
303
|
+
logger.groupCollapsed(`Error thrown when responding to: ${getFriendlyURL(url)}. Falling back to global Catch Handler.`);
|
|
304
|
+
logger.error("Error thrown by:", route);
|
|
305
|
+
logger.error(err);
|
|
306
|
+
logger.groupEnd();
|
|
307
|
+
}
|
|
308
|
+
return this._catchHandler.handle({
|
|
309
|
+
url,
|
|
310
|
+
request,
|
|
311
|
+
event
|
|
312
|
+
});
|
|
313
|
+
}
|
|
314
|
+
throw err;
|
|
315
|
+
});
|
|
316
|
+
}
|
|
317
|
+
return responsePromise;
|
|
318
|
+
}
|
|
319
|
+
findMatchingRoute({ url, sameOrigin, request, event }) {
|
|
320
|
+
const routes = this._routes.get(request.method) || [];
|
|
321
|
+
for (const route of routes){
|
|
322
|
+
let params;
|
|
323
|
+
const matchResult = route.match({
|
|
324
|
+
url,
|
|
325
|
+
sameOrigin,
|
|
326
|
+
request,
|
|
327
|
+
event
|
|
328
|
+
});
|
|
329
|
+
if (matchResult) {
|
|
330
|
+
if (process.env.NODE_ENV !== "production") {
|
|
331
|
+
if (matchResult instanceof Promise) {
|
|
332
|
+
logger.warn(`While routing ${getFriendlyURL(url)}, an async matchCallback function was used. Please convert the following route to use a synchronous matchCallback function:`, route);
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
params = matchResult;
|
|
336
|
+
if (Array.isArray(params) && params.length === 0) {
|
|
337
|
+
params = undefined;
|
|
338
|
+
} else if (matchResult.constructor === Object && Object.keys(matchResult).length === 0) {
|
|
339
|
+
params = undefined;
|
|
340
|
+
} else if (typeof matchResult === "boolean") {
|
|
341
|
+
params = undefined;
|
|
342
|
+
}
|
|
343
|
+
return {
|
|
344
|
+
route,
|
|
345
|
+
params
|
|
346
|
+
};
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
return {};
|
|
350
|
+
}
|
|
351
|
+
setDefaultHandler(handler, method = defaultMethod) {
|
|
352
|
+
this._defaultHandlerMap.set(method, normalizeHandler(handler));
|
|
353
|
+
}
|
|
354
|
+
setCatchHandler(handler) {
|
|
355
|
+
this._catchHandler = normalizeHandler(handler);
|
|
356
|
+
}
|
|
357
|
+
registerCapture(capture, handler, method) {
|
|
358
|
+
const route = parseRoute(capture, handler, method);
|
|
359
|
+
this.registerRoute(route);
|
|
360
|
+
return route;
|
|
361
|
+
}
|
|
362
|
+
registerRoute(route) {
|
|
363
|
+
if (process.env.NODE_ENV !== "production") {
|
|
364
|
+
assert.isType(route, "object", {
|
|
365
|
+
moduleName: "@serwist/routing",
|
|
366
|
+
className: "Router",
|
|
367
|
+
funcName: "registerRoute",
|
|
368
|
+
paramName: "route"
|
|
369
|
+
});
|
|
370
|
+
assert.hasMethod(route, "match", {
|
|
371
|
+
moduleName: "@serwist/routing",
|
|
372
|
+
className: "Router",
|
|
373
|
+
funcName: "registerRoute",
|
|
374
|
+
paramName: "route"
|
|
375
|
+
});
|
|
376
|
+
assert.isType(route.handler, "object", {
|
|
377
|
+
moduleName: "@serwist/routing",
|
|
378
|
+
className: "Router",
|
|
379
|
+
funcName: "registerRoute",
|
|
380
|
+
paramName: "route"
|
|
381
|
+
});
|
|
382
|
+
assert.hasMethod(route.handler, "handle", {
|
|
383
|
+
moduleName: "@serwist/routing",
|
|
384
|
+
className: "Router",
|
|
385
|
+
funcName: "registerRoute",
|
|
386
|
+
paramName: "route.handler"
|
|
387
|
+
});
|
|
388
|
+
assert.isType(route.method, "string", {
|
|
389
|
+
moduleName: "@serwist/routing",
|
|
390
|
+
className: "Router",
|
|
391
|
+
funcName: "registerRoute",
|
|
392
|
+
paramName: "route.method"
|
|
393
|
+
});
|
|
394
|
+
}
|
|
395
|
+
if (!this._routes.has(route.method)) {
|
|
396
|
+
this._routes.set(route.method, []);
|
|
397
|
+
}
|
|
398
|
+
this._routes.get(route.method).push(route);
|
|
399
|
+
}
|
|
400
|
+
unregisterRoute(route) {
|
|
401
|
+
if (!this._routes.has(route.method)) {
|
|
402
|
+
throw new SerwistError("unregister-route-but-not-found-with-method", {
|
|
403
|
+
method: route.method
|
|
404
|
+
});
|
|
405
|
+
}
|
|
406
|
+
const routeIndex = this._routes.get(route.method).indexOf(route);
|
|
407
|
+
if (routeIndex > -1) {
|
|
408
|
+
this._routes.get(route.method).splice(routeIndex, 1);
|
|
409
|
+
} else {
|
|
410
|
+
throw new SerwistError("unregister-route-route-not-registered");
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
let defaultRouter = undefined;
|
|
416
|
+
const getSingletonRouter = ()=>{
|
|
417
|
+
if (!defaultRouter) {
|
|
418
|
+
defaultRouter = new Router();
|
|
419
|
+
defaultRouter.addFetchListener();
|
|
420
|
+
defaultRouter.addCacheListener();
|
|
421
|
+
}
|
|
422
|
+
return defaultRouter;
|
|
423
|
+
};
|
|
424
|
+
const setSingletonRouter = (router)=>{
|
|
425
|
+
if (defaultRouter) {
|
|
426
|
+
defaultRouter.removeFetchListener();
|
|
427
|
+
defaultRouter.removeCacheListener();
|
|
428
|
+
}
|
|
429
|
+
defaultRouter = router;
|
|
430
|
+
defaultRouter.addFetchListener();
|
|
431
|
+
defaultRouter.addCacheListener();
|
|
432
|
+
return defaultRouter;
|
|
433
|
+
};
|
|
434
|
+
|
|
435
|
+
export { Route as R, RegExpRoute as a, Router as b, getSingletonRouter as g, parseRoute as p, setSingletonRouter as s };
|
package/dist/index.js
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { setCacheNameDetails, clientsClaim } from '@serwist/core';
|
|
2
2
|
import { P as PrecacheFallbackPlugin, i as initialize } from './chunks/PrecacheFallbackPlugin.js';
|
|
3
3
|
import { p as precacheAndRoute, P as PrecacheRoute, c as cleanupOutdatedCaches, a as createHandlerBoundToURL } from './chunks/precacheAndRoute.js';
|
|
4
|
-
import { g as
|
|
4
|
+
import { g as getSingletonPrecacheController } from './chunks/singletonPrecacheController.js';
|
|
5
5
|
import { N as NavigationRoute } from './chunks/NavigationRoute.js';
|
|
6
|
-
import { g as
|
|
6
|
+
import { g as getSingletonRouter, p as parseRoute } from './chunks/singletonRouter.js';
|
|
7
7
|
import { S as Strategy } from './chunks/Strategy.js';
|
|
8
8
|
import { logger } from '@serwist/core/internal';
|
|
9
|
+
import { r as registerRoute } from './chunks/registerRoute.js';
|
|
9
10
|
import './chunks/NetworkOnly.js';
|
|
10
11
|
import 'idb';
|
|
11
12
|
|
|
@@ -68,10 +69,10 @@ class Serwist {
|
|
|
68
69
|
_precacheController;
|
|
69
70
|
_router;
|
|
70
71
|
constructor({ precacheController, router } = {}){
|
|
71
|
-
this._precacheController = precacheController ||
|
|
72
|
-
this._router = router ||
|
|
72
|
+
this._precacheController = precacheController || getSingletonPrecacheController();
|
|
73
|
+
this._router = router || getSingletonRouter();
|
|
73
74
|
}
|
|
74
|
-
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 }) {
|
|
75
|
+
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 } = {}) {
|
|
75
76
|
if (!!importScripts && importScripts.length > 0) self.importScripts(...importScripts);
|
|
76
77
|
if (navigationPreload) enableNavigationPreload();
|
|
77
78
|
if (cacheId !== undefined) {
|
|
@@ -140,8 +141,8 @@ const installSerwist = (options)=>{
|
|
|
140
141
|
logger.warn("'installSerwist' has been deprecated. Please migrate to 'new Serwist().install()'.");
|
|
141
142
|
}
|
|
142
143
|
const serwist = new Serwist({
|
|
143
|
-
precacheController:
|
|
144
|
-
router:
|
|
144
|
+
precacheController: getSingletonPrecacheController(),
|
|
145
|
+
router: getSingletonRouter()
|
|
145
146
|
});
|
|
146
147
|
serwist.install(options);
|
|
147
148
|
};
|
package/dist/index.plugins.js
CHANGED
|
@@ -2,10 +2,10 @@ export { B as BackgroundSyncPlugin, Q as BackgroundSyncQueue, a as BackgroundSyn
|
|
|
2
2
|
import { SerwistError, logger, assert, resultingClientExists, timeout, getFriendlyURL, privateCacheNames } from '@serwist/core/internal';
|
|
3
3
|
import { deleteDB, openDB } from 'idb';
|
|
4
4
|
import { registerQuotaErrorCallback } from '@serwist/core';
|
|
5
|
-
import './chunks/
|
|
5
|
+
import './chunks/singletonRouter.js';
|
|
6
6
|
import './chunks/NetworkOnly.js';
|
|
7
7
|
import './chunks/Strategy.js';
|
|
8
|
-
import './chunks/
|
|
8
|
+
import './chunks/singletonPrecacheController.js';
|
|
9
9
|
|
|
10
10
|
const CACHE_UPDATED_MESSAGE_TYPE = "CACHE_UPDATED";
|
|
11
11
|
const CACHE_UPDATED_MESSAGE_META = "serwist-broadcast-update";
|
|
@@ -9,6 +9,7 @@ import { getCacheKeyForURL } from "./precaching/getCacheKeyForURL.js";
|
|
|
9
9
|
import { matchPrecache } from "./precaching/matchPrecache.js";
|
|
10
10
|
import { precache } from "./precaching/precache.js";
|
|
11
11
|
import { precacheAndRoute } from "./precaching/precacheAndRoute.js";
|
|
12
|
+
import { getSingletonPrecacheController, setSingletonPrecacheController } from "./precaching/singletonPrecacheController.js";
|
|
12
13
|
/**
|
|
13
14
|
* Most consumers of this module will want to use the
|
|
14
15
|
* `@serwist/sw/precaching.precacheAndRoute`
|
|
@@ -19,6 +20,6 @@ import { precacheAndRoute } from "./precaching/precacheAndRoute.js";
|
|
|
19
20
|
* `@serwist/precaching.PrecacheController`
|
|
20
21
|
* interface.
|
|
21
22
|
*/
|
|
22
|
-
export { addPlugins, addRoute, cleanupOutdatedCaches, createHandlerBoundToURL, getCacheKeyForURL, matchPrecache, precache, precacheAndRoute, PrecacheController, PrecacheRoute, PrecacheStrategy, };
|
|
23
|
+
export { addPlugins, addRoute, cleanupOutdatedCaches, createHandlerBoundToURL, getCacheKeyForURL, matchPrecache, precache, precacheAndRoute, PrecacheController, PrecacheRoute, PrecacheStrategy, getSingletonPrecacheController, setSingletonPrecacheController, };
|
|
23
24
|
export type * from "./precaching/types.js";
|
|
24
25
|
//# sourceMappingURL=index.precaching.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.precaching.d.ts","sourceRoot":"","sources":["../src/index.precaching.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,oCAAoC,CAAC;AACxE,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAC9D,OAAO,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AACpE,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AACxD,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACpD,OAAO,EAAE,qBAAqB,EAAE,MAAM,uCAAuC,CAAC;AAC9E,OAAO,EAAE,uBAAuB,EAAE,MAAM,yCAAyC,CAAC;AAClF,OAAO,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAC;AACtE,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAC9D,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACpD,OAAO,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;
|
|
1
|
+
{"version":3,"file":"index.precaching.d.ts","sourceRoot":"","sources":["../src/index.precaching.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,oCAAoC,CAAC;AACxE,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAC9D,OAAO,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AACpE,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AACxD,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACpD,OAAO,EAAE,qBAAqB,EAAE,MAAM,uCAAuC,CAAC;AAC9E,OAAO,EAAE,uBAAuB,EAAE,MAAM,yCAAyC,CAAC;AAClF,OAAO,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAC;AACtE,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAC9D,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACpD,OAAO,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AACpE,OAAO,EAAE,8BAA8B,EAAE,8BAA8B,EAAE,MAAM,6CAA6C,CAAC;AAE7H;;;;;;;;;GASG;AAEH,OAAO,EACL,UAAU,EACV,QAAQ,EACR,qBAAqB,EACrB,uBAAuB,EACvB,iBAAiB,EACjB,aAAa,EACb,QAAQ,EACR,gBAAgB,EAChB,kBAAkB,EAClB,aAAa,EACb,gBAAgB,EAChB,8BAA8B,EAC9B,8BAA8B,GAC/B,CAAC;AAEF,mBAAmB,uBAAuB,CAAC"}
|
package/dist/index.precaching.js
CHANGED
|
@@ -1,24 +1,24 @@
|
|
|
1
|
-
import { g as
|
|
2
|
-
export { P as PrecacheController, a as PrecacheStrategy } from './chunks/
|
|
1
|
+
import { g as getSingletonPrecacheController } from './chunks/singletonPrecacheController.js';
|
|
2
|
+
export { P as PrecacheController, a as PrecacheStrategy, s as setSingletonPrecacheController } from './chunks/singletonPrecacheController.js';
|
|
3
3
|
export { P as PrecacheRoute, b as addRoute, c as cleanupOutdatedCaches, a as createHandlerBoundToURL, d as precache, p as precacheAndRoute } from './chunks/precacheAndRoute.js';
|
|
4
4
|
import '@serwist/core/internal';
|
|
5
5
|
import '@serwist/core';
|
|
6
6
|
import './chunks/Strategy.js';
|
|
7
7
|
import './chunks/registerRoute.js';
|
|
8
|
+
import './chunks/singletonRouter.js';
|
|
8
9
|
|
|
9
10
|
const addPlugins = (plugins)=>{
|
|
10
|
-
const precacheController =
|
|
11
|
+
const precacheController = getSingletonPrecacheController();
|
|
11
12
|
precacheController.strategy.plugins.push(...plugins);
|
|
12
13
|
};
|
|
13
14
|
|
|
14
15
|
function getCacheKeyForURL(url) {
|
|
15
|
-
const precacheController =
|
|
16
|
+
const precacheController = getSingletonPrecacheController();
|
|
16
17
|
return precacheController.getCacheKeyForURL(url);
|
|
17
18
|
}
|
|
18
19
|
|
|
19
20
|
const matchPrecache = (request)=>{
|
|
20
|
-
|
|
21
|
-
return precacheController.matchPrecache(request);
|
|
21
|
+
return getSingletonPrecacheController().matchPrecache(request);
|
|
22
22
|
};
|
|
23
23
|
|
|
24
|
-
export { addPlugins, getCacheKeyForURL, matchPrecache };
|
|
24
|
+
export { addPlugins, getCacheKeyForURL, getSingletonPrecacheController, matchPrecache };
|
package/dist/index.routing.d.ts
CHANGED
|
@@ -3,11 +3,13 @@ import { NavigationRoute } from "./routing/NavigationRoute.js";
|
|
|
3
3
|
import { RegExpRoute } from "./routing/RegExpRoute.js";
|
|
4
4
|
import { Route } from "./routing/Route.js";
|
|
5
5
|
import { Router } from "./routing/Router.js";
|
|
6
|
+
import { parseRoute } from "./routing/parseRoute.js";
|
|
6
7
|
import { registerRoute } from "./routing/registerRoute.js";
|
|
7
8
|
import { setCatchHandler } from "./routing/setCatchHandler.js";
|
|
8
9
|
import { setDefaultHandler } from "./routing/setDefaultHandler.js";
|
|
10
|
+
import { getSingletonRouter, setSingletonRouter } from "./routing/singletonRouter.js";
|
|
9
11
|
import { unregisterRoute } from "./routing/unregisterRoute.js";
|
|
10
12
|
import type { HTTPMethod } from "./routing/utils/constants.js";
|
|
11
|
-
export { NavigationRoute, RegExpRoute, registerRoute, Route, Router, setCatchHandler, setDefaultHandler, unregisterRoute };
|
|
13
|
+
export { NavigationRoute, RegExpRoute, parseRoute, registerRoute, Route, Router, setCatchHandler, setDefaultHandler, getSingletonRouter, setSingletonRouter, unregisterRoute, };
|
|
12
14
|
export type { HTTPMethod, NavigationRouteMatchOptions };
|
|
13
15
|
//# sourceMappingURL=index.routing.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.routing.d.ts","sourceRoot":"","sources":["../src/index.routing.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,8BAA8B,CAAC;AAChF,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAC/D,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAC3D,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAC/D,OAAO,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AACnE,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAC/D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAE/D,OAAO,
|
|
1
|
+
{"version":3,"file":"index.routing.d.ts","sourceRoot":"","sources":["../src/index.routing.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,8BAA8B,CAAC;AAChF,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAC/D,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAC3D,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAC/D,OAAO,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AACnE,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AACtF,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAC/D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAE/D,OAAO,EACL,eAAe,EACf,WAAW,EACX,UAAU,EACV,aAAa,EACb,KAAK,EACL,MAAM,EACN,eAAe,EACf,iBAAiB,EACjB,kBAAkB,EAClB,kBAAkB,EAClB,eAAe,GAChB,CAAC;AAEF,YAAY,EAAE,UAAU,EAAE,2BAA2B,EAAE,CAAC"}
|
package/dist/index.routing.js
CHANGED
|
@@ -1,21 +1,19 @@
|
|
|
1
1
|
export { N as NavigationRoute } from './chunks/NavigationRoute.js';
|
|
2
|
-
import { g as
|
|
3
|
-
export { a as RegExpRoute, R as Route, b as Router,
|
|
2
|
+
import { g as getSingletonRouter } from './chunks/singletonRouter.js';
|
|
3
|
+
export { a as RegExpRoute, R as Route, b as Router, p as parseRoute, s as setSingletonRouter } from './chunks/singletonRouter.js';
|
|
4
|
+
export { r as registerRoute } from './chunks/registerRoute.js';
|
|
4
5
|
import '@serwist/core/internal';
|
|
5
6
|
|
|
6
7
|
const setCatchHandler = (handler)=>{
|
|
7
|
-
|
|
8
|
-
defaultRouter.setCatchHandler(handler);
|
|
8
|
+
getSingletonRouter().setCatchHandler(handler);
|
|
9
9
|
};
|
|
10
10
|
|
|
11
11
|
const setDefaultHandler = (handler)=>{
|
|
12
|
-
|
|
13
|
-
defaultRouter.setDefaultHandler(handler);
|
|
12
|
+
getSingletonRouter().setDefaultHandler(handler);
|
|
14
13
|
};
|
|
15
14
|
|
|
16
15
|
const unregisterRoute = (route)=>{
|
|
17
|
-
|
|
18
|
-
defaultRouter.unregisterRoute(route);
|
|
16
|
+
getSingletonRouter().unregisterRoute(route);
|
|
19
17
|
};
|
|
20
18
|
|
|
21
|
-
export { setCatchHandler, setDefaultHandler, unregisterRoute };
|
|
19
|
+
export { getSingletonRouter, setCatchHandler, setDefaultHandler, unregisterRoute };
|
|
@@ -1,4 +1,10 @@
|
|
|
1
|
+
import type { Router } from "../../routing/Router.js";
|
|
1
2
|
export interface GoogleAnalyticsInitializeOptions {
|
|
3
|
+
/**
|
|
4
|
+
* An optional `Router` instance. If not provided, the singleton `Router`
|
|
5
|
+
* will be used.
|
|
6
|
+
*/
|
|
7
|
+
router?: Router;
|
|
2
8
|
/**
|
|
3
9
|
* The cache name to store and retrieve analytics.js. Defaults to the cache names provided by `@serwist/core`.
|
|
4
10
|
*/
|
|
@@ -20,7 +26,9 @@ export interface GoogleAnalyticsInitializeOptions {
|
|
|
20
26
|
hitFilter?: (params: URLSearchParams) => void;
|
|
21
27
|
}
|
|
22
28
|
/**
|
|
29
|
+
* Initialize Serwist's offline Google Analytics v3 support.
|
|
30
|
+
*
|
|
23
31
|
* @param options
|
|
24
32
|
*/
|
|
25
|
-
export declare const initialize: (options?: GoogleAnalyticsInitializeOptions) => void;
|
|
33
|
+
export declare const initialize: ({ cacheName, router, ...options }?: GoogleAnalyticsInitializeOptions) => void;
|
|
26
34
|
//# sourceMappingURL=initialize.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"initialize.d.ts","sourceRoot":"","sources":["../../../src/plugins/googleAnalytics/initialize.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"initialize.d.ts","sourceRoot":"","sources":["../../../src/plugins/googleAnalytics/initialize.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AAatD,MAAM,WAAW,gCAAgC;IAC/C;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;OAKG;IACH,kBAAkB,CAAC,EAAE;QAAE,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAC;IACrD;;;;OAIG;IACH,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,eAAe,KAAK,IAAI,CAAC;CAC/C;AAyID;;;;GAIG;AACH,eAAO,MAAM,UAAU,uCAA8D,gCAAgC,KAAQ,IAkB5H,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"addRoute.d.ts","sourceRoot":"","sources":["../../src/precaching/addRoute.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"addRoute.d.ts","sourceRoot":"","sources":["../../src/precaching/addRoute.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAEvD;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,QAAQ,aAAc,oBAAoB,KAAG,IAKzD,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"matchPrecache.d.ts","sourceRoot":"","sources":["../../src/precaching/matchPrecache.ts"],"names":[],"mappings":"AAUA;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,aAAa,YAAa,MAAM,GAAG,OAAO,KAAG,QAAQ,QAAQ,GAAG,SAAS,
|
|
1
|
+
{"version":3,"file":"matchPrecache.d.ts","sourceRoot":"","sources":["../../src/precaching/matchPrecache.ts"],"names":[],"mappings":"AAUA;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,aAAa,YAAa,MAAM,GAAG,OAAO,KAAG,QAAQ,QAAQ,GAAG,SAAS,CAErF,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"precache.d.ts","sourceRoot":"","sources":["../../src/precaching/precache.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"precache.d.ts","sourceRoot":"","sources":["../../src/precaching/precache.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,QAAQ,YAAa,CAAC,aAAa,GAAG,MAAM,CAAC,EAAE,KAAG,IAG9D,CAAC"}
|