@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
@@ -1,2423 +0,0 @@
1
- /*
2
- * Author: Daan van den Bergh
3
- * Copyright: © 2022 - 2024 Daan van den Bergh.
4
- */
5
- // ---------------------------------------------------------
6
- // Libraries.
7
- import { spawn } from "child_process";
8
- import { deserialize, serialize } from "bson";
9
- import { MongoClient, ServerApiVersion } from 'mongodb';
10
- import { logger } from "./logger.js";
11
- import { Status } from "./status.js";
12
- import { vlib } from "./vinc.js";
13
- import { ExternalError, InternalError } from "./utils.js";
14
- const { log, debug } = logger.loggers();
15
- // ---------------------------------------------------------
16
- // Collection.
17
- // Path based collection, so "myfile", "mydir/myfile".
18
- // @warning: The "path" param must always be allowed to be an object or string, also for the UIDCollection class.
19
- // @warning: THE DATABASE COLLECTION SHOULD ALSO ACCEPT OBJECTS FOR PATHS.
20
- /* @docs:
21
- @nav: Backend
22
- @chapter: Database
23
- @title: Collection
24
- @desc: The database collection class.
25
- @note: The document attribute `_path` is a reserved index attribute for the path of the document.
26
- @attribute:
27
- @name: col
28
- @desc: The native mongodb collection.
29
- */
30
- export class Collection {
31
- // Static attributes.
32
- static chunk_size = 1024 * 1024 * 4; // 4MB chunks, lower is better for frequent updates.
33
- static constructor_scheme = {
34
- name: "string",
35
- uid_based: "boolean",
36
- ttl: { type: "number", default: null }, // ttl in msec
37
- indexes: {
38
- type: "array",
39
- default: [],
40
- value_scheme: {
41
- type: ["string", "object"],
42
- scheme: {
43
- key: { type: "string", required: (data) => data.key == null && data.keys == null },
44
- keys: {
45
- type: ["array"],
46
- required: (data) => data.key == null && data.keys == null, value_scheme: "string",
47
- postprocess: (keys) => typeof keys === "string" ? [keys] : keys,
48
- },
49
- options: { type: "object", required: false },
50
- commit_quorom: { type: "object", required: false },
51
- forced: { type: "boolean", default: false },
52
- },
53
- postprocess: (info) => {
54
- if (typeof info === "string")
55
- return { keys: [info] };
56
- return info;
57
- },
58
- },
59
- },
60
- };
61
- // Instance attributes
62
- col;
63
- name;
64
- uid_based;
65
- ttl; // ttl in msec
66
- ttl_enabled;
67
- constructor(name, collection, ttl = null, // ttl in msec
68
- indexes = [], uid_based = false) {
69
- // Verify scheme.
70
- ({ indexes, ttl } = vlib.Scheme.verify({
71
- object: {
72
- name,
73
- indexes,
74
- ttl,
75
- uid_based,
76
- },
77
- check_unknown: true,
78
- scheme: Collection.constructor_scheme,
79
- }));
80
- // Attributes.
81
- this.name = name;
82
- this.col = collection;
83
- this.uid_based = uid_based;
84
- this.ttl = ttl;
85
- this.ttl_enabled = typeof ttl === "number";
86
- // Create default indexes.
87
- if (uid_based) {
88
- this.col.createIndex({ _path: 1, _uid: 1 });
89
- }
90
- else {
91
- this.col.createIndex({ _path: 1 });
92
- }
93
- // Create ttl index.
94
- if (this.ttl_enabled) {
95
- this.col.dropIndex("_ttl_timestamp_1")
96
- .catch(err => {
97
- if (err.codeName !== 'IndexNotFound' && err.codeName !== 'NamespaceNotFound') {
98
- err.stack = new Error(err.message).stack;
99
- throw err;
100
- }
101
- })
102
- .then(() => {
103
- this.col.createIndex({ _ttl_timestamp: 1 }, { expireAfterSeconds: parseInt(String(this.ttl / 1000)) });
104
- });
105
- }
106
- // Create indexes.
107
- if (Array.isArray(indexes) && indexes.length > 0) {
108
- for (let item of indexes) {
109
- this.create_index(item);
110
- }
111
- }
112
- }
113
- // Handle file response.
114
- _process_doc(doc) {
115
- if (doc == null) {
116
- return null;
117
- }
118
- else if (doc._content != null) {
119
- return doc._content;
120
- }
121
- return doc;
122
- }
123
- // Chunked methods.
124
- async _load_chunked(path, find_opts) {
125
- let query = typeof path === "string" ?
126
- { _path: path, chunk: { $gte: 0 } } :
127
- { ...path, chunk: { $gte: 0 } };
128
- const chunks_cursor = this.col.find(query, find_opts).sort({ chunk: 1 });
129
- const chunks = await chunks_cursor.toArray();
130
- if (chunks.length === 0) {
131
- return null;
132
- }
133
- const buffer = Buffer.concat(chunks.map(chunk => chunk.data.buffer));
134
- return deserialize(buffer);
135
- }
136
- async _save_chunked(path, content) {
137
- // Serialize.
138
- const buffer = serialize(content);
139
- const new_chunk_count = Math.ceil(buffer.length / Collection.chunk_size);
140
- // Retrieve the old chunk count
141
- const ref_query = typeof path === "string" ?
142
- { _path: path, chunk: -1 } :
143
- { ...path, chunk: -1 };
144
- const object_ref = await this.col.findOne(ref_query);
145
- const old_chunk_count = object_ref ? object_ref.chunks : 0;
146
- // Update chunks.
147
- const bulk_ops = [];
148
- for (let i = 0; i < buffer.length; i += Collection.chunk_size) {
149
- let query, update;
150
- if (typeof path === "string") {
151
- query = {
152
- _path: path,
153
- chunk: i / Collection.chunk_size,
154
- };
155
- update = {
156
- chunk: i / Collection.chunk_size,
157
- data: buffer.slice(i, i + Collection.chunk_size)
158
- };
159
- }
160
- else {
161
- query = {
162
- ...path,
163
- chunk: i / Collection.chunk_size,
164
- };
165
- update = {
166
- chunk: i / Collection.chunk_size,
167
- data: buffer.slice(i, i + Collection.chunk_size)
168
- };
169
- }
170
- const full_update = {
171
- $set: update,
172
- };
173
- if (this.ttl_enabled) {
174
- full_update["$setOnInsert"] = { _ttl_timestamp: new Date() };
175
- }
176
- bulk_ops.push({
177
- updateOne: {
178
- filter: query,
179
- update: full_update,
180
- upsert: true
181
- }
182
- });
183
- }
184
- // Update reference.
185
- const full_update = {
186
- $set: {
187
- chunk: -1,
188
- chunks: new_chunk_count,
189
- },
190
- };
191
- if (this.ttl_enabled) {
192
- full_update["$setOnInsert"] = { _ttl_timestamp: new Date() };
193
- }
194
- bulk_ops.push({
195
- updateOne: {
196
- filter: ref_query,
197
- update: full_update,
198
- upsert: true
199
- }
200
- });
201
- // Write.
202
- await this.col.bulkWrite(bulk_ops, { ordered: true });
203
- // Delete any excess chunks if the new chunk count is less than the old chunk count
204
- if (new_chunk_count < old_chunk_count) {
205
- ref_query.chunk = { $gte: new_chunk_count };
206
- await this.col.deleteMany(ref_query);
207
- }
208
- }
209
- /* @docs:
210
- @title: Create index
211
- @description: Creates indexes on collections.
212
- @return:
213
- Returns the document that was found or `null` when no document is found.
214
- @parameter:
215
- @name: keys
216
- @desc: The `keys` argument for the orignal mongodb `createIndex()` function.
217
- @parameter:
218
- @name: options
219
- @desc: The `options` argument for the orignal mongodb `createIndex()` function.
220
- @parameter:
221
- @name: commitQuorum
222
- @desc: The `commitQuorum` argument for the orignal mongodb `createIndex()` function.
223
- */
224
- async create_index({ key = undefined, keys = undefined, // following the IndexOptions "key" or "keys" must be defined in typescript but not in raw js.
225
- options = undefined, commit_quorum = undefined, forced = false }) {
226
- // Create keys objs per input type.
227
- let keys_obj = {};
228
- if (key) {
229
- keys_obj = {};
230
- keys_obj[key] = 1;
231
- }
232
- else if (Array.isArray(keys) && keys.length > 0) {
233
- keys_obj = {};
234
- for (const key of keys) {
235
- keys_obj[key] = 1;
236
- }
237
- }
238
- else {
239
- throw new Error("Define one of the following parameters: [key, keys].");
240
- }
241
- // Drop index.
242
- if (forced) {
243
- try {
244
- await this.col.dropIndex(options?.name ??
245
- Object.entries(keys_obj)
246
- .map(([key, value]) => `${key}_${value}`)
247
- .join('_'));
248
- }
249
- catch (err) {
250
- if (err.codeName !== 'IndexNotFound') {
251
- throw err;
252
- }
253
- }
254
- }
255
- // Create index.
256
- // @ts-ignore
257
- return await this.col.createIndex(keys_obj, options || {}, commit_quorum);
258
- }
259
- /* @docs:
260
- * @title: Find
261
- * @description: Find a document by a query.
262
- * @return:
263
- * Returns the document that was found or `null` when no document is found.
264
- * @parameter:
265
- * @name: query
266
- * @desc: The query options.
267
- * @type: object
268
- */
269
- async find(query) {
270
- try {
271
- return this._process_doc(await this.col.findOne(query));
272
- }
273
- catch (error) {
274
- console.error(error);
275
- throw new Error('Encountered an error while finding the document.');
276
- }
277
- }
278
- /* @docs:
279
- * @title: Exists
280
- * @description: Check if a document exists.
281
- * @parameter:
282
- * @name: path
283
- * @description: The database path to the document.
284
- * @type: string
285
- */
286
- async exists(path) {
287
- if (typeof path !== "string" && (typeof path !== "object" || path == null)) {
288
- throw Error(`Parameter "path" has an invalid type "${typeof path}", the valid type is "string".`);
289
- }
290
- try {
291
- const doc = await this.col.findOne(typeof path === "object" ? path : { _path: path }, { projection: { _id: 1 } });
292
- return doc != null;
293
- }
294
- catch (error) {
295
- console.error(error);
296
- throw new Error('Encountered an error while checking if the document exists.');
297
- }
298
- }
299
- /* @docs:
300
- * @title: Load
301
- * @description: Load data by path.
302
- * @return:
303
- * Returns the loaded document.
304
- *
305
- * 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.
306
- * @parameter:
307
- * @name: path
308
- * @description: The database path to the document.
309
- * @type: string
310
- * @parameter:
311
- * @name: opts
312
- * @desc: Additional options.
313
- * @type: null, object
314
- * @attribute:
315
- * @name: default
316
- * @description:
317
- * The default data to be returned when the data does not exist.
318
- *
319
- * 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.
320
- * @type: null, object
321
- * @attribute:
322
- * @name: chunked
323
- * @description: Load a chunked document.
324
- * @type: null, object
325
- * @attribute:
326
- * @name: attributes
327
- * @description: The attributes to load.
328
- * @type: null, string[]
329
- */
330
- async load(path, opts = null) {
331
- if (typeof path !== "string" && (typeof path !== "object" || path == null)) {
332
- throw Error(`Parameter "path" has an invalid type "${typeof path}", the valid type is "string".`);
333
- }
334
- if (opts && opts.projection && opts.chunked) {
335
- throw new Error("The `projection` and `chunked` options cannot be used together.");
336
- }
337
- try {
338
- // Get attributes.
339
- let find_opts;
340
- if (opts) {
341
- if (opts.projection) {
342
- find_opts = { projection: opts.projection };
343
- }
344
- else if (opts.attributes) {
345
- find_opts = { projection: {
346
- _id: 1,
347
- _path: 1,
348
- _uid: 1,
349
- } };
350
- opts.attributes.forEach((i) => {
351
- if (find_opts?.projection) {
352
- find_opts.projection[i] = 1;
353
- }
354
- });
355
- }
356
- }
357
- // Load doc.
358
- let doc;
359
- if (opts != null && opts.chunked === true) {
360
- doc = await this._load_chunked(path, find_opts);
361
- }
362
- else {
363
- // Load.
364
- doc = await this.col.findOne(typeof path === "object" ? path : { _path: path }, find_opts);
365
- this.clean(doc);
366
- }
367
- // Process doc.
368
- doc = this._process_doc(doc);
369
- // Handle default.
370
- if (doc == null) {
371
- if (opts != null && opts.default !== undefined) {
372
- return opts.default;
373
- }
374
- return null;
375
- }
376
- // Insert default keys.
377
- else if (opts != null && typeof opts.default === "object" && opts.default != null && Array.isArray(opts.default) === false) {
378
- const set_defaults = (obj, defaults) => {
379
- Object.keys(defaults).forEach((key) => {
380
- if (obj[key] === undefined) {
381
- obj[key] = defaults[key];
382
- }
383
- else if (typeof obj[key] === "object" && !Array.isArray(obj[key]) && obj[key] != null &&
384
- typeof defaults[key] === "object" && !Array.isArray(defaults[key]) && defaults[key] != null) {
385
- set_defaults(obj[key], defaults[key]);
386
- }
387
- });
388
- };
389
- set_defaults(doc, opts.default);
390
- }
391
- // Response.
392
- return doc;
393
- }
394
- catch (error) {
395
- console.error(error);
396
- throw new Error('Encountered an error while loading the document.');
397
- }
398
- }
399
- /* @docs:
400
- * @title: Save
401
- * @description: Save data by path. When the document already exists this function only updates the specified content attributes.
402
- * @return:
403
- * Returns the updated document.
404
- * @parameter:
405
- * @name: path
406
- * @description: The database path to the document.
407
- * @type: string
408
- * @parameter:
409
- * @name: data
410
- * @description: The data to save.
411
- * @type: null, boolean, number, string, array, object
412
- * @parameter:
413
- * @name: opts
414
- * @desc: Additional options.
415
- * @type: null, object
416
- * @attribute:
417
- * @name: chunked
418
- * @description: Chunk the document into multiple documents, therefore documents larger than 16MB are supported.
419
- * @warning: Currently this option is only supported for types `object` and `array`.
420
- * @default: false
421
- * @type: boolean
422
- * @attribute:
423
- * @name: bulk
424
- * @description: Get a bulk operation object, so several operations can be executed in bulk.
425
- * @default: false
426
- * @type: boolean
427
- * @attribute:
428
- * @name: set
429
- * @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.
430
- * @warning: This does not work in combination with `opts.chunked`.
431
- * @default: true
432
- * @type: boolean
433
- */
434
- async save(path, content, opts = null) {
435
- if (typeof path !== "string" && (typeof path !== "object" || path == null)) {
436
- throw Error(`Parameter "path" has an invalid type "${typeof path}", the valid type is "string".`);
437
- }
438
- try {
439
- // Vars.
440
- let doc, set;
441
- // Create set.
442
- if (typeof content === "object" && Array.isArray(content) == false && content != null) {
443
- delete content._id;
444
- delete content._path;
445
- delete content._uid;
446
- delete content._ttl_timestamp;
447
- set = content;
448
- }
449
- else {
450
- set = { _content: content };
451
- }
452
- // Save chunked.
453
- if (opts != null && opts.chunked === true) {
454
- await this._save_chunked(path, set);
455
- }
456
- // Save as single doc.
457
- else {
458
- // Apply $set rules.
459
- if (opts == null || (opts.set !== false)) {
460
- set = { $set: set };
461
- }
462
- // Apply TTL.
463
- if (this.ttl_enabled) {
464
- if (set["$setOnInsert"] === undefined) {
465
- set["$setOnInsert"] = {};
466
- set["$setOnInsert"]._ttl_timestamp = new Date();
467
- }
468
- else if (set["$setOnInsert"] != null && typeof set["$setOnInsert"] === "object") {
469
- set["$setOnInsert"]._ttl_timestamp = new Date();
470
- }
471
- else {
472
- throw new Error(`Undefined behaviour: Unable to assign the $setOnInsert data for ttl control.`);
473
- }
474
- }
475
- // Bulk operation.
476
- if (opts != null && opts.bulk) {
477
- return {
478
- updateOne: {
479
- filter: typeof path === "object" ? path : { _path: path },
480
- update: set,
481
- upsert: true,
482
- }
483
- };
484
- }
485
- // Normal operation.
486
- else {
487
- await this.col.updateOne(typeof path === "object" ? path : { _path: path }, set, { upsert: true });
488
- }
489
- }
490
- // Response.
491
- return content;
492
- }
493
- catch (error) {
494
- console.error(error);
495
- throw new Error('Encountered an error while updating the document.');
496
- }
497
- }
498
- /** Update many. */
499
- async update_many(...args) {
500
- return this.col.updateMany(...args);
501
- }
502
- // List.
503
- /* @docs:
504
- * @title: List
505
- * @description: List all child documents of directory path.
506
- * @parameter:
507
- * @name: path
508
- * @description: The database directory path.
509
- * @type: string
510
- * @parameter:
511
- * @name: options
512
- * @description: List options.
513
- * @type: object
514
- * @attribute:
515
- * @name: process
516
- * @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.
517
- * @type: boolean
518
- * @default: true
519
- * @attribute:
520
- * @name: projection
521
- * @description: The data attributes to retrieve, when left undefined all attributes are retrieved.
522
- * @type: object
523
- * @default: undefined
524
- */
525
- async list(path, options = {}) {
526
- if (typeof path !== "string" && (typeof path !== "object" || path == null)) {
527
- throw Error(`Parameter "path" has an invalid type "${typeof path}", the valid type is "string".`);
528
- }
529
- if (typeof path === "string") {
530
- while (path.length > 0 && path.charAt(path.length - 1) === "/") {
531
- path = path.substr(0, path.length - 1);
532
- }
533
- if (path.length == 0) {
534
- throw Error("Invalid path.");
535
- }
536
- path = { _path: { $regex: `^${path}/` } };
537
- }
538
- else if (path._path) {
539
- let _path = path._path;
540
- while (_path.length > 0 && _path.charAt(_path.length - 1) === "/") {
541
- _path = _path.substr(0, _path.length - 1);
542
- }
543
- if (_path.length == 0) {
544
- throw Error("Invalid path.");
545
- }
546
- path._path = { $regex: `^${_path}/` };
547
- }
548
- try {
549
- const docs = await this.col.find(path, { projection: options.projection }).toArray();
550
- if (options.process === false) {
551
- return docs;
552
- }
553
- return docs.map((doc) => this._process_doc(doc));
554
- }
555
- catch (error) {
556
- console.error(error);
557
- throw new Error('Encountered an error while listing all documents.');
558
- }
559
- }
560
- /* @docs:
561
- * @title: List Query
562
- * @description: List all documents of the collection based on a query.
563
- * @parameter:
564
- * @name: query
565
- * @desc: The query options.
566
- * @type: object
567
- * @parameter:
568
- * @name: options
569
- * @description: List options.
570
- * @type: object
571
- * @attribute:
572
- * @name: process
573
- * @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.
574
- * @type: boolean
575
- * @default: true
576
- * @attribute:
577
- * @name: projection
578
- * @description: The data attributes to retrieve, when left undefined all attributes are retrieved.
579
- * @type: object
580
- * @default: undefined
581
- */
582
- async list_query(query = {}, options = {}) {
583
- try {
584
- const docs = await this.col.find(query, { projection: options.projection }).toArray();
585
- if (options.process === false) {
586
- return docs;
587
- }
588
- 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.
589
- }
590
- catch (error) {
591
- console.error(error);
592
- throw new Error('Encountered an error while listing all documents.');
593
- }
594
- }
595
- /* @docs:
596
- * @title: List All
597
- * @description: List all documents of the collection, optionally per uid.
598
- * @parameter:
599
- * @name: query
600
- * @ignore: true
601
- * @parameter:
602
- * @name: options
603
- * @description: List options.
604
- * @type: object
605
- * @attribute:
606
- * @name: process
607
- * @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.
608
- * @type: boolean
609
- * @default: true
610
- * @attribute:
611
- * @name: projection
612
- * @description: The data attributes to retrieve, when left undefined all attributes are retrieved.
613
- * @type: object
614
- * @default: undefined
615
- */
616
- async list_all(query = {}, options = {}) {
617
- let docs;
618
- if (this.uid_based) {
619
- docs = await this.col.find(query, { projection: options.projection }).toArray();
620
- }
621
- else {
622
- docs = await this.col.find(query, { projection: options.projection }).toArray();
623
- }
624
- if (options.process === false) {
625
- return docs;
626
- }
627
- 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.
628
- }
629
- /* @docs:
630
- * @title: Delete
631
- * @description: Delete a document of the collection by path.
632
- * @parameter:
633
- * @name: path
634
- * @description: The database path to the document.
635
- * @type: string
636
- * @parameter:
637
- * @name: opts
638
- * @desc: Additional options.
639
- * @type: null, object
640
- * @attribute:
641
- * @name: chunked
642
- * @description: Delete a chunked document.
643
- * @default: false
644
- * @type: boolean
645
- * @attribute:
646
- * @name: bulk
647
- * @description: Get a bulk operation object, so several operations can be executed in bulk.
648
- * @default: false
649
- * @type: boolean
650
- */
651
- async delete(path, opts) {
652
- if (typeof path !== "string" && (typeof path !== "object" || path == null)) {
653
- throw Error(`Parameter "path" has an invalid type "${typeof path}", the valid type is "string".`);
654
- }
655
- try {
656
- if (opts != null && opts.chunked === true) {
657
- if (opts.bulk) {
658
- return { deleteMany: { filter: typeof path === "object" ? path : { _path: path } } };
659
- }
660
- else {
661
- await this.col.deleteMany(typeof path === "object" ? path : { _path: path });
662
- }
663
- }
664
- else {
665
- if (opts != null && opts.bulk) {
666
- return { deleteOne: { filter: typeof path === "object" ? path : { _path: path } } };
667
- }
668
- else {
669
- await this.col.deleteOne(typeof path === "object" ? path : { _path: path });
670
- }
671
- }
672
- }
673
- catch (error) {
674
- console.error(error);
675
- throw new Error('Encountered an error while deleting.');
676
- }
677
- }
678
- /* @docs:
679
- * @title: Delete Query
680
- * @description: Delete a document of the collection by query.
681
- * @parameter:
682
- * @name: query
683
- * @description: The query object.
684
- * @type: object
685
- */
686
- async delete_query(query = {}) {
687
- if (typeof query !== "object" || query == null || Object.keys(query).length === 0) {
688
- throw Error(`Parameter "query" has an invalid type "${typeof query}", the valid type is "object".`);
689
- }
690
- if (Object.keys(query).length === 0) {
691
- throw Error(`Parameter "query" is an empty object.`);
692
- }
693
- return await this.col.deleteMany(query);
694
- }
695
- // Delete all.
696
- async delete_all(path) {
697
- if (typeof path !== "string" && (typeof path !== "object" || path == null)) {
698
- throw Error(`Parameter "path" has an invalid type "${typeof path}", the valid type is "string".`);
699
- }
700
- try {
701
- await this.col.deleteMany(typeof path === "object" ? path : { _path: path });
702
- }
703
- catch (error) {
704
- console.error(error);
705
- throw new Error('Encountered an error while deleting.');
706
- }
707
- }
708
- async delete_many(query) {
709
- try {
710
- await this.col.deleteMany(query);
711
- }
712
- catch (error) {
713
- console.error(error);
714
- throw new Error('Encountered an error while deleting.');
715
- }
716
- }
717
- /* @docs:
718
- * @title: Delete Collection
719
- * @description: Delete all documents of from the collection.
720
- */
721
- async delete_collection() {
722
- await this.col.deleteMany();
723
- await this.col.drop();
724
- }
725
- /* @docs:
726
- * @title: Clean document
727
- * @description: Clean a document from all default system attributes.
728
- */
729
- clean(doc) {
730
- if (doc == null) {
731
- return doc;
732
- }
733
- if (typeof doc === "object") {
734
- delete doc._id;
735
- delete doc._path;
736
- if (this.uid_based) {
737
- delete doc._uid;
738
- }
739
- if (this.ttl_enabled) {
740
- delete doc._ttl_timestamp;
741
- }
742
- }
743
- return doc;
744
- }
745
- /** Write bulk operations. */
746
- async bulk_operations(operations = []) {
747
- return await this.col.bulkWrite(operations, { ordered: true });
748
- }
749
- }
750
- // ---------------------------------------------------------
751
- // UID based collection.
752
- // @warning: The "path" param must always be allowed to be an object or string, also for the UIDCollection class.
753
- // @warning: THE DATABASE COLLECTION SHOULD ALSO ACCEPT OBJECTS FOR PATHS.
754
- /* @docs:
755
- @nav: Backend
756
- @chapter: Database
757
- @title: UID Collection
758
- @desc: The UID based database collection class.
759
- @note: The document attribute `_uid` is a reserved index attribute for the user id of the document.
760
- @note: The document attribute `_path` is a reserved index attribute for the path of the document.
761
- @attribute:
762
- @name: col
763
- @desc: The native mongodb collection.
764
- */
765
- export class UIDCollection {
766
- _col;
767
- col;
768
- constructor(name, collection, indexes = [], ttl = null) {
769
- this._col = new Collection(name, collection, ttl, indexes, true);
770
- this.col = this._col.col;
771
- }
772
- /* @docs:
773
- @title: Create index
774
- @description: Creates indexes on collections.
775
- @return:
776
- Returns the document that was found or `null` when no document is found.
777
- @parameter:
778
- @name: keys
779
- @desc: The `keys` argument for the orignal mongodb `createIndex()` function.
780
- @parameter:
781
- @name: options
782
- @desc: The `options` argument for the orignal mongodb `createIndex()` function.
783
- @parameter:
784
- @name: commitQuorum
785
- @desc: The `commitQuorum` argument for the orignal mongodb `createIndex()` function.
786
- */
787
- async create_index(args) {
788
- return this._col.create_index(args);
789
- }
790
- /* @docs:
791
- * @title: Find
792
- * @description: Find a document by a query.
793
- * @return:
794
- * Returns the document that was found or `null` when no document is found.
795
- * @parameter:
796
- * @name: uid
797
- * @cached: Users:uid:param
798
- * @required: false
799
- * @parameter:
800
- * @name: query
801
- * @desc: The query options.
802
- * @type: object
803
- */
804
- async find(uid = null, query = {}) {
805
- if (uid != null) {
806
- query._uid = uid;
807
- }
808
- return await this._col.find(query);
809
- }
810
- /* @docs:
811
- * @title: Exists
812
- * @description: Check if a document exists.
813
- * @parameter:
814
- * @name: uid
815
- * @cached: Users:uid:param
816
- * @parameter:
817
- * @name: path
818
- * @description: The database path to the document.
819
- * @type: string, object
820
- */
821
- async exists(uid, path) {
822
- if (typeof path !== "string" && (typeof path !== "object" || path == null)) {
823
- throw Error(`Parameter "path" has an invalid type "${typeof path}", the valid type is "string".`);
824
- }
825
- if (typeof uid !== "string") {
826
- throw Error(`Parameter "uid" has an invalid type "${typeof uid}", the valid type is "string".`);
827
- }
828
- if (typeof path === "object") {
829
- return await this._col.exists({ ...path, _uid: uid });
830
- }
831
- else {
832
- return await this._col.exists({ _path: path, _uid: uid });
833
- }
834
- }
835
- /* @docs:
836
- * @title: Load
837
- * @description: Load data by user id and path.
838
- * @return:
839
- * Returns the loaded document.
840
- *
841
- * 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.
842
- * @parameter:
843
- * @name: uid
844
- * @cached: Users:uid:param
845
- * @parameter:
846
- * @name: path
847
- * @description: The database path to the document.
848
- * @type: string, object
849
- * @parameter:
850
- * @name: opts
851
- * @desc: Additional options.
852
- * @type: null, object
853
- * @attribute:
854
- * @name: default
855
- * @description:
856
- * The default data to be returned when the data does not exist.
857
- *
858
- * 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.
859
- * @type: null, object
860
- */
861
- async load(uid, path, opts = null) {
862
- if (typeof path !== "string" && (typeof path !== "object" || path == null)) {
863
- throw Error(`Parameter "path" has an invalid type "${typeof path}", the valid type is "string".`);
864
- }
865
- if (typeof uid !== "string") {
866
- throw Error(`Parameter "uid" has an invalid type "${typeof uid}", the valid type is "string".`);
867
- }
868
- if (typeof path === "object") {
869
- return await this._col.load({ ...path, _uid: uid }, opts);
870
- }
871
- else {
872
- return await this._col.load({ _path: path, _uid: uid }, opts);
873
- }
874
- }
875
- /* @docs:
876
- * @title: Save
877
- * @description: Save data by user id and path. When the document already exists this function only updates the specified content attributes.
878
- * @return:
879
- * Returns the updated document.
880
- * @parameter:
881
- * @name: uid
882
- * @cached: Users:uid:param
883
- * @parameter:
884
- * @name: path
885
- * @description: The database path to the document.
886
- * @type: string, object
887
- * @parameter:
888
- * @name: data
889
- * @description: The data to save.
890
- * @type: null, boolean, number, string, array, object
891
- * @parameter:
892
- * @name: opts
893
- * @desc: Additional options.
894
- * @type: null, object
895
- * @attribute:
896
- * @name: chunked
897
- * @description: Chunk the document into multiple documents, therefore documents larger than 16MB are supported.
898
- * @warning: Currently this option is only supported for types `object` and `array`.
899
- * @default: false
900
- * @type: boolean
901
- * @attribute:
902
- * @name: bulk
903
- * @description: Get a bulk operation object, so several operations can be executed in bulk.
904
- * @default: false
905
- * @type: boolean
906
- * @attribute:
907
- * @name: set
908
- * @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.
909
- * @warning: This does not work in combination with `opts.chunked`.
910
- * @default: true
911
- * @type: boolean
912
- */
913
- async save(uid, path, content, opts = null) {
914
- if (typeof path !== "string" && (typeof path !== "object" || path == null)) {
915
- throw Error(`Parameter "path" has an invalid type "${typeof path}", the valid type is "string".`);
916
- }
917
- if (typeof uid !== "string") {
918
- throw Error(`Parameter "uid" has an invalid type "${typeof uid}", the valid type is "string".`);
919
- }
920
- if (typeof path === "object") {
921
- return await this._col.save({ ...path, _uid: uid }, content, opts);
922
- }
923
- else {
924
- return await this._col.save({ _path: path, _uid: uid }, content, opts);
925
- }
926
- }
927
- /** Update many. */
928
- async update_many(...args) {
929
- return this.col.updateMany(...args);
930
- }
931
- /* @docs:
932
- * @title: List
933
- * @description: List all child documents of directory path.
934
- * @parameter:
935
- * @name: uid
936
- * @cached: Users:uid:param
937
- * @parameter:
938
- * @name: path
939
- * @description: The database directory path.
940
- * @type: string, object
941
- * @parameter:
942
- * @name: options
943
- * @description: List options.
944
- * @type: object
945
- * @attribute:
946
- * @name: process
947
- * @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.
948
- * @type: boolean
949
- * @default: true
950
- * @attribute:
951
- * @name: projection
952
- * @description: The data attributes to retrieve, when left undefined all attributes are retrieved.
953
- * @type: object
954
- * @default: undefined
955
- */
956
- async list(uid, path, options = {}) {
957
- if (typeof path !== "string" && (typeof path !== "object" || path == null)) {
958
- throw Error(`Parameter "path" has an invalid type "${typeof path}", the valid type is "string".`);
959
- }
960
- if (typeof uid !== "string") {
961
- throw Error(`Parameter "uid" has an invalid type "${typeof uid}", the valid type is "string".`);
962
- }
963
- if (typeof path === "object") {
964
- return await this._col.list({ ...path, _uid: uid }, options);
965
- }
966
- else {
967
- return await this._col.list({ _path: path, _uid: uid }, options);
968
- }
969
- }
970
- /* @docs:
971
- * @title: List Query
972
- * @description: List all documents of the collection based on a query.
973
- * @parameter:
974
- * @name: query
975
- * @desc: The query options.
976
- * @type: object
977
- * @parameter:
978
- * @name: options
979
- * @description: List options.
980
- * @type: object
981
- * @attribute:
982
- * @name: process
983
- * @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.
984
- * @type: boolean
985
- * @default: true
986
- * @attribute:
987
- * @name: projection
988
- * @description: The data attributes to retrieve, when left undefined all attributes are retrieved.
989
- * @type: object
990
- * @default: undefined
991
- */
992
- async list_query(query = {}, options = {}) {
993
- return await this._col.list_query(query, options);
994
- }
995
- /* @docs:
996
- * @title: List All
997
- * @description: List all documents of the collection, optionally per uid.
998
- * @parameter:
999
- * @name: uid
1000
- * @cached: Users:uid:param
1001
- * @parameter:
1002
- * @name: options
1003
- * @description: List options.
1004
- * @type: object
1005
- * @attribute:
1006
- * @name: process
1007
- * @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.
1008
- * @type: boolean
1009
- * @default: true
1010
- * @attribute:
1011
- * @name: projection
1012
- * @description: The data attributes to retrieve, when left undefined all attributes are retrieved.
1013
- * @type: object
1014
- * @default: undefined
1015
- */
1016
- async list_all(uid = null, options = {}) {
1017
- if (uid == null) {
1018
- return await this._col.list_all({}, options);
1019
- }
1020
- else {
1021
- return await this._col.list_all({ _uid: uid }, options);
1022
- }
1023
- }
1024
- /* @docs:
1025
- * @title: Delete
1026
- * @description: Delete a document of the collection by uid and path.
1027
- * @parameter:
1028
- * @name: uid
1029
- * @cached: Users:uid:param
1030
- * @parameter:
1031
- * @name: path
1032
- * @description: The database path to the document.
1033
- * @type: string, object
1034
- * @parameter:
1035
- * @name: opts
1036
- * @desc: Additional options.
1037
- * @type: null, object
1038
- * @attribute:
1039
- * @name: chunked
1040
- * @description: Delete a chunked document.
1041
- * @default: false
1042
- * @type: boolean
1043
- * @attribute:
1044
- * @name: bulk
1045
- * @description: Get a bulk operation object, so several operations can be executed in bulk.
1046
- * @default: false
1047
- * @type: boolean
1048
- */
1049
- async delete(uid, path, opts) {
1050
- if (typeof path !== "string" && (typeof path !== "object" || path == null)) {
1051
- throw Error(`Parameter "path" has an invalid type "${typeof path}", the valid type is "string".`);
1052
- }
1053
- if (typeof uid !== "string") {
1054
- throw Error(`Parameter "uid" has an invalid type "${typeof uid}", the valid type is "string".`);
1055
- }
1056
- if (typeof path === "object") {
1057
- return await this._col.delete({ ...path, _uid: uid }, opts);
1058
- }
1059
- else {
1060
- return await this._col.delete({ _path: path, _uid: uid }, opts);
1061
- }
1062
- }
1063
- /* @docs:
1064
- * @title: Delete Query
1065
- * @description: Delete a document of the collection by query.
1066
- * @parameter:
1067
- * @name: query
1068
- * @description: The query object.
1069
- * @type: object
1070
- */
1071
- async delete_query(query) {
1072
- if (typeof query !== "object" || query == null || Object.keys(query).length === 0) {
1073
- throw Error(`Parameter "query" has an invalid type "${typeof query}", the valid type is "object".`);
1074
- }
1075
- if (Object.keys(query).length === 0) {
1076
- throw Error(`Parameter "query" is an empty object.`);
1077
- }
1078
- return await this._col.delete_query(query);
1079
- }
1080
- // Delete all.
1081
- async delete_all(uid, path = null) {
1082
- if (typeof uid !== "string") {
1083
- throw Error(`Parameter "uid" has an invalid type "${typeof uid}", the valid type is "string".`);
1084
- }
1085
- if (path == null) {
1086
- return await this._col.delete_all({ _uid: uid });
1087
- }
1088
- else if (typeof path === "object") {
1089
- return await this._col.delete_all({ ...path, _uid: uid });
1090
- }
1091
- else {
1092
- return await this._col.delete_all({ _path: path, _uid: uid });
1093
- }
1094
- }
1095
- async delete_many(query) {
1096
- return await this._col.delete_many(query);
1097
- }
1098
- /* @docs:
1099
- * @title: Delete Collection
1100
- * @description: Delete all documents of from the collection.
1101
- */
1102
- async delete_collection() {
1103
- await this._col.delete_collection();
1104
- }
1105
- /* @docs:
1106
- * @title: Clean document
1107
- * @description: Clean a document from all default system attributes.
1108
- */
1109
- clean(doc) {
1110
- return this._col.clean(doc);
1111
- }
1112
- /** Write bulk operations. */
1113
- async bulk_operations(operations = []) {
1114
- return await this.col.bulkWrite(operations, { ordered: true });
1115
- }
1116
- }
1117
- // ---------------------------------------------------------
1118
- // Database.
1119
- /* @docs:
1120
- @nav: Backend
1121
- @chapter: Database
1122
- @title: Database
1123
- @desc:
1124
- The MongoDB database class, accessable under `Server.db`.
1125
-
1126
- The database class can be utilized in two ways.
1127
-
1128
- 1. You only provide the `uri` parameter to access an already running mongodb database.
1129
-
1130
- 2. You provide parameters `config` and `start_args` to start and optionally create the database.
1131
-
1132
- @warning:
1133
- Do not forget to enable TLS when using the `config` parameter.
1134
- @param:
1135
- @name: uri
1136
- @desc: The mongodb server uri.
1137
- @type: string
1138
- @param:
1139
- @name: source
1140
- @desc: The source path of the database directory, by default path `$server_source/.db` will be used.
1141
- @type: null, string
1142
- @param:
1143
- @name: config
1144
- @desc: The json data for the mongodb config file.
1145
- @type: null, string
1146
- @param:
1147
- @name: start_args
1148
- @desc: The mongod database start command arguments.
1149
- @type: null, array[string]
1150
- @param:
1151
- @name: client
1152
- @desc: The MongoClient options.
1153
- @type: null, object
1154
- */
1155
- export class Database {
1156
- static constructor_scheme = {
1157
- uri: { type: "string", default: null },
1158
- source: { type: "string", default: null },
1159
- config: { type: "object", default: {} },
1160
- start_args: { type: "array", default: [] },
1161
- client: { type: "object", default: {} },
1162
- collections: { type: "array", default: [], value_scheme: {
1163
- type: ["string", "object"],
1164
- preprocess: (info) => typeof info === "string" ? { name: info } : info,
1165
- scheme: {
1166
- name: Collection.constructor_scheme.name,
1167
- ttl: Collection.constructor_scheme.ttl,
1168
- indexes: Collection.constructor_scheme.indexes,
1169
- },
1170
- } },
1171
- uid_collections: { type: "array", default: [], value_scheme: {
1172
- type: ["string", "object"],
1173
- preprocess: (info) => typeof info === "string" ? { name: info } : info,
1174
- scheme: {
1175
- name: Collection.constructor_scheme.name,
1176
- ttl: Collection.constructor_scheme.ttl,
1177
- indexes: Collection.constructor_scheme.indexes,
1178
- },
1179
- } },
1180
- preview: { type: "boolean", default: true },
1181
- preview_ip_whitelist: { type: "array", default: [] },
1182
- daemon: { type: ["object", "boolean"], default: {} },
1183
- _server: { type: ["object", "undefined"] },
1184
- };
1185
- uri;
1186
- // preview: boolean;
1187
- // preview_ip_whitelist: string[];
1188
- client_opts;
1189
- config;
1190
- source; // Using vlib.Path type
1191
- start_args;
1192
- _collections;
1193
- _uid_collections;
1194
- server;
1195
- client;
1196
- collections;
1197
- proc;
1198
- daemon;
1199
- db;
1200
- // System.
1201
- _listed_cols;
1202
- constructor({ uri = null, source = null, config = null, start_args = [], client = null, collections = [], uid_collections = [],
1203
- // preview = true,
1204
- // preview_ip_whitelist = [],
1205
- daemon = {}, _server = undefined, }) {
1206
- // Checks.
1207
- if (!_server || (_server.is_primary && uri == null)) {
1208
- ({ uri, config, start_args, config, client } = vlib.Scheme.verify({
1209
- object: arguments[0],
1210
- check_unknown: true,
1211
- throw_err: true,
1212
- scheme: Database.constructor_scheme
1213
- }));
1214
- }
1215
- // Arguments.
1216
- this.uri = uri;
1217
- // this.preview = preview;
1218
- // this.preview_ip_whitelist = preview_ip_whitelist;
1219
- this.client_opts = client;
1220
- this.config = config || {};
1221
- this.source = source != null ? new vlib.Path(source) : _server?.source.join(".db");
1222
- this.start_args = start_args;
1223
- this._collections = collections ?? [];
1224
- this._uid_collections = uid_collections ?? [];
1225
- this.server = _server;
1226
- // Attributes.
1227
- this.client = null;
1228
- this.collections = {};
1229
- // Initialize the service daemon.
1230
- if (this.server?.daemon && daemon !== false) {
1231
- const log_source = this.server.source.join(".logs");
1232
- if (!log_source.exists()) {
1233
- log_source.mkdir_sync();
1234
- }
1235
- if (!this.server) {
1236
- throw new Error("Parameter 'Database._server' must be defined for this behaviour.");
1237
- }
1238
- this.daemon = new vlib.Daemon({
1239
- name: this.server.daemon.name + ".mongodb",
1240
- user: daemon.user || this.server.daemon.user,
1241
- group: daemon.group || this.server.daemon.group,
1242
- command: "mongod",
1243
- cwd: this.server.daemon.cwd,
1244
- args: ["--config", this.source.join("mongod.json").str(), ...this.start_args],
1245
- env: daemon.env || this.server.daemon.env,
1246
- description: daemon.description || `Service daemon for the mongo database of website ${this.server.domain}.`,
1247
- auto_restart: true,
1248
- logs: daemon.logs || log_source.join("logs.mongodb").str(),
1249
- errors: daemon.errors || log_source.join("errors.mongodb").str(),
1250
- });
1251
- }
1252
- }
1253
- /* Database preview.
1254
- _initialize_db_preview(): void {
1255
-
1256
- if (this.preview && this.server.production === false) {
1257
- this.server.endpoint(
1258
-
1259
- // Database preview.
1260
- {
1261
- method: "GET" ,
1262
- endpoint: "/volt/db/preview",
1263
- view: {
1264
- callback: () => {
1265
- volt.utils.on_load(async () => {
1266
-
1267
- // Style theme.
1268
- const style = {
1269
- // bg: "#151721",
1270
- // sub_bg: "#191B28",
1271
- // tag_bg: "#1C203A",
1272
- // div_bg: "#282B40",
1273
- // fg: "#FFFFFF",
1274
- // sub_fg: "#FFFFFF99",
1275
- // tag_fg: "#FFFFFF",
1276
-
1277
- bg: "#F6F8F8",
1278
- sub_bg: "#FFFFFF",
1279
- tag_bg: "#F6F8F8",
1280
- div_bg: "#00000010",
1281
- fg: "#32334F",
1282
- sub_fg: "#31344599",
1283
- tag_fg: "#313445",
1284
- };
1285
-
1286
- // List all collections.
1287
- const collections = (await volt.utils.request({url: "/volt/db/collections"})).collections;
1288
-
1289
- // Render a list.
1290
- const prev_lists = [];
1291
- function RenderList ({
1292
- title,
1293
- list,
1294
- doc = null,
1295
- add_prev = true,
1296
- }) {
1297
- if (add_prev) {
1298
- prev_lists.append({title, list, doc});
1299
- }
1300
-
1301
- // Object view.
1302
- const obj_view = VStack();
1303
- const refresh_obj_view = () => {
1304
- obj_view.inner_html("");
1305
- let index = 0;
1306
- obj_view.append(
1307
- ForEach(list, (key, value) => {
1308
- ++index;
1309
- let current_key = key;
1310
- let value_type = Array.isArray(value) ? "array" : value == null ? "null" : typeof value;
1311
- if (Array.isArray(value)) {
1312
- value = JSON.stringify(value, null, 4)
1313
- }
1314
-
1315
- // Key input.
1316
- const key_input = Input("key")
1317
- .value(key)
1318
- .font_family("'Menlo', 'Consolas', monospace")
1319
- .color(style.sub_fg)
1320
- .font_size(14)
1321
- .padding(0)
1322
- .readonly(key === "_path" || key === "_uid" || key === "uid")
1323
- .on_mouse_over(e => e.color(style.fg))
1324
- .on_mouse_out(e => e.color(style.sub_fg))
1325
- .on_render((e) => e.width(e.text_width(key)))
1326
- .on_input((e) => {
1327
- if (key != current_key) {
1328
- list[e.value()] = list[current_key];
1329
- delete list[current_key];
1330
- current_key = e.value();
1331
- }
1332
- e.width(e.text_width(current_key));
1333
- });
1334
-
1335
- // Value input.
1336
- const value_input = Input("value")
1337
- .value(value == null ? "null" : value)
1338
- .font_family("'Menlo', 'Consolas', monospace")
1339
- .color(style.sub_fg)
1340
- .display("inline-block")
1341
- .width("fit-content")
1342
- .font_size(14)
1343
- .readonly(key === "_path" || key === "_uid")
1344
- .stretch(true)
1345
- .on_mouse_over(e => e.color(style.fg))
1346
- .on_mouse_out(e => e.color(style.sub_fg))
1347
- .on_input(() => {
1348
- clearTimeout(value_input.timeout)
1349
- value_input.timeout = setTimeout(update_value, 500);
1350
- })
1351
-
1352
- // Type select.
1353
- const type_select = ExtendedSelect({items: ["null", "boolean", "number", "string", "array", "object"]})
1354
- .center()
1355
- .margin(0)
1356
- .max_width(73)
1357
- .color(style.sub_fg)
1358
- .font_size(14)
1359
- .border_radius(10)
1360
- .background(style.tag_bg)
1361
- .border_color(style.div_bg)
1362
- .value(value_type)
1363
- .container
1364
- .padding(2.5, 5)
1365
- .parent();
1366
-
1367
- // Update the list after edits.
1368
- const update_value = () => {
1369
- const type = type_select.value();
1370
- const value = value_input.value();
1371
- if (type === "null") {
1372
- list[current_key] = null;
1373
- value_input.value(list[current_key].toString());
1374
- }
1375
- else if (type === "boolean") {
1376
- list[current_key] = value == "true" || value == "True" || value == "TRUE" || value == "1";
1377
- value_input.value(list[current_key].toString());
1378
- }
1379
- else if (type === "number") {
1380
- if (value.indexOf(".") === -1) {
1381
- list[current_key] = paseInt(value);
1382
- } else {
1383
- list[current_key] = paseFloat(value);
1384
- }
1385
- if (isNaN(list[key_input.key])) {
1386
- list[current_key] = 0;
1387
- }
1388
- value_input.value(list[current_key].toString());
1389
- }
1390
- else if (type === "string") {
1391
- list[current_key] = value;
1392
- }
1393
- else if (type === "object") {
1394
- list[current_key] = JSON.parse(value);
1395
- }
1396
- }
1397
-
1398
- // Row.
1399
- const row = HStack(
1400
- key_input,
1401
- Text(" : ")
1402
- .white_space("pre")
1403
- .font_family("'Menlo', 'Consolas', monospace")
1404
- .color(style.sub_fg)
1405
- .font_size(14),
1406
- value_input,
1407
- type_select,
1408
-
1409
- index < Object.keys(list).length ? null : VStack("add")
1410
- .background(style.tag_bg)
1411
- .padding(5, 12.5)
1412
- .border_radius(10)
1413
- .font_size(13)
1414
- .color("#3B8553")
1415
- .margin_left(10)
1416
- .border(1, style.div_bg)
1417
- .on_click(() => {
1418
- list["_new"] = "";
1419
- refresh_obj_view();
1420
- }),
1421
-
1422
- VStack("delete")
1423
- .background(style.tag_bg)
1424
- .color("#B2321E")
1425
- .padding(5, 12.5)
1426
- .border_radius(10)
1427
- .font_size(13)
1428
- .margin_left(10)
1429
- .border(1, style.div_bg)
1430
- .on_click(async () => {
1431
- }),
1432
- )
1433
- .center_vertical()
1434
- .padding(7.5, 0)
1435
- if (volt.utils.is_obj(value)) {
1436
- row.on_click(() => RenderList({title: `${title}.${key}`, list: value}));
1437
- }
1438
- return [
1439
- row,
1440
- Divider().background(style.div_bg),
1441
- ]
1442
- })
1443
- );
1444
- }
1445
-
1446
- // Add.
1447
- preview.inner_html("");
1448
- preview.append(
1449
- Scroller(
1450
- VStack(
1451
- HStack(
1452
- Title("Database")
1453
- .font_family("'Menlo', 'Consolas', monospace")
1454
- .font_size(12)
1455
- .color(style.tag_fg)
1456
- .background(style.tag_bg)
1457
- .padding(5, 12.5)
1458
- .border_radius(10)
1459
- .margin(0, 0, 0, 0)
1460
- .border(1, style.div_bg)
1461
- .width("fit-content"),
1462
-
1463
- Spacer(),
1464
-
1465
- doc == null ? null : Button("Update")
1466
- .background(style.tag_bg)
1467
- .color("#3B8553")
1468
- .padding(5, 12.5)
1469
- .margin_right(10)
1470
- .border_radius(10)
1471
- .border(1, style.div_bg)
1472
- .on_click(() => {
1473
- // --prev_lists.length;
1474
- // const last = prev_lists[prev_lists.length - 1];
1475
- // RenderList({...last, add_prev: false})
1476
- }),
1477
-
1478
- doc == null ? null : Button("Delete")
1479
- .background(style.tag_bg)
1480
- .color("#B2321E")
1481
- .padding(5, 12.5)
1482
- .margin_right(10)
1483
- .border_radius(10)
1484
- .border(1, style.div_bg)
1485
- .on_click(async () => {
1486
- volt.utils.request({
1487
- method: "DELETE",
1488
- url: "/volt/db/document",
1489
- data: doc,
1490
- })
1491
- --prev_lists.length;
1492
- const last = prev_lists[prev_lists.length - 1];
1493
-
1494
- const __name = doc.uid != null ? `${doc.uid}:${doc.id}` : doc.id
1495
- const filtered_list = [];
1496
- last.list.iterate((item) => {
1497
- if (item.__name !== __name) {
1498
- filtered_list.append(item);
1499
- }
1500
- })
1501
- last.list = filtered_list;
1502
- RenderList({...last, add_prev: false})
1503
- }),
1504
-
1505
- prev_lists.length == 1 ? null : Button("Prev")
1506
- .background(style.tag_bg)
1507
- .color(style.tag_fg)
1508
- .padding(5, 12.5)
1509
- .border_radius(10)
1510
- .border(1, style.div_bg)
1511
- .on_click(() => {
1512
- --prev_lists.length;
1513
- const last = prev_lists[prev_lists.length - 1];
1514
- RenderList({...last, add_prev: false})
1515
- }),
1516
- ),
1517
-
1518
- Title(title)
1519
- .font_family("'Menlo', 'Consolas', monospace")
1520
- .font_size(18)
1521
- .color(style.fg)
1522
- .margin(15, 0),
1523
-
1524
- Divider().background(style.div_bg),
1525
-
1526
- Array.isArray(list)
1527
- ? ForEach(list, (item) => {
1528
- return [
1529
- VStack(
1530
- Text(item.__name)
1531
- .font_family("'Menlo', 'Consolas', monospace")
1532
- .color(style.sub_fg)
1533
- .font_size(14)
1534
- .on_mouse_over(e => e.color(style.fg))
1535
- .on_mouse_out(e => e.color(style.sub_fg))
1536
- )
1537
- .padding(7.5, 0)
1538
- .on_click(item.__click),
1539
-
1540
- Divider().background(style.div_bg),
1541
- ]
1542
- })
1543
- : () => {refresh_obj_view(); return obj_view}
1544
- )
1545
- .margin(25, 50)
1546
- .padding(25, 25)
1547
- .background(style.sub_bg)
1548
- .border_radius(10)
1549
- .box_shadow("0px 0px 5px #00000090")
1550
- )
1551
- .font_family("Helvetica, sans-serif")
1552
- .background(style.bg)
1553
- .frame("100%", "100%")
1554
- )
1555
- }
1556
-
1557
- // Render the collections.
1558
- const RenderCollections = () => {
1559
- RenderList({title: "/", list: collections.iterate_append((item) => {
1560
- return {
1561
- __name: `${item}/`,
1562
- __click: () => RenderCollection(item),
1563
- }
1564
- })})
1565
- }
1566
-
1567
- // Render a collection.
1568
- const RenderCollection = async (collection) => {
1569
- const documents = (await volt.utils.request({url: "/volt/db/documents", data: {collection}})).documents;
1570
- RenderList({title: `${collection}/`, list: documents.iterate_append((item) => {
1571
- return {
1572
- __name: item._uid != null ? `${item._uid}:${item._path}` : item._path,
1573
- __click: () => RenderDocument(collection, item._path, item._uid),
1574
- }
1575
- })})
1576
- }
1577
-
1578
- // Render a document.
1579
- const RenderDocument = async (collection, path, uid = null) => {
1580
- let doc = (await volt.utils.request({url: "/volt/db/document", data: {collection, path, uid}})).document
1581
- if (Array.isArray(doc)) {
1582
- doc = {_content: doc};
1583
- }
1584
- RenderList({
1585
- title: uid != null ? `${collection}/${uid}:${path}` : `${collection}/${path}`,
1586
- list: doc,
1587
- doc: {collection, uid, path},
1588
- })
1589
- }
1590
-
1591
- // Stack.
1592
- const preview = VStack()
1593
- .position(0, 0, 0, 0);
1594
-
1595
- // Render all collections.
1596
- RenderCollections();
1597
-
1598
- // Response.
1599
- return preview;
1600
-
1601
- });
1602
- }
1603
- }
1604
- },
1605
-
1606
- // Get collections.
1607
- {
1608
- method: "GET",
1609
- endpoint: "/volt/db/collections",
1610
- content_type: "application/json",
1611
- rate_limit: "global",
1612
- callback: async (stream) => {
1613
-
1614
- // Check ip whitelist.
1615
- if (!this.preview_ip_whitelist.includes(stream.ip)) {
1616
- return stream.error({status: Status.forbidden});
1617
- }
1618
-
1619
- // Sign in.
1620
- return stream.success({data: {
1621
- message: "Successfully retrieved all collections.",
1622
- collections: await this.get_collections(),
1623
- }});
1624
- }
1625
- },
1626
-
1627
- // Get collection documents.
1628
- {
1629
- method: "GET",
1630
- endpoint: "/volt/db/documents",
1631
- content_type: "application/json",
1632
- rate_limit: "global",
1633
- params: {
1634
- collection: "string",
1635
- },
1636
- callback: async (stream, params) => {
1637
-
1638
- // Check ip whitelist.
1639
- if (!this.preview_ip_whitelist.includes(stream.ip)) {
1640
- return stream.error({status: Status.forbidden});
1641
- }
1642
-
1643
- // Check collection.
1644
- let col;
1645
- if ((col = this.collections[params.collection]) == null) {
1646
- return stream.error({data: {error: `Invalid collection "${params.collection}".`}})
1647
- }
1648
-
1649
- // Load docs.
1650
- let docs = await col.list_all();
1651
-
1652
- // Sign in.
1653
- return stream.success({data: {
1654
- message: "Successfully loaded the document.",
1655
- documents: docs,
1656
- }});
1657
- }
1658
- },
1659
-
1660
- // Get document.
1661
- {
1662
- method: "GET",
1663
- endpoint: "/volt/db/document",
1664
- content_type: "application/json",
1665
- rate_limit: "global",
1666
- params: {
1667
- collection: "string",
1668
- path: ["string", "object"],
1669
- uid: {type: ["string", "null"], default: null},
1670
- },
1671
- callback: async (stream, params) => {
1672
-
1673
- // Check ip whitelist.
1674
- if (!this.preview_ip_whitelist.includes(stream.ip)) {
1675
- return stream.error({status: Status.forbidden});
1676
- }
1677
-
1678
- // Check collection.
1679
- let col;
1680
- if ((col = this.collections[params.collection]) == null) {
1681
- return stream.error({data: {error: `Invalid collection "${params.collection}".`}})
1682
- }
1683
-
1684
- // Load doc.
1685
- let doc;
1686
- if (params.uid == null) {
1687
- doc = await col.load(params.path);
1688
- } else {
1689
- doc = await col.load(params.uid, params.path);
1690
- }
1691
-
1692
- // Sign in.
1693
- return stream.success({data: {
1694
- message: "Successfully loaded the document.",
1695
- document: doc,
1696
- }});
1697
- }
1698
- },
1699
-
1700
- // Delete document.
1701
- {
1702
- method: "DELETE",
1703
- endpoint: "/volt/db/document",
1704
- content_type: "application/json",
1705
- rate_limit: "global",
1706
- params: {
1707
- collection: "string",
1708
- path: ["string", "object"],
1709
- uid: {type: ["string", "null"], default: null},
1710
- },
1711
- callback: async (stream, params) => {
1712
-
1713
- // Check ip whitelist.
1714
- if (!this.preview_ip_whitelist.includes(stream.ip)) {
1715
- return stream.error({status: Status.forbidden});
1716
- }
1717
-
1718
- // Check collection.
1719
- let col;
1720
- if ((col = this.collections[params.collection]) == null) {
1721
- return stream.error({data: {error: `Invalid collection "${params.collection}".`}})
1722
- }
1723
-
1724
- // Load doc.
1725
- let doc;
1726
- if (params.uid == null) {
1727
- doc = await col.delete(params.path);
1728
- } else {
1729
- doc = await col.delete(params.uid, params.path);
1730
- }
1731
-
1732
- // Sign in.
1733
- return stream.success({data: {
1734
- message: "Successfully deleted the document.",
1735
- }});
1736
- }
1737
- },
1738
-
1739
- // Update document.
1740
- {
1741
- method: "PATCH",
1742
- endpoint: "/volt/db/document",
1743
- content_type: "application/json",
1744
- rate_limit: "global",
1745
- params: {
1746
- collection: "string",
1747
- path: ["string", "object"],
1748
- uid: {type: ["string", "null"], default: null},
1749
- content: "object",
1750
- },
1751
- callback: async (stream, params) => {
1752
-
1753
- // Check ip whitelist.
1754
- if (!this.preview_ip_whitelist.includes(stream.ip)) {
1755
- return stream.error({status: Status.forbidden});
1756
- }
1757
-
1758
- // Check collection.
1759
- let col;
1760
- if ((col = this.collections[params.collection]) == null) {
1761
- return stream.error({data: {error: `Invalid collection "${params.collection}".`}})
1762
- }
1763
-
1764
- // Load doc.
1765
- let doc;
1766
- if (params.uid == null) {
1767
- doc = await col.save(params.path, params.content);
1768
- } else {
1769
- doc = await col.save(params.uid, params.path, params.content);
1770
- }
1771
-
1772
- // Sign in.
1773
- return stream.success({data: {
1774
- message: "Successfully updated the document.",
1775
- }});
1776
- }
1777
- },
1778
- )
1779
- }
1780
- }*/
1781
- // Connect.
1782
- async connect() {
1783
- try {
1784
- await this.client?.connect();
1785
- if (this.client) {
1786
- this.db = this.client.db();
1787
- }
1788
- }
1789
- catch (error) {
1790
- console.error(error);
1791
- throw new Error('Error connecting to the database');
1792
- }
1793
- }
1794
- // Initialize.
1795
- async initialize() {
1796
- // Set default config.
1797
- if (this.config.systemLog === undefined) {
1798
- this.config.systemLog = {};
1799
- }
1800
- this.config.systemLog.path = this.source?.join("mongod.log").str();
1801
- if (this.config.systemLog.destination === undefined) {
1802
- this.config.systemLog.destination = "file";
1803
- }
1804
- if (this.config.systemLog.logAppend === undefined) {
1805
- this.config.systemLog.logAppend = true;
1806
- }
1807
- if (this.config.systemLog.logRotate === undefined) {
1808
- this.config.systemLog.logRotate = "reopen";
1809
- }
1810
- if (this.config.systemLog.verbosity === undefined && this.server) {
1811
- this.config.systemLog.verbosity = this.server.production ? 0 : 1;
1812
- }
1813
- if (this.config.storage === undefined) {
1814
- this.config.storage = {};
1815
- }
1816
- if (this.source) {
1817
- const db_path = this.source.join("db");
1818
- this.config.storage.dbPath = db_path.str();
1819
- if (!db_path.exists()) {
1820
- db_path.mkdir_sync();
1821
- }
1822
- if (this.config.processManagement === undefined) {
1823
- this.config.processManagement = {};
1824
- }
1825
- this.config.processManagement.pidFilePath = this.source.join("mongod.pid").str();
1826
- }
1827
- if (this.config.net === undefined) {
1828
- this.config.net = {};
1829
- }
1830
- if (this.config.net.port === undefined) {
1831
- this.config.net.port = 27017;
1832
- }
1833
- if (this.config.net.bindIp === undefined) {
1834
- this.config.net.bindIp = "127.0.0.1";
1835
- }
1836
- // Mode 2: Start database.
1837
- if (this.server?.is_primary && this.uri == null) {
1838
- // Create the database.
1839
- if (!this.source.exists()) {
1840
- this.source.mkdir_sync();
1841
- }
1842
- // Set the uri.
1843
- if (this.uri == null) {
1844
- this.uri = `mongodb://${this.config.net.bindIp}:${this.config.net.port}/main`;
1845
- }
1846
- // Save the config.
1847
- const config_path = this.source.join("mongod.json");
1848
- config_path.save_sync(JSON.stringify(this.config));
1849
- // Start the database.
1850
- this.proc = spawn("mongod", ["--config", config_path.str(), ...this.start_args], {
1851
- stdio: "pipe",
1852
- detached: true,
1853
- env: { ...process.env },
1854
- });
1855
- this.proc.stdout?.on('data', (data) => {
1856
- console.log(data.toString());
1857
- });
1858
- this.proc.stderr?.on('data', (data) => {
1859
- console.error(data.toString());
1860
- });
1861
- this.proc.on("error", (code, signal) => {
1862
- console.error(`MongoDB crashed with error signal ${signal}.`);
1863
- process.exit(code);
1864
- });
1865
- }
1866
- // Assign URI.
1867
- else if (this.server && !this.server.is_primary && this.uri == null) {
1868
- this.uri = `mongodb://${this.config.net.bindIp}:${this.config.net.port}/main`;
1869
- }
1870
- // Initialize client.
1871
- if (this.uri) {
1872
- const opts = this.client_opts ?? {};
1873
- opts.serverApi ??= {
1874
- version: ServerApiVersion.v1,
1875
- strict: true,
1876
- deprecationErrors: true,
1877
- };
1878
- this.client = new MongoClient(this.uri, opts);
1879
- }
1880
- // Connect.
1881
- await this.connect();
1882
- // Batch.
1883
- const multiprocessing = true;
1884
- const promises = [];
1885
- // Create collections.
1886
- for (const info of this._collections) {
1887
- const promise = new Promise(resolve => {
1888
- if (this[info.name] !== undefined) {
1889
- throw Error(`Unable to initialize database collection "${info.name}", this attribute name is reserved for a system value.`);
1890
- }
1891
- if (Array.isArray(info.indexes)) {
1892
- for (let index = 0; index < info.indexes.length; index++) {
1893
- let item = info.indexes[index];
1894
- if (typeof item === "string") {
1895
- info.indexes[index] = item = { keys: [item] };
1896
- }
1897
- }
1898
- }
1899
- this.create_collection(info).then(data => {
1900
- this[info.name] = data;
1901
- resolve();
1902
- });
1903
- });
1904
- if (multiprocessing) {
1905
- promises.push(promise);
1906
- }
1907
- else {
1908
- await promise;
1909
- }
1910
- }
1911
- for (const info of this._uid_collections) {
1912
- const promise = new Promise(resolve => {
1913
- if (this[info.name] !== undefined) {
1914
- throw Error(`Unable to initialize database collection "${info.name}", this attribute name is reserved for a system value.`);
1915
- }
1916
- if (Array.isArray(info.indexes)) {
1917
- for (let index = 0; index < info.indexes.length; index++) {
1918
- let item = info.indexes[index];
1919
- if (typeof item === "string") {
1920
- info.indexes[index] = item = {
1921
- key: item,
1922
- };
1923
- }
1924
- }
1925
- }
1926
- this.create_uid_collection(info).then(data => {
1927
- this[info.name] = data;
1928
- resolve();
1929
- });
1930
- });
1931
- if (multiprocessing) {
1932
- promises.push(promise);
1933
- }
1934
- else {
1935
- await promise;
1936
- }
1937
- }
1938
- if (multiprocessing) {
1939
- await Promise.all(promises);
1940
- }
1941
- }
1942
- // Close.
1943
- async close() {
1944
- log(0, "Stopping the database.");
1945
- await this.client?.close();
1946
- }
1947
- /* @docs:
1948
- * @title: Create Collection
1949
- * @description: Create a database collection.
1950
- */
1951
- async create_collection(info) {
1952
- // Set name by single string argument.
1953
- let name;
1954
- let indexes = [];
1955
- let ttl = null;
1956
- if (typeof info === "string") {
1957
- name = info;
1958
- }
1959
- else {
1960
- name = info.name;
1961
- indexes = info.indexes || [];
1962
- ttl = info.ttl || null;
1963
- }
1964
- // Check collection.
1965
- if (name in this.collections) {
1966
- throw Error(`Collection "${name}" is already initialized.`);
1967
- }
1968
- // Logs.
1969
- debug(2, `Initializing collection "${name}".`);
1970
- // Check if the collection exists
1971
- if (this._listed_cols == null) {
1972
- this._listed_cols = await this.db.listCollections().toArray();
1973
- }
1974
- if (!this._listed_cols.find(x => x.name === name)) {
1975
- log(0, `Creating collection "${name}".`);
1976
- await this.db.createCollection(name);
1977
- }
1978
- // Create collection.
1979
- const col = new Collection(name, this.db.collection(name), ttl, indexes);
1980
- this.collections[name] = col;
1981
- return col;
1982
- }
1983
- /* @docs:
1984
- * @title: Create UID Based Collection
1985
- * @description: Create a UID based database collection.
1986
- */
1987
- async create_uid_collection(info) {
1988
- // Set name by single string argument.
1989
- let name;
1990
- let indexes = [];
1991
- let ttl = null;
1992
- if (typeof info === "string") {
1993
- name = info;
1994
- }
1995
- else {
1996
- name = info.name;
1997
- indexes = info.indexes || [];
1998
- ttl = info.ttl || null;
1999
- }
2000
- // Check duplicate collection.
2001
- if (name in this.collections) {
2002
- throw Error(`Collection "${name}" is already initialized.`);
2003
- }
2004
- // Logs.
2005
- debug(2, `Initializing uid collection "${name}".`);
2006
- // Check if the collection exists
2007
- const collections = await this.db.listCollections({ name: name }).toArray();
2008
- if (collections.length === 0) {
2009
- log(0, `Creating uid collection "${name}".`);
2010
- await this.db.createCollection(name);
2011
- }
2012
- // Collection.
2013
- const col = new UIDCollection(name, this.db.collection(name), indexes, ttl);
2014
- this.collections[name] = col;
2015
- return col;
2016
- }
2017
- /* @docs:
2018
- * @title: Get Collections
2019
- * @description: Get the names of the initializated database collections.
2020
- */
2021
- async get_collections() {
2022
- const created = Object.keys(this.collections);
2023
- const database = (await this.db.listCollections().toArray()).map((item) => item.name);
2024
- return created.concat(database)
2025
- .filter((value, index, self) => self.indexOf(value) === index)
2026
- .sort((a, b) => {
2027
- const result = a.toLowerCase().localeCompare(b.toLowerCase());
2028
- if (a.startsWith('_') && b.startsWith('_')) {
2029
- return result;
2030
- }
2031
- if (a.startsWith('_')) {
2032
- return 1;
2033
- }
2034
- if (b.startsWith('_')) {
2035
- return -1;
2036
- }
2037
- return result;
2038
- });
2039
- }
2040
- }
2041
- /** Objective document class.
2042
- * @deprecated Use `Reference` instead.
2043
- */
2044
- export class UIDDocument {
2045
- col;
2046
- data;
2047
- def;
2048
- uid;
2049
- path;
2050
- chunked;
2051
- error_type;
2052
- /** Constructor
2053
- * @param def The default value, when the default value is an object then the attributes will be checked / inserted as well.
2054
- */
2055
- constructor({ col, uid, path, data, def, chunked = false, external_errors = false }) {
2056
- this.col = col;
2057
- this.uid = uid;
2058
- this.path = path;
2059
- this.data = data;
2060
- this.def = def;
2061
- this.chunked = chunked;
2062
- this.error_type = external_errors ? ExternalError : InternalError;
2063
- }
2064
- /** As database document. */
2065
- document() {
2066
- return this.data;
2067
- }
2068
- // ---------------------------------------------------------
2069
- // Utils.
2070
- /** Create error options. */
2071
- not_found_error() {
2072
- let id = this.uid + "/";
2073
- if (typeof this.path === "string") {
2074
- id += this.path;
2075
- }
2076
- else {
2077
- id += Object.values(this.path).join("@");
2078
- }
2079
- return {
2080
- type: "DocumentNotFound",
2081
- message: `Requested document "${id}" does not exist.`,
2082
- status: Status.bad_request,
2083
- };
2084
- }
2085
- not_loaded_error() {
2086
- let id = this.uid + "/";
2087
- if (typeof this.path === "string") {
2088
- id += this.path;
2089
- }
2090
- else {
2091
- id += Object.values(this.path).join("@");
2092
- }
2093
- return {
2094
- type: "DocumentNotLoaded",
2095
- message: `Requested document "${id}" does not exist.`,
2096
- status: Status.bad_request,
2097
- };
2098
- }
2099
- /** Set defaults from constructor param `def`. */
2100
- set_defaults() {
2101
- if (this.data && this.def && !Array.isArray(this.def) && (typeof this.def === "object" || typeof this.def === "function")) {
2102
- const set_defaults = (obj, defaults) => {
2103
- Object.keys(defaults).forEach((key) => {
2104
- if (obj[key] === undefined) {
2105
- obj[key] = defaults[key];
2106
- }
2107
- else if (typeof obj[key] === "object" && !Array.isArray(obj[key]) && obj[key] != null &&
2108
- typeof defaults[key] === "object" && !Array.isArray(defaults[key]) && defaults[key] != null) {
2109
- set_defaults(obj[key], defaults[key]);
2110
- }
2111
- });
2112
- };
2113
- set_defaults(this.data, typeof this.def === "function" ? this.def() : this.def);
2114
- }
2115
- }
2116
- // ---------------------------------------------------------
2117
- // Callbacks.
2118
- /** On load callback.
2119
- * @note this is not called when default data is used for an empty document.
2120
- * @warning the user MUST always call this function after manually loading the document.
2121
- */
2122
- on_load() {
2123
- this.set_defaults();
2124
- }
2125
- /** Assert load. */
2126
- async assert_load() {
2127
- if (!this.data) {
2128
- await this.try_load();
2129
- this.assert_load();
2130
- }
2131
- }
2132
- /** Assert load */
2133
- assert_loaded() {
2134
- if (!this.data) {
2135
- throw new this.error_type(this.not_loaded_error());
2136
- }
2137
- }
2138
- /** Check if a project exists.
2139
- * @note this does not load the full document.
2140
- */
2141
- async exists() {
2142
- return await this.col.exists(this.uid, this.path);
2143
- }
2144
- /**
2145
- * Load a project from the database
2146
- * @param def the default value, when the default value is an object then the attributes will be checked / inserted as well.
2147
- */
2148
- async load() {
2149
- if (!await this.try_load() || !this.data) {
2150
- if (this.def) {
2151
- this.data = typeof this.def === "function" ? this.def() : this.def;
2152
- }
2153
- else {
2154
- throw new this.error_type(this.not_found_error());
2155
- }
2156
- }
2157
- return this.data;
2158
- }
2159
- async try_load() {
2160
- const data = await this.col.load(this.uid, this.path, { chunked: this.chunked });
2161
- if (!data) {
2162
- return;
2163
- }
2164
- this.data = data;
2165
- this.on_load();
2166
- return data;
2167
- }
2168
- /** Load partial by projection.
2169
- * @note This automatically inserts the new values when the document is loaded in this specific scenario it also calls the on load callback.
2170
- * @param fields The fields to load, nested fields should be separated by a dot (e.g. "a.b.c").
2171
- */
2172
- async load_partial(...fields) {
2173
- const data = await this.try_load_partial(...fields);
2174
- if (!data) {
2175
- throw new this.error_type(this.not_found_error());
2176
- }
2177
- return data;
2178
- }
2179
- async try_load_partial(...fields) {
2180
- const projection = {};
2181
- for (const field of fields) {
2182
- projection[field] = 1;
2183
- }
2184
- const data = await this.col.load(this.uid, this.path, { projection });
2185
- if (!data) {
2186
- return undefined;
2187
- }
2188
- if (this.data) {
2189
- UIDDocument.__insert_obj(this.data, data);
2190
- this.on_load();
2191
- }
2192
- return data;
2193
- }
2194
- /** Save the project to the database */
2195
- async save() {
2196
- if (!this.data) {
2197
- throw new this.error_type(this.not_loaded_error());
2198
- }
2199
- await this.col.save(this.uid, this.path, this.data, { chunked: this.chunked });
2200
- }
2201
- /** Save partial to the database
2202
- * @note automatically inserts the new values when the document is loaded.
2203
- */
2204
- async save_partial(partial_data) {
2205
- if (this.chunked) {
2206
- throw new this.error_type({
2207
- type: "UnsupportedDocumentOperation",
2208
- message: "Chunked documents do not support partial updates.",
2209
- status: Status.bad_request,
2210
- });
2211
- }
2212
- if (this.data && typeof partial_data === "object" && !Array.isArray(this.data) &&
2213
- partial_data && typeof partial_data === "object" && !Array.isArray(partial_data)) {
2214
- UIDDocument.__insert_obj(this.data, partial_data);
2215
- }
2216
- await this.col.save(this.uid, this.path, partial_data, { chunked: this.chunked });
2217
- }
2218
- /** Delete database record. */
2219
- async delete(opts) {
2220
- return this.col.delete(this.uid, this.path, {
2221
- ...opts,
2222
- chunked: this.chunked,
2223
- });
2224
- }
2225
- /** Wrapper function to insert an obj into another
2226
- * @note this is not a deep copy.
2227
- */
2228
- static __insert_obj(obj, partial) {
2229
- Object.keys(partial).forEach((key) => {
2230
- const val = partial[key];
2231
- // If both current value and new value are plain objects, recurse:
2232
- if (val !== null &&
2233
- typeof val === "object" &&
2234
- !Array.isArray(val) &&
2235
- obj[key] !== null &&
2236
- typeof obj[key] === "object" &&
2237
- !Array.isArray(obj[key])) {
2238
- UIDDocument.__insert_obj(obj[key], val);
2239
- }
2240
- else {
2241
- // Otherwise overwrite (including arrays, primitives, null, etc.)
2242
- obj[key] = val;
2243
- }
2244
- });
2245
- }
2246
- ;
2247
- }
2248
- // ---------------------------------------------------------
2249
- /**
2250
- * Document reference object. Its objectively an document without holding its data.
2251
- * Its more efficient to store that separately and use this to perform operations on it.
2252
- */
2253
- export class DocumentRef {
2254
- col;
2255
- uid;
2256
- path;
2257
- def;
2258
- chunked;
2259
- record_version;
2260
- error_type;
2261
- transform_version;
2262
- _on_load;
2263
- /** Constructor
2264
- * @param col The collection created by the server.
2265
- * @param uid The uid of the document, this is only required when the collection is a UIDCollection.
2266
- * @param path The path of the document, this can be a string or an object query.
2267
- * @param def The default value, when the default value is an object then the attributes will be checked / inserted as well.
2268
- * @param chunked If true then the document is stored in chunks.
2269
- * @param external_errors If true then the errors are thrown as external errors, instead of internal errors.
2270
- * @param record_version The record type version for the database.
2271
- * This can be used in combination with parameter `transform_version` to ...
2272
- * Transform older record versions to the current version.
2273
- * @param transform_version The function to transform an older document version to the current version.
2274
- * @param on_load The function to call when the document is loaded.
2275
- */
2276
- constructor({ col, uid, path, def, chunked = false, external_errors = false, record_version = 1, transform_version, on_load, }) {
2277
- this.col = col;
2278
- this.uid = uid;
2279
- this.path = path;
2280
- this.def = def;
2281
- this.chunked = chunked;
2282
- this.error_type = external_errors ? ExternalError : InternalError;
2283
- this.record_version = record_version;
2284
- this.transform_version = transform_version;
2285
- this._on_load = on_load;
2286
- // Check uid, also dont allow mistakes.
2287
- if (this.col instanceof UIDCollection && !this.uid) {
2288
- throw new this.error_type({
2289
- type: "InvalidDocumentRef",
2290
- message: "UIDCollection reference must have a uid.",
2291
- status: Status.bad_request,
2292
- });
2293
- }
2294
- if (this.col instanceof Collection && this.uid) {
2295
- throw new this.error_type({
2296
- type: "InvalidDocumentRef",
2297
- message: "Collection reference must not have a uid.",
2298
- status: Status.bad_request,
2299
- });
2300
- }
2301
- // Check transform.
2302
- if (this.record_version != 1 && !this.transform_version) {
2303
- throw new this.error_type({
2304
- type: "InvalidDocumentRef",
2305
- message: "Transform version must be set when record version is set.",
2306
- status: Status.bad_request,
2307
- });
2308
- }
2309
- }
2310
- /** Set defaults from constructor param `def`. */
2311
- set_defaults(data) {
2312
- if (data && this.def && !Array.isArray(this.def) && (typeof this.def === "object" || typeof this.def === "function")) {
2313
- const set_defaults = (obj, defaults) => {
2314
- Object.keys(defaults).forEach((key) => {
2315
- if (obj[key] === undefined) {
2316
- obj[key] = defaults[key];
2317
- }
2318
- else if (typeof obj[key] === "object" && !Array.isArray(obj[key]) && obj[key] != null &&
2319
- typeof defaults[key] === "object" && !Array.isArray(defaults[key]) && defaults[key] != null) {
2320
- set_defaults(obj[key], defaults[key]);
2321
- }
2322
- });
2323
- };
2324
- set_defaults(data, typeof this.def === "function" ? this.def() : this.def);
2325
- }
2326
- }
2327
- /** Get the computed default value, when defined. */
2328
- as_default() {
2329
- if (this.def) {
2330
- return typeof this.def === "function" ? this.def() : this.def;
2331
- }
2332
- }
2333
- /**
2334
- * On load callback.
2335
- * @note this is not called when default data is used for an empty document.
2336
- */
2337
- on_load(data) {
2338
- // Transform version.
2339
- if (this.record_version && data.__record_version !== 1) {
2340
- data = this.transform_version(this.record_version, data);
2341
- }
2342
- // Set defaults.
2343
- this.set_defaults(data);
2344
- // Call on load.
2345
- if (this._on_load) {
2346
- data = this._on_load(data);
2347
- }
2348
- // Response.
2349
- return data;
2350
- }
2351
- /** Check if a project exists.
2352
- * @note this does not load the full document.
2353
- */
2354
- async exists() {
2355
- if (this.col instanceof UIDCollection) {
2356
- return await this.col.exists(this.uid, this.path);
2357
- }
2358
- return await this.col.exists(this.path);
2359
- }
2360
- /**
2361
- * Load a project from the database
2362
- * @param def the default value, when the default value is an object then the attributes will be checked / inserted as well.
2363
- */
2364
- async load() {
2365
- const data = this.col instanceof UIDCollection
2366
- ? await this.col.load(this.uid, this.path, { chunked: this.chunked })
2367
- : await this.col.load(this.path, { chunked: this.chunked });
2368
- if (!data) {
2369
- if (this.def) {
2370
- return typeof this.def === "function" ? this.def() : this.def;
2371
- }
2372
- return;
2373
- }
2374
- return this.on_load(data);
2375
- }
2376
- /**
2377
- * Load partial by projection.
2378
- * @param fields The fields to load, nested fields should be separated by a dot (e.g. "a.b.c").
2379
- */
2380
- async load_partial(...fields) {
2381
- const projection = {};
2382
- for (const field of fields) {
2383
- projection[field] = 1;
2384
- }
2385
- return await (this.col instanceof UIDCollection
2386
- ? this.col.load(this.uid, this.path, { projection })
2387
- : this.col.load(this.path, { projection }));
2388
- }
2389
- /** Save the project to the database */
2390
- async save(data) {
2391
- data.__record_version = this.record_version;
2392
- return (this.col instanceof UIDCollection
2393
- ? this.col.save(this.uid, this.path, data, { chunked: this.chunked })
2394
- : this.col.save(this.path, data, { chunked: this.chunked }));
2395
- }
2396
- /** Save partial to the database
2397
- * @note automatically inserts the new values when the document is loaded.
2398
- */
2399
- async save_partial(partial_data) {
2400
- if (this.chunked) {
2401
- throw new this.error_type({
2402
- type: "UnsupportedDocumentOperation",
2403
- message: "Chunked documents do not support partial updates.",
2404
- status: Status.bad_request,
2405
- });
2406
- }
2407
- return (this.col instanceof UIDCollection
2408
- ? this.col.save(this.uid, this.path, partial_data, { chunked: this.chunked })
2409
- : this.col.save(this.path, partial_data, { chunked: this.chunked }));
2410
- }
2411
- /** Delete database record. */
2412
- async delete(opts) {
2413
- return (this.col instanceof UIDCollection
2414
- ? this.col.delete(this.uid, this.path, {
2415
- ...opts,
2416
- chunked: this.chunked,
2417
- })
2418
- : this.col.delete(this.path, {
2419
- ...opts,
2420
- chunked: this.chunked,
2421
- }));
2422
- }
2423
- }