@webqit/webflo 0.11.61-0 → 0.20.1

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 (274) hide show
  1. package/.github/FUNDING.yml +12 -0
  2. package/.github/workflows/publish.yml +48 -0
  3. package/.gitignore +9 -7
  4. package/LICENSE +21 -21
  5. package/README.md +100 -2074
  6. package/docker/Dockerfile +42 -42
  7. package/docker/README.md +91 -91
  8. package/docker/package.json +2 -2
  9. package/package.json +95 -81
  10. package/site/-/_.md +139 -0
  11. package/site/-/docs.old.md +2010 -0
  12. package/site/.vitepress/cache/deps/@braintree_sanitize-url 2.js +93 -0
  13. package/site/.vitepress/cache/deps/@braintree_sanitize-url.js +93 -0
  14. package/site/.vitepress/cache/deps/@braintree_sanitize-url.js 2.map +7 -0
  15. package/site/.vitepress/cache/deps/@braintree_sanitize-url.js.map +7 -0
  16. package/site/.vitepress/cache/deps/_metadata 2.json +85 -0
  17. package/site/.vitepress/cache/deps/_metadata.json +85 -0
  18. package/site/.vitepress/cache/deps/chunk-BUSYA2B4 2.js +9 -0
  19. package/site/.vitepress/cache/deps/chunk-BUSYA2B4.js +9 -0
  20. package/site/.vitepress/cache/deps/chunk-BUSYA2B4.js 2.map +7 -0
  21. package/site/.vitepress/cache/deps/chunk-BUSYA2B4.js.map +7 -0
  22. package/site/.vitepress/cache/deps/chunk-Q2AYPHVK 2.js +9719 -0
  23. package/site/.vitepress/cache/deps/chunk-Q2AYPHVK.js +9719 -0
  24. package/site/.vitepress/cache/deps/chunk-Q2AYPHVK.js 2.map +7 -0
  25. package/site/.vitepress/cache/deps/chunk-Q2AYPHVK.js.map +7 -0
  26. package/site/.vitepress/cache/deps/chunk-QAXAIFA7 2.js +12705 -0
  27. package/site/.vitepress/cache/deps/chunk-QAXAIFA7.js +12705 -0
  28. package/site/.vitepress/cache/deps/chunk-QAXAIFA7.js 2.map +7 -0
  29. package/site/.vitepress/cache/deps/chunk-QAXAIFA7.js.map +7 -0
  30. package/site/.vitepress/cache/deps/cytoscape 2.js +30278 -0
  31. package/site/.vitepress/cache/deps/cytoscape-cose-bilkent 2.js +4710 -0
  32. package/site/.vitepress/cache/deps/cytoscape-cose-bilkent.js +4710 -0
  33. package/site/.vitepress/cache/deps/cytoscape-cose-bilkent.js 2.map +7 -0
  34. package/site/.vitepress/cache/deps/cytoscape-cose-bilkent.js.map +7 -0
  35. package/site/.vitepress/cache/deps/cytoscape.js +30278 -0
  36. package/site/.vitepress/cache/deps/cytoscape.js 2.map +7 -0
  37. package/site/.vitepress/cache/deps/cytoscape.js.map +7 -0
  38. package/site/.vitepress/cache/deps/dayjs 2.js +285 -0
  39. package/site/.vitepress/cache/deps/dayjs.js +285 -0
  40. package/site/.vitepress/cache/deps/dayjs.js 2.map +7 -0
  41. package/site/.vitepress/cache/deps/dayjs.js.map +7 -0
  42. package/site/.vitepress/cache/deps/debug 2.js +453 -0
  43. package/site/.vitepress/cache/deps/debug.js +453 -0
  44. package/site/.vitepress/cache/deps/debug.js 2.map +7 -0
  45. package/site/.vitepress/cache/deps/debug.js.map +7 -0
  46. package/site/.vitepress/cache/deps/package 2.json +3 -0
  47. package/site/.vitepress/cache/deps/package.json +3 -0
  48. package/site/.vitepress/cache/deps/vitepress___@vue_devtools-api 2.js +4507 -0
  49. package/site/.vitepress/cache/deps/vitepress___@vue_devtools-api.js +4507 -0
  50. package/site/.vitepress/cache/deps/vitepress___@vue_devtools-api.js 2.map +7 -0
  51. package/site/.vitepress/cache/deps/vitepress___@vue_devtools-api.js.map +7 -0
  52. package/site/.vitepress/cache/deps/vitepress___@vueuse_core 2.js +584 -0
  53. package/site/.vitepress/cache/deps/vitepress___@vueuse_core.js +584 -0
  54. package/site/.vitepress/cache/deps/vitepress___@vueuse_core.js 2.map +7 -0
  55. package/site/.vitepress/cache/deps/vitepress___@vueuse_core.js.map +7 -0
  56. package/site/.vitepress/cache/deps/vitepress___@vueuse_integrations_useFocusTrap 2.js +1166 -0
  57. package/site/.vitepress/cache/deps/vitepress___@vueuse_integrations_useFocusTrap.js +1166 -0
  58. package/site/.vitepress/cache/deps/vitepress___@vueuse_integrations_useFocusTrap.js 2.map +7 -0
  59. package/site/.vitepress/cache/deps/vitepress___@vueuse_integrations_useFocusTrap.js.map +7 -0
  60. package/site/.vitepress/cache/deps/vitepress___mark__js_src_vanilla__js 2.js +1667 -0
  61. package/site/.vitepress/cache/deps/vitepress___mark__js_src_vanilla__js.js +1667 -0
  62. package/site/.vitepress/cache/deps/vitepress___mark__js_src_vanilla__js.js 2.map +7 -0
  63. package/site/.vitepress/cache/deps/vitepress___mark__js_src_vanilla__js.js.map +7 -0
  64. package/site/.vitepress/cache/deps/vitepress___minisearch 2.js +1815 -0
  65. package/site/.vitepress/cache/deps/vitepress___minisearch.js +1815 -0
  66. package/site/.vitepress/cache/deps/vitepress___minisearch.js 2.map +7 -0
  67. package/site/.vitepress/cache/deps/vitepress___minisearch.js.map +7 -0
  68. package/site/.vitepress/cache/deps/vue 2.js +344 -0
  69. package/site/.vitepress/cache/deps/vue.js +344 -0
  70. package/site/.vitepress/cache/deps/vue.js 2.map +7 -0
  71. package/site/.vitepress/cache/deps/vue.js.map +7 -0
  72. package/site/.vitepress/config.ts +147 -0
  73. package/site/.vitepress/theme/custom.css +50 -0
  74. package/site/.vitepress/theme/index.ts +6 -0
  75. package/site/api/webflo-fetch/FormData.md +0 -0
  76. package/site/api/webflo-fetch/Headers.md +0 -0
  77. package/site/api/webflo-fetch/LiveResponse.md +0 -0
  78. package/site/api/webflo-fetch/Request.md +0 -0
  79. package/site/api/webflo-fetch/Response.md +0 -0
  80. package/site/api/webflo-fetch/fetch.md +0 -0
  81. package/site/api/webflo-routing/HttpCookies.md +0 -0
  82. package/site/api/webflo-routing/HttpEvent/respondWith.md +1 -0
  83. package/site/api/webflo-routing/HttpEvent/waitUntil.md +1 -0
  84. package/site/api/webflo-routing/HttpEvent/waitUntilNavigate.md +1 -0
  85. package/site/api/webflo-routing/HttpEvent.md +30 -0
  86. package/site/api/webflo-routing/HttpSession.md +0 -0
  87. package/site/api/webflo-routing/HttpState.md +0 -0
  88. package/site/api/webflo-routing/HttpUser.md +0 -0
  89. package/site/api/webflo-routing/handler/fetch.md +42 -0
  90. package/site/api/webflo-routing/handler/next.md +54 -0
  91. package/site/api/webflo-routing/handler.md +119 -0
  92. package/site/api.md +26 -0
  93. package/site/contributing.md +16 -0
  94. package/site/docs/advanced/lifecycles.md +20 -0
  95. package/site/docs/advanced/redirects.md +0 -0
  96. package/site/docs/advanced/routing.md +1 -0
  97. package/site/docs/advanced.md +9 -0
  98. package/site/docs/concepts/realtime.md +637 -0
  99. package/site/docs/concepts/rendering.md +60 -0
  100. package/site/docs/concepts/request-response.md +47 -0
  101. package/site/docs/concepts/routing.md +656 -0
  102. package/site/docs/concepts/state.md +44 -0
  103. package/site/docs/concepts/templates.md +48 -0
  104. package/site/docs/concepts.md +97 -0
  105. package/site/docs/getting-started.md +378 -0
  106. package/site/docs/tech-stack.md +56 -0
  107. package/site/docs.md +100 -0
  108. package/site/examples/pwa.md +10 -0
  109. package/site/examples/web.md +11 -0
  110. package/site/examples.md +10 -0
  111. package/site/faq.md +13 -0
  112. package/site/guides/guide-auth.md +13 -0
  113. package/site/guides/guide-file-upload.md +11 -0
  114. package/site/guides/guide-service-worker.md +10 -0
  115. package/site/guides/tutorial-1-todo.md +24 -0
  116. package/site/guides.md +15 -0
  117. package/site/index.md +39 -0
  118. package/site/public/img/brand/logo-670x670.png +0 -0
  119. package/site/recipes/realtime.md +11 -0
  120. package/site/recipes/streaming.md +15 -0
  121. package/site/reference/cli.md +11 -0
  122. package/site/reference/config.md +13 -0
  123. package/site/reference/tools.md +9 -0
  124. package/src/Context.js +71 -79
  125. package/src/config-pi/deployment/Env.js +55 -68
  126. package/src/config-pi/deployment/Layout.js +71 -63
  127. package/src/config-pi/deployment/Origins.js +139 -139
  128. package/src/config-pi/deployment/Proxy.js +74 -74
  129. package/src/config-pi/deployment/index.js +17 -17
  130. package/src/config-pi/index.js +15 -15
  131. package/src/config-pi/runtime/Client.js +108 -98
  132. package/src/config-pi/runtime/Server.js +157 -125
  133. package/src/config-pi/runtime/client/Worker.js +111 -134
  134. package/src/config-pi/runtime/client/index.js +11 -11
  135. package/src/config-pi/runtime/index.js +17 -17
  136. package/src/config-pi/runtime/server/Headers.js +74 -74
  137. package/src/config-pi/runtime/server/Redirects.js +69 -69
  138. package/src/config-pi/runtime/server/index.js +13 -13
  139. package/src/config-pi/static/Init.js +57 -0
  140. package/src/config-pi/static/Manifest.js +319 -319
  141. package/src/config-pi/static/Ssg.js +49 -49
  142. package/src/config-pi/static/index.js +15 -13
  143. package/src/deployment-pi/index.js +10 -10
  144. package/src/deployment-pi/origins/index.js +216 -216
  145. package/src/deployment-pi/util.js +161 -0
  146. package/src/index.js +13 -19
  147. package/src/init-pi/index.js +117 -0
  148. package/src/init-pi/templates/pwa/app/handler.server.js +8 -0
  149. package/src/init-pi/templates/pwa/app/page.html +7 -0
  150. package/src/init-pi/templates/pwa/package.json +19 -0
  151. package/src/init-pi/templates/pwa/public/assets/app.css +16 -0
  152. package/src/init-pi/templates/pwa/public/index.html +39 -0
  153. package/src/init-pi/templates/pwa/public/manifest.json +29 -0
  154. package/src/init-pi/templates/web/app/handler.server.js +8 -0
  155. package/src/init-pi/templates/web/app/page.html +7 -0
  156. package/src/init-pi/templates/web/package.json +19 -0
  157. package/src/init-pi/templates/web/public/assets/app.css +16 -0
  158. package/src/init-pi/templates/web/public/index.html +39 -0
  159. package/src/runtime-pi/WebfloRuntime.js +350 -0
  160. package/src/runtime-pi/index.js +6 -13
  161. package/src/runtime-pi/webflo-client/ClientSideCookies.js +17 -0
  162. package/src/runtime-pi/webflo-client/ClientSideWorkport.js +63 -0
  163. package/src/runtime-pi/webflo-client/DeviceCapabilities.js +213 -0
  164. package/src/runtime-pi/webflo-client/WebfloClient.js +500 -0
  165. package/src/runtime-pi/webflo-client/WebfloRootClient1.js +206 -0
  166. package/src/runtime-pi/webflo-client/WebfloRootClient2.js +113 -0
  167. package/src/runtime-pi/webflo-client/WebfloSubClient.js +118 -0
  168. package/src/runtime-pi/webflo-client/index.js +17 -0
  169. package/src/runtime-pi/webflo-client/webflo-codegen.js +469 -0
  170. package/src/runtime-pi/webflo-client/webflo-devmode.js +243 -0
  171. package/src/runtime-pi/webflo-client/webflo-embedded.js +50 -0
  172. package/src/runtime-pi/webflo-fetch/LiveResponse.js +437 -0
  173. package/src/runtime-pi/webflo-fetch/cookies.js +10 -0
  174. package/src/runtime-pi/webflo-fetch/fetch.js +16 -0
  175. package/src/runtime-pi/webflo-fetch/formdata.js +54 -0
  176. package/src/runtime-pi/webflo-fetch/headers.js +151 -0
  177. package/src/runtime-pi/webflo-fetch/index.js +5 -0
  178. package/src/runtime-pi/webflo-fetch/message.js +49 -0
  179. package/src/runtime-pi/webflo-fetch/request.js +62 -0
  180. package/src/runtime-pi/webflo-fetch/response.js +110 -0
  181. package/src/runtime-pi/webflo-fetch/util.js +28 -0
  182. package/src/runtime-pi/webflo-messaging/WQBroadcastChannel.js +10 -0
  183. package/src/runtime-pi/webflo-messaging/WQMessageChannel.js +26 -0
  184. package/src/runtime-pi/webflo-messaging/WQMessageEvent.js +87 -0
  185. package/src/runtime-pi/webflo-messaging/WQMessagePort.js +38 -0
  186. package/src/runtime-pi/webflo-messaging/WQRelayPort.js +47 -0
  187. package/src/runtime-pi/webflo-messaging/WQSockPort.js +113 -0
  188. package/src/runtime-pi/webflo-messaging/WQStarPort.js +104 -0
  189. package/src/runtime-pi/webflo-messaging/wq-message-port.js +404 -0
  190. package/src/runtime-pi/webflo-routing/HttpCookies.js +42 -0
  191. package/src/runtime-pi/webflo-routing/HttpEvent.js +112 -0
  192. package/src/runtime-pi/webflo-routing/HttpSession.js +11 -0
  193. package/src/runtime-pi/webflo-routing/HttpState.js +153 -0
  194. package/src/runtime-pi/webflo-routing/HttpUser.js +54 -0
  195. package/src/runtime-pi/webflo-routing/WebfloRouter.js +245 -0
  196. package/src/runtime-pi/webflo-server/ServerSideCookies.js +19 -0
  197. package/src/runtime-pi/webflo-server/ServerSideSession.js +38 -0
  198. package/src/runtime-pi/webflo-server/WebfloServer.js +937 -0
  199. package/src/runtime-pi/webflo-server/index.js +11 -0
  200. package/src/runtime-pi/webflo-server/messaging/Client.js +27 -0
  201. package/src/runtime-pi/webflo-server/messaging/ClientRequestRealtime.js +50 -0
  202. package/src/runtime-pi/webflo-server/messaging/Clients.js +25 -0
  203. package/src/runtime-pi/webflo-server/webflo-devmode.js +326 -0
  204. package/src/runtime-pi/{client → webflo-url}/Url.js +155 -205
  205. package/src/runtime-pi/webflo-url/index.js +1 -0
  206. package/src/runtime-pi/webflo-url/urlpattern.js +38 -0
  207. package/src/runtime-pi/{util-url.js → webflo-url/util.js} +109 -147
  208. package/src/runtime-pi/webflo-url/xURL.js +94 -0
  209. package/src/runtime-pi/webflo-worker/WebfloWorker.js +234 -0
  210. package/src/runtime-pi/webflo-worker/WorkerSideCookies.js +19 -0
  211. package/src/runtime-pi/webflo-worker/WorkerSideWorkport.js +18 -0
  212. package/src/runtime-pi/webflo-worker/index.js +11 -0
  213. package/src/services-pi/cert/http-auth-hook.js +22 -22
  214. package/src/services-pi/cert/http-cleanup-hook.js +22 -22
  215. package/src/services-pi/cert/index.js +79 -79
  216. package/src/services-pi/index.js +10 -8
  217. package/src/services-pi/push/index.js +23 -0
  218. package/src/util.js +10 -0
  219. package/src/{webflo.js → webflo-cli.js} +30 -30
  220. package/test/index.test.js +26 -26
  221. package/test/site/package.json +9 -9
  222. package/test/site/public/bundle.html +5 -5
  223. package/test/site/public/bundle.html.json +3 -3
  224. package/test/site/public/bundle.js +2 -2
  225. package/test/site/public/bundle.webflo.js +15 -15
  226. package/test/site/public/index.html +29 -29
  227. package/test/site/public/index1.html +34 -34
  228. package/test/site/public/page-2/bundle.html +4 -4
  229. package/test/site/public/page-2/bundle.js +2 -2
  230. package/test/site/public/page-2/index.html +45 -45
  231. package/test/site/public/page-2/main.html +2 -2
  232. package/test/site/public/page-4/subpage/bundle.js +2 -2
  233. package/test/site/public/page-4/subpage/index.html +30 -30
  234. package/test/site/public/sparoots.json +4 -4
  235. package/test/site/public/worker.js +3 -3
  236. package/test/site/server/index.js +15 -15
  237. package/src/runtime-pi/Application.js +0 -29
  238. package/src/runtime-pi/Cookies.js +0 -82
  239. package/src/runtime-pi/HttpEvent.js +0 -107
  240. package/src/runtime-pi/Router.js +0 -130
  241. package/src/runtime-pi/Runtime.js +0 -21
  242. package/src/runtime-pi/client/Application.js +0 -100
  243. package/src/runtime-pi/client/Context.js +0 -7
  244. package/src/runtime-pi/client/Router.js +0 -48
  245. package/src/runtime-pi/client/Runtime.js +0 -332
  246. package/src/runtime-pi/client/Workport.js +0 -178
  247. package/src/runtime-pi/client/createStorage.js +0 -57
  248. package/src/runtime-pi/client/generate.js +0 -472
  249. package/src/runtime-pi/client/index.js +0 -21
  250. package/src/runtime-pi/client/oohtml/full.js +0 -7
  251. package/src/runtime-pi/client/oohtml/namespacing.js +0 -7
  252. package/src/runtime-pi/client/oohtml/scripting.js +0 -8
  253. package/src/runtime-pi/client/oohtml/templating.js +0 -8
  254. package/src/runtime-pi/client/worker/Application.js +0 -44
  255. package/src/runtime-pi/client/worker/Context.js +0 -7
  256. package/src/runtime-pi/client/worker/Runtime.js +0 -269
  257. package/src/runtime-pi/client/worker/Workport.js +0 -86
  258. package/src/runtime-pi/client/worker/index.js +0 -21
  259. package/src/runtime-pi/server/Application.js +0 -116
  260. package/src/runtime-pi/server/Context.js +0 -16
  261. package/src/runtime-pi/server/Router.js +0 -159
  262. package/src/runtime-pi/server/Runtime.js +0 -557
  263. package/src/runtime-pi/server/index.js +0 -21
  264. package/src/runtime-pi/util-http.js +0 -86
  265. package/src/runtime-pi/xFormData.js +0 -24
  266. package/src/runtime-pi/xHeaders.js +0 -146
  267. package/src/runtime-pi/xRequest.js +0 -46
  268. package/src/runtime-pi/xRequestHeaders.js +0 -109
  269. package/src/runtime-pi/xResponse.js +0 -33
  270. package/src/runtime-pi/xResponseHeaders.js +0 -117
  271. package/src/runtime-pi/xURL.js +0 -105
  272. package/src/runtime-pi/xfetch.js +0 -23
  273. package/src/runtime-pi/xxHttpMessage.js +0 -102
  274. package/src/static-pi/index.js +0 -11
@@ -1,269 +0,0 @@
1
-
2
- /**
3
- * @imports
4
- */
5
- import { _any } from '@webqit/util/arr/index.js';
6
- import { Observer } from '@webqit/oohtml-ssr/apis.js';
7
- import { pattern } from '../../util-url.js';
8
- import Workport from './Workport.js';
9
- import _Runtime from '../../Runtime.js';
10
- import xRequest from "../../xRequest.js";
11
- import xResponse from "../../xResponse.js";
12
- import xfetch from '../../xfetch.js';
13
- import HttpEvent from '../../HttpEvent.js';
14
-
15
- export {
16
- HttpEvent,
17
- Observer,
18
- }
19
-
20
- /**
21
- * ---------------------------
22
- * The Runtime Initializer
23
- * ---------------------------
24
- */
25
-
26
- export default class Runtime extends _Runtime {
27
-
28
- /**
29
- * Runtime
30
- *
31
- * @param Object cx
32
- * @param Function applicationInstance
33
- *
34
- * @return void
35
- */
36
- constructor(cx, applicationInstance) {
37
- super(cx, applicationInstance);
38
- // ---------------
39
- this.mockSessionStore = {};
40
- // --------------
41
- // ONINSTALL
42
- self.addEventListener('install', evt => {
43
- if (this.cx.params.skip_waiting) { self.skipWaiting(); }
44
- // Manage CACHE
45
- if (this.cx.params.cache_name && (this.cx.params.cache_only_urls || []).length) {
46
- // Add files to cache
47
- evt.waitUntil( self.caches.open(this.cx.params.cache_name).then(cache => {
48
- if (this.cx.logger) { this.cx.logger.log('[ServiceWorker] Pre-caching resources.'); }
49
- const cache_only_urls = (this.cx.params.cache_only_urls || []).map(c => c.trim()).filter(c => c && !pattern(c, self.origin).isPattern());
50
- return cache.addAll(cache_only_urls);
51
- }) );
52
- }
53
- });
54
-
55
- // -------------
56
- // ONACTIVATE
57
- self.addEventListener('activate', evt => {
58
- evt.waitUntil( new Promise(async resolve => {
59
- if (this.cx.params.skip_waiting) { await self.clients.claim(); }
60
- // Manage CACHE
61
- if (this.cx.params.cache_name) {
62
- // Clear outdated CACHES
63
- await self.caches.keys().then(keyList => {
64
- return Promise.all(keyList.map(key => {
65
- if (key !== this.cx.params.cache_name && key !== this.cx.params.cache_name + '_json') {
66
- if (this.cx.logger) { this.cx.logger.log('[ServiceWorker] Removing old cache:', key); }
67
- return self.caches.delete(key);
68
- }
69
- }));
70
- })
71
- }
72
- resolve();
73
- }) );
74
- });
75
-
76
- // ---------------
77
- Observer.set(this, 'location', {});
78
- Observer.set(this, 'network', {});
79
- // ---------------
80
- Observer.observe(this.network, es => {
81
- //console.log('//////////', ...es.map(e => `${e.name}: ${e.value}`))
82
- });
83
-
84
- // -------------
85
- // ONFETCH
86
- self.addEventListener('fetch', event => {
87
- // URL schemes that might arrive here but not supported; e.g.: chrome-extension://
88
- if (!event.request.url.startsWith('http')) return;
89
- event.respondWith((async evt => {
90
- let requestingClient = await self.clients.get(evt.clientId);
91
- this.workport.setCurrentClient(requestingClient);
92
- const [ url, requestInit ] = await xRequest.rip(evt.request);
93
- // Now, the following is key:
94
- // The browser likes to use "force-cache" for "navigate" requests, when, e.g: re-entering your site with the back button
95
- // Problem here, force-cache forces out JSON not HTML as per webflo's design.
96
- // So, we detect this scenerio and avoid it.
97
- if (requestInit.cache === 'force-cache'/* && evt.request.mode === 'navigate' - even webflo client init call also comes with that... needs investigation */) {
98
- requestInit.cache = 'default';
99
- }
100
- return this.go(url, requestInit, { event: evt });
101
- })(event));
102
- });
103
-
104
- // -------------
105
- // Workport
106
- const workport = new Workport();
107
- Observer.set(this, 'workport', workport);
108
-
109
- // -------------
110
- // Initialize
111
- (async () => {
112
- if (!this.app.init) return;
113
- const request = this.generateRequest('/');
114
- const httpEvent = new HttpEvent(request, { srcType: 'initialization' }, (id = null, persistent = false) => this.getSession(httpEvent, id, persistent));
115
- await this.app.init(httpEvent, ( ...args ) => this.remoteFetch( ...args ));
116
- })();
117
-
118
- }
119
-
120
- /**
121
- * Performs a request.
122
- *
123
- * @param object|string url
124
- * @param object|Request init
125
- * @param object detail
126
- *
127
- * @return Response
128
- */
129
- async go(url, init = {}, detail = {}) {
130
- // ------------
131
- url = typeof url === 'string' ? new URL(url, self.location.origin) : url;
132
- if (!(init instanceof Request) && !init.referrer) {
133
- init = { referrer: this.location.href, ...init };
134
- }
135
- // ------------
136
- // The request object
137
- const request = this.generateRequest(url.href, init);
138
- if (detail.event) { Object.defineProperty(detail.event, 'request', { value: request }); }
139
- // The navigation event
140
- const httpEvent = new HttpEvent(request, detail, (id = null, persistent = false) => this.getSession(httpEvent, id, persistent));
141
- httpEvent.port.listen(message => {
142
- if (message.$type === 'handler:hints' && message.session) {
143
- // TODO: Sync session data from client
144
- return Promise.resolve();
145
- }
146
- });
147
- // Response
148
- let response;
149
- if (httpEvent.request.url.startsWith(self.origin)/* && httpEvent.request.mode === 'navigate'*/) {
150
- response = await this.app.handle(httpEvent, ( ...args ) => this.remoteFetch( ...args ));
151
- } else {
152
- response = await this.remoteFetch(httpEvent.request);
153
- }
154
- const finalResponse = await this.handleResponse(httpEvent, response);
155
- // Return value
156
- return finalResponse;
157
- }
158
-
159
- // Generates request object
160
- generateRequest(href, init = {}) {
161
- const request = new xRequest(href, init);
162
- return request;
163
- }
164
-
165
- // Generates session object
166
- getSession(e, id = null, persistent = false) {
167
- return {
168
- get: () => this.mockSessionStore,
169
- set: value => { this.mockSessionStore = value },
170
- };
171
- }
172
-
173
- // Initiates remote fetch and sets the status
174
- remoteFetch(request, ...args) {
175
- if (arguments.length > 1) {
176
- request = this.generateRequest(request, ...args);
177
- }
178
- const matchUrl = (patterns, url) => _any((patterns || []).map(p => p.trim()).filter(p => p), p => pattern(p, self.origin).test(url));
179
- const execFetch = () => {
180
- // network_first_urls
181
- if (!this.cx.params.default_fetching_strategy || this.cx.params.default_fetching_strategy === 'network-first' || matchUrl(this.cx.params.network_first_urls, request.url)) {
182
- Observer.set(this.network, 'strategy', 'network-first');
183
- return this.networkFetch(request, { cacheFallback: true, cacheRefresh: true });
184
- }
185
- // cache_first_urls
186
- if (this.cx.params.default_fetching_strategy === 'cache-first' || matchUrl(this.cx.params.cache_first_urls, request.url)) {
187
- Observer.set(this.network, 'strategy', 'cache-first');
188
- return this.cacheFetch(request, { networkFallback: true, cacheRefresh: true });
189
- }
190
- // network_only_urls
191
- if (this.cx.params.default_fetching_strategy === 'network-only' || matchUrl(this.cx.params.network_only_urls, request.url)) {
192
- Observer.set(this.network, 'strategy', 'network-only');
193
- return this.networkFetch(request, { cacheFallback: false, cacheRefresh: false });
194
- }
195
- // cache_only_urls
196
- if (this.cx.params.default_fetching_strategy === 'cache-only' || matchUrl(this.cx.params.cache_only_urls, request.url)) {
197
- Observer.set(this.network, 'strategy', 'cache-only');
198
- return this.cacheFetch(request, { networkFallback: false, cacheRefresh: false });
199
- }
200
- };
201
- let response = execFetch(request);
202
- // This catch() is NOT intended to handle failure of the fetch
203
- response.catch(e => Observer.set(this.network, 'error', e.message));
204
- // Return xResponse
205
- return response.then(_response => xResponse.compat(_response));
206
- }
207
-
208
- // Caching strategy: network_first
209
- networkFetch(request, params = {}) {
210
- if (!params.cacheFallback) {
211
- Observer.set(this.network, 'remote', true);
212
- return xfetch(request);
213
- }
214
- return xfetch(request).then(response => {
215
- if (params.cacheRefresh) this.refreshCache(request, response);
216
- Observer.set(this.network, 'remote', true);
217
- return response;
218
- }).catch(() => this.getRequestCache(request).then(cache => {
219
- Observer.set(this.network, 'cache', true);
220
- return cache.match(request);
221
- }));
222
- }
223
-
224
- // Caching strategy: cache_first
225
- cacheFetch(request, params = {}) {
226
- return this.getRequestCache(request).then(cache => cache.match(request).then(response => {
227
- // Nothing cache, use network
228
- if (!response && params.networkFallback) return this.networkFetch(request, { ...params, cacheFallback: false });
229
- // Note: fetch, but for refreshing purposes only... not the returned response
230
- if (response && params.cacheRefresh) this.networkFetch(request, { ...params, justRefreshing: true });
231
- Observer.set(this.network, 'cache', true);
232
- return response;
233
- }));
234
- }
235
-
236
- // Caches response
237
- refreshCache(request, response) {
238
- // Check if we received a valid response
239
- if (request.method !== 'GET' || !response || response.status !== 200 || (response.type !== 'basic' && response.type !== 'cors')) {
240
- return response;
241
- }
242
- // IMPORTANT: Clone the response. A response is a stream
243
- // and because we want the browser to consume the response
244
- // as well as the cache consuming the response, we need
245
- // to clone it so we have two streams.
246
- var responseToCache = response.clone();
247
- this.getRequestCache(request).then(cache => {
248
- Observer.set(this.network, 'cacheRefresh', true);
249
- cache.put(request, responseToCache);
250
- });
251
- return response;
252
- }
253
-
254
- // Returns either the regular cache or a json-specific cache
255
- getRequestCache(request) {
256
- let cacheName = request.headers.get('Accept') === 'application/json'
257
- ? this.cx.params.cache_name + '_json'
258
- : this.cx.params.cache_name;
259
- return self.caches.open(cacheName);
260
- }
261
-
262
- // Handles response object
263
- handleResponse(e, response) {
264
- if (!response && response !== 0) { response = new xResponse(null, { status: 404 }); }
265
- else if (!(response instanceof xResponse)) { response = xResponse.compat(response); }
266
- return response;
267
- }
268
-
269
- }
@@ -1,86 +0,0 @@
1
-
2
- export default class Workport {
3
-
4
- constructor() {
5
- // --------
6
- // Post messaging
7
- // --------
8
- this.messaging = {
9
- post: (message, client = this.client) => {
10
- if (!client) throw new Error(`No client for this operation.`);
11
- client.postMessage(message);
12
- return this.post;
13
- },
14
- listen: (callback, client = this.client) => {
15
- (client || self).addEventListener('message', evt => {
16
- this.client = evt.source;
17
- const response = callback(evt);
18
- let responsePort = evt.ports[0];
19
- if (responsePort) {
20
- if (response instanceof Promise) {
21
- response.then(data => {
22
- responsePort.postMessage(data);
23
- });
24
- } else {
25
- responsePort.postMessage(response);
26
- }
27
- }
28
- });
29
- return this.post;
30
- },
31
- request: (message, client = this.client) => {
32
- if (!client) throw new Error(`No client for this operation.`);
33
- return new Promise(res => {
34
- let messageChannel = new MessageChannel();
35
- client.postMessage(message, [ messageChannel.port2 ]);
36
- messageChannel.port1.onmessage = e => res(e.data);
37
- });
38
- },
39
- channel(channelId) {
40
- if (!this.channels.has(channelId)) { this.channels.set(channelId, new BroadcastChannel(channel)); }
41
- let channel = this.channels.get(channelId);
42
- return {
43
- broadcast: message => channel.postMessage(message),
44
- listen: callback => channel.addEventListener('message', callback),
45
- };
46
- },
47
- channels: new Map,
48
- };
49
-
50
- // --------
51
- // Notifications
52
- // --------
53
- this.notifications = {
54
- fire: (title, params = {}) => {
55
- return new Promise((res, rej) => {
56
- if (!(self.Notification && self.Notification.permission === 'granted')) {
57
- return rej(self.Notification && self.Notification.permission);
58
- }
59
- notification.addEventListener('error', rej);
60
- let notification = new self.Notification(title, params);
61
- notification.addEventListener('click', res);
62
- notification.addEventListener('close', res);
63
- });
64
- },
65
- handle: callback => {
66
- self.addEventListener('notificationclick', callback);
67
- return this.notifications;
68
- },
69
- };
70
-
71
- // --------
72
- // Push Notifications
73
- // --------
74
- this.push = {
75
- listen: callback => {
76
- self.addEventListener('push', callback);
77
- return this.post;
78
- },
79
- };
80
- }
81
-
82
- setCurrentClient(client) {
83
- this.client = client;
84
- }
85
-
86
- }
@@ -1,21 +0,0 @@
1
-
2
- /**
3
- * @imports
4
- */
5
- import Context from './Context.js';
6
- import Application from './Application.js';
7
- import Runtime from './Runtime.js';
8
-
9
- /**
10
- * @start
11
- */
12
- export async function start(applicationInstance = null) {
13
- const cx = this || {};
14
- const defaultApplicationInstance = _cx => new Application(_cx);
15
- return new Runtime(Context.create(cx), applicationInstance || defaultApplicationInstance);
16
- }
17
-
18
- /**
19
- * @APIS
20
- */
21
- export * as APIS from './Runtime.js';
@@ -1,116 +0,0 @@
1
-
2
- /**
3
- * imports
4
- */
5
- import Fs from 'fs';
6
- import Path from 'path';
7
- import QueryString from 'querystring';
8
- import Router from './Router.js';
9
- import _Application from '../Application.js';
10
-
11
- export default class Application extends _Application {
12
-
13
- /**
14
- * Application
15
- *
16
- * @param Context cx
17
- */
18
- constructor(cx) {
19
- super(cx);
20
- this.renderFileCache = {};
21
- }
22
-
23
- // Returns router class
24
- get Router() {
25
- return Router;
26
- }
27
-
28
- /**
29
- * Handles navigation events.
30
- *
31
- * @param NavigationEvent httpEvent
32
- * @param Function remoteFetch
33
- *
34
- * @return Response
35
- */
36
- async handle(httpEvent, remoteFetch) {
37
- // The app router
38
- const router = new this.Router(this.cx, httpEvent.url.pathname);
39
- const handle = async () => {
40
- // --------
41
- // ROUTE FOR DATA
42
- // --------
43
- let response = await router.route([httpEvent.request.method, 'default'], httpEvent, {}, async event => {
44
- return router.file(event);
45
- }, remoteFetch);
46
- if (!(response instanceof httpEvent.Response)) {
47
- response = httpEvent.Response.compat(response);
48
- }
49
- // --------
50
- // Rendering
51
- // --------
52
- if (response.ok && response.meta.type === 'json' && typeof response.meta.body === 'object' && response.meta.body && httpEvent.request.headers.accept.match('text/html')) {
53
- let rendering = await this.render(httpEvent, router, response);
54
- if (typeof rendering !== 'string' && !(typeof rendering === 'object' && rendering && typeof rendering.toString === 'function')) {
55
- throw new Error('render() must return a string response or an object that implements toString()..');
56
- }
57
- rendering = rendering.toString();
58
- response = new httpEvent.Response(rendering, {
59
- headers: { ...response.headers.json(), contentType: 'text/html', contentLength: (new Blob([rendering]).size) },
60
- status: response.status,
61
- });
62
- }
63
-
64
- return response;
65
- };
66
- // --------
67
- // PIPE THROUGH MIDDLEWARES
68
- // --------
69
- return (this.cx.middlewares || []).concat(handle).reverse().reduce((next, fn) => {
70
- return () => fn.call(this.cx, httpEvent, router, next);
71
- }, null)();
72
- }
73
-
74
- // Renderer
75
- async render(httpEvent, router, response) {
76
- let data = await response.jsonfy();
77
- let rendering = await router.route('render', httpEvent, data, async (httpEvent, data) => {
78
- var renderFile, pathnameSplit = httpEvent.url.pathname.split('/');
79
- while ((renderFile = Path.join(this.cx.CWD, this.cx.layout.PUBLIC_DIR, './' + pathnameSplit.join('/'), 'index.html'))
80
- && (this.renderFileCache[renderFile] === false/* false on previous runs */ || !Fs.existsSync(renderFile))) {
81
- this.renderFileCache[renderFile] = false;
82
- pathnameSplit.pop();
83
- }
84
- const instanceParams = QueryString.stringify({
85
- file: renderFile,
86
- url: httpEvent.url.href,
87
- root: this.cx.CWD,
88
- oohtml_level: this.cx.server.oohtml_support,
89
- });
90
- const { window } = await import('@webqit/oohtml-ssr/instance.js?' + instanceParams);
91
- // --------
92
- // OOHTML would waiting for DOM-ready in order to be initialized
93
- if (window.WebQit.DOM) {
94
- await new Promise(res => window.WebQit.DOM.ready(res));
95
- }
96
- if (window.document.templates) {
97
- await new Promise(res => (window.document.templatesReadyState === 'complete' && res(), window.document.addEventListener('templatesreadystatechange', res)));
98
- }
99
- if (window.document.state) {
100
- if (!window.document.state.env) {
101
- window.document.setState({
102
- env: 'server',
103
- }, { update: true });
104
- }
105
- window.document.setState({ data, url: httpEvent.url }, { update: 'merge' });
106
- }
107
- if (window.document.templates) {
108
- window.document.body.setAttribute('template', 'routes/' + httpEvent.url.pathname.split('/').filter(a => a).map(a => a + '+-').join('/'));
109
- }
110
- await new Promise(res => setTimeout(res, 60));
111
- return window;
112
- });
113
- return rendering + '';
114
- }
115
-
116
- }
@@ -1,16 +0,0 @@
1
-
2
- /**
3
- * @imports
4
- */
5
- import _Contex from '../../Context.js';
6
-
7
- export default class Context extends _Contex {
8
- // env
9
- get env() {
10
- return this.dict.env || {};
11
- }
12
-
13
- set env(value) {
14
- this.dict.env = value;
15
- }
16
- }
@@ -1,159 +0,0 @@
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 };