@webqit/webflo 0.8.45 → 0.8.49
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/docker/Dockerfile +25 -0
- package/docker/README.md +69 -0
- package/package.json +9 -5
- package/src/cmd/client.js +68 -97
- package/src/cmd/origins.js +2 -2
- package/src/modules/Router.js +130 -0
- package/src/modules/_FormData.js +60 -0
- package/src/modules/_Headers.js +88 -0
- package/src/modules/_MessageStream.js +191 -0
- package/src/modules/_NavigationEvent.js +89 -0
- package/src/modules/_Request.js +61 -0
- package/src/modules/_RequestHeaders.js +72 -0
- package/src/modules/_Response.js +56 -0
- package/src/modules/_ResponseHeaders.js +81 -0
- package/src/modules/_URL.js +111 -0
- package/src/modules/client/Cache.js +38 -0
- package/src/modules/client/Client.js +51 -22
- package/src/modules/client/Http.js +26 -11
- package/src/modules/client/NavigationEvent.js +20 -0
- package/src/modules/client/Router.js +30 -104
- package/src/modules/client/StdRequest.js +34 -33
- package/src/modules/client/Storage.js +56 -0
- package/src/modules/client/Url.js +1 -1
- package/src/modules/client/Worker.js +74 -68
- package/src/modules/client/WorkerClient.js +102 -0
- package/src/modules/client/WorkerComm.js +183 -0
- package/src/modules/client/effects/sounds.js +64 -0
- package/src/modules/server/NavigationEvent.js +38 -0
- package/src/modules/server/Router.js +53 -124
- package/src/modules/server/Server.js +195 -87
- package/src/modules/util.js +7 -7
- package/src/modules/NavigationEvent.js +0 -32
- package/src/modules/Response.js +0 -98
- package/src/modules/XURL.js +0 -125
- package/src/modules/client/ClientNavigationEvent.js +0 -22
- package/src/modules/client/Push.js +0 -84
- package/src/modules/server/ServerNavigationEvent.js +0 -23
- package/src/modules/server/StdIncomingMessage.js +0 -70
package/src/modules/Response.js
DELETED
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
/**
|
|
3
|
-
* @imports
|
|
4
|
-
*/
|
|
5
|
-
import { _toTitle, _fromCamel, _after, _beforeLast } from "@webqit/util/str/index.js";
|
|
6
|
-
import { _isString, _getType, _isObject } from "@webqit/util/js/index.js";
|
|
7
|
-
|
|
8
|
-
export default class Response {
|
|
9
|
-
|
|
10
|
-
// construct
|
|
11
|
-
constructor(definition) {
|
|
12
|
-
// We have the request instance in scope.
|
|
13
|
-
this._request = this.constructor._request;
|
|
14
|
-
Object.keys(definition).forEach(prop => {
|
|
15
|
-
var value = definition[prop];
|
|
16
|
-
if (['contentType', 'cacheControl', 'redirect', 'cors', 'cookies'].includes(prop)) {
|
|
17
|
-
this[prop] = value;
|
|
18
|
-
} else {
|
|
19
|
-
Object.defineProperty(this, prop, { value, enumerable:true });
|
|
20
|
-
}
|
|
21
|
-
});
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
setHeader(name, value) {
|
|
25
|
-
if (!this.headers) {
|
|
26
|
-
Object.defineProperty(this, 'headers', { value: {}, enumerable:true });
|
|
27
|
-
}
|
|
28
|
-
this.headers[name.includes('-') ? name : _fromCamel(_toTitle(name), '-')] = value;
|
|
29
|
-
return this;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
getHeader(name) {
|
|
33
|
-
return Object.keys(this.headers || {}).reduce((val, _name) => val || (_name.toLowerCase() === name.toLowerCase() ? this.headers[_name] : null), null);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
set contentType(value) {
|
|
37
|
-
return this.setHeader('Content-Type', value);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
get contentType() {
|
|
41
|
-
return this.getHeader('Content-Type');
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
set cookies(cookieJar) {
|
|
45
|
-
if (!_isObject(cookieJar)) {
|
|
46
|
-
throw new Error(`The "cookies" response directive does not support the type: ${_getType(cookieJar)}`);
|
|
47
|
-
}
|
|
48
|
-
this.setHeader('Set-Cookie', cookieJar);
|
|
49
|
-
return true;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
get cookies() {
|
|
53
|
-
return this.getHeader('Set-Cookie');
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
set redirect(value) {
|
|
57
|
-
return this.setHeader('Location', value);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
get redirect() {
|
|
61
|
-
return this.getHeader('Location');
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
set download(value) {
|
|
65
|
-
value = value === true ? 'attachment' : (value === false ? 'inline' : value);
|
|
66
|
-
if (!_isString(value)) {
|
|
67
|
-
throw new Error(`The "download" response directive does not support the type: ${_getType(value)}`);
|
|
68
|
-
}
|
|
69
|
-
if (!['attachment', 'inline'].includes(value)) {
|
|
70
|
-
value = `attachment; filename="${value}"`;
|
|
71
|
-
}
|
|
72
|
-
return this.setHeader('Content-Disposition', value);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
get download() {
|
|
76
|
-
var value = (this.getHeader('Content-Disposition') || '').trim();
|
|
77
|
-
value = value === 'attachment' ? true : (
|
|
78
|
-
value === 'inline' ? false : _after(_beforeLast(value, '"'), 'filename="')
|
|
79
|
-
);
|
|
80
|
-
return value;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
set cors(value) {
|
|
84
|
-
return this.setHeader('Access-Control-Allow-Origin', value === true ? '*' : (value === false ? '' : value));
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
get cors() {
|
|
88
|
-
return this.getHeader('Access-Control-Allow-Origin');
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
set cacheControl(value) {
|
|
92
|
-
return this.setHeader('Cache-Control', value);
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
get cacheControl() {
|
|
96
|
-
return this.getHeader('Cache-Control');
|
|
97
|
-
}
|
|
98
|
-
}
|
package/src/modules/XURL.js
DELETED
|
@@ -1,125 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
/**
|
|
3
|
-
* @imports
|
|
4
|
-
*/
|
|
5
|
-
import { Observer } from '@webqit/pseudo-browser/index2.js';
|
|
6
|
-
import _isArray from '@webqit/util/js/isArray.js';
|
|
7
|
-
import _isObject from '@webqit/util/js/isObject.js';
|
|
8
|
-
import { wwwFormUnserialize, wwwFormSerialize } from './util.js';
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* ---------------------------
|
|
12
|
-
* URLX Mixin
|
|
13
|
-
* ---------------------------
|
|
14
|
-
*/
|
|
15
|
-
export const _URLX = BaseURL => class URL extends BaseURL {
|
|
16
|
-
|
|
17
|
-
// constructor
|
|
18
|
-
constructor(...args) {
|
|
19
|
-
super(...args);
|
|
20
|
-
var query = wwwFormUnserialize(this.search);
|
|
21
|
-
const updateSearch = query => {
|
|
22
|
-
// "query" was updated. So we update "search"
|
|
23
|
-
var search = wwwFormSerialize(query);
|
|
24
|
-
search = search ? '?' + search : '';
|
|
25
|
-
if (search !== this.search) {
|
|
26
|
-
this.search = search;
|
|
27
|
-
}
|
|
28
|
-
};
|
|
29
|
-
this.__query = {
|
|
30
|
-
value: query,
|
|
31
|
-
proxy: new Proxy(query, {
|
|
32
|
-
set(t, n, v) {
|
|
33
|
-
t[n] = v;
|
|
34
|
-
updateSearch(t);
|
|
35
|
-
return true;
|
|
36
|
-
},
|
|
37
|
-
deleteProperty(t, n) {
|
|
38
|
-
delete t[n];
|
|
39
|
-
updateSearch(t);
|
|
40
|
-
return true;
|
|
41
|
-
}
|
|
42
|
-
})
|
|
43
|
-
};
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
// Set search
|
|
47
|
-
set search(value) {
|
|
48
|
-
super.search = value;
|
|
49
|
-
// "search" was updated. So we update "query"
|
|
50
|
-
var query = wwwFormUnserialize(value);
|
|
51
|
-
if (!_strictEven(query, this.query)) {
|
|
52
|
-
this.query = query;
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
// Get search
|
|
57
|
-
get search() {
|
|
58
|
-
return super.search;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
// Get query
|
|
62
|
-
get query() {
|
|
63
|
-
return this.__query.proxy;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* ---------------------------
|
|
70
|
-
* URLXX Mixin
|
|
71
|
-
* ---------------------------
|
|
72
|
-
*/
|
|
73
|
-
export const _URLXX = BaseURL => class URL extends _URLX(BaseURL) {
|
|
74
|
-
|
|
75
|
-
constructor() {
|
|
76
|
-
super(...arguments);
|
|
77
|
-
Observer.accessorize(this, [
|
|
78
|
-
'protocol',
|
|
79
|
-
'username',
|
|
80
|
-
'password',
|
|
81
|
-
'host',
|
|
82
|
-
'hostname',
|
|
83
|
-
'port',
|
|
84
|
-
'origin',
|
|
85
|
-
'pathname',
|
|
86
|
-
'search',
|
|
87
|
-
'query',
|
|
88
|
-
'hash',
|
|
89
|
-
'href',
|
|
90
|
-
]);
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
* ---------------------------
|
|
97
|
-
* Helpers
|
|
98
|
-
* ---------------------------
|
|
99
|
-
*/
|
|
100
|
-
var _strictEven = (a, b) => {
|
|
101
|
-
if (_isObject(a) && _isObject(b)) {
|
|
102
|
-
return _strictEven(Object.keys(a), Object.keys(b))
|
|
103
|
-
&& _strictEven(Object.values(a), Object.values(b));
|
|
104
|
-
}
|
|
105
|
-
if (_isArray(a) && _isArray(b)) {
|
|
106
|
-
return a.length === b.length
|
|
107
|
-
&& a.reduce((recieved, item, i) => recieved && item === b[i], true);
|
|
108
|
-
}
|
|
109
|
-
return a === b;
|
|
110
|
-
};
|
|
111
|
-
|
|
112
|
-
/**
|
|
113
|
-
* ---------------------------
|
|
114
|
-
* URLX Classes
|
|
115
|
-
* ---------------------------
|
|
116
|
-
*/
|
|
117
|
-
const URLX = _URLX(URL);
|
|
118
|
-
export default URLX;
|
|
119
|
-
|
|
120
|
-
/**
|
|
121
|
-
* ---------------------------
|
|
122
|
-
* URLXX Classes
|
|
123
|
-
* ---------------------------
|
|
124
|
-
*/
|
|
125
|
-
export const URLXX = _URLXX(URL);
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
/**
|
|
3
|
-
* @imports
|
|
4
|
-
*/
|
|
5
|
-
import XURL from '../XURL.js';
|
|
6
|
-
import NavigationEvent from '../NavigationEvent.js';
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* The ClientNavigationEvent class
|
|
10
|
-
*/
|
|
11
|
-
export default class ClientNavigationEvent extends NavigationEvent {
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Initializes a new NavigationEvent instance.
|
|
15
|
-
*
|
|
16
|
-
* @param Request request
|
|
17
|
-
*/
|
|
18
|
-
constructor(request) {
|
|
19
|
-
super(request);
|
|
20
|
-
this._url = new XURL(request.url);
|
|
21
|
-
}
|
|
22
|
-
}
|
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
/**
|
|
3
|
-
*
|
|
4
|
-
* @imports
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* ------------------
|
|
9
|
-
* Push Notifications client class
|
|
10
|
-
* ------------------
|
|
11
|
-
*/
|
|
12
|
-
export default class Push {
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Push Notifications client class
|
|
16
|
-
*
|
|
17
|
-
* @param object registration
|
|
18
|
-
* @param object params
|
|
19
|
-
*
|
|
20
|
-
* @return void
|
|
21
|
-
*/
|
|
22
|
-
constructor(registration, params) {
|
|
23
|
-
this.registration = registration;
|
|
24
|
-
this.params = params;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Gets the user's subscription
|
|
29
|
-
*
|
|
30
|
-
* @return void
|
|
31
|
-
*/
|
|
32
|
-
async getSubscription() {
|
|
33
|
-
return await this.registration.pushManager.getSubscription();
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Subscribes to Push Notifications
|
|
38
|
-
*
|
|
39
|
-
* @return object
|
|
40
|
-
*/
|
|
41
|
-
async subscribe() {
|
|
42
|
-
var subscription = await this.getSubscription();
|
|
43
|
-
if (!subscription) {
|
|
44
|
-
subscription = await this.registration.pushManager.subscribe({
|
|
45
|
-
userVisibleOnly: true,
|
|
46
|
-
applicationServerKey: urlBase64ToUint8Array(this.params.public_key),
|
|
47
|
-
}).then(subscription => {
|
|
48
|
-
console.log('Subscribed to', subscription.endpoint);
|
|
49
|
-
return subscription;
|
|
50
|
-
});
|
|
51
|
-
return await fetch(this.params.registration_url, {
|
|
52
|
-
method: 'post',
|
|
53
|
-
headers: {'Content-type': 'application/json', Accept: 'application/json'},
|
|
54
|
-
body: JSON.stringify({subscription,}),
|
|
55
|
-
}).then(response => response.json()).then(response => {
|
|
56
|
-
console.log('Subscribed with Notifications server', response);
|
|
57
|
-
return response;
|
|
58
|
-
});
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* Unsubscribes from Push Notifications
|
|
64
|
-
*
|
|
65
|
-
* @return object
|
|
66
|
-
*/
|
|
67
|
-
async unsubscribe() {
|
|
68
|
-
var subscription = await this.getSubscription();
|
|
69
|
-
if (subscription) {
|
|
70
|
-
subscription.unsubscribe().then(subscription => {
|
|
71
|
-
console.log('Unsubscribed', subscription.endpoint);
|
|
72
|
-
return subscription;
|
|
73
|
-
});
|
|
74
|
-
return await fetch(this.params.deregistration_url, {
|
|
75
|
-
method: 'post',
|
|
76
|
-
headers: {'Content-type': 'application/json', Accept: 'application/json'},
|
|
77
|
-
body: JSON.stringify({subscription,}),
|
|
78
|
-
}).then(response => response.json()).then(response => {
|
|
79
|
-
console.log('Unsubscribed with Notifications server', response);
|
|
80
|
-
return response;
|
|
81
|
-
});
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
};
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
/**
|
|
3
|
-
* @imports
|
|
4
|
-
*/
|
|
5
|
-
import XURL from '../XURL.js';
|
|
6
|
-
import NavigationEvent from '../NavigationEvent.js';
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* The ServerNavigationEvent class
|
|
10
|
-
*/
|
|
11
|
-
export default class ServerNavigationEvent extends NavigationEvent {
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Initializes a new NavigationEvent instance.
|
|
15
|
-
*
|
|
16
|
-
* @param Request request
|
|
17
|
-
* @param String protocol
|
|
18
|
-
*/
|
|
19
|
-
constructor(request, protocol = 'http') {
|
|
20
|
-
super(request);
|
|
21
|
-
this._url = new XURL(protocol + '://' + request.headers.host + request.url);
|
|
22
|
-
}
|
|
23
|
-
}
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
/**
|
|
3
|
-
* @imports
|
|
4
|
-
*/
|
|
5
|
-
import Http from 'http';
|
|
6
|
-
import Accepts from 'accepts';
|
|
7
|
-
import Formidable from 'formidable';
|
|
8
|
-
import { _isTypeObject } from '@webqit/util/js/index.js';
|
|
9
|
-
import { wwwFormUnserialize, wwwFormSet } from '../util.js';
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* The Request class
|
|
13
|
-
*/
|
|
14
|
-
export default class StdIncomingMessage extends Http.IncomingMessage {
|
|
15
|
-
|
|
16
|
-
// Accept Header
|
|
17
|
-
get accepts() {
|
|
18
|
-
if (!this._accepts) {
|
|
19
|
-
this._accepts = Accepts(this);
|
|
20
|
-
}
|
|
21
|
-
return this._accepts;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
get cookies() {
|
|
25
|
-
if (!this._cookies) {
|
|
26
|
-
this._cookies = wwwFormUnserialize(this.headers.cookie, {}, ';');
|
|
27
|
-
}
|
|
28
|
-
return this._cookies;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
// Payload
|
|
33
|
-
parse() {
|
|
34
|
-
return new Promise(async resolve => {
|
|
35
|
-
var request = this;
|
|
36
|
-
var contentType = request.headers['content-type'];
|
|
37
|
-
var submits = {
|
|
38
|
-
payload: null,
|
|
39
|
-
inputs: {},
|
|
40
|
-
files: {},
|
|
41
|
-
type: contentType === 'application/x-www-form-urlencoded' || contentType.startsWith('multipart/') ? 'form-data'
|
|
42
|
-
: (contentType === 'application/json' ? 'json'
|
|
43
|
-
: (contentType === 'text/plain' ? 'plain'
|
|
44
|
-
: 'other')),
|
|
45
|
-
};
|
|
46
|
-
var formidable = new Formidable.IncomingForm({multiples: true, keepExtensions: true});
|
|
47
|
-
formidable.parse(request, function(error, inputs, files) {
|
|
48
|
-
if (error) {
|
|
49
|
-
reject(error);
|
|
50
|
-
return;
|
|
51
|
-
}
|
|
52
|
-
if (submits.type === 'form-data') {
|
|
53
|
-
submits.payload = { ...inputs, ...files };
|
|
54
|
-
Object.keys(inputs).forEach(name => {
|
|
55
|
-
wwwFormSet(submits.inputs, name, inputs[name]);
|
|
56
|
-
});
|
|
57
|
-
Object.keys(files).forEach(name => {
|
|
58
|
-
wwwFormSet(submits.files, name, files[name]);
|
|
59
|
-
});
|
|
60
|
-
} else {
|
|
61
|
-
submits.payload = inputs;
|
|
62
|
-
if (submits.type === 'json' && _isTypeObject(submits.payload)) {
|
|
63
|
-
submits.inputs = inputs;
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
resolve(submits);
|
|
67
|
-
});
|
|
68
|
-
});
|
|
69
|
-
}
|
|
70
|
-
}
|