@webqit/webflo 0.11.39 → 0.11.40

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 (38) hide show
  1. package/package.json +2 -3
  2. package/src/Context.js +3 -3
  3. package/src/config-pi/deployment/Layout.js +0 -1
  4. package/src/runtime-pi/{RuntimeClient.js → Application.js} +2 -2
  5. package/src/runtime-pi/HttpEvent.js +106 -0
  6. package/src/runtime-pi/Router.js +2 -3
  7. package/src/runtime-pi/Runtime.js +3 -3
  8. package/src/runtime-pi/client/{RuntimeClient.js → Application.js} +12 -4
  9. package/src/runtime-pi/client/Router.js +4 -3
  10. package/src/runtime-pi/client/Runtime.js +37 -59
  11. package/src/runtime-pi/client/Url.js +3 -3
  12. package/src/runtime-pi/client/Workport.js +1 -1
  13. package/src/runtime-pi/client/{Storage.js → createStorage.js} +3 -3
  14. package/src/runtime-pi/client/generate.js +5 -3
  15. package/src/runtime-pi/client/index.js +4 -4
  16. package/src/runtime-pi/client/worker/{WorkerClient.js → Application.js} +12 -8
  17. package/src/runtime-pi/client/worker/{Worker.js → Runtime.js} +25 -27
  18. package/src/runtime-pi/client/worker/index.js +6 -6
  19. package/src/runtime-pi/server/{RuntimeClient.js → Application.js} +8 -8
  20. package/src/runtime-pi/server/Router.js +3 -2
  21. package/src/runtime-pi/server/Runtime.js +41 -98
  22. package/src/runtime-pi/server/index.js +4 -4
  23. package/src/runtime-pi/util-http.js +70 -0
  24. package/src/runtime-pi/util-url.js +147 -0
  25. package/src/runtime-pi/xFormData.js +10 -46
  26. package/src/runtime-pi/xHeaders.js +2 -11
  27. package/src/runtime-pi/xRequest.js +29 -42
  28. package/src/runtime-pi/xRequestHeaders.js +20 -23
  29. package/src/runtime-pi/xResponse.js +19 -15
  30. package/src/runtime-pi/xResponseHeaders.js +41 -43
  31. package/src/runtime-pi/xURL.js +71 -77
  32. package/src/runtime-pi/xfetch.js +15 -6
  33. package/src/runtime-pi/xxHttpMessage.js +102 -0
  34. package/src/runtime-pi/client/whatwag.js +0 -27
  35. package/src/runtime-pi/server/whatwag.js +0 -35
  36. package/src/runtime-pi/util.js +0 -162
  37. package/src/runtime-pi/xHttpEvent.js +0 -101
  38. package/src/runtime-pi/xHttpMessage.js +0 -171
package/package.json CHANGED
@@ -12,7 +12,7 @@
12
12
  "vanila-javascript"
13
13
  ],
14
14
  "homepage": "https://webqit.io/tooling/webflo",
15
- "version": "0.11.39",
15
+ "version": "0.11.40",
16
16
  "license": "MIT",
17
17
  "repository": {
18
18
  "type": "git",
@@ -37,7 +37,7 @@
37
37
  "dependencies": {
38
38
  "@octokit/webhooks": "^7.15.1",
39
39
  "@webqit/backpack": "^0.1.6",
40
- "@webqit/oohtml-ssr": "^1.1.0",
40
+ "@webqit/oohtml-ssr": "^1.1.5",
41
41
  "@webqit/util": "^0.8.9",
42
42
  "client-sessions": "^0.8.0",
43
43
  "esbuild": "^0.14.38",
@@ -45,7 +45,6 @@
45
45
  "formdata-node": "^4.3.0",
46
46
  "formidable": "^2.0.1",
47
47
  "mime-types": "^2.1.33",
48
- "node-fetch": "^2.6.1",
49
48
  "simple-git": "^2.20.1",
50
49
  "stream-slice": "^0.1.2",
51
50
  "urlpattern-polyfill": "^4.0.3"
package/src/Context.js CHANGED
@@ -56,7 +56,7 @@ export default class Context {
56
56
  }
57
57
 
58
58
  set flags(value) {
59
- this.dict.flags = value;
59
+ Object.defineProperty(this.dict, 'flags', { value } );
60
60
  }
61
61
 
62
62
  // layout
@@ -65,7 +65,7 @@ export default class Context {
65
65
  }
66
66
 
67
67
  set layout(value) {
68
- this.dict.layout = value;
68
+ Object.defineProperty(this.dict, 'layout', { value } );
69
69
  }
70
70
 
71
71
  // logger
@@ -74,7 +74,7 @@ export default class Context {
74
74
  }
75
75
 
76
76
  set logger(value) {
77
- this.dict.logger = value;
77
+ Object.defineProperty(this.dict, 'logger', { value } );
78
78
  }
79
79
 
80
80
  }
@@ -19,7 +19,6 @@ export default class Layout extends Dotfile {
19
19
  // Defaults merger
20
20
  withDefaults(config) {
21
21
  return this.merge({
22
- ROOT: process.cwd(),
23
22
  PUBLIC_DIR: './public',
24
23
  SERVER_DIR: './server',
25
24
  CLIENT_DIR: './client',
@@ -1,11 +1,11 @@
1
1
 
2
2
  /**
3
3
  * ---------------------------
4
- * The base RuntimeClient class
4
+ * The base Application class
5
5
  * ---------------------------
6
6
  */
7
7
 
8
- export default class RuntimeClient {
8
+ export default class Application {
9
9
 
10
10
  constructor(cx) {
11
11
  this.cx = cx;
@@ -0,0 +1,106 @@
1
+
2
+ /**
3
+ * @imports
4
+ */
5
+ import { _isEmpty } from '@webqit/util/js/index.js';
6
+ import xRequest from "./xRequest.js";
7
+ import xResponse from "./xResponse.js";
8
+ import xURL from "./xURL.js";
9
+
10
+ /**
11
+ * The xHttpEvent Mixin
12
+ */
13
+ export default class HttpEvent {
14
+
15
+ /**
16
+ * Initializes a new HttpEvent instance.
17
+ *
18
+ * @param Request _request
19
+ * @param Object _detail
20
+ * @param Function _sessionFactory
21
+ * @param Function _storageFactory
22
+ */
23
+ constructor(_request, _detail, _sessionFactory, _storageFactory) {
24
+ this._request = _request;
25
+ this._detail = _detail || {};
26
+ this._sessionFactory = _sessionFactory;
27
+ this._storageFactory = _storageFactory;
28
+ // -------
29
+ this.Request = xRequest;
30
+ this.Response = xResponse;
31
+ this.URL = xURL;
32
+ // -------
33
+ this.port = {
34
+ listeners: [],
35
+ post(message) {
36
+ const promises = this.listeners.map(listener => listener(message))
37
+ .filter(returnValue => returnValue instanceof Promise);
38
+ if (process.length) return Promise.all(promises);
39
+ },
40
+ listen(listener) { this.listeners.push(listener); },
41
+ }
42
+ }
43
+
44
+ // url
45
+ get url() {
46
+ if (!this._url) {
47
+ this._url = new this.URL(this._request.url);
48
+ }
49
+ return this._url;
50
+ }
51
+
52
+ // request
53
+ get request() {
54
+ return this._request;
55
+ }
56
+
57
+ // detail
58
+ get detail() {
59
+ return this._detail;
60
+ }
61
+
62
+ // Session
63
+ get session() {
64
+ if (!this._session) {
65
+ this._session = this.sessionFactory();
66
+ }
67
+ return this._session;
68
+ }
69
+
70
+ // Storage
71
+ get storage() {
72
+ if (!this._storage) {
73
+ this._storage = this.storageFactory();
74
+ }
75
+ return this._storage;
76
+ }
77
+
78
+ // Session factory
79
+ sessionFactory(...args) {
80
+ return this._sessionFactory(...args);
81
+ }
82
+
83
+ // storage factory
84
+ storageFactory(...args) {
85
+ return this._storageFactory(...args);
86
+ }
87
+
88
+ // Redirect Response
89
+ redirect(url, code = 302) {
90
+ return new this.Response(null, { status: code, headers: { Location: url } });
91
+ }
92
+
93
+ // "with()"
94
+ with(url, init = {}) {
95
+ let request;
96
+ if (url instanceof Request) {
97
+ request = !_isEmpty(init) ? new xRequest(url, init) : url;
98
+ } else {
99
+ url = new this.URL(url, this.url.origin);
100
+ request = new xRequest(url, this._request);
101
+ request = new xRequest(request, { ...init, referrer: this.request.url });
102
+ }
103
+ return new HttpEvent(request, this.detail, this._sessionFactory, this.storageFactory);
104
+ }
105
+
106
+ }
@@ -58,7 +58,7 @@ export default class Router {
58
58
  if (thisTick.exports) {
59
59
  // Broadcast any hints exported by handler
60
60
  if (thisTick.exports.hints) { await event.port.post({ ...thisTick.exports.hints, $type: 'handler:hints' }); }
61
- const methods = _arrFrom(thisTick.method);
61
+ const methods = _arrFrom(thisTick.method).map(m => m === 'default' ? m : m.toUpperCase());
62
62
  const handler = _isFunction(thisTick.exports) && methods.includes('default') ? thisTick.exports : methods.reduce((_handler, name) => _handler || thisTick.exports[name], null);
63
63
  if (handler) {
64
64
  // -------------
@@ -74,7 +74,7 @@ export default class Router {
74
74
  } else if (!_isString(_url)) {
75
75
  throw new Error('Router redirect url must be a string!');
76
76
  }
77
- var newDestination = _url.startsWith('/') ? _url : $this.pathJoin(`/${thisTick.trail.join('/')}`, _url);
77
+ let newDestination = _url.startsWith('/') ? _url : $this.pathJoin(`/${thisTick.trail.join('/')}`, _url);
78
78
  if (newDestination.startsWith('../')) {
79
79
  throw new Error('Router redirect cannot traverse beyond the routing directory! (' + _url + ' >> ' + newDestination + ')');
80
80
  }
@@ -89,7 +89,6 @@ export default class Router {
89
89
  } else {
90
90
  nextTick.event = thisTick.event.with(newDestination, requestInit);
91
91
  }
92
-
93
92
  nextTick.source = thisTick.destination.join('/');
94
93
  nextTick.destination = newDestination.split('?').shift().split('/').map(a => a.trim()).filter(a => a);
95
94
  nextTick.trail = _args[1].startsWith('/') ? [] : thisTick.trail.reduce((_commonRoot, _seg, i) => _commonRoot.length === i && _seg === nextTick.destination[i] ? _commonRoot.concat(_seg) : _commonRoot, []);
@@ -12,10 +12,10 @@ import { _isFunction } from "@webqit/util/js/index.js";
12
12
  */
13
13
 
14
14
  export default class Runtime {
15
- constructor(cx, client) {
15
+ constructor(cx, applicationInstance) {
16
16
  this.cx = cx;
17
17
  this.cx.runtime = this;
18
- this.client = _isFunction(client) ? client(this.cx) : client;
19
- if (!this.client || !this.client.handle) throw new Error(`Application instance must define a ".handle()" method.`);
18
+ this.app = _isFunction(applicationInstance) ? applicationInstance(this.cx) : applicationInstance;
19
+ if (!this.app || !this.app.handle) throw new Error(`Application instance must define a ".handle()" method.`);
20
20
  }
21
21
  }
@@ -3,9 +3,9 @@
3
3
  * @imports
4
4
  */
5
5
  import Router from './Router.js';
6
- import _RuntimeClient from '../RuntimeClient.js';
6
+ import _Application from '../Application.js';
7
7
 
8
- export default class RuntimeClient extends _RuntimeClient {
8
+ export default class Application extends _Application {
9
9
 
10
10
  // Returns router class
11
11
  get Router() {
@@ -27,8 +27,16 @@ export default class RuntimeClient extends _RuntimeClient {
27
27
  // --------
28
28
  // ROUTE FOR DATA
29
29
  // --------
30
- const httpMethodName = httpEvent.request.method.toUpperCase();
31
- return router.route([httpMethodName, 'default'], httpEvent, {}, async event => {
30
+ return router.route([httpEvent.request.method, 'default'], httpEvent, { ...( document.state?.data || {} ) }, 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
+ if (event.request.body && !event.request.headers.has('Content-Type')) {
37
+ event.request.headers.set('Content-Type', 'application/json');
38
+ }
39
+ }
32
40
  return remoteFetch(event.request);
33
41
  }, remoteFetch);
34
42
  };
@@ -2,7 +2,7 @@
2
2
  /**
3
3
  * @imports
4
4
  */
5
- import { path as Path } from '../util.js';
5
+ import { path as Path } from '../util-url.js';
6
6
  import _Router from '../Router.js';
7
7
 
8
8
  /**
@@ -14,6 +14,7 @@ import _Router from '../Router.js';
14
14
  export default class Router extends _Router {
15
15
 
16
16
  async readTick(thisTick) {
17
+ thisTick = { ...thisTick };
17
18
  var routeTree = this.cx.layout;
18
19
  var routePaths = Object.keys(this.cx.layout);
19
20
  if (thisTick.trail) {
@@ -25,8 +26,8 @@ export default class Router extends _Router {
25
26
  routePaths.filter(p => p.startsWith(`${_currentPath}/`)).length ? { seg: _seg, dirExists: true } : _segmentOnFile
26
27
  );
27
28
  }, { seg: null });
28
- thisTick.trail.push(thisTick.currentSegment);
29
- thisTick.trailOnFile.push(thisTick.currentSegmentOnFile.seg);
29
+ thisTick.trail = thisTick.trail.concat(thisTick.currentSegment);
30
+ thisTick.trailOnFile = thisTick.trailOnFile.concat(thisTick.currentSegmentOnFile.seg);
30
31
  thisTick.exports = routeTree[thisTick.currentSegmentOnFile.index];
31
32
  } else {
32
33
  thisTick.trail = [];
@@ -4,40 +4,17 @@
4
4
  */
5
5
  import { _before, _toTitle } from '@webqit/util/str/index.js';
6
6
  import { Observer } from '@webqit/oohtml-ssr/apis.js';
7
- import Storage from './Storage.js';
7
+ import createStorage from './createStorage.js';
8
8
  import Url from './Url.js';
9
- import { wwwFormUnserialize, wwwFormSet, wwwFormSerialize } from '../util.js';
10
- import * as whatwag from './whatwag.js';
11
- import xURL from '../xURL.js';
12
- import xFormData from "../xFormData.js";
13
- import xRequestHeaders from "../xRequestHeaders.js";
14
- import xResponseHeaders from "../xResponseHeaders.js";
9
+ import Workport from './Workport.js';
15
10
  import xRequest from "../xRequest.js";
16
11
  import xResponse from "../xResponse.js";
17
12
  import xfetch from '../xfetch.js';
18
- import xHttpEvent from '../xHttpEvent.js';
19
- import Workport from './Workport.js';
13
+ import HttpEvent from '../HttpEvent.js';
20
14
  import _Runtime from '../Runtime.js';
21
-
22
- const URL = xURL(whatwag.URL);
23
- const FormData = xFormData(whatwag.FormData);
24
- const ReadableStream = whatwag.ReadableStream;
25
- const RequestHeaders = xRequestHeaders(whatwag.Headers);
26
- const ResponseHeaders = xResponseHeaders(whatwag.Headers);
27
- const Request = xRequest(whatwag.Request, RequestHeaders, FormData, whatwag.Blob);
28
- const Response = xResponse(whatwag.Response, ResponseHeaders, FormData, whatwag.Blob);
29
- const fetch = xfetch(whatwag.fetch, Request);
30
- const HttpEvent = xHttpEvent(Request, Response, URL);
15
+ import { params } from '../util-url.js';
31
16
 
32
17
  export {
33
- URL,
34
- FormData,
35
- ReadableStream,
36
- RequestHeaders,
37
- ResponseHeaders,
38
- Request,
39
- Response,
40
- fetch,
41
18
  HttpEvent,
42
19
  Observer,
43
20
  }
@@ -48,12 +25,12 @@ export default class Runtime extends _Runtime {
48
25
  * Runtime
49
26
  *
50
27
  * @param Object cx
51
- * @param Function clientCallback
28
+ * @param Function applicationInstance
52
29
  *
53
30
  * @return void
54
31
  */
55
- constructor(cx, clientCallback) {
56
- super(cx, clientCallback);
32
+ constructor(cx, applicationInstance) {
33
+ super(cx, applicationInstance);
57
34
  // -----------------------
58
35
  // Initialize location
59
36
  Observer.set(this, 'location', new Url(window.document.location));
@@ -124,11 +101,11 @@ export default class Runtime extends _Runtime {
124
101
  formData.set(submitter.name, submitter.value);
125
102
  }
126
103
  if (submitParams.method.toUpperCase() === 'GET') {
127
- var query = wwwFormUnserialize(actionEl.search);
104
+ var query = params.parse(actionEl.search);
128
105
  Array.from(formData.entries()).forEach(_entry => {
129
- wwwFormSet(query, _entry[0], _entry[1], false);
106
+ params.set(query, _entry[0], _entry[1]);
130
107
  });
131
- actionEl.search = wwwFormSerialize(query);
108
+ actionEl.search = params.stringify(query);
132
109
  formData = null;
133
110
  }
134
111
  this.go(Url.copy(actionEl), {
@@ -150,7 +127,8 @@ export default class Runtime extends _Runtime {
150
127
  // -----------------------
151
128
  // Service Worker && COMM
152
129
  if (this.cx.params.service_worker_support) {
153
- const workport = new Workport(this.cx.params.worker_filename, { scope: this.cx.params.worker_scope, startMessages: true });
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 });
154
132
  Observer.set(this, 'workport', workport);
155
133
  }
156
134
 
@@ -158,10 +136,10 @@ export default class Runtime extends _Runtime {
158
136
  // Initialize and Hydration
159
137
  (async () => {
160
138
  let shouldHydrate;
161
- if (this.client.init) {
139
+ if (this.app.init) {
162
140
  const request = this.generateRequest(this.location);
163
141
  const httpEvent = new HttpEvent(request, { srcType: 'initialization' }, (id = null, persistent = false) => this.getSession(httpEvent, id, persistent));
164
- shouldHydrate = await this.client.init(httpEvent, ( ...args ) => this.remoteFetch( ...args ));
142
+ shouldHydrate = await this.app.init(httpEvent, ( ...args ) => this.remoteFetch( ...args ));
165
143
  }
166
144
  if (shouldHydrate !== false) {
167
145
  this.go(this.location, {}, { srcType: 'hydration' });
@@ -185,7 +163,7 @@ export default class Runtime extends _Runtime {
185
163
 
186
164
  // Check is-spa-route
187
165
  isSpaRoute(url, e = undefined) {
188
- url = typeof url === 'string' ? new whatwag.URL(url) : url;
166
+ url = typeof url === 'string' ? new URL(url, this.location.origin) : url;
189
167
  if (url.origin && url.origin !== this.location.origin) return false;
190
168
  if (e && (e.metaKey || e.altKey || e.ctrlKey || e.shiftKey)) return false;
191
169
  if (!this.cx.params.routing) return true;
@@ -202,7 +180,7 @@ export default class Runtime extends _Runtime {
202
180
 
203
181
  // Generates request object
204
182
  generateRequest(href, init = {}) {
205
- return new Request(href, {
183
+ return new xRequest(href, {
206
184
  signal: this._abortController && this._abortController.signal,
207
185
  ...init,
208
186
  headers: {
@@ -216,8 +194,8 @@ export default class Runtime extends _Runtime {
216
194
  }
217
195
 
218
196
  // Generates session object
219
- getSession(e, id = null, persistent = false) {
220
- return Storage(id, persistent);
197
+ createStorage(e, id = null, persistent = false) {
198
+ return createStorage(id, persistent);
221
199
  }
222
200
 
223
201
  /**
@@ -230,13 +208,13 @@ export default class Runtime extends _Runtime {
230
208
  * @return Response
231
209
  */
232
210
  async go(url, init = {}, detail = {}) {
233
- url = typeof url === 'string' ? new whatwag.URL(url) : url;
211
+ url = typeof url === 'string' ? new URL(url, this.location.origin) : url;
234
212
  init = { referrer: this.location.href, ...init };
235
213
  // ------------
236
214
  // Put his forward before instantiating a request and aborting previous
237
215
  // Same-page hash-links clicks on chrome recurse here from histroy popstate
238
- if (detail.srcType !== 'hydration' && (_before(url.href, '#') === _before(init.referrer, '#') && (init.method || 'GET').toUpperCase() === 'GET')) {
239
- return new Response(null, { status: 304 }); // Not Modified
216
+ if (![ 'hydration', 'rdr' ].includes(detail.srcType) && (_before(url.href, '#') === _before(init.referrer, '#') && (init.method || 'GET').toUpperCase() === 'GET')) {
217
+ return new xResponse(null, { status: 304 }); // Not Modified
240
218
  }
241
219
  // ------------
242
220
  if (this._abortController) {
@@ -257,23 +235,21 @@ export default class Runtime extends _Runtime {
257
235
  // Run
258
236
  // ------------
259
237
  const request = this.generateRequest(url.href, init);
260
- const httpEvent = new HttpEvent(request, detail, (id = null, persistent = false) => this.getSession(httpEvent, id, persistent));
238
+ const httpEvent = new HttpEvent(request, detail, (id = null, persistent = false) => this.createStorage(httpEvent, id, persistent));
261
239
  let response, finalResponse;
262
240
  try {
263
241
  // ------------
264
242
  // Response
265
243
  // ------------
266
- response = await this.client.handle(httpEvent, ( ...args ) => this.remoteFetch( ...args ));
244
+ response = await this.app.handle(httpEvent, ( ...args ) => this.remoteFetch( ...args ));
267
245
  finalResponse = this.handleResponse(httpEvent, response);
268
246
  // ------------
269
247
  // Address bar
270
248
  // ------------
271
- if (response.redirected) {
272
- Observer.set(this.location, { href: response.url }, { detail: { redirected: true }, });
273
- Observer.set(this.network, 'requesting', null);
249
+ if (response && response.redirected) {
250
+ Observer.set(this.location, { href: response.url }, { detail: { redirected: true, ...detail }, });
274
251
  } else if (![302, 301].includes(finalResponse.status)) {
275
- Observer.set(this.location, Url.copy(url)/* copy() is important */);
276
- Observer.set(this.network, 'requesting', null);
252
+ Observer.set(this.location, Url.copy(url)/* copy() is important */, { detail });
277
253
  }
278
254
  // ------------
279
255
  // States
@@ -286,19 +262,19 @@ export default class Runtime extends _Runtime {
286
262
  // Rendering
287
263
  // ------------
288
264
  if (finalResponse.ok && (finalResponse.headers.contentType === 'application/json' || finalResponse.headers.contentType.startsWith('multipart/form-data'))) {
289
- this.client.render && await this.client.render(httpEvent, finalResponse);
265
+ this.app.render && await this.app.render(httpEvent, finalResponse);
290
266
  } else if (!finalResponse.ok) {
291
267
  if ([404, 500].includes(finalResponse.status)) {
292
268
  Observer.set(this.network, 'error', new Error(finalResponse.statusText, { cause: finalResponse.status }));
293
269
  }
294
270
  if (!finalResponse.headers.get('Location')) {
295
- this.client.unrender && await this.client.unrender(httpEvent);
271
+ this.app.unrender && await this.app.unrender(httpEvent);
296
272
  }
297
273
  }
298
274
  } catch(e) {
299
275
  console.error(e);
300
276
  Observer.set(this.network, 'error', { ...e, retry: () => this.go(url, init = {}, detail) });
301
- finalResponse = new Response(null, { status: 500, statusText: e.message });
277
+ finalResponse = new xResponse(null, { status: 500, statusText: e.message });
302
278
  }
303
279
  // ------------
304
280
  // Return value
@@ -310,35 +286,37 @@ export default class Runtime extends _Runtime {
310
286
  let href = request;
311
287
  if (request instanceof Request) {
312
288
  href = request.url;
313
- } else if (request instanceof whatwag.URL) {
289
+ } else if (request instanceof URL) {
314
290
  href = request.href;
315
291
  }
316
292
  Observer.set(this.network, 'remote', href);
317
- let _response = fetch(request, ...args);
293
+ let _response = xfetch(request, ...args);
318
294
  // This catch() is NOT intended to handle failure of the fetch
319
295
  _response.catch(e => Observer.set(this.network, 'error', e));
320
296
  // Return xResponse
321
297
  return _response.then(async response => {
322
298
  // Stop loading status
323
299
  Observer.set(this.network, 'remote', null);
324
- return new Response(response);
300
+ return new xResponse(response);
325
301
  });
326
302
  }
327
303
 
328
304
  // Handles response object
329
305
  handleResponse(e, response) {
330
- if (!(response instanceof Response)) { response = new Response(response); }
306
+ if (typeof response === 'undefined') { response = new xResponse(undefined, { status: 404 }); }
307
+ else if (!(response instanceof xResponse)) { response = new xResponse(response); }
308
+ Observer.set(this.network, 'requesting', null);
309
+ Observer.set(this.network, 'redirecting', null);
331
310
  if (!response.redirected) {
332
311
  let location = response.headers.get('Location');
333
312
  if (location) {
334
313
  let xActualRedirectCode = parseInt(response.headers.get('X-Redirect-Code'));
314
+ Observer.set(this.network, 'redirecting', location);
335
315
  if (xActualRedirectCode && response.status === this._xRedirectCode) {
336
316
  response.attrs.status = xActualRedirectCode;
337
- Observer.set(this.network, 'redirecting', location);
338
317
  window.location = location;
339
318
  } else if ([302,301].includes(response.status)) {
340
319
  if (!this.isSpaRoute(location)) {
341
- Observer.set(this.network, 'redirecting', location);
342
320
  window.location = location;
343
321
  } else {
344
322
  this.go(location, {}, { srcType: 'rdr' });
@@ -4,8 +4,8 @@
4
4
  */
5
5
  import { _with } from '@webqit/util/obj/index.js';
6
6
  import { _isArray, _isObject, _isTypeObject, _isString, _isEmpty } from '@webqit/util/js/index.js';
7
- import { wwwFormUnserialize, wwwFormSerialize } from '../util.js';
8
7
  import { Observer } from './Runtime.js';
8
+ import { params } from '../util-url.js';
9
9
 
10
10
  /**
11
11
  * ---------------------------
@@ -169,7 +169,7 @@ export default class Url {
169
169
  * @return object
170
170
  */
171
171
  static toQuery(search) {
172
- return wwwFormUnserialize(search);
172
+ return params.parse(search);
173
173
  }
174
174
 
175
175
  /**
@@ -180,7 +180,7 @@ export default class Url {
180
180
  * @return string
181
181
  */
182
182
  static toSearch(query) {
183
- var search = wwwFormSerialize(query);
183
+ var search = params.stringify(query);
184
184
  return search ? '?' + search : '';
185
185
  }}
186
186
 
@@ -45,7 +45,7 @@ export default class Workport {
45
45
  resolve(registration);
46
46
  }).catch(e => reject(e));
47
47
  };
48
- if (params.onWondowLoad) {
48
+ if (params.onWindowLoad) {
49
49
  window.addEventListener('load', register);
50
50
  } else {
51
51
  register();
@@ -29,7 +29,7 @@ export default function(namespace = null, persistent = false) {
29
29
  return true;
30
30
  }
31
31
  if (event.type === 'has') {
32
- for(var i = 0; i < window[storeType].length; i ++){
32
+ for(let i = 0; i < window[storeType].length; i ++){
33
33
  if (window[storeType].key(i) === key) {
34
34
  return true;
35
35
  }
@@ -37,8 +37,8 @@ export default function(namespace = null, persistent = false) {
37
37
  return false;
38
38
  }
39
39
  if (event.type === 'ownKeys') {
40
- var keys = [];
41
- for(var i = 0; i < window[storeType].length; i ++){
40
+ const keys = [];
41
+ for(let i = 0; i < window[storeType].length; i ++){
42
42
  keys.push(window[storeType].key(i));
43
43
  };
44
44
  return keys;
@@ -11,7 +11,7 @@ import { _afterLast, _beforeLast } from '@webqit/util/str/index.js';
11
11
  import { _isObject, _isArray } from '@webqit/util/js/index.js';
12
12
  import { jsFile } from '@webqit/backpack/src/dotfile/index.js';
13
13
  import { gzipSync, brotliCompressSync } from 'zlib';
14
- import { urlPattern } from '../util.js';
14
+ import { pattern } from '../util-url.js';
15
15
 
16
16
  /**
17
17
  * @generate
@@ -152,12 +152,14 @@ export async function generate() {
152
152
  // >> Modules import
153
153
  gen.imports[`${dirSelf}/worker/index.js`] = `{ start }`;
154
154
  gen.code.push(``);
155
+ gen.code.push(`self.WebQit = {}`);
156
+ gen.code.push(``);
155
157
  // ------------------
156
158
  // Bundle
157
159
  if (workerConfig.cache_only_urls.length) {
158
160
  // Separate URLs from patterns
159
161
  let [ urls, patterns ] = workerConfig.cache_only_urls.reduce(([ urls, patterns ], url) => {
160
- let patternInstance = urlPattern(url, 'http://localhost'),
162
+ let patternInstance = pattern(url, 'http://localhost'),
161
163
  isPattern = patternInstance.isPattern();
162
164
  if (isPattern && (patternInstance.pattern.pattern.hostname !== 'localhost' || patternInstance.pattern.pattern.port)) {
163
165
  throw new Error(`Pattern URLs must have no origin part. Recieved "${url}".`);
@@ -233,7 +235,7 @@ function declareStart(gen, routesDir, targetDir, paramsObj, routing) {
233
235
  // ------------------
234
236
  // >> Startup
235
237
  gen.code.push(`// >> Startup`);
236
- gen.code.push(`start.call({ layout, params })`);
238
+ gen.code.push(`WebQit.app = await start.call({ layout, params })`);
237
239
  }
238
240
 
239
241
  /**
@@ -3,16 +3,16 @@
3
3
  * @imports
4
4
  */
5
5
  import Context from './Context.js';
6
- import RuntimeClient from './RuntimeClient.js';
6
+ import Application from './Application.js';
7
7
  import Runtime from './Runtime.js';
8
8
 
9
9
  /**
10
10
  * @start
11
11
  */
12
- export async function start(clientCallback = null) {
12
+ export async function start(applicationInstance = null) {
13
13
  const cx = this || {};
14
- const defaultClientCallback = _cx => new RuntimeClient(_cx);
15
- return new Runtime(Context.create(cx), clientCallback || defaultClientCallback);
14
+ const defaultApplicationInstance = _cx => new Application(_cx);
15
+ return new Runtime(Context.create(cx), applicationInstance || defaultApplicationInstance);
16
16
  }
17
17
 
18
18
  /**