@vandenberghinc/volt 1.1.26 → 1.1.28

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 (502) hide show
  1. package/backend/dist/cjs/{blacklist.d.ts → backend/src/blacklist.d.ts} +5 -3
  2. package/backend/dist/cjs/{blacklist.js → backend/src/blacklist.js} +8 -5
  3. package/backend/dist/cjs/{cli.js → backend/src/cli.js} +29 -47
  4. package/backend/dist/cjs/backend/src/database/collection.d.ts +1543 -0
  5. package/backend/dist/cjs/backend/src/database/collection.js +3042 -0
  6. package/backend/dist/cjs/backend/src/database/database.d.ts +66 -0
  7. package/backend/dist/cjs/{database → backend/src/database}/database.js +48 -43
  8. package/backend/dist/cjs/backend/src/database/filters/filters.d.ts +6 -0
  9. package/backend/dist/cjs/backend/src/database/filters/filters.js +15 -0
  10. package/backend/dist/cjs/backend/src/database/filters/strict_filter.d.ts +223 -0
  11. package/backend/dist/cjs/backend/src/database/filters/strict_filter.js +15 -0
  12. package/backend/dist/cjs/backend/src/database/filters/strict_filter_test.js +443 -0
  13. package/backend/dist/cjs/backend/src/database/filters/strict_filter_test_v0.js +15 -0
  14. package/backend/dist/cjs/backend/src/database/filters/strict_filter_v0.d.ts +50 -0
  15. package/backend/dist/cjs/backend/src/database/filters/strict_filter_v0.js +15 -0
  16. package/backend/dist/cjs/backend/src/database/filters/strict_filter_v1.d.ts +76 -0
  17. package/backend/dist/cjs/backend/src/database/filters/strict_filter_v1.js +15 -0
  18. package/backend/dist/cjs/backend/src/database/filters/strict_filter_v2.d.ts +75 -0
  19. package/backend/dist/cjs/backend/src/database/filters/strict_filter_v2.js +15 -0
  20. package/backend/dist/cjs/backend/src/database/filters/strict_filter_v3.d.ts +219 -0
  21. package/backend/dist/cjs/backend/src/database/filters/strict_filter_v3.js +15 -0
  22. package/backend/dist/cjs/backend/src/database/filters/strict_update_filter.d.ts +165 -0
  23. package/backend/dist/cjs/backend/src/database/filters/strict_update_filter.js +15 -0
  24. package/backend/dist/cjs/backend/src/database/filters/strict_update_filter_test.d.ts +5 -0
  25. package/backend/dist/cjs/backend/src/database/filters/strict_update_filter_test.js +355 -0
  26. package/backend/dist/cjs/backend/src/database/flatten.d.ts +75 -0
  27. package/backend/dist/cjs/{logger.js → backend/src/database/flatten.js} +18 -7
  28. package/backend/dist/cjs/backend/src/database/flatten_test.js +175 -0
  29. package/backend/dist/cjs/backend/src/database/quota/quota.d.ts +461 -0
  30. package/backend/dist/cjs/backend/src/database/quota/quota.js +1014 -0
  31. package/backend/dist/cjs/backend/src/database/quota/quota_v1.d.ts +534 -0
  32. package/backend/dist/cjs/backend/src/database/quota/quota_v1.js +1087 -0
  33. package/backend/dist/cjs/backend/src/database/quota/safe_int.d.ts +293 -0
  34. package/backend/dist/cjs/backend/src/database/quota/safe_int.js +573 -0
  35. package/backend/dist/{esm → cjs/backend/src}/endpoint.d.ts +69 -46
  36. package/backend/dist/cjs/{endpoint.js → backend/src/endpoint.js} +87 -101
  37. package/backend/dist/cjs/backend/src/errors/index.d.ts +7 -0
  38. package/backend/dist/cjs/backend/src/errors/index.js +25 -0
  39. package/backend/dist/{esm/utils.d.ts → cjs/backend/src/errors/internal_external.d.ts} +14 -22
  40. package/backend/dist/cjs/backend/src/errors/internal_external.js +85 -0
  41. package/backend/dist/cjs/backend/src/errors/invalid_usage_error.d.ts +38 -0
  42. package/backend/dist/cjs/{mutex.js → backend/src/errors/invalid_usage_error.js} +20 -37
  43. package/backend/dist/cjs/backend/src/errors/system_error.d.ts +230 -0
  44. package/backend/dist/cjs/backend/src/errors/system_error.js +393 -0
  45. package/backend/dist/cjs/backend/src/events.d.ts +54 -0
  46. package/backend/dist/cjs/backend/src/events.js +15 -0
  47. package/backend/dist/cjs/{frontend.js → backend/src/frontend.js} +1 -1
  48. package/backend/dist/cjs/{image_endpoint.d.ts → backend/src/image_endpoint.d.ts} +16 -1
  49. package/backend/dist/cjs/{image_endpoint.js → backend/src/image_endpoint.js} +3 -5
  50. package/backend/dist/cjs/backend/src/logger.d.ts +5 -0
  51. package/backend/dist/cjs/backend/src/logger.js +15 -0
  52. package/backend/dist/cjs/backend/src/meta.d.ts +64 -0
  53. package/backend/dist/cjs/{meta.js → backend/src/meta.js} +9 -12
  54. package/backend/dist/cjs/backend/src/payments/paddle.d.ts +326 -0
  55. package/backend/dist/cjs/{payments → backend/src/payments}/paddle.js +377 -327
  56. package/backend/dist/cjs/backend/src/plugins/browser.d.ts +1 -0
  57. package/backend/dist/cjs/backend/src/plugins/browser.js +15 -0
  58. package/backend/dist/cjs/backend/src/plugins/mail/mail.d.ts +248 -0
  59. package/backend/dist/cjs/backend/src/plugins/mail/mail.js +379 -0
  60. package/backend/dist/{esm → cjs/backend/src}/plugins/mail/ui.d.ts +23 -0
  61. package/backend/dist/cjs/backend/src/plugins/pdf.d.ts +1 -0
  62. package/backend/dist/cjs/backend/src/rate_limit.d.ts +145 -0
  63. package/backend/dist/cjs/backend/src/rate_limit.js +549 -0
  64. package/backend/dist/cjs/{route.d.ts → backend/src/route.d.ts} +3 -10
  65. package/backend/dist/cjs/{route.js → backend/src/route.js} +23 -21
  66. package/backend/dist/cjs/backend/src/server.d.ts +485 -0
  67. package/backend/dist/cjs/{server.js → backend/src/server.js} +688 -873
  68. package/backend/dist/cjs/backend/src/splash_screen.d.ts +80 -0
  69. package/backend/dist/cjs/{splash_screen.js → backend/src/splash_screen.js} +24 -3
  70. package/backend/dist/cjs/backend/src/status.d.ts +74 -0
  71. package/backend/dist/cjs/{status.js → backend/src/status.js} +64 -64
  72. package/backend/dist/cjs/backend/src/stream.d.ts +376 -0
  73. package/backend/dist/cjs/{stream.js → backend/src/stream.js} +299 -276
  74. package/backend/dist/cjs/backend/src/users.d.ts +807 -0
  75. package/backend/dist/cjs/backend/src/users.js +1971 -0
  76. package/backend/dist/cjs/backend/src/utils.d.ts +16 -0
  77. package/backend/dist/cjs/{utils.js → backend/src/utils.js} +14 -77
  78. package/backend/dist/{esm → cjs/backend/src}/view.d.ts +33 -11
  79. package/backend/dist/cjs/backend/src/view.js +508 -0
  80. package/backend/dist/{esm → cjs/backend/src}/volt.d.ts +10 -1
  81. package/backend/dist/cjs/{volt.js → backend/src/volt.js} +8 -5
  82. package/backend/dist/cjs/frontend/src/modules/request.d.ts +70 -0
  83. package/backend/dist/cjs/frontend/src/modules/request.js +99 -0
  84. package/backend/dist/esm/{blacklist.d.ts → backend/src/blacklist.d.ts} +5 -3
  85. package/backend/dist/esm/{blacklist.js → backend/src/blacklist.js} +9 -6
  86. package/backend/dist/esm/{cli.js → backend/src/cli.js} +43 -60
  87. package/backend/dist/esm/backend/src/database/collection.d.ts +1543 -0
  88. package/backend/dist/esm/backend/src/database/collection.js +3510 -0
  89. package/backend/dist/esm/backend/src/database/database.d.ts +66 -0
  90. package/backend/dist/esm/{database → backend/src/database}/database.js +62 -103
  91. package/backend/dist/esm/backend/src/database/document.d.ts +1 -0
  92. package/backend/dist/esm/backend/src/database/document.js +558 -0
  93. package/backend/dist/esm/backend/src/database/filters/filters.d.ts +6 -0
  94. package/backend/dist/esm/backend/src/database/filters/filters.js +1 -0
  95. package/backend/dist/esm/backend/src/database/filters/strict_filter.d.ts +223 -0
  96. package/backend/dist/esm/backend/src/database/filters/strict_filter.js +3 -0
  97. package/backend/dist/esm/backend/src/database/filters/strict_filter_test.d.ts +1 -0
  98. package/backend/dist/esm/backend/src/database/filters/strict_filter_test.js +505 -0
  99. package/backend/dist/esm/backend/src/database/filters/strict_filter_test_v0.d.ts +1 -0
  100. package/backend/dist/esm/backend/src/database/filters/strict_filter_test_v0.js +712 -0
  101. package/backend/dist/esm/backend/src/database/filters/strict_filter_v0.d.ts +50 -0
  102. package/backend/dist/esm/backend/src/database/filters/strict_filter_v0.js +5 -0
  103. package/backend/dist/esm/backend/src/database/filters/strict_filter_v1.d.ts +76 -0
  104. package/backend/dist/esm/backend/src/database/filters/strict_filter_v1.js +44 -0
  105. package/backend/dist/esm/backend/src/database/filters/strict_filter_v2.d.ts +75 -0
  106. package/backend/dist/esm/backend/src/database/filters/strict_filter_v2.js +5 -0
  107. package/backend/dist/esm/backend/src/database/filters/strict_filter_v3.d.ts +219 -0
  108. package/backend/dist/esm/backend/src/database/filters/strict_filter_v3.js +1 -0
  109. package/backend/dist/esm/backend/src/database/filters/strict_update_filter.d.ts +165 -0
  110. package/backend/dist/esm/backend/src/database/filters/strict_update_filter.js +5 -0
  111. package/backend/dist/esm/backend/src/database/filters/strict_update_filter_test.d.ts +5 -0
  112. package/backend/dist/esm/backend/src/database/filters/strict_update_filter_test.js +405 -0
  113. package/backend/dist/esm/backend/src/database/flatten.d.ts +75 -0
  114. package/backend/dist/esm/backend/src/database/flatten.js +22 -0
  115. package/backend/dist/esm/backend/src/database/flatten_test.d.ts +1 -0
  116. package/backend/dist/esm/backend/src/database/flatten_test.js +174 -0
  117. package/backend/dist/esm/backend/src/database/quota/quota.d.ts +461 -0
  118. package/backend/dist/esm/backend/src/database/quota/quota.js +1118 -0
  119. package/backend/dist/esm/backend/src/database/quota/quota_v1.d.ts +534 -0
  120. package/backend/dist/esm/backend/src/database/quota/quota_v1.js +1242 -0
  121. package/backend/dist/esm/backend/src/database/quota/safe_int.d.ts +293 -0
  122. package/backend/dist/esm/backend/src/database/quota/safe_int.js +602 -0
  123. package/backend/dist/{cjs → esm/backend/src}/endpoint.d.ts +69 -46
  124. package/backend/dist/esm/{endpoint.js → backend/src/endpoint.js} +136 -127
  125. package/backend/dist/esm/backend/src/errors/index.d.ts +7 -0
  126. package/backend/dist/esm/backend/src/errors/index.js +7 -0
  127. package/backend/dist/{cjs/utils.d.ts → esm/backend/src/errors/internal_external.d.ts} +14 -22
  128. package/backend/dist/esm/backend/src/errors/internal_external.js +70 -0
  129. package/backend/dist/esm/backend/src/errors/invalid_usage_error.d.ts +38 -0
  130. package/backend/dist/esm/backend/src/errors/invalid_usage_error.js +30 -0
  131. package/backend/dist/esm/backend/src/errors/system_error.d.ts +230 -0
  132. package/backend/dist/esm/backend/src/errors/system_error.js +402 -0
  133. package/backend/dist/esm/backend/src/events.d.ts +54 -0
  134. package/backend/dist/esm/backend/src/events.js +5 -0
  135. package/backend/dist/esm/{frontend.js → backend/src/frontend.js} +1 -1
  136. package/backend/dist/esm/{image_endpoint.d.ts → backend/src/image_endpoint.d.ts} +16 -1
  137. package/backend/dist/esm/{image_endpoint.js → backend/src/image_endpoint.js} +16 -20
  138. package/backend/dist/esm/backend/src/logger.d.ts +5 -0
  139. package/backend/dist/esm/backend/src/logger.js +8 -0
  140. package/backend/dist/esm/backend/src/meta.d.ts +64 -0
  141. package/backend/dist/esm/{meta.js → backend/src/meta.js} +15 -54
  142. package/backend/dist/esm/backend/src/payments/paddle.d.ts +326 -0
  143. package/backend/dist/esm/{payments → backend/src/payments}/paddle.js +417 -452
  144. package/backend/dist/esm/backend/src/plugins/browser.d.ts +1 -0
  145. package/backend/dist/esm/backend/src/plugins/browser.js +170 -0
  146. package/backend/dist/esm/backend/src/plugins/mail/mail.d.ts +248 -0
  147. package/backend/dist/esm/backend/src/plugins/mail/mail.js +389 -0
  148. package/backend/dist/{cjs → esm/backend/src}/plugins/mail/ui.d.ts +23 -0
  149. package/backend/dist/esm/{plugins → backend/src/plugins}/mail/ui.js +3 -6
  150. package/backend/dist/esm/backend/src/plugins/pdf.d.ts +1 -0
  151. package/backend/dist/esm/{plugins → backend/src/plugins}/pdf.js +3 -3
  152. package/backend/dist/esm/backend/src/rate_limit.d.ts +145 -0
  153. package/backend/dist/esm/backend/src/rate_limit.js +667 -0
  154. package/backend/dist/esm/{route.d.ts → backend/src/route.d.ts} +3 -10
  155. package/backend/dist/esm/{route.js → backend/src/route.js} +26 -21
  156. package/backend/dist/esm/backend/src/server.d.ts +485 -0
  157. package/backend/dist/esm/{server.js → backend/src/server.js} +891 -1441
  158. package/backend/dist/esm/backend/src/splash_screen.d.ts +80 -0
  159. package/backend/dist/esm/{splash_screen.js → backend/src/splash_screen.js} +42 -55
  160. package/backend/dist/esm/backend/src/status.d.ts +74 -0
  161. package/backend/dist/esm/backend/src/status.js +199 -0
  162. package/backend/dist/esm/backend/src/stream.d.ts +376 -0
  163. package/backend/dist/esm/{stream.js → backend/src/stream.js} +327 -292
  164. package/backend/dist/esm/backend/src/users.d.ts +809 -0
  165. package/backend/dist/esm/backend/src/users.js +2140 -0
  166. package/backend/dist/esm/backend/src/utils.d.ts +16 -0
  167. package/backend/dist/esm/{utils.js → backend/src/utils.js} +20 -81
  168. package/backend/dist/{cjs → esm/backend/src}/view.d.ts +33 -11
  169. package/backend/dist/esm/{view.js → backend/src/view.js} +266 -86
  170. package/backend/dist/{cjs → esm/backend/src}/volt.d.ts +10 -1
  171. package/backend/dist/esm/{volt.js → backend/src/volt.js} +7 -4
  172. package/backend/dist/esm/frontend/src/modules/request.d.ts +70 -0
  173. package/backend/dist/esm/frontend/src/modules/request.js +117 -0
  174. package/frontend/dist/backend/src/database/collection.d.ts +1543 -0
  175. package/frontend/dist/backend/src/database/collection.js +3510 -0
  176. package/frontend/dist/backend/src/database/database.d.ts +66 -0
  177. package/frontend/dist/backend/src/database/database.js +196 -0
  178. package/frontend/dist/backend/src/database/filters/filters.d.ts +6 -0
  179. package/frontend/dist/backend/src/database/filters/filters.js +1 -0
  180. package/frontend/dist/backend/src/database/filters/strict_filter.d.ts +223 -0
  181. package/frontend/dist/backend/src/database/filters/strict_filter.js +3 -0
  182. package/frontend/dist/backend/src/database/filters/strict_update_filter.d.ts +165 -0
  183. package/frontend/dist/backend/src/database/filters/strict_update_filter.js +5 -0
  184. package/frontend/dist/backend/src/database/flatten.d.ts +75 -0
  185. package/frontend/dist/backend/src/database/flatten.js +22 -0
  186. package/frontend/dist/backend/src/endpoint.d.ts +204 -0
  187. package/frontend/dist/backend/src/endpoint.js +570 -0
  188. package/frontend/dist/backend/src/errors/index.d.ts +7 -0
  189. package/frontend/dist/backend/src/errors/index.js +7 -0
  190. package/frontend/dist/backend/src/errors/internal_external.d.ts +38 -0
  191. package/frontend/dist/backend/src/errors/internal_external.js +70 -0
  192. package/frontend/dist/backend/src/errors/invalid_usage_error.d.ts +38 -0
  193. package/frontend/dist/backend/src/errors/invalid_usage_error.js +30 -0
  194. package/frontend/dist/backend/src/errors/system_error.d.ts +230 -0
  195. package/frontend/dist/backend/src/errors/system_error.js +402 -0
  196. package/frontend/dist/backend/src/events.d.ts +54 -0
  197. package/frontend/dist/backend/src/events.js +5 -0
  198. package/frontend/dist/backend/src/frontend.d.ts +11 -0
  199. package/frontend/dist/backend/src/frontend.js +12 -0
  200. package/frontend/dist/backend/src/image_endpoint.d.ts +39 -0
  201. package/frontend/dist/backend/src/image_endpoint.js +202 -0
  202. package/frontend/dist/backend/src/meta.d.ts +64 -0
  203. package/frontend/dist/backend/src/meta.js +110 -0
  204. package/frontend/dist/backend/src/payments/paddle.d.ts +326 -0
  205. package/frontend/dist/backend/src/payments/paddle.js +2256 -0
  206. package/frontend/dist/backend/src/plugins/mail/mail.d.ts +248 -0
  207. package/frontend/dist/backend/src/plugins/mail/mail.js +389 -0
  208. package/{backend/dist/esm/plugins/mail.d.ts → frontend/dist/backend/src/plugins/mail/ui.d.ts} +23 -0
  209. package/{backend/dist/esm/plugins/mail.js → frontend/dist/backend/src/plugins/mail/ui.js} +3 -6
  210. package/frontend/dist/backend/src/rate_limit.d.ts +145 -0
  211. package/frontend/dist/backend/src/rate_limit.js +673 -0
  212. package/frontend/dist/backend/src/route.d.ts +35 -0
  213. package/frontend/dist/backend/src/route.js +212 -0
  214. package/frontend/dist/backend/src/server.d.ts +485 -0
  215. package/frontend/dist/backend/src/server.js +2670 -0
  216. package/frontend/dist/backend/src/splash_screen.d.ts +80 -0
  217. package/frontend/dist/backend/src/splash_screen.js +135 -0
  218. package/frontend/dist/backend/src/status.d.ts +74 -0
  219. package/frontend/dist/backend/src/status.js +199 -0
  220. package/frontend/dist/backend/src/stream.d.ts +376 -0
  221. package/frontend/dist/backend/src/stream.js +1007 -0
  222. package/frontend/dist/backend/src/users.d.ts +807 -0
  223. package/frontend/dist/backend/src/users.js +2118 -0
  224. package/frontend/dist/backend/src/utils.d.ts +16 -0
  225. package/frontend/dist/backend/src/utils.js +241 -0
  226. package/frontend/dist/backend/src/view.d.ts +162 -0
  227. package/frontend/dist/backend/src/view.js +720 -0
  228. package/frontend/dist/frontend/src/elements/base.d.ts +4414 -0
  229. package/frontend/dist/{elements → frontend/src/elements}/base.js +3624 -260
  230. package/frontend/dist/frontend/src/elements/module.d.ts +95 -0
  231. package/frontend/dist/{elements → frontend/src/elements}/module.js +53 -52
  232. package/frontend/dist/frontend/src/elements/types.d.ts +52 -0
  233. package/frontend/dist/frontend/src/elements/types.js +5 -0
  234. package/frontend/dist/frontend/src/modules/attachment.d.ts +126 -0
  235. package/frontend/dist/frontend/src/modules/attachment.js +306 -0
  236. package/frontend/dist/frontend/src/modules/auth.d.ts +44 -0
  237. package/frontend/dist/frontend/src/modules/auth.js +80 -0
  238. package/frontend/dist/{modules → frontend/src/modules}/color.js +2 -2
  239. package/frontend/dist/frontend/src/modules/compression.d.ts +39 -0
  240. package/frontend/dist/frontend/src/modules/compression.js +102 -0
  241. package/frontend/dist/frontend/src/modules/cookies.d.ts +44 -0
  242. package/frontend/dist/frontend/src/modules/cookies.js +143 -0
  243. package/frontend/dist/frontend/src/modules/events.d.ts +31 -0
  244. package/frontend/dist/frontend/src/modules/events.js +74 -0
  245. package/frontend/dist/frontend/src/modules/google.d.ts +23 -0
  246. package/frontend/dist/frontend/src/modules/google.js +52 -0
  247. package/frontend/dist/frontend/src/modules/meta.d.ts +14 -0
  248. package/frontend/dist/{modules → frontend/src/modules}/meta.js +9 -7
  249. package/frontend/dist/{modules → frontend/src/modules}/paddle.d.ts +37 -134
  250. package/frontend/dist/{modules → frontend/src/modules}/paddle.js +620 -568
  251. package/frontend/dist/frontend/src/modules/request.d.ts +70 -0
  252. package/frontend/dist/frontend/src/modules/request.js +117 -0
  253. package/frontend/dist/frontend/src/modules/settings.d.ts +3 -0
  254. package/frontend/dist/frontend/src/modules/settings.js +5 -0
  255. package/frontend/dist/frontend/src/modules/statics.d.ts +21 -0
  256. package/frontend/dist/{modules → frontend/src/modules}/statics.js +15 -18
  257. package/frontend/dist/frontend/src/modules/support.d.ts +30 -0
  258. package/frontend/dist/frontend/src/modules/support.js +53 -0
  259. package/frontend/dist/{modules → frontend/src/modules}/theme.d.ts +67 -0
  260. package/frontend/dist/{modules → frontend/src/modules}/theme.js +68 -38
  261. package/frontend/dist/frontend/src/modules/themes.d.ts +12 -0
  262. package/frontend/dist/frontend/src/modules/themes.js +22 -0
  263. package/frontend/dist/frontend/src/modules/user.d.ts +164 -0
  264. package/frontend/dist/frontend/src/modules/user.js +268 -0
  265. package/frontend/dist/frontend/src/modules/utils.d.ts +176 -0
  266. package/frontend/dist/frontend/src/modules/utils.js +569 -0
  267. package/frontend/dist/frontend/src/types/gradient.d.ts +29 -0
  268. package/frontend/dist/{types → frontend/src/types}/gradient.js +14 -18
  269. package/frontend/dist/frontend/src/ui/border_button.d.ts +94 -0
  270. package/frontend/dist/{ui → frontend/src/ui}/border_button.js +7 -13
  271. package/frontend/dist/frontend/src/ui/button.d.ts +28 -0
  272. package/frontend/dist/{ui → frontend/src/ui}/button.js +21 -12
  273. package/frontend/dist/frontend/src/ui/canvas.d.ts +138 -0
  274. package/frontend/dist/{ui → frontend/src/ui}/canvas.js +88 -55
  275. package/frontend/dist/frontend/src/ui/checkbox.d.ts +74 -0
  276. package/frontend/dist/{ui → frontend/src/ui}/checkbox.js +80 -41
  277. package/frontend/dist/{ui → frontend/src/ui}/code.d.ts +73 -6
  278. package/frontend/dist/{ui → frontend/src/ui}/code.js +55 -52
  279. package/frontend/dist/{ui → frontend/src/ui}/context_menu.d.ts +4 -0
  280. package/frontend/dist/{ui → frontend/src/ui}/context_menu.js +12 -17
  281. package/frontend/dist/{ui → frontend/src/ui}/css.d.ts +4 -0
  282. package/frontend/dist/{ui → frontend/src/ui}/css.js +3 -3
  283. package/frontend/dist/{ui → frontend/src/ui}/divider.d.ts +4 -0
  284. package/frontend/dist/{ui → frontend/src/ui}/divider.js +3 -3
  285. package/frontend/dist/{ui → frontend/src/ui}/dropdown.d.ts +57 -2
  286. package/frontend/dist/{ui → frontend/src/ui}/dropdown.js +87 -94
  287. package/frontend/dist/{ui → frontend/src/ui}/for_each.d.ts +4 -0
  288. package/frontend/dist/{ui → frontend/src/ui}/for_each.js +3 -3
  289. package/frontend/dist/{ui → frontend/src/ui}/form.d.ts +6 -2
  290. package/frontend/dist/{ui → frontend/src/ui}/form.js +10 -7
  291. package/frontend/dist/frontend/src/ui/frame_modes.d.ts +37 -0
  292. package/frontend/dist/{ui → frontend/src/ui}/frame_modes.js +16 -22
  293. package/frontend/dist/{ui → frontend/src/ui}/google_map.d.ts +4 -0
  294. package/frontend/dist/{ui → frontend/src/ui}/google_map.js +4 -4
  295. package/frontend/dist/{ui → frontend/src/ui}/gradient.d.ts +4 -0
  296. package/frontend/dist/{ui → frontend/src/ui}/gradient.js +3 -3
  297. package/frontend/dist/{ui → frontend/src/ui}/image.d.ts +4 -0
  298. package/frontend/dist/{ui → frontend/src/ui}/image.js +5 -5
  299. package/frontend/dist/frontend/src/ui/input.d.ts +392 -0
  300. package/frontend/dist/{ui → frontend/src/ui}/input.js +346 -360
  301. package/frontend/dist/{ui → frontend/src/ui}/link.d.ts +4 -0
  302. package/frontend/dist/{ui → frontend/src/ui}/link.js +3 -3
  303. package/frontend/dist/{ui → frontend/src/ui}/list.d.ts +4 -0
  304. package/frontend/dist/{ui → frontend/src/ui}/list.js +12 -6
  305. package/frontend/dist/frontend/src/ui/loader_button.d.ts +80 -0
  306. package/frontend/dist/{ui → frontend/src/ui}/loader_button.js +35 -47
  307. package/frontend/dist/frontend/src/ui/loaders.d.ts +57 -0
  308. package/frontend/dist/{ui → frontend/src/ui}/loaders.js +11 -11
  309. package/frontend/dist/{ui → frontend/src/ui}/popup.d.ts +11 -6
  310. package/frontend/dist/{ui → frontend/src/ui}/popup.js +32 -18
  311. package/frontend/dist/frontend/src/ui/pseudo.d.ts +44 -0
  312. package/frontend/dist/{ui → frontend/src/ui}/pseudo.js +84 -8
  313. package/frontend/dist/{ui → frontend/src/ui}/scroller.d.ts +14 -2
  314. package/frontend/dist/{ui → frontend/src/ui}/scroller.js +37 -43
  315. package/frontend/dist/{ui → frontend/src/ui}/slider.d.ts +5 -1
  316. package/frontend/dist/{ui → frontend/src/ui}/slider.js +4 -4
  317. package/frontend/dist/{ui → frontend/src/ui}/spacer.d.ts +4 -0
  318. package/frontend/dist/{ui → frontend/src/ui}/spacer.js +3 -3
  319. package/frontend/dist/{ui → frontend/src/ui}/span.d.ts +4 -0
  320. package/frontend/dist/{ui → frontend/src/ui}/span.js +3 -3
  321. package/frontend/dist/{ui → frontend/src/ui}/stack.d.ts +4 -0
  322. package/frontend/dist/{ui → frontend/src/ui}/stack.js +3 -9
  323. package/frontend/dist/frontend/src/ui/steps.d.ts +131 -0
  324. package/frontend/dist/{ui → frontend/src/ui}/steps.js +30 -45
  325. package/frontend/dist/{ui → frontend/src/ui}/style.d.ts +4 -0
  326. package/frontend/dist/{ui → frontend/src/ui}/style.js +3 -3
  327. package/frontend/dist/{ui → frontend/src/ui}/switch.d.ts +5 -1
  328. package/frontend/dist/{ui → frontend/src/ui}/switch.js +4 -4
  329. package/frontend/dist/{ui → frontend/src/ui}/table.d.ts +4 -0
  330. package/frontend/dist/{ui → frontend/src/ui}/table.js +6 -6
  331. package/frontend/dist/{ui → frontend/src/ui}/tabs.d.ts +45 -3
  332. package/frontend/dist/{ui → frontend/src/ui}/tabs.js +65 -40
  333. package/frontend/dist/{ui → frontend/src/ui}/text.d.ts +4 -0
  334. package/frontend/dist/{ui → frontend/src/ui}/text.js +3 -3
  335. package/frontend/dist/frontend/src/ui/title.d.ts +91 -0
  336. package/frontend/dist/frontend/src/ui/title.js +272 -0
  337. package/frontend/dist/{ui → frontend/src/ui}/view.d.ts +4 -0
  338. package/frontend/dist/{ui → frontend/src/ui}/view.js +3 -3
  339. package/frontend/dist/{volt.d.ts → frontend/src/volt.d.ts} +3 -0
  340. package/frontend/dist/{volt.js → frontend/src/volt.js} +4 -0
  341. package/frontend/tools/bundle_d_ts.js +71 -0
  342. package/frontend/tools/convert_to_jsdoc_input.txt +9452 -0
  343. package/frontend/tools/convert_to_jsdoc_output.txt +7626 -0
  344. package/frontend/tools/convert_to_jsdoc_tmp.js +345 -0
  345. package/package.json +11 -12
  346. package/backend/dist/cjs/database/collection.d.ts +0 -160
  347. package/backend/dist/cjs/database/collection.js +0 -842
  348. package/backend/dist/cjs/database/database.d.ts +0 -121
  349. package/backend/dist/cjs/database/document.d.ts +0 -131
  350. package/backend/dist/cjs/database/document.js +0 -224
  351. package/backend/dist/cjs/database.d.ts +0 -502
  352. package/backend/dist/cjs/database.js +0 -2248
  353. package/backend/dist/cjs/logger.d.ts +0 -3
  354. package/backend/dist/cjs/meta.d.ts +0 -50
  355. package/backend/dist/cjs/mutex.d.ts +0 -24
  356. package/backend/dist/cjs/payments/paddle.d.ts +0 -160
  357. package/backend/dist/cjs/plugins/browser.d.ts +0 -36
  358. package/backend/dist/cjs/plugins/browser.js +0 -198
  359. package/backend/dist/cjs/plugins/css.d.ts +0 -11
  360. package/backend/dist/cjs/plugins/css.js +0 -80
  361. package/backend/dist/cjs/plugins/mail.d.ts +0 -277
  362. package/backend/dist/cjs/plugins/mail.js +0 -1370
  363. package/backend/dist/cjs/plugins/ts/compiler.d.ts +0 -139
  364. package/backend/dist/cjs/plugins/ts/compiler.js +0 -750
  365. package/backend/dist/cjs/plugins/ts/preprocessing.d.ts +0 -14
  366. package/backend/dist/cjs/plugins/ts/preprocessing.js +0 -440
  367. package/backend/dist/cjs/rate_limit.d.ts +0 -63
  368. package/backend/dist/cjs/rate_limit.js +0 -348
  369. package/backend/dist/cjs/request.deprc.d.ts +0 -48
  370. package/backend/dist/cjs/request.deprc.js +0 -572
  371. package/backend/dist/cjs/response.deprc.d.ts +0 -55
  372. package/backend/dist/cjs/response.deprc.js +0 -275
  373. package/backend/dist/cjs/server.d.ts +0 -342
  374. package/backend/dist/cjs/splash_screen.d.ts +0 -35
  375. package/backend/dist/cjs/status.d.ts +0 -61
  376. package/backend/dist/cjs/stream.d.ts +0 -79
  377. package/backend/dist/cjs/users.d.ts +0 -111
  378. package/backend/dist/cjs/users.js +0 -1817
  379. package/backend/dist/cjs/view.js +0 -352
  380. package/backend/dist/cjs/vinc.dev.d.ts +0 -3
  381. package/backend/dist/cjs/vinc.dev.js +0 -7
  382. package/backend/dist/css/adyen.css +0 -92
  383. package/backend/dist/css/volt.css +0 -70
  384. package/backend/dist/esm/database/collection.d.ts +0 -160
  385. package/backend/dist/esm/database/collection.js +0 -1328
  386. package/backend/dist/esm/database/database.d.ts +0 -121
  387. package/backend/dist/esm/database/document.d.ts +0 -131
  388. package/backend/dist/esm/database/document.js +0 -247
  389. package/backend/dist/esm/database.d.ts +0 -502
  390. package/backend/dist/esm/database.js +0 -2423
  391. package/backend/dist/esm/file_watcher.js +0 -329
  392. package/backend/dist/esm/logger.d.ts +0 -3
  393. package/backend/dist/esm/logger.js +0 -11
  394. package/backend/dist/esm/meta.d.ts +0 -50
  395. package/backend/dist/esm/mutex.d.ts +0 -24
  396. package/backend/dist/esm/mutex.js +0 -48
  397. package/backend/dist/esm/payments/paddle.d.ts +0 -160
  398. package/backend/dist/esm/plugins/browser.d.ts +0 -36
  399. package/backend/dist/esm/plugins/browser.js +0 -176
  400. package/backend/dist/esm/plugins/css.d.ts +0 -11
  401. package/backend/dist/esm/plugins/css.js +0 -90
  402. package/backend/dist/esm/plugins/ts/compiler.d.ts +0 -139
  403. package/backend/dist/esm/plugins/ts/compiler.js +0 -1194
  404. package/backend/dist/esm/plugins/ts/preprocessing.d.ts +0 -14
  405. package/backend/dist/esm/plugins/ts/preprocessing.js +0 -726
  406. package/backend/dist/esm/rate_limit.d.ts +0 -63
  407. package/backend/dist/esm/rate_limit.js +0 -417
  408. package/backend/dist/esm/request.deprc.d.ts +0 -48
  409. package/backend/dist/esm/request.deprc.js +0 -572
  410. package/backend/dist/esm/response.deprc.d.ts +0 -55
  411. package/backend/dist/esm/response.deprc.js +0 -275
  412. package/backend/dist/esm/server.d.ts +0 -342
  413. package/backend/dist/esm/splash_screen.d.ts +0 -35
  414. package/backend/dist/esm/status.d.ts +0 -61
  415. package/backend/dist/esm/status.js +0 -197
  416. package/backend/dist/esm/stream.d.ts +0 -79
  417. package/backend/dist/esm/users.d.ts +0 -111
  418. package/backend/dist/esm/users.js +0 -1935
  419. package/backend/dist/esm/vinc.dev.d.ts +0 -3
  420. package/backend/dist/esm/vinc.dev.js +0 -7
  421. package/frontend/dist/elements/base.d.ts +0 -9889
  422. package/frontend/dist/elements/module.d.ts +0 -30
  423. package/frontend/dist/modules/array.d.ts +0 -94
  424. package/frontend/dist/modules/array.js +0 -634
  425. package/frontend/dist/modules/auth.d.ts +0 -46
  426. package/frontend/dist/modules/auth.js +0 -139
  427. package/frontend/dist/modules/colors.d.ts +0 -1
  428. package/frontend/dist/modules/colors.js +0 -417
  429. package/frontend/dist/modules/compression.d.ts +0 -6
  430. package/frontend/dist/modules/compression.js +0 -999
  431. package/frontend/dist/modules/cookies.d.ts +0 -18
  432. package/frontend/dist/modules/cookies.js +0 -167
  433. package/frontend/dist/modules/date.d.ts +0 -142
  434. package/frontend/dist/modules/date.js +0 -493
  435. package/frontend/dist/modules/events.d.ts +0 -8
  436. package/frontend/dist/modules/events.js +0 -91
  437. package/frontend/dist/modules/google.d.ts +0 -11
  438. package/frontend/dist/modules/google.js +0 -54
  439. package/frontend/dist/modules/meta.d.ts +0 -10
  440. package/frontend/dist/modules/mutex.d.ts +0 -7
  441. package/frontend/dist/modules/mutex.js +0 -51
  442. package/frontend/dist/modules/number.d.ts +0 -16
  443. package/frontend/dist/modules/number.js +0 -23
  444. package/frontend/dist/modules/object.d.ts +0 -52
  445. package/frontend/dist/modules/object.js +0 -383
  446. package/frontend/dist/modules/scheme.d.ts +0 -227
  447. package/frontend/dist/modules/scheme.js +0 -531
  448. package/frontend/dist/modules/settings.d.ts +0 -3
  449. package/frontend/dist/modules/settings.js +0 -4
  450. package/frontend/dist/modules/statics.d.ts +0 -5
  451. package/frontend/dist/modules/string.d.ts +0 -124
  452. package/frontend/dist/modules/string.js +0 -745
  453. package/frontend/dist/modules/support.d.ts +0 -19
  454. package/frontend/dist/modules/support.js +0 -103
  455. package/frontend/dist/modules/themes.d.ts +0 -8
  456. package/frontend/dist/modules/themes.js +0 -18
  457. package/frontend/dist/modules/user.d.ts +0 -59
  458. package/frontend/dist/modules/user.js +0 -280
  459. package/frontend/dist/modules/utils.d.ts +0 -87
  460. package/frontend/dist/modules/utils.js +0 -923
  461. package/frontend/dist/types/gradient.d.ts +0 -12
  462. package/frontend/dist/ui/border_button.d.ts +0 -152
  463. package/frontend/dist/ui/button.d.ts +0 -21
  464. package/frontend/dist/ui/canvas.d.ts +0 -56
  465. package/frontend/dist/ui/checkbox.d.ts +0 -52
  466. package/frontend/dist/ui/frame_modes.d.ts +0 -25
  467. package/frontend/dist/ui/input.d.ts +0 -241
  468. package/frontend/dist/ui/loader_button.d.ts +0 -93
  469. package/frontend/dist/ui/loaders.d.ts +0 -57
  470. package/frontend/dist/ui/pseudo.d.ts +0 -16
  471. package/frontend/dist/ui/steps.d.ts +0 -59
  472. package/frontend/dist/ui/title.d.ts +0 -21
  473. package/frontend/dist/ui/title.js +0 -121
  474. package/frontend/examples/dashboard/dashboard.ts +0 -776
  475. /package/backend/dist/cjs/{cli.d.ts → backend/src/cli.d.ts} +0 -0
  476. /package/backend/dist/cjs/{file_watcher.d.ts → backend/src/database/document.d.ts} +0 -0
  477. /package/backend/dist/cjs/{file_watcher.js → backend/src/database/document.js} +0 -0
  478. /package/backend/dist/cjs/{plugins/pdf.d.ts → backend/src/database/filters/strict_filter_test.d.ts} +0 -0
  479. /package/backend/dist/{esm/file_watcher.d.ts → cjs/backend/src/database/filters/strict_filter_test_v0.d.ts} +0 -0
  480. /package/backend/dist/{esm/plugins/pdf.d.ts → cjs/backend/src/database/flatten_test.d.ts} +0 -0
  481. /package/backend/dist/cjs/{frontend.d.ts → backend/src/frontend.d.ts} +0 -0
  482. /package/backend/dist/cjs/{plugins → backend/src/plugins}/communication.d.ts +0 -0
  483. /package/backend/dist/cjs/{plugins → backend/src/plugins}/communication.js +0 -0
  484. /package/backend/dist/cjs/{plugins → backend/src/plugins}/mail/ui.js +0 -0
  485. /package/backend/dist/cjs/{plugins → backend/src/plugins}/pdf.js +0 -0
  486. /package/backend/dist/cjs/{plugins → backend/src/plugins}/thread_monitor.d.ts +0 -0
  487. /package/backend/dist/cjs/{plugins → backend/src/plugins}/thread_monitor.js +0 -0
  488. /package/backend/dist/cjs/{vinc.d.ts → backend/src/vinc.d.ts} +0 -0
  489. /package/backend/dist/cjs/{vinc.js → backend/src/vinc.js} +0 -0
  490. /package/backend/dist/esm/{cli.d.ts → backend/src/cli.d.ts} +0 -0
  491. /package/backend/dist/esm/{frontend.d.ts → backend/src/frontend.d.ts} +0 -0
  492. /package/backend/dist/esm/{plugins → backend/src/plugins}/communication.d.ts +0 -0
  493. /package/backend/dist/esm/{plugins → backend/src/plugins}/communication.js +0 -0
  494. /package/backend/dist/esm/{plugins → backend/src/plugins}/thread_monitor.d.ts +0 -0
  495. /package/backend/dist/esm/{plugins → backend/src/plugins}/thread_monitor.js +0 -0
  496. /package/backend/dist/esm/{vinc.d.ts → backend/src/vinc.d.ts} +0 -0
  497. /package/backend/dist/esm/{vinc.js → backend/src/vinc.js} +0 -0
  498. /package/frontend/dist/{elements → frontend/src/elements}/register_element.d.ts +0 -0
  499. /package/frontend/dist/{elements → frontend/src/elements}/register_element.js +0 -0
  500. /package/frontend/dist/{modules → frontend/src/modules}/color.d.ts +0 -0
  501. /package/frontend/dist/{ui → frontend/src/ui}/ui.d.ts +0 -0
  502. /package/frontend/dist/{ui → frontend/src/ui}/ui.js +0 -0
@@ -27,20 +27,21 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
27
27
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
28
28
  var stdin_exports = {};
29
29
  __export(stdin_exports, {
30
- Server: () => Server,
31
- default: () => stdin_default
30
+ Server: () => Server
32
31
  });
33
32
  module.exports = __toCommonJS(stdin_exports);
33
+ var import_url = require("url");
34
+ var path = __toESM(require("path"));
34
35
  var http = __toESM(require("http"));
35
36
  var http2 = __toESM(require("http2"));
36
37
  var crypto = __toESM(require("crypto"));
37
- var nodemailer = __toESM(require("nodemailer"));
38
38
  var import_cluster = __toESM(require("cluster"));
39
39
  var os = __toESM(require("os"));
40
40
  var vlib = __toESM(require("@vandenberghinc/vlib"));
41
41
  var import_utils = require("./utils.js");
42
42
  var import_meta2 = require("./meta.js");
43
- var Mail = __toESM(require("./plugins/mail/ui.js"));
43
+ var MailUI = __toESM(require("./plugins/mail/ui.js"));
44
+ var import_mail = require("./plugins/mail/mail.js");
44
45
  var import_status = require("./status.js");
45
46
  var import_endpoint = require("./endpoint.js");
46
47
  var import_image_endpoint = require("./image_endpoint.js");
@@ -49,15 +50,18 @@ var import_database = require("./database/database.js");
49
50
  var import_users = require("./users.js");
50
51
  var import_paddle = require("./payments/paddle.js");
51
52
  var import_rate_limit = require("./rate_limit.js");
52
- var import_logger = require("./logger.js");
53
53
  var import_route = require("./route.js");
54
+ var import_volt = require("@vandenberghinc/volt");
54
55
  const import_meta = {};
55
- var __dirname = typeof __dirname !== "undefined" ? __dirname : import_meta.dirname;
56
- const { log, error, warn } = import_logger.logger;
56
+ const __filename = (0, import_url.fileURLToPath)(import_meta.url);
57
+ const __dirname = path.dirname(__filename);
57
58
  const { debug } = vlib;
58
59
  class Server {
60
+ // ---------------------------------------------------------
59
61
  // Static attributes.
60
- static content_type_mimes = [
62
+ // ---------------------------------------------------------
63
+ /** Content type per mime. */
64
+ static content_type_mimes = /* @__PURE__ */ new Map([
61
65
  [".html", "text/html"],
62
66
  [".htm", "text/html"],
63
67
  [".shtml", "text/html"],
@@ -67,7 +71,7 @@ class Server {
67
71
  [".jpeg", "image/jpeg"],
68
72
  [".jpg", "image/jpeg"],
69
73
  [".js", "application/javascript"],
70
- [".ts", "application/javascript"],
74
+ [".ts", "application/typescript"],
71
75
  [".atom", "application/atom+xml"],
72
76
  [".rss", "application/rss+xml"],
73
77
  [".mml", "text/mathml"],
@@ -163,11 +167,9 @@ class Server {
163
167
  [".asf", "video/x-ms-asf"],
164
168
  [".wmv", "video/x-ms-wmv"],
165
169
  [".avi", "video/x-msvideo"]
166
- ];
167
- log;
168
- warn;
169
- error;
170
- static compressed_extensions = [
170
+ ]);
171
+ /** All file path extensions that are already compressed. */
172
+ static compressed_extensions = /* @__PURE__ */ new Set([
171
173
  ".png",
172
174
  ".jpg",
173
175
  ".jpeg",
@@ -176,7 +178,7 @@ class Server {
176
178
  ".bmp",
177
179
  ".tiff",
178
180
  ".ico",
179
- ".svg",
181
+ // ".svg",
180
182
  ".svgz",
181
183
  ".mng",
182
184
  ".apng",
@@ -205,68 +207,79 @@ class Server {
205
207
  ".mpg",
206
208
  ".mpeg",
207
209
  ".flv"
208
- ];
209
- // Instance properties
210
+ ]);
211
+ // ---------------------------------------------------------
212
+ // Attributes.
213
+ // ---------------------------------------------------------
214
+ /** The binded ip address. */
210
215
  ip;
216
+ /** The binded http port. */
211
217
  port;
218
+ /** The binded https port. */
212
219
  https_port;
220
+ /** The raw domain. */
213
221
  domain;
222
+ /** The full domain name with http/https depending if tls is enabled. */
214
223
  full_domain;
224
+ /** The persistent storage source directory. */
215
225
  source;
216
- // vlib.Path type
226
+ /** Is the primary thread. */
217
227
  is_primary;
218
- statics;
219
- statics_aspect_ratios;
220
- favicon;
221
- enable_2fa;
222
- enable_account_activation;
223
- token_expiration;
224
- google_tag;
228
+ /** Is in production mode. */
225
229
  production;
226
- // public localhost: boolean;
227
- multiprocessing;
228
- processes;
230
+ /** The company information. */
229
231
  company;
232
+ /** The default meta information. */
230
233
  meta;
231
- mail_style;
232
- online;
234
+ /** Is running in offline mode. */
233
235
  offline;
234
- // private honey_pot_key: string | null;
235
- _keys;
236
- additional_sitemap_endpoints;
237
- log_level;
238
- tls;
239
- // public admin: AdminConfig;
240
- // public ts: TypeScriptConfig;
241
- lightweight;
242
- performance;
243
- csp;
244
- default_headers;
245
- http;
246
- https;
247
- endpoints;
248
- err_endpoints;
236
+ /** The database instance. */
249
237
  db;
250
- _sys_db;
251
- // needs to be public for the RateLimit classes.
252
- storage;
253
- smtp;
254
- smtp_sender;
238
+ /** The rate limit instance. */
255
239
  rate_limit;
256
- blacklist;
257
- _hash_key = null;
240
+ /** The added endpoints. */
241
+ endpoints = /* @__PURE__ */ new Map();
242
+ /** The added error endpoints. */
243
+ err_endpoints = /* @__PURE__ */ new Map();
244
+ /** A record of keys used for hashing. */
258
245
  keys = {};
259
- _on_start = [];
260
- _on_initialize = [];
261
- _on_stop = [];
262
- // public browser_preview?: BrowserPreview;
263
- daemon;
264
- _stop_tscompiler_watcher;
265
- users;
266
- payments;
246
+ /** Alias for the `Status` module. */
267
247
  status;
248
+ /** Alias for the `RateLimits` module. */
268
249
  rate_limits;
269
- logger;
250
+ /** The file logger. */
251
+ log;
252
+ /** The users instance. */
253
+ users;
254
+ /** The payments instance. */
255
+ payments;
256
+ /** Daemon instance to manage a live daemon. */
257
+ daemon;
258
+ /** The mail instance. */
259
+ mail;
260
+ // Public for internal use:
261
+ csp;
262
+ statics_aspect_ratios;
263
+ google_tag;
264
+ rate_limit_api_key;
265
+ performance;
266
+ /** The events map @internal */
267
+ events = new vlib.Events();
268
+ // Private.
269
+ favicon;
270
+ statics;
271
+ _user_keys_opts;
272
+ additional_sitemap_endpoints;
273
+ tls;
274
+ default_headers;
275
+ http;
276
+ https;
277
+ threading;
278
+ // Private ollections.
279
+ _keys_db;
280
+ _sys_keys_db;
281
+ _website_status_db;
282
+ /** Construct a new server instance. */
270
283
  constructor({
271
284
  ip = "127.0.0.1",
272
285
  port,
@@ -280,46 +293,33 @@ class Server {
280
293
  company,
281
294
  meta = new import_meta2.Meta(),
282
295
  tls,
283
- smtp,
284
- mail_style = {
285
- font: '"Helvetica", sans-serif',
286
- title_fg: "#121B23",
287
- subtitle_fg: "#121B23",
288
- text_fg: "#1F2F3D",
289
- button_fg: "#FFFFFF",
290
- footer_fg: "#686B80",
291
- bg: "#EEEEEE",
292
- widget_bg: "#FFFFFF",
293
- widget_border: "#E6E6E6",
294
- button_bg: "#1F2F3D",
295
- divider_bg: "#706780"
296
- },
296
+ mail,
297
297
  rate_limit = {
298
298
  server: {
299
- ip: null,
299
+ ip: void 0,
300
300
  port: import_rate_limit.RateLimitServer.default_port,
301
- https: null
301
+ https: void 0
302
302
  },
303
303
  client: {
304
- ip: null,
304
+ ip: void 0,
305
305
  port: import_rate_limit.RateLimitServer.default_port,
306
- url: null
306
+ url: void 0
307
307
  }
308
308
  },
309
309
  keys = [],
310
310
  payments,
311
311
  default_headers,
312
312
  google_tag = void 0,
313
- token_expiration = 86400,
314
- enable_2fa = false,
315
- enable_account_activation = true,
313
+ users,
316
314
  production = false,
317
- multiprocessing = true,
318
- processes,
315
+ threading = {
316
+ enabled: false,
317
+ threads: void 0
318
+ },
319
319
  offline = false,
320
320
  additional_sitemap_endpoints = [],
321
321
  log_level = 0,
322
- daemon = {},
322
+ daemon = false
323
323
  // admin = {
324
324
  // password: null,
325
325
  // ips: [],
@@ -329,120 +329,7 @@ class Server {
329
329
  // output: undefined,
330
330
  // },
331
331
  // browser_preview = undefined,
332
- lightweight = false
333
332
  }) {
334
- vlib.Scheme.validate(arguments[0], { err_prefix: "Server: ", strict: true, scheme: {
335
- ip: { type: "string", required: false },
336
- port: { type: "number", required: false },
337
- domain: "string",
338
- statics: { type: "array", default: [] },
339
- is_primary: { type: "boolean", default: true },
340
- source: "string",
341
- database: {
342
- type: ["string", "object"],
343
- required: false,
344
- scheme: { ...import_database.Database.constructor_scheme, _server: void 0 }
345
- },
346
- favicon: { type: "string", required: false },
347
- // honey_pot_key: {type: "string", default: null},
348
- company: {
349
- type: "object",
350
- default: {},
351
- scheme: {
352
- name: "string",
353
- legal_name: "string",
354
- street: "string",
355
- house_number: "string",
356
- postal_code: "string",
357
- city: "string",
358
- province: "string",
359
- country: "string",
360
- country_code: "string",
361
- tax_id: { type: "string", default: null },
362
- icon: { type: "string", default: null },
363
- icon_path: { type: "string", default: null },
364
- stroke_icon: { type: "string", default: null },
365
- stroke_icon_path: { type: "string", default: null }
366
- }
367
- },
368
- meta: { type: "object", required: false },
369
- tls: {
370
- type: ["object"],
371
- required: false,
372
- scheme: {
373
- cert: "string",
374
- key: "string",
375
- ca: { type: "string", default: null },
376
- passphrase: { type: "string", default: null }
377
- }
378
- },
379
- rate_limit: {
380
- type: ["boolean", "object"],
381
- default: false,
382
- scheme: {
383
- server: { type: "object", default: {}, scheme: {
384
- ip: { type: "string", default: null },
385
- port: { type: "number", default: import_rate_limit.RateLimitServer.default_port },
386
- https: { type: "object", default: null }
387
- } },
388
- client: { type: "object", default: {}, scheme: {
389
- ip: { type: "string", default: null },
390
- port: { type: "number", default: import_rate_limit.RateLimitServer.default_port },
391
- url: { type: "string", default: null }
392
- } }
393
- }
394
- },
395
- keys: { type: "array", default: [] },
396
- smtp: { type: ["null", "object"], required: false },
397
- mail_style: {
398
- type: "object",
399
- required: false,
400
- scheme: {
401
- font: { type: "string", default: '"Helvetica", sans-serif' },
402
- title_fg: { type: "string", default: "#121B23" },
403
- subtitle_fg: { type: "string", default: "#121B23" },
404
- text_fg: { type: "string", default: "#1F2F3D" },
405
- button_fg: { type: "string", default: "#FFFFFF" },
406
- footer_fg: { type: "string", default: "#686B80" },
407
- bg: { type: "string", default: "#EEEEEE" },
408
- widget_bg: { type: "string", default: "#FFFFFF" },
409
- button_bg: { type: "string", default: "#421959" },
410
- widget_border: { type: "string", default: "#E6E6E6" },
411
- divider_bg: { type: "string", default: "#E6E6E6" }
412
- }
413
- },
414
- payments: { type: ["null", "object"], required: false },
415
- default_headers: { type: ["null", "object"], required: false },
416
- google_tag: { type: "string", required: false },
417
- token_expiration: { type: "number", required: false },
418
- enable_2fa: { type: "boolean", required: false },
419
- enable_account_activation: { type: "boolean", required: false },
420
- production: { type: "boolean", required: false },
421
- // localhost: { type: "boolean", required: false },
422
- multiprocessing: { type: "boolean", required: false, default: true },
423
- processes: { type: "number", required: false, default: null },
424
- offline: { type: "boolean", default: false },
425
- additional_sitemap_endpoints: { type: "array", default: [] },
426
- log_level: { type: "number", default: 0 },
427
- daemon: { type: ["object", "boolean"], default: {} },
428
- // admin: {type: "object", default: {}, attributes: {
429
- // ips: {type: "array", default: []},
430
- // password: {
431
- // type: "string",
432
- // verify: (param: string, attrs) => (param.length < 10 ? `Parameter "Server.admin.password" must have a length of at least 10 characters.` : undefined),
433
- // },
434
- // }},
435
- // ts: {
436
- // type: "object",
437
- // required: false,
438
- // scheme: {
439
- // compiler_opts: {type: "object", default: {}},
440
- // output: "string",
441
- // },
442
- // },
443
- // browser_preview: {type: ["string", "undefined"], required: false, default: undefined},
444
- lightweight: { type: "boolean", required: false }
445
- } });
446
333
  if (production || port == null) {
447
334
  this.port = 80;
448
335
  this.https_port = 443;
@@ -454,29 +341,36 @@ class Server {
454
341
  this.is_primary = is_primary && import_cluster.default.isPrimary;
455
342
  this.source = new vlib.Path(source);
456
343
  this.favicon = favicon;
457
- this.enable_2fa = enable_2fa;
458
- this.enable_account_activation = enable_account_activation;
459
- this.token_expiration = token_expiration;
460
344
  this.google_tag = google_tag;
461
345
  this.production = production;
462
- this.lightweight = lightweight;
463
- this.multiprocessing = multiprocessing;
464
- this.processes = processes == null ? os.cpus().length : processes;
465
346
  this.company = company;
466
- this.mail_style = mail_style;
467
347
  this.offline = offline;
468
- this.online = !offline;
469
- this._keys = keys;
348
+ this._user_keys_opts = keys;
470
349
  this.additional_sitemap_endpoints = additional_sitemap_endpoints;
471
- this.log_level = log_level;
472
350
  this.tls = tls;
473
- this.endpoints = /* @__PURE__ */ new Map();
474
- this.err_endpoints = /* @__PURE__ */ new Map();
475
- this.performance = new vlib.Performance("Server performance");
351
+ if (typeof threading === "boolean") {
352
+ this.threading = {
353
+ enabled: threading,
354
+ threads: os.cpus().length
355
+ };
356
+ } else {
357
+ this.threading = {
358
+ enabled: threading.enabled ?? true,
359
+ threads: threading.threads ?? os.cpus().length
360
+ };
361
+ }
476
362
  this.status = import_status.Status;
477
- this.logger = import_logger.logger;
478
363
  this.rate_limits = import_rate_limit.RateLimits;
479
- this.rate_limits.add({ group: "global", interval: 60, limit: 1e3 });
364
+ this.performance = new vlib.Performance("Server performance");
365
+ const log_source = this.source.join("logs");
366
+ if (!log_source.exists()) {
367
+ log_source.mkdir_sync({ recursive: true });
368
+ }
369
+ this.log = new vlib.logging.FileLogger({
370
+ level: log_level,
371
+ log_path: log_source.join("logs").str(),
372
+ error_path: log_source.join("errors").str()
373
+ });
480
374
  if (!this.source.exists()) {
481
375
  throw Error(`Source directory "${this.source.str()}" does not exist.`);
482
376
  }
@@ -485,9 +379,9 @@ class Server {
485
379
  while (this.domain.length > 0 && this.domain.charAt(this.domain.length - 1) === "/") {
486
380
  this.domain = this.domain.substr(0, this.domain.length - 1);
487
381
  }
488
- this.full_domain = `http${tls == null || tls.key == null ? "" : "s"}://${domain}`;
489
- while (this.full_domain.charAt(this.full_domain.length - 1) === "/") {
490
- this.full_domain = this.full_domain.substr(0, this.full_domain.length - 1);
382
+ this.full_domain = `http${this.tls ? "s" : ""}://${this.domain}`;
383
+ while (this.full_domain.endsWith("/")) {
384
+ this.full_domain = this.full_domain.slice(0, -1);
491
385
  }
492
386
  this.statics = statics;
493
387
  this.statics_aspect_ratios = /* @__PURE__ */ new Map();
@@ -508,23 +402,43 @@ class Server {
508
402
  }
509
403
  this.meta = meta;
510
404
  const base_default_headers = {
511
- "Vary": "Origin",
512
- "Referrer-Policy": "same-origin",
405
+ // Cache correctness for CORS/preflight:
406
+ "Vary": "Origin, Access-Control-Request-Method, Access-Control-Request-Headers",
407
+ // Safer default than same-origin, still keeps useful referrers:
408
+ "Referrer-Policy": "strict-origin-when-cross-origin",
513
409
  "Access-Control-Allow-Methods": "GET, POST, PUT, PATCH, DELETE, OPTIONS",
514
- "Access-Control-Allow-Origin": "*",
515
410
  "Access-Control-Allow-Headers": "Content-Type, Authorization",
516
- "Access-Control-Allow-Credentials": "true",
517
- "X-XSS-Protection": "1; mode=block",
411
+ // Let browsers read our rate-limit hint:
412
+ "Access-Control-Expose-Headers": "X-RateLimit-Reset",
518
413
  "X-Content-Type-Options": "nosniff",
519
- "frame-ancestors": "none",
520
414
  "X-Frame-Options": "DENY",
521
- "Strict-Transport-Security": "max-age=31536000"
415
+ // Helpful isolation defaults (safe for most apps):
416
+ "Cross-Origin-Opener-Policy": "same-origin",
417
+ "Cross-Origin-Resource-Policy": "same-site",
418
+ // If you need SharedArrayBuffer, add COEP below (can break some embeds):
419
+ // "Cross-Origin-Embedder-Policy": "require-corp",
420
+ "Strict-Transport-Security": "max-age=63072000; includeSubDomains; preload",
421
+ // Lock down powerful APIs by default.
422
+ // If you need one on a third-party origin, add it beside (self).
423
+ "Permissions-Policy": "accelerometer=(), camera=(), geolocation=(), gyroscope=(), magnetometer=(), microphone=(), midi=(), payment=(), usb=(), hid=(), serial=(), xr-spatial-tracking=(), display-capture=(), screen-wake-lock=(), sync-xhr=(), publickey-credentials-get=(self), encrypted-media=(self), autoplay=(self 'https://www.youtube-nocookie.com') fullscreen=(self 'https://www.youtube-nocookie.com'), browsing-topics=()"
424
+ // Do NOT set Allow-Origin / Credentials statically; set them per-request below.
425
+ // "X-XSS-Protection": "1; mode=block", // deprecated
522
426
  };
523
427
  const default_csp = {
524
- "default-src": "'self' https://*.google-analytics.com",
525
- "img-src": `'self' http://${this.domain} https://${this.domain} https://*.google-analytics.com https://raw.githubusercontent.com/vandenberghinc/ `,
526
- "script-src": "'self' 'unsafe-inline' https://ajax.googleapis.com https://www.googletagmanager.com https://googletagmanager.com https://*.google-analytics.com https://code.jquery.com https://cdn.jsdelivr.net/npm/@vandenberghinc/",
527
- "style-src": "'self' 'unsafe-inline' https://cdn.jsdelivr.net/npm/@vandenberghinc/"
428
+ "default-src": "'self'",
429
+ "base-uri": "'none'",
430
+ "object-src": "'none'",
431
+ "form-action": "'self'",
432
+ "frame-ancestors": "'none'",
433
+ // Keep GA images; drop explicit http:// to avoid mixed content.
434
+ "img-src": "'self' data: blob: https://*.google-analytics.com",
435
+ "script-src": "'self' https://ajax.googleapis.com https://www.googletagmanager.com https://*.google-analytics.com",
436
+ // Needed for GA/GTAG beacons/fetch:
437
+ "connect-src": "'self' https://*.google-analytics.com",
438
+ "style-src": "'self'",
439
+ "font-src": "'self' data:",
440
+ // Auto-upgrade stray http URLs where possible:
441
+ "upgrade-insecure-requests": ""
528
442
  };
529
443
  if (default_headers == null) {
530
444
  this.csp = default_csp;
@@ -541,6 +455,9 @@ class Server {
541
455
  });
542
456
  this.default_headers = default_headers;
543
457
  }
458
+ if (!this.tls) {
459
+ delete this.default_headers["Strict-Transport-Security"];
460
+ }
544
461
  if (payments) {
545
462
  if (payments.type === "paddle") {
546
463
  this.payments = new import_paddle.Paddle({
@@ -551,47 +468,49 @@ class Server {
551
468
  throw Error(`Invalid payment processor type "${payments.type}", valid types are ["paddle"].`);
552
469
  }
553
470
  }
554
- this.endpoints = /* @__PURE__ */ new Map();
555
- this.err_endpoints = /* @__PURE__ */ new Map();
556
- const log_source = this.source.join("logs");
557
- if (!log_source.exists()) {
558
- log_source.mkdir_sync();
559
- }
560
- import_logger.logger.log_level.set(this.log_level);
561
- if (daemon === false) {
562
- import_logger.logger.assign_paths(log_source.join("logs").str(), log_source.join("errors").str());
563
- }
564
- this.log = import_logger.logger.log.bind(import_logger.logger);
565
- this.warn = import_logger.logger.warn.bind(import_logger.logger);
566
- this.error = import_logger.logger.error.bind(import_logger.logger);
567
471
  if (daemon !== false) {
568
472
  const log_source2 = this.source.join("daemon");
569
473
  if (!log_source2.exists()) {
570
- log_source2.mkdir_sync();
474
+ log_source2.mkdir_sync({ recursive: true });
571
475
  }
572
476
  this.daemon = new vlib.Daemon({
573
477
  name: this.domain.replaceAll(".", ""),
574
- user: daemon.user || os.userInfo().username,
575
- group: daemon.group || null,
576
- command: "volt --service --start",
577
- cwd: this.source.str(),
578
- args: daemon.args || [],
579
- env: daemon.env || {},
580
- description: daemon.description || `Service daemon for website ${this.domain}.`,
581
- auto_restart: true,
582
478
  logs: daemon.logs || log_source2.join("logs").str(),
583
- errors: daemon.errors || log_source2.join("errors").str()
479
+ errors: daemon.errors || log_source2.join("errors").str(),
480
+ ...daemon
481
+ // user: (daemon as Record<string, any>).user || os.userInfo().username,
482
+ // group: (daemon as Record<string, any>).group || null,
483
+ // command: "volt --service --start",
484
+ // cwd: this.source.str(),
485
+ // args: (daemon as Record<string, any>).args || [],
486
+ // env: (daemon as Record<string, any>).env || {},
487
+ // description: (daemon as Record<string, any>).description || `Service daemon for website ${this.domain}.`,
488
+ // auto_restart: true,
584
489
  });
585
490
  }
586
491
  if (typeof database === "string") {
587
492
  this.db = new import_database.Database({ uri: database, _server: this });
588
- } else if (database != null) {
493
+ } else {
589
494
  this.db = new import_database.Database({ ...database, _server: this });
590
495
  }
591
- this.users = new import_users.Users(this);
592
- if (smtp) {
593
- this.smtp_sender = smtp.sender;
594
- this.smtp = nodemailer.createTransport(smtp);
496
+ this._keys_db = this.db.collection({
497
+ name: "Volt.Keys",
498
+ indexes: ["id"]
499
+ });
500
+ this._sys_keys_db = this.db.collection({
501
+ name: "Volt.SystemKeys",
502
+ indexes: ["id"]
503
+ });
504
+ this._website_status_db = this.db.collection({
505
+ name: "Volt.WebsiteStatus",
506
+ indexes: ["id"]
507
+ });
508
+ this.users = new import_users.Users({
509
+ ...users,
510
+ _server: this
511
+ });
512
+ if (mail) {
513
+ this.mail = new import_mail.Mail(mail);
595
514
  }
596
515
  if (rate_limit) {
597
516
  if (this.is_primary) {
@@ -606,44 +525,36 @@ class Server {
606
525
  }
607
526
  // ---------------------------------------------------------
608
527
  // Utils.
609
- // Get a content type from an extension.
528
+ /** Get a content type (MIME) from a file extension. */
610
529
  get_content_type(extension) {
611
- let content_type = Server.content_type_mimes.find((item) => {
612
- if (item[0] == extension) {
613
- return item[1];
614
- }
615
- })?.[1];
616
- if (content_type == null) {
617
- content_type = "application/octet-stream";
618
- }
619
- return content_type;
530
+ return Server.content_type_mimes.get(extension.toLowerCase()) ?? "application/octet-stream";
620
531
  }
621
- // Set log level.
532
+ /** Set the logging verbosity level. */
622
533
  set_log_level(level) {
623
- this.log_level = level;
624
- import_logger.logger.log_level.set(level);
534
+ this.log.level.set(level);
625
535
  }
626
536
  // ---------------------------------------------------------
627
537
  // Crypto (private).
628
- // Generate a crypto key.
538
+ /** Generate a cryptographically secure random key as a hex string. */
629
539
  generate_crypto_key(length = 32) {
630
540
  return crypto.randomBytes(length).toString("hex");
631
541
  }
632
- // Create a sha hmac with the master key.
542
+ /** Create an HMAC hash using the provided key and data. */
633
543
  hmac(key, data, algo = "sha256") {
634
544
  const hmac = crypto.createHmac(algo, key);
635
545
  hmac.update(data);
636
546
  return hmac.digest("hex");
637
547
  }
638
- _hmac(data) {
639
- if (!this._hash_key) {
640
- throw new Error("Hash key not initialized");
641
- }
642
- const hmac = crypto.createHmac("sha256", this._hash_key);
643
- hmac.update(data);
644
- return hmac.digest("hex");
645
- }
646
- // Hash without a key.
548
+ // /** Create an HMAC hash using the server's master hash key. */
549
+ // hmac_with_master(data: string): string {
550
+ // if (!this._master_hash_key) {
551
+ // throw new Error("Hash key not initialized");
552
+ // }
553
+ // const hmac = crypto.createHmac("sha256", this._master_hash_key);
554
+ // hmac.update(data);
555
+ // return hmac.digest("hex");
556
+ // }
557
+ /** Create a hash (no key) of the given data using the specified algorithm. */
647
558
  hash(data, algo = "sha256") {
648
559
  if (typeof data !== "string") {
649
560
  data = JSON.stringify(data);
@@ -668,6 +579,23 @@ class Server {
668
579
  // Add header defaults.
669
580
  _set_header_defaults(stream) {
670
581
  stream.set_headers(this.default_headers);
582
+ const origin = stream.headers.origin;
583
+ if (origin) {
584
+ const same_http = `http://${this.domain}`;
585
+ const same_https = `https://${this.domain}`;
586
+ if (origin === same_http || origin === same_https) {
587
+ stream.set_header("Access-Control-Allow-Origin", origin);
588
+ stream.set_header("Access-Control-Allow-Credentials", "true");
589
+ } else {
590
+ stream.set_header("Access-Control-Allow-Origin", "*");
591
+ }
592
+ const req_hdrs = stream.headers["access-control-request-headers"];
593
+ if (req_hdrs)
594
+ stream.set_header("Access-Control-Allow-Headers", String(req_hdrs));
595
+ const req_method = stream.headers["access-control-request-method"];
596
+ if (req_method)
597
+ stream.set_header("Access-Control-Allow-Methods", String(req_method));
598
+ }
671
599
  }
672
600
  _find_endpoint(endpoint, method) {
673
601
  let route;
@@ -702,12 +630,12 @@ class Server {
702
630
  data: favicon.load_sync({ type: "buffer" }),
703
631
  content_type: this.get_content_type(favicon.extension()),
704
632
  _is_static: true,
705
- _server: this
633
+ server: this
706
634
  });
707
635
  }
708
636
  const status_dir = this.source.join(".status");
709
637
  if (!status_dir.exists()) {
710
- status_dir.mkdir_sync();
638
+ status_dir.mkdir_sync({ recursive: true });
711
639
  }
712
640
  const status_key_path = status_dir.join("key");
713
641
  let status_key;
@@ -740,9 +668,10 @@ class Server {
740
668
  if (this.https) {
741
669
  status.https_port = this.https_port;
742
670
  }
743
- const data = await this._sys_db.load("status", {
671
+ const data = await this._website_status_db.load({ id: "status" }, {
744
672
  default: {
745
- running_since: null,
673
+ id: "status",
674
+ running_since: void 0,
746
675
  running_threads: 0,
747
676
  total_threads: 0
748
677
  }
@@ -758,17 +687,17 @@ class Server {
758
687
  }
759
688
  // Create the sitemap endpoint.
760
689
  async _create_sitemap() {
761
- if (this.lightweight) {
762
- return;
763
- }
764
- log(2, "Creating sitemap.");
690
+ this.log(2, "Creating sitemap.");
765
691
  let sitemap = "";
766
692
  sitemap += '<?xml version="1.0" encoding="UTF-8"?>\n';
767
693
  sitemap += '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">\n';
768
694
  for (const endpoint of this.endpoints.values()) {
769
695
  if (endpoint.allow_sitemap) {
696
+ if (endpoint.route.is_regex)
697
+ continue;
698
+ const ep = encodeURI(endpoint.route.endpoint_str.startsWith("/") ? endpoint.route.endpoint_str : `/${endpoint.route.endpoint_str}`);
770
699
  sitemap += `<url>
771
- <loc>${this.full_domain}/${endpoint.route.endpoint_str}</loc>
700
+ <loc>${this.full_domain}${ep}</loc>
772
701
  </url>
773
702
  `;
774
703
  }
@@ -793,10 +722,7 @@ class Server {
793
722
  }
794
723
  // Create the robots.txt endpoint.
795
724
  async _create_robots_txt() {
796
- if (this.lightweight) {
797
- return;
798
- }
799
- log(2, "Creating robots.txt.");
725
+ this.log(2, "Creating robots.txt.");
800
726
  let robots = "User-agent: *\n";
801
727
  let disallowed = 0;
802
728
  for (const endpoint of this.endpoints.values()) {
@@ -825,8 +751,7 @@ Sitemap: ${this.full_domain}/sitemap.xml`;
825
751
  /* private _create_admin_endpoint(): void {
826
752
 
827
753
  // Logs.
828
- if (this.lightweight) { return; }
829
- log(2, "Creating admin endpoint.");
754
+ this.log(2, "Creating admin endpoint.");
830
755
 
831
756
  // Add admin tokens.
832
757
  this.admin.tokens = [];
@@ -862,7 +787,7 @@ Sitemap: ${this.full_domain}/sitemap.xml`;
862
787
  password: "string",
863
788
  },
864
789
  ip_whitelist: this.admin.ips,
865
- callback: async (stream: any, params: {password: string}) => {
790
+ callback: async (stream: Stream, params: {password: string}) => {
866
791
  // Check key.
867
792
  if (params.password !== this.admin.password) {
868
793
  return stream.send({
@@ -898,7 +823,7 @@ Sitemap: ${this.full_domain}/sitemap.xml`;
898
823
  token: "string",
899
824
  },
900
825
  ip_whitelist: this.admin.ips,
901
- callback: async (stream: any, params: {token: string}) => {
826
+ callback: async (stream: Stream, params: {token: string}) => {
902
827
  // Verify token.
903
828
  if (!verify_token(params.token)) {
904
829
  return stream.send({
@@ -976,16 +901,16 @@ Sitemap: ${this.full_domain}/sitemap.xml`;
976
901
  } */
977
902
  // Initialize statics.
978
903
  async _initialize_statics() {
979
- log(2, "Initializing static directories.");
904
+ this.log(2, "Initializing static directories.");
980
905
  const static_paths = [];
981
- const add_static_file = async (path, endpoint, cache = true) => {
982
- static_paths.push(path.str());
983
- const content_type = this.get_content_type(path.extension());
984
- if (import_image_endpoint.ImageEndpoint.supported_images.includes(path.extension())) {
906
+ const add_static_file = async (path2, endpoint, cache = true) => {
907
+ static_paths.push(path2.str());
908
+ const content_type = this.get_content_type(path2.extension());
909
+ if (import_image_endpoint.ImageEndpoint.supported_images.includes(path2.extension())) {
985
910
  const e = new import_image_endpoint.ImageEndpoint({
986
911
  endpoint,
987
912
  content_type,
988
- path,
913
+ path: path2,
989
914
  cache,
990
915
  rate_limit: "global",
991
916
  _is_static: true
@@ -1000,12 +925,12 @@ Sitemap: ${this.full_domain}/sitemap.xml`;
1000
925
  method: "GET",
1001
926
  endpoint,
1002
927
  content_type,
1003
- compress: !Server.compressed_extensions.includes(path.extension()),
928
+ compress: !Server.compressed_extensions.has(path2.extension().toLowerCase()),
1004
929
  cache,
1005
930
  rate_limit: "global",
1006
- _static_path: path.str(),
931
+ file_path: path2,
1007
932
  _is_static: true
1008
- })._load_data_by_path(this));
933
+ }));
1009
934
  }
1010
935
  };
1011
936
  const add_static = async (opts) => {
@@ -1013,9 +938,10 @@ Sitemap: ${this.full_domain}/sitemap.xml`;
1013
938
  return;
1014
939
  }
1015
940
  if (typeof opts === "object") {
1016
- vlib.Scheme.validate(opts, {
1017
- strict: true,
1018
- scheme: {
941
+ vlib.schema.validate(opts, {
942
+ unknown: false,
943
+ throw: true,
944
+ schema: {
1019
945
  path: "string",
1020
946
  endpoint: { type: "string", default: null },
1021
947
  cache: { type: ["boolean", "number"], default: true },
@@ -1023,27 +949,18 @@ Sitemap: ${this.full_domain}/sitemap.xml`;
1023
949
  exclude: { type: "array", default: [] }
1024
950
  }
1025
951
  });
1026
- const exclude = [/.*\.DS_Store/, /.*\.cache/, /.*\.old/, /.*\.ignore/, ...opts.exclude || []];
1027
952
  const paths = [];
1028
953
  const source = new vlib.Path(opts.path).abs();
954
+ if (!source.exists()) {
955
+ this.log(1, `Static path "${source.str()}" does not exist; skipping.`);
956
+ return;
957
+ }
1029
958
  const source_len = source.str().length;
1030
959
  const is_dir = source.is_dir();
1031
- const is_excluded = (path) => {
1032
- return exclude.some((pattern) => {
1033
- if (path instanceof RegExp) {
1034
- if (pattern instanceof RegExp) {
1035
- return pattern.source === path.source;
1036
- } else {
1037
- return path.test(String(pattern));
1038
- }
1039
- } else {
1040
- if (pattern instanceof RegExp) {
1041
- return pattern.test(String(path));
1042
- } else {
1043
- return path === pattern;
1044
- }
1045
- }
1046
- });
960
+ const exclude = [/\.DS_Store$/, /\.cache(?:\/|$)/, /\.old(?:\/|$)/, /\.ignore$/, ...opts.exclude || []];
961
+ const is_excluded = (p) => {
962
+ const s = typeof p === "string" ? p : p.str();
963
+ return exclude.some((pattern) => pattern instanceof RegExp ? pattern.test(s) : s === String(pattern));
1047
964
  };
1048
965
  opts.endpoint = opts.endpoint || `/${source.full_name()}`;
1049
966
  if (opts.endpoint.charAt(0) != "/") {
@@ -1055,8 +972,8 @@ Sitemap: ${this.full_domain}/sitemap.xml`;
1055
972
  if (!is_dir) {
1056
973
  return await add_static_file(source, opts.endpoint, opts.cache);
1057
974
  }
1058
- const read_dir = async (path) => {
1059
- const dir_paths = await path.paths();
975
+ const read_dir = async (path2) => {
976
+ const dir_paths = await path2.paths();
1060
977
  const promises = [];
1061
978
  for (let i = 0; i < dir_paths.length; i++) {
1062
979
  if (!is_excluded(dir_paths[i])) {
@@ -1073,9 +990,9 @@ Sitemap: ${this.full_domain}/sitemap.xml`;
1073
990
  if (is_dir) {
1074
991
  await read_dir(source);
1075
992
  }
1076
- for (const path of paths) {
1077
- const endpoint = `${opts.endpoint}${path.str().substr(source_len)}`;
1078
- await add_static_file(path, endpoint, opts.endpoints_cache === void 0 ? opts.cache : opts.endpoints_cache[endpoint] ?? opts.cache);
993
+ for (const path2 of paths) {
994
+ const endpoint = `${opts.endpoint}${path2.str().substr(source_len)}`;
995
+ await add_static_file(path2, endpoint, opts.endpoints_cache === void 0 ? opts.cache : opts.endpoints_cache[endpoint] ?? opts.cache);
1079
996
  }
1080
997
  } else if (typeof opts === "string") {
1081
998
  await add_static({ path: opts });
@@ -1089,161 +1006,78 @@ Sitemap: ${this.full_domain}/sitemap.xml`;
1089
1006
  }
1090
1007
  return static_paths;
1091
1008
  }
1092
- // ---------------------------------------------------------
1093
- // Server (private).
1094
- // Initialize.
1095
- // Initialize.
1096
- async initialize() {
1097
- log(1, "Initializing server.");
1098
- this.performance.start();
1099
- if (this.tls) {
1100
- this.https = http2.createSecureServer(
1101
- {
1102
- key: new vlib.Path(this.tls.key).load_sync({ encoding: "utf8" }),
1103
- cert: new vlib.Path(this.tls.cert).load_sync({ encoding: "utf8" }),
1104
- ca: this.tls.ca == null ? void 0 : new vlib.Path(this.tls.ca).load_sync({ encoding: "utf8" }),
1105
- passphrase: this.tls.passphrase,
1106
- allowHTTP1: true
1107
- },
1108
- // Support for http1.
1109
- // Does not work, requests get triggered on the stream and on this callback.
1110
- (req, res) => {
1111
- if (req.httpVersion.charAt(0) !== "2") {
1112
- this._serve(void 0, void 0, req, res);
1113
- }
1114
- }
1115
- );
1116
- this.https.on("stream", (stream, headers) => {
1117
- this._serve(stream, headers, void 0, void 0);
1118
- });
1119
- } else if (this.production && this.payments) {
1120
- throw Error("Accepting payments in production mode requires HTTPS.");
1121
- }
1122
- if (this.tls) {
1123
- this.http = http.createServer((request, response) => {
1124
- response.writeHead(301, { Location: `https://${request.headers.host}${request.url}` });
1125
- response.end();
1126
- });
1009
+ /** Initialize the system and user defined keys. */
1010
+ async _initialize_keys() {
1011
+ const start = Date.now();
1012
+ await this._db_init_promise;
1013
+ this.performance.end("_initialize_keys():await-db-init", start);
1014
+ const sys_keys = await this._sys_keys_db.load({ id: "sys_keys" }, {
1015
+ default: {
1016
+ id: "sys_keys",
1017
+ rate_limit_api_key: void 0
1018
+ }
1019
+ });
1020
+ let perform_sys_keys_save = false;
1021
+ if (sys_keys.rate_limit_api_key == null) {
1022
+ this.rate_limit_api_key = this.generate_crypto_key(32);
1023
+ sys_keys.rate_limit_api_key = this.rate_limit_api_key;
1024
+ perform_sys_keys_save = true;
1127
1025
  } else {
1128
- this.http = http.createServer((req, res) => {
1129
- this._serve(void 0, void 0, req, res);
1130
- });
1026
+ this.rate_limit_api_key = sys_keys.rate_limit_api_key;
1131
1027
  }
1132
- this.performance.end("create-http-server");
1133
- if (this.db) {
1134
- await this.db.initialize();
1135
- this.performance.end("init-db");
1136
- this._sys_db = await this.db.collection({
1137
- name: "Volt.System",
1138
- indexes: ["_path"]
1139
- });
1140
- this.performance.end("init-sys-collection");
1141
- const keys_document = await this._sys_db.load("keys");
1142
- const gen_user_crypto_key = (doc, key) => {
1028
+ if (perform_sys_keys_save) {
1029
+ await this._sys_keys_db.set({ id: "sys_keys" }, sys_keys);
1030
+ }
1031
+ const user_keys = await this._keys_db.load({ id: "user_keys" }, {
1032
+ default: {
1033
+ id: "user_keys",
1034
+ keys: {}
1035
+ }
1036
+ });
1037
+ let perform_user_keys_save = false;
1038
+ for (const key of this._user_keys_opts) {
1039
+ const name = typeof key === "string" ? key : key.name;
1040
+ if (user_keys[name]) {
1041
+ this.keys[name] = user_keys[name];
1042
+ } else {
1043
+ perform_user_keys_save = true;
1143
1044
  if (typeof key === "string") {
1144
- doc[key] = this.generate_crypto_key(32);
1045
+ if (!key) {
1046
+ throw Error(`Crypto key "${key}" is an invalid key name.`);
1047
+ }
1048
+ const generated_key = this.generate_crypto_key(32);
1049
+ user_keys.keys[key] = generated_key;
1050
+ this.keys[key] = generated_key;
1145
1051
  } else {
1052
+ if (!key.name) {
1053
+ throw Error(`Crypto key "${key.name}" is an invalid key name.`);
1054
+ }
1146
1055
  if (key.length == null) {
1147
- throw Error(`Crypto key object "${JSON.stringify(key)}" does not contain a "length" attribute.`);
1056
+ throw Error(`Crypto key "${key.name}" does not contain a "length" attribute.`);
1148
1057
  }
1149
1058
  if (typeof key.length !== "number") {
1150
- throw Error(`Crypto key object "${JSON.stringify(key)}" has an invalid type fo attribute "length", the valid type is "number".`);
1151
- }
1152
- if (key.name == null) {
1153
- throw Error(`Crypto key object "${JSON.stringify(key)}" does not contain a "name" attribute.`);
1154
- }
1155
- if (typeof key.name !== "string") {
1156
- throw Error(`Crypto key object "${JSON.stringify(key)}" has an invalid type fo attribute "name", the valid type is "string".`);
1157
- }
1158
- doc[key.name] = this.generate_crypto_key(key.length);
1159
- this.keys[key.name] = doc[key.name];
1160
- }
1161
- };
1162
- if (keys_document == null) {
1163
- this._hash_key = this.generate_crypto_key(32);
1164
- const doc = {
1165
- _master_sha256: this._hash_key
1166
- };
1167
- this._keys.forEach((key) => {
1168
- gen_user_crypto_key(doc, key);
1169
- });
1170
- await this._sys_db.save("keys", doc);
1171
- } else {
1172
- this._hash_key = keys_document._master_sha256;
1173
- let perform_save = false;
1174
- if (this._hash_key === void 0) {
1175
- this._hash_key = this.generate_crypto_key(32);
1176
- keys_document._master_sha256 = this._hash_key;
1177
- perform_save = true;
1178
- }
1179
- this._keys.forEach((key) => {
1180
- let name = typeof key === "string" ? key : key.name;
1181
- if (keys_document[name] == null) {
1182
- gen_user_crypto_key(keys_document, key);
1183
- perform_save = true;
1059
+ throw Error(`Crypto key "${key.name}" has an invalid type for attribute "length", the valid type is "number".`);
1184
1060
  }
1185
- this.keys[name] = keys_document[name];
1186
- });
1187
- if (perform_save) {
1188
- await this._sys_db.save("keys", keys_document);
1061
+ const generated_key = this.generate_crypto_key(key.length);
1062
+ user_keys.keys[key.name] = generated_key;
1063
+ this.keys[key.name] = generated_key;
1189
1064
  }
1190
1065
  }
1191
- this.performance.end("load-keys");
1192
- }
1193
- this._init_default_headers();
1194
- this.performance.end("init-default-headers");
1195
- this._create_default_endpoints();
1196
- this.performance.end("create-default-endpoints");
1197
- const promises = [];
1198
- promises.push(this._initialize_statics());
1199
- if (this.db) {
1200
- promises.push(this.users._initialize());
1201
1066
  }
1202
- if (this.payments !== void 0) {
1203
- promises.push(this.payments._initialize());
1204
- }
1205
- if (this._find_endpoint("sitemap.xml") == null) {
1206
- promises.push(this._create_sitemap());
1207
- }
1208
- if (this._find_endpoint("robots.txt") == null) {
1209
- promises.push(this._create_robots_txt());
1210
- }
1211
- await Promise.all(promises);
1212
- if (this.company.stroke_icon || this.company.icon) {
1213
- for (const endpoint of this.endpoints.values()) {
1214
- if (this.company.stroke_icon_path == null && endpoint.route.endpoint === this.company.stroke_icon) {
1215
- this.company.stroke_icon_path = endpoint._static_path ?? void 0;
1216
- }
1217
- if (this.company.icon_path == null && endpoint.route.endpoint === this.company.icon) {
1218
- this.company.icon_path = endpoint._static_path ?? void 0;
1219
- }
1220
- }
1221
- if (this.company.stroke_icon != null && this.company.stroke_icon_path == null) {
1222
- throw Error(`Unable to find the company's stroke icon endpoint "${this.company.stroke_icon}".`);
1223
- }
1224
- if (this.company.icon != null && this.company.icon_path == null) {
1225
- throw Error(`Unable to find the company's icon endpoint "${this.company.icon}".`);
1226
- }
1227
- }
1228
- for (const endpoint of this.endpoints.values()) {
1229
- endpoint._initialize(this);
1230
- }
1231
- for (const endpoint of this.err_endpoints.values()) {
1232
- endpoint._initialize(this);
1233
- }
1234
- for (const callback of this._on_initialize) {
1235
- const res = callback();
1236
- if (res instanceof Promise) {
1237
- await res;
1238
- }
1067
+ if (perform_user_keys_save) {
1068
+ await this._keys_db.set({ id: "user_keys" }, user_keys);
1239
1069
  }
1240
1070
  }
1241
1071
  /**
1242
- * Add callback to be called when the server is initialized.
1243
- * @param callback The callback to be called when the server is initialized.
1072
+ * Checks if an endpoint route already exists.
1073
+ * @param method HTTP method
1074
+ * @param endpoint String path or RegExp
1244
1075
  */
1245
- on_initialize(callback) {
1246
- this._on_initialize.append(callback);
1076
+ _check_duplicate_route(route) {
1077
+ const e = this._find_endpoint(route);
1078
+ if (e) {
1079
+ throw new Error(`Duplicate "${route.method}:${route.endpoint_str}" endpoint route, it is already defined by endpoint "${e.id}".`);
1080
+ }
1247
1081
  }
1248
1082
  // Serve a client.
1249
1083
  // @todo implement rate limiting.
@@ -1254,12 +1088,12 @@ Sitemap: ${this.full_domain}/sitemap.xml`;
1254
1088
  let endpoint;
1255
1089
  let method;
1256
1090
  let endpoint_url;
1257
- const log_endpoint_result = (message = null, status = null) => {
1091
+ const log_endpoint_result = (message, status) => {
1258
1092
  let log_level = endpoint && endpoint.is_static ? 3 : 0;
1259
1093
  if (status == null) {
1260
1094
  status = stream.status_code;
1261
1095
  }
1262
- log(log_level, `${method}:${endpoint_url}: ${message ? message : import_status.Status.get_description(status)} [${status}] (${stream.ip}).`);
1096
+ this.log(log_level, `${method}:${endpoint_url}: ${message ? message : import_status.Status.get_description(status ?? "unknown")} [${status}] (${stream.ip}).`);
1263
1097
  };
1264
1098
  const serve_error_endpoint = async (status_code) => {
1265
1099
  const is_api_endpoint = endpoint && endpoint.callback != null;
@@ -1303,31 +1137,27 @@ Sitemap: ${this.full_domain}/sitemap.xml`;
1303
1137
  try {
1304
1138
  await err_endpoint._serve(stream, status_code);
1305
1139
  } catch (err) {
1306
- error(`Error endpoint ${status_code}: `, err);
1140
+ this.log.error(`Error endpoint ${status_code}: `, err);
1307
1141
  stream.send(default_response);
1308
1142
  }
1309
1143
  }
1310
1144
  }
1311
1145
  };
1312
- if (this.online && this.blacklist !== void 0 && !this.blacklist.verify(stream.ip)) {
1313
- await serve_error_endpoint(403);
1314
- log_endpoint_result();
1315
- return;
1316
- }
1317
1146
  method = stream.method;
1318
1147
  endpoint_url = stream.endpoint;
1319
- log(3, "Searching for endpoint: ", `${method}:${endpoint_url}`);
1148
+ this.log(3, "Searching for endpoint: ", `${method}:${endpoint_url}`);
1320
1149
  endpoint = this.endpoints.get(`${method}:${endpoint_url}`);
1321
1150
  if (!endpoint) {
1322
1151
  const route = new import_route.Route(method, endpoint_url);
1323
1152
  for (const e of this.endpoints.values()) {
1324
1153
  if (e.route.is_regex) {
1325
- if (e.route.match(route)) {
1326
- log(3, "Matched regex route: ", e.route.id);
1154
+ const matched_params = e.route.match(route);
1155
+ if (matched_params !== false) {
1156
+ this.log(3, "Matched regex route: ", e.route.id);
1327
1157
  endpoint = e;
1328
- Object.keys(route.matched_params).walk((k) => {
1158
+ Object.keys(matched_params).walk((k) => {
1329
1159
  if (stream.params[k] == null) {
1330
- stream.params[k] = route.matched_params[k];
1160
+ stream.params[k] = matched_params[k];
1331
1161
  }
1332
1162
  });
1333
1163
  break;
@@ -1335,7 +1165,7 @@ Sitemap: ${this.full_domain}/sitemap.xml`;
1335
1165
  }
1336
1166
  }
1337
1167
  } else {
1338
- log(3, "Matched route: ", endpoint.route.id);
1168
+ this.log(3, "Matched route: ", endpoint.route.id);
1339
1169
  }
1340
1170
  if (!endpoint) {
1341
1171
  if (method === "OPTIONS") {
@@ -1344,10 +1174,6 @@ Sitemap: ${this.full_domain}/sitemap.xml`;
1344
1174
  if (original_endpoint) {
1345
1175
  this._set_header_defaults(stream);
1346
1176
  original_endpoint._set_headers(stream);
1347
- if (stream.headers.origin && this.default_headers["Access-Control-Allow-Origin"] === "*") {
1348
- stream.remove_header("Access-Control-Allow-Origin", "access-control-allow-origin");
1349
- stream.set_header("Access-Control-Allow-Origin", stream.headers.origin);
1350
- }
1351
1177
  stream.send({ status: import_status.Status.no_content });
1352
1178
  log_endpoint_result();
1353
1179
  return;
@@ -1358,16 +1184,12 @@ Sitemap: ${this.full_domain}/sitemap.xml`;
1358
1184
  return;
1359
1185
  }
1360
1186
  this._set_header_defaults(stream);
1361
- if (stream.headers.origin && this.default_headers["Access-Control-Allow-Origin"] === "*") {
1362
- stream.remove_header("Access-Control-Allow-Origin", "access-control-allow-origin");
1363
- stream.set_header("Access-Control-Allow-Origin", stream.headers.origin);
1364
- }
1365
1187
  if (method === "OPTIONS") {
1366
1188
  try {
1367
1189
  await endpoint._serve_options(stream);
1368
1190
  } catch (err) {
1369
- error(`${method}:${endpoint_url}: `, err);
1370
- if (!stream.destroyed && !stream.closed) {
1191
+ this.log.error(`${method}:${endpoint_url}: `, err);
1192
+ if (!stream.destroyed && !stream.finished) {
1371
1193
  await serve_error_endpoint(500);
1372
1194
  log_endpoint_result();
1373
1195
  }
@@ -1376,7 +1198,7 @@ Sitemap: ${this.full_domain}/sitemap.xml`;
1376
1198
  log_endpoint_result();
1377
1199
  return;
1378
1200
  }
1379
- if (this.online && this.production && this.rate_limit !== void 0 && endpoint.rate_limit_groups.length > 0) {
1201
+ if (!this.offline && this.production && this.rate_limit !== void 0 && endpoint.rate_limit_groups.length > 0) {
1380
1202
  const result = await this.rate_limit.limit(stream.ip, endpoint.rate_limit_groups);
1381
1203
  if (result != null) {
1382
1204
  stream.send({
@@ -1394,7 +1216,7 @@ Sitemap: ${this.full_domain}/sitemap.xml`;
1394
1216
  try {
1395
1217
  await stream.join();
1396
1218
  } catch (err) {
1397
- error(`${method}:${endpoint_url}: `, err);
1219
+ this.log.error(`${method}:${endpoint_url}: `, err);
1398
1220
  await serve_error_endpoint(500);
1399
1221
  log_endpoint_result();
1400
1222
  return;
@@ -1402,7 +1224,7 @@ Sitemap: ${this.full_domain}/sitemap.xml`;
1402
1224
  try {
1403
1225
  stream._parse_params();
1404
1226
  } catch (err) {
1405
- error(`${method}:${endpoint_url}: `, err);
1227
+ this.log.error(`${method}:${endpoint_url}: `, err);
1406
1228
  await serve_error_endpoint(400);
1407
1229
  log_endpoint_result();
1408
1230
  return;
@@ -1412,6 +1234,9 @@ Sitemap: ${this.full_domain}/sitemap.xml`;
1412
1234
  if (auth_result != null && !endpoint.is_static) {
1413
1235
  this.users._reset_cookies(stream);
1414
1236
  }
1237
+ if (auth_result != null && !endpoint.is_static && (endpoint.view != null || endpoint.content_type === "text/html")) {
1238
+ stream.set_header("Location", `/signin?next=${encodeURIComponent(stream.endpoint)}`);
1239
+ }
1415
1240
  if (auth_result != null && endpoint.authenticated) {
1416
1241
  stream.send(auth_result);
1417
1242
  log_endpoint_result();
@@ -1421,34 +1246,145 @@ Sitemap: ${this.full_domain}/sitemap.xml`;
1421
1246
  try {
1422
1247
  await endpoint._serve(stream);
1423
1248
  } catch (err) {
1424
- error(`${method}:${endpoint_url}: `, err);
1425
- if (!stream.destroyed && !stream.closed) {
1249
+ this.log.error(`${method}:${endpoint_url}: `, err);
1250
+ if (!stream.destroyed && !stream.finished) {
1426
1251
  await serve_error_endpoint(500);
1427
1252
  log_endpoint_result();
1428
1253
  }
1429
1254
  return;
1430
1255
  }
1431
1256
  if (!stream.finished) {
1432
- error(`${method}:${endpoint_url}: `, "Unfinished response.");
1257
+ this.log.error(`${method}:${endpoint_url}: `, "Unfinished response.");
1433
1258
  await serve_error_endpoint(500);
1434
1259
  log_endpoint_result();
1435
1260
  return;
1436
1261
  }
1437
1262
  log_endpoint_result();
1438
1263
  } catch (err) {
1439
- error("Fatal error:", err);
1264
+ this.log.error(err);
1440
1265
  }
1441
1266
  }
1442
1267
  // ---------------------------------------------------------
1268
+ // Server (private).
1269
+ /** The promise of database initialization and connecting. */
1270
+ _db_init_promise;
1271
+ // Initialize.
1272
+ // Initialize.
1273
+ async initialize() {
1274
+ this.log(1, "Initializing server.");
1275
+ const initialize_start = Date.now();
1276
+ this.performance.start();
1277
+ this._db_init_promise = (async () => {
1278
+ let start = Date.now();
1279
+ await this.db.initialize();
1280
+ this.performance.end("init-db", start);
1281
+ start = Date.now();
1282
+ await this.db.connect();
1283
+ this.performance.end("connect-db", start);
1284
+ })();
1285
+ if (this.tls) {
1286
+ this.https = http2.createSecureServer({
1287
+ key: new vlib.Path(this.tls.key).load_sync({ encoding: "utf8" }),
1288
+ cert: new vlib.Path(this.tls.cert).load_sync({ encoding: "utf8" }),
1289
+ ca: this.tls.ca == null ? void 0 : new vlib.Path(this.tls.ca).load_sync({ encoding: "utf8" }),
1290
+ passphrase: this.tls.passphrase,
1291
+ allowHTTP1: true
1292
+ });
1293
+ this.https.on("stream", (stream, headers) => {
1294
+ this._serve(stream, headers, void 0, void 0);
1295
+ });
1296
+ this.https.on("request", (req, res) => {
1297
+ if (req.httpVersionMajor === 1) {
1298
+ this._serve(void 0, void 0, req, res);
1299
+ }
1300
+ });
1301
+ } else if (this.production && this.payments) {
1302
+ throw Error("Accepting payments in production mode requires HTTPS.");
1303
+ }
1304
+ this.performance.end("create-https-server");
1305
+ if (this.tls) {
1306
+ this.http = http.createServer((request, response) => {
1307
+ const reqUrl = typeof request.url === "string" ? request.url : "/";
1308
+ const location = `https://${this.domain}${reqUrl}`;
1309
+ response.writeHead(308, { Location: location });
1310
+ response.end();
1311
+ });
1312
+ } else {
1313
+ this.http = http.createServer((req, res) => {
1314
+ this._serve(void 0, void 0, req, res);
1315
+ });
1316
+ }
1317
+ this.performance.end("create-http-server");
1318
+ this._init_default_headers();
1319
+ this.performance.end("init-default-headers");
1320
+ this._create_default_endpoints();
1321
+ this.performance.end("create-default-endpoints");
1322
+ await this._initialize_statics();
1323
+ this.performance.end("_initialize_statics()");
1324
+ const promises = [];
1325
+ this.performance.start();
1326
+ if (this.production) {
1327
+ promises.push(this._initialize_keys());
1328
+ } else {
1329
+ this._initialize_keys().then(() => {
1330
+ this.log(1, "Finished loading keys.");
1331
+ }).catch((err) => {
1332
+ this.log(0, `Error while loading keys.`);
1333
+ this.log.error(err);
1334
+ });
1335
+ }
1336
+ promises.push(this.users._initialize());
1337
+ if (this.payments !== void 0) {
1338
+ promises.push(this.payments._initialize());
1339
+ }
1340
+ if (this._find_endpoint("/sitemap.xml") == null) {
1341
+ promises.push(this._create_sitemap());
1342
+ }
1343
+ if (this._find_endpoint("/robots.txt") == null) {
1344
+ promises.push(this._create_robots_txt());
1345
+ }
1346
+ if (this.company.stroke_icon || this.company.icon) {
1347
+ for (const endpoint of this.endpoints.values()) {
1348
+ if (this.company.stroke_icon_path == null && endpoint.route.endpoint === this.company.stroke_icon) {
1349
+ this.company.stroke_icon_path = endpoint.file_path?.str() || void 0;
1350
+ }
1351
+ if (this.company.icon_path == null && endpoint.route.endpoint === this.company.icon) {
1352
+ this.company.icon_path = endpoint.file_path?.str() || void 0;
1353
+ }
1354
+ }
1355
+ if (this.company.stroke_icon != null && this.company.stroke_icon_path == null) {
1356
+ throw Error(`Unable to find the company's stroke icon endpoint "${this.company.stroke_icon}".`);
1357
+ }
1358
+ if (this.company.icon != null && this.company.icon_path == null) {
1359
+ throw Error(`Unable to find the company's icon endpoint "${this.company.icon}".`);
1360
+ }
1361
+ }
1362
+ await Promise.all(promises);
1363
+ this.performance.end("awaiting-promise-list");
1364
+ this.performance.start();
1365
+ for (const endpoint of this.endpoints.values()) {
1366
+ endpoint._initialize(this);
1367
+ }
1368
+ for (const endpoint of this.err_endpoints.values()) {
1369
+ endpoint._initialize(this);
1370
+ }
1371
+ this.performance.end("initialize-endpoints");
1372
+ for (const callback of this.events.get("initialize")) {
1373
+ const res = callback();
1374
+ if (res instanceof Promise) {
1375
+ await res;
1376
+ }
1377
+ }
1378
+ this.performance.end("on-initialize-callbacks");
1379
+ this.performance.end("initialize()", initialize_start);
1380
+ }
1381
+ // ---------------------------------------------------------
1443
1382
  // Server.
1444
- // Start the server.
1445
- /* @docs:
1446
- * @title: Start
1447
- * @description:
1448
- * Start the server.
1449
- * @usage:
1450
- * ...
1451
- * server.start();
1383
+ /**
1384
+ * Start the server.
1385
+ * @example
1386
+ * ...
1387
+ * server.start();
1452
1388
  */
1453
1389
  async start() {
1454
1390
  await this.initialize();
@@ -1459,31 +1395,31 @@ Sitemap: ${this.full_domain}/sitemap.xml`;
1459
1395
  }
1460
1396
  }
1461
1397
  }
1462
- if (this.db && this.rate_limit) {
1398
+ if (this.rate_limit) {
1463
1399
  this.performance.start();
1464
1400
  await this.rate_limit.start();
1465
1401
  this.performance.end("init-rate-limit");
1466
1402
  }
1467
1403
  let forked = false;
1468
- if (this.production && this.multiprocessing && import_cluster.default.isPrimary && this.processes > 1) {
1469
- this.log(0, `Starting ${this.processes} threads.`);
1404
+ if (this.production && this.threading.enabled && import_cluster.default.isPrimary && this.threading.threads > 1) {
1405
+ this.log(0, `Starting ${this.threading.threads} threads.`);
1470
1406
  let active_threads = 0;
1471
1407
  const thread_ids = {};
1472
1408
  const restart_limiters = {};
1473
1409
  const start_thread = (thread_id, restart = false) => {
1474
1410
  const worker = import_cluster.default.fork();
1475
- log(restart ? 0 : 1, `Starting thread ${worker.process.pid}.`);
1411
+ this.log(restart ? 0 : 1, `Starting thread ${worker.process.pid}.`);
1476
1412
  thread_ids[worker.process.pid] = thread_id;
1477
1413
  ++active_threads;
1478
1414
  };
1479
- for (let i = 0; i < this.processes; i++) {
1415
+ for (let i = 0; i < this.threading.threads; i++) {
1480
1416
  let thread_id;
1481
1417
  while ((thread_id = vlib.String.random(8)) && Object.values(thread_ids).includes(thread_id)) {
1482
1418
  }
1483
1419
  restart_limiters[thread_id] = new vlib.TimeLimiter({ limit: 3, duration: 60 * 1e3 });
1484
1420
  start_thread(thread_id);
1485
1421
  }
1486
- await this._sys_db.save("status", {
1422
+ await this._website_status_db.set({ id: "status" }, {
1487
1423
  running_since: Date.now(),
1488
1424
  total_threads: active_threads,
1489
1425
  running_threads: active_threads
@@ -1491,39 +1427,39 @@ Sitemap: ${this.full_domain}/sitemap.xml`;
1491
1427
  import_cluster.default.addListener("exit", async (worker, code, signal) => {
1492
1428
  const thread_id = thread_ids[worker.process.pid];
1493
1429
  delete thread_ids[worker.process.pid];
1494
- error(`Thread ${worker.process.pid} crashed.`);
1430
+ this.log.error(`Thread ${worker.process.pid} crashed.`);
1495
1431
  const limiter = restart_limiters[thread_id];
1496
1432
  if (limiter != null && limiter.limit()) {
1497
1433
  --active_threads;
1498
1434
  start_thread(thread_id, true);
1499
1435
  } else {
1500
- error(`Thread ${worker.process.pid} is being shut down due too its periodic restart limit.`);
1436
+ this.log.error(`Thread ${worker.process.pid} is being shut down due to its periodic restart limit.`);
1501
1437
  --active_threads;
1502
- await this._sys_db.save("status", { running_threads: active_threads });
1438
+ await this._website_status_db.save({ id: "status" }, { $inc: { running_threads: -1 } });
1503
1439
  if (active_threads === 0) {
1504
- error(`All threads died, stopping server.`);
1440
+ this.log.error(`All threads died, stopping server.`);
1505
1441
  process.exit(0);
1506
1442
  }
1507
1443
  }
1508
1444
  });
1509
1445
  } else {
1510
- forked = this.production && this.multiprocessing;
1446
+ forked = this.production && this.threading.enabled;
1511
1447
  let is_running = false;
1512
1448
  const on_running = () => {
1513
1449
  if (!is_running) {
1514
1450
  is_running = true;
1515
1451
  if (this.https !== void 0) {
1516
- log(0, `Running on http://${this.ip}:${this.port} and https://${this.ip}:${this.https_port}.`);
1452
+ this.log(0, `Running on http://${this.ip}:${this.port} and https://${this.ip}:${this.https_port}.`);
1517
1453
  } else {
1518
- log(0, `Running on http://${this.ip}:${this.port}.`);
1454
+ this.log(0, `Running on http://${this.ip}:${this.port}.`);
1519
1455
  }
1520
1456
  }
1521
1457
  };
1522
- const on_error = (error2) => {
1523
- if (error2.syscall !== "listen") {
1524
- throw error2;
1458
+ const on_error = (error) => {
1459
+ if (error.syscall !== "listen") {
1460
+ throw error;
1525
1461
  }
1526
- switch (error2.code) {
1462
+ switch (error.code) {
1527
1463
  case "EACCES":
1528
1464
  console.error(`Error: Address ${this.ip}:${this.port} requires elevated privileges.`);
1529
1465
  process.exit(1);
@@ -1533,7 +1469,7 @@ Sitemap: ${this.full_domain}/sitemap.xml`;
1533
1469
  process.exit(1);
1534
1470
  break;
1535
1471
  default:
1536
- throw error2;
1472
+ throw error;
1537
1473
  }
1538
1474
  };
1539
1475
  this.http.listen(this.port, this.ip === "*" ? void 0 : this.ip, on_running);
@@ -1542,45 +1478,46 @@ Sitemap: ${this.full_domain}/sitemap.xml`;
1542
1478
  this.https.listen(this.https_port, this.ip === "*" ? void 0 : this.ip, on_running);
1543
1479
  this.https.on("error", on_error);
1544
1480
  }
1545
- process.on("SIGTERM", () => process.exit(0));
1546
- process.on("SIGINT", () => process.exit(0));
1481
+ let graceful_shutdown_shutting_down = false;
1482
+ const graceful_shutdown = async () => {
1483
+ if (graceful_shutdown_shutting_down)
1484
+ return;
1485
+ graceful_shutdown_shutting_down = true;
1486
+ try {
1487
+ await this.stop();
1488
+ } catch (e) {
1489
+ this.log.error("Shutdown error:", e);
1490
+ } finally {
1491
+ process.exit(0);
1492
+ }
1493
+ };
1494
+ process.on("SIGTERM", graceful_shutdown);
1495
+ process.on("SIGINT", graceful_shutdown);
1547
1496
  if (process.env.VOLT_FILE_WATCHER === "1") {
1548
1497
  new vlib.Path(process.env.VOLT_STARTED_FILE).save_sync("1");
1549
1498
  }
1550
1499
  this.performance.end("listen");
1551
1500
  }
1552
- for (const callback of this._on_start) {
1501
+ this.performance.start();
1502
+ for (const callback of this.events.get("start")) {
1553
1503
  const res = callback({ forked });
1554
1504
  if (res instanceof Promise) {
1555
1505
  await res;
1556
1506
  }
1557
1507
  }
1558
- debug(2, () => this.performance.dump((v) => v >= 50));
1559
- }
1560
- /* @docs:
1561
- * @title: On start
1562
- * @description:
1563
- * Add an (async) callback which will be executed at the end of `server.start()`.
1564
- * The callback may take arguments `({forked <boolean>})`.
1565
- * @usage:
1566
- * ...
1567
- * server.on_start(({forked}) => console.log("Hello World!"));
1568
- */
1569
- on_start(callback) {
1570
- this._on_start.append(callback);
1508
+ this.performance.end("on-start-callbacks");
1509
+ console.log(this.performance.dump());
1571
1510
  }
1572
1511
  // Stop the server.
1573
- /* @docs:
1574
- * @title: Stop
1575
- * @description:
1576
- * Stop the server.
1577
- * @usage:
1578
- * ...
1579
- * server.stop();
1512
+ /**
1513
+ * Stop the server.
1514
+ * @example
1515
+ * ...
1516
+ * server.stop();
1580
1517
  */
1581
1518
  async stop() {
1582
- log(0, "Stopping the server...");
1583
- for (const callback of this._on_stop) {
1519
+ this.log(0, "Stopping the server...");
1520
+ for (const callback of this.events.get("stop")) {
1584
1521
  const res = callback();
1585
1522
  if (res instanceof Promise) {
1586
1523
  await res;
@@ -1589,89 +1526,81 @@ Sitemap: ${this.full_domain}/sitemap.xml`;
1589
1526
  if (this.rate_limit) {
1590
1527
  await this.rate_limit.stop();
1591
1528
  }
1592
- if (this._stop_tscompiler_watcher) {
1593
- log(0, "Stopping typescript watcher.");
1594
- this._stop_tscompiler_watcher();
1595
- }
1596
- if (this.https) {
1597
- await this.https.close();
1598
- }
1599
- if (this.http) {
1600
- await this.http.close();
1601
- }
1602
- if (this.db) {
1603
- await this.db.close();
1604
- }
1605
- import_logger.logger.stop();
1529
+ if (this.https)
1530
+ this.https.close();
1531
+ if (this.http)
1532
+ this.http.close();
1533
+ await this.db.close();
1534
+ this.log.stop();
1606
1535
  }
1607
- /* @docs:
1608
- * @title: On stop
1609
- * @description:
1610
- * Set an (async) callback which will be executed at the start of `server.stop()`.
1611
- * @usage:
1612
- * ...
1613
- * server.on_stop(() => console.log("Hello World!"));
1536
+ // ---------------------------------------------------------
1537
+ // Events.
1538
+ /** Add an event callback. */
1539
+ on(name, callback) {
1540
+ this.events.add(name, callback);
1541
+ return this;
1542
+ }
1543
+ /** Remove an event callback. */
1544
+ off(name, callback) {
1545
+ this.events.remove(name, callback);
1546
+ return this;
1547
+ }
1548
+ // ---------------------------------------------------------
1549
+ // Endpoints.
1550
+ /**
1551
+ * Add a single endpoint.
1552
+ * Only supports a single endpoint due to parameter inference.
1553
+ * @note An error is thrown when the endpoint route already exists.
1554
+ * @template Response User inputted response type that will be returned as response, optionaly typing used for consistency.
1555
+ * @template S system template for inferring the endpoint callback parameters.
1556
+ * @param endpoint The endpoint or endpoint options to add.
1557
+ * @returns A registered endpoint object that can for instance be used to infer the endpoint parameters.
1614
1558
  */
1615
- on_stop(callback) {
1616
- this._on_stop.append(callback);
1559
+ endpoint(endpoint) {
1560
+ const e = endpoint instanceof import_endpoint.Endpoint ? endpoint : new import_endpoint.Endpoint(endpoint);
1561
+ this._check_duplicate_route(e.route);
1562
+ this.endpoints.set(e.route.id, e);
1563
+ return {
1564
+ Params: void 0,
1565
+ method: e.route.method,
1566
+ Method: e.route.method,
1567
+ endpoint: e.route.endpoint,
1568
+ Endpoint: e.route.endpoint,
1569
+ route: e.route
1570
+ };
1617
1571
  }
1618
- // Fetch status.
1619
- /* @docs:
1620
- @title: Fetch status.
1621
- @desc: This function is meant to be used when the server is in production mode, it will make an API request to your server through the defined `Server.domain` parameter.
1622
- @note: This function can be called without initializing the server.
1623
- @param:
1624
- @name: type
1625
- @desc: The wanted output type. Either an `object` or a `string` type for CLI purposes.
1572
+ // Add an error endpoint.
1573
+ /**
1574
+ * Add an endpoint per error status code.
1575
+ * @param status_code
1576
+ * The status code of the error.
1577
+ *
1578
+ * The supported status codes are:
1579
+ * * `404`
1580
+ * * `400` (Will not be used when the endpoint uses an API callback).
1581
+ * * `403`
1582
+ * * `404`
1583
+ * * `500`
1584
+ * @param endpoint The error endpoint or error endpoint options
1626
1585
  */
1627
- async fetch_status(type = "object") {
1628
- const key_path = this.source.join(".status/key");
1629
- if (!key_path.exists()) {
1630
- throw new Error("No status key has been generated yet. Start your server first.");
1631
- }
1632
- const key = key_path.load_sync();
1633
- const { body: status } = await vlib.request({
1634
- host: this.domain,
1635
- endpoint: "/.status",
1636
- method: "GET",
1637
- params: { key },
1638
- query: true,
1639
- json: true
1640
- });
1641
- if (type === "string") {
1642
- if (status.running_since != null) {
1643
- status.running_since = new vlib.Date(status.running_since).format("%d-%m-%y %H:%M:%S");
1644
- }
1645
- let str = `${this.domain}:
1646
- `;
1647
- Object.keys(status).forEach((key2) => {
1648
- str += ` * ${key2}: ${status[key2]}
1649
- `;
1650
- });
1651
- str = str.substr(0, str.length - 1);
1652
- return str;
1653
- }
1654
- return status;
1586
+ error_endpoint(status_code, endpoint) {
1587
+ const e = endpoint instanceof import_endpoint.Endpoint ? endpoint : new import_endpoint.Endpoint(endpoint);
1588
+ this._check_duplicate_route(e.route);
1589
+ this.err_endpoints.set(status_code, e);
1590
+ return this;
1655
1591
  }
1656
1592
  // ---------------------------------------------------------
1657
1593
  // Content Security Policy.
1658
1594
  // Add a csp.
1659
- /* @docs:
1660
- * @title: Add CSP
1661
- * @description: Add an url to the Content-Security-Policy. This function does not overwrite the existing key's value.
1662
- * @warning: This function no longer has any effect when `Server.start()` has been called.
1663
- * @parameter:
1664
- * @name: key
1665
- * @description: The Content-Security-Policy key, e.g. `script-src`.
1666
- * @type: string
1667
- * @parameter:
1668
- * @name: value
1669
- * @description: The value to add to the Content-Security-Policy key.
1670
- * @type: null, string, string[]
1671
- * @usage:
1672
- * ...
1673
- * server.add_csp("script-src", "somewebsite.com");
1674
- * server.add_csp("upgrade-insecure-requests");
1595
+ /**
1596
+ * Add an url to the Content-Security-Policy. This function does not overwrite the existing key's value.
1597
+ * @warning This function no longer has any effect when `Server.start()` has been called.
1598
+ * @param key The Content-Security-Policy key, e.g. `script-src`.
1599
+ * @param value The value to add to the Content-Security-Policy key.
1600
+ * @example
1601
+ * ...
1602
+ * server.add_csp("script-src", "somewebsite.com");
1603
+ * server.add_csp("upgrade-insecure-requests");
1675
1604
  */
1676
1605
  add_csp(key, value = null) {
1677
1606
  if (this.csp[key] === void 0) {
@@ -1688,22 +1617,15 @@ Sitemap: ${this.full_domain}/sitemap.xml`;
1688
1617
  }
1689
1618
  }
1690
1619
  // Remove a csp.
1691
- /* @docs:
1692
- * @title: Remove CSP
1693
- * @description: Remove an url from the Content-Security-Policy. This function does not overwrite the existing key's value.
1694
- * @warning: This function no longer has any effect when `Server.start()` has been called.
1695
- * @parameter:
1696
- * @name: key
1697
- * @description: The Content-Security-Policy key, e.g. `script-src`.
1698
- * @type: string
1699
- * @parameter:
1700
- * @name: value
1701
- * @description: The value to remove from the Content-Security-Policy key.
1702
- * @type: null, string
1703
- * @usage:
1704
- * ...
1705
- * server.remove_csp("script-src", "somewebsite.com");
1706
- * server.remove_csp("upgrade-insecure-requests");
1620
+ /**
1621
+ * Remove an url from the Content-Security-Policy. This function does not overwrite the existing key's value.
1622
+ * @warning This function no longer has any effect when `Server.start()` has been called.
1623
+ * @param key The Content-Security-Policy key, e.g. `script-src`.
1624
+ * @param value The value to remove from the Content-Security-Policy key.
1625
+ * @example
1626
+ * ...
1627
+ * server.remove_csp("script-src", "somewebsite.com");
1628
+ * server.remove_csp("upgrade-insecure-requests");
1707
1629
  */
1708
1630
  remove_csp(key, value = null) {
1709
1631
  if (this.csp[key] === void 0) {
@@ -1716,25 +1638,58 @@ Sitemap: ${this.full_domain}/sitemap.xml`;
1716
1638
  }
1717
1639
  }
1718
1640
  // Delete a csp key.
1719
- /* @docs:
1720
- * @title: Delete CSP
1721
- * @description: Delete an key from the Content-Security-Policy.
1722
- * @warning: This function no longer has any effect when `Server.start()` has been called.
1723
- * @parameter:
1724
- * @name: key
1725
- * @description: The Content-Security-Policy key, e.g. `script-src`.
1726
- * @type: string
1727
- * @usage:
1728
- * ...
1729
- * server.del_csp("script-src");
1730
- * server.del_csp("upgrade-insecure-requests");
1641
+ /**
1642
+ * Delete an key from the Content-Security-Policy.
1643
+ * @warning This function no longer has any effect when `Server.start()` has been called.
1644
+ * @param key The Content-Security-Policy key, e.g. `script-src`.
1645
+ * @example
1646
+ * ...
1647
+ * server.del_csp("script-src");
1648
+ * server.del_csp("upgrade-insecure-requests");
1731
1649
  */
1732
1650
  del_csp(key) {
1733
1651
  delete this.csp[key];
1734
1652
  }
1735
1653
  // ---------------------------------------------------------
1654
+ // Status.
1655
+ // Fetch status.
1656
+ /**
1657
+ * This function is meant to be used when the server is in production mode, it will make an API request to your server through the defined `Server.domain` parameter.
1658
+ * @note This function can be called without initializing the server.
1659
+ * @param type The wanted output type. Either an `object` or a `string` type for CLI purposes.
1660
+ */
1661
+ async fetch_status(type = "object") {
1662
+ const key_path = this.source.join(".status/key");
1663
+ if (!key_path.exists()) {
1664
+ throw new Error("No status key has been generated yet. Start your server first.");
1665
+ }
1666
+ const key = key_path.load_sync();
1667
+ const { body: status } = await vlib.request({
1668
+ host: this.domain,
1669
+ endpoint: "/.status",
1670
+ method: "GET",
1671
+ params: { key },
1672
+ query: true,
1673
+ json: true
1674
+ });
1675
+ if (type === "string") {
1676
+ if (status.running_since != null) {
1677
+ status.running_since = new vlib.Date(status.running_since).format("%d-%m-%y %H:%M:%S");
1678
+ }
1679
+ let str = `${this.domain}:
1680
+ `;
1681
+ Object.keys(status).forEach((key2) => {
1682
+ str += ` * ${key2}: ${status[key2]}
1683
+ `;
1684
+ });
1685
+ str = str.substr(0, str.length - 1);
1686
+ return str;
1687
+ }
1688
+ return status;
1689
+ }
1690
+ // ---------------------------------------------------------
1736
1691
  // TLS.
1737
- // Generate a key and csr for tls.
1692
+ /** Generate a key and csr for tls. */
1738
1693
  async generate_ssl_key({ output_path, ec = true }) {
1739
1694
  if (output_path == null) {
1740
1695
  throw Error('Define parameter "path".');
@@ -1753,7 +1708,7 @@ Sitemap: ${this.full_domain}/sitemap.xml`;
1753
1708
  throw Error(`Encountered an error while generating the private key [${proc.exit_status}]: ${proc.err}`);
1754
1709
  }
1755
1710
  }
1756
- // Generate a csr for tls.
1711
+ /** Generate a csr for tls. */
1757
1712
  async generate_csr({ output_path, key_path, name, domain, organization_unit, country_code, province, city }) {
1758
1713
  if (key_path == null) {
1759
1714
  throw Error('Define parameter "key_path".');
@@ -1763,7 +1718,7 @@ Sitemap: ${this.full_domain}/sitemap.xml`;
1763
1718
  }
1764
1719
  const key = new vlib.Path(key_path);
1765
1720
  if (!key.exists()) {
1766
- throw Error(`Key path "${key.str()}" already exists, remove the file manually to continue.`);
1721
+ throw Error(`Key path "${key.str()}" does not exist.`);
1767
1722
  }
1768
1723
  const csr = new vlib.Path(output_path);
1769
1724
  if (csr.exists()) {
@@ -1780,232 +1735,63 @@ Sitemap: ${this.full_domain}/sitemap.xml`;
1780
1735
  "-out",
1781
1736
  csr.str(),
1782
1737
  "-subj",
1783
- '"/C=' + country_code + "/ST=" + province + "/L=" + city + "/O=" + name + "/OU=" + organization_unit + "/CN=" + domain + '"'
1738
+ `/C=${country_code}/ST=${province}/L=${city}/O=${name}/OU=${organization_unit}/CN=${domain}`
1784
1739
  ],
1785
1740
  opts: { stdio: "inherit" }
1786
1741
  });
1787
1742
  if (proc.exit_status != 0) {
1788
1743
  throw Error(`Encountered an error while generating the CSR [${proc.exit_status}]: ${proc.err}`);
1789
1744
  }
1790
- log(0, `Generated the tls key with CSR for domain "${this.domain}".`);
1791
- }
1792
- // ---------------------------------------------------------
1793
- // Endpoints.
1794
- // private registered_routes: Map<string, Array<string | RegExp>> = new Map();
1795
- /**
1796
- * Checks if an endpoint route already exists.
1797
- * @param method HTTP method
1798
- * @param endpoint String path or RegExp
1799
- */
1800
- _check_duplicate_route(route) {
1801
- const e = this._find_endpoint(route);
1802
- if (e) {
1803
- throw new Error(`Duplicate "${route.method}:${route.endpoint_str}" endpoint route, it is already defined by endpoint "${e.id}".`);
1804
- }
1805
- }
1806
- /**
1807
- * Add a single endpoint.
1808
- * Only supports a single endpoint due to parameter inference.
1809
- * @param endpoint The endpoint or endpoint options to add.
1810
- */
1811
- endpoint(endpoint) {
1812
- const e = endpoint instanceof import_endpoint.Endpoint ? endpoint : new import_endpoint.Endpoint(endpoint);
1813
- this._check_duplicate_route(e.route);
1814
- this.endpoints.set(e.route.id, e);
1815
- return this;
1816
- }
1817
- // Add an error endpoint.
1818
- /**
1819
- * Add an endpoint per error status code.
1820
- * @param status_code
1821
- * The status code of the error.
1822
- *
1823
- * The supported status codes are:
1824
- * * `404`
1825
- * * `400` (Will not be used when the endpoint uses an API callback).
1826
- * * `403`
1827
- * * `404`
1828
- * * `500`
1829
- * @param endpoint The error endpoint or error endpoint options
1830
- */
1831
- error_endpoint(status_code, endpoint) {
1832
- const e = endpoint instanceof import_endpoint.Endpoint ? endpoint : new import_endpoint.Endpoint(endpoint);
1833
- this._check_duplicate_route(e.route);
1834
- this.err_endpoints.set(status_code, e);
1835
- return this;
1836
- }
1837
- // ---------------------------------------------------------
1838
- // Functions.
1839
- // Send a mail.
1840
- /* @docs:
1841
- * @title: Send Mail
1842
- * @description: Send one or multiple mails.
1843
- * @note: Make sure the domain's DNS records SPF and DKIM are properly configured when sending attachments.
1844
- * @return:
1845
- * Returns a promise that will be resolved or rejected when the mail has been sent.
1846
- * @parameter:
1847
- * @name: sender
1848
- * @description:
1849
- * The sender address.
1850
- * A sender address may either be a string with the email address, e.g. `your@email.com`.
1851
- * Or an array with the sender name and email address, e.g. `["Sender", "your@email.com"]`.
1852
- * @type: string, array
1853
- * @parameter:
1854
- * @name: recipients
1855
- * @description:
1856
- * The recipient addresses.
1857
- * A reciepient address may either be a string with the email address, e.g. `your@email.com`.
1858
- * Or an array with the sender name and email address, e.g. `["Sender", "your@email.com"]`.
1859
- * @type: array[string, array]
1860
- * @parameter:
1861
- * @name: subject
1862
- * @description: The subject text.
1863
- * @type: string
1864
- * @parameter:
1865
- * @name: body
1866
- * @description: The body text.
1867
- * @type: string
1868
- * @parameter:
1869
- * @name: attachments
1870
- * @description: An array with absolute file paths for attachments, or an array with nodemailer attachment objects.
1871
- * @type: array[string], array[object]
1872
- * @usage:
1873
- * ...
1874
- * await server.send_mail({
1875
- * sender: ["Sender Name", "sender\@email.com"],
1876
- * recipients: [
1877
- * ["Recipient Name", "recipient1\@email.com"],
1878
- * "recipient2\@email.com",
1879
- * },
1880
- * subject: "Example Mail",
1881
- * body: "Hello World!",
1882
- * attachments: ["/path/to/image.png"]
1883
- * });
1884
- */
1885
- async send_mail({ sender = void 0, recipients = [], subject = void 0, body = "", attachments = [] }) {
1886
- if (this.smtp === void 0) {
1887
- throw new Error("SMTP is not enabled, define the required server argument on initialization to enable smtp.");
1888
- }
1889
- if (body instanceof Mail.MailElement) {
1890
- body = body.html();
1891
- }
1892
- if (sender == null && this.smtp_sender != null) {
1893
- sender = this.smtp_sender;
1894
- }
1895
- if (recipients.length === 0) {
1896
- throw new Error(`The mail has no recipients.`);
1897
- }
1898
- if (sender == null) {
1899
- throw new Error(`Parameter "sender" should be a defined value of type "string" or "array".`);
1900
- }
1901
- const format_address = (address) => {
1902
- if (Array.isArray(address)) {
1903
- return `${address[0]} <${address[1]}>`;
1904
- }
1905
- return address;
1906
- };
1907
- const to = [];
1908
- recipients.forEach((address) => to.push(format_address(address)));
1909
- let attached_files = [];
1910
- if (attachments != null) {
1911
- attachments.forEach((path) => {
1912
- if (path instanceof vlib.Path) {
1913
- attached_files.push({
1914
- filename: path.full_name(),
1915
- path: path.str(),
1916
- content: path.load_sync()
1917
- });
1918
- } else if (typeof path === "string") {
1919
- const p = new vlib.Path(path);
1920
- attached_files.push({
1921
- filename: p.full_name(),
1922
- path,
1923
- content: p.load_sync()
1924
- });
1925
- } else {
1926
- attached_files.push(path);
1927
- }
1928
- });
1929
- }
1930
- try {
1931
- await this.smtp.sendMail({
1932
- from: format_address(sender),
1933
- to,
1934
- subject,
1935
- html: body,
1936
- attachments: attached_files
1937
- });
1938
- } catch (error2) {
1939
- throw new Error(error2.message);
1940
- }
1745
+ this.log(0, `Generated the tls key with CSR for domain "${this.domain}".`);
1941
1746
  }
1942
1747
  // ---------------------------------------------------------
1943
- // Default callbacks.
1944
- // These can all be overwritten by the user.
1945
- // @todo add scheme for payment params.
1946
- // On delete user.
1947
- /* @docs:
1948
- * @title: On delete user
1949
- * @description: This function can be overridden with a callback for when a user is deleted.
1950
- * @parameter:
1951
- * @name: uid
1952
- * @description: The uid of the deleted user.
1953
- * @type: string, array
1954
- * @usage:
1955
- * ...
1956
- * server.on_delete_user = ({uid}) => {}
1957
- */
1958
- async on_delete_user({ uid }) {
1959
- }
1960
- // On successfull one-time payment.
1961
- // This gets called for every product in the payment.
1748
+ // DEPRECATED
1749
+ // these will all be removed and replaced when using stripe instead of paddle.
1750
+ /** Called for each product in a successful one-time payment. Override to implement your logic. */
1962
1751
  async on_payment({ product, payment }) {
1963
1752
  }
1964
- // On successfull subscription.
1965
- // This gets called for every product in the payment.
1753
+ /** Called for each product in a successful subscription. Override to implement your logic. */
1966
1754
  async on_subscription({ product, payment }) {
1967
1755
  }
1968
1756
  // On failed one-time or recurring payment.
1969
1757
  // async on_failed_payment({ payment }: { payment: any }): Promise<void> {}
1970
- // On successfull cancellation.
1758
+ /** Called when a cancellation succeeds. Override to implement your logic. */
1971
1759
  async on_cancellation({ payment, line_items }) {
1972
1760
  }
1973
1761
  // On failed cancellation.
1974
1762
  // async on_failed_cancellation({ payment, line_items }: { payment: any; line_items: any[] }): Promise<void> {}
1975
- // On successfull refund.
1976
- // The line items array are the items were refunded.
1763
+ /** Called when a refund succeeds. The line items array are the items that were refunded. */
1977
1764
  async on_refund({ payment, line_items }) {
1978
1765
  }
1979
- // On failed refund.
1980
- // The line items array are the items were the refund failed.
1766
+ /** Called when a refund fails. The line items array are the items where the refund failed. */
1981
1767
  async on_failed_refund({ payment, line_items }) {
1982
1768
  }
1983
- // On chargeback.
1984
- // The line items array are the items were charged back.
1769
+ /** Called when a chargeback occurs. The line items array are the items that were charged back. */
1985
1770
  async on_chargeback({ payment, line_items }) {
1986
1771
  }
1987
- // On failed chargeback.
1988
- // The line items array are the items were the chargeback failed.
1772
+ /** Called when a chargeback fails. The line items array are the items where the chargeback failed. */
1989
1773
  async on_failed_chargeback({ payment, line_items }) {
1990
1774
  }
1991
1775
  // Mail template.
1776
+ /** Build the base email layout used by the various transactional email builders. */
1992
1777
  _mail_template({ max_width = 400, children = [] }) {
1993
- const style = this.mail_style;
1994
- const { Title, Text, Image, Table, TableRow, TableData, VStack } = Mail;
1778
+ this.assert_mail();
1779
+ const style = this.mail.style;
1780
+ const { Title, Text, Image, Table, TableRow, TableData, VStack } = MailUI;
1995
1781
  let header;
1996
1782
  if (this.company.stroke_icon != null) {
1997
1783
  header = [
1998
- Image(`${this.full_domain}/${this.company.stroke_icon}`).height(16)
1784
+ Image(`${this.full_domain}${this.company.stroke_icon ?? ""}`).height(16)
1999
1785
  ];
2000
1786
  } else if (this.company.icon != null) {
2001
1787
  header = [
2002
- Image(`${this.full_domain}/${this.company.icon}`).frame(20, 40)
1788
+ Image(`${this.full_domain}${this.company.icon ?? ""}`).frame(20, 40)
2003
1789
  ];
2004
1790
  }
2005
1791
  if (header) {
2006
1792
  header = Table(TableRow(...header).wrap(true).center().center_vertical()).margin_bottom(15);
2007
1793
  }
2008
- return Mail.Mail(Table(TableData(Table(
1794
+ return MailUI.Mail(Table(TableData(Table(
2009
1795
  // Header.
2010
1796
  header,
2011
1797
  // Widget.
@@ -2017,9 +1803,13 @@ ${this.company.street} ${this.company.house_number}, ${this.company.postal_code}
2017
1803
  ).max_width(max_width)).center()).padding(25, 20, 25, 20)).font_family(style.font).background(style.bg);
2018
1804
  }
2019
1805
  // Render payment line items.
1806
+ /** Helper that renders a list of payment line items for use in transactional emails. */
2020
1807
  _render_mail_payment_line_items({ payment, line_items, show_total_due = false }) {
2021
- const style = this.mail_style;
2022
- const { Title, Text, Image, Table, TableRow, TableData, VStack } = Mail;
1808
+ if (!this.payments)
1809
+ throw new Error("Payments not initialized");
1810
+ this.assert_mail();
1811
+ const style = this.mail.style;
1812
+ const { Title, Text, Image, Table, TableRow, TableData, VStack } = MailUI;
2023
1813
  const _render_mail_payment_line_item = ({ name, desc, unit_cost, quantity, total_cost, font_weight = "normal", divider = true, color = style.text_fg }) => {
2024
1814
  return [
2025
1815
  Table(TableRow(TableData(Text(name).color(color).font_size(14).text_wrap("wrap").overflow_wrap("break-word").word_wrap("break-word").font_weight(font_weight)).width("25%").margin_right(10), TableData(Text(desc).color(color).font_size(14).text_wrap("wrap").overflow_wrap("break-word").word_wrap("break-word").font_weight(font_weight)).width("35%").margin_right(10), TableData(Text(unit_cost).color(color).font_size(14).text_wrap("wrap").overflow_wrap("break-word").word_wrap("break-word").font_weight(font_weight)).fixed_width("13.32%").margin_right(10), TableData(Text(quantity).color(color).font_size(14).text_wrap("wrap").overflow_wrap("break-word").word_wrap("break-word").font_weight(font_weight)).fixed_width("13.32%").margin_right(10), TableData(Text(total_cost).color(color).font_size(14).text_wrap("wrap").overflow_wrap("break-word").word_wrap("break-word").font_weight(font_weight)).fixed_width("13.32%")).width("100%").styles({ "vertical-align": "baseline" })).width("100%"),
@@ -2033,14 +1823,16 @@ ${this.company.street} ${this.company.house_number}, ${this.company.postal_code}
2033
1823
  let subtotal = 0;
2034
1824
  let subtotal_tax = 0;
2035
1825
  let total = 0;
2036
- payment.line_items.iterate((item) => {
1826
+ payment.line_items.walk((item) => {
1827
+ if (!this.payments)
1828
+ throw new Error("Payments not initialized");
2037
1829
  if (typeof item.product === "string") {
2038
1830
  item.product = this.payments.get_product_sync(item.product);
2039
1831
  }
2040
1832
  if (currency == null) {
2041
1833
  const c = import_utils.Utils.get_currency_symbol(item.product.currency);
2042
1834
  if (c == null) {
2043
- error(`Failed to create a payment mail: `, new Error(`Unable to determine the currency of payment "${payment.id}".`));
1835
+ this.log.error(`Failed to create a payment mail: `, new Error(`Unable to determine the currency of payment "${payment.id}".`));
2044
1836
  }
2045
1837
  currency = c ?? "?";
2046
1838
  }
@@ -2069,10 +1861,18 @@ ${this.company.street} ${this.company.house_number}, ${this.company.postal_code}
2069
1861
  }))
2070
1862
  ];
2071
1863
  }
1864
+ /** Assert mail is configured. */
1865
+ assert_mail() {
1866
+ if (!this.mail) {
1867
+ throw new import_volt.ExternalError({ message: "Mail is not configured." });
1868
+ }
1869
+ }
2072
1870
  // On 2fa mail.
1871
+ /** Build the 2FA verification email content. */
2073
1872
  on_2fa_mail({ code, username, email, date, ip, device }) {
2074
- const style = this.mail_style;
2075
- const { Title, Text, Image, Table, TableRow, TableData, VStack } = Mail;
1873
+ this.assert_mail();
1874
+ const style = this.mail.style;
1875
+ const { Title, Text, Image, Table, TableRow, TableData, VStack } = MailUI;
2076
1876
  return this._mail_template({
2077
1877
  max_width: 400,
2078
1878
  children: [
@@ -2101,9 +1901,11 @@ ${this.company.street} ${this.company.house_number}, ${this.company.postal_code}
2101
1901
  });
2102
1902
  }
2103
1903
  // On successfull payment mail.
1904
+ /** Build the successful payment email content. */
2104
1905
  on_payment_mail({ payment }) {
2105
- const style = this.mail_style;
2106
- const { Title, Text, Image, Table, TableRow, TableData, VStack } = Mail;
1906
+ this.assert_mail();
1907
+ const style = this.mail.style;
1908
+ const { Title, Text, Image, Table, TableRow, TableData, VStack } = MailUI;
2107
1909
  return this._mail_template({
2108
1910
  max_width: 600,
2109
1911
  children: [
@@ -2115,7 +1917,7 @@ ${this.company.street} ${this.company.house_number}, ${this.company.postal_code}
2115
1917
  TableRow(Image(`${this.full_domain}/volt_static/payments/party.png`).frame(60, 60).margin(0, 0, 30, 0)).center(),
2116
1918
  // Title.
2117
1919
  TableRow(Title("Order Summary").color(style.subtitle_fg).font_size(18).margin(0)),
2118
- TableRow(Text("A summary of your order can be found below or in the attachmed invoice pdf.").margin(5, 0, 20, 0).color(style.text_fg).font_size(16)),
1920
+ TableRow(Text("A summary of your order can be found below or in the attached invoice PDF.").margin(5, 0, 20, 0).color(style.text_fg).font_size(16)),
2119
1921
  // Line items.
2120
1922
  this._render_mail_payment_line_items({ payment, line_items: payment.line_items, show_total_due: true }),
2121
1923
  // Bottom spacing.
@@ -2124,16 +1926,18 @@ ${this.company.street} ${this.company.house_number}, ${this.company.postal_code}
2124
1926
  });
2125
1927
  }
2126
1928
  // On failed payment mail.
1929
+ /** Build the failed payment email content. */
2127
1930
  on_failed_payment_mail({ payment }) {
2128
- const style = this.mail_style;
2129
- const { Title, Text, Image, ImageMask, Table, TableRow, TableData, VStack } = Mail;
1931
+ this.assert_mail();
1932
+ const style = this.mail.style;
1933
+ const { Title, Text, Image, ImageMask, Table, TableRow, TableData, VStack } = MailUI;
2130
1934
  return this._mail_template({
2131
1935
  max_width: 800,
2132
1936
  children: [
2133
1937
  // Title.
2134
1938
  TableRow(Title("Payment Failed").color(style.title_fg).width("fit-content").font_size(26)).center(),
2135
1939
  // Text.
2136
- TableRow(Text("We regret to inform you that your payment has encountered an issue and could not be processed successfully. We understand the inconvenience this may cause. Please try again, please contact customer support if the problem persists.").margin(10, 0, 20, 0).color(style.text_fg).font_size(16).center()),
1940
+ TableRow(Text("We regret to inform you that your payment could not be processed successfully. We understand the inconvenience this may cause. Please try again, or contact customer support if the problem persists.").margin(10, 0, 20, 0).color(style.text_fg).font_size(16).center()),
2137
1941
  // Image.
2138
1942
  TableRow(ImageMask(`${this.full_domain}/volt_static/payments/error.png`).frame(40, 40).mask_color("#E8454E").margin(0, 0, 30, 0)).center(),
2139
1943
  // Title.
@@ -2147,14 +1951,16 @@ ${this.company.street} ${this.company.house_number}, ${this.company.postal_code}
2147
1951
  });
2148
1952
  }
2149
1953
  // On cancellation mail.
1954
+ /** Build the successful cancellation email content. */
2150
1955
  on_cancellation_mail({ payment, line_items }) {
2151
- const style = this.mail_style;
2152
- const { Title, Text, Image, Table, TableRow, TableData, VStack } = Mail;
1956
+ this.assert_mail();
1957
+ const style = this.mail.style;
1958
+ const { Title, Text, Image, Table, TableRow, TableData, VStack } = MailUI;
2153
1959
  return this._mail_template({
2154
1960
  max_width: 800,
2155
1961
  children: [
2156
1962
  // Title.
2157
- TableRow(Title("Successfull Cancellation").color(style.title_fg).width("fit-content").font_size(26)).center(),
1963
+ TableRow(Title("Successful Cancellation").color(style.title_fg).width("fit-content").font_size(26)).center(),
2158
1964
  // Text.
2159
1965
  TableRow(Text("Your recent cancellation request has been successfully processed.").margin(10, 0, 20, 0).color(style.text_fg).font_size(16).center()),
2160
1966
  // Image.
@@ -2170,9 +1976,11 @@ ${this.company.street} ${this.company.house_number}, ${this.company.postal_code}
2170
1976
  });
2171
1977
  }
2172
1978
  // On refund mail.
1979
+ /** Build the failed cancellation email content. */
2173
1980
  on_failed_cancellation_mail({ payment }) {
2174
- const style = this.mail_style;
2175
- const { Title, Text, Image, ImageMask, Table, TableRow, TableData, VStack } = Mail;
1981
+ this.assert_mail();
1982
+ const style = this.mail.style;
1983
+ const { Title, Text, Image, ImageMask, Table, TableRow, TableData, VStack } = MailUI;
2176
1984
  return this._mail_template({
2177
1985
  max_width: 800,
2178
1986
  children: [
@@ -2193,14 +2001,16 @@ ${this.company.street} ${this.company.house_number}, ${this.company.postal_code}
2193
2001
  });
2194
2002
  }
2195
2003
  // On refund mail.
2004
+ /** Build the successful refund email content. */
2196
2005
  on_refund_mail({ payment, line_items }) {
2197
- const style = this.mail_style;
2198
- const { Title, Text, Image, Table, TableRow, TableData, VStack } = Mail;
2006
+ this.assert_mail();
2007
+ const style = this.mail.style;
2008
+ const { Title, Text, Image, Table, TableRow, TableData, VStack } = MailUI;
2199
2009
  return this._mail_template({
2200
2010
  max_width: 800,
2201
2011
  children: [
2202
2012
  // Title.
2203
- TableRow(Title("Successful Refund").color(style.title_fg).width("fit-content").font_size(26)).center(),
2013
+ TableRow(Title("Chargeback Successful").color(style.title_fg).width("fit-content").font_size(26)).center(),
2204
2014
  // Text.
2205
2015
  TableRow(Text("We're delighted to inform you that your recent refund request has been successfully processed. The charged amount will soon be credited back to your account.").margin(10, 0, 20, 0).color(style.text_fg).font_size(16).center()),
2206
2016
  // Image.
@@ -2216,9 +2026,11 @@ ${this.company.street} ${this.company.house_number}, ${this.company.postal_code}
2216
2026
  });
2217
2027
  }
2218
2028
  // On refund mail.
2029
+ /** Build the failed refund email content. */
2219
2030
  on_failed_refund_mail({ payment, line_items }) {
2220
- const style = this.mail_style;
2221
- const { Title, Text, Image, ImageMask, Table, TableRow, TableData, VStack } = Mail;
2031
+ this.assert_mail();
2032
+ const style = this.mail.style;
2033
+ const { Title, Text, Image, ImageMask, Table, TableRow, TableData, VStack } = MailUI;
2222
2034
  return this._mail_template({
2223
2035
  max_width: 800,
2224
2036
  children: [
@@ -2239,9 +2051,11 @@ ${this.company.street} ${this.company.house_number}, ${this.company.postal_code}
2239
2051
  });
2240
2052
  }
2241
2053
  // On refund mail.
2054
+ /** Build the successful chargeback email content. */
2242
2055
  on_chargeback_mail({ payment, line_items }) {
2243
- const style = this.mail_style;
2244
- const { Title, Text, Image, Table, TableRow, TableData, VStack } = Mail;
2056
+ this.assert_mail();
2057
+ const style = this.mail.style;
2058
+ const { Title, Text, Image, Table, TableRow, TableData, VStack } = MailUI;
2245
2059
  return this._mail_template({
2246
2060
  max_width: 800,
2247
2061
  children: [
@@ -2253,7 +2067,7 @@ ${this.company.street} ${this.company.house_number}, ${this.company.postal_code}
2253
2067
  TableRow(Image(`${this.full_domain}/volt_static/payments/party.png`).frame(60, 60).margin(0, 0, 30, 0)).center(),
2254
2068
  // Title.
2255
2069
  TableRow(Title("Chargeback Summary").color(style.subtitle_fg).font_size(18).margin(0)),
2256
- TableRow(Text("A summary of your refundend products.").margin(5, 0, 20, 0).color(style.text_fg).font_size(16)),
2070
+ TableRow(Text("A summary of the items charged back.").margin(5, 0, 20, 0).color(style.text_fg).font_size(16)),
2257
2071
  // Line items.
2258
2072
  this._render_mail_payment_line_items({ payment, line_items }),
2259
2073
  // Bottom spacing.
@@ -2262,9 +2076,11 @@ ${this.company.street} ${this.company.house_number}, ${this.company.postal_code}
2262
2076
  });
2263
2077
  }
2264
2078
  // On refund mail.
2079
+ /** Build the failed chargeback email content. */
2265
2080
  on_failed_chargeback_mail({ payment, line_items }) {
2266
- const style = this.mail_style;
2267
- const { Title, Text, Image, ImageMask, Table, TableRow, TableData, VStack } = Mail;
2081
+ this.assert_mail();
2082
+ const style = this.mail.style;
2083
+ const { Title, Text, Image, ImageMask, Table, TableRow, TableData, VStack } = MailUI;
2268
2084
  return this._mail_template({
2269
2085
  max_width: 800,
2270
2086
  children: [
@@ -2285,7 +2101,6 @@ ${this.company.street} ${this.company.house_number}, ${this.company.postal_code}
2285
2101
  });
2286
2102
  }
2287
2103
  }
2288
- var stdin_default = Server;
2289
2104
  // Annotate the CommonJS export names for ESM import in node:
2290
2105
  0 && (module.exports = {
2291
2106
  Server