@vandenberghinc/volt 1.1.2

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 (451) hide show
  1. package/.vrepo +28 -0
  2. package/.vscode/tasks.json +87 -0
  3. package/README.md +67 -0
  4. package/backend/dist/cjs/blacklist.d.ts +10 -0
  5. package/backend/dist/cjs/blacklist.js +53 -0
  6. package/backend/dist/cjs/cli.d.ts +2 -0
  7. package/backend/dist/cjs/cli.js +263 -0
  8. package/backend/dist/cjs/database.d.ts +364 -0
  9. package/backend/dist/cjs/database.js +1962 -0
  10. package/backend/dist/cjs/endpoint.d.ts +57 -0
  11. package/backend/dist/cjs/endpoint.js +425 -0
  12. package/backend/dist/cjs/file_watcher.d.ts +44 -0
  13. package/backend/dist/cjs/file_watcher.js +348 -0
  14. package/backend/dist/cjs/frontend.d.ts +13 -0
  15. package/backend/dist/cjs/frontend.js +30 -0
  16. package/backend/dist/cjs/image_endpoint.d.ts +24 -0
  17. package/backend/dist/cjs/image_endpoint.js +210 -0
  18. package/backend/dist/cjs/logger.d.ts +5 -0
  19. package/backend/dist/cjs/logger.js +16 -0
  20. package/backend/dist/cjs/meta.d.ts +50 -0
  21. package/backend/dist/cjs/meta.js +153 -0
  22. package/backend/dist/cjs/mutex.d.ts +24 -0
  23. package/backend/dist/cjs/mutex.js +52 -0
  24. package/backend/dist/cjs/package.json +1 -0
  25. package/backend/dist/cjs/payments/paddle.d.ts +161 -0
  26. package/backend/dist/cjs/payments/paddle.js +2301 -0
  27. package/backend/dist/cjs/plugins/browser.d.ts +36 -0
  28. package/backend/dist/cjs/plugins/browser.js +183 -0
  29. package/backend/dist/cjs/plugins/communication.d.ts +70 -0
  30. package/backend/dist/cjs/plugins/communication.js +177 -0
  31. package/backend/dist/cjs/plugins/css.d.ts +10 -0
  32. package/backend/dist/cjs/plugins/css.js +71 -0
  33. package/backend/dist/cjs/plugins/mail.d.ts +277 -0
  34. package/backend/dist/cjs/plugins/mail.js +1419 -0
  35. package/backend/dist/cjs/plugins/pdf.d.ts +757 -0
  36. package/backend/dist/cjs/plugins/pdf.js +1694 -0
  37. package/backend/dist/cjs/plugins/thread_monitor.d.ts +18 -0
  38. package/backend/dist/cjs/plugins/thread_monitor.js +127 -0
  39. package/backend/dist/cjs/plugins/ts/compiler.d.ts +132 -0
  40. package/backend/dist/cjs/plugins/ts/compiler.js +944 -0
  41. package/backend/dist/cjs/plugins/ts/preprocessing.d.ts +14 -0
  42. package/backend/dist/cjs/plugins/ts/preprocessing.js +762 -0
  43. package/backend/dist/cjs/rate_limit.d.ts +65 -0
  44. package/backend/dist/cjs/rate_limit.js +463 -0
  45. package/backend/dist/cjs/request.deprc.d.ts +48 -0
  46. package/backend/dist/cjs/request.deprc.js +572 -0
  47. package/backend/dist/cjs/response.deprc.d.ts +55 -0
  48. package/backend/dist/cjs/response.deprc.js +275 -0
  49. package/backend/dist/cjs/server.d.ts +311 -0
  50. package/backend/dist/cjs/server.js +3475 -0
  51. package/backend/dist/cjs/splash_screen.d.ts +35 -0
  52. package/backend/dist/cjs/splash_screen.js +152 -0
  53. package/backend/dist/cjs/status.d.ts +60 -0
  54. package/backend/dist/cjs/status.js +199 -0
  55. package/backend/dist/cjs/stream.d.ts +75 -0
  56. package/backend/dist/cjs/stream.js +954 -0
  57. package/backend/dist/cjs/users.d.ts +111 -0
  58. package/backend/dist/cjs/users.js +1945 -0
  59. package/backend/dist/cjs/utils.d.ts +27 -0
  60. package/backend/dist/cjs/utils.js +329 -0
  61. package/backend/dist/cjs/view.d.ts +52 -0
  62. package/backend/dist/cjs/view.js +568 -0
  63. package/backend/dist/cjs/vinc.d.ts +2 -0
  64. package/backend/dist/cjs/vinc.dev.d.ts +2 -0
  65. package/backend/dist/cjs/vinc.dev.js +42 -0
  66. package/backend/dist/cjs/vinc.js +42 -0
  67. package/backend/dist/cjs/volt.d.ts +15 -0
  68. package/backend/dist/cjs/volt.js +64 -0
  69. package/backend/dist/css/adyen.css +92 -0
  70. package/backend/dist/css/volt.css +65 -0
  71. package/backend/dist/esm/blacklist.d.ts +10 -0
  72. package/backend/dist/esm/blacklist.js +49 -0
  73. package/backend/dist/esm/cli.d.ts +2 -0
  74. package/backend/dist/esm/cli.js +228 -0
  75. package/backend/dist/esm/database.d.ts +364 -0
  76. package/backend/dist/esm/database.js +1957 -0
  77. package/backend/dist/esm/endpoint.d.ts +57 -0
  78. package/backend/dist/esm/endpoint.js +421 -0
  79. package/backend/dist/esm/file_watcher.d.ts +44 -0
  80. package/backend/dist/esm/file_watcher.js +313 -0
  81. package/backend/dist/esm/frontend.d.ts +13 -0
  82. package/backend/dist/esm/frontend.js +27 -0
  83. package/backend/dist/esm/image_endpoint.d.ts +24 -0
  84. package/backend/dist/esm/image_endpoint.js +206 -0
  85. package/backend/dist/esm/logger.d.ts +5 -0
  86. package/backend/dist/esm/logger.js +13 -0
  87. package/backend/dist/esm/meta.d.ts +50 -0
  88. package/backend/dist/esm/meta.js +149 -0
  89. package/backend/dist/esm/mutex.d.ts +24 -0
  90. package/backend/dist/esm/mutex.js +48 -0
  91. package/backend/dist/esm/payments/paddle.d.ts +161 -0
  92. package/backend/dist/esm/payments/paddle.js +2261 -0
  93. package/backend/dist/esm/plugins/browser.d.ts +36 -0
  94. package/backend/dist/esm/plugins/browser.js +176 -0
  95. package/backend/dist/esm/plugins/communication.d.ts +70 -0
  96. package/backend/dist/esm/plugins/communication.js +169 -0
  97. package/backend/dist/esm/plugins/css.d.ts +10 -0
  98. package/backend/dist/esm/plugins/css.js +64 -0
  99. package/backend/dist/esm/plugins/mail.d.ts +277 -0
  100. package/backend/dist/esm/plugins/mail.js +1403 -0
  101. package/backend/dist/esm/plugins/pdf.d.ts +757 -0
  102. package/backend/dist/esm/plugins/pdf.js +1694 -0
  103. package/backend/dist/esm/plugins/thread_monitor.d.ts +18 -0
  104. package/backend/dist/esm/plugins/thread_monitor.js +120 -0
  105. package/backend/dist/esm/plugins/ts/compiler.d.ts +132 -0
  106. package/backend/dist/esm/plugins/ts/compiler.js +907 -0
  107. package/backend/dist/esm/plugins/ts/preprocessing.d.ts +14 -0
  108. package/backend/dist/esm/plugins/ts/preprocessing.js +724 -0
  109. package/backend/dist/esm/rate_limit.d.ts +65 -0
  110. package/backend/dist/esm/rate_limit.js +425 -0
  111. package/backend/dist/esm/request.deprc.d.ts +48 -0
  112. package/backend/dist/esm/request.deprc.js +572 -0
  113. package/backend/dist/esm/response.deprc.d.ts +55 -0
  114. package/backend/dist/esm/response.deprc.js +275 -0
  115. package/backend/dist/esm/server.d.ts +311 -0
  116. package/backend/dist/esm/server.js +3435 -0
  117. package/backend/dist/esm/splash_screen.d.ts +35 -0
  118. package/backend/dist/esm/splash_screen.js +148 -0
  119. package/backend/dist/esm/status.d.ts +60 -0
  120. package/backend/dist/esm/status.js +196 -0
  121. package/backend/dist/esm/stream.d.ts +75 -0
  122. package/backend/dist/esm/stream.js +947 -0
  123. package/backend/dist/esm/users.d.ts +111 -0
  124. package/backend/dist/esm/users.js +1908 -0
  125. package/backend/dist/esm/utils.d.ts +27 -0
  126. package/backend/dist/esm/utils.js +324 -0
  127. package/backend/dist/esm/view.d.ts +52 -0
  128. package/backend/dist/esm/view.js +561 -0
  129. package/backend/dist/esm/vinc.d.ts +2 -0
  130. package/backend/dist/esm/vinc.dev.d.ts +2 -0
  131. package/backend/dist/esm/vinc.dev.js +6 -0
  132. package/backend/dist/esm/vinc.js +6 -0
  133. package/backend/dist/esm/volt.d.ts +15 -0
  134. package/backend/dist/esm/volt.js +23 -0
  135. package/backend/dist/esm-dev/blacklist.d.ts +10 -0
  136. package/backend/dist/esm-dev/blacklist.js +49 -0
  137. package/backend/dist/esm-dev/cli.d.ts +2 -0
  138. package/backend/dist/esm-dev/cli.js +228 -0
  139. package/backend/dist/esm-dev/database.d.ts +364 -0
  140. package/backend/dist/esm-dev/database.js +1957 -0
  141. package/backend/dist/esm-dev/endpoint.d.ts +57 -0
  142. package/backend/dist/esm-dev/endpoint.js +421 -0
  143. package/backend/dist/esm-dev/file_watcher.d.ts +44 -0
  144. package/backend/dist/esm-dev/file_watcher.js +313 -0
  145. package/backend/dist/esm-dev/frontend.d.ts +13 -0
  146. package/backend/dist/esm-dev/frontend.js +27 -0
  147. package/backend/dist/esm-dev/image_endpoint.d.ts +24 -0
  148. package/backend/dist/esm-dev/image_endpoint.js +206 -0
  149. package/backend/dist/esm-dev/logger.d.ts +5 -0
  150. package/backend/dist/esm-dev/logger.js +13 -0
  151. package/backend/dist/esm-dev/meta.d.ts +50 -0
  152. package/backend/dist/esm-dev/meta.js +149 -0
  153. package/backend/dist/esm-dev/mutex.d.ts +24 -0
  154. package/backend/dist/esm-dev/mutex.js +48 -0
  155. package/backend/dist/esm-dev/payments/paddle.d.ts +161 -0
  156. package/backend/dist/esm-dev/payments/paddle.js +2261 -0
  157. package/backend/dist/esm-dev/plugins/browser.d.ts +36 -0
  158. package/backend/dist/esm-dev/plugins/browser.js +176 -0
  159. package/backend/dist/esm-dev/plugins/communication.d.ts +70 -0
  160. package/backend/dist/esm-dev/plugins/communication.js +169 -0
  161. package/backend/dist/esm-dev/plugins/css.d.ts +10 -0
  162. package/backend/dist/esm-dev/plugins/css.js +64 -0
  163. package/backend/dist/esm-dev/plugins/mail.d.ts +277 -0
  164. package/backend/dist/esm-dev/plugins/mail.js +1403 -0
  165. package/backend/dist/esm-dev/plugins/pdf.d.ts +757 -0
  166. package/backend/dist/esm-dev/plugins/pdf.js +1694 -0
  167. package/backend/dist/esm-dev/plugins/thread_monitor.d.ts +18 -0
  168. package/backend/dist/esm-dev/plugins/thread_monitor.js +120 -0
  169. package/backend/dist/esm-dev/plugins/ts/compiler.d.ts +132 -0
  170. package/backend/dist/esm-dev/plugins/ts/compiler.js +907 -0
  171. package/backend/dist/esm-dev/plugins/ts/preprocessing.d.ts +14 -0
  172. package/backend/dist/esm-dev/plugins/ts/preprocessing.js +724 -0
  173. package/backend/dist/esm-dev/rate_limit.d.ts +65 -0
  174. package/backend/dist/esm-dev/rate_limit.js +425 -0
  175. package/backend/dist/esm-dev/request.deprc.d.ts +48 -0
  176. package/backend/dist/esm-dev/request.deprc.js +572 -0
  177. package/backend/dist/esm-dev/response.deprc.d.ts +55 -0
  178. package/backend/dist/esm-dev/response.deprc.js +275 -0
  179. package/backend/dist/esm-dev/server.d.ts +311 -0
  180. package/backend/dist/esm-dev/server.js +3435 -0
  181. package/backend/dist/esm-dev/splash_screen.d.ts +35 -0
  182. package/backend/dist/esm-dev/splash_screen.js +148 -0
  183. package/backend/dist/esm-dev/status.d.ts +60 -0
  184. package/backend/dist/esm-dev/status.js +196 -0
  185. package/backend/dist/esm-dev/stream.d.ts +75 -0
  186. package/backend/dist/esm-dev/stream.js +947 -0
  187. package/backend/dist/esm-dev/users.d.ts +111 -0
  188. package/backend/dist/esm-dev/users.js +1908 -0
  189. package/backend/dist/esm-dev/utils.d.ts +27 -0
  190. package/backend/dist/esm-dev/utils.js +324 -0
  191. package/backend/dist/esm-dev/view.d.ts +52 -0
  192. package/backend/dist/esm-dev/view.js +561 -0
  193. package/backend/dist/esm-dev/vinc.d.ts +2 -0
  194. package/backend/dist/esm-dev/vinc.dev.d.ts +2 -0
  195. package/backend/dist/esm-dev/vinc.dev.js +6 -0
  196. package/backend/dist/esm-dev/vinc.js +6 -0
  197. package/backend/dist/esm-dev/volt.d.ts +15 -0
  198. package/backend/dist/esm-dev/volt.js +23 -0
  199. package/backend/src/blacklist.ts +69 -0
  200. package/backend/src/cli.js +245 -0
  201. package/backend/src/database.ts +2241 -0
  202. package/backend/src/endpoint.ts +494 -0
  203. package/backend/src/file_watcher.ts +359 -0
  204. package/backend/src/frontend.ts +35 -0
  205. package/backend/src/globals.d.ts +8 -0
  206. package/backend/src/image_endpoint.ts +258 -0
  207. package/backend/src/logger.ts +18 -0
  208. package/backend/src/meta.ts +202 -0
  209. package/backend/src/mutex.ts +51 -0
  210. package/backend/src/payments/paddle.ts +2659 -0
  211. package/backend/src/plugins/browser.ts +188 -0
  212. package/backend/src/plugins/communication.ts +204 -0
  213. package/backend/src/plugins/css.ts +84 -0
  214. package/backend/src/plugins/fonts/Menlo-Bold.ttf +0 -0
  215. package/backend/src/plugins/fonts/Menlo-Regular.ttf +0 -0
  216. package/backend/src/plugins/mail.ts +1720 -0
  217. package/backend/src/plugins/pdf.js +1932 -0
  218. package/backend/src/plugins/thread_monitor.ts +164 -0
  219. package/backend/src/plugins/ts/compiler.ts +1242 -0
  220. package/backend/src/plugins/ts/preprocessing.ts +812 -0
  221. package/backend/src/rate_limit.ts +503 -0
  222. package/backend/src/request.deprc.js +626 -0
  223. package/backend/src/response.deprc.js +354 -0
  224. package/backend/src/server.ts +4149 -0
  225. package/backend/src/splash_screen.ts +192 -0
  226. package/backend/src/status.ts +199 -0
  227. package/backend/src/stream.ts +1070 -0
  228. package/backend/src/users.ts +2077 -0
  229. package/backend/src/utils.ts +359 -0
  230. package/backend/src/view.ts +655 -0
  231. package/backend/src/vinc.dev.js +6 -0
  232. package/backend/src/vinc.ts +6 -0
  233. package/backend/src/volt.js +25 -0
  234. package/backend/tsconfig.cjs.json +29 -0
  235. package/backend/tsconfig.esm.dev.json +34 -0
  236. package/backend/tsconfig.esm.json +30 -0
  237. package/backend/tsconfig.json +2 -0
  238. package/frontend/compile.js +436 -0
  239. package/frontend/dist/elements/base.d.ts +9891 -0
  240. package/frontend/dist/elements/base.js +8818 -0
  241. package/frontend/dist/elements/module.d.ts +16 -0
  242. package/frontend/dist/elements/module.js +178 -0
  243. package/frontend/dist/modules/array.d.ts +37 -0
  244. package/frontend/dist/modules/array.js +284 -0
  245. package/frontend/dist/modules/auth.d.ts +45 -0
  246. package/frontend/dist/modules/auth.js +138 -0
  247. package/frontend/dist/modules/colors.d.ts +26 -0
  248. package/frontend/dist/modules/colors.js +340 -0
  249. package/frontend/dist/modules/compression.d.ts +6 -0
  250. package/frontend/dist/modules/compression.js +999 -0
  251. package/frontend/dist/modules/cookies.d.ts +17 -0
  252. package/frontend/dist/modules/cookies.js +166 -0
  253. package/frontend/dist/modules/date.d.ts +142 -0
  254. package/frontend/dist/modules/date.js +493 -0
  255. package/frontend/dist/modules/events.d.ts +7 -0
  256. package/frontend/dist/modules/events.js +90 -0
  257. package/frontend/dist/modules/google.d.ts +10 -0
  258. package/frontend/dist/modules/google.js +53 -0
  259. package/frontend/dist/modules/meta.d.ts +9 -0
  260. package/frontend/dist/modules/meta.js +45 -0
  261. package/frontend/dist/modules/mutex.d.ts +8 -0
  262. package/frontend/dist/modules/mutex.js +52 -0
  263. package/frontend/dist/modules/number.d.ts +12 -0
  264. package/frontend/dist/modules/number.js +8 -0
  265. package/frontend/dist/modules/object.d.ts +50 -0
  266. package/frontend/dist/modules/object.js +147 -0
  267. package/frontend/dist/modules/paddle.d.ts +1403 -0
  268. package/frontend/dist/modules/paddle.js +2641 -0
  269. package/frontend/dist/modules/scheme.d.ts +207 -0
  270. package/frontend/dist/modules/scheme.js +649 -0
  271. package/frontend/dist/modules/settings.d.ts +3 -0
  272. package/frontend/dist/modules/settings.js +4 -0
  273. package/frontend/dist/modules/statics.d.ts +4 -0
  274. package/frontend/dist/modules/statics.js +45 -0
  275. package/frontend/dist/modules/string.d.ts +163 -0
  276. package/frontend/dist/modules/string.js +291 -0
  277. package/frontend/dist/modules/support.d.ts +18 -0
  278. package/frontend/dist/modules/support.js +102 -0
  279. package/frontend/dist/modules/themes.d.ts +8 -0
  280. package/frontend/dist/modules/themes.js +17 -0
  281. package/frontend/dist/modules/user.d.ts +58 -0
  282. package/frontend/dist/modules/user.js +279 -0
  283. package/frontend/dist/modules/utils.d.ts +58 -0
  284. package/frontend/dist/modules/utils.js +1159 -0
  285. package/frontend/dist/types/gradient.d.ts +12 -0
  286. package/frontend/dist/types/gradient.js +79 -0
  287. package/frontend/dist/ui/border_button.d.ts +177 -0
  288. package/frontend/dist/ui/border_button.js +235 -0
  289. package/frontend/dist/ui/button.d.ts +42 -0
  290. package/frontend/dist/ui/button.js +114 -0
  291. package/frontend/dist/ui/canvas.d.ts +56 -0
  292. package/frontend/dist/ui/canvas.js +411 -0
  293. package/frontend/dist/ui/checkbox.d.ts +72 -0
  294. package/frontend/dist/ui/checkbox.js +277 -0
  295. package/frontend/dist/ui/code.d.ts +232 -0
  296. package/frontend/dist/ui/code.js +977 -0
  297. package/frontend/dist/ui/color.d.ts +1 -0
  298. package/frontend/dist/ui/color.js +110 -0
  299. package/frontend/dist/ui/context_menu.d.ts +30 -0
  300. package/frontend/dist/ui/context_menu.js +211 -0
  301. package/frontend/dist/ui/css.d.ts +10 -0
  302. package/frontend/dist/ui/css.js +44 -0
  303. package/frontend/dist/ui/divider.d.ts +18 -0
  304. package/frontend/dist/ui/divider.js +82 -0
  305. package/frontend/dist/ui/dropdown.d.ts +115 -0
  306. package/frontend/dist/ui/dropdown.js +446 -0
  307. package/frontend/dist/ui/for_each.d.ts +38 -0
  308. package/frontend/dist/ui/for_each.js +97 -0
  309. package/frontend/dist/ui/form.d.ts +25 -0
  310. package/frontend/dist/ui/form.js +227 -0
  311. package/frontend/dist/ui/frame_modes.d.ts +28 -0
  312. package/frontend/dist/ui/frame_modes.js +116 -0
  313. package/frontend/dist/ui/google_map.d.ts +31 -0
  314. package/frontend/dist/ui/google_map.js +111 -0
  315. package/frontend/dist/ui/gradient.d.ts +24 -0
  316. package/frontend/dist/ui/gradient.js +115 -0
  317. package/frontend/dist/ui/image.d.ts +138 -0
  318. package/frontend/dist/ui/image.js +570 -0
  319. package/frontend/dist/ui/input.d.ts +316 -0
  320. package/frontend/dist/ui/input.js +1187 -0
  321. package/frontend/dist/ui/link.d.ts +39 -0
  322. package/frontend/dist/ui/link.js +146 -0
  323. package/frontend/dist/ui/list.d.ts +33 -0
  324. package/frontend/dist/ui/list.js +161 -0
  325. package/frontend/dist/ui/loader_button.d.ts +108 -0
  326. package/frontend/dist/ui/loader_button.js +207 -0
  327. package/frontend/dist/ui/loaders.d.ts +60 -0
  328. package/frontend/dist/ui/loaders.js +150 -0
  329. package/frontend/dist/ui/popup.d.ts +84 -0
  330. package/frontend/dist/ui/popup.js +331 -0
  331. package/frontend/dist/ui/pseudo.d.ts +16 -0
  332. package/frontend/dist/ui/pseudo.js +81 -0
  333. package/frontend/dist/ui/scroller.d.ts +131 -0
  334. package/frontend/dist/ui/scroller.js +1251 -0
  335. package/frontend/dist/ui/slider.d.ts +35 -0
  336. package/frontend/dist/ui/slider.js +203 -0
  337. package/frontend/dist/ui/spacer.d.ts +20 -0
  338. package/frontend/dist/ui/spacer.js +83 -0
  339. package/frontend/dist/ui/span.d.ts +11 -0
  340. package/frontend/dist/ui/span.js +75 -0
  341. package/frontend/dist/ui/stack.d.ts +123 -0
  342. package/frontend/dist/ui/stack.js +344 -0
  343. package/frontend/dist/ui/steps.d.ts +72 -0
  344. package/frontend/dist/ui/steps.js +306 -0
  345. package/frontend/dist/ui/style.d.ts +12 -0
  346. package/frontend/dist/ui/style.js +78 -0
  347. package/frontend/dist/ui/switch.d.ts +44 -0
  348. package/frontend/dist/ui/switch.js +280 -0
  349. package/frontend/dist/ui/table.d.ts +118 -0
  350. package/frontend/dist/ui/table.js +411 -0
  351. package/frontend/dist/ui/tabs.d.ts +85 -0
  352. package/frontend/dist/ui/tabs.js +392 -0
  353. package/frontend/dist/ui/text.d.ts +19 -0
  354. package/frontend/dist/ui/text.js +88 -0
  355. package/frontend/dist/ui/theme.d.ts +25 -0
  356. package/frontend/dist/ui/theme.js +237 -0
  357. package/frontend/dist/ui/title.d.ts +36 -0
  358. package/frontend/dist/ui/title.js +127 -0
  359. package/frontend/dist/ui/ui.d.ts +38 -0
  360. package/frontend/dist/ui/ui.js +41 -0
  361. package/frontend/dist/ui/view.d.ts +25 -0
  362. package/frontend/dist/ui/view.js +93 -0
  363. package/frontend/dist/volt.d.ts +22 -0
  364. package/frontend/dist/volt.js +27 -0
  365. package/frontend/exports.json +1340 -0
  366. package/frontend/src/css/adyen.css +92 -0
  367. package/frontend/src/css/volt.css +65 -0
  368. package/frontend/src/elements/base.ts +16790 -0
  369. package/frontend/src/elements/module.ts +184 -0
  370. package/frontend/src/elements/types.d.ts +155 -0
  371. package/frontend/src/modules/array.ts +366 -0
  372. package/frontend/src/modules/auth.ts +188 -0
  373. package/frontend/src/modules/colors.ts +449 -0
  374. package/frontend/src/modules/compression.ts +67 -0
  375. package/frontend/src/modules/cookies.ts +182 -0
  376. package/frontend/src/modules/date.js +535 -0
  377. package/frontend/src/modules/date.ts +583 -0
  378. package/frontend/src/modules/events.ts +96 -0
  379. package/frontend/src/modules/google.ts +60 -0
  380. package/frontend/src/modules/meta.ts +59 -0
  381. package/frontend/src/modules/mutex.ts +59 -0
  382. package/frontend/src/modules/number.ts +20 -0
  383. package/frontend/src/modules/object.ts +212 -0
  384. package/frontend/src/modules/paddle.ts +2990 -0
  385. package/frontend/src/modules/scheme.ts +740 -0
  386. package/frontend/src/modules/settings.ts +5 -0
  387. package/frontend/src/modules/statics.ts +47 -0
  388. package/frontend/src/modules/string.ts +500 -0
  389. package/frontend/src/modules/support.ts +118 -0
  390. package/frontend/src/modules/themes.ts +24 -0
  391. package/frontend/src/modules/user.ts +321 -0
  392. package/frontend/src/modules/utils.ts +1260 -0
  393. package/frontend/src/static/admin/admin.png +0 -0
  394. package/frontend/src/static/admin/password.webp +0 -0
  395. package/frontend/src/static/icons/copy.webp +0 -0
  396. package/frontend/src/static/payments/arrow.long.webp +0 -0
  397. package/frontend/src/static/payments/arrow.long2.webp +0 -0
  398. package/frontend/src/static/payments/cancelled.webp +0 -0
  399. package/frontend/src/static/payments/check.sign.webp +0 -0
  400. package/frontend/src/static/payments/check.webp +0 -0
  401. package/frontend/src/static/payments/close.webp +0 -0
  402. package/frontend/src/static/payments/error.webp +0 -0
  403. package/frontend/src/static/payments/exclamation.webp +0 -0
  404. package/frontend/src/static/payments/minus.webp +0 -0
  405. package/frontend/src/static/payments/party.webp +0 -0
  406. package/frontend/src/static/payments/plus.webp +0 -0
  407. package/frontend/src/static/payments/shopping_cart.webp +0 -0
  408. package/frontend/src/static/payments/trash.webp +0 -0
  409. package/frontend/src/types/global.d.ts +4 -0
  410. package/frontend/src/types/gradient.ts +87 -0
  411. package/frontend/src/ui/any_element.d.ts +5 -0
  412. package/frontend/src/ui/border_button.ts +320 -0
  413. package/frontend/src/ui/button.ts +62 -0
  414. package/frontend/src/ui/canvas.ts +431 -0
  415. package/frontend/src/ui/checkbox.ts +284 -0
  416. package/frontend/src/ui/code.ts +1049 -0
  417. package/frontend/src/ui/color.ts +117 -0
  418. package/frontend/src/ui/context_menu.ts +194 -0
  419. package/frontend/src/ui/css.ts +57 -0
  420. package/frontend/src/ui/divider.ts +28 -0
  421. package/frontend/src/ui/dropdown.ts +503 -0
  422. package/frontend/src/ui/for_each.ts +71 -0
  423. package/frontend/src/ui/form.ts +208 -0
  424. package/frontend/src/ui/frame_modes.ts +140 -0
  425. package/frontend/src/ui/google_map.ts +70 -0
  426. package/frontend/src/ui/gradient.ts +73 -0
  427. package/frontend/src/ui/image.ts +587 -0
  428. package/frontend/src/ui/input.ts +1284 -0
  429. package/frontend/src/ui/link.ts +77 -0
  430. package/frontend/src/ui/list.ts +88 -0
  431. package/frontend/src/ui/loader_button.ts +192 -0
  432. package/frontend/src/ui/loaders.ts +126 -0
  433. package/frontend/src/ui/popup.ts +370 -0
  434. package/frontend/src/ui/pseudo.ts +33 -0
  435. package/frontend/src/ui/scroller.ts +1324 -0
  436. package/frontend/src/ui/slider.ts +215 -0
  437. package/frontend/src/ui/spacer.ts +29 -0
  438. package/frontend/src/ui/span.ts +23 -0
  439. package/frontend/src/ui/stack.ts +238 -0
  440. package/frontend/src/ui/steps.ts +334 -0
  441. package/frontend/src/ui/style.ts +26 -0
  442. package/frontend/src/ui/switch.ts +286 -0
  443. package/frontend/src/ui/table.ts +323 -0
  444. package/frontend/src/ui/tabs.ts +441 -0
  445. package/frontend/src/ui/text.ts +38 -0
  446. package/frontend/src/ui/theme.ts +279 -0
  447. package/frontend/src/ui/title.ts +64 -0
  448. package/frontend/src/ui/ui.ts +47 -0
  449. package/frontend/src/ui/view.ts +44 -0
  450. package/frontend/src/volt.ts +31 -0
  451. package/package.json +58 -0
@@ -0,0 +1,1962 @@
1
+ "use strict";
2
+ /*
3
+ * Author: Daan van den Bergh
4
+ * Copyright: © 2022 - 2024 Daan van den Bergh.
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.Database = exports.UIDCollection = exports.Collection = void 0;
8
+ // ---------------------------------------------------------
9
+ // Libraries.
10
+ const child_process_1 = require("child_process");
11
+ const bson_1 = require("bson");
12
+ const mongodb_1 = require("mongodb");
13
+ const logger_js_1 = require("./logger.js");
14
+ const _vinc_1 = require("./vinc.js");
15
+ const log_source = new logger_js_1.LogSource("Database");
16
+ // ---------------------------------------------------------
17
+ // Collection.
18
+ // Path based collection, so "myfile", "mydir/myfile".
19
+ // @warning: The "path" param must always be allowed to be an object or string, also for the UIDCollection class.
20
+ // @warning: THE DATABASE COLLECTION SHOULD ALSO ACCEPT OBJECTS FOR PATHS.
21
+ /* @docs:
22
+ @nav: Backend
23
+ @chapter: Database
24
+ @title: Collection
25
+ @desc: The database collection class.
26
+ @note: The document attribute `_path` is a reserved index attribute for the path of the document.
27
+ @attribute:
28
+ @name: col
29
+ @desc: The native mongodb collection.
30
+ */
31
+ class Collection {
32
+ // Static attributes.
33
+ static chunk_size = 1024 * 1024 * 4; // 4MB chunks, lower is better for frequent updates.
34
+ static constructor_scheme = {
35
+ name: "string",
36
+ uid_based: "boolean",
37
+ ttl: { type: "number", default: null },
38
+ indexes: {
39
+ type: "array",
40
+ default: [],
41
+ value_scheme: {
42
+ type: ["string", "object"],
43
+ scheme: {
44
+ key: { type: "string", required: (data) => data.key == null && data.keys == null },
45
+ keys: {
46
+ type: ["string", "array"],
47
+ required: (data) => data.key == null && data.keys == null, value_scheme: "string",
48
+ postprocess: (keys) => typeof keys === "string" ? [keys] : keys,
49
+ },
50
+ options: { type: "object", required: false },
51
+ commit_quorom: { type: "object", required: false },
52
+ forced: { type: "boolean", default: false },
53
+ },
54
+ postprocess: (info) => {
55
+ if (typeof info === "string")
56
+ return { keys: [info] };
57
+ if (typeof info === "object" && info.key) {
58
+ info.keys = info.key;
59
+ delete info.key;
60
+ return info;
61
+ }
62
+ return info;
63
+ },
64
+ },
65
+ },
66
+ };
67
+ // Instance attributes
68
+ col;
69
+ name;
70
+ uid_based;
71
+ ttl;
72
+ ttl_enabled;
73
+ constructor(name, collection, ttl = null, indexes = [], uid_based = false) {
74
+ // Verify scheme.
75
+ ({ indexes, ttl } = _vinc_1.vlib.Scheme.verify({
76
+ object: {
77
+ name,
78
+ indexes,
79
+ ttl,
80
+ uid_based,
81
+ },
82
+ check_unknown: true,
83
+ scheme: Collection.constructor_scheme,
84
+ }));
85
+ // Attributes.
86
+ this.name = name;
87
+ this.col = collection;
88
+ this.uid_based = uid_based;
89
+ this.ttl = ttl;
90
+ this.ttl_enabled = typeof ttl === "number";
91
+ // Create default indexes.
92
+ if (uid_based) {
93
+ this.col.createIndex({ _path: 1, _uid: 1 });
94
+ }
95
+ else {
96
+ this.col.createIndex({ _path: 1 });
97
+ }
98
+ // Create ttl index.
99
+ if (this.ttl_enabled) {
100
+ this.col.dropIndex("_ttl_timestamp_1")
101
+ .catch(err => {
102
+ if (err.codeName !== 'IndexNotFound') {
103
+ throw err;
104
+ }
105
+ })
106
+ .then(() => {
107
+ this.col.createIndex({ _ttl_timestamp: 1 }, { expireAfterSeconds: parseInt(String(this.ttl / 1000)) });
108
+ });
109
+ }
110
+ // Create indexes.
111
+ if (Array.isArray(indexes) && indexes.length > 0) {
112
+ for (const index of indexes) {
113
+ this.create_index({
114
+ keys: index.keys,
115
+ options: index.options,
116
+ commit_quorum: index.commit_quorum,
117
+ forced: index.forced,
118
+ });
119
+ }
120
+ }
121
+ }
122
+ // Handle file response.
123
+ _process_doc(doc) {
124
+ if (doc == null) {
125
+ return null;
126
+ }
127
+ else if (doc._content != null) {
128
+ return doc._content;
129
+ }
130
+ return doc;
131
+ }
132
+ // Chunked methods.
133
+ async _load_chunked(path, find_opts) {
134
+ let query = typeof path === "string" ?
135
+ { _path: path, chunk: { $gte: 0 } } :
136
+ { ...path, chunk: { $gte: 0 } };
137
+ const chunks_cursor = this.col.find(query, find_opts).sort({ chunk: 1 });
138
+ const chunks = await chunks_cursor.toArray();
139
+ if (chunks.length === 0) {
140
+ return null;
141
+ }
142
+ const buffer = Buffer.concat(chunks.map(chunk => chunk.data.buffer));
143
+ return (0, bson_1.deserialize)(buffer);
144
+ }
145
+ async _save_chunked(path, content) {
146
+ // Serialize.
147
+ const buffer = (0, bson_1.serialize)(content);
148
+ const new_chunk_count = Math.ceil(buffer.length / Collection.chunk_size);
149
+ // Retrieve the old chunk count
150
+ const ref_query = typeof path === "string" ?
151
+ { _path: path, chunk: -1 } :
152
+ { ...path, chunk: -1 };
153
+ const object_ref = await this.col.findOne(ref_query);
154
+ const old_chunk_count = object_ref ? object_ref.chunks : 0;
155
+ // Update chunks.
156
+ const bulk_ops = [];
157
+ for (let i = 0; i < buffer.length; i += Collection.chunk_size) {
158
+ let query, update;
159
+ if (typeof path === "string") {
160
+ query = {
161
+ _path: path,
162
+ chunk: i / Collection.chunk_size,
163
+ };
164
+ update = {
165
+ chunk: i / Collection.chunk_size,
166
+ data: buffer.slice(i, i + Collection.chunk_size)
167
+ };
168
+ }
169
+ else {
170
+ query = {
171
+ ...path,
172
+ chunk: i / Collection.chunk_size,
173
+ };
174
+ update = {
175
+ chunk: i / Collection.chunk_size,
176
+ data: buffer.slice(i, i + Collection.chunk_size)
177
+ };
178
+ }
179
+ const full_update = {
180
+ $set: update,
181
+ };
182
+ if (this.ttl_enabled) {
183
+ full_update["$setOnInsert"] = { _ttl_timestamp: new Date() };
184
+ }
185
+ bulk_ops.push({
186
+ updateOne: {
187
+ filter: query,
188
+ update: full_update,
189
+ upsert: true
190
+ }
191
+ });
192
+ }
193
+ // Update reference.
194
+ const full_update = {
195
+ $set: {
196
+ chunk: -1,
197
+ chunks: new_chunk_count,
198
+ },
199
+ };
200
+ if (this.ttl_enabled) {
201
+ full_update["$setOnInsert"] = { _ttl_timestamp: new Date() };
202
+ }
203
+ bulk_ops.push({
204
+ updateOne: {
205
+ filter: ref_query,
206
+ update: full_update,
207
+ upsert: true
208
+ }
209
+ });
210
+ // Write.
211
+ await this.col.bulkWrite(bulk_ops, { ordered: true });
212
+ // Delete any excess chunks if the new chunk count is less than the old chunk count
213
+ if (new_chunk_count < old_chunk_count) {
214
+ ref_query.chunk = { $gte: new_chunk_count };
215
+ await this.col.deleteMany(ref_query);
216
+ }
217
+ }
218
+ /* @docs:
219
+ @title: Create index
220
+ @description: Creates indexes on collections.
221
+ @return:
222
+ Returns the document that was found or `null` when no document is found.
223
+ @parameter:
224
+ @name: keys
225
+ @desc: The `keys` argument for the orignal mongodb `createIndex()` function.
226
+ @parameter:
227
+ @name: options
228
+ @desc: The `options` argument for the orignal mongodb `createIndex()` function.
229
+ @parameter:
230
+ @name: commitQuorum
231
+ @desc: The `commitQuorum` argument for the orignal mongodb `createIndex()` function.
232
+ */
233
+ async create_index({ keys, options = null, commit_quorum = null, forced = false }) {
234
+ let keys_obj = {};
235
+ if (typeof keys === "string") {
236
+ keys_obj = {};
237
+ keys_obj[keys] = 1;
238
+ }
239
+ else if (Array.isArray(keys)) {
240
+ keys_obj = {};
241
+ for (const key of keys) {
242
+ keys_obj[key] = 1;
243
+ }
244
+ }
245
+ else if (keys == null || typeof keys !== "object") {
246
+ _vinc_1.vlib.Scheme.throw_invalid_type("keys", keys, ["string", "string[]", "object"], true);
247
+ }
248
+ else {
249
+ keys_obj = keys;
250
+ }
251
+ // Drop index.
252
+ if (forced) {
253
+ try {
254
+ await this.col.dropIndex(options?.name ??
255
+ Object.entries(keys_obj)
256
+ .map(([key, value]) => `${key}_${value}`)
257
+ .join('_'));
258
+ }
259
+ catch (err) {
260
+ if (err.codeName !== 'IndexNotFound') {
261
+ throw err;
262
+ }
263
+ }
264
+ }
265
+ // Create index.
266
+ // @ts-ignore
267
+ return await this.col.createIndex(keys_obj, options || {}, commit_quorum);
268
+ }
269
+ /* @docs:
270
+ * @title: Find
271
+ * @description: Find a document by a query.
272
+ * @return:
273
+ * Returns the document that was found or `null` when no document is found.
274
+ * @parameter:
275
+ * @name: query
276
+ * @desc: The query options.
277
+ * @type: object
278
+ */
279
+ async find(query) {
280
+ try {
281
+ return this._process_doc(await this.col.findOne(query));
282
+ }
283
+ catch (error) {
284
+ console.error(error);
285
+ throw new Error('Encountered an error while finding the document.');
286
+ }
287
+ }
288
+ /* @docs:
289
+ * @title: Exists
290
+ * @description: Check if a document exists.
291
+ * @parameter:
292
+ * @name: path
293
+ * @description: The database path to the document.
294
+ * @type: string
295
+ */
296
+ async exists(path) {
297
+ if (typeof path !== "string" && (typeof path !== "object" || path == null)) {
298
+ throw Error(`Parameter "path" has an invalid type "${typeof path}", the valid type is "string".`);
299
+ }
300
+ try {
301
+ const doc = await this.col.findOne(typeof path === "object" ? path : { _path: path }, { projection: { _id: 1 } });
302
+ return doc != null;
303
+ }
304
+ catch (error) {
305
+ console.error(error);
306
+ throw new Error('Encountered an error while checking if the document exists.');
307
+ }
308
+ }
309
+ /* @docs:
310
+ * @title: Load
311
+ * @description: Load data by path.
312
+ * @return:
313
+ * Returns the loaded document.
314
+ *
315
+ * Returns the `def` parameter when the data does not exist, keep in mind that when parameter `def` is an object it could be a reference to a defined variable.
316
+ * @parameter:
317
+ * @name: path
318
+ * @description: The database path to the document.
319
+ * @type: string
320
+ * @parameter:
321
+ * @name: opts
322
+ * @desc: Additional options.
323
+ * @type: null, object
324
+ * @attribute:
325
+ * @name: default
326
+ * @description:
327
+ * The default data to be returned when the data does not exist.
328
+ *
329
+ * When the type of attribute `default` is `object` then the keys that do not exist in the loaded object, but do exist in the default object will be inserted into the loaded object.
330
+ * @type: null, object
331
+ * @attribute:
332
+ * @name: chunked
333
+ * @description: Load a chunked document.
334
+ * @type: null, object
335
+ * @attribute:
336
+ * @name: attributes
337
+ * @description: The attributes to load.
338
+ * @type: null, string[]
339
+ */
340
+ async load(path, opts = null) {
341
+ if (typeof path !== "string" && (typeof path !== "object" || path == null)) {
342
+ throw Error(`Parameter "path" has an invalid type "${typeof path}", the valid type is "string".`);
343
+ }
344
+ try {
345
+ // Get attributes.
346
+ let find_opts;
347
+ if (opts) {
348
+ if (opts.projection) {
349
+ find_opts = { projection: opts.projection };
350
+ }
351
+ else if (opts.attributes) {
352
+ find_opts = { projection: {
353
+ _id: 1,
354
+ _path: 1,
355
+ _uid: 1,
356
+ } };
357
+ opts.attributes.forEach((i) => {
358
+ if (find_opts?.projection) {
359
+ find_opts.projection[i] = 1;
360
+ }
361
+ });
362
+ }
363
+ }
364
+ // Load doc.
365
+ let doc;
366
+ if (opts != null && opts.chunked === true) {
367
+ doc = await this._load_chunked(path, find_opts);
368
+ }
369
+ else {
370
+ // Load.
371
+ doc = await this.col.findOne(typeof path === "object" ? path : { _path: path }, find_opts);
372
+ this.clean(doc);
373
+ }
374
+ // Process doc.
375
+ doc = this._process_doc(doc);
376
+ // Handle default.
377
+ if (doc == null) {
378
+ if (opts != null && opts.default !== undefined) {
379
+ return opts.default;
380
+ }
381
+ return null;
382
+ }
383
+ // Insert default keys.
384
+ else if (opts != null && typeof opts.default === "object" && opts.default != null && Array.isArray(opts.default) === false) {
385
+ const set_defaults = (obj, defaults) => {
386
+ Object.keys(defaults).forEach((key) => {
387
+ if (obj[key] === undefined) {
388
+ obj[key] = defaults[key];
389
+ }
390
+ else if (typeof obj[key] === "object" && !Array.isArray(obj[key]) && obj[key] != null &&
391
+ typeof defaults[key] === "object" && !Array.isArray(defaults[key]) && defaults[key] != null) {
392
+ set_defaults(obj[key], defaults[key]);
393
+ }
394
+ });
395
+ };
396
+ set_defaults(doc, opts.default);
397
+ }
398
+ // Response.
399
+ return doc;
400
+ }
401
+ catch (error) {
402
+ console.error(error);
403
+ throw new Error('Encountered an error while loading the document.');
404
+ }
405
+ }
406
+ /* @docs:
407
+ * @title: Save
408
+ * @description: Save data by path. When the document already exists this function only updates the specified content attributes.
409
+ * @return:
410
+ * Returns the updated document.
411
+ * @parameter:
412
+ * @name: path
413
+ * @description: The database path to the document.
414
+ * @type: string
415
+ * @parameter:
416
+ * @name: data
417
+ * @description: The data to save.
418
+ * @type: null, boolean, number, string, array, object
419
+ * @parameter:
420
+ * @name: opts
421
+ * @desc: Additional options.
422
+ * @type: null, object
423
+ * @attribute:
424
+ * @name: chunked
425
+ * @description: Chunk the document into multiple documents, therefore documents larger than 16MB are supported.
426
+ * @warning: Currently this option is only supported for types `object` and `array`.
427
+ * @default: false
428
+ * @type: boolean
429
+ * @attribute:
430
+ * @name: bulk
431
+ * @description: Get a bulk operation object, so several operations can be executed in bulk.
432
+ * @default: false
433
+ * @type: boolean
434
+ * @attribute:
435
+ * @name: set
436
+ * @description: By default the $set attribute is used for the content, with `opts.set` disabled you can create your own instructions. The `content` attribute must reflect this.
437
+ * @warning: This does not work in combination with `opts.chunked`.
438
+ * @default: true
439
+ * @type: boolean
440
+ */
441
+ async save(path, content, opts = null) {
442
+ if (typeof path !== "string" && (typeof path !== "object" || path == null)) {
443
+ throw Error(`Parameter "path" has an invalid type "${typeof path}", the valid type is "string".`);
444
+ }
445
+ try {
446
+ // Vars.
447
+ let doc, set;
448
+ // Create set.
449
+ if (typeof content === "object" && Array.isArray(content) == false && content != null) {
450
+ delete content._id;
451
+ delete content._path;
452
+ delete content._uid;
453
+ delete content._ttl_timestamp;
454
+ set = content;
455
+ }
456
+ else {
457
+ set = { _content: content };
458
+ }
459
+ // Save chunked.
460
+ if (opts != null && opts.chunked === true) {
461
+ await this._save_chunked(path, set);
462
+ }
463
+ // Save as single doc.
464
+ else {
465
+ // Apply $set rules.
466
+ if (opts == null || (opts.set !== false)) {
467
+ set = { $set: set };
468
+ }
469
+ // Apply TTL.
470
+ if (this.ttl_enabled) {
471
+ if (set["$setOnInsert"] === undefined) {
472
+ set["$setOnInsert"] = {};
473
+ set["$setOnInsert"]._ttl_timestamp = new Date();
474
+ }
475
+ else if (set["$setOnInsert"] != null && typeof set["$setOnInsert"] === "object") {
476
+ set["$setOnInsert"]._ttl_timestamp = new Date();
477
+ }
478
+ else {
479
+ throw new Error(`Undefined behaviour: Unable to assign the $setOnInsert data for ttl control.`);
480
+ }
481
+ }
482
+ // Bulk operation.
483
+ if (opts != null && opts.bulk) {
484
+ return {
485
+ updateOne: {
486
+ filter: typeof path === "object" ? path : { _path: path },
487
+ update: set,
488
+ upsert: true,
489
+ }
490
+ };
491
+ }
492
+ // Normal operation.
493
+ else {
494
+ await this.col.updateOne(typeof path === "object" ? path : { _path: path }, set, { upsert: true });
495
+ }
496
+ }
497
+ // Response.
498
+ return content;
499
+ }
500
+ catch (error) {
501
+ console.error(error);
502
+ throw new Error('Encountered an error while updating the document.');
503
+ }
504
+ }
505
+ // List.
506
+ /* @docs:
507
+ * @title: List
508
+ * @description: List all child documents of directory path.
509
+ * @parameter:
510
+ * @name: path
511
+ * @description: The database directory path.
512
+ * @type: string
513
+ * @parameter:
514
+ * @name: options
515
+ * @description: List options.
516
+ * @type: object
517
+ * @attribute:
518
+ * @name: process
519
+ * @description: Process the document. By default saved non object data will be stored under `_content`. Processing checks this attribute and uses that content instead when it is detected.
520
+ * @type: boolean
521
+ * @default: true
522
+ * @attribute:
523
+ * @name: projection
524
+ * @description: The data attributes to retrieve, when left undefined all attributes are retrieved.
525
+ * @type: object
526
+ * @default: undefined
527
+ */
528
+ async list(path, options = {}) {
529
+ if (typeof path !== "string" && (typeof path !== "object" || path == null)) {
530
+ throw Error(`Parameter "path" has an invalid type "${typeof path}", the valid type is "string".`);
531
+ }
532
+ if (typeof path === "string") {
533
+ while (path.length > 0 && path.charAt(path.length - 1) === "/") {
534
+ path = path.substr(0, path.length - 1);
535
+ }
536
+ if (path.length == 0) {
537
+ throw Error("Invalid path.");
538
+ }
539
+ path = { _path: { $regex: `^${path}/` } };
540
+ }
541
+ else if (path._path) {
542
+ let _path = path._path;
543
+ while (_path.length > 0 && _path.charAt(_path.length - 1) === "/") {
544
+ _path = _path.substr(0, _path.length - 1);
545
+ }
546
+ if (_path.length == 0) {
547
+ throw Error("Invalid path.");
548
+ }
549
+ path._path = { $regex: `^${_path}/` };
550
+ }
551
+ try {
552
+ const docs = await this.col.find(path, { projection: options.projection }).toArray();
553
+ if (options.process === false) {
554
+ return docs;
555
+ }
556
+ return docs.map((doc) => this._process_doc(doc));
557
+ }
558
+ catch (error) {
559
+ console.error(error);
560
+ throw new Error('Encountered an error while listing all documents.');
561
+ }
562
+ }
563
+ /* @docs:
564
+ * @title: List Query
565
+ * @description: List all documents of the collection based on a query.
566
+ * @parameter:
567
+ * @name: query
568
+ * @desc: The query options.
569
+ * @type: object
570
+ * @parameter:
571
+ * @name: options
572
+ * @description: List options.
573
+ * @type: object
574
+ * @attribute:
575
+ * @name: process
576
+ * @description: Process the document. By default saved non object data will be stored under `_content`. Processing checks this attribute and uses that content instead when it is detected.
577
+ * @type: boolean
578
+ * @default: true
579
+ * @attribute:
580
+ * @name: projection
581
+ * @description: The data attributes to retrieve, when left undefined all attributes are retrieved.
582
+ * @type: object
583
+ * @default: undefined
584
+ */
585
+ async list_query(query = {}, options = {}) {
586
+ try {
587
+ const docs = await this.col.find(query, { projection: options.projection }).toArray();
588
+ if (options.process === false) {
589
+ return docs;
590
+ }
591
+ return docs.map((doc) => this._process_doc(doc)); // list as array since the user might have used a path object width different attributes so dict is not reliable.
592
+ }
593
+ catch (error) {
594
+ console.error(error);
595
+ throw new Error('Encountered an error while listing all documents.');
596
+ }
597
+ }
598
+ /* @docs:
599
+ * @title: List All
600
+ * @description: List all documents of the collection, optionally per uid.
601
+ * @parameter:
602
+ * @name: query
603
+ * @ignore: true
604
+ * @parameter:
605
+ * @name: options
606
+ * @description: List options.
607
+ * @type: object
608
+ * @attribute:
609
+ * @name: process
610
+ * @description: Process the document. By default saved non object data will be stored under `_content`. Processing checks this attribute and uses that content instead when it is detected.
611
+ * @type: boolean
612
+ * @default: true
613
+ * @attribute:
614
+ * @name: projection
615
+ * @description: The data attributes to retrieve, when left undefined all attributes are retrieved.
616
+ * @type: object
617
+ * @default: undefined
618
+ */
619
+ async list_all(query = {}, options = {}) {
620
+ let docs;
621
+ if (this.uid_based) {
622
+ docs = await this.col.find(query, { projection: options.projection }).toArray();
623
+ }
624
+ else {
625
+ docs = await this.col.find(query, { projection: options.projection }).toArray();
626
+ }
627
+ if (options.process === false) {
628
+ return docs;
629
+ }
630
+ return docs.map((doc) => this._process_doc(doc)); // list as array since the user might have used a path object width different attributes so dict is not reliable.
631
+ }
632
+ /* @docs:
633
+ * @title: Delete
634
+ * @description: Delete a document of the collection by path.
635
+ * @parameter:
636
+ * @name: path
637
+ * @description: The database path to the document.
638
+ * @type: string
639
+ * @parameter:
640
+ * @name: opts
641
+ * @desc: Additional options.
642
+ * @type: null, object
643
+ * @attribute:
644
+ * @name: chunked
645
+ * @description: Delete a chunked document.
646
+ * @default: false
647
+ * @type: boolean
648
+ * @attribute:
649
+ * @name: bulk
650
+ * @description: Get a bulk operation object, so several operations can be executed in bulk.
651
+ * @default: false
652
+ * @type: boolean
653
+ */
654
+ async delete(path, opts = null) {
655
+ if (typeof path !== "string" && (typeof path !== "object" || path == null)) {
656
+ throw Error(`Parameter "path" has an invalid type "${typeof path}", the valid type is "string".`);
657
+ }
658
+ try {
659
+ if (opts != null && opts.chunked === true) {
660
+ if (opts.bulk) {
661
+ return { deleteMany: { filter: typeof path === "object" ? path : { _path: path } } };
662
+ }
663
+ else {
664
+ await this.col.deleteMany(typeof path === "object" ? path : { _path: path });
665
+ }
666
+ }
667
+ else {
668
+ if (opts != null && opts.bulk) {
669
+ return { deleteOne: { filter: typeof path === "object" ? path : { _path: path } } };
670
+ }
671
+ else {
672
+ await this.col.deleteOne(typeof path === "object" ? path : { _path: path });
673
+ }
674
+ }
675
+ }
676
+ catch (error) {
677
+ console.error(error);
678
+ throw new Error('Encountered an error while deleting.');
679
+ }
680
+ }
681
+ /* @docs:
682
+ * @title: Delete Query
683
+ * @description: Delete a document of the collection by query.
684
+ * @parameter:
685
+ * @name: query
686
+ * @description: The query object.
687
+ * @type: object
688
+ */
689
+ async delete_query(query = {}) {
690
+ if (typeof query !== "object" || query == null || Object.keys(query).length === 0) {
691
+ throw Error(`Parameter "query" has an invalid type "${typeof query}", the valid type is "object".`);
692
+ }
693
+ if (Object.keys(query).length === 0) {
694
+ throw Error(`Parameter "query" is an empty object.`);
695
+ }
696
+ return await this.col.deleteMany(query);
697
+ }
698
+ // Delete all.
699
+ async delete_all(path) {
700
+ if (typeof path !== "string" && (typeof path !== "object" || path == null)) {
701
+ throw Error(`Parameter "path" has an invalid type "${typeof path}", the valid type is "string".`);
702
+ }
703
+ try {
704
+ await this.col.deleteMany(typeof path === "object" ? path : { _path: path });
705
+ }
706
+ catch (error) {
707
+ console.error(error);
708
+ throw new Error('Encountered an error while deleting.');
709
+ }
710
+ }
711
+ /* @docs:
712
+ * @title: Delete Collection
713
+ * @description: Delete all documents of from the collection.
714
+ */
715
+ async delete_collection() {
716
+ await this.col.deleteMany();
717
+ await this.col.drop();
718
+ }
719
+ /* @docs:
720
+ * @title: Clean document
721
+ * @description: Clean a document from all default system attributes.
722
+ */
723
+ clean(doc) {
724
+ if (doc == null) {
725
+ return doc;
726
+ }
727
+ if (typeof doc === "object") {
728
+ delete doc._id;
729
+ delete doc._path;
730
+ if (this.uid_based) {
731
+ delete doc._uid;
732
+ }
733
+ if (this.ttl_enabled) {
734
+ delete doc._ttl_timestamp;
735
+ }
736
+ }
737
+ return doc;
738
+ }
739
+ /** Write bulk operations. */
740
+ async bulk_operations(operations = []) {
741
+ return await this.col.bulkWrite(operations, { ordered: true });
742
+ }
743
+ }
744
+ exports.Collection = Collection;
745
+ // ---------------------------------------------------------
746
+ // UID based collection.
747
+ // @warning: The "path" param must always be allowed to be an object or string, also for the UIDCollection class.
748
+ // @warning: THE DATABASE COLLECTION SHOULD ALSO ACCEPT OBJECTS FOR PATHS.
749
+ /* @docs:
750
+ @nav: Backend
751
+ @chapter: Database
752
+ @title: UID Collection
753
+ @desc: The UID based database collection class.
754
+ @note: The document attribute `_uid` is a reserved index attribute for the user id of the document.
755
+ @note: The document attribute `_path` is a reserved index attribute for the path of the document.
756
+ @attribute:
757
+ @name: col
758
+ @desc: The native mongodb collection.
759
+ */
760
+ class UIDCollection {
761
+ _col;
762
+ col;
763
+ constructor(name, collection, indexes = [], ttl = null) {
764
+ this._col = new Collection(name, collection, ttl, indexes, true);
765
+ this.col = this._col.col;
766
+ }
767
+ /* @docs:
768
+ @title: Create index
769
+ @description: Creates indexes on collections.
770
+ @return:
771
+ Returns the document that was found or `null` when no document is found.
772
+ @parameter:
773
+ @name: keys
774
+ @desc: The `keys` argument for the orignal mongodb `createIndex()` function.
775
+ @parameter:
776
+ @name: options
777
+ @desc: The `options` argument for the orignal mongodb `createIndex()` function.
778
+ @parameter:
779
+ @name: commitQuorum
780
+ @desc: The `commitQuorum` argument for the orignal mongodb `createIndex()` function.
781
+ */
782
+ async create_index({ keys, options = null, commit_quorum = null }) {
783
+ return this._col.create_index({ keys, options, commit_quorum });
784
+ }
785
+ /* @docs:
786
+ * @title: Find
787
+ * @description: Find a document by a query.
788
+ * @return:
789
+ * Returns the document that was found or `null` when no document is found.
790
+ * @parameter:
791
+ * @name: uid
792
+ * @cached: Users:uid:param
793
+ * @required: false
794
+ * @parameter:
795
+ * @name: query
796
+ * @desc: The query options.
797
+ * @type: object
798
+ */
799
+ async find(uid = null, query = {}) {
800
+ if (uid != null) {
801
+ query._uid = uid;
802
+ }
803
+ return await this._col.find(query);
804
+ }
805
+ /* @docs:
806
+ * @title: Exists
807
+ * @description: Check if a document exists.
808
+ * @parameter:
809
+ * @name: uid
810
+ * @cached: Users:uid:param
811
+ * @parameter:
812
+ * @name: path
813
+ * @description: The database path to the document.
814
+ * @type: string, object
815
+ */
816
+ async exists(uid, path) {
817
+ if (typeof path !== "string" && (typeof path !== "object" || path == null)) {
818
+ throw Error(`Parameter "path" has an invalid type "${typeof path}", the valid type is "string".`);
819
+ }
820
+ if (typeof uid !== "string") {
821
+ throw Error(`Parameter "uid" has an invalid type "${typeof uid}", the valid type is "string".`);
822
+ }
823
+ if (typeof path === "object") {
824
+ return await this._col.exists({ ...path, _uid: uid });
825
+ }
826
+ else {
827
+ return await this._col.exists({ _path: path, _uid: uid });
828
+ }
829
+ }
830
+ /* @docs:
831
+ * @title: Load
832
+ * @description: Load data by user id and path.
833
+ * @return:
834
+ * Returns the loaded document.
835
+ *
836
+ * Returns the `def` parameter when the data does not exist, keep in mind that when parameter `def` is an object it could be a reference to a defined variable.
837
+ * @parameter:
838
+ * @name: uid
839
+ * @cached: Users:uid:param
840
+ * @parameter:
841
+ * @name: path
842
+ * @description: The database path to the document.
843
+ * @type: string, object
844
+ * @parameter:
845
+ * @name: opts
846
+ * @desc: Additional options.
847
+ * @type: null, object
848
+ * @attribute:
849
+ * @name: default
850
+ * @description:
851
+ * The default data to be returned when the data does not exist.
852
+ *
853
+ * When the type of attribute `default` is `object` then the keys that do not exist in the loaded object, but do exist in the default object will be inserted into the loaded object.
854
+ * @type: null, object
855
+ */
856
+ async load(uid, path, opts = null) {
857
+ if (typeof path !== "string" && (typeof path !== "object" || path == null)) {
858
+ throw Error(`Parameter "path" has an invalid type "${typeof path}", the valid type is "string".`);
859
+ }
860
+ if (typeof uid !== "string") {
861
+ throw Error(`Parameter "uid" has an invalid type "${typeof uid}", the valid type is "string".`);
862
+ }
863
+ if (typeof path === "object") {
864
+ return await this._col.load({ ...path, _uid: uid }, opts);
865
+ }
866
+ else {
867
+ return await this._col.load({ _path: path, _uid: uid }, opts);
868
+ }
869
+ }
870
+ /* @docs:
871
+ * @title: Save
872
+ * @description: Save data by user id and path. When the document already exists this function only updates the specified content attributes.
873
+ * @return:
874
+ * Returns the updated document.
875
+ * @parameter:
876
+ * @name: uid
877
+ * @cached: Users:uid:param
878
+ * @parameter:
879
+ * @name: path
880
+ * @description: The database path to the document.
881
+ * @type: string, object
882
+ * @parameter:
883
+ * @name: data
884
+ * @description: The data to save.
885
+ * @type: null, boolean, number, string, array, object
886
+ * @parameter:
887
+ * @name: opts
888
+ * @desc: Additional options.
889
+ * @type: null, object
890
+ * @attribute:
891
+ * @name: chunked
892
+ * @description: Chunk the document into multiple documents, therefore documents larger than 16MB are supported.
893
+ * @warning: Currently this option is only supported for types `object` and `array`.
894
+ * @default: false
895
+ * @type: boolean
896
+ * @attribute:
897
+ * @name: bulk
898
+ * @description: Get a bulk operation object, so several operations can be executed in bulk.
899
+ * @default: false
900
+ * @type: boolean
901
+ * @attribute:
902
+ * @name: set
903
+ * @description: By default the $set attribute is used for the content, with `opts.set` disabled you can create your own instructions. The `content` attribute must reflect this.
904
+ * @warning: This does not work in combination with `opts.chunked`.
905
+ * @default: true
906
+ * @type: boolean
907
+ */
908
+ async save(uid, path, content, opts = null) {
909
+ if (typeof path !== "string" && (typeof path !== "object" || path == null)) {
910
+ throw Error(`Parameter "path" has an invalid type "${typeof path}", the valid type is "string".`);
911
+ }
912
+ if (typeof uid !== "string") {
913
+ throw Error(`Parameter "uid" has an invalid type "${typeof uid}", the valid type is "string".`);
914
+ }
915
+ if (typeof path === "object") {
916
+ return await this._col.save({ ...path, _uid: uid }, content, opts);
917
+ }
918
+ else {
919
+ return await this._col.save({ _path: path, _uid: uid }, content, opts);
920
+ }
921
+ }
922
+ /* @docs:
923
+ * @title: List
924
+ * @description: List all child documents of directory path.
925
+ * @parameter:
926
+ * @name: uid
927
+ * @cached: Users:uid:param
928
+ * @parameter:
929
+ * @name: path
930
+ * @description: The database directory path.
931
+ * @type: string, object
932
+ * @parameter:
933
+ * @name: options
934
+ * @description: List options.
935
+ * @type: object
936
+ * @attribute:
937
+ * @name: process
938
+ * @description: Process the document. By default saved non object data will be stored under `_content`. Processing checks this attribute and uses that content instead when it is detected.
939
+ * @type: boolean
940
+ * @default: true
941
+ * @attribute:
942
+ * @name: projection
943
+ * @description: The data attributes to retrieve, when left undefined all attributes are retrieved.
944
+ * @type: object
945
+ * @default: undefined
946
+ */
947
+ async list(uid, path, options = {}) {
948
+ if (typeof path !== "string" && (typeof path !== "object" || path == null)) {
949
+ throw Error(`Parameter "path" has an invalid type "${typeof path}", the valid type is "string".`);
950
+ }
951
+ if (typeof uid !== "string") {
952
+ throw Error(`Parameter "uid" has an invalid type "${typeof uid}", the valid type is "string".`);
953
+ }
954
+ if (typeof path === "object") {
955
+ return await this._col.list({ ...path, _uid: uid }, options);
956
+ }
957
+ else {
958
+ return await this._col.list({ _path: path, _uid: uid }, options);
959
+ }
960
+ }
961
+ /* @docs:
962
+ * @title: List Query
963
+ * @description: List all documents of the collection based on a query.
964
+ * @parameter:
965
+ * @name: query
966
+ * @desc: The query options.
967
+ * @type: object
968
+ * @parameter:
969
+ * @name: options
970
+ * @description: List options.
971
+ * @type: object
972
+ * @attribute:
973
+ * @name: process
974
+ * @description: Process the document. By default saved non object data will be stored under `_content`. Processing checks this attribute and uses that content instead when it is detected.
975
+ * @type: boolean
976
+ * @default: true
977
+ * @attribute:
978
+ * @name: projection
979
+ * @description: The data attributes to retrieve, when left undefined all attributes are retrieved.
980
+ * @type: object
981
+ * @default: undefined
982
+ */
983
+ async list_query(query = {}, options = {}) {
984
+ return await this._col.list_query(query, options);
985
+ }
986
+ /* @docs:
987
+ * @title: List All
988
+ * @description: List all documents of the collection, optionally per uid.
989
+ * @parameter:
990
+ * @name: uid
991
+ * @cached: Users:uid:param
992
+ * @parameter:
993
+ * @name: options
994
+ * @description: List options.
995
+ * @type: object
996
+ * @attribute:
997
+ * @name: process
998
+ * @description: Process the document. By default saved non object data will be stored under `_content`. Processing checks this attribute and uses that content instead when it is detected.
999
+ * @type: boolean
1000
+ * @default: true
1001
+ * @attribute:
1002
+ * @name: projection
1003
+ * @description: The data attributes to retrieve, when left undefined all attributes are retrieved.
1004
+ * @type: object
1005
+ * @default: undefined
1006
+ */
1007
+ async list_all(uid = null, options = {}) {
1008
+ if (uid == null) {
1009
+ return await this._col.list_all({}, options);
1010
+ }
1011
+ else {
1012
+ return await this._col.list_all({ _uid: uid }, options);
1013
+ }
1014
+ }
1015
+ /* @docs:
1016
+ * @title: Delete
1017
+ * @description: Delete a document of the collection by uid and path.
1018
+ * @parameter:
1019
+ * @name: uid
1020
+ * @cached: Users:uid:param
1021
+ * @parameter:
1022
+ * @name: path
1023
+ * @description: The database path to the document.
1024
+ * @type: string, object
1025
+ * @parameter:
1026
+ * @name: opts
1027
+ * @desc: Additional options.
1028
+ * @type: null, object
1029
+ * @attribute:
1030
+ * @name: chunked
1031
+ * @description: Delete a chunked document.
1032
+ * @default: false
1033
+ * @type: boolean
1034
+ * @attribute:
1035
+ * @name: bulk
1036
+ * @description: Get a bulk operation object, so several operations can be executed in bulk.
1037
+ * @default: false
1038
+ * @type: boolean
1039
+ */
1040
+ async delete(uid, path, opts = null) {
1041
+ if (typeof path !== "string" && (typeof path !== "object" || path == null)) {
1042
+ throw Error(`Parameter "path" has an invalid type "${typeof path}", the valid type is "string".`);
1043
+ }
1044
+ if (typeof uid !== "string") {
1045
+ throw Error(`Parameter "uid" has an invalid type "${typeof uid}", the valid type is "string".`);
1046
+ }
1047
+ if (typeof path === "object") {
1048
+ return await this._col.delete({ ...path, _uid: uid }, opts);
1049
+ }
1050
+ else {
1051
+ return await this._col.delete({ _path: path, _uid: uid }, opts);
1052
+ }
1053
+ }
1054
+ /* @docs:
1055
+ * @title: Delete Query
1056
+ * @description: Delete a document of the collection by query.
1057
+ * @parameter:
1058
+ * @name: query
1059
+ * @description: The query object.
1060
+ * @type: object
1061
+ */
1062
+ async delete_query(query) {
1063
+ if (typeof query !== "object" || query == null || Object.keys(query).length === 0) {
1064
+ throw Error(`Parameter "query" has an invalid type "${typeof query}", the valid type is "object".`);
1065
+ }
1066
+ if (Object.keys(query).length === 0) {
1067
+ throw Error(`Parameter "query" is an empty object.`);
1068
+ }
1069
+ return await this._col.delete_query(query);
1070
+ }
1071
+ // Delete all.
1072
+ async delete_all(uid, path = null) {
1073
+ if (typeof uid !== "string") {
1074
+ throw Error(`Parameter "uid" has an invalid type "${typeof uid}", the valid type is "string".`);
1075
+ }
1076
+ if (path == null) {
1077
+ return await this._col.delete_all({ _uid: uid });
1078
+ }
1079
+ else if (typeof path === "object") {
1080
+ return await this._col.delete_all({ ...path, _uid: uid });
1081
+ }
1082
+ else {
1083
+ return await this._col.delete_all({ _path: path, _uid: uid });
1084
+ }
1085
+ }
1086
+ /* @docs:
1087
+ * @title: Delete Collection
1088
+ * @description: Delete all documents of from the collection.
1089
+ */
1090
+ async delete_collection() {
1091
+ await this._col.delete_collection();
1092
+ }
1093
+ /* @docs:
1094
+ * @title: Clean document
1095
+ * @description: Clean a document from all default system attributes.
1096
+ */
1097
+ clean(doc) {
1098
+ return this._col.clean(doc);
1099
+ }
1100
+ /** Write bulk operations. */
1101
+ async bulk_operations(operations = []) {
1102
+ return await this.col.bulkWrite(operations, { ordered: true });
1103
+ }
1104
+ }
1105
+ exports.UIDCollection = UIDCollection;
1106
+ // ---------------------------------------------------------
1107
+ // Database.
1108
+ /* @docs:
1109
+ @nav: Backend
1110
+ @chapter: Database
1111
+ @title: Database
1112
+ @desc:
1113
+ The MongoDB database class, accessable under `Server.db`.
1114
+
1115
+ The database class can be utilized in two ways.
1116
+
1117
+ 1. You only provide the `uri` parameter to access an already running mongodb database.
1118
+
1119
+ 2. You provide parameters `config` and `start_args` to start and optionally create the database.
1120
+
1121
+ @warning:
1122
+ Do not forget to enable TLS when using the `config` parameter.
1123
+ @param:
1124
+ @name: uri
1125
+ @desc: The mongodb server uri.
1126
+ @type: string
1127
+ @param:
1128
+ @name: source
1129
+ @desc: The source path of the database directory, by default path `$server_source/.db` will be used.
1130
+ @type: null, string
1131
+ @param:
1132
+ @name: config
1133
+ @desc: The json data for the mongodb config file.
1134
+ @type: null, string
1135
+ @param:
1136
+ @name: start_args
1137
+ @desc: The mongod database start command arguments.
1138
+ @type: null, array[string]
1139
+ @param:
1140
+ @name: client
1141
+ @desc: The MongoClient options.
1142
+ @type: null, object
1143
+ */
1144
+ class Database {
1145
+ static constructor_scheme = {
1146
+ uri: { type: "string", default: null },
1147
+ source: { type: "string", default: null },
1148
+ config: { type: "object", default: {} },
1149
+ start_args: { type: "array", default: [] },
1150
+ client: { type: "object", default: {} },
1151
+ collections: { type: "array", default: [], value_scheme: {
1152
+ type: ["string", "object"],
1153
+ preprocess: (info) => typeof info === "string" ? { name: info } : info,
1154
+ scheme: {
1155
+ name: Collection.constructor_scheme.name,
1156
+ ttl: Collection.constructor_scheme.ttl,
1157
+ indexes: Collection.constructor_scheme.indexes,
1158
+ },
1159
+ } },
1160
+ uid_collections: { type: "array", default: [], value_scheme: {
1161
+ type: ["string", "object"],
1162
+ preprocess: (info) => typeof info === "string" ? { name: info } : info,
1163
+ scheme: {
1164
+ name: Collection.constructor_scheme.name,
1165
+ ttl: Collection.constructor_scheme.ttl,
1166
+ indexes: Collection.constructor_scheme.indexes,
1167
+ },
1168
+ } },
1169
+ preview: { type: "boolean", default: true },
1170
+ preview_ip_whitelist: { type: "array", default: [] },
1171
+ daemon: { type: ["object", "boolean"], default: {} },
1172
+ _server: "object",
1173
+ };
1174
+ uri;
1175
+ preview;
1176
+ preview_ip_whitelist;
1177
+ client_opts;
1178
+ config;
1179
+ source; // Using vlib.Path type
1180
+ start_args;
1181
+ _collections;
1182
+ _uid_collections;
1183
+ server;
1184
+ client;
1185
+ collections;
1186
+ proc;
1187
+ daemon;
1188
+ db;
1189
+ constructor({ uri = null, source = null, config = null, start_args = [], client = null, collections = [], uid_collections = [], preview = true, preview_ip_whitelist = [], daemon = {}, _server, }) {
1190
+ // Checks.
1191
+ if (_server.is_primary && uri == null) {
1192
+ ({ uri, config, start_args, config, client } = _vinc_1.vlib.Scheme.verify({
1193
+ object: arguments[0],
1194
+ check_unknown: true,
1195
+ scheme: Database.constructor_scheme
1196
+ }));
1197
+ }
1198
+ // Arguments.
1199
+ this.uri = uri;
1200
+ this.preview = preview;
1201
+ this.preview_ip_whitelist = preview_ip_whitelist;
1202
+ this.client_opts = client;
1203
+ this.config = config || {};
1204
+ this.source = source != null ? new _vinc_1.vlib.Path(source) : _server.source.join(".db");
1205
+ this.start_args = start_args;
1206
+ this._collections = collections;
1207
+ this._uid_collections = uid_collections;
1208
+ this.server = _server;
1209
+ // Attributes.
1210
+ this.client = null;
1211
+ this.collections = {};
1212
+ // Initialize the service daemon.
1213
+ if (this.server.daemon && daemon !== false) {
1214
+ const log_source = this.server.source.join(".logs");
1215
+ if (!log_source.exists()) {
1216
+ log_source.mkdir_sync();
1217
+ }
1218
+ this.daemon = new _vinc_1.vlib.Daemon({
1219
+ name: this.server.daemon.name + ".mongodb",
1220
+ user: daemon.user || this.server.daemon.user,
1221
+ group: daemon.group || this.server.daemon.group,
1222
+ command: "mongod",
1223
+ cwd: this.server.daemon.cwd,
1224
+ args: ["--config", this.source.join("mongod.json").str(), ...this.start_args],
1225
+ env: daemon.env || this.server.daemon.env,
1226
+ description: daemon.description || `Service daemon for the mongo database of website ${this.server.domain}.`,
1227
+ auto_restart: true,
1228
+ logs: daemon.logs || log_source.join("logs.mongodb").str(),
1229
+ errors: daemon.errors || log_source.join("errors.mongodb").str(),
1230
+ });
1231
+ }
1232
+ }
1233
+ // Database preview.
1234
+ _initialize_db_preview() {
1235
+ /*
1236
+ if (this.preview && this.server.production === false) {
1237
+ this.server.endpoint(
1238
+
1239
+ // Database preview.
1240
+ {
1241
+ method: "GET" ,
1242
+ endpoint: "/volt/db/preview",
1243
+ view: {
1244
+ callback: () => {
1245
+ volt.utils.on_load(async () => {
1246
+
1247
+ // Style theme.
1248
+ const style = {
1249
+ // bg: "#151721",
1250
+ // sub_bg: "#191B28",
1251
+ // tag_bg: "#1C203A",
1252
+ // div_bg: "#282B40",
1253
+ // fg: "#FFFFFF",
1254
+ // sub_fg: "#FFFFFF99",
1255
+ // tag_fg: "#FFFFFF",
1256
+
1257
+ bg: "#F6F8F8",
1258
+ sub_bg: "#FFFFFF",
1259
+ tag_bg: "#F6F8F8",
1260
+ div_bg: "#00000010",
1261
+ fg: "#32334F",
1262
+ sub_fg: "#31344599",
1263
+ tag_fg: "#313445",
1264
+ };
1265
+
1266
+ // List all collections.
1267
+ const collections = (await volt.utils.request({url: "/volt/db/collections"})).collections;
1268
+
1269
+ // Render a list.
1270
+ const prev_lists = [];
1271
+ function RenderList ({
1272
+ title,
1273
+ list,
1274
+ doc = null,
1275
+ add_prev = true,
1276
+ }) {
1277
+ if (add_prev) {
1278
+ prev_lists.append({title, list, doc});
1279
+ }
1280
+
1281
+ // Object view.
1282
+ const obj_view = VStack();
1283
+ const refresh_obj_view = () => {
1284
+ obj_view.inner_html("");
1285
+ let index = 0;
1286
+ obj_view.append(
1287
+ ForEach(list, (key, value) => {
1288
+ ++index;
1289
+ let current_key = key;
1290
+ let value_type = Array.isArray(value) ? "array" : value == null ? "null" : typeof value;
1291
+ if (Array.isArray(value)) {
1292
+ value = JSON.stringify(value, null, 4)
1293
+ }
1294
+
1295
+ // Key input.
1296
+ const key_input = Input("key")
1297
+ .value(key)
1298
+ .font_family("'Menlo', 'Consolas', monospace")
1299
+ .color(style.sub_fg)
1300
+ .font_size(14)
1301
+ .padding(0)
1302
+ .readonly(key === "_path" || key === "_uid" || key === "uid")
1303
+ .on_mouse_over(e => e.color(style.fg))
1304
+ .on_mouse_out(e => e.color(style.sub_fg))
1305
+ .on_render((e) => e.width(e.text_width(key)))
1306
+ .on_input((e) => {
1307
+ if (key != current_key) {
1308
+ list[e.value()] = list[current_key];
1309
+ delete list[current_key];
1310
+ current_key = e.value();
1311
+ }
1312
+ e.width(e.text_width(current_key));
1313
+ });
1314
+
1315
+ // Value input.
1316
+ const value_input = Input("value")
1317
+ .value(value == null ? "null" : value)
1318
+ .font_family("'Menlo', 'Consolas', monospace")
1319
+ .color(style.sub_fg)
1320
+ .display("inline-block")
1321
+ .width("fit-content")
1322
+ .font_size(14)
1323
+ .readonly(key === "_path" || key === "_uid")
1324
+ .stretch(true)
1325
+ .on_mouse_over(e => e.color(style.fg))
1326
+ .on_mouse_out(e => e.color(style.sub_fg))
1327
+ .on_input(() => {
1328
+ clearTimeout(value_input.timeout)
1329
+ value_input.timeout = setTimeout(update_value, 500);
1330
+ })
1331
+
1332
+ // Type select.
1333
+ const type_select = ExtendedSelect({items: ["null", "boolean", "number", "string", "array", "object"]})
1334
+ .center()
1335
+ .margin(0)
1336
+ .max_width(73)
1337
+ .color(style.sub_fg)
1338
+ .font_size(14)
1339
+ .border_radius(10)
1340
+ .background(style.tag_bg)
1341
+ .border_color(style.div_bg)
1342
+ .value(value_type)
1343
+ .container
1344
+ .padding(2.5, 5)
1345
+ .parent();
1346
+
1347
+ // Update the list after edits.
1348
+ const update_value = () => {
1349
+ const type = type_select.value();
1350
+ const value = value_input.value();
1351
+ if (type === "null") {
1352
+ list[current_key] = null;
1353
+ value_input.value(list[current_key].toString());
1354
+ }
1355
+ else if (type === "boolean") {
1356
+ list[current_key] = value == "true" || value == "True" || value == "TRUE" || value == "1";
1357
+ value_input.value(list[current_key].toString());
1358
+ }
1359
+ else if (type === "number") {
1360
+ if (value.indexOf(".") === -1) {
1361
+ list[current_key] = paseInt(value);
1362
+ } else {
1363
+ list[current_key] = paseFloat(value);
1364
+ }
1365
+ if (isNaN(list[key_input.key])) {
1366
+ list[current_key] = 0;
1367
+ }
1368
+ value_input.value(list[current_key].toString());
1369
+ }
1370
+ else if (type === "string") {
1371
+ list[current_key] = value;
1372
+ }
1373
+ else if (type === "object") {
1374
+ list[current_key] = JSON.parse(value);
1375
+ }
1376
+ }
1377
+
1378
+ // Row.
1379
+ const row = HStack(
1380
+ key_input,
1381
+ Text(" : ")
1382
+ .white_space("pre")
1383
+ .font_family("'Menlo', 'Consolas', monospace")
1384
+ .color(style.sub_fg)
1385
+ .font_size(14),
1386
+ value_input,
1387
+ type_select,
1388
+
1389
+ index < Object.keys(list).length ? null : VStack("add")
1390
+ .background(style.tag_bg)
1391
+ .padding(5, 12.5)
1392
+ .border_radius(10)
1393
+ .font_size(13)
1394
+ .color("#3B8553")
1395
+ .margin_left(10)
1396
+ .border(1, style.div_bg)
1397
+ .on_click(() => {
1398
+ list["_new"] = "";
1399
+ refresh_obj_view();
1400
+ }),
1401
+
1402
+ VStack("delete")
1403
+ .background(style.tag_bg)
1404
+ .color("#B2321E")
1405
+ .padding(5, 12.5)
1406
+ .border_radius(10)
1407
+ .font_size(13)
1408
+ .margin_left(10)
1409
+ .border(1, style.div_bg)
1410
+ .on_click(async () => {
1411
+ }),
1412
+ )
1413
+ .center_vertical()
1414
+ .padding(7.5, 0)
1415
+ if (volt.utils.is_obj(value)) {
1416
+ row.on_click(() => RenderList({title: `${title}.${key}`, list: value}));
1417
+ }
1418
+ return [
1419
+ row,
1420
+ Divider().background(style.div_bg),
1421
+ ]
1422
+ })
1423
+ );
1424
+ }
1425
+
1426
+ // Add.
1427
+ preview.inner_html("");
1428
+ preview.append(
1429
+ Scroller(
1430
+ VStack(
1431
+ HStack(
1432
+ Title("Database")
1433
+ .font_family("'Menlo', 'Consolas', monospace")
1434
+ .font_size(12)
1435
+ .color(style.tag_fg)
1436
+ .background(style.tag_bg)
1437
+ .padding(5, 12.5)
1438
+ .border_radius(10)
1439
+ .margin(0, 0, 0, 0)
1440
+ .border(1, style.div_bg)
1441
+ .width("fit-content"),
1442
+
1443
+ Spacer(),
1444
+
1445
+ doc == null ? null : Button("Update")
1446
+ .background(style.tag_bg)
1447
+ .color("#3B8553")
1448
+ .padding(5, 12.5)
1449
+ .margin_right(10)
1450
+ .border_radius(10)
1451
+ .border(1, style.div_bg)
1452
+ .on_click(() => {
1453
+ // --prev_lists.length;
1454
+ // const last = prev_lists[prev_lists.length - 1];
1455
+ // RenderList({...last, add_prev: false})
1456
+ }),
1457
+
1458
+ doc == null ? null : Button("Delete")
1459
+ .background(style.tag_bg)
1460
+ .color("#B2321E")
1461
+ .padding(5, 12.5)
1462
+ .margin_right(10)
1463
+ .border_radius(10)
1464
+ .border(1, style.div_bg)
1465
+ .on_click(async () => {
1466
+ volt.utils.request({
1467
+ method: "DELETE",
1468
+ url: "/volt/db/document",
1469
+ data: doc,
1470
+ })
1471
+ --prev_lists.length;
1472
+ const last = prev_lists[prev_lists.length - 1];
1473
+
1474
+ const __name = doc.uid != null ? `${doc.uid}:${doc.id}` : doc.id
1475
+ const filtered_list = [];
1476
+ last.list.iterate((item) => {
1477
+ if (item.__name !== __name) {
1478
+ filtered_list.append(item);
1479
+ }
1480
+ })
1481
+ last.list = filtered_list;
1482
+ RenderList({...last, add_prev: false})
1483
+ }),
1484
+
1485
+ prev_lists.length == 1 ? null : Button("Prev")
1486
+ .background(style.tag_bg)
1487
+ .color(style.tag_fg)
1488
+ .padding(5, 12.5)
1489
+ .border_radius(10)
1490
+ .border(1, style.div_bg)
1491
+ .on_click(() => {
1492
+ --prev_lists.length;
1493
+ const last = prev_lists[prev_lists.length - 1];
1494
+ RenderList({...last, add_prev: false})
1495
+ }),
1496
+ ),
1497
+
1498
+ Title(title)
1499
+ .font_family("'Menlo', 'Consolas', monospace")
1500
+ .font_size(18)
1501
+ .color(style.fg)
1502
+ .margin(15, 0),
1503
+
1504
+ Divider().background(style.div_bg),
1505
+
1506
+ Array.isArray(list)
1507
+ ? ForEach(list, (item) => {
1508
+ return [
1509
+ VStack(
1510
+ Text(item.__name)
1511
+ .font_family("'Menlo', 'Consolas', monospace")
1512
+ .color(style.sub_fg)
1513
+ .font_size(14)
1514
+ .on_mouse_over(e => e.color(style.fg))
1515
+ .on_mouse_out(e => e.color(style.sub_fg))
1516
+ )
1517
+ .padding(7.5, 0)
1518
+ .on_click(item.__click),
1519
+
1520
+ Divider().background(style.div_bg),
1521
+ ]
1522
+ })
1523
+ : () => {refresh_obj_view(); return obj_view}
1524
+ )
1525
+ .margin(25, 50)
1526
+ .padding(25, 25)
1527
+ .background(style.sub_bg)
1528
+ .border_radius(10)
1529
+ .box_shadow("0px 0px 5px #00000090")
1530
+ )
1531
+ .font_family("Helvetica, sans-serif")
1532
+ .background(style.bg)
1533
+ .frame("100%", "100%")
1534
+ )
1535
+ }
1536
+
1537
+ // Render the collections.
1538
+ const RenderCollections = () => {
1539
+ RenderList({title: "/", list: collections.iterate_append((item) => {
1540
+ return {
1541
+ __name: `${item}/`,
1542
+ __click: () => RenderCollection(item),
1543
+ }
1544
+ })})
1545
+ }
1546
+
1547
+ // Render a collection.
1548
+ const RenderCollection = async (collection) => {
1549
+ const documents = (await volt.utils.request({url: "/volt/db/documents", data: {collection}})).documents;
1550
+ RenderList({title: `${collection}/`, list: documents.iterate_append((item) => {
1551
+ return {
1552
+ __name: item._uid != null ? `${item._uid}:${item._path}` : item._path,
1553
+ __click: () => RenderDocument(collection, item._path, item._uid),
1554
+ }
1555
+ })})
1556
+ }
1557
+
1558
+ // Render a document.
1559
+ const RenderDocument = async (collection, path, uid = null) => {
1560
+ let doc = (await volt.utils.request({url: "/volt/db/document", data: {collection, path, uid}})).document
1561
+ if (Array.isArray(doc)) {
1562
+ doc = {_content: doc};
1563
+ }
1564
+ RenderList({
1565
+ title: uid != null ? `${collection}/${uid}:${path}` : `${collection}/${path}`,
1566
+ list: doc,
1567
+ doc: {collection, uid, path},
1568
+ })
1569
+ }
1570
+
1571
+ // Stack.
1572
+ const preview = VStack()
1573
+ .position(0, 0, 0, 0);
1574
+
1575
+ // Render all collections.
1576
+ RenderCollections();
1577
+
1578
+ // Response.
1579
+ return preview;
1580
+
1581
+ });
1582
+ }
1583
+ }
1584
+ },
1585
+
1586
+ // Get collections.
1587
+ {
1588
+ method: "GET",
1589
+ endpoint: "/volt/db/collections",
1590
+ content_type: "application/json",
1591
+ rate_limit: "global",
1592
+ callback: async (stream) => {
1593
+
1594
+ // Check ip whitelist.
1595
+ if (!this.preview_ip_whitelist.includes(stream.ip)) {
1596
+ return stream.error({status: Status.forbidden});
1597
+ }
1598
+
1599
+ // Sign in.
1600
+ return stream.success({data: {
1601
+ message: "Successfully retrieved all collections.",
1602
+ collections: await this.get_collections(),
1603
+ }});
1604
+ }
1605
+ },
1606
+
1607
+ // Get collection documents.
1608
+ {
1609
+ method: "GET",
1610
+ endpoint: "/volt/db/documents",
1611
+ content_type: "application/json",
1612
+ rate_limit: "global",
1613
+ params: {
1614
+ collection: "string",
1615
+ },
1616
+ callback: async (stream, params) => {
1617
+
1618
+ // Check ip whitelist.
1619
+ if (!this.preview_ip_whitelist.includes(stream.ip)) {
1620
+ return stream.error({status: Status.forbidden});
1621
+ }
1622
+
1623
+ // Check collection.
1624
+ let col;
1625
+ if ((col = this.collections[params.collection]) == null) {
1626
+ return stream.error({data: {error: `Invalid collection "${params.collection}".`}})
1627
+ }
1628
+
1629
+ // Load docs.
1630
+ let docs = await col.list_all();
1631
+
1632
+ // Sign in.
1633
+ return stream.success({data: {
1634
+ message: "Successfully loaded the document.",
1635
+ documents: docs,
1636
+ }});
1637
+ }
1638
+ },
1639
+
1640
+ // Get document.
1641
+ {
1642
+ method: "GET",
1643
+ endpoint: "/volt/db/document",
1644
+ content_type: "application/json",
1645
+ rate_limit: "global",
1646
+ params: {
1647
+ collection: "string",
1648
+ path: ["string", "object"],
1649
+ uid: {type: ["string", "null"], default: null},
1650
+ },
1651
+ callback: async (stream, params) => {
1652
+
1653
+ // Check ip whitelist.
1654
+ if (!this.preview_ip_whitelist.includes(stream.ip)) {
1655
+ return stream.error({status: Status.forbidden});
1656
+ }
1657
+
1658
+ // Check collection.
1659
+ let col;
1660
+ if ((col = this.collections[params.collection]) == null) {
1661
+ return stream.error({data: {error: `Invalid collection "${params.collection}".`}})
1662
+ }
1663
+
1664
+ // Load doc.
1665
+ let doc;
1666
+ if (params.uid == null) {
1667
+ doc = await col.load(params.path);
1668
+ } else {
1669
+ doc = await col.load(params.uid, params.path);
1670
+ }
1671
+
1672
+ // Sign in.
1673
+ return stream.success({data: {
1674
+ message: "Successfully loaded the document.",
1675
+ document: doc,
1676
+ }});
1677
+ }
1678
+ },
1679
+
1680
+ // Delete document.
1681
+ {
1682
+ method: "DELETE",
1683
+ endpoint: "/volt/db/document",
1684
+ content_type: "application/json",
1685
+ rate_limit: "global",
1686
+ params: {
1687
+ collection: "string",
1688
+ path: ["string", "object"],
1689
+ uid: {type: ["string", "null"], default: null},
1690
+ },
1691
+ callback: async (stream, params) => {
1692
+
1693
+ // Check ip whitelist.
1694
+ if (!this.preview_ip_whitelist.includes(stream.ip)) {
1695
+ return stream.error({status: Status.forbidden});
1696
+ }
1697
+
1698
+ // Check collection.
1699
+ let col;
1700
+ if ((col = this.collections[params.collection]) == null) {
1701
+ return stream.error({data: {error: `Invalid collection "${params.collection}".`}})
1702
+ }
1703
+
1704
+ // Load doc.
1705
+ let doc;
1706
+ if (params.uid == null) {
1707
+ doc = await col.delete(params.path);
1708
+ } else {
1709
+ doc = await col.delete(params.uid, params.path);
1710
+ }
1711
+
1712
+ // Sign in.
1713
+ return stream.success({data: {
1714
+ message: "Successfully deleted the document.",
1715
+ }});
1716
+ }
1717
+ },
1718
+
1719
+ // Update document.
1720
+ {
1721
+ method: "PATCH",
1722
+ endpoint: "/volt/db/document",
1723
+ content_type: "application/json",
1724
+ rate_limit: "global",
1725
+ params: {
1726
+ collection: "string",
1727
+ path: ["string", "object"],
1728
+ uid: {type: ["string", "null"], default: null},
1729
+ content: "object",
1730
+ },
1731
+ callback: async (stream, params) => {
1732
+
1733
+ // Check ip whitelist.
1734
+ if (!this.preview_ip_whitelist.includes(stream.ip)) {
1735
+ return stream.error({status: Status.forbidden});
1736
+ }
1737
+
1738
+ // Check collection.
1739
+ let col;
1740
+ if ((col = this.collections[params.collection]) == null) {
1741
+ return stream.error({data: {error: `Invalid collection "${params.collection}".`}})
1742
+ }
1743
+
1744
+ // Load doc.
1745
+ let doc;
1746
+ if (params.uid == null) {
1747
+ doc = await col.save(params.path, params.content);
1748
+ } else {
1749
+ doc = await col.save(params.uid, params.path, params.content);
1750
+ }
1751
+
1752
+ // Sign in.
1753
+ return stream.success({data: {
1754
+ message: "Successfully updated the document.",
1755
+ }});
1756
+ }
1757
+ },
1758
+ )
1759
+ }
1760
+ */
1761
+ }
1762
+ // Connect.
1763
+ async connect() {
1764
+ try {
1765
+ await this.client?.connect();
1766
+ if (this.client) {
1767
+ this.db = this.client.db();
1768
+ }
1769
+ }
1770
+ catch (error) {
1771
+ console.error(error);
1772
+ throw new Error('Error connecting to the database');
1773
+ }
1774
+ }
1775
+ // Initialize.
1776
+ async initialize() {
1777
+ // Set default config.
1778
+ if (this.config.systemLog === undefined) {
1779
+ this.config.systemLog = {};
1780
+ }
1781
+ this.config.systemLog.path = this.source.join("mongod.log").str();
1782
+ if (this.config.systemLog.destination === undefined) {
1783
+ this.config.systemLog.destination = "file";
1784
+ }
1785
+ if (this.config.systemLog.logAppend === undefined) {
1786
+ this.config.systemLog.logAppend = true;
1787
+ }
1788
+ if (this.config.systemLog.logRotate === undefined) {
1789
+ this.config.systemLog.logRotate = "reopen";
1790
+ }
1791
+ if (this.config.systemLog.verbosity === undefined) {
1792
+ this.config.systemLog.verbosity = this.server.production ? 0 : 1;
1793
+ }
1794
+ if (this.config.storage === undefined) {
1795
+ this.config.storage = {};
1796
+ }
1797
+ const db_path = this.source.join("db");
1798
+ this.config.storage.dbPath = db_path.str();
1799
+ if (!db_path.exists()) {
1800
+ db_path.mkdir_sync();
1801
+ }
1802
+ if (this.config.processManagement === undefined) {
1803
+ this.config.processManagement = {};
1804
+ }
1805
+ this.config.processManagement.pidFilePath = this.source.join("mongod.pid").str();
1806
+ if (this.config.net === undefined) {
1807
+ this.config.net = {};
1808
+ }
1809
+ if (this.config.net.port === undefined) {
1810
+ this.config.net.port = 27017;
1811
+ }
1812
+ if (this.config.net.bindIp === undefined) {
1813
+ this.config.net.bindIp = "127.0.0.1";
1814
+ }
1815
+ // Mode 2: Start database.
1816
+ if (this.server.is_primary && this.uri == null) {
1817
+ // Create the database.
1818
+ if (!this.source.exists()) {
1819
+ this.source.mkdir_sync();
1820
+ }
1821
+ // Set the uri.
1822
+ if (this.uri == null) {
1823
+ this.uri = `mongodb://${this.config.net.bindIp}:${this.config.net.port}/main`;
1824
+ }
1825
+ // Save the config.
1826
+ const config_path = this.source.join("mongod.json");
1827
+ config_path.save_sync(JSON.stringify(this.config));
1828
+ // Start the database.
1829
+ this.proc = (0, child_process_1.spawn)("mongod", ["--config", config_path.str(), ...this.start_args], {
1830
+ stdio: "pipe",
1831
+ detached: true,
1832
+ env: { ...process.env },
1833
+ });
1834
+ this.proc.stdout?.on('data', (data) => {
1835
+ console.log(data.toString());
1836
+ });
1837
+ this.proc.stderr?.on('data', (data) => {
1838
+ console.error(data.toString());
1839
+ });
1840
+ this.proc.on("error", (code, signal) => {
1841
+ console.error(`MongoDB crashed with error signal ${signal}.`);
1842
+ process.exit(code);
1843
+ });
1844
+ }
1845
+ // Assign URI.
1846
+ else if (!this.server.is_primary && this.uri == null) {
1847
+ this.uri = `mongodb://${this.config.net.bindIp}:${this.config.net.port}/main`;
1848
+ }
1849
+ // Initialize client.
1850
+ if (this.uri) {
1851
+ this.client = new mongodb_1.MongoClient(this.uri, this.client_opts || {});
1852
+ }
1853
+ // Connect.
1854
+ await this.connect();
1855
+ // Create collections.
1856
+ this._collections.forEach((info) => {
1857
+ if (this[info.name] !== undefined) {
1858
+ throw Error(`Unable to initialize database collection "${info.name}", this attribute name is already used.`);
1859
+ }
1860
+ if (Array.isArray(info.indexes)) {
1861
+ for (const index of info.indexes) {
1862
+ if (index != null && typeof index === "object") {
1863
+ index.forced = true;
1864
+ }
1865
+ }
1866
+ }
1867
+ this[info.name] = this.create_collection(info);
1868
+ });
1869
+ this._uid_collections.forEach((info) => {
1870
+ if (this[info.name] !== undefined) {
1871
+ throw Error(`Unable to initialize database collection "${info.name}", this attribute name is already used.`);
1872
+ }
1873
+ if (Array.isArray(info.indexes)) {
1874
+ for (const index of info.indexes) {
1875
+ if (index != null && typeof index === "object") {
1876
+ index.forced = true;
1877
+ }
1878
+ }
1879
+ }
1880
+ this[info.name] = this.create_uid_collection(info);
1881
+ });
1882
+ }
1883
+ // Close.
1884
+ async close() {
1885
+ logger_js_1.logger.log(0, log_source, "Stopping the database.");
1886
+ await this.client?.close();
1887
+ }
1888
+ /* @docs:
1889
+ * @title: Create Collection
1890
+ * @description: Create a database collection.
1891
+ */
1892
+ create_collection(info) {
1893
+ // Set name by single string argument.
1894
+ let name;
1895
+ let indexes = [];
1896
+ let ttl = null;
1897
+ if (typeof info === "string") {
1898
+ name = info;
1899
+ }
1900
+ else {
1901
+ name = info.name;
1902
+ indexes = info.indexes || [];
1903
+ ttl = info.ttl || null;
1904
+ }
1905
+ // Check collection.
1906
+ if (name in this.collections) {
1907
+ throw Error(`Collection "${name}" is already initialized.`);
1908
+ }
1909
+ const col = new Collection(name, this.db.collection(name), ttl, indexes);
1910
+ this.collections[name] = col;
1911
+ return col;
1912
+ }
1913
+ /* @docs:
1914
+ * @title: Create UID Based Collection
1915
+ * @description: Create a UID based database collection.
1916
+ */
1917
+ create_uid_collection(info) {
1918
+ // Set name by single string argument.
1919
+ let name;
1920
+ let indexes = [];
1921
+ let ttl = null;
1922
+ if (typeof info === "string") {
1923
+ name = info;
1924
+ }
1925
+ else {
1926
+ name = info.name;
1927
+ indexes = info.indexes || [];
1928
+ ttl = info.ttl || null;
1929
+ }
1930
+ // Check collection.
1931
+ if (name in this.collections) {
1932
+ throw Error(`Collection "${name}" is already initialized.`);
1933
+ }
1934
+ const col = new UIDCollection(name, this.db.collection(name), indexes, ttl);
1935
+ this.collections[name] = col;
1936
+ return col;
1937
+ }
1938
+ /* @docs:
1939
+ * @title: Get Collections
1940
+ * @description: Get the names of the initializated database collections.
1941
+ */
1942
+ async get_collections() {
1943
+ const created = Object.keys(this.collections);
1944
+ const database = (await this.db.listCollections().toArray()).map((item) => item.name);
1945
+ return created.concat(database)
1946
+ .filter((value, index, self) => self.indexOf(value) === index)
1947
+ .sort((a, b) => {
1948
+ const result = a.toLowerCase().localeCompare(b.toLowerCase());
1949
+ if (a.startsWith('_') && b.startsWith('_')) {
1950
+ return result;
1951
+ }
1952
+ if (a.startsWith('_')) {
1953
+ return 1;
1954
+ }
1955
+ if (b.startsWith('_')) {
1956
+ return -1;
1957
+ }
1958
+ return result;
1959
+ });
1960
+ }
1961
+ }
1962
+ exports.Database = Database;