@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.
Files changed (118) hide show
  1. package/.gitignore +7 -7
  2. package/LICENSE +20 -20
  3. package/README.md +2079 -2074
  4. package/docker/Dockerfile +42 -42
  5. package/docker/README.md +91 -91
  6. package/docker/package.json +2 -2
  7. package/package.json +80 -81
  8. package/src/{Context.js → AbstractContext.js} +71 -79
  9. package/src/config-pi/deployment/Env.js +68 -68
  10. package/src/config-pi/deployment/Layout.js +63 -63
  11. package/src/config-pi/deployment/Origins.js +139 -139
  12. package/src/config-pi/deployment/Proxy.js +74 -74
  13. package/src/config-pi/deployment/index.js +17 -17
  14. package/src/config-pi/index.js +15 -15
  15. package/src/config-pi/runtime/Client.js +116 -98
  16. package/src/config-pi/runtime/Server.js +125 -125
  17. package/src/config-pi/runtime/client/Worker.js +109 -134
  18. package/src/config-pi/runtime/client/index.js +11 -11
  19. package/src/config-pi/runtime/index.js +17 -17
  20. package/src/config-pi/runtime/server/Headers.js +74 -74
  21. package/src/config-pi/runtime/server/Redirects.js +69 -69
  22. package/src/config-pi/runtime/server/index.js +13 -13
  23. package/src/config-pi/static/Manifest.js +319 -319
  24. package/src/config-pi/static/Ssg.js +49 -49
  25. package/src/config-pi/static/index.js +13 -13
  26. package/src/deployment-pi/index.js +10 -10
  27. package/src/deployment-pi/origins/index.js +216 -216
  28. package/src/index.js +11 -19
  29. package/src/runtime-pi/HttpEvent.js +126 -106
  30. package/src/runtime-pi/HttpUser.js +126 -0
  31. package/src/runtime-pi/MessagingOverBroadcast.js +9 -0
  32. package/src/runtime-pi/MessagingOverChannel.js +85 -0
  33. package/src/runtime-pi/MessagingOverSocket.js +106 -0
  34. package/src/runtime-pi/MultiportMessagingAPI.js +81 -0
  35. package/src/runtime-pi/WebfloCookieStorage.js +27 -0
  36. package/src/runtime-pi/WebfloEventTarget.js +39 -0
  37. package/src/runtime-pi/WebfloMessageEvent.js +58 -0
  38. package/src/runtime-pi/WebfloMessagingAPI.js +69 -0
  39. package/src/runtime-pi/{Router.js → WebfloRouter.js} +99 -130
  40. package/src/runtime-pi/WebfloRuntime.js +52 -0
  41. package/src/runtime-pi/WebfloStorage.js +109 -0
  42. package/src/runtime-pi/client/ClientMessaging.js +5 -0
  43. package/src/runtime-pi/client/Context.js +3 -7
  44. package/src/runtime-pi/client/CookieStorage.js +17 -0
  45. package/src/runtime-pi/client/Router.js +38 -48
  46. package/src/runtime-pi/client/SessionStorage.js +33 -0
  47. package/src/runtime-pi/client/Url.js +156 -205
  48. package/src/runtime-pi/client/WebfloClient.js +544 -0
  49. package/src/runtime-pi/client/WebfloRootClient1.js +179 -0
  50. package/src/runtime-pi/client/WebfloRootClient2.js +109 -0
  51. package/src/runtime-pi/client/WebfloSubClient.js +165 -0
  52. package/src/runtime-pi/client/Workport.js +118 -178
  53. package/src/runtime-pi/client/generate.js +480 -471
  54. package/src/runtime-pi/client/index.js +16 -21
  55. package/src/runtime-pi/client/worker/ClientMessaging.js +5 -0
  56. package/src/runtime-pi/client/worker/Context.js +3 -7
  57. package/src/runtime-pi/client/worker/CookieStorage.js +17 -0
  58. package/src/runtime-pi/client/worker/SessionStorage.js +13 -0
  59. package/src/runtime-pi/client/worker/WebfloWorker.js +294 -0
  60. package/src/runtime-pi/client/worker/Workport.js +17 -85
  61. package/src/runtime-pi/client/worker/index.js +10 -21
  62. package/src/runtime-pi/index.js +6 -13
  63. package/src/runtime-pi/server/ClientMessaging.js +18 -0
  64. package/src/runtime-pi/server/ClientMessagingRegistry.js +57 -0
  65. package/src/runtime-pi/server/Context.js +11 -15
  66. package/src/runtime-pi/server/CookieStorage.js +17 -0
  67. package/src/runtime-pi/server/Router.js +93 -159
  68. package/src/runtime-pi/server/SessionStorage.js +53 -0
  69. package/src/runtime-pi/server/WebfloServer.js +755 -0
  70. package/src/runtime-pi/server/index.js +10 -21
  71. package/src/runtime-pi/util-http.js +322 -86
  72. package/src/runtime-pi/util-url.js +146 -146
  73. package/src/runtime-pi/xURL.js +108 -105
  74. package/src/runtime-pi/xfetch.js +22 -22
  75. package/src/services-pi/cert/http-auth-hook.js +22 -22
  76. package/src/services-pi/cert/http-cleanup-hook.js +22 -22
  77. package/src/services-pi/cert/index.js +79 -79
  78. package/src/services-pi/index.js +8 -8
  79. package/src/static-pi/index.js +10 -10
  80. package/src/webflo.js +30 -30
  81. package/test/index.test.js +26 -26
  82. package/test/site/package.json +9 -9
  83. package/test/site/public/bundle.html +5 -5
  84. package/test/site/public/bundle.html.json +3 -3
  85. package/test/site/public/bundle.js +2 -2
  86. package/test/site/public/bundle.webflo.js +15 -15
  87. package/test/site/public/index.html +29 -29
  88. package/test/site/public/index1.html +34 -34
  89. package/test/site/public/page-2/bundle.html +4 -4
  90. package/test/site/public/page-2/bundle.js +2 -2
  91. package/test/site/public/page-2/index.html +45 -45
  92. package/test/site/public/page-2/main.html +2 -2
  93. package/test/site/public/page-4/subpage/bundle.js +2 -2
  94. package/test/site/public/page-4/subpage/index.html +30 -30
  95. package/test/site/public/sparoots.json +4 -4
  96. package/test/site/public/worker.js +3 -3
  97. package/test/site/server/index.js +15 -15
  98. package/src/runtime-pi/Application.js +0 -29
  99. package/src/runtime-pi/Cookies.js +0 -82
  100. package/src/runtime-pi/Runtime.js +0 -21
  101. package/src/runtime-pi/client/Application.js +0 -100
  102. package/src/runtime-pi/client/Runtime.js +0 -332
  103. package/src/runtime-pi/client/createStorage.js +0 -57
  104. package/src/runtime-pi/client/oohtml/full.js +0 -7
  105. package/src/runtime-pi/client/oohtml/namespacing.js +0 -7
  106. package/src/runtime-pi/client/oohtml/scripting.js +0 -8
  107. package/src/runtime-pi/client/oohtml/templating.js +0 -8
  108. package/src/runtime-pi/client/worker/Application.js +0 -44
  109. package/src/runtime-pi/client/worker/Runtime.js +0 -269
  110. package/src/runtime-pi/server/Application.js +0 -116
  111. package/src/runtime-pi/server/Runtime.js +0 -557
  112. package/src/runtime-pi/xFormData.js +0 -24
  113. package/src/runtime-pi/xHeaders.js +0 -146
  114. package/src/runtime-pi/xRequest.js +0 -46
  115. package/src/runtime-pi/xRequestHeaders.js +0 -109
  116. package/src/runtime-pi/xResponse.js +0 -33
  117. package/src/runtime-pi/xResponseHeaders.js +0 -117
  118. package/src/runtime-pi/xxHttpMessage.js +0 -102
@@ -1,159 +1,93 @@
1
-
2
- /**
3
- * @imports
4
- */
5
- import Fs from 'fs';
6
- import Url from 'url';
7
- import Path from 'path';
8
- import Mime from 'mime-types';
9
- import _Router from '../Router.js';
10
-
11
- /**
12
- * ---------------------------
13
- * The Router class
14
- * ---------------------------
15
- */
16
-
17
- export default class Router extends _Router {
18
-
19
- async readTick(thisTick) {
20
- thisTick = { ...thisTick };
21
- if (thisTick.trail) {
22
- thisTick.currentSegment = thisTick.destination[thisTick.trail.length];
23
- thisTick.currentSegmentOnFile = [ thisTick.currentSegment, '-' ].reduce((_segmentOnFile, _seg) => {
24
- if (_segmentOnFile.index) return _segmentOnFile;
25
- var _currentPath = thisTick.trailOnFile.concat(_seg).join('/'),
26
- routeHandlerFile;
27
- return Fs.existsSync(routeHandlerFile = Path.join(this.cx.CWD, this.cx.layout.SERVER_DIR, _currentPath, 'index.js')) ? { seg: _seg, index: routeHandlerFile } : (
28
- Fs.existsSync(Path.join(this.cx.CWD, this.cx.layout.SERVER_DIR, _currentPath)) ? { seg: _seg, dirExists: true } : _segmentOnFile
29
- );
30
- }, { seg: null });
31
- thisTick.trail = thisTick.trail.concat(thisTick.currentSegment);
32
- thisTick.trailOnFile = thisTick.trailOnFile.concat(thisTick.currentSegmentOnFile.seg);
33
- thisTick.exports = thisTick.currentSegmentOnFile.index ? await import(Url.pathToFileURL(thisTick.currentSegmentOnFile.index)) : undefined;
34
- } else {
35
- thisTick.trail = [];
36
- thisTick.trailOnFile = [];
37
- thisTick.currentSegmentOnFile = { index: Path.join(this.cx.CWD, this.cx.layout.SERVER_DIR, 'index.js') };
38
- thisTick.exports = Fs.existsSync(thisTick.currentSegmentOnFile.index)
39
- ? await import(Url.pathToFileURL(thisTick.currentSegmentOnFile.index))
40
- : null;
41
- }
42
- return thisTick;
43
- }
44
-
45
- finalizeHandlerContext(context, thisTick) {
46
- if (thisTick.currentSegmentOnFile.index) {
47
- context.dirname = Path.dirname(thisTick.currentSegmentOnFile.index);
48
- }
49
- }
50
-
51
- pathJoin(...args) {
52
- return Path.join(...args);
53
- }
54
-
55
- /**
56
- * Reads a static file from the public directory.
57
- *
58
- * @param ServerNavigationEvent httpEvent
59
- *
60
- * @return Promise
61
- */
62
- file(httpEvent) {
63
- let filename = Path.join(this.cx.CWD, this.cx.layout.PUBLIC_DIR, decodeURIComponent(httpEvent.url.pathname));
64
- let index, ext = Path.parse(httpEvent.url.pathname).ext;
65
- // if is a directory search for index file matching the extention
66
- if (!ext && Fs.existsSync(filename) && Fs.lstatSync(filename).isDirectory()) {
67
- ext = '.html';
68
- index = `index${ext}`;
69
- filename = Path.join(filename, index);
70
- }
71
- let enc, acceptEncs = [], supportedEncs = { gzip: '.gz', br: '.br' };
72
- // based on the URL path, extract the file extention. e.g. .js, .doc, ...
73
- // and process encoding
74
- if ((acceptEncs = (httpEvent.request.headers.get('Accept-Encoding') || '').split(',').map(e => e.trim())).length
75
- && (enc = acceptEncs.reduce((prev, _enc) => prev || (Fs.existsSync(filename + supportedEncs[_enc]) && _enc), null))) {
76
- filename = filename + supportedEncs[enc];
77
- } else {
78
- if (!Fs.existsSync(filename)) return;
79
- if (Object.values(supportedEncs).includes(ext)) {
80
- enc = Object.keys(supportedEncs).reduce((prev, _enc) => prev || (supportedEncs[_enc] === ext && _enc), null);
81
- ext = Path.parse(filename.substring(0, filename.length - ext.length)).ext;
82
- }
83
- }
84
-
85
- // read file from file system
86
- return new Promise(resolve => {
87
- Fs.readFile(filename, function(err, data) {
88
- let response;
89
- if (err) {
90
- response = new httpEvent.Response(null, { status: 500, statusText: `Error reading static file: ${filename}` } );
91
- } else {
92
- // if the file is found, set Content-type and send data
93
- let mime = Mime.lookup(ext);
94
- response = new httpEvent.Response(data, { headers: {
95
- contentType: mime === 'application/javascript' ? 'text/javascript' : mime,
96
- contentLength: Buffer.byteLength(data),
97
- } });
98
- if (enc) {
99
- response.headers.set('Content-Encoding', enc);
100
- }
101
- }
102
- response.attrs.filename = filename;
103
- response.attrs.static = true;
104
- response.attrs.index = index;
105
- resolve(response);
106
- });
107
- });
108
- }
109
-
110
- /**
111
- * Writes a file to the public directory.
112
- *
113
- * @param object filename
114
- * @param string content
115
- *
116
- * @return bool
117
- */
118
- putPreRendered(filename, content) {
119
- var _filename = Path.join(this.cx.layout.PUBLIC_DIR, '.', filename);
120
- if (!Path.parse(filename).ext && filename.lastIndexOf('.') < filename.lastIndexOf('/')) {
121
- _filename = Path.join(_filename, '/index.html');
122
- }
123
- var dir = Path.dirname(_filename);
124
- if (!Fs.existsSync(dir)) {
125
- Fs.mkdirSync(dir, {recursive:true});
126
- }
127
- return Fs.writeFileSync(_filename, content);
128
- }
129
-
130
- /**
131
- * Deletes a file from the public directory.
132
- *
133
- * @param object filename
134
- *
135
- * @return bool
136
- */
137
- deletePreRendered(filename) {
138
- return Fs.unlinkSync(filename);
139
- }
140
- };
141
-
142
- // maps file extention to MIME typere
143
- const mimeTypes = {
144
- '.ico': 'image/x-icon',
145
- '.html': 'text/html',
146
- '.js': 'text/javascript',
147
- '.json': 'application/json',
148
- '.css': 'text/css',
149
- '.png': 'image/png',
150
- '.jpeg': 'image/jpeg',
151
- '.jpg': 'image/jpeg',
152
- '.wav': 'audio/wav',
153
- '.mp3': 'audio/mpeg',
154
- '.svg': 'image/svg+xml',
155
- '.pdf': 'application/pdf',
156
- '.doc': 'application/msword'
157
- };
158
-
159
- export { mimeTypes };
1
+ import Fs from 'fs';
2
+ import Url from 'url';
3
+ import Path from 'path';
4
+ import { WebfloRouter } from '../WebfloRouter.js';
5
+
6
+ export class Router extends WebfloRouter {
7
+
8
+ async readTick(thisTick) {
9
+ thisTick = { ...thisTick };
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
+ routeHandlerFile;
16
+ return Fs.existsSync(routeHandlerFile = Path.join(this.cx.CWD, this.cx.layout.SERVER_DIR, _currentPath, 'index.js')) ? { seg: _seg, index: routeHandlerFile } : (
17
+ Fs.existsSync(Path.join(this.cx.CWD, this.cx.layout.SERVER_DIR, _currentPath)) ? { seg: _seg, dirExists: true } : _segmentOnFile
18
+ );
19
+ }, { seg: null });
20
+ thisTick.trail = thisTick.trail.concat(thisTick.currentSegment);
21
+ thisTick.trailOnFile = thisTick.trailOnFile.concat(thisTick.currentSegmentOnFile.seg);
22
+ thisTick.exports = thisTick.currentSegmentOnFile.index ? await import(Url.pathToFileURL(thisTick.currentSegmentOnFile.index)) : undefined;
23
+ } else {
24
+ thisTick.trail = [];
25
+ thisTick.trailOnFile = [];
26
+ thisTick.currentSegmentOnFile = { index: Path.join(this.cx.CWD, this.cx.layout.SERVER_DIR, 'index.js') };
27
+ thisTick.exports = Fs.existsSync(thisTick.currentSegmentOnFile.index)
28
+ ? await import(Url.pathToFileURL(thisTick.currentSegmentOnFile.index))
29
+ : null;
30
+ }
31
+ return thisTick;
32
+ }
33
+
34
+ finalizeHandlerContext(context, thisTick) {
35
+ if (thisTick.currentSegmentOnFile.index) {
36
+ context.dirname = Path.dirname(thisTick.currentSegmentOnFile.index);
37
+ }
38
+ }
39
+
40
+ pathJoin(...args) {
41
+ return Path.join(...args);
42
+ }
43
+
44
+ /**
45
+ * Writes a file to the public directory.
46
+ *
47
+ * @param object filename
48
+ * @param string content
49
+ *
50
+ * @return bool
51
+ */
52
+ putPreRendered(filename, content) {
53
+ var _filename = Path.join(this.cx.layout.PUBLIC_DIR, '.', filename);
54
+ if (!Path.parse(filename).ext && filename.lastIndexOf('.') < filename.lastIndexOf('/')) {
55
+ _filename = Path.join(_filename, '/index.html');
56
+ }
57
+ var dir = Path.dirname(_filename);
58
+ if (!Fs.existsSync(dir)) {
59
+ Fs.mkdirSync(dir, {recursive:true});
60
+ }
61
+ return Fs.writeFileSync(_filename, content);
62
+ }
63
+
64
+ /**
65
+ * Deletes a file from the public directory.
66
+ *
67
+ * @param object filename
68
+ *
69
+ * @return bool
70
+ */
71
+ deletePreRendered(filename) {
72
+ return Fs.unlinkSync(filename);
73
+ }
74
+ };
75
+
76
+ // maps file extention to MIME typere
77
+ const mimeTypes = {
78
+ '.ico': 'image/x-icon',
79
+ '.html': 'text/html',
80
+ '.js': 'text/javascript',
81
+ '.json': 'application/json',
82
+ '.css': 'text/css',
83
+ '.png': 'image/png',
84
+ '.jpeg': 'image/jpeg',
85
+ '.jpg': 'image/jpeg',
86
+ '.wav': 'audio/wav',
87
+ '.mp3': 'audio/mpeg',
88
+ '.svg': 'image/svg+xml',
89
+ '.pdf': 'application/pdf',
90
+ '.doc': 'application/msword'
91
+ };
92
+
93
+ export { mimeTypes };
@@ -0,0 +1,53 @@
1
+ import { WebfloStorage } from '../WebfloStorage.js';
2
+ import crypto from 'crypto';
3
+
4
+ const sessionStorage = new Map;
5
+ export class SessionStorage extends WebfloStorage {
6
+
7
+ static create(request, params = {}) {
8
+ let sessionID = request.headers.get('Cookie', true).find((c) => c.name === '__sessid')?.value;
9
+ if (sessionID?.includes('.')) {
10
+ const [rand, signature] = sessionID.split('.');
11
+ const expectedSignature = crypto.createHmac('sha256', params.secret)
12
+ .update(rand)
13
+ .digest('hex');
14
+ if (signature !== expectedSignature) {
15
+ sessionID = undefined;
16
+ }
17
+ }
18
+ if (!sessionID) {
19
+ if (params.secret) {
20
+ const rand = `${(0 | Math.random() * 9e6).toString(36)}`;
21
+ const signature = crypto.createHmac('sha256', params.secret)
22
+ .update(rand)
23
+ .digest('hex');
24
+ sessionID = `${rand}.${signature}`
25
+ } else {
26
+ sessionID = crypto.randomUUID();
27
+ }
28
+ }
29
+ if (sessionStorage.has(sessionID)) {
30
+ return sessionStorage.get(sessionID);
31
+ }
32
+ const instance = new this(request, sessionID);
33
+ sessionStorage.set(sessionID, instance);
34
+ return instance;
35
+ }
36
+
37
+ constructor(request, sessionID) {
38
+ super(request, true);
39
+ this.#sessionID = sessionID;
40
+ }
41
+
42
+ #sessionID;
43
+ get sessionID() {
44
+ return this.#sessionID;
45
+ }
46
+
47
+ commit(response, force = false) {
48
+ if (response.headers.get('Set-Cookie', true).find((c) => c.name === '__sessid')) return;
49
+ if (!force && !this.getAdded().length && !this.getDeleted().length) return;
50
+ response.headers.append('Set-Cookie', `__sessid=${this.#sessionID}; Path=/; Secure; HttpOnly; SameSite=Lax; Max-Age=31536000`);
51
+ super.commit();
52
+ }
53
+ }