@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.
- 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 → AbstractContext.js} +71 -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 +11 -19
- package/src/runtime-pi/HttpEvent.js +126 -106
- package/src/runtime-pi/HttpUser.js +126 -0
- package/src/runtime-pi/MessagingOverBroadcast.js +9 -0
- package/src/runtime-pi/MessagingOverChannel.js +85 -0
- package/src/runtime-pi/MessagingOverSocket.js +106 -0
- package/src/runtime-pi/MultiportMessagingAPI.js +81 -0
- package/src/runtime-pi/WebfloCookieStorage.js +27 -0
- package/src/runtime-pi/WebfloEventTarget.js +39 -0
- package/src/runtime-pi/WebfloMessageEvent.js +58 -0
- package/src/runtime-pi/WebfloMessagingAPI.js +69 -0
- package/src/runtime-pi/{Router.js → WebfloRouter.js} +99 -130
- package/src/runtime-pi/WebfloRuntime.js +52 -0
- package/src/runtime-pi/WebfloStorage.js +109 -0
- package/src/runtime-pi/client/ClientMessaging.js +5 -0
- package/src/runtime-pi/client/Context.js +3 -7
- package/src/runtime-pi/client/CookieStorage.js +17 -0
- package/src/runtime-pi/client/Router.js +38 -48
- package/src/runtime-pi/client/SessionStorage.js +33 -0
- package/src/runtime-pi/client/Url.js +156 -205
- package/src/runtime-pi/client/WebfloClient.js +544 -0
- package/src/runtime-pi/client/WebfloRootClient1.js +179 -0
- package/src/runtime-pi/client/WebfloRootClient2.js +109 -0
- package/src/runtime-pi/client/WebfloSubClient.js +165 -0
- package/src/runtime-pi/client/Workport.js +118 -178
- package/src/runtime-pi/client/generate.js +480 -471
- package/src/runtime-pi/client/index.js +16 -21
- package/src/runtime-pi/client/worker/ClientMessaging.js +5 -0
- package/src/runtime-pi/client/worker/Context.js +3 -7
- package/src/runtime-pi/client/worker/CookieStorage.js +17 -0
- package/src/runtime-pi/client/worker/SessionStorage.js +13 -0
- package/src/runtime-pi/client/worker/WebfloWorker.js +294 -0
- package/src/runtime-pi/client/worker/Workport.js +17 -85
- package/src/runtime-pi/client/worker/index.js +10 -21
- package/src/runtime-pi/index.js +6 -13
- package/src/runtime-pi/server/ClientMessaging.js +18 -0
- package/src/runtime-pi/server/ClientMessagingRegistry.js +57 -0
- package/src/runtime-pi/server/Context.js +11 -15
- package/src/runtime-pi/server/CookieStorage.js +17 -0
- package/src/runtime-pi/server/Router.js +93 -159
- package/src/runtime-pi/server/SessionStorage.js +53 -0
- package/src/runtime-pi/server/WebfloServer.js +755 -0
- package/src/runtime-pi/server/index.js +10 -21
- package/src/runtime-pi/util-http.js +322 -86
- package/src/runtime-pi/util-url.js +146 -146
- package/src/runtime-pi/xURL.js +108 -105
- package/src/runtime-pi/xfetch.js +22 -22
- 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/Application.js +0 -29
- package/src/runtime-pi/Cookies.js +0 -82
- package/src/runtime-pi/Runtime.js +0 -21
- package/src/runtime-pi/client/Application.js +0 -100
- package/src/runtime-pi/client/Runtime.js +0 -332
- package/src/runtime-pi/client/createStorage.js +0 -57
- 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
- package/src/runtime-pi/client/worker/Application.js +0 -44
- package/src/runtime-pi/client/worker/Runtime.js +0 -269
- package/src/runtime-pi/server/Application.js +0 -116
- package/src/runtime-pi/server/Runtime.js +0 -557
- package/src/runtime-pi/xFormData.js +0 -24
- package/src/runtime-pi/xHeaders.js +0 -146
- package/src/runtime-pi/xRequest.js +0 -46
- package/src/runtime-pi/xRequestHeaders.js +0 -109
- package/src/runtime-pi/xResponse.js +0 -33
- package/src/runtime-pi/xResponseHeaders.js +0 -117
- package/src/runtime-pi/xxHttpMessage.js +0 -102
|
@@ -1,48 +1,38 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
thisTick.
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
finalizeHandlerContext(context, thisTick) {
|
|
42
|
-
return context.dirname = thisTick.currentSegmentOnFile.index;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
pathJoin(...args) {
|
|
46
|
-
return Path.join(...args);
|
|
47
|
-
}
|
|
48
|
-
};
|
|
1
|
+
import { path as Path } from '../util-url.js';
|
|
2
|
+
import { WebfloRouter } from '../WebfloRouter.js';
|
|
3
|
+
|
|
4
|
+
export class Router extends WebfloRouter {
|
|
5
|
+
|
|
6
|
+
async readTick(thisTick) {
|
|
7
|
+
thisTick = { ...thisTick };
|
|
8
|
+
var routeTree = this.cx.layout;
|
|
9
|
+
var routePaths = Object.keys(this.cx.layout);
|
|
10
|
+
if (thisTick.trail) {
|
|
11
|
+
thisTick.currentSegment = thisTick.destination[thisTick.trail.length];
|
|
12
|
+
thisTick.currentSegmentOnFile = [ thisTick.currentSegment, '-' ].reduce((_segmentOnFile, _seg) => {
|
|
13
|
+
if (_segmentOnFile.index) return _segmentOnFile;
|
|
14
|
+
var _currentPath = `/${thisTick.trailOnFile.concat(_seg).join('/')}`;
|
|
15
|
+
return routeTree[_currentPath] ? { seg: _seg, index: _currentPath } : (
|
|
16
|
+
routePaths.filter(p => p.startsWith(`${_currentPath}/`)).length ? { seg: _seg, dirExists: true } : _segmentOnFile
|
|
17
|
+
);
|
|
18
|
+
}, { seg: null });
|
|
19
|
+
thisTick.trail = thisTick.trail.concat(thisTick.currentSegment);
|
|
20
|
+
thisTick.trailOnFile = thisTick.trailOnFile.concat(thisTick.currentSegmentOnFile.seg);
|
|
21
|
+
thisTick.exports = routeTree[thisTick.currentSegmentOnFile.index];
|
|
22
|
+
} else {
|
|
23
|
+
thisTick.trail = [];
|
|
24
|
+
thisTick.trailOnFile = [];
|
|
25
|
+
thisTick.currentSegmentOnFile = { index: '/' };
|
|
26
|
+
thisTick.exports = routeTree['/'];
|
|
27
|
+
}
|
|
28
|
+
return thisTick;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
finalizeHandlerContext(context, thisTick) {
|
|
32
|
+
return context.dirname = thisTick.currentSegmentOnFile.index;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
pathJoin(...args) {
|
|
36
|
+
return Path.join(...args);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { WebfloStorage } from '../WebfloStorage.js';
|
|
2
|
+
|
|
3
|
+
export class SessionStorage extends WebfloStorage {
|
|
4
|
+
static get type() { return 'session'; }
|
|
5
|
+
|
|
6
|
+
static create(request) {
|
|
7
|
+
const keys = [];
|
|
8
|
+
const storeType = this.type === 'user' ? 'localStorage' : 'sessionStorage';
|
|
9
|
+
for(let i = 0; i < window[storeType].length; i ++){
|
|
10
|
+
keys.push(window[storeType].key(i));
|
|
11
|
+
};
|
|
12
|
+
const instance = new this(
|
|
13
|
+
request,
|
|
14
|
+
keys.map((key) => [key, window[storeType].getItem(key)])
|
|
15
|
+
);
|
|
16
|
+
return instance;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
constructor(request, iterable) {
|
|
20
|
+
super(request, true, iterable);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
commit() {
|
|
24
|
+
const storeType = this.constructor.type === 'user' ? 'localStorage' : 'sessionStorage';
|
|
25
|
+
for (const key of this.getAdded()) {
|
|
26
|
+
window[storeType].setItem(key, this.get(key));
|
|
27
|
+
}
|
|
28
|
+
for (const key of this.getDeleted()) {
|
|
29
|
+
window[storeType].removeItem(key);
|
|
30
|
+
}
|
|
31
|
+
super.commit();
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -1,206 +1,157 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
var
|
|
60
|
-
|
|
61
|
-
|
|
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
|
-
|
|
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
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
*/
|
|
158
|
-
static parseUrl(href) {
|
|
159
|
-
var a = document.createElement('a');
|
|
160
|
-
a.href = href;
|
|
161
|
-
return this.copy(a);
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
/**
|
|
165
|
-
* Parses the input search string into a named map
|
|
166
|
-
*
|
|
167
|
-
* @param string search
|
|
168
|
-
*
|
|
169
|
-
* @return object
|
|
170
|
-
*/
|
|
171
|
-
static toQuery(search) {
|
|
172
|
-
return params.parse(search);
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
/**
|
|
176
|
-
* Stringifies the input query to search string.
|
|
177
|
-
*
|
|
178
|
-
* @param object query
|
|
179
|
-
*
|
|
180
|
-
* @return string
|
|
181
|
-
*/
|
|
182
|
-
static toSearch(query) {
|
|
183
|
-
var search = params.stringify(query);
|
|
184
|
-
return search ? '?' + search : '';
|
|
185
|
-
}}
|
|
186
|
-
|
|
187
|
-
/**
|
|
188
|
-
* These are standard
|
|
189
|
-
* and shouldnt'/can't be modified
|
|
190
|
-
*
|
|
191
|
-
* @array
|
|
192
|
-
*/
|
|
193
|
-
const urlProperties = [
|
|
194
|
-
'protocol',
|
|
195
|
-
'username',
|
|
196
|
-
'password',
|
|
197
|
-
'host',
|
|
198
|
-
'hostname',
|
|
199
|
-
'port',
|
|
200
|
-
'origin',
|
|
201
|
-
'pathname',
|
|
202
|
-
'search',
|
|
203
|
-
'query',
|
|
204
|
-
'hash',
|
|
205
|
-
'href',
|
|
1
|
+
import { _with } from '@webqit/util/obj/index.js';
|
|
2
|
+
import { _isArray, _isObject, _isTypeObject, _isString, _isEmpty } from '@webqit/util/js/index.js';
|
|
3
|
+
import { params } from '../util-url.js';
|
|
4
|
+
|
|
5
|
+
const { Observer } = webqit;
|
|
6
|
+
|
|
7
|
+
export class Url {
|
|
8
|
+
|
|
9
|
+
constructor(input) {
|
|
10
|
+
const Self = this.constructor;
|
|
11
|
+
// -----------------------
|
|
12
|
+
// Helpers
|
|
13
|
+
var _strictEven = (a, b) => {
|
|
14
|
+
if (_isObject(a) && _isObject(b)) {
|
|
15
|
+
return _strictEven(Object.keys(a), Object.keys(b))
|
|
16
|
+
&& _strictEven(Object.values(a), Object.values(b));
|
|
17
|
+
}
|
|
18
|
+
if (_isArray(a) && _isArray(b)) {
|
|
19
|
+
return a.length === b.length
|
|
20
|
+
&& a.reduce((recieved, item, i) => recieved && item === b[i], true);
|
|
21
|
+
}
|
|
22
|
+
return a === b;
|
|
23
|
+
};
|
|
24
|
+
Observer.intercept(this, 'set', (e, prev, next) => {
|
|
25
|
+
if (e.key === 'hash' && e.value && !e.value.startsWith('#')) {
|
|
26
|
+
e.value = '#' + e.value;
|
|
27
|
+
} else if (e.key === 'search' && e.value && !e.value.startsWith('?')) {
|
|
28
|
+
e.value = '?' + e.value;
|
|
29
|
+
}
|
|
30
|
+
return next();
|
|
31
|
+
});
|
|
32
|
+
// -----------------------
|
|
33
|
+
// When any one of these properties change,
|
|
34
|
+
// the others are automatically derived
|
|
35
|
+
Observer.observe(this, changes => {
|
|
36
|
+
var urlObj = {};
|
|
37
|
+
var onlyHrefChanged;
|
|
38
|
+
for (var e of changes) {
|
|
39
|
+
// ----------
|
|
40
|
+
if (e.key === 'href' && e.related.length === 1) {
|
|
41
|
+
var urlObj = Self.parseUrl(e.value);
|
|
42
|
+
if (urlObj.pathname) {
|
|
43
|
+
urlObj.pathname = '/' + urlObj.pathname.split('/').filter(s => s.trim()).join('/');
|
|
44
|
+
}
|
|
45
|
+
delete urlObj.query;
|
|
46
|
+
delete urlObj.href;
|
|
47
|
+
onlyHrefChanged = true;
|
|
48
|
+
}
|
|
49
|
+
// ----------
|
|
50
|
+
if (e.key === 'query' && !e.related.includes('search')) {
|
|
51
|
+
// "query" was updated. So we update "search"
|
|
52
|
+
var search = Self.toSearch(this.query); // Not e.value, as that might be a subtree value
|
|
53
|
+
if (search !== this.search) {
|
|
54
|
+
urlObj.search = search;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
if (e.key === 'search' && !e.related.includes('query')) {
|
|
58
|
+
// "search" was updated. So we update "query"
|
|
59
|
+
var query = Self.toQuery(urlObj.search || this.search); // Not e.value, as that might be a href value
|
|
60
|
+
if (!_strictEven(query, this.query)) {
|
|
61
|
+
urlObj.query = query;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
if (e.key === 'pathname' && !e.related.includes('ancestorPathname')) {
|
|
65
|
+
// "pathname" was updated. So we update "ancestorPathname"
|
|
66
|
+
var ancestorPathname = (urlObj.pathname || this.pathname).replace(new RegExp('/[^/]+(?:/)?$'), '');
|
|
67
|
+
if (ancestorPathname !== this.ancestorPathname) {
|
|
68
|
+
urlObj.ancestorPathname = ancestorPathname;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
if (e.key === 'ancestorPathname' && !e.related.includes('pathname')) {
|
|
72
|
+
// "ancestorPathname" was updated. So we update "pathname"
|
|
73
|
+
var pathname = '/' + (urlObj.ancestorPathname || this.ancestorPathname).split('/').filter(s => s).concat((urlObj.pathname || this.pathname).split('/').filter(s => s).pop()).join('/');
|
|
74
|
+
if (pathname !== this.pathname) {
|
|
75
|
+
urlObj.pathname = pathname;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
if (!onlyHrefChanged) {
|
|
80
|
+
var fullOrigin = this.origin,
|
|
81
|
+
usernamePassword = [ this.username, this.password ].filter(a => a);
|
|
82
|
+
if (usernamePassword.length === 2) {
|
|
83
|
+
fullOrigin = `${this.protocol}//${usernamePassword.join(':')}@${this.hostname}${(this.port ? `:${this.port}` : '')}`;
|
|
84
|
+
}
|
|
85
|
+
var href = [ fullOrigin, urlObj.pathname || this.pathname, urlObj.search || this.search || (this.href.includes('?') ? '?' : ''), this.hash || (this.href.includes('#') ? '#' : '') ].join('');
|
|
86
|
+
if (href !== this.href) {
|
|
87
|
+
urlObj.href = href;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
if (!_isEmpty(urlObj)) {
|
|
91
|
+
return Observer.set(this, urlObj);
|
|
92
|
+
}
|
|
93
|
+
}, { diff: true });
|
|
94
|
+
// -----------------------
|
|
95
|
+
// Validate e.detail
|
|
96
|
+
Observer.observe(this, changes => {
|
|
97
|
+
changes.forEach(e => {
|
|
98
|
+
if (e && e.detail) {
|
|
99
|
+
if (!_isTypeObject(e.detail)) {
|
|
100
|
+
throw new Error('"e.detail" can only be of type object.');
|
|
101
|
+
}
|
|
102
|
+
if (e.detail.request && !_isObject(e.detail.request)) {
|
|
103
|
+
throw new Error('"e.detail.request" can only be of type object.');
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
}, { diff: true });
|
|
108
|
+
// -----------------------
|
|
109
|
+
// Startup properties
|
|
110
|
+
Observer.set(this, _isString(input) ? Self.parseUrl(input) : Url.copy(input));
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
toString() {
|
|
114
|
+
return this.href;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
static from(href) {
|
|
118
|
+
return new this(_isObject(href) ? href : this.parseUrl(href));
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
static copy(urlObj) {
|
|
122
|
+
var url = urlProperties.reduce((obj, prop) => _with(obj, prop, urlObj[prop] || ''), {});
|
|
123
|
+
if (!('query' in urlObj)) {
|
|
124
|
+
delete url.query;
|
|
125
|
+
}
|
|
126
|
+
return url;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
static parseUrl(href) {
|
|
130
|
+
var a = new URL(href);
|
|
131
|
+
return this.copy(a);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
static toQuery(search) {
|
|
135
|
+
return params.parse(search);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
static toSearch(query) {
|
|
139
|
+
var search = params.stringify(query);
|
|
140
|
+
return search ? '?' + search : '';
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
const urlProperties = [
|
|
145
|
+
'protocol',
|
|
146
|
+
'username',
|
|
147
|
+
'password',
|
|
148
|
+
'host',
|
|
149
|
+
'hostname',
|
|
150
|
+
'port',
|
|
151
|
+
'origin',
|
|
152
|
+
'pathname',
|
|
153
|
+
'search',
|
|
154
|
+
'query',
|
|
155
|
+
'hash',
|
|
156
|
+
'href',
|
|
206
157
|
];
|