@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.
- package/package.json +2 -3
- package/src/Context.js +3 -3
- package/src/config-pi/deployment/Layout.js +0 -1
- package/src/runtime-pi/{RuntimeClient.js → Application.js} +2 -2
- package/src/runtime-pi/HttpEvent.js +106 -0
- package/src/runtime-pi/Router.js +2 -3
- package/src/runtime-pi/Runtime.js +3 -3
- package/src/runtime-pi/client/{RuntimeClient.js → Application.js} +12 -4
- package/src/runtime-pi/client/Router.js +4 -3
- package/src/runtime-pi/client/Runtime.js +37 -59
- package/src/runtime-pi/client/Url.js +3 -3
- package/src/runtime-pi/client/Workport.js +1 -1
- package/src/runtime-pi/client/{Storage.js → createStorage.js} +3 -3
- package/src/runtime-pi/client/generate.js +5 -3
- package/src/runtime-pi/client/index.js +4 -4
- package/src/runtime-pi/client/worker/{WorkerClient.js → Application.js} +12 -8
- package/src/runtime-pi/client/worker/{Worker.js → Runtime.js} +25 -27
- package/src/runtime-pi/client/worker/index.js +6 -6
- package/src/runtime-pi/server/{RuntimeClient.js → Application.js} +8 -8
- package/src/runtime-pi/server/Router.js +3 -2
- package/src/runtime-pi/server/Runtime.js +41 -98
- package/src/runtime-pi/server/index.js +4 -4
- package/src/runtime-pi/util-http.js +70 -0
- package/src/runtime-pi/util-url.js +147 -0
- package/src/runtime-pi/xFormData.js +10 -46
- package/src/runtime-pi/xHeaders.js +2 -11
- package/src/runtime-pi/xRequest.js +29 -42
- package/src/runtime-pi/xRequestHeaders.js +20 -23
- package/src/runtime-pi/xResponse.js +19 -15
- package/src/runtime-pi/xResponseHeaders.js +41 -43
- package/src/runtime-pi/xURL.js +71 -77
- package/src/runtime-pi/xfetch.js +15 -6
- package/src/runtime-pi/xxHttpMessage.js +102 -0
- package/src/runtime-pi/client/whatwag.js +0 -27
- package/src/runtime-pi/server/whatwag.js +0 -35
- package/src/runtime-pi/util.js +0 -162
- package/src/runtime-pi/xHttpEvent.js +0 -101
- 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.
|
|
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.
|
|
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
|
|
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
|
|
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
|
|
77
|
+
Object.defineProperty(this.dict, 'logger', { value } );
|
|
78
78
|
}
|
|
79
79
|
|
|
80
80
|
}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
|
|
2
2
|
/**
|
|
3
3
|
* ---------------------------
|
|
4
|
-
* The base
|
|
4
|
+
* The base Application class
|
|
5
5
|
* ---------------------------
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
export default class
|
|
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
|
+
}
|
package/src/runtime-pi/Router.js
CHANGED
|
@@ -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
|
-
|
|
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,
|
|
15
|
+
constructor(cx, applicationInstance) {
|
|
16
16
|
this.cx = cx;
|
|
17
17
|
this.cx.runtime = this;
|
|
18
|
-
this.
|
|
19
|
-
if (!this.
|
|
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
|
|
6
|
+
import _Application from '../Application.js';
|
|
7
7
|
|
|
8
|
-
export default class
|
|
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
|
-
|
|
31
|
-
|
|
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.
|
|
29
|
-
thisTick.trailOnFile.
|
|
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
|
|
7
|
+
import createStorage from './createStorage.js';
|
|
8
8
|
import Url from './Url.js';
|
|
9
|
-
import
|
|
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
|
|
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
|
|
28
|
+
* @param Function applicationInstance
|
|
52
29
|
*
|
|
53
30
|
* @return void
|
|
54
31
|
*/
|
|
55
|
-
constructor(cx,
|
|
56
|
-
super(cx,
|
|
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 =
|
|
104
|
+
var query = params.parse(actionEl.search);
|
|
128
105
|
Array.from(formData.entries()).forEach(_entry => {
|
|
129
|
-
|
|
106
|
+
params.set(query, _entry[0], _entry[1]);
|
|
130
107
|
});
|
|
131
|
-
actionEl.search =
|
|
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
|
|
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.
|
|
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.
|
|
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
|
|
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
|
|
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
|
-
|
|
220
|
-
return
|
|
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
|
|
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 (
|
|
239
|
-
return new
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
|
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
|
|
289
|
+
} else if (request instanceof URL) {
|
|
314
290
|
href = request.href;
|
|
315
291
|
}
|
|
316
292
|
Observer.set(this.network, 'remote', href);
|
|
317
|
-
let _response =
|
|
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
|
|
300
|
+
return new xResponse(response);
|
|
325
301
|
});
|
|
326
302
|
}
|
|
327
303
|
|
|
328
304
|
// Handles response object
|
|
329
305
|
handleResponse(e, response) {
|
|
330
|
-
if (
|
|
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
|
|
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 =
|
|
183
|
+
var search = params.stringify(query);
|
|
184
184
|
return search ? '?' + search : '';
|
|
185
185
|
}}
|
|
186
186
|
|
|
@@ -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(
|
|
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
|
-
|
|
41
|
-
for(
|
|
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 {
|
|
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 =
|
|
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
|
|
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(
|
|
12
|
+
export async function start(applicationInstance = null) {
|
|
13
13
|
const cx = this || {};
|
|
14
|
-
const
|
|
15
|
-
return new Runtime(Context.create(cx),
|
|
14
|
+
const defaultApplicationInstance = _cx => new Application(_cx);
|
|
15
|
+
return new Runtime(Context.create(cx), applicationInstance || defaultApplicationInstance);
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
/**
|