@webqit/webflo 0.8.71-0 → 0.8.72-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/package.json CHANGED
@@ -12,7 +12,7 @@
12
12
  "vanila-javascript"
13
13
  ],
14
14
  "homepage": "https://webqit.io/tooling/webflo",
15
- "version": "0.8.71-0",
15
+ "version": "0.8.72-0",
16
16
  "license": "MIT",
17
17
  "repository": {
18
18
  "type": "git",
@@ -104,26 +104,26 @@ const _MessageStream = (NativeMessageStream, Headers, FormData) => {
104
104
  }
105
105
 
106
106
  // Payload
107
- jsonBuild(force = false) {
108
- if (!this._typedDataCache.jsonBuild || force) {
109
- this._typedDataCache.jsonBuild = new Promise(async resolve => {
110
- var request = this, jsonBuild, contentType = request.headers.get('content-type') || '';
107
+ data(force = false) {
108
+ if (!this._typedDataCache.data || force) {
109
+ this._typedDataCache.data = new Promise(async resolve => {
110
+ var request = this, data, contentType = request.headers.get('content-type') || '';
111
111
  var type = contentType === 'application/json' || this._typedDataCache.json ? 'json' : (
112
112
  contentType === 'application/x-www-form-urlencoded' || contentType.startsWith('multipart/') || this._typedDataCache.formData || (!contentType && !['get'].includes((request.method || '').toLowerCase())) ? 'formData' : (
113
113
  contentType === 'text/plain' ? 'plain' : 'other'
114
114
  )
115
115
  );
116
116
  if (type === 'formData') {
117
- jsonBuild = (await request.formData()).json();
117
+ data = (await request.formData()).json();
118
118
  } else {
119
- jsonBuild = type === 'json' ? await request.json() : (
119
+ data = type === 'json' ? await request.json() : (
120
120
  type === 'plain' ? await request.text() : request.body
121
121
  );
122
122
  }
123
- resolve(jsonBuild);
123
+ resolve(data);
124
124
  });
125
125
  }
126
- return this._typedDataCache.jsonBuild;
126
+ return this._typedDataCache.data;
127
127
  }
128
128
 
129
129
  };
@@ -178,7 +178,7 @@ export function encodeBody(body, globals) {
178
178
  contentLength: Buffer.byteLength(detailsObj.body, 'utf8'), // Buffer.from(string).length
179
179
  };
180
180
  }
181
- detailsObj.jsonBuild = body;
181
+ detailsObj.data = body;
182
182
  }
183
183
  return detailsObj;
184
184
  }
@@ -22,12 +22,14 @@ const _NavigationEvent = globals => {
22
22
  /**
23
23
  * Initializes a new NavigationEvent instance.
24
24
  *
25
- * @param Request request
26
- * @param Object sessionStore
25
+ * @param Request _request
26
+ * @param Object _session
27
+ * @param Function _sessionFactory
27
28
  */
28
- constructor(_request, _session = null) {
29
+ constructor(_request, _session = {}, _sessionFactory = null) {
29
30
  this._request = _request;
30
31
  this._session = _session;
32
+ this.sessionFactory = _sessionFactory;
31
33
  // -------
32
34
  this.URL = URL;
33
35
  // -------
@@ -73,7 +75,7 @@ const _NavigationEvent = globals => {
73
75
  init._proxy.referrer = this.request.url;
74
76
  request = new NavigationEvent.Request(this._request, init);
75
77
  }
76
- return new NavigationEvent(request, this._session);
78
+ return new NavigationEvent(request, this._session, this.sessionFactory);
77
79
  }
78
80
 
79
81
  }
@@ -81,7 +81,7 @@ export default class Http {
81
81
  var anchor, href;
82
82
  if ((anchor = e.target.closest('a')) && (href = anchor.href)
83
83
  // And not towards any target nor have a download directive
84
- && !anchor.target && !anchor.download
84
+ && !anchor.target && !anchor.download && !href.includes('/my-account')
85
85
  // Same origin... but...
86
86
  && (!anchor.origin || anchor.origin === instance.location.origin)) {
87
87
  if (e.metaKey || e.altKey || e.ctrlKey || e.shiftKey) {
@@ -187,6 +187,8 @@ export default class Http {
187
187
  };
188
188
  const handleResponse = response => {
189
189
  if (response && response.redirected) {
190
+ window.location = response.url;
191
+ return;
190
192
  var actionEl = window.document.createElement('a');
191
193
  if ((actionEl.href = response.url) && (!actionEl.origin || actionEl.origin === instance.location.origin)) {
192
194
  Observer.set(instance.location, { href: response.url }, {
@@ -17,4 +17,5 @@ export default _NavigationEvent({
17
17
  File,
18
18
  Blob,
19
19
  ReadableStream,
20
+ fetch,
20
21
  });
@@ -111,7 +111,7 @@ export default function(layout, params) {
111
111
  });
112
112
  });
113
113
  if ($context.response instanceof clientNavigationEvent.Response) {
114
- $context.response = await $context.response.jsonBuild();
114
+ $context.response = await $context.response.data();
115
115
  }
116
116
 
117
117
  // --------
@@ -6,7 +6,7 @@ import { URL } from 'url';
6
6
  import { Readable } from "stream";
7
7
  import { FormData, File, Blob } from 'formdata-node';
8
8
  import { FormDataEncoder } from 'form-data-encoder';
9
- import { Request, Response, Headers } from 'node-fetch';
9
+ import fetch, { Request, Response, Headers } from 'node-fetch';
10
10
  import _NavigationEvent from '../_NavigationEvent.js';
11
11
  import _FormData from '../_FormData.js';
12
12
 
@@ -34,5 +34,6 @@ export default _NavigationEvent({
34
34
  File,
35
35
  Blob,
36
36
  ReadableStream: Readable,
37
- FormDataEncoder
37
+ FormDataEncoder,
38
+ fetch
38
39
  });
@@ -34,33 +34,11 @@ import Router from './Router.js';
34
34
  export default async function(Ui, flags = {}) {
35
35
 
36
36
  const layout = await config.layout.read(flags, {});
37
- const setup = {
37
+ const v_setup = {}, setup = {
38
38
  layout,
39
39
  server: await config.server.read(flags, layout),
40
40
  variables: await config.variables.read(flags, layout),
41
41
  };
42
-
43
- if (!setup.server.shared && setup.variables.autoload !== false) {
44
- Object.keys(setup.variables.entries).forEach(key => {
45
- if (!(key in process.env) || setup.variables.autoload === 2) {
46
- process.env[key] = setup.variables.entries[key];
47
- }
48
- });
49
- }
50
-
51
- const getSessionInitializer = (sesskey, hostname = null) => {
52
- const secret = sesskey || (hostname ? uuidv5(hostname, uuidv4()) : uuidv4());
53
- return Sessions({
54
- cookieName: '_session', // cookie name dictates the key name added to the request object
55
- secret, // should be a large unguessable string
56
- duration: 24 * 60 * 60 * 1000, // how long the session will stay valid in ms
57
- activeDuration: 1000 * 60 * 5 // if expiresIn < activeDuration, the session will be extended by activeDuration milliseconds
58
- });
59
- };
60
-
61
- const instanceSetup = setup;
62
-
63
- const v_setup = {};
64
42
  if (setup.server.shared) {
65
43
  await Promise.all(((await config.vhosts.read(flags, setup.layout)).entries || []).map(vh => new Promise(async resolve => {
66
44
  const vlayout = await config.layout.read(flags, {ROOT: Path.join(setup.layout.ROOT, vh.path)});
@@ -70,86 +48,57 @@ export default async function(Ui, flags = {}) {
70
48
  variables: await config.variables.read(flags, vlayout),
71
49
  vh,
72
50
  };
73
- v_setup[vh.host].sessionInit = getSessionInitializer(v_setup[vh.host].variables.entries.sesskey, vh.host),
74
51
  resolve();
75
52
  })));
76
- } else {
77
- setup.sessionInit = getSessionInitializer(setup.variables.entries.sesskey);
78
- }
53
+ } else if (setup.variables.autoload !== false) {
54
+ Object.keys(setup.variables.entries).forEach(key => {
55
+ if (!(key in process.env) || setup.variables.autoload === 2) {
56
+ process.env[key] = setup.variables.entries[key];
57
+ }
58
+ });
59
+ }
79
60
 
80
61
  // ---------------------------------------------
81
-
82
- const getVSetup = (request, response) => {
83
- var _setup, v_hostname = (request.headers.host || '').split(':')[0];
84
- if (_setup = v_setup[v_hostname]) {
85
- return _setup;
62
+
63
+ function handleRequest(protocol, request, response) {
64
+ let _setup = setup, hostname = (request.headers.host || '').split(':')[0];
65
+ if (setup.server.shared) {
66
+ if (!(_setup = v_setup[hostname])
67
+ && ((hostname.startsWith('www.') && (_setup = v_setup[hostname.substr(4)]) && _setup.server.force_www)
68
+ && (!hostname.startsWith('www.') && (_setup = v_setup['www.' + hostname]) && _setup.server.force_www))) {
69
+ response.statusCode = 500;
70
+ response.end('Unrecognized host');
71
+ return;
72
+ }
86
73
  }
87
- if ((v_hostname.startsWith('www.') && (_setup = v_setup[v_hostname.substr(4)]) && _setup.server.force_www)
88
- || (!v_hostname.startsWith('www.') && (_setup = v_setup['www.' + v_hostname]) && _setup.server.force_www)) {
89
- return _setup;
74
+ if (protocol === 'http' && _setup.server.https.force && !flags['http-only'] && /** main server */setup.server.https.port) {
75
+ response.statusCode = 302;
76
+ response.setHeader('Location', 'https://' + request.headers.host + request.url);
77
+ response.end();
78
+ return;
90
79
  }
91
- response.statusCode = 500;
92
- response.end('Unrecognized host');
93
- };
94
-
95
- const goOrForceWww = (setup, request, response, protocol) => {
96
- var hostname = request.headers.host || '';
97
80
  if (hostname.startsWith('www.') && setup.server.force_www === 'remove') {
98
81
  response.statusCode = 302;
99
82
  response.setHeader('Location', protocol + '://' + hostname.substr(4) + request.url);
100
83
  response.end();
101
- } else if (!hostname.startsWith('www.') && setup.server.force_www === 'add') {
84
+ return;
85
+ }
86
+ if (!hostname.startsWith('www.') && setup.server.force_www === 'add') {
102
87
  response.statusCode = 302;
103
88
  response.setHeader('Location', protocol + '://www.' + hostname + request.url);
104
89
  response.end();
105
- } else {
106
- setup.sessionInit(request, response, () => {});
107
- run(instanceSetup, setup, request, response, Ui, flags, protocol);
90
+ return;
108
91
  }
92
+ run(_setup, request, response, Ui, flags, protocol);
109
93
  };
110
94
 
111
95
  // ---------------------------------------------
112
-
113
- if (!flags['https-only']) {
114
-
115
- Http.createServer((request, response) => {
116
- if (setup.server.shared) {
117
- var _setup;
118
- if (_setup = getVSetup(request, response)) {
119
- goOrForceHttps(_setup, request, response);
120
- }
121
- } else {
122
- goOrForceHttps(setup, request, response);
123
- }
124
- }).listen(process.env.PORT || setup.server.port);
125
-
126
- const goOrForceHttps = ($setup, $request, $response) => {
127
- if ($setup.server.https.force && !flags['http-only'] && /** main server */setup.server.https.port) {
128
- $response.statusCode = 302;
129
- $response.setHeader('Location', 'https://' + $request.headers.host + $request.url);
130
- $response.end();
131
- } else {
132
- goOrForceWww($setup, $request, $response, 'http');
133
- }
134
- };
135
96
 
97
+ if (!flags['https-only']) {
98
+ Http.createServer((request, response) => handleRequest('http', request, response)).listen(process.env.PORT || setup.server.port);
136
99
  }
137
-
138
- // ---------------------------------------------
139
-
140
100
  if (!flags['http-only'] && setup.server.https.port) {
141
-
142
- const httpsServer = Https.createServer((request, response) => {
143
- if (setup.server.shared) {
144
- var _setup;
145
- if (_setup = getVSetup(request, response)) {
146
- goOrForceWww(_setup, request, response, 'https');
147
- }
148
- } else {
149
- goOrForceWww(setup, request, response, 'https');
150
- }
151
- });
152
-
101
+ const httpsServer = Https.createServer((request, response) => handleRequest('https', request, response));
153
102
  if (setup.server.shared) {
154
103
  _each(v_setup, (host, _setup) => {
155
104
  if (Fs.existsSync(_setup.server.https.keyfile)) {
@@ -185,7 +134,6 @@ export default async function(Ui, flags = {}) {
185
134
  });
186
135
  }
187
136
  }
188
-
189
137
  httpsServer.listen(process.env.PORT2 || setup.server.https.port);
190
138
  }
191
139
  };
@@ -193,7 +141,6 @@ export default async function(Ui, flags = {}) {
193
141
  /**
194
142
  * The Server.
195
143
  *
196
- * @param Object instanceSetup
197
144
  * @param Object hostSetup
198
145
  * @param Request request
199
146
  * @param Response response
@@ -203,13 +150,12 @@ export default async function(Ui, flags = {}) {
203
150
  *
204
151
  * @return void
205
152
  */
206
- export async function run(instanceSetup, hostSetup, request, response, Ui, flags = {}, protocol = 'http') {
153
+ export async function run(hostSetup, request, response, Ui, flags = {}, protocol = 'http') {
207
154
 
208
155
  // --------
209
156
  // Request parsing
210
157
  // --------
211
158
 
212
- const fullUrl = protocol + '://' + request.headers.host + request.url;
213
159
  const requestInit = { method: request.method, headers: request.headers };
214
160
  if (request.method !== 'GET' && request.method !== 'HEAD') {
215
161
  requestInit.body = await new Promise((resolve, reject) => {
@@ -257,10 +203,38 @@ export async function run(instanceSetup, hostSetup, request, response, Ui, flags
257
203
  });
258
204
  });
259
205
  }
260
- // The Formidabble thing in NavigationEvent class would still need
261
- // a reference to the Nodejs request
206
+
207
+ // --------
208
+ // NavigationEvent instance
209
+ // --------
210
+
211
+ const fullUrl = protocol + '://' + request.headers.host + request.url;
262
212
  const _request = new NavigationEvent.Request(fullUrl, requestInit);
263
- const serverNavigationEvent = new NavigationEvent(_request, request._session);
213
+ const _sessionFactory = function(id, params = {}, callback = null) {
214
+ let factory, secret = hostSetup.variables.entries.SESSION_KEY;
215
+ Sessions({
216
+ duration: 0, // how long the session will stay valid in ms
217
+ activeDuration: 0, // if expiresIn < activeDuration, the session will be extended by activeDuration milliseconds
218
+ ...params,
219
+ cookieName: id, // cookie name dictates the key name added to the request object
220
+ secret, // should be a large unguessable string
221
+ })(request, response, e => {
222
+ factory = Object.getOwnPropertyDescriptor(request, id);
223
+ if (callback) {
224
+ callback(e, factory);
225
+ } else if (e) {
226
+ // TODO
227
+ }
228
+ });
229
+ // Where theres no error, factory is available Sync
230
+ return !callback ? factory : undefined;
231
+ };
232
+ const serverNavigationEvent = new NavigationEvent(
233
+ _request,
234
+ _sessionFactory('_session', {duration: 60 * 60 * 24 * 30}).get(),
235
+ _sessionFactory
236
+ );
237
+
264
238
  const $context = {
265
239
  rdr: null,
266
240
  layout: hostSetup.layout,
@@ -485,7 +459,7 @@ export async function run(instanceSetup, hostSetup, request, response, Ui, flags
485
459
  if (name === 'set-cookie') {
486
460
  setCookies(value);
487
461
  } else {
488
- if (name.toLowerCase() === 'location' && !$context.response.status) {
462
+ if (name.toLowerCase() === 'location' && $context.response.status === 200) {
489
463
  response.statusCode = 302 /* Temporary */;
490
464
  }
491
465
  response.setHeader(name, value);
@@ -496,6 +470,7 @@ export async function run(instanceSetup, hostSetup, request, response, Ui, flags
496
470
  // Send
497
471
  // -------------------
498
472
  if ($context.response.headers.redirect) {
473
+ response.statusCode = $context.response.status;
499
474
  response.end();
500
475
  } else if ($context.response.original !== undefined && $context.response.original !== null) {
501
476
  response.statusCode = $context.response.status;