@webqit/webflo 0.11.61-0 → 0.11.61
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/.gitignore +7 -7
- package/LICENSE +20 -20
- package/README.md +2079 -2074
- package/docker/Dockerfile +42 -42
- package/docker/README.md +91 -91
- package/docker/package.json +2 -2
- package/package.json +80 -81
- package/src/Context.js +79 -79
- package/src/config-pi/deployment/Env.js +68 -68
- package/src/config-pi/deployment/Layout.js +63 -63
- package/src/config-pi/deployment/Origins.js +139 -139
- package/src/config-pi/deployment/Proxy.js +74 -74
- package/src/config-pi/deployment/index.js +17 -17
- package/src/config-pi/index.js +15 -15
- package/src/config-pi/runtime/Client.js +116 -98
- package/src/config-pi/runtime/Server.js +125 -125
- package/src/config-pi/runtime/client/Worker.js +109 -134
- package/src/config-pi/runtime/client/index.js +11 -11
- package/src/config-pi/runtime/index.js +17 -17
- package/src/config-pi/runtime/server/Headers.js +74 -74
- package/src/config-pi/runtime/server/Redirects.js +69 -69
- package/src/config-pi/runtime/server/index.js +13 -13
- package/src/config-pi/static/Manifest.js +319 -319
- package/src/config-pi/static/Ssg.js +49 -49
- package/src/config-pi/static/index.js +13 -13
- package/src/deployment-pi/index.js +10 -10
- package/src/deployment-pi/origins/index.js +216 -216
- package/src/index.js +19 -19
- package/src/runtime-pi/Application.js +28 -28
- package/src/runtime-pi/Cookies.js +81 -81
- package/src/runtime-pi/HttpEvent.js +106 -106
- package/src/runtime-pi/Router.js +130 -130
- package/src/runtime-pi/Runtime.js +20 -20
- package/src/runtime-pi/client/Application.js +76 -100
- package/src/runtime-pi/client/Context.js +7 -7
- package/src/runtime-pi/client/Router.js +48 -48
- package/src/runtime-pi/client/Runtime.js +524 -331
- package/src/runtime-pi/client/Url.js +204 -205
- package/src/runtime-pi/client/Workport.js +190 -178
- package/src/runtime-pi/client/createStorage.js +57 -56
- package/src/runtime-pi/client/generate.js +480 -471
- package/src/runtime-pi/client/index.js +21 -21
- package/src/runtime-pi/client/worker/Application.js +44 -44
- package/src/runtime-pi/client/worker/Context.js +7 -7
- package/src/runtime-pi/client/worker/Runtime.js +274 -268
- package/src/runtime-pi/client/worker/Workport.js +77 -85
- package/src/runtime-pi/client/worker/index.js +21 -21
- package/src/runtime-pi/index.js +13 -13
- package/src/runtime-pi/server/Application.js +100 -115
- package/src/runtime-pi/server/Context.js +15 -15
- package/src/runtime-pi/server/Router.js +159 -159
- package/src/runtime-pi/server/Runtime.js +557 -556
- package/src/runtime-pi/server/index.js +21 -21
- package/src/runtime-pi/util-http.js +85 -85
- package/src/runtime-pi/util-url.js +146 -146
- package/src/runtime-pi/xFormData.js +23 -23
- package/src/runtime-pi/xHeaders.js +145 -145
- package/src/runtime-pi/xRequest.js +45 -45
- package/src/runtime-pi/xRequestHeaders.js +108 -108
- package/src/runtime-pi/xResponse.js +32 -32
- package/src/runtime-pi/xResponseHeaders.js +116 -116
- package/src/runtime-pi/xURL.js +105 -105
- package/src/runtime-pi/xfetch.js +22 -22
- package/src/runtime-pi/xxHttpMessage.js +101 -101
- package/src/services-pi/cert/http-auth-hook.js +22 -22
- package/src/services-pi/cert/http-cleanup-hook.js +22 -22
- package/src/services-pi/cert/index.js +79 -79
- package/src/services-pi/index.js +8 -8
- package/src/static-pi/index.js +10 -10
- package/src/webflo.js +30 -30
- package/test/index.test.js +26 -26
- package/test/site/package.json +9 -9
- package/test/site/public/bundle.html +5 -5
- package/test/site/public/bundle.html.json +3 -3
- package/test/site/public/bundle.js +2 -2
- package/test/site/public/bundle.webflo.js +15 -15
- package/test/site/public/index.html +29 -29
- package/test/site/public/index1.html +34 -34
- package/test/site/public/page-2/bundle.html +4 -4
- package/test/site/public/page-2/bundle.js +2 -2
- package/test/site/public/page-2/index.html +45 -45
- package/test/site/public/page-2/main.html +2 -2
- package/test/site/public/page-4/subpage/bundle.js +2 -2
- package/test/site/public/page-4/subpage/index.html +30 -30
- package/test/site/public/sparoots.json +4 -4
- package/test/site/public/worker.js +3 -3
- package/test/site/server/index.js +15 -15
- package/src/runtime-pi/client/oohtml/full.js +0 -7
- package/src/runtime-pi/client/oohtml/namespacing.js +0 -7
- package/src/runtime-pi/client/oohtml/scripting.js +0 -8
- package/src/runtime-pi/client/oohtml/templating.js +0 -8
|
@@ -1,269 +1,275 @@
|
|
|
1
|
-
|
|
2
|
-
/**
|
|
3
|
-
* @imports
|
|
4
|
-
*/
|
|
5
|
-
import
|
|
6
|
-
import {
|
|
7
|
-
import { pattern } from '../../util-url.js';
|
|
8
|
-
import Workport from './Workport.js';
|
|
9
|
-
import _Runtime from '../../Runtime.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
|
-
|
|
15
|
-
export {
|
|
16
|
-
HttpEvent,
|
|
17
|
-
Observer,
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* ---------------------------
|
|
22
|
-
* The Runtime Initializer
|
|
23
|
-
* ---------------------------
|
|
24
|
-
*/
|
|
25
|
-
|
|
26
|
-
export default class Runtime extends _Runtime {
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Runtime
|
|
30
|
-
*
|
|
31
|
-
* @param Object cx
|
|
32
|
-
* @param Function applicationInstance
|
|
33
|
-
*
|
|
34
|
-
* @return void
|
|
35
|
-
*/
|
|
36
|
-
constructor(cx, applicationInstance) {
|
|
37
|
-
super(cx, applicationInstance);
|
|
38
|
-
// ---------------
|
|
39
|
-
this.mockSessionStore = {};
|
|
40
|
-
// --------------
|
|
41
|
-
// ONINSTALL
|
|
42
|
-
self.addEventListener('install', evt => {
|
|
43
|
-
if (this.cx.params.skip_waiting) { self.skipWaiting(); }
|
|
44
|
-
// Manage CACHE
|
|
45
|
-
if (this.cx.params.cache_name && (this.cx.params.cache_only_urls || []).length) {
|
|
46
|
-
// Add files to cache
|
|
47
|
-
evt.waitUntil( self.caches.open(this.cx.params.cache_name).then(cache => {
|
|
48
|
-
if (this.cx.logger) { this.cx.logger.log('[ServiceWorker] Pre-caching resources.'); }
|
|
49
|
-
const
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
if (this.cx.params.
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
//
|
|
94
|
-
//
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
*
|
|
122
|
-
*
|
|
123
|
-
* @param object
|
|
124
|
-
*
|
|
125
|
-
* @
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
response = await this.
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
//
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
1
|
+
|
|
2
|
+
/**
|
|
3
|
+
* @imports
|
|
4
|
+
*/
|
|
5
|
+
import Observer from '@webqit/observer';
|
|
6
|
+
import { _any } from '@webqit/util/arr/index.js';
|
|
7
|
+
import { pattern } from '../../util-url.js';
|
|
8
|
+
import Workport from './Workport.js';
|
|
9
|
+
import _Runtime from '../../Runtime.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
|
+
|
|
15
|
+
export {
|
|
16
|
+
HttpEvent,
|
|
17
|
+
Observer,
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* ---------------------------
|
|
22
|
+
* The Runtime Initializer
|
|
23
|
+
* ---------------------------
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
export default class Runtime extends _Runtime {
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Runtime
|
|
30
|
+
*
|
|
31
|
+
* @param Object cx
|
|
32
|
+
* @param Function applicationInstance
|
|
33
|
+
*
|
|
34
|
+
* @return void
|
|
35
|
+
*/
|
|
36
|
+
constructor(cx, applicationInstance) {
|
|
37
|
+
super(cx, applicationInstance);
|
|
38
|
+
// ---------------
|
|
39
|
+
this.mockSessionStore = {};
|
|
40
|
+
// --------------
|
|
41
|
+
// ONINSTALL
|
|
42
|
+
self.addEventListener('install', evt => {
|
|
43
|
+
if (this.cx.params.skip_waiting) { self.skipWaiting(); }
|
|
44
|
+
// Manage CACHE
|
|
45
|
+
if (this.cx.params.cache_name && (this.cx.params.cache_only_urls || []).length) {
|
|
46
|
+
// Add files to cache
|
|
47
|
+
evt.waitUntil( self.caches.open(this.cx.params.cache_name).then(async cache => {
|
|
48
|
+
if (this.cx.logger) { this.cx.logger.log('[ServiceWorker] Pre-caching resources.'); }
|
|
49
|
+
for (const urls of [ 'cache_first_urls', 'cache_only_urls' ]) {
|
|
50
|
+
const _urls = (this.cx.params[urls] || []).map(c => c.trim()).filter(c => c && !pattern(c, self.origin).isPattern());
|
|
51
|
+
await cache.addAll(_urls);
|
|
52
|
+
}
|
|
53
|
+
}) );
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
// -------------
|
|
58
|
+
// ONACTIVATE
|
|
59
|
+
self.addEventListener('activate', evt => {
|
|
60
|
+
evt.waitUntil( new Promise(async resolve => {
|
|
61
|
+
if (this.cx.params.skip_waiting) { await self.clients.claim(); }
|
|
62
|
+
// Manage CACHE
|
|
63
|
+
if (this.cx.params.cache_name) {
|
|
64
|
+
// Clear outdated CACHES
|
|
65
|
+
await self.caches.keys().then(keyList => {
|
|
66
|
+
return Promise.all(keyList.map(key => {
|
|
67
|
+
if (key !== this.cx.params.cache_name && key !== this.cx.params.cache_name + '_json') {
|
|
68
|
+
if (this.cx.logger) { this.cx.logger.log('[ServiceWorker] Removing old cache:', key); }
|
|
69
|
+
return self.caches.delete(key);
|
|
70
|
+
}
|
|
71
|
+
}));
|
|
72
|
+
})
|
|
73
|
+
}
|
|
74
|
+
resolve();
|
|
75
|
+
}) );
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
// ---------------
|
|
79
|
+
Observer.set(this, 'location', {});
|
|
80
|
+
Observer.set(this, 'network', {});
|
|
81
|
+
|
|
82
|
+
// -------------
|
|
83
|
+
// ONFETCH
|
|
84
|
+
self.addEventListener('fetch', event => {
|
|
85
|
+
// URL schemes that might arrive here but not supported; e.g.: chrome-extension://
|
|
86
|
+
if (!event.request.url.startsWith('http')) return;
|
|
87
|
+
event.respondWith((async evt => {
|
|
88
|
+
let requestingClient = await self.clients.get(evt.clientId);
|
|
89
|
+
this.workport.setCurrentClient(requestingClient);
|
|
90
|
+
const [ url, requestInit ] = await xRequest.rip(evt.request);
|
|
91
|
+
// Now, the following is key:
|
|
92
|
+
// The browser likes to use "force-cache" for "navigate" requests, when, e.g: re-entering your site with the back button
|
|
93
|
+
// Problem here, force-cache forces out JSON not HTML as per webflo's design.
|
|
94
|
+
// So, we detect this scenerio and avoid it.
|
|
95
|
+
if (requestInit.cache === 'force-cache'/* && evt.request.mode === 'navigate' - even webflo client init call also comes with that... needs investigation */) {
|
|
96
|
+
requestInit.cache = 'default';
|
|
97
|
+
}
|
|
98
|
+
return this.go(url, requestInit, { event: evt });
|
|
99
|
+
})(event));
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
// -------------
|
|
103
|
+
// Workport
|
|
104
|
+
const workport = new Workport();
|
|
105
|
+
Observer.set(this, 'workport', workport);
|
|
106
|
+
|
|
107
|
+
// -------------
|
|
108
|
+
// Initialize
|
|
109
|
+
(async () => {
|
|
110
|
+
if (!this.app.init) return;
|
|
111
|
+
const request = this.generateRequest('/');
|
|
112
|
+
const httpEvent = new HttpEvent(request, { navigationType: 'init' }, (id = null, persistent = false) => this.getSession(httpEvent, id, persistent));
|
|
113
|
+
await this.app.init(httpEvent, ( ...args ) => this.remoteFetch( ...args ));
|
|
114
|
+
})();
|
|
115
|
+
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Performs a request.
|
|
120
|
+
*
|
|
121
|
+
* @param object|string url
|
|
122
|
+
* @param object|Request init
|
|
123
|
+
* @param object detail
|
|
124
|
+
*
|
|
125
|
+
* @return Response
|
|
126
|
+
*/
|
|
127
|
+
async go(url, init = {}, detail = {}) {
|
|
128
|
+
// ------------
|
|
129
|
+
url = typeof url === 'string' ? new URL(url, self.location.origin) : url;
|
|
130
|
+
if (!(init instanceof Request) && !init.referrer) {
|
|
131
|
+
init = { referrer: this.location.href, ...init };
|
|
132
|
+
}
|
|
133
|
+
// ------------
|
|
134
|
+
// The request object
|
|
135
|
+
const request = this.generateRequest(url.href, init);
|
|
136
|
+
if (detail.event) { Object.defineProperty(detail.event, 'request', { value: request }); }
|
|
137
|
+
// The navigation event
|
|
138
|
+
const httpEvent = new HttpEvent(request, detail, (id = null, persistent = false) => this.getSession(httpEvent, id, persistent));
|
|
139
|
+
httpEvent.port.listen(message => {
|
|
140
|
+
if (message.$type === 'handler:hints' && message.session) {
|
|
141
|
+
// TODO: Sync session data from client
|
|
142
|
+
return Promise.resolve();
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
// Response
|
|
146
|
+
let response;
|
|
147
|
+
if (httpEvent.request.url.startsWith(self.origin)/* && httpEvent.request.mode === 'navigate'*/) {
|
|
148
|
+
response = await this.app.handle(httpEvent, ( ...args ) => this.remoteFetch( ...args ));
|
|
149
|
+
} else {
|
|
150
|
+
response = await this.remoteFetch(httpEvent.request);
|
|
151
|
+
}
|
|
152
|
+
const finalResponse = await this.handleResponse(httpEvent, response);
|
|
153
|
+
// Return value
|
|
154
|
+
return finalResponse;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// Generates request object
|
|
158
|
+
generateRequest(href, init = {}) {
|
|
159
|
+
const request = new xRequest(href, init);
|
|
160
|
+
return request;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// Generates session object
|
|
164
|
+
getSession(e, id = null, persistent = false) {
|
|
165
|
+
return {
|
|
166
|
+
get: () => this.mockSessionStore,
|
|
167
|
+
set: value => { this.mockSessionStore = value },
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// Initiates remote fetch and sets the status
|
|
172
|
+
remoteFetch(request, ...args) {
|
|
173
|
+
if (arguments.length > 1) {
|
|
174
|
+
request = this.generateRequest(request, ...args);
|
|
175
|
+
}
|
|
176
|
+
const matchUrl = (patterns, url) => _any((patterns || []).map(p => p.trim()).filter(p => p), p => pattern(p, self.origin).test(url));
|
|
177
|
+
const execFetch = () => {
|
|
178
|
+
// cache_only_urls
|
|
179
|
+
if (matchUrl(this.cx.params.cache_only_urls, request.url)) {
|
|
180
|
+
Observer.set(this.network, 'strategy', 'cache-only');
|
|
181
|
+
return this.cacheFetch(request, { networkFallback: false, cacheRefresh: false });
|
|
182
|
+
}
|
|
183
|
+
// network_only_urls
|
|
184
|
+
if (matchUrl(this.cx.params.network_only_urls, request.url)) {
|
|
185
|
+
Observer.set(this.network, 'strategy', 'network-only');
|
|
186
|
+
return this.networkFetch(request, { cacheFallback: false, cacheRefresh: false });
|
|
187
|
+
}
|
|
188
|
+
// cache_first_urls
|
|
189
|
+
if (matchUrl(this.cx.params.cache_first_urls, request.url)) {
|
|
190
|
+
Observer.set(this.network, 'strategy', 'cache-first');
|
|
191
|
+
return this.cacheFetch(request, { networkFallback: true, cacheRefresh: true });
|
|
192
|
+
}
|
|
193
|
+
// network_first_urls
|
|
194
|
+
if (matchUrl(this.cx.params.network_first_urls, request.url) || !this.cx.params.default_fetching_strategy) {
|
|
195
|
+
Observer.set(this.network, 'strategy', 'network-first');
|
|
196
|
+
return this.networkFetch(request, { cacheFallback: true, cacheRefresh: true });
|
|
197
|
+
}
|
|
198
|
+
// Default strategy
|
|
199
|
+
Observer.set(this.network, 'strategy', this.cx.params.default_fetching_strategy);
|
|
200
|
+
switch (this.cx.params.default_fetching_strategy) {
|
|
201
|
+
case 'cache-only': return this.cacheFetch(request, { networkFallback: false, cacheRefresh: false });
|
|
202
|
+
case 'network-only': return this.networkFetch(request, { cacheFallback: false, cacheRefresh: false });
|
|
203
|
+
case 'cache-first': return this.cacheFetch(request, { networkFallback: true, cacheRefresh: true });
|
|
204
|
+
case 'network-first': return this.networkFetch(request, { cacheFallback: true, cacheRefresh: true });
|
|
205
|
+
}
|
|
206
|
+
};
|
|
207
|
+
let response = execFetch(request);
|
|
208
|
+
// This catch() is NOT intended to handle failure of the fetch
|
|
209
|
+
response.catch(e => Observer.set(this.network, 'error', e.message));
|
|
210
|
+
// Return xResponse
|
|
211
|
+
return response.then(_response => xResponse.compat(_response));
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
// Caching strategy: network_first
|
|
215
|
+
networkFetch(request, params = {}) {
|
|
216
|
+
if (!params.cacheFallback) {
|
|
217
|
+
Observer.set(this.network, 'remote', true);
|
|
218
|
+
return xfetch(request);
|
|
219
|
+
}
|
|
220
|
+
return xfetch(request).then(response => {
|
|
221
|
+
if (params.cacheRefresh) this.refreshCache(request, response);
|
|
222
|
+
Observer.set(this.network, 'remote', true);
|
|
223
|
+
return response;
|
|
224
|
+
}).catch(() => this.getRequestCache(request).then(cache => {
|
|
225
|
+
Observer.set(this.network, 'cache', true);
|
|
226
|
+
return cache.match(request);
|
|
227
|
+
}));
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// Caching strategy: cache_first
|
|
231
|
+
cacheFetch(request, params = {}) {
|
|
232
|
+
return this.getRequestCache(request).then(cache => cache.match(request).then(response => {
|
|
233
|
+
// Nothing cache, use network
|
|
234
|
+
if (!response && params.networkFallback) return this.networkFetch(request, { ...params, cacheFallback: false });
|
|
235
|
+
// Note: fetch, but for refreshing purposes only... not the returned response
|
|
236
|
+
if (response && params.cacheRefresh) this.networkFetch(request, { ...params, justRefreshing: true });
|
|
237
|
+
Observer.set(this.network, 'cache', true);
|
|
238
|
+
return response;
|
|
239
|
+
}));
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// Caches response
|
|
243
|
+
refreshCache(request, response) {
|
|
244
|
+
// Check if we received a valid response
|
|
245
|
+
if (request.method !== 'GET' || !response || response.status !== 200 || (response.type !== 'basic' && response.type !== 'cors')) {
|
|
246
|
+
return response;
|
|
247
|
+
}
|
|
248
|
+
// IMPORTANT: Clone the response. A response is a stream
|
|
249
|
+
// and because we want the browser to consume the response
|
|
250
|
+
// as well as the cache consuming the response, we need
|
|
251
|
+
// to clone it so we have two streams.
|
|
252
|
+
var responseToCache = response.clone();
|
|
253
|
+
this.getRequestCache(request).then(cache => {
|
|
254
|
+
Observer.set(this.network, 'cacheRefresh', true);
|
|
255
|
+
cache.put(request, responseToCache);
|
|
256
|
+
});
|
|
257
|
+
return response;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
// Returns either the regular cache or a json-specific cache
|
|
261
|
+
getRequestCache(request) {
|
|
262
|
+
let cacheName = request.headers.get('Accept') === 'application/json'
|
|
263
|
+
? this.cx.params.cache_name + '_json'
|
|
264
|
+
: this.cx.params.cache_name;
|
|
265
|
+
return self.caches.open(cacheName);
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
// Handles response object
|
|
269
|
+
handleResponse(e, response) {
|
|
270
|
+
if (!response && response !== 0) { response = new xResponse(null, { status: 404 }); }
|
|
271
|
+
else if (!(response instanceof xResponse)) { response = xResponse.compat(response); }
|
|
272
|
+
return response;
|
|
273
|
+
}
|
|
274
|
+
|
|
269
275
|
}
|