@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
@@ -0,0 +1,161 @@
1
+ import Fs from 'fs';
2
+ import Path from 'path';
3
+
4
+ function parseHostnames(hostnames) {
5
+ return [].concat(hostnames).reduce((arr, str) => arr.concat(str.split(',')), []).map((str) => str.trim()).filter(str => str);
6
+ }
7
+
8
+ function selectHostnames(serverDefs, matchingPort = null) {
9
+ return serverDefs.reduce((hosts, def) => hosts.length ? hosts : (((!matchingPort || def.port === matchingPort) && parseHostnames(def.hostnames)) || []), []);
10
+ }
11
+
12
+ // config.runtime
13
+
14
+ export async function readInitConfig($context) {
15
+ if (!$context.config.static.Init) {
16
+ throw new Error(`The Client configurator "config.static.Init" is required in context.`);
17
+ }
18
+ return await (new $context.config.static.Init($context)).read();
19
+ }
20
+
21
+ export async function readClientConfig($context) {
22
+ if (!$context.config.runtime?.Client) {
23
+ throw new Error(`The Client configurator "config.runtime.Client" is required in context.`);
24
+ }
25
+ return await (new $context.config.runtime.Client($context)).read();
26
+ }
27
+
28
+ export async function readWorkerConfig($context) {
29
+ if (!$context.config.runtime?.client.Worker) {
30
+ throw new Error(`The Client configurator "config.runtime.client.Worker" is required in context.`);
31
+ }
32
+ return await (new $context.config.runtime.client.Worker($context)).read();
33
+ }
34
+
35
+ export async function readServerConfig($context) {
36
+ if (!$context.config.runtime?.Server) {
37
+ throw new Error(`The Client configurator "config.runtime.Server" is required in context.`);
38
+ }
39
+ const serverConfig = await (new $context.config.runtime.Server($context)).read();
40
+ serverConfig.hostnames = serverConfig.hostnames.length ? parseHostnames(serverConfig.hostnames) : ['*'];
41
+ if (serverConfig.https.port) {
42
+ serverConfig.https.hostnames = serverConfig.https.hostnames.length ? parseHostnames(serverConfig.https.hostnames) : ['*'];
43
+ }
44
+ return serverConfig;
45
+ }
46
+
47
+ export async function readHeadersConfig($context) {
48
+ if (!$context.config.runtime?.server.Headers) {
49
+ throw new Error(`The Client configurator "config.runtime.server.Headers" is required in context.`);
50
+ }
51
+ return await (new $context.config.runtime.server.Headers($context)).read();
52
+ }
53
+
54
+ export async function readRedirectsConfig($context) {
55
+ if (!$context.config.runtime?.server.Redirects) {
56
+ throw new Error(`The Client configurator "config.runtime.server.Redirects" is required in context.`);
57
+ }
58
+ return await (new $context.config.runtime.server.Redirects($context)).read();
59
+ }
60
+
61
+ // config.deployment
62
+
63
+ export async function readLayoutConfig($context) {
64
+ if (!$context.config.deployment?.Layout) {
65
+ throw new Error(`The Client configurator "config.deployment.Layout" is required in context.`);
66
+ }
67
+ const layoutConfig = await (new $context.config.deployment.Layout($context)).read();
68
+ return Object.fromEntries(['CLIENT_DIR', 'WORKER_DIR', 'SERVER_DIR', 'PUBLIC_DIR', 'VIEWS_DIR'].map((name) => {
69
+ return [name, Path.resolve($context.CWD || '', layoutConfig[name])];
70
+ }));
71
+ }
72
+
73
+ export async function readEnvConfig($context) {
74
+ if (!$context.config.deployment?.Env) {
75
+ throw new Error(`The Client configurator "config.deployment.Env" is required in context.`);
76
+ }
77
+ return await (new $context.config.deployment.Env($context)).read();
78
+ }
79
+
80
+ export async function readOriginsConfig($context) {
81
+ if (!$context.config.deployment?.Origins) {
82
+ throw new Error(`The Client configurator "config.deployment.Origins" is required in context.`);
83
+ }
84
+ return await (new $context.config.deployment.Origins($context)).read();
85
+ }
86
+
87
+ export async function readProxyConfig($context) {
88
+ if (!$context.config.deployment?.Proxy) {
89
+ throw new Error(`The Client configurator "config.deployment.Proxy" is required in context.`);
90
+ }
91
+ const proxyConfig = await (new $context.config.deployment.Proxy($context)).read();
92
+ const entries = await Promise.all(proxyConfig.entries.map(async ({ ...proxy }) => {
93
+ if (proxy.hostnames) {
94
+ proxy.hostnames = parseHostnames(proxy.hostnames);
95
+ }
96
+ if (proxy.path) {
97
+ const $$context = $context.constructor.create($context, Path.join($context.CWD, proxy.path));
98
+ proxy.SERVER = await (new $$context.config.runtime.Server($$context)).read();
99
+ if (!proxy.port) {
100
+ // Dynamically figure the local port on which this could be running
101
+ proxy.port = proxy.SERVER.https.port || proxy.SERVER.port;
102
+ }
103
+ if (!proxy.proto) {
104
+ // Dynamically figure the proto to forward the request with - to match running server
105
+ proxy.proto = proxy.port === proxy.SERVER.https.port ? 'https' : 'http';
106
+ }
107
+ if (!proxy.hostnames?.length) {
108
+ // Dynamically figure the hostnames to forward
109
+ proxy.hostnames = selectHostnames([proxy.SERVER.https, proxy.SERVER], proxy.port);
110
+ if (!proxy.hostnames.length) {
111
+ proxy.hostnames = selectHostnames([proxy.SERVER.https, proxy.SERVER]);
112
+ }
113
+ }
114
+ }
115
+ // Whether local or remote...
116
+ if (!proxy.hostnames) {
117
+ proxy.hostnames = ['*'];
118
+ }
119
+ return proxy;
120
+ }));
121
+ return { entries };
122
+ }
123
+
124
+ // -----------
125
+
126
+ export function scanRoots(DIR, rootFileName, offset = '') {
127
+ return Fs.readdirSync(Path.join(DIR, offset)).reduce((roots, f) => {
128
+ const resource = Path.join(DIR, offset, f);
129
+ if (Fs.statSync(resource).isDirectory()) {
130
+ const $offset = Path.join(offset, f);
131
+ if (Fs.existsSync(Path.join(resource, rootFileName))) {
132
+ return roots.concat($offset.replace(/\\/g, '/'));
133
+ }
134
+ return roots.concat(scanRoots(DIR, rootFileName, $offset));
135
+ }
136
+ return roots;
137
+ }, []);
138
+ }
139
+
140
+ export function scanRouteHandlers(LAYOUT, which, callback, offset, roots = []) {
141
+ const routingDir = LAYOUT[`${which.toUpperCase()}_DIR`];
142
+ const dir = Path.join(routingDir, offset);
143
+ const routeFileEnding = new RegExp(`(?:handler\\.${which}|handler)\\.js$`);
144
+ const dedicatedRouteFileName = `handler.${which}.js`;
145
+ const hasDedicatedRouteFile = Fs.existsSync(Path.join(dir, dedicatedRouteFileName));
146
+ try {
147
+ Fs.readdirSync(dir).forEach((f) => {
148
+ const resource = Path.join(dir, f);
149
+ const fstat = Fs.statSync(resource);
150
+ if (fstat.isDirectory()) {
151
+ const $offset = Path.join(offset, f).replace(/\\/g, '/');
152
+ if (roots.includes($offset)) return;
153
+ scanRouteHandlers(LAYOUT, which, callback, $offset, roots);
154
+ } else {
155
+ if (!routeFileEnding.test(f)
156
+ || (hasDedicatedRouteFile && f !== dedicatedRouteFileName)) return;
157
+ callback(resource, `/${offset}`, f, fstat);
158
+ }
159
+ });
160
+ } catch(e) {}
161
+ }
package/src/index.js CHANGED
@@ -1,20 +1,14 @@
1
-
2
- /**
3
- * @imports
4
- */
5
- import * as config from './config-pi/index.js';
6
- import * as deployment from './deployment-pi/index.js';
7
- import * as runtime from './runtime-pi/index.js';
8
- import * as services from './services-pi/index.js';
9
- import Context from './Context.js';
10
-
11
- /**
12
- * @exports
13
- */
14
- export {
15
- config,
16
- deployment,
17
- runtime,
18
- services,
19
- Context,
1
+ import * as config from './config-pi/index.js';
2
+ import * as deployment from './deployment-pi/index.js';
3
+ import * as runtime from './runtime-pi/index.js';
4
+ import * as services from './services-pi/index.js';
5
+ import * as starter from './init-pi/index.js';
6
+
7
+ export { Context } from './Context.js';
8
+ export {
9
+ config,
10
+ deployment,
11
+ runtime,
12
+ services,
13
+ starter,
20
14
  }
@@ -0,0 +1,117 @@
1
+ import Fs from 'fs';
2
+ import Fs2 from 'fs/promises';
3
+ import Path from 'path';
4
+ import { exec } from 'child_process';
5
+ import { _toTitle } from '@webqit/util/str/index.js';
6
+ import { readInitConfig } from '../deployment-pi/util.js';
7
+ import { Context } from '../Context.js';
8
+
9
+ export const desc = {
10
+ init: 'Generate a preset Webflo starter app.',
11
+ };
12
+
13
+ export async function init(projectName = 'my-webflo-app', projectTitle = '', projectDescription = '') {
14
+ const $context = this;
15
+
16
+ if (!($context instanceof Context)) {
17
+ throw new Error(`The "this" context must be a Webflo Context object.`);
18
+ }
19
+
20
+ const { flags: FLAGS, logger: LOGGER } = $context;
21
+ const $config = {
22
+ INIT: await readInitConfig($context),
23
+ };
24
+
25
+ // Validate chosen tamplate
26
+ const template = FLAGS.template || $config.INIT.template;
27
+ const templateDir = Path.resolve(new URL(import.meta.url).pathname, '../templates', template);
28
+ if (!Fs.existsSync(templateDir)) {
29
+ LOGGER?.error(LOGGER.style.err(`Error: template "${template}" not found.`));
30
+ process.exit(1);
31
+ }
32
+
33
+ // Validate target dir
34
+ const targetDir = Path.resolve(process.cwd(), projectName);
35
+ if (Fs.existsSync(targetDir)) {
36
+ LOGGER?.error(LOGGER.style.err(`Error: directory ${projectName} already exists.`));
37
+ process.exit(1);
38
+ }
39
+
40
+ LOGGER?.log(LOGGER.style.keyword(`> `) + `Initializing your webflo app: "${projectName}" using template "${template}"...\n`);
41
+
42
+ // 1. Create project dir
43
+ await Fs2.mkdir(targetDir, { recursive: true });
44
+ // 2. Copy template files
45
+ await Fs2.cp(templateDir, targetDir, { recursive: true });
46
+
47
+ if (!projectTitle) {
48
+ projectTitle = _toTitle(projectName.replace(/-/g, ' '));
49
+ }
50
+ if (!projectDescription) {
51
+ projectDescription = `${projectTitle} - powered by Webflo`;
52
+ }
53
+
54
+ // 3. Customize package.json
55
+ const pkgFile = Path.join(targetDir, 'package.json');
56
+ if (Fs.existsSync(pkgFile)) {
57
+ const pkgData = JSON.parse(await Fs2.readFile(pkgFile, 'utf8'));
58
+ pkgData.name = projectName;
59
+ pkgData.title = projectTitle;
60
+ pkgData.description = projectDescription;
61
+ await Fs2.writeFile(pkgFile, JSON.stringify(pkgData, null, 2));
62
+ }
63
+
64
+ // 4. Customize index.html and manifest.json
65
+ for (const fileName of ['public/index.html', 'public/manifest.json']) {
66
+ const filePath = Path.join(targetDir, fileName);
67
+ if (Fs.existsSync(filePath)) {
68
+ let fileContents = await Fs2.readFile(filePath, 'utf8');
69
+ fileContents = fileContents.replace(/APP_NAME/g, projectName);
70
+ fileContents = fileContents.replace(/APP_TITLE/g, projectTitle);
71
+ fileContents = fileContents.replace(/APP_DESCRIPTION/g, projectDescription);
72
+ await Fs2.writeFile(filePath, fileContents);
73
+ }
74
+ }
75
+
76
+ // 5. Run setup commands
77
+ const comands = [];
78
+ const nextSteps = [];
79
+ if (FLAGS.install ?? $config.INIT.install) {
80
+ comands.push('npm install');
81
+ comands.push('npm run build');
82
+ } else {
83
+ nextSteps.push('npm install');
84
+ }
85
+ if (FLAGS.git ?? $config.INIT.git) {
86
+ comands.push('git init');
87
+ } else {
88
+ nextSteps.push('git init');
89
+ }
90
+ if (comands.length) {
91
+ LOGGER?.log(LOGGER.style.keyword(`> `) + `Running setup commands...`);
92
+ for (const cmd of comands) {
93
+ LOGGER?.log(LOGGER.style.token(`$ `) + cmd);
94
+ await new Promise((resolve, reject) => {
95
+ exec(cmd, { cwd: targetDir }, (error, stdout, stderr) => {
96
+ if (error) {
97
+ LOGGER?.log(LOGGER.style.err(stderr || error.message));
98
+ return reject(error);
99
+ }
100
+ resolve();
101
+ });
102
+ });
103
+ }
104
+ }
105
+
106
+ // 6. Done message
107
+ LOGGER?.log(`\n✔ Successfully created "${projectName}" using template "${template}"`);
108
+ LOGGER?.log(`\nNext steps:`);
109
+ LOGGER?.log(` cd ${projectName}`);
110
+ if (nextSteps.length) {
111
+ LOGGER?.log(` # Additional setup commands:`);
112
+ for (const step of nextSteps) {
113
+ LOGGER?.log(` ${step}`);
114
+ }
115
+ }
116
+ LOGGER?.log(` npm run dev -- --open\n`);
117
+ }
@@ -0,0 +1,8 @@
1
+ export default async function (event, next, fetch) {
2
+ if (next.stepname) return await next();
3
+ return {
4
+ title: 'Webflo PWA',
5
+ greeting: 'Hello World!',
6
+ menu: [{ title: 'Home', href: '/' }],
7
+ };
8
+ }
@@ -0,0 +1,7 @@
1
+ <ul render="#items: (item) of data?.menu / 'menu'">
2
+ <template def="menu" scoped="">
3
+ <li>
4
+ <a render="~href: item?.href; #text: item?.title;"></a>
5
+ </li>
6
+ </template>
7
+ </ul>
@@ -0,0 +1,19 @@
1
+ {
2
+ "title": "",
3
+ "name": "",
4
+ "description": "",
5
+ "type": "module",
6
+ "scripts": {
7
+ "build:html": "oohtml bundle --recursive --outdir=public/assets --auto-embed=app",
8
+ "build:js": "webflo generate::client --recursive --outdir=public/assets --auto-embed",
9
+ "build": "npm run build:html && npm run build:js",
10
+ "dev": "webflo start --dev --build-sensitivity=2",
11
+ "start": "webflo start"
12
+ },
13
+ "dependencies": {
14
+ "@webqit/webflo": "file:../../webflo"
15
+ },
16
+ "devDependencies": {
17
+ "@webqit/oohtml-cli": "latest"
18
+ }
19
+ }
@@ -0,0 +1,16 @@
1
+ body {
2
+ background-color: #4e40ce;
3
+ margin: 0;
4
+ color: white;
5
+ }
6
+ h1 {
7
+ background-color: black;
8
+ padding: 2rem;
9
+ }
10
+ h1 span:first-of-type {
11
+ color: crimson;
12
+ }
13
+ ul {
14
+ padding: 2rem;
15
+ padding-inline: 3rem;
16
+ }
@@ -0,0 +1,39 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en-US">
3
+
4
+ <head>
5
+ <meta charset="UTF-8">
6
+ <meta name="viewport" content="width=device-width, initial-scale=1">
7
+ <title render="#text: titleBar || title">APP_TITLE</title>
8
+ <meta name="description" content="APP_DESCRIPTION">
9
+ <meta name="apple-mobile-web-app-title" content="APP_TITLE">
10
+ <meta name="color-scheme" content="dark">
11
+ <meta name="theme-color" content="#313131">
12
+ <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
13
+ <meta name="apple-mobile-web-app-capable" content="yes">
14
+ <meta name="mobile-web-app-capable" content="yes">
15
+ <link rel="manifest" href="/manifest.json">
16
+ <!--
17
+ <link rel="icon" href="/assets/..." type="image/png">
18
+ <link rel="apple-touch-icon" href="/assets/...">
19
+ -->
20
+ <script crossorigin ssr src="https://unpkg.com/@webqit/oohtml@latest/dist/main.lite.js"></script>
21
+ <template def="app" ssr src="/assets/app.html" by="oohtml-cli"></template>
22
+ <script type="module" src="/assets/app.js" by="webflo"></script>
23
+ <link rel="stylesheet" href="/assets/app.css">
24
+ </head>
25
+
26
+ <body importscontext="/app">
27
+
28
+ <h1>
29
+ <span><?{ data.title }?></span><br>
30
+ <span><?{ data.greeting }?></span>
31
+ </h1>
32
+
33
+ <import ref="#page.html">
34
+ Import will show here...
35
+ </import>
36
+
37
+ </body>
38
+
39
+ </html>
@@ -0,0 +1,29 @@
1
+ {
2
+ "name": "APP_TITLE",
3
+ "short_name": "APP_TITLE",
4
+ "description": "APP_DESCRIPTION",
5
+ "start_url": "/",
6
+ "display": "standalone",
7
+ "orientation": "portrait",
8
+ "background_color": "#4e40ce",
9
+ "theme_color": "#4e40ce",
10
+ "scope": "/",
11
+ "icons": [
12
+ {
13
+ "src": "/assets/...",
14
+ "sizes": "192x192",
15
+ "type": "image/png"
16
+ },
17
+ {
18
+ "src": "/assets/...",
19
+ "sizes": "512x512",
20
+ "type": "image/png",
21
+ "purpose": "maskable"
22
+ }
23
+ ],
24
+ "categories": [],
25
+ "related_applications": [],
26
+ "prefer_related_applications": false,
27
+ "lang": "en",
28
+ "dir": "ltr"
29
+ }
@@ -0,0 +1,8 @@
1
+ export default async function (event, next, fetch) {
2
+ if (next.stepname) return await next();
3
+ return {
4
+ title: 'Webflo Web',
5
+ greeting: 'Hello World!',
6
+ menu: [{ title: 'Home', href: '/' }],
7
+ };
8
+ }
@@ -0,0 +1,7 @@
1
+ <ul render="#items: (item) of data?.menu / 'menu'">
2
+ <template def="menu" scoped="">
3
+ <li>
4
+ <a render="~href: item?.href; #text: item?.title;"></a>
5
+ </li>
6
+ </template>
7
+ </ul>
@@ -0,0 +1,19 @@
1
+ {
2
+ "title": "",
3
+ "name": "",
4
+ "description": "",
5
+ "type": "module",
6
+ "scripts": {
7
+ "build:html": "oohtml bundle --recursive --outdir=public/assets --auto-embed=app",
8
+ "build:js": "webflo generate::client --recursive --outdir=public/assets --auto-embed",
9
+ "build": "npm run build:html && npm run build:js",
10
+ "dev": "webflo start --dev --build-sensitivity=2",
11
+ "start": "webflo start"
12
+ },
13
+ "dependencies": {
14
+ "@webqit/webflo": "file:../../webflo"
15
+ },
16
+ "devDependencies": {
17
+ "@webqit/oohtml-cli": "latest"
18
+ }
19
+ }
@@ -0,0 +1,16 @@
1
+ body {
2
+ background-color: #4e40ce;
3
+ margin: 0;
4
+ color: white;
5
+ }
6
+ h1 {
7
+ background-color: black;
8
+ padding: 2rem;
9
+ }
10
+ h1 span:first-of-type {
11
+ color: crimson;
12
+ }
13
+ ul {
14
+ padding: 2rem;
15
+ padding-inline: 3rem;
16
+ }
@@ -0,0 +1,39 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en-US">
3
+
4
+ <head>
5
+ <meta charset="UTF-8">
6
+ <meta name="viewport" content="width=device-width, initial-scale=1">
7
+ <title render="#text: data?.titleBar || data?.title">APP_TITLE</title>
8
+ <meta name="description" content="APP_DESCRIPTION">
9
+ <meta name="apple-mobile-web-app-title" content="APP_TITLE">
10
+ <meta name="color-scheme" content="dark">
11
+ <meta name="theme-color" content="#313131">
12
+ <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
13
+ <meta name="apple-mobile-web-app-capable" content="yes">
14
+ <meta name="mobile-web-app-capable" content="yes">
15
+ <!--
16
+ <link rel="icon" href="/assets/..." type="image/png">
17
+ <link rel="apple-touch-icon" href="/assets/...">
18
+ <link rel="manifest" href="/manifest.json">
19
+ -->
20
+ <script crossorigin ssr src="https://unpkg.com/@webqit/oohtml@latest/dist/main.lite.js"></script>
21
+ <template def="app" ssr src="/assets/app.html" by="oohtml-cli"></template>
22
+ <script type="module" src="/assets/app.js" by="webflo"></script>
23
+ <link rel="stylesheet" href="/assets/app.css">
24
+ </head>
25
+
26
+ <body importscontext="/app">
27
+
28
+ <h1>
29
+ <span><?{ data.title }?></span><br>
30
+ <span><?{ data.greeting }?></span>
31
+ </h1>
32
+
33
+ <import ref="#page.html">
34
+ Import will show here...
35
+ </import>
36
+
37
+ </body>
38
+
39
+ </html>