@webqit/webflo 0.11.61-0 → 1.0.0

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 (118) hide show
  1. package/.gitignore +7 -7
  2. package/LICENSE +20 -20
  3. package/README.md +2079 -2074
  4. package/docker/Dockerfile +42 -42
  5. package/docker/README.md +91 -91
  6. package/docker/package.json +2 -2
  7. package/package.json +80 -81
  8. package/src/{Context.js → AbstractContext.js} +71 -79
  9. package/src/config-pi/deployment/Env.js +68 -68
  10. package/src/config-pi/deployment/Layout.js +63 -63
  11. package/src/config-pi/deployment/Origins.js +139 -139
  12. package/src/config-pi/deployment/Proxy.js +74 -74
  13. package/src/config-pi/deployment/index.js +17 -17
  14. package/src/config-pi/index.js +15 -15
  15. package/src/config-pi/runtime/Client.js +116 -98
  16. package/src/config-pi/runtime/Server.js +125 -125
  17. package/src/config-pi/runtime/client/Worker.js +109 -134
  18. package/src/config-pi/runtime/client/index.js +11 -11
  19. package/src/config-pi/runtime/index.js +17 -17
  20. package/src/config-pi/runtime/server/Headers.js +74 -74
  21. package/src/config-pi/runtime/server/Redirects.js +69 -69
  22. package/src/config-pi/runtime/server/index.js +13 -13
  23. package/src/config-pi/static/Manifest.js +319 -319
  24. package/src/config-pi/static/Ssg.js +49 -49
  25. package/src/config-pi/static/index.js +13 -13
  26. package/src/deployment-pi/index.js +10 -10
  27. package/src/deployment-pi/origins/index.js +216 -216
  28. package/src/index.js +11 -19
  29. package/src/runtime-pi/HttpEvent.js +126 -106
  30. package/src/runtime-pi/HttpUser.js +126 -0
  31. package/src/runtime-pi/MessagingOverBroadcast.js +9 -0
  32. package/src/runtime-pi/MessagingOverChannel.js +85 -0
  33. package/src/runtime-pi/MessagingOverSocket.js +106 -0
  34. package/src/runtime-pi/MultiportMessagingAPI.js +81 -0
  35. package/src/runtime-pi/WebfloCookieStorage.js +27 -0
  36. package/src/runtime-pi/WebfloEventTarget.js +39 -0
  37. package/src/runtime-pi/WebfloMessageEvent.js +58 -0
  38. package/src/runtime-pi/WebfloMessagingAPI.js +69 -0
  39. package/src/runtime-pi/{Router.js → WebfloRouter.js} +99 -130
  40. package/src/runtime-pi/WebfloRuntime.js +52 -0
  41. package/src/runtime-pi/WebfloStorage.js +109 -0
  42. package/src/runtime-pi/client/ClientMessaging.js +5 -0
  43. package/src/runtime-pi/client/Context.js +3 -7
  44. package/src/runtime-pi/client/CookieStorage.js +17 -0
  45. package/src/runtime-pi/client/Router.js +38 -48
  46. package/src/runtime-pi/client/SessionStorage.js +33 -0
  47. package/src/runtime-pi/client/Url.js +156 -205
  48. package/src/runtime-pi/client/WebfloClient.js +544 -0
  49. package/src/runtime-pi/client/WebfloRootClient1.js +179 -0
  50. package/src/runtime-pi/client/WebfloRootClient2.js +109 -0
  51. package/src/runtime-pi/client/WebfloSubClient.js +165 -0
  52. package/src/runtime-pi/client/Workport.js +118 -178
  53. package/src/runtime-pi/client/generate.js +480 -471
  54. package/src/runtime-pi/client/index.js +16 -21
  55. package/src/runtime-pi/client/worker/ClientMessaging.js +5 -0
  56. package/src/runtime-pi/client/worker/Context.js +3 -7
  57. package/src/runtime-pi/client/worker/CookieStorage.js +17 -0
  58. package/src/runtime-pi/client/worker/SessionStorage.js +13 -0
  59. package/src/runtime-pi/client/worker/WebfloWorker.js +294 -0
  60. package/src/runtime-pi/client/worker/Workport.js +17 -85
  61. package/src/runtime-pi/client/worker/index.js +10 -21
  62. package/src/runtime-pi/index.js +6 -13
  63. package/src/runtime-pi/server/ClientMessaging.js +18 -0
  64. package/src/runtime-pi/server/ClientMessagingRegistry.js +57 -0
  65. package/src/runtime-pi/server/Context.js +11 -15
  66. package/src/runtime-pi/server/CookieStorage.js +17 -0
  67. package/src/runtime-pi/server/Router.js +93 -159
  68. package/src/runtime-pi/server/SessionStorage.js +53 -0
  69. package/src/runtime-pi/server/WebfloServer.js +755 -0
  70. package/src/runtime-pi/server/index.js +10 -21
  71. package/src/runtime-pi/util-http.js +322 -86
  72. package/src/runtime-pi/util-url.js +146 -146
  73. package/src/runtime-pi/xURL.js +108 -105
  74. package/src/runtime-pi/xfetch.js +22 -22
  75. package/src/services-pi/cert/http-auth-hook.js +22 -22
  76. package/src/services-pi/cert/http-cleanup-hook.js +22 -22
  77. package/src/services-pi/cert/index.js +79 -79
  78. package/src/services-pi/index.js +8 -8
  79. package/src/static-pi/index.js +10 -10
  80. package/src/webflo.js +30 -30
  81. package/test/index.test.js +26 -26
  82. package/test/site/package.json +9 -9
  83. package/test/site/public/bundle.html +5 -5
  84. package/test/site/public/bundle.html.json +3 -3
  85. package/test/site/public/bundle.js +2 -2
  86. package/test/site/public/bundle.webflo.js +15 -15
  87. package/test/site/public/index.html +29 -29
  88. package/test/site/public/index1.html +34 -34
  89. package/test/site/public/page-2/bundle.html +4 -4
  90. package/test/site/public/page-2/bundle.js +2 -2
  91. package/test/site/public/page-2/index.html +45 -45
  92. package/test/site/public/page-2/main.html +2 -2
  93. package/test/site/public/page-4/subpage/bundle.js +2 -2
  94. package/test/site/public/page-4/subpage/index.html +30 -30
  95. package/test/site/public/sparoots.json +4 -4
  96. package/test/site/public/worker.js +3 -3
  97. package/test/site/server/index.js +15 -15
  98. package/src/runtime-pi/Application.js +0 -29
  99. package/src/runtime-pi/Cookies.js +0 -82
  100. package/src/runtime-pi/Runtime.js +0 -21
  101. package/src/runtime-pi/client/Application.js +0 -100
  102. package/src/runtime-pi/client/Runtime.js +0 -332
  103. package/src/runtime-pi/client/createStorage.js +0 -57
  104. package/src/runtime-pi/client/oohtml/full.js +0 -7
  105. package/src/runtime-pi/client/oohtml/namespacing.js +0 -7
  106. package/src/runtime-pi/client/oohtml/scripting.js +0 -8
  107. package/src/runtime-pi/client/oohtml/templating.js +0 -8
  108. package/src/runtime-pi/client/worker/Application.js +0 -44
  109. package/src/runtime-pi/client/worker/Runtime.js +0 -269
  110. package/src/runtime-pi/server/Application.js +0 -116
  111. package/src/runtime-pi/server/Runtime.js +0 -557
  112. package/src/runtime-pi/xFormData.js +0 -24
  113. package/src/runtime-pi/xHeaders.js +0 -146
  114. package/src/runtime-pi/xRequest.js +0 -46
  115. package/src/runtime-pi/xRequestHeaders.js +0 -109
  116. package/src/runtime-pi/xResponse.js +0 -33
  117. package/src/runtime-pi/xResponseHeaders.js +0 -117
  118. package/src/runtime-pi/xxHttpMessage.js +0 -102
@@ -1,332 +0,0 @@
1
-
2
- /**
3
- * @imports
4
- */
5
- import { _before, _toTitle } from '@webqit/util/str/index.js';
6
- import { Observer } from '@webqit/oohtml-ssr/apis.js';
7
- import createStorage from './createStorage.js';
8
- import Url from './Url.js';
9
- import Workport from './Workport.js';
10
- import xRequest from "../xRequest.js";
11
- import xResponse from "../xResponse.js";
12
- import xfetch from '../xfetch.js';
13
- import HttpEvent from '../HttpEvent.js';
14
- import _Runtime from '../Runtime.js';
15
- import { params } from '../util-url.js';
16
-
17
- export {
18
- HttpEvent,
19
- Observer,
20
- }
21
-
22
- export default class Runtime extends _Runtime {
23
-
24
- /**
25
- * Runtime
26
- *
27
- * @param Object cx
28
- * @param Function applicationInstance
29
- *
30
- * @return void
31
- */
32
- constructor(cx, applicationInstance) {
33
- super(cx, applicationInstance);
34
- // -----------------------
35
- // Initialize location
36
- Observer.set(this, 'location', new Url(window.document.location));
37
- // -----------------------
38
- // Syndicate changes to the browser;s location bar
39
- Observer.observe(this.location, [[ 'href' ]], ([e]) => {
40
- if (e.value === 'http:' || (e.detail || {}).src === window.document.location) {
41
- // Already from a "popstate" event as above, so don't push again
42
- return;
43
- }
44
- if (e.value === window.document.location.href || e.value + '/' === window.document.location.href) {
45
- window.history.replaceState(window.history.state, '', this.location.href);
46
- } else {
47
- try { window.history.pushState(window.history.state, '', this.location.href); } catch(e) {}
48
- }
49
- }, { diff: true });
50
-
51
- // -----------------------
52
- // This event is triggered by
53
- // either the browser back button,
54
- // the window.history.back(),
55
- // the window.history.forward(),
56
- // or the window.history.go() action.
57
- window.addEventListener('popstate', e => {
58
- // Needed to allow window.document.location
59
- // to update to window.location
60
- window.setTimeout(() => {
61
- this.go(Url.copy(window.document.location), {}, { src: window.document.location, srcType: 'history', });
62
- }, 0);
63
- });
64
-
65
- // -----------------------
66
- // Capture all link-clicks
67
- // and fire to this router.
68
- window.addEventListener('click', e => {
69
- var anchorEl = e.target.closest('a');
70
- if (!anchorEl || !anchorEl.href) return;
71
- if (!anchorEl.target && !anchorEl.download && this.isSpaRoute(anchorEl, e)) {
72
- // Publish everything, including hash
73
- this.go(Url.copy(anchorEl), {}, { src: anchorEl, srcType: 'link', });
74
- if (!this.isHashAction(anchorEl)) {
75
- e.preventDefault();
76
- }
77
- }
78
- });
79
-
80
- // -----------------------
81
- // Capture all form-submit
82
- // and fire to this router.
83
- window.addEventListener('submit', e => {
84
- const form = e.target.closest('form'), submitter = e.submitter;
85
- const submitParams = [ 'action', 'enctype', 'method', 'noValidate', 'target' ].reduce((params, prop) => {
86
- params[prop] = submitter && submitter.hasAttribute(`form${prop.toLowerCase()}`) ? submitter[`form${_toTitle(prop)}`] : form[prop];
87
- return params;
88
- }, {});
89
- // We support method hacking
90
- submitParams.method = (submitter && submitter.dataset.formmethod) || form.dataset.method || submitParams.method;
91
- submitParams.submitter = submitter;
92
- // ---------------
93
- var actionEl = window.document.createElement('a');
94
- actionEl.href = submitParams.action;
95
- // ---------------
96
- // If not targeted and same origin...
97
- if (!submitParams.target && this.isSpaRoute(actionEl, e)) {
98
- // Build data
99
- var formData = new FormData(form);
100
- if ((submitter || {}).name) {
101
- formData.set(submitter.name, submitter.value);
102
- }
103
- if (submitParams.method.toUpperCase() === 'GET') {
104
- var query = params.parse(actionEl.search);
105
- Array.from(formData.entries()).forEach(_entry => {
106
- params.set(query, _entry[0], _entry[1]);
107
- });
108
- actionEl.search = params.stringify(query);
109
- formData = null;
110
- }
111
- this.go(Url.copy(actionEl), {
112
- method: submitParams.method,
113
- body: formData,
114
- }, { ...submitParams, src: form, srcType: 'form', });
115
- if (!this.isHashAction(actionEl)) {
116
- e.preventDefault();
117
- }
118
- }
119
- });
120
-
121
- // -----------------------
122
- // Initialize network
123
- Observer.set(this, 'network', {});
124
- window.addEventListener('online', () => Observer.set(this.network, 'connectivity', 'online'));
125
- window.addEventListener('offline', () => Observer.set(this.network, 'connectivity', 'offline'));
126
-
127
- // -----------------------
128
- // Service Worker && COMM
129
- if (this.cx.params.service_worker_support) {
130
- const { public_base_url: base, worker_filename: filename, worker_scope: scope } = this.cx.params;
131
- const workport = new Workport(base + filename, { scope, startMessages: true });
132
- Observer.set(this, 'workport', workport);
133
- }
134
-
135
- // -----------------------
136
- // Initialize and Hydration
137
- (async () => {
138
- let shouldHydrate;
139
- if (this.app.init) {
140
- const request = this.generateRequest(this.location);
141
- const httpEvent = new HttpEvent(request, { srcType: 'initialization' }, (id = null, persistent = false) => this.getSession(httpEvent, id, persistent));
142
- shouldHydrate = await this.app.init(httpEvent, ( ...args ) => this.remoteFetch( ...args ));
143
- }
144
- if (shouldHydrate !== false) {
145
- this.go(this.location, {}, { srcType: 'hydration' });
146
- }
147
- })();
148
-
149
- }
150
-
151
- /**
152
- * History object
153
- */
154
- get history() {
155
- return window.history;
156
- }
157
-
158
- // Check is-hash-action
159
- isHashAction(urlObj) {
160
- const isHashNav = _before(window.document.location.href, '#') === _before(urlObj.href, '#') && urlObj.href.includes('#');
161
- return isHashNav// && urlObj.hash.length > 1 && document.querySelector(urlObj.hash);
162
- }
163
-
164
- // Check is-spa-route
165
- isSpaRoute(url, e = undefined) {
166
- url = typeof url === 'string' ? new URL(url, this.location.origin) : url;
167
- if (url.origin && url.origin !== this.location.origin) return false;
168
- if (e && (e.metaKey || e.altKey || e.ctrlKey || e.shiftKey)) return false;
169
- if (!this.cx.params.routing) return true;
170
- if (this.cx.params.routing.targets === false/** explicit false means disabled */) return false;
171
- let b = url.pathname.split('/').filter(s => s);
172
- const match = a => {
173
- a = a.split('/').filter(s => s);
174
- return a.reduce((prev, s, i) => prev && (s === b[i] || [s, b[i]].includes('-')), true);
175
- };
176
- return match(this.cx.params.routing.root) && this.cx.params.routing.subroots.reduce((prev, subroot) => {
177
- return prev && !match(subroot);
178
- }, true);
179
- }
180
-
181
- // Generates request object
182
- generateRequest(href, init = {}) {
183
- return new xRequest(href, {
184
- signal: this._abortController && this._abortController.signal,
185
- ...init,
186
- headers: {
187
- 'Accept': 'application/json',
188
- 'X-Redirect-Policy': 'manual-when-cross-spa',
189
- 'X-Redirect-Code': this._xRedirectCode,
190
- 'X-Powered-By': '@webqit/webflo',
191
- ...(init.headers || {}),
192
- },
193
- });
194
- }
195
-
196
- // Generates session object
197
- createStorage(e, id = null, persistent = false) {
198
- return createStorage(id, persistent);
199
- }
200
-
201
- /**
202
- * Performs a request.
203
- *
204
- * @param object|string href
205
- * @param object|Request init
206
- * @param object src
207
- *
208
- * @return Response
209
- */
210
- async go(url, init = {}, detail = {}) {
211
- url = typeof url === 'string' ? new URL(url, this.location.origin) : url;
212
- if (!(init instanceof Request) && !init.referrer) {
213
- init = { referrer: this.location.href, ...init };
214
- }
215
- // ------------
216
- // Put his forward before instantiating a request and aborting previous
217
- // Same-page hash-links clicks on chrome recurse here from histroy popstate
218
- if (![ 'hydration', 'rdr' ].includes(detail.srcType) && (_before(url.href, '#') === _before(init.referrer, '#') && (init.method || 'GET').toUpperCase() === 'GET')) {
219
- return new xResponse(null, { status: 304 }); // Not Modified
220
- }
221
- // ------------
222
- if (this._abortController) {
223
- this._abortController.abort();
224
- }
225
- this._abortController = new AbortController();
226
- this._xRedirectCode = 200;
227
- // ------------
228
- // States
229
- // ------------
230
- Observer.set(this.network, 'error', null);
231
- Observer.set(this.network, 'requesting', { init, ...detail });
232
- if (['link', 'form'].includes(detail.srcType)) {
233
- detail.src.state && (detail.src.state.active = true);
234
- detail.submitter && detail.submitter.state && (detail.submitter.state.active = true);
235
- }
236
- // ------------
237
- // Run
238
- // ------------
239
- const request = this.generateRequest(url.href, init);
240
- const httpEvent = new HttpEvent(request, detail, (id = null, persistent = false) => this.createStorage(httpEvent, id, persistent));
241
- let response, finalResponse;
242
- try {
243
- // ------------
244
- // Response
245
- // ------------
246
- response = await this.app.handle(httpEvent, ( ...args ) => this.remoteFetch( ...args ));
247
- finalResponse = this.handleResponse(httpEvent, response);
248
- // ------------
249
- // Address bar
250
- // ------------
251
- if (response && response.redirected) {
252
- Observer.set(this.location, { href: response.url }, { detail: { redirected: true, ...detail }, });
253
- } else if (![302, 301].includes(finalResponse.status)) {
254
- Observer.set(this.location, Url.copy(url)/* copy() is important */, { detail });
255
- }
256
- // ------------
257
- // States
258
- // ------------
259
- if (['link', 'form'].includes(detail.srcType)) {
260
- detail.src.state && (detail.src.state.active = false);
261
- detail.submitter && detail.submitter.state && (detail.submitter.state.active = false);
262
- }
263
- // ------------
264
- // Rendering
265
- // ------------
266
- if (finalResponse.ok && (finalResponse.headers.contentType === 'application/json' || finalResponse.headers.contentType.startsWith('multipart/form-data'))) {
267
- this.app.render && await this.app.render(httpEvent, finalResponse);
268
- } else if (!finalResponse.ok) {
269
- if ([404, 500].includes(finalResponse.status)) {
270
- Observer.set(this.network, 'error', new Error(finalResponse.statusText, { cause: finalResponse.status }));
271
- }
272
- if (!finalResponse.headers.get('Location')) {
273
- this.app.unrender && await this.app.unrender(httpEvent);
274
- }
275
- }
276
- } catch(e) {
277
- console.error(e);
278
- Observer.set(this.network, 'error', { ...e, retry: () => this.go(url, init = {}, detail) });
279
- finalResponse = new xResponse(e.message, { status: 500 });
280
- }
281
- // ------------
282
- // Return value
283
- return finalResponse;
284
- }
285
-
286
- // Initiates remote fetch and sets the status
287
- async remoteFetch(request, ...args) {
288
- let href = request;
289
- if (request instanceof Request) {
290
- href = request.url;
291
- } else if (request instanceof URL) {
292
- href = request.href;
293
- }
294
- Observer.set(this.network, 'remote', href);
295
- let _response = xfetch(request, ...args);
296
- // This catch() is NOT intended to handle failure of the fetch
297
- _response.catch(e => Observer.set(this.network, 'error', e));
298
- // Return xResponse
299
- return _response.then(async response => {
300
- // Stop loading status
301
- Observer.set(this.network, 'remote', null);
302
- return xResponse.compat(response);
303
- });
304
- }
305
-
306
- // Handles response object
307
- handleResponse(e, response) {
308
- if (!response && response !== 0) { response = new xResponse(null, { status: 404 }); }
309
- else if (!(response instanceof xResponse)) { response = xResponse.compat(response); }
310
- Observer.set(this.network, 'requesting', null);
311
- Observer.set(this.network, 'redirecting', null);
312
- if (!response.redirected) {
313
- let location = response.headers.get('Location');
314
- if (location) {
315
- let xActualRedirectCode = parseInt(response.headers.get('X-Redirect-Code'));
316
- Observer.set(this.network, 'redirecting', location);
317
- if (xActualRedirectCode && response.status === this._xRedirectCode) {
318
- response.attrs.status = xActualRedirectCode;
319
- window.location = location;
320
- } else if ([302,301].includes(response.status)) {
321
- if (!this.isSpaRoute(location)) {
322
- window.location = location;
323
- } else {
324
- this.go(location, {}, { srcType: 'rdr' });
325
- }
326
- }
327
- }
328
- }
329
- return response;
330
- }
331
-
332
- }
@@ -1,57 +0,0 @@
1
-
2
-
3
- /**
4
- * @imports
5
- */
6
- import { _isString, _isUndefined } from '@webqit/util/js/index.js';
7
- import { Observer } from './Runtime.js';
8
-
9
- export default function(namespace = null, persistent = false) {
10
-
11
- const storeType = persistent ? 'localStorage' : 'sessionStorage';
12
- if (!window[storeType]) {
13
- throw new Error(`The specified Web Storage API ${storeType} is invalid or not supported`);
14
- }
15
-
16
- const _storage = {};
17
- Observer.intercept(_storage, (event, received, next) => {
18
- const key = namespace ? `${namespace}.${event.name}` : event.name;
19
- if (event.type === 'get' && _isString(key)) {
20
- const value = window[storeType].getItem(key);
21
- return !_isUndefined(value) ? JSON.parse(value) : value;
22
- }
23
- if (event.type === 'set') {
24
- window[storeType].setItem(key, !_isUndefined(event.value) ? JSON.stringify(event.value) : event.value);
25
- return true;
26
- }
27
- if (event.type === 'deleteProperty') {
28
- window[storeType].removeItem(key);
29
- return true;
30
- }
31
- if (event.type === 'has') {
32
- for(let i = 0; i < window[storeType].length; i ++){
33
- if (window[storeType].key(i) === key) {
34
- return true;
35
- }
36
- };
37
- return false;
38
- }
39
- if (event.type === 'ownKeys') {
40
- const keys = [];
41
- for(let i = 0; i < window[storeType].length; i ++){
42
- keys.push(window[storeType].key(i));
43
- };
44
- return keys;
45
- }
46
- if (event.type === 'getOwnPropertyDescriptor') {
47
- return { enumerable: true, configurable: true };
48
- }
49
- return next();
50
- });
51
-
52
- return Observer.proxy(_storage);
53
- }
54
-
55
- export {
56
- Observer,
57
- }
@@ -1,7 +0,0 @@
1
-
2
- /**
3
- * @imports
4
- */
5
- import { OOHTML } from '@webqit/oohtml-ssr/apis.js';
6
-
7
- OOHTML.call( window );
@@ -1,7 +0,0 @@
1
-
2
- /**
3
- * @imports
4
- */
5
- import { NamespacedHTML } from '@webqit/oohtml-ssr/apis.js';
6
-
7
- NamespacedHTML.call( window );
@@ -1,8 +0,0 @@
1
-
2
- /**
3
- * @imports
4
- */
5
- import { StateAPI, Subscript } from '@webqit/oohtml-ssr/apis.js';
6
-
7
- StateAPI.call( window );
8
- Subscript.call( window );
@@ -1,8 +0,0 @@
1
-
2
- /**
3
- * @imports
4
- */
5
- import { HTMLModules, HTMLImports } from '@webqit/oohtml-ssr/apis.js';
6
-
7
- HTMLModules.call( window );
8
- HTMLImports.call( window );
@@ -1,44 +0,0 @@
1
-
2
- /**
3
- * @imports
4
- */
5
- import Router from '../Router.js';
6
- import _Application from '../../Application.js';
7
-
8
- export default class Application extends _Application {
9
-
10
- // Returns router class
11
- get Router() {
12
- return Router;
13
- }
14
-
15
- /**
16
- * Handles HTTP events.
17
- *
18
- * @param HttpEvent httpEvent
19
- * @param Function remoteFetch
20
- *
21
- * @return Response
22
- */
23
- async handle(httpEvent, remoteFetch) {
24
- // The app router
25
- const router = new this.Router(this.cx, httpEvent.url.pathname);
26
- const handle = async () => {
27
- // --------
28
- // ROUTE FOR DATA
29
- // --------
30
- return router.route([httpEvent.request.method, 'default'], httpEvent, {}, async event => {
31
- if (event !== httpEvent) {
32
- // This was nexted()
33
- if (!event.request.headers.has('Accept')) {
34
- event.request.headers.set('Accept', 'application/json');
35
- }
36
- }
37
- return remoteFetch(event.request);
38
- }, remoteFetch);
39
- };
40
- return handle();
41
- }
42
-
43
- }
44
-