@webqit/webflo 0.11.39 → 0.11.41

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 (47) hide show
  1. package/README.md +1 -1
  2. package/docker/Dockerfile +43 -0
  3. package/docker/README.md +91 -0
  4. package/docker/package.json +3 -0
  5. package/package.json +2 -3
  6. package/src/Context.js +3 -3
  7. package/src/config-pi/deployment/Layout.js +0 -1
  8. package/src/config-pi/deployment/Origins.js +7 -0
  9. package/src/config-pi/deployment/{Virtualization.js → Proxy.js} +3 -3
  10. package/src/config-pi/deployment/index.js +2 -2
  11. package/src/config-pi/runtime/Server.js +2 -2
  12. package/src/deployment-pi/origins/index.js +3 -2
  13. package/src/runtime-pi/{RuntimeClient.js → Application.js} +2 -2
  14. package/src/runtime-pi/HttpEvent.js +106 -0
  15. package/src/runtime-pi/Router.js +2 -3
  16. package/src/runtime-pi/Runtime.js +3 -3
  17. package/src/runtime-pi/client/{RuntimeClient.js → Application.js} +12 -4
  18. package/src/runtime-pi/client/Router.js +4 -3
  19. package/src/runtime-pi/client/Runtime.js +37 -59
  20. package/src/runtime-pi/client/Url.js +3 -3
  21. package/src/runtime-pi/client/Workport.js +1 -1
  22. package/src/runtime-pi/client/{Storage.js → createStorage.js} +3 -3
  23. package/src/runtime-pi/client/generate.js +5 -3
  24. package/src/runtime-pi/client/index.js +4 -4
  25. package/src/runtime-pi/client/worker/{WorkerClient.js → Application.js} +12 -8
  26. package/src/runtime-pi/client/worker/{Worker.js → Runtime.js} +25 -27
  27. package/src/runtime-pi/client/worker/index.js +6 -6
  28. package/src/runtime-pi/server/{RuntimeClient.js → Application.js} +8 -8
  29. package/src/runtime-pi/server/Router.js +3 -2
  30. package/src/runtime-pi/server/Runtime.js +50 -107
  31. package/src/runtime-pi/server/index.js +4 -4
  32. package/src/runtime-pi/util-http.js +70 -0
  33. package/src/runtime-pi/util-url.js +147 -0
  34. package/src/runtime-pi/xFormData.js +10 -46
  35. package/src/runtime-pi/xHeaders.js +2 -11
  36. package/src/runtime-pi/xRequest.js +29 -42
  37. package/src/runtime-pi/xRequestHeaders.js +20 -23
  38. package/src/runtime-pi/xResponse.js +19 -15
  39. package/src/runtime-pi/xResponseHeaders.js +41 -43
  40. package/src/runtime-pi/xURL.js +71 -77
  41. package/src/runtime-pi/xfetch.js +15 -6
  42. package/src/runtime-pi/xxHttpMessage.js +102 -0
  43. package/src/runtime-pi/client/whatwag.js +0 -27
  44. package/src/runtime-pi/server/whatwag.js +0 -35
  45. package/src/runtime-pi/util.js +0 -162
  46. package/src/runtime-pi/xHttpEvent.js +0 -101
  47. package/src/runtime-pi/xHttpMessage.js +0 -171
@@ -0,0 +1,102 @@
1
+
2
+ /**
3
+ * @imports
4
+ */
5
+ import { _isTypeObject } from '@webqit/util/js/index.js';
6
+ import xFormData from './xFormData.js';
7
+
8
+ /**
9
+ * The _Request Mixin
10
+ */
11
+ const xxHttpMessage = (whatwagHttpMessage, xHeaders) => {
12
+ const HttpMessage = class extends whatwagHttpMessage {
13
+
14
+ constructor(input, init, meta) {
15
+ // ------------
16
+ if (init.headers) { init = { ...init, headers: new xHeaders(init.headers) }; }
17
+ super(input, init);
18
+ if (meta.headers) { this.headers.json(meta.headers); }
19
+ // ------------
20
+ let attrs = {};
21
+ Object.defineProperty(this, '_attrs', { get: () => attrs });
22
+ Object.defineProperty(this, 'meta', { get: () => meta });
23
+ }
24
+
25
+ get attrs() {
26
+ return this._attrs || {};
27
+ }
28
+
29
+ clone() {
30
+ return new this.constructor(super.clone());
31
+ }
32
+
33
+ get headers() {
34
+ xHeaders.compat(super.headers);
35
+ return super.headers;
36
+ }
37
+
38
+ get url() {
39
+ return 'url' in this.attrs ? this.attrs.url : super.url;
40
+ }
41
+
42
+ async arrayBuffer() {
43
+ if (this.meta.type === 'ArrayBuffer') { return this.meta.body; }
44
+ return super.arrayBuffer();
45
+ }
46
+
47
+ async blob() {
48
+ if (this.meta.type === 'Blob') { return this.meta.body; }
49
+ return super.blob();
50
+ }
51
+
52
+ async formData() {
53
+ let formData;
54
+ if (this.meta.type === 'FormData' && this.meta.body instanceof FormData) {
55
+ formData = this.meta.body;
56
+ } else { formData = await super.formData(); }
57
+ if (formData) { xFormData.compat(formData); }
58
+ return formData;
59
+ }
60
+
61
+ async json() {
62
+ if (this.meta.type === 'json' && _isTypeObject(this.meta.body)) { return this.meta.body; }
63
+ return super.json();
64
+ }
65
+
66
+ async text() {
67
+ if (this.meta.type === 'json' && !_isTypeObject(this.meta.body)) { return this.meta.body; }
68
+ return super.text();
69
+ }
70
+
71
+ // Resolve
72
+ jsonfy(force = false) {
73
+ if (!this.meta.jsonfied || force) {
74
+ this.meta.jsonfied = new Promise(async (resolve, reject) => {
75
+ let jsonfied;
76
+ let contentType = this.headers.get('Content-Type') || '';
77
+ try {
78
+ if (contentType === 'application/x-www-form-urlencoded' || contentType.startsWith('multipart/form-data')) {
79
+ const formData = await this.formData();
80
+ jsonfied = formData?.json();
81
+ } else if (contentType === 'application/json') {
82
+ jsonfied = await this.json();
83
+ } else if (contentType === 'text/plain') {
84
+ jsonfied = await this.text();
85
+ }
86
+ resolve(jsonfied);
87
+ } catch(e) {
88
+ reject(e);
89
+ }
90
+ });
91
+ }
92
+ return this.meta.jsonfied;
93
+ }
94
+
95
+ };
96
+ // ----------
97
+ HttpMessage.Headers = xHeaders;
98
+ // ----------
99
+ return HttpMessage;
100
+ }
101
+
102
+ export default xxHttpMessage;
@@ -1,27 +0,0 @@
1
-
2
- const {
3
- URL,
4
- fetch,
5
- Headers,
6
- Request,
7
- Response,
8
- FormData,
9
- ReadableStream,
10
- File,
11
- Blob
12
- } = globalThis;
13
-
14
- /**
15
- * @exports
16
- */
17
- export {
18
- URL,
19
- fetch,
20
- Headers,
21
- Request,
22
- Response,
23
- FormData,
24
- ReadableStream,
25
- File,
26
- Blob,
27
- }
@@ -1,35 +0,0 @@
1
-
2
- /**
3
- * @imports
4
- */
5
- import { URL } from 'url';
6
- import { FormData, File, Blob } from 'formdata-node';
7
- import fetch, { Request, Response, Headers } from 'node-fetch';
8
- import { FormDataEncoder } from 'form-data-encoder';
9
- import { Readable } from "stream";
10
-
11
- /**
12
- * The NavigationEvent class
13
- */
14
- if (!Request.prototype.formData) {
15
- Request.prototype.formData = async function() { return null }
16
- }
17
- if (!Response.prototype.formData) {
18
- Response.prototype.formData = async function() { return null }
19
- }
20
- FormData.encode = formData => {
21
- const encoder = new FormDataEncoder(formData);
22
- return [ Readable.from(encoder.encode()), encoder.headers ];
23
- };
24
-
25
- export {
26
- URL,
27
- fetch,
28
- Headers,
29
- Request,
30
- Response,
31
- FormData,
32
- Readable as ReadableStream,
33
- File,
34
- Blob,
35
- }
@@ -1,162 +0,0 @@
1
-
2
- /**
3
- * @imports
4
- */
5
- import { _isString, _isObject, _isNumeric, _isArray } from '@webqit/util/js/index.js';
6
- import { _beforeLast, _afterLast } from '@webqit/util/str/index.js';
7
- import { _from as _arrFrom } from '@webqit/util/arr/index.js';
8
- if (typeof URLPattern === 'undefined') {
9
- await import('urlpattern-polyfill');
10
- }
11
-
12
- /**
13
- * ---------------
14
- * @wwwFormPathUnserializeCallback
15
- * ---------------
16
- */
17
-
18
- export function wwwFormPathUnserializeCallback(form, wwwFormPath, callback, touch = false) {
19
- if (_isString(wwwFormPath) && wwwFormPath.endsWith(']')) {
20
- var index = _beforeLast(_afterLast(wwwFormPath, '['), ']') || 0;
21
- if (_isNumeric(index)) {
22
- index = parseInt(index);
23
- }
24
- wwwFormPath = _beforeLast(wwwFormPath, '[') || 0;
25
- if (_isNumeric(wwwFormPath)) {
26
- wwwFormPath = parseInt(wwwFormPath);
27
- }
28
- return wwwFormPathUnserializeCallback(form, wwwFormPath, (_form, _wwwFormPath) => {
29
- if (!_form[_wwwFormPath]) {
30
- if (!touch) {
31
- return callback();
32
- }
33
- _form[_wwwFormPath] = _isNumeric(index) ? [] : {};
34
- }
35
- return callback(_form[_wwwFormPath], index);
36
- }, touch);
37
- } else {
38
- return callback(form, wwwFormPath);
39
- }
40
- }
41
-
42
- export function wwwFormSet(form, wwwFormPath, value, append = true) {
43
- wwwFormPathUnserializeCallback(form, wwwFormPath, (_form, _key) => {
44
- if (_isNumeric(_key)) {
45
- _key = _key || _isArray(_form)
46
- ? _form.length
47
- : Object.keys(_form).filter(_isNumeric).length;
48
- _arrFrom(value, false).forEach((_value, i) => {
49
- _form[_key + i] = _value;
50
- });
51
- } else {
52
- _form[_key] = append && (_key in _form) ? _arrFrom(_form[_key], false).concat(value) : value;
53
- }
54
- }, true);
55
- }
56
-
57
- export function wwwFormGet(form, wwwFormPath) {
58
- return wwwFormPathUnserializeCallback(form, wwwFormPath, function(_form, _key) {
59
- if (arguments.length) {
60
- return _form[_key]
61
- }
62
- }, false);
63
- }
64
-
65
- export function wwwFormUnserialize(str, target = {}, delim = '&') {
66
- str = str || '';
67
- (str.startsWith('?') ? str.substr(1) : str)
68
- .split(delim).filter(q => q).map(q => q.split('=').map(q => q.trim()))
69
- .forEach(q => wwwFormSet(target, q[0], decodeURIComponent(q[1])));
70
- return target;
71
- }
72
-
73
- /**
74
- * ---------------
75
- * @wwwFormPathSerialize
76
- * ---------------
77
- */
78
-
79
- export function wwwFormPathSerializeCallback(wwwFormPath, value, callback, shouldSerialize = null) {
80
- if ((_isObject(value) || _isArray(value)) && (!shouldSerialize || shouldSerialize(value, wwwFormPath))) {
81
- var isArr = _isArray(value);
82
- Object.keys(value).forEach(key => {
83
- wwwFormPathSerializeCallback(`${wwwFormPath}[${key}]`, value[key], callback, shouldSerialize);
84
- });
85
- } else {
86
- callback(wwwFormPath, !value && value !== 0 ? '' : value);
87
- }
88
- }
89
-
90
- export function wwwFormSerialize(form, delim = '&', shouldSerialize = null) {
91
- var q = [];
92
- Object.keys(form).forEach(key => {
93
- wwwFormPathSerializeCallback(key, form[key], (_wwwFormPath, _value) => {
94
- q.push(`${_wwwFormPath}=${encodeURIComponent(_value)}`);
95
- }, shouldSerialize);
96
- });
97
- return q.join(delim);
98
- }
99
-
100
- export const path = {
101
- join(/* path segments */) {
102
- // Split the inputs into a list of path commands.
103
- var parts = [], backsteps = 0;
104
- for (var i = 0, l = arguments.length; i < l; i++) {
105
- parts = parts.concat(arguments[i].split("/"));
106
- }
107
- // Interpret the path commands to get the new resolved path.
108
- var newParts = [];
109
- for (i = 0, l = parts.length; i < l; i++) {
110
- var part = parts[i];
111
- // Remove leading and trailing slashes
112
- // Also remove "." segments
113
- if (!part || part === ".") continue;
114
- // Interpret ".." to pop the last segment
115
- if (part === "..") {
116
- if (!newParts.length) backsteps ++;
117
- else newParts.pop();
118
- }
119
- // Push new path segments.
120
- else newParts.push(part);
121
- }
122
- // Preserve the initial slash if there was one.
123
- if (parts[0] === "") newParts.unshift("");
124
- // Turn back into a single string path.
125
- return '../'.repeat(backsteps) + newParts.join("/") || (newParts.length ? "/" : ".");
126
- },
127
-
128
- // A simple function to get the dirname of a path
129
- // Trailing slashes are ignored. Leading slash is preserved.
130
- dirname(path) {
131
- return this.join(path, "..");
132
- }
133
- };
134
-
135
- export const urlPattern = (pattern, baseUrl = null) => ({
136
- pattern: new URLPattern(pattern, baseUrl),
137
- isPattern() {
138
- return Object.keys(this.pattern.keys || {}).some(compName => this.pattern.keys[compName].length);
139
- },
140
- test(...args) { return this.pattern.test(...args) },
141
- exec(...args) {
142
- let components = this.pattern.exec(...args);
143
- if (!components) return;
144
- components.vars = Object.keys(this.pattern.keys).reduce(({ named, unnamed }, compName) => {
145
- this.pattern.keys[compName].forEach(key => {
146
- let value = components[compName].groups[key.name];
147
- if (typeof key.name === 'number') {
148
- unnamed.push(value);
149
- } else {
150
- named[key.name] = value;
151
- }
152
- });
153
- return { named, unnamed };
154
- }, { named: {}, unnamed: [] });
155
- components.render = str => {
156
- return str.replace(/\$(\$|[0-9A-Z]+)/gi, (a, b) => {
157
- return b === '$' ? '$' : (_isNumeric(b) ? components.vars.unnamed[b - 1] : components.vars.named[b]) || '';
158
- });
159
- }
160
- return components;
161
- }
162
- });
@@ -1,101 +0,0 @@
1
-
2
- /**
3
- * @imports
4
- */
5
- import { _isEmpty } from '@webqit/util/js/index.js';
6
-
7
- /**
8
- * The xHttpEvent Mixin
9
- */
10
- const xHttpEvent = (Request, Response, URL) => {
11
-
12
- const HttpEvent = class {
13
-
14
- /**
15
- * Initializes a new HttpEvent instance.
16
- *
17
- * @param Request _request
18
- * @param Object _detail
19
- * @param Object _sessionFactory
20
- */
21
- constructor(_request, _detail, _sessionFactory) {
22
- this._request = _request;
23
- this._detail = _detail || {};
24
- this._sessionFactory = _sessionFactory;
25
- // -------
26
- this.Request = Request;
27
- this.Response = Response;
28
- this.URL = URL;
29
- // -------
30
- this.port = {
31
- listeners: [],
32
- post(message) {
33
- const promises = this.listeners.map(listener => listener(message))
34
- .filter(returnValue => returnValue instanceof Promise);
35
- if (process.length) return Promise.all(promises);
36
- },
37
- listen(listener) { this.listeners.push(listener); },
38
- }
39
- }
40
-
41
- // url
42
- get url() {
43
- if (!this._url) {
44
- this._url = new this.URL(this._request.url);
45
- }
46
- return this._url;
47
- }
48
-
49
- // request
50
- get request() {
51
- return this._request;
52
- }
53
-
54
- // detail
55
- get detail() {
56
- return this._detail;
57
- }
58
-
59
- // Session
60
- get session() {
61
- if (!this._session) {
62
- this._session = this.sessionFactory().get();
63
- }
64
- return this._session;
65
- }
66
-
67
- // Session factory
68
- sessionFactory(...args) {
69
- return this._sessionFactory(...args);
70
- }
71
-
72
- // Redirect Response
73
- redirect(url, code = 302) {
74
- return new this.Response(null, { status: code, headers: { Location: url } });
75
- }
76
-
77
- // "with()"
78
- with(url, init = {}, _url = null) {
79
- let request;
80
- if (url instanceof Request) {
81
- if (!_isEmpty(init)) {
82
- request = new Request(url, init);
83
- } else {
84
- request = url;
85
- }
86
- if (_url) {
87
- request.attrs.url = `${this.url.origin}${_url}`;
88
- }
89
- } else {
90
- request = new Request(this._request, init);
91
- request.attrs.url = `${this.url.origin}${url}`;
92
- request.attrs.referrer = this.request.url;
93
- }
94
- return new HttpEvent(request, this.detail);
95
- }
96
-
97
- }
98
- return HttpEvent;
99
- }
100
-
101
- export default xHttpEvent;
@@ -1,171 +0,0 @@
1
-
2
- /**
3
- * @imports
4
- */
5
- import { _isArray, _isEmpty, _isNumber, _isObject, _isPlainArray, _isPlainObject, _isString } from '@webqit/util/js/index.js';
6
- import { formDataType } from './xFormData.js';
7
-
8
- /**
9
- * The _Request Mixin
10
- */
11
- const xHttpMessage = (whatwagHttpMessage, Headers, FormData) => {
12
- const HttpMessage = class extends whatwagHttpMessage {
13
-
14
- constructor(input, init, bodyAttrs) {
15
- if (init.headers) { init = { ...init, headers: new Headers(init.headers) }; }
16
- super(input, init);
17
- if (bodyAttrs.headers) {
18
- this.headers.json(bodyAttrs.headers);
19
- }
20
- let attrs = {};
21
- Object.defineProperty(this, 'attrs', { get: () => attrs });
22
- Object.defineProperty(this, 'bodyAttrs', { get: () => bodyAttrs });
23
- }
24
-
25
- clone() {
26
- return new this.constructor(super.clone());
27
- }
28
-
29
- get headers() {
30
- Headers.compat(super.headers);
31
- return super.headers;
32
- }
33
-
34
- get attrs() {
35
- return this.attrs;
36
- }
37
-
38
- get url() {
39
- return 'url' in this.attrs ? this.attrs.url : super.url;
40
- }
41
-
42
- async arrayBuffer() {
43
- if (this.bodyAttrs.arrayBuffer) {
44
- return this.bodyAttrs.arrayBuffer;
45
- }
46
- return super.arrayBuffer();
47
- }
48
-
49
- async blob() {
50
- if (this.bodyAttrs.blob) {
51
- return this.bodyAttrs.blob;
52
- }
53
- return super.blob();
54
- }
55
-
56
- async formData() {
57
- if (this.bodyAttrs.formData) {
58
- return this.bodyAttrs.formData;
59
- }
60
- const formData = await super.formData();
61
- formData.tee = FormData.prototype.tee.bind(formData);
62
- formData.json = FormData.prototype.json.bind(formData);
63
- return formData;
64
- }
65
-
66
- async json() {
67
- if (this.bodyAttrs.json) {
68
- return this.bodyAttrs.json;
69
- }
70
- return super.json();
71
- }
72
-
73
- async text() {
74
- if (this.bodyAttrs.text) {
75
- return this.bodyAttrs.text;
76
- }
77
- return super.text();
78
- }
79
-
80
- // Resolve
81
- jsonfy(force = false) {
82
- if (!this.bodyAttrs.jsonfied || force) {
83
- this.bodyAttrs.jsonfied = new Promise(async (resolve, reject) => {
84
- var messageInstance = this, jsonfied, contentType = messageInstance.headers.get('content-type') || '';
85
- var type = contentType === 'application/json' || this.bodyAttrs.json ? 'json' : (
86
- contentType === 'application/x-www-form-urlencoded' || contentType.startsWith('multipart/form-data') || this.bodyAttrs.formData ? 'formData' : (
87
- contentType === 'text/plain' ? 'plain' : 'other'
88
- )
89
- );
90
- try {
91
- if (type === 'formData') {
92
- jsonfied = (await messageInstance.formData()).json();
93
- } else {
94
- jsonfied = type === 'json' ? await messageInstance.json() : (
95
- type === 'plain' ? await messageInstance.text() : messageInstance.body
96
- );
97
- }
98
- resolve(jsonfied);
99
- } catch(e) {
100
- reject(e);
101
- }
102
- });
103
- }
104
- return this.bodyAttrs.jsonfied;
105
- }
106
-
107
- };
108
- // ----------
109
- HttpMessage.Headers = Headers;
110
- // ----------
111
- return HttpMessage;
112
- }
113
-
114
- export default xHttpMessage;
115
- export function encodeBody(body, FormData, Blob) {
116
- const detailsObj = { body, input: body };
117
- const encodeFormData = (detailsObj, formData) => {
118
- if (FormData.encode) {
119
- let [ body, headers ] = FormData.encode(formData);
120
- detailsObj.body = body;
121
- detailsObj.headers = headers;
122
- return;
123
- }
124
- detailsObj.body = formData;
125
- }
126
- if (_isString(body) || _isNumber(body)) {
127
- detailsObj.inputType = 'text';
128
- detailsObj.text = body;
129
- detailsObj.headers = {
130
- contentLength: (body + '').length,
131
- };
132
- return detailsObj;
133
- }
134
- detailsObj.inputType = formDataType(body);
135
- if ([ 'Blob', 'File' ].includes(detailsObj.inputType)) {
136
- detailsObj.blob = body;
137
- detailsObj.headers = {
138
- contentType: body.type,
139
- contentLength: body.size,
140
- };
141
- } else if ([ 'Uint8Array', 'Uint16Array', 'Uint32Array', 'ArrayBuffer' ].includes(detailsObj.inputType)) {
142
- detailsObj.arrayBuffer = body;
143
- detailsObj.headers = {
144
- contentLength: body.byteLength,
145
- };
146
- } else if (detailsObj.inputType === 'FormData') {
147
- detailsObj.formData = body;
148
- encodeFormData(detailsObj, body);
149
- } else if ((_isObject(body) && _isPlainObject(body)) || (_isArray(body) && _isPlainArray(body))) {
150
- detailsObj.inputType = 'object';
151
- // Deserialize object while detecting if multipart
152
- var hasBlobs, formData = new FormData;
153
- formData.json(body, (path, value, objectType) => {
154
- hasBlobs = hasBlobs || objectType;
155
- return true;
156
- });
157
- if (hasBlobs) {
158
- detailsObj.formData = formData;
159
- encodeFormData(detailsObj, formData);
160
- } else {
161
- detailsObj.json = body;
162
- detailsObj.body = JSON.stringify(body);
163
- detailsObj.headers = {
164
- contentType: 'application/json',
165
- contentLength: (new Blob([ detailsObj.body ])).size, // Buffer.byteLength(detailsObj.body, 'utf8') isn't cross-environment
166
- };
167
- }
168
- detailsObj.jsonfied = body;
169
- }
170
- return detailsObj;
171
- }