mongoku 2.9.2 → 2.10.0-compat

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 (458) hide show
  1. package/build/client/_app/immutable/assets/0.D8aXA7G5.css +1 -0
  2. package/build/client/_app/immutable/assets/0.D8aXA7G5.css.br +0 -0
  3. package/build/client/_app/immutable/assets/0.D8aXA7G5.css.gz +0 -0
  4. package/build/client/_app/immutable/assets/10.-WSj0hXT.css +1 -0
  5. package/build/client/_app/immutable/assets/10.-WSj0hXT.css.br +1 -0
  6. package/build/client/_app/immutable/assets/10.-WSj0hXT.css.gz +0 -0
  7. package/build/client/_app/immutable/assets/16.BpmHh9U0.css +1 -0
  8. package/build/client/_app/immutable/assets/16.BpmHh9U0.css.br +0 -0
  9. package/build/client/_app/immutable/assets/16.BpmHh9U0.css.gz +0 -0
  10. package/build/client/_app/immutable/chunks/-8z-rXzu.js +1 -0
  11. package/build/client/_app/immutable/chunks/-8z-rXzu.js.br +0 -0
  12. package/build/client/_app/immutable/chunks/-8z-rXzu.js.gz +0 -0
  13. package/build/client/_app/immutable/chunks/ADrS3reX.js +1 -0
  14. package/build/client/_app/immutable/chunks/ADrS3reX.js.br +0 -0
  15. package/build/client/_app/immutable/chunks/ADrS3reX.js.gz +0 -0
  16. package/build/client/_app/immutable/chunks/B3A9hx44.js +1 -0
  17. package/build/client/_app/immutable/chunks/B3A9hx44.js.br +0 -0
  18. package/build/client/_app/immutable/chunks/B3A9hx44.js.gz +0 -0
  19. package/build/client/_app/immutable/chunks/B48saTbS.js +1 -0
  20. package/build/client/_app/immutable/chunks/B48saTbS.js.br +0 -0
  21. package/build/client/_app/immutable/chunks/B48saTbS.js.gz +0 -0
  22. package/build/client/_app/immutable/chunks/{IixngxlS.js → BoF-bMzh.js} +2 -2
  23. package/build/client/_app/immutable/chunks/BoF-bMzh.js.br +0 -0
  24. package/build/client/_app/immutable/chunks/BoF-bMzh.js.gz +0 -0
  25. package/build/client/_app/immutable/chunks/C5BvtFsa.js +1 -0
  26. package/build/client/_app/immutable/chunks/C5BvtFsa.js.br +0 -0
  27. package/build/client/_app/immutable/chunks/C5BvtFsa.js.gz +0 -0
  28. package/build/client/_app/immutable/chunks/C5dXZyme.js +1 -0
  29. package/build/client/_app/immutable/chunks/C5dXZyme.js.br +0 -0
  30. package/build/client/_app/immutable/chunks/C5dXZyme.js.gz +0 -0
  31. package/build/client/_app/immutable/chunks/CUBPtF8t.js +65 -0
  32. package/build/client/_app/immutable/chunks/CUBPtF8t.js.br +0 -0
  33. package/build/client/_app/immutable/chunks/CUBPtF8t.js.gz +0 -0
  34. package/build/client/_app/immutable/chunks/{9xpgPu5N.js → Cf6RCjfg.js} +1 -1
  35. package/build/client/_app/immutable/chunks/Cf6RCjfg.js.br +0 -0
  36. package/build/client/_app/immutable/chunks/Cf6RCjfg.js.gz +0 -0
  37. package/build/client/_app/immutable/chunks/CrLGr586.js +2 -0
  38. package/build/client/_app/immutable/chunks/CrLGr586.js.br +0 -0
  39. package/build/client/_app/immutable/chunks/CrLGr586.js.gz +0 -0
  40. package/build/client/_app/immutable/chunks/CsbWzWJI.js +1 -0
  41. package/build/client/_app/immutable/chunks/CsbWzWJI.js.br +0 -0
  42. package/build/client/_app/immutable/chunks/CsbWzWJI.js.gz +0 -0
  43. package/build/client/_app/immutable/chunks/CyTV7fHl.js +1 -0
  44. package/build/client/_app/immutable/chunks/CyTV7fHl.js.br +0 -0
  45. package/build/client/_app/immutable/chunks/CyTV7fHl.js.gz +0 -0
  46. package/build/client/_app/immutable/chunks/{DCAtHodH.js → D3UCTJm-.js} +2 -2
  47. package/build/client/_app/immutable/chunks/D3UCTJm-.js.br +0 -0
  48. package/build/client/_app/immutable/chunks/D3UCTJm-.js.gz +0 -0
  49. package/build/client/_app/immutable/chunks/{Dzt_TFtX.js → DH7nqg5-.js} +1 -1
  50. package/build/client/_app/immutable/chunks/DH7nqg5-.js.br +0 -0
  51. package/build/client/_app/immutable/chunks/DH7nqg5-.js.gz +0 -0
  52. package/build/client/_app/immutable/chunks/DKMyRjux.js +1 -0
  53. package/build/client/_app/immutable/chunks/DKMyRjux.js.br +0 -0
  54. package/build/client/_app/immutable/chunks/DKMyRjux.js.gz +0 -0
  55. package/build/client/_app/immutable/chunks/DO0gnjpd.js +1 -0
  56. package/build/client/_app/immutable/chunks/DO0gnjpd.js.br +0 -0
  57. package/build/client/_app/immutable/chunks/DO0gnjpd.js.gz +0 -0
  58. package/build/client/_app/immutable/chunks/DVIi8uNn.js +1 -0
  59. package/build/client/_app/immutable/chunks/DVIi8uNn.js.br +0 -0
  60. package/build/client/_app/immutable/chunks/DVIi8uNn.js.gz +0 -0
  61. package/build/client/_app/immutable/chunks/Dc47-4iR.js +1 -0
  62. package/build/client/_app/immutable/chunks/Dc47-4iR.js.br +0 -0
  63. package/build/client/_app/immutable/chunks/Dc47-4iR.js.gz +0 -0
  64. package/build/client/_app/immutable/chunks/{CTk2PBcX.js → Dcgd1m6P.js} +1 -1
  65. package/build/client/_app/immutable/chunks/Dcgd1m6P.js.br +0 -0
  66. package/build/client/_app/immutable/chunks/Dcgd1m6P.js.gz +0 -0
  67. package/build/client/_app/immutable/chunks/Ddz9xOa-.js +1 -0
  68. package/build/client/_app/immutable/chunks/Ddz9xOa-.js.br +0 -0
  69. package/build/client/_app/immutable/chunks/Ddz9xOa-.js.gz +0 -0
  70. package/build/client/_app/immutable/chunks/{IwGwbOe7.js → DfW1b8bA.js} +1 -1
  71. package/build/client/_app/immutable/chunks/DfW1b8bA.js.br +0 -0
  72. package/build/client/_app/immutable/chunks/{IwGwbOe7.js.gz → DfW1b8bA.js.gz} +0 -0
  73. package/build/client/_app/immutable/chunks/Dfjkeakv.js +1 -0
  74. package/build/client/_app/immutable/chunks/Dfjkeakv.js.br +0 -0
  75. package/build/client/_app/immutable/chunks/Dfjkeakv.js.gz +0 -0
  76. package/build/client/_app/immutable/chunks/{ChWGK2Ce.js → DgwByHCB.js} +1 -1
  77. package/build/client/_app/immutable/chunks/DgwByHCB.js.br +0 -0
  78. package/build/client/_app/immutable/chunks/DgwByHCB.js.gz +0 -0
  79. package/build/client/_app/immutable/chunks/{v8XDA7ui.js → DlVaABeK.js} +3 -3
  80. package/build/client/_app/immutable/chunks/DlVaABeK.js.br +0 -0
  81. package/build/client/_app/immutable/chunks/DlVaABeK.js.gz +0 -0
  82. package/build/client/_app/immutable/chunks/DupjJGFi.js +1 -0
  83. package/build/client/_app/immutable/chunks/DupjJGFi.js.br +0 -0
  84. package/build/client/_app/immutable/chunks/DupjJGFi.js.gz +0 -0
  85. package/build/client/_app/immutable/chunks/DymqlScG.js +1 -0
  86. package/build/client/_app/immutable/chunks/DymqlScG.js.br +0 -0
  87. package/build/client/_app/immutable/chunks/DymqlScG.js.gz +0 -0
  88. package/build/client/_app/immutable/chunks/{Z7BFksgg.js → J9ZSs_8c.js} +1 -1
  89. package/build/client/_app/immutable/chunks/J9ZSs_8c.js.br +0 -0
  90. package/build/client/_app/immutable/chunks/J9ZSs_8c.js.gz +0 -0
  91. package/build/client/_app/immutable/chunks/{CKvueigk.js → OvZJ6gNJ.js} +1 -1
  92. package/build/client/_app/immutable/chunks/OvZJ6gNJ.js.br +0 -0
  93. package/build/client/_app/immutable/chunks/OvZJ6gNJ.js.gz +0 -0
  94. package/build/client/_app/immutable/chunks/URA3nPWG.js +1 -0
  95. package/build/client/_app/immutable/chunks/URA3nPWG.js.br +0 -0
  96. package/build/client/_app/immutable/chunks/URA3nPWG.js.gz +0 -0
  97. package/build/client/_app/immutable/chunks/bZzTqofF.js +1 -0
  98. package/build/client/_app/immutable/chunks/bZzTqofF.js.br +0 -0
  99. package/build/client/_app/immutable/chunks/bZzTqofF.js.gz +0 -0
  100. package/build/client/_app/immutable/chunks/oSuzXE6i.js +1 -0
  101. package/build/client/_app/immutable/chunks/oSuzXE6i.js.br +0 -0
  102. package/build/client/_app/immutable/chunks/oSuzXE6i.js.gz +0 -0
  103. package/build/client/_app/immutable/chunks/wZh6TcLb.js +2 -0
  104. package/build/client/_app/immutable/chunks/wZh6TcLb.js.br +0 -0
  105. package/build/client/_app/immutable/chunks/wZh6TcLb.js.gz +0 -0
  106. package/build/client/_app/immutable/entry/app.G0Hwsu0f.js +2 -0
  107. package/build/client/_app/immutable/entry/app.G0Hwsu0f.js.br +0 -0
  108. package/build/client/_app/immutable/entry/app.G0Hwsu0f.js.gz +0 -0
  109. package/build/client/_app/immutable/entry/start.pOs5gHaO.js +1 -0
  110. package/build/client/_app/immutable/entry/start.pOs5gHaO.js.br +0 -0
  111. package/build/client/_app/immutable/entry/start.pOs5gHaO.js.gz +0 -0
  112. package/build/client/_app/immutable/nodes/0.BPw_KPrY.js +1 -0
  113. package/build/client/_app/immutable/nodes/0.BPw_KPrY.js.br +0 -0
  114. package/build/client/_app/immutable/nodes/0.BPw_KPrY.js.gz +0 -0
  115. package/build/client/_app/immutable/nodes/1.eWL7yJRK.js +1 -0
  116. package/build/client/_app/immutable/nodes/1.eWL7yJRK.js.br +4 -0
  117. package/build/client/_app/immutable/nodes/1.eWL7yJRK.js.gz +0 -0
  118. package/build/client/_app/immutable/nodes/10.AwBSgK4-.js +2 -0
  119. package/build/client/_app/immutable/nodes/10.AwBSgK4-.js.br +0 -0
  120. package/build/client/_app/immutable/nodes/10.AwBSgK4-.js.gz +0 -0
  121. package/build/client/_app/immutable/nodes/11.DS8hIvI2.js +6 -0
  122. package/build/client/_app/immutable/nodes/11.DS8hIvI2.js.br +0 -0
  123. package/build/client/_app/immutable/nodes/11.DS8hIvI2.js.gz +0 -0
  124. package/build/client/_app/immutable/nodes/{12.CuCxLKQr.js → 12.DP-oGzlU.js} +1 -1
  125. package/build/client/_app/immutable/nodes/12.DP-oGzlU.js.br +0 -0
  126. package/build/client/_app/immutable/nodes/12.DP-oGzlU.js.gz +0 -0
  127. package/build/client/_app/immutable/nodes/13.DCNBPtGq.js +1 -0
  128. package/build/client/_app/immutable/nodes/13.DCNBPtGq.js.br +0 -0
  129. package/build/client/_app/immutable/nodes/13.DCNBPtGq.js.gz +0 -0
  130. package/build/client/_app/immutable/nodes/14.B3qXj1Pz.js +65 -0
  131. package/build/client/_app/immutable/nodes/14.B3qXj1Pz.js.br +0 -0
  132. package/build/client/_app/immutable/nodes/14.B3qXj1Pz.js.gz +0 -0
  133. package/build/client/_app/immutable/nodes/15.DFTrPy3K.js +1 -0
  134. package/build/client/_app/immutable/nodes/15.DFTrPy3K.js.br +0 -0
  135. package/build/client/_app/immutable/nodes/15.DFTrPy3K.js.gz +0 -0
  136. package/build/client/_app/immutable/nodes/16.wrfG8awE.js +1 -0
  137. package/build/client/_app/immutable/nodes/16.wrfG8awE.js.br +0 -0
  138. package/build/client/_app/immutable/nodes/16.wrfG8awE.js.gz +0 -0
  139. package/build/client/_app/immutable/nodes/{2.Bai-TIgH.js → 2.6jE8uEJq.js} +1 -1
  140. package/build/client/_app/immutable/nodes/2.6jE8uEJq.js.br +0 -0
  141. package/build/client/_app/immutable/nodes/2.6jE8uEJq.js.gz +0 -0
  142. package/build/client/_app/immutable/nodes/{3.ev9oAmrG.js → 3.C59rlT3p.js} +1 -1
  143. package/build/client/_app/immutable/nodes/3.C59rlT3p.js.br +0 -0
  144. package/build/client/_app/immutable/nodes/3.C59rlT3p.js.gz +0 -0
  145. package/build/client/_app/immutable/nodes/4.DbZo8waJ.js +1 -0
  146. package/build/client/_app/immutable/nodes/4.DbZo8waJ.js.br +0 -0
  147. package/build/client/_app/immutable/nodes/4.DbZo8waJ.js.gz +0 -0
  148. package/build/client/_app/immutable/nodes/{5.CyK0fI1l.js → 5.Cu8LcB5H.js} +1 -1
  149. package/build/client/_app/immutable/nodes/5.Cu8LcB5H.js.br +0 -0
  150. package/build/client/_app/immutable/nodes/5.Cu8LcB5H.js.gz +0 -0
  151. package/build/client/_app/immutable/nodes/7.BSMf3Keu.js +1 -0
  152. package/build/client/_app/immutable/nodes/7.BSMf3Keu.js.br +0 -0
  153. package/build/client/_app/immutable/nodes/7.BSMf3Keu.js.gz +0 -0
  154. package/build/client/_app/immutable/nodes/8.CmQOYs57.js +2 -0
  155. package/build/client/_app/immutable/nodes/8.CmQOYs57.js.br +0 -0
  156. package/build/client/_app/immutable/nodes/8.CmQOYs57.js.gz +0 -0
  157. package/build/client/_app/immutable/nodes/9.6ZB3-a4j.js +1 -0
  158. package/build/client/_app/immutable/nodes/9.6ZB3-a4j.js.br +0 -0
  159. package/build/client/_app/immutable/nodes/9.6ZB3-a4j.js.gz +0 -0
  160. package/build/client/_app/version.json +1 -1
  161. package/build/client/_app/version.json.br +0 -0
  162. package/build/client/_app/version.json.gz +0 -0
  163. package/build/server/chunks/0-2tDL-Z_M.js +32 -0
  164. package/build/server/chunks/0-2tDL-Z_M.js.map +1 -0
  165. package/build/server/chunks/1-L1YRtIEr.js +9 -0
  166. package/build/server/chunks/{1-lx7f4PWt.js.map → 1-L1YRtIEr.js.map} +1 -1
  167. package/build/server/chunks/10-kSTe-NQK.js +43 -0
  168. package/build/server/chunks/10-kSTe-NQK.js.map +1 -0
  169. package/build/server/chunks/{11-BEDQUU1_.js → 11-BSFyIooa.js} +5 -24
  170. package/build/server/chunks/11-BSFyIooa.js.map +1 -0
  171. package/build/server/chunks/{12-CzhXMlU9.js → 12-DhN9fz9p.js} +4 -5
  172. package/build/server/chunks/12-DhN9fz9p.js.map +1 -0
  173. package/build/server/chunks/{13-D1eLiA_r.js → 13-B1mdDktE.js} +5 -24
  174. package/build/server/chunks/13-B1mdDktE.js.map +1 -0
  175. package/build/server/chunks/14-G2fvhIG4.js +38 -0
  176. package/build/server/chunks/14-G2fvhIG4.js.map +1 -0
  177. package/build/server/chunks/15-BxHbA5Ao.js +48 -0
  178. package/build/server/chunks/15-BxHbA5Ao.js.map +1 -0
  179. package/build/server/chunks/16-D0Gv3LNT.js +46 -0
  180. package/build/server/chunks/16-D0Gv3LNT.js.map +1 -0
  181. package/build/server/chunks/{2-ckJpvP-Z.js → 2-DGpX4fMQ.js} +2 -2
  182. package/build/server/chunks/{2-ckJpvP-Z.js.map → 2-DGpX4fMQ.js.map} +1 -1
  183. package/build/server/chunks/{3-TPjZ0P0_.js → 3-CwHfLh5P.js} +2 -2
  184. package/build/server/chunks/{3-TPjZ0P0_.js.map → 3-CwHfLh5P.js.map} +1 -1
  185. package/build/server/chunks/{4-DoW1zEiI.js → 4-B5F5-cxe.js} +10 -2
  186. package/build/server/chunks/4-B5F5-cxe.js.map +1 -0
  187. package/build/server/chunks/{5-cZ6VD-C-.js → 5-CxqBB_6c.js} +2 -2
  188. package/build/server/chunks/{5-cZ6VD-C-.js.map → 5-CxqBB_6c.js.map} +1 -1
  189. package/build/server/chunks/{6-eXO6RVDu.js → 6-Qus887OP.js} +3 -2
  190. package/build/server/chunks/{6-eXO6RVDu.js.map → 6-Qus887OP.js.map} +1 -1
  191. package/build/server/chunks/{7-BmJzLrSm.js → 7-BNgFbh-a.js} +6 -5
  192. package/build/server/chunks/{7-BmJzLrSm.js.map → 7-BNgFbh-a.js.map} +1 -1
  193. package/build/server/chunks/{8-Ba9OHB5H.js → 8-DOgOgmwJ.js} +4 -5
  194. package/build/server/chunks/8-DOgOgmwJ.js.map +1 -0
  195. package/build/server/chunks/{9-DSgRe_DY.js → 9-D-PO69az.js} +4 -5
  196. package/build/server/chunks/9-D-PO69az.js.map +1 -0
  197. package/build/server/chunks/IconChevronDown-D8V4kB6o.js +10 -0
  198. package/build/server/chunks/IconChevronDown-D8V4kB6o.js.map +1 -0
  199. package/build/server/chunks/{JsonValue-CGVfzyTL.js → JsonValue-B-iqFShN.js} +4 -3
  200. package/build/server/chunks/JsonValue-B-iqFShN.js.map +1 -0
  201. package/build/server/chunks/{Modal-D2E5OLRi.js → Modal-D10te4nR.js} +2 -2
  202. package/build/server/chunks/Modal-D10te4nR.js.map +1 -0
  203. package/build/server/chunks/{Panel-C6VWd6JD.js → Panel-CBztHh2Y.js} +2 -2
  204. package/build/server/chunks/Panel-CBztHh2Y.js.map +1 -0
  205. package/build/server/chunks/{PrettyJson-Bo4UtQ1o.js → PrettyJson-Dz5fCjPq.js} +6 -6
  206. package/build/server/chunks/PrettyJson-Dz5fCjPq.js.map +1 -0
  207. package/build/server/chunks/{Tooltip-OVylvwfb.js → Tooltip-BHX9gIpe.js} +2 -2
  208. package/build/server/chunks/Tooltip-BHX9gIpe.js.map +1 -0
  209. package/build/server/chunks/{TooltipTable-CLglfpck.js → TooltipTable-BIwNd3UB.js} +3 -3
  210. package/build/server/chunks/TooltipTable-BIwNd3UB.js.map +1 -0
  211. package/build/server/chunks/{_layout.svelte-CLPxHDiP.js → _layout.svelte-BX5H_goi.js} +38 -15
  212. package/build/server/chunks/_layout.svelte-BX5H_goi.js.map +1 -0
  213. package/build/server/chunks/{_page.svelte-zD7qndty.js → _page.svelte-Bh6uDLz6.js} +15 -15
  214. package/build/server/chunks/_page.svelte-Bh6uDLz6.js.map +1 -0
  215. package/build/server/chunks/_page.svelte-CHqJAnyH.js +258 -0
  216. package/build/server/chunks/_page.svelte-CHqJAnyH.js.map +1 -0
  217. package/build/server/chunks/{_page.svelte-CPcgVZQj.js → _page.svelte-CsCyoCpn.js} +15 -15
  218. package/build/server/chunks/_page.svelte-CsCyoCpn.js.map +1 -0
  219. package/build/server/chunks/{_page.svelte-CAAPpbun.js → _page.svelte-Cwyc6wIg.js} +14 -14
  220. package/build/server/chunks/_page.svelte-Cwyc6wIg.js.map +1 -0
  221. package/build/server/chunks/{_page.svelte-e5wWk327.js → _page.svelte-DE0XWW__.js} +12 -12
  222. package/build/server/chunks/_page.svelte-DE0XWW__.js.map +1 -0
  223. package/build/server/chunks/{_page.svelte-DVjTn-ck.js → _page.svelte-DIe5tQ3z.js} +14 -14
  224. package/build/server/chunks/_page.svelte-DIe5tQ3z.js.map +1 -0
  225. package/build/server/chunks/{_page.svelte-C3QVwl-z.js → _page.svelte-DT0U0FvS.js} +5 -4
  226. package/build/server/chunks/_page.svelte-DT0U0FvS.js.map +1 -0
  227. package/build/server/chunks/{_page.svelte-C_GX0K8M.js → _page.svelte-YOsljIow.js} +19 -22
  228. package/build/server/chunks/_page.svelte-YOsljIow.js.map +1 -0
  229. package/build/server/chunks/{_page.svelte-BeiSosXN.js → _page.svelte-aEFurJZ0.js} +55 -15
  230. package/build/server/chunks/_page.svelte-aEFurJZ0.js.map +1 -0
  231. package/build/server/chunks/{_page.svelte-CkZUu9Wh.js → _page.svelte-vWYc1vOs.js} +9 -9
  232. package/build/server/chunks/_page.svelte-vWYc1vOs.js.map +1 -0
  233. package/build/server/chunks/{_server.ts-i-glbZtX.js → _server.ts-BTmpua-U.js} +4 -3
  234. package/build/server/chunks/{_server.ts-i-glbZtX.js.map → _server.ts-BTmpua-U.js.map} +1 -1
  235. package/build/server/chunks/{_server.ts-CEBmCzTO.js → _server.ts-BhWrvCAV.js} +4 -3
  236. package/build/server/chunks/{_server.ts-CEBmCzTO.js.map → _server.ts-BhWrvCAV.js.map} +1 -1
  237. package/build/server/chunks/{_server.ts-CoUHVeKI.js → _server.ts-CUj-HfCf.js} +4 -3
  238. package/build/server/chunks/{_server.ts-CoUHVeKI.js.map → _server.ts-CUj-HfCf.js.map} +1 -1
  239. package/build/server/chunks/client-DrDUOhf5.js +7 -0
  240. package/build/server/chunks/{client-COtw9Xqw.js.map → client-DrDUOhf5.js.map} +1 -1
  241. package/build/server/chunks/{client2-BIa3wTXU.js → client2-Birk_77A.js} +4 -4
  242. package/build/server/chunks/{client2-BIa3wTXU.js.map → client2-Birk_77A.js.map} +1 -1
  243. package/build/server/chunks/error.svelte-DisWvlhZ.js +19 -0
  244. package/build/server/chunks/error.svelte-DisWvlhZ.js.map +1 -0
  245. package/build/server/chunks/{filters-B3U8Nh9P.js → filters-BTgp9cdC.js} +4 -7
  246. package/build/server/chunks/filters-BTgp9cdC.js.map +1 -0
  247. package/build/server/chunks/{hooks.server-BiUSRqj1.js → hooks.server-Cc7EKf-Z.js} +4 -3
  248. package/build/server/chunks/{hooks.server-BiUSRqj1.js.map → hooks.server-Cc7EKf-Z.js.map} +1 -1
  249. package/build/server/chunks/{index-CtYzvcG6.js → index-CDf-jMhD.js} +3 -2
  250. package/build/server/chunks/index-CDf-jMhD.js.map +1 -0
  251. package/build/server/chunks/{index2-B0RgZaJY.js → index2-DNcGQp0K.js} +3 -3
  252. package/build/server/chunks/index2-DNcGQp0K.js.map +1 -0
  253. package/build/server/chunks/{mongo-B92d7zNj.js → mongo-Du0OjH5b.js} +257 -24
  254. package/build/server/chunks/mongo-Du0OjH5b.js.map +1 -0
  255. package/build/server/chunks/{oauth-D6jTWKFd.js → oauth-CyIuK65I.js} +2 -2
  256. package/build/server/chunks/{oauth-D6jTWKFd.js.map → oauth-CyIuK65I.js.map} +1 -1
  257. package/build/server/chunks/{remote-xxtqbu-CDChJkWc.js → remote-xxtqbu-BCjbN3T4.js} +6 -6
  258. package/build/server/chunks/remote-xxtqbu-BCjbN3T4.js.map +1 -0
  259. package/build/server/chunks/renderer-wJWkLEmh.js +1844 -0
  260. package/build/server/chunks/renderer-wJWkLEmh.js.map +1 -0
  261. package/build/server/chunks/{root-otUAnOAR.js → root-Bs42DBih.js} +12 -1849
  262. package/build/server/chunks/root-Bs42DBih.js.map +1 -0
  263. package/build/server/chunks/{routing-EDfUNu8L.js → routing-CJRzZHIr.js} +2 -2
  264. package/build/server/chunks/{routing-EDfUNu8L.js.map → routing-CJRzZHIr.js.map} +1 -1
  265. package/build/server/chunks/{server2-D_y4YbpC.js → server2-B0ZXRoOj.js} +3 -3
  266. package/build/server/chunks/{server2-D_y4YbpC.js.map → server2-B0ZXRoOj.js.map} +1 -1
  267. package/build/server/chunks/{servers.remote-CGenkEHX.js → servers.remote-Bise-7j4.js} +5 -14
  268. package/build/server/chunks/servers.remote-Bise-7j4.js.map +1 -0
  269. package/build/server/chunks/shardKey-BnXqfB_r.js +11 -0
  270. package/build/server/chunks/shardKey-BnXqfB_r.js.map +1 -0
  271. package/build/server/chunks/{shared-DlqhoNLb.js → shared-BJTImRjE.js} +3 -2
  272. package/build/server/chunks/{shared-DlqhoNLb.js.map → shared-BJTImRjE.js.map} +1 -1
  273. package/build/server/chunks/{state.svelte-Bj5yxNNk.js → state.svelte-YUn1p3EK.js} +3 -2
  274. package/build/server/chunks/{state.svelte-Bj5yxNNk.js.map → state.svelte-YUn1p3EK.js.map} +1 -1
  275. package/build/server/index.js +7 -6
  276. package/build/server/index.js.map +1 -1
  277. package/build/server/manifest.js +29 -21
  278. package/build/server/manifest.js.map +1 -1
  279. package/package.json +1 -1
  280. package/src/api/servers.remote.ts +3 -12
  281. package/src/lib/collectionCategories.ts +25 -0
  282. package/src/lib/components/PageSwitcher.svelte +74 -6
  283. package/src/lib/components/ShardBadge.svelte +65 -0
  284. package/src/lib/server/connectionString.ts +50 -0
  285. package/src/lib/server/mongo.ts +208 -37
  286. package/src/lib/types.ts +34 -0
  287. package/src/lib/utils/filters.ts +5 -7
  288. package/src/lib/utils/mongoUri.ts +164 -0
  289. package/src/lib/utils/shardKey.ts +16 -0
  290. package/src/routes/servers/+page.svelte +1 -1
  291. package/src/routes/servers/[server]/databases/[database]/collections/+page.server.ts +5 -0
  292. package/src/routes/servers/[server]/databases/[database]/collections/+page.svelte +47 -9
  293. package/src/routes/servers/[server]/databases/[database]/collections/[collection]/+layout.ts +3 -0
  294. package/src/routes/servers/[server]/databases/[database]/collections/[collection]/sharding/+page.server.ts +26 -0
  295. package/src/routes/servers/[server]/databases/[database]/collections/[collection]/sharding/+page.svelte +319 -0
  296. package/src/tests/server/connectionString.test.ts +108 -0
  297. package/build/client/_app/immutable/assets/0.DTh4C4pw.css +0 -1
  298. package/build/client/_app/immutable/assets/0.DTh4C4pw.css.br +0 -0
  299. package/build/client/_app/immutable/assets/0.DTh4C4pw.css.gz +0 -0
  300. package/build/client/_app/immutable/chunks/8tf5Lvl3.js +0 -1
  301. package/build/client/_app/immutable/chunks/8tf5Lvl3.js.br +0 -0
  302. package/build/client/_app/immutable/chunks/8tf5Lvl3.js.gz +0 -0
  303. package/build/client/_app/immutable/chunks/951V-MIZ.js +0 -1
  304. package/build/client/_app/immutable/chunks/951V-MIZ.js.br +0 -0
  305. package/build/client/_app/immutable/chunks/951V-MIZ.js.gz +0 -0
  306. package/build/client/_app/immutable/chunks/9xpgPu5N.js.br +0 -0
  307. package/build/client/_app/immutable/chunks/9xpgPu5N.js.gz +0 -0
  308. package/build/client/_app/immutable/chunks/BDGd1aqF.js +0 -2
  309. package/build/client/_app/immutable/chunks/BDGd1aqF.js.br +0 -0
  310. package/build/client/_app/immutable/chunks/BDGd1aqF.js.gz +0 -0
  311. package/build/client/_app/immutable/chunks/BN_N9-2s.js +0 -1
  312. package/build/client/_app/immutable/chunks/BN_N9-2s.js.br +0 -0
  313. package/build/client/_app/immutable/chunks/BN_N9-2s.js.gz +0 -0
  314. package/build/client/_app/immutable/chunks/BUO1EOQu.js +0 -1
  315. package/build/client/_app/immutable/chunks/BUO1EOQu.js.br +0 -0
  316. package/build/client/_app/immutable/chunks/BUO1EOQu.js.gz +0 -0
  317. package/build/client/_app/immutable/chunks/BiVfO0yo.js +0 -1
  318. package/build/client/_app/immutable/chunks/BiVfO0yo.js.br +0 -0
  319. package/build/client/_app/immutable/chunks/BiVfO0yo.js.gz +0 -0
  320. package/build/client/_app/immutable/chunks/C6P2UOyZ.js +0 -1
  321. package/build/client/_app/immutable/chunks/C6P2UOyZ.js.br +0 -0
  322. package/build/client/_app/immutable/chunks/C6P2UOyZ.js.gz +0 -0
  323. package/build/client/_app/immutable/chunks/CCOVnadf.js +0 -1
  324. package/build/client/_app/immutable/chunks/CCOVnadf.js.br +0 -0
  325. package/build/client/_app/immutable/chunks/CCOVnadf.js.gz +0 -0
  326. package/build/client/_app/immutable/chunks/CKvueigk.js.br +0 -0
  327. package/build/client/_app/immutable/chunks/CKvueigk.js.gz +0 -0
  328. package/build/client/_app/immutable/chunks/CQE8d3kg.js +0 -1
  329. package/build/client/_app/immutable/chunks/CQE8d3kg.js.br +0 -0
  330. package/build/client/_app/immutable/chunks/CQE8d3kg.js.gz +0 -0
  331. package/build/client/_app/immutable/chunks/CTk2PBcX.js.br +0 -0
  332. package/build/client/_app/immutable/chunks/CTk2PBcX.js.gz +0 -0
  333. package/build/client/_app/immutable/chunks/ChWGK2Ce.js.br +0 -0
  334. package/build/client/_app/immutable/chunks/ChWGK2Ce.js.gz +0 -0
  335. package/build/client/_app/immutable/chunks/CkMoyTwc.js +0 -1
  336. package/build/client/_app/immutable/chunks/CkMoyTwc.js.br +0 -0
  337. package/build/client/_app/immutable/chunks/CkMoyTwc.js.gz +0 -0
  338. package/build/client/_app/immutable/chunks/CmI1igJD.js +0 -1
  339. package/build/client/_app/immutable/chunks/CmI1igJD.js.br +0 -0
  340. package/build/client/_app/immutable/chunks/CmI1igJD.js.gz +0 -0
  341. package/build/client/_app/immutable/chunks/DCAtHodH.js.br +0 -0
  342. package/build/client/_app/immutable/chunks/DCAtHodH.js.gz +0 -0
  343. package/build/client/_app/immutable/chunks/DFXj4NOH.js +0 -1
  344. package/build/client/_app/immutable/chunks/DFXj4NOH.js.br +0 -0
  345. package/build/client/_app/immutable/chunks/DFXj4NOH.js.gz +0 -0
  346. package/build/client/_app/immutable/chunks/DaMh_eeB.js +0 -1
  347. package/build/client/_app/immutable/chunks/DaMh_eeB.js.br +0 -0
  348. package/build/client/_app/immutable/chunks/DaMh_eeB.js.gz +0 -0
  349. package/build/client/_app/immutable/chunks/DqxUmOYD.js +0 -66
  350. package/build/client/_app/immutable/chunks/DqxUmOYD.js.br +0 -0
  351. package/build/client/_app/immutable/chunks/DqxUmOYD.js.gz +0 -0
  352. package/build/client/_app/immutable/chunks/Dzt_TFtX.js.br +0 -0
  353. package/build/client/_app/immutable/chunks/Dzt_TFtX.js.gz +0 -0
  354. package/build/client/_app/immutable/chunks/IixngxlS.js.br +0 -0
  355. package/build/client/_app/immutable/chunks/IixngxlS.js.gz +0 -0
  356. package/build/client/_app/immutable/chunks/IwGwbOe7.js.br +0 -0
  357. package/build/client/_app/immutable/chunks/YMZQSnF3.js +0 -1
  358. package/build/client/_app/immutable/chunks/YMZQSnF3.js.br +0 -0
  359. package/build/client/_app/immutable/chunks/YMZQSnF3.js.gz +0 -0
  360. package/build/client/_app/immutable/chunks/Z7BFksgg.js.br +0 -0
  361. package/build/client/_app/immutable/chunks/Z7BFksgg.js.gz +0 -0
  362. package/build/client/_app/immutable/chunks/dlHwFtkV.js +0 -1
  363. package/build/client/_app/immutable/chunks/dlHwFtkV.js.br +0 -0
  364. package/build/client/_app/immutable/chunks/dlHwFtkV.js.gz +0 -0
  365. package/build/client/_app/immutable/chunks/v8XDA7ui.js.br +0 -0
  366. package/build/client/_app/immutable/chunks/v8XDA7ui.js.gz +0 -0
  367. package/build/client/_app/immutable/entry/app.B1EvSYDg.js +0 -2
  368. package/build/client/_app/immutable/entry/app.B1EvSYDg.js.br +0 -0
  369. package/build/client/_app/immutable/entry/app.B1EvSYDg.js.gz +0 -0
  370. package/build/client/_app/immutable/entry/start.BFVM56Yz.js +0 -1
  371. package/build/client/_app/immutable/entry/start.BFVM56Yz.js.br +0 -0
  372. package/build/client/_app/immutable/entry/start.BFVM56Yz.js.gz +0 -0
  373. package/build/client/_app/immutable/nodes/0.1R1dLPSd.js +0 -1
  374. package/build/client/_app/immutable/nodes/0.1R1dLPSd.js.br +0 -0
  375. package/build/client/_app/immutable/nodes/0.1R1dLPSd.js.gz +0 -0
  376. package/build/client/_app/immutable/nodes/1.LhEdwE1H.js +0 -1
  377. package/build/client/_app/immutable/nodes/1.LhEdwE1H.js.br +0 -0
  378. package/build/client/_app/immutable/nodes/1.LhEdwE1H.js.gz +0 -0
  379. package/build/client/_app/immutable/nodes/10.eB7zuikE.js +0 -2
  380. package/build/client/_app/immutable/nodes/10.eB7zuikE.js.br +0 -0
  381. package/build/client/_app/immutable/nodes/10.eB7zuikE.js.gz +0 -0
  382. package/build/client/_app/immutable/nodes/11.fvrVbout.js +0 -6
  383. package/build/client/_app/immutable/nodes/11.fvrVbout.js.br +0 -0
  384. package/build/client/_app/immutable/nodes/11.fvrVbout.js.gz +0 -0
  385. package/build/client/_app/immutable/nodes/12.CuCxLKQr.js.br +0 -0
  386. package/build/client/_app/immutable/nodes/12.CuCxLKQr.js.gz +0 -0
  387. package/build/client/_app/immutable/nodes/13.DPotp8O6.js +0 -1
  388. package/build/client/_app/immutable/nodes/13.DPotp8O6.js.br +0 -0
  389. package/build/client/_app/immutable/nodes/13.DPotp8O6.js.gz +0 -0
  390. package/build/client/_app/immutable/nodes/14.D5zVPym5.js +0 -65
  391. package/build/client/_app/immutable/nodes/14.D5zVPym5.js.br +0 -0
  392. package/build/client/_app/immutable/nodes/14.D5zVPym5.js.gz +0 -0
  393. package/build/client/_app/immutable/nodes/15.Cucd16Gx.js +0 -1
  394. package/build/client/_app/immutable/nodes/15.Cucd16Gx.js.br +0 -0
  395. package/build/client/_app/immutable/nodes/15.Cucd16Gx.js.gz +0 -0
  396. package/build/client/_app/immutable/nodes/2.Bai-TIgH.js.br +0 -0
  397. package/build/client/_app/immutable/nodes/2.Bai-TIgH.js.gz +0 -0
  398. package/build/client/_app/immutable/nodes/3.ev9oAmrG.js.br +0 -0
  399. package/build/client/_app/immutable/nodes/3.ev9oAmrG.js.gz +0 -0
  400. package/build/client/_app/immutable/nodes/4.DS2d90xq.js +0 -1
  401. package/build/client/_app/immutable/nodes/4.DS2d90xq.js.br +0 -0
  402. package/build/client/_app/immutable/nodes/4.DS2d90xq.js.gz +0 -0
  403. package/build/client/_app/immutable/nodes/5.CyK0fI1l.js.br +0 -0
  404. package/build/client/_app/immutable/nodes/5.CyK0fI1l.js.gz +0 -0
  405. package/build/client/_app/immutable/nodes/7.D-uzybGz.js +0 -1
  406. package/build/client/_app/immutable/nodes/7.D-uzybGz.js.br +0 -0
  407. package/build/client/_app/immutable/nodes/7.D-uzybGz.js.gz +0 -0
  408. package/build/client/_app/immutable/nodes/8.CYKKqJhA.js +0 -2
  409. package/build/client/_app/immutable/nodes/8.CYKKqJhA.js.br +0 -0
  410. package/build/client/_app/immutable/nodes/8.CYKKqJhA.js.gz +0 -0
  411. package/build/client/_app/immutable/nodes/9.CQcxG5IS.js +0 -1
  412. package/build/client/_app/immutable/nodes/9.CQcxG5IS.js.br +0 -0
  413. package/build/client/_app/immutable/nodes/9.CQcxG5IS.js.gz +0 -0
  414. package/build/server/chunks/0-BRQgSkWt.js +0 -31
  415. package/build/server/chunks/0-BRQgSkWt.js.map +0 -1
  416. package/build/server/chunks/1-lx7f4PWt.js +0 -9
  417. package/build/server/chunks/10-Censc2uj.js +0 -42
  418. package/build/server/chunks/10-Censc2uj.js.map +0 -1
  419. package/build/server/chunks/11-BEDQUU1_.js.map +0 -1
  420. package/build/server/chunks/12-CzhXMlU9.js.map +0 -1
  421. package/build/server/chunks/13-D1eLiA_r.js.map +0 -1
  422. package/build/server/chunks/14-BVNQ2wyL.js +0 -57
  423. package/build/server/chunks/14-BVNQ2wyL.js.map +0 -1
  424. package/build/server/chunks/15-Ch9c9iYB.js +0 -67
  425. package/build/server/chunks/15-Ch9c9iYB.js.map +0 -1
  426. package/build/server/chunks/4-DoW1zEiI.js.map +0 -1
  427. package/build/server/chunks/8-Ba9OHB5H.js.map +0 -1
  428. package/build/server/chunks/9-DSgRe_DY.js.map +0 -1
  429. package/build/server/chunks/JsonValue-CGVfzyTL.js.map +0 -1
  430. package/build/server/chunks/Modal-D2E5OLRi.js.map +0 -1
  431. package/build/server/chunks/Panel-C6VWd6JD.js.map +0 -1
  432. package/build/server/chunks/PrettyJson-Bo4UtQ1o.js.map +0 -1
  433. package/build/server/chunks/Tooltip-OVylvwfb.js.map +0 -1
  434. package/build/server/chunks/TooltipTable-CLglfpck.js.map +0 -1
  435. package/build/server/chunks/_layout.svelte-CLPxHDiP.js.map +0 -1
  436. package/build/server/chunks/_page.svelte-BeiSosXN.js.map +0 -1
  437. package/build/server/chunks/_page.svelte-C3QVwl-z.js.map +0 -1
  438. package/build/server/chunks/_page.svelte-CAAPpbun.js.map +0 -1
  439. package/build/server/chunks/_page.svelte-CPcgVZQj.js.map +0 -1
  440. package/build/server/chunks/_page.svelte-C_GX0K8M.js.map +0 -1
  441. package/build/server/chunks/_page.svelte-CkZUu9Wh.js.map +0 -1
  442. package/build/server/chunks/_page.svelte-DVjTn-ck.js.map +0 -1
  443. package/build/server/chunks/_page.svelte-e5wWk327.js.map +0 -1
  444. package/build/server/chunks/_page.svelte-zD7qndty.js.map +0 -1
  445. package/build/server/chunks/client-COtw9Xqw.js +0 -7
  446. package/build/server/chunks/error.svelte-DUZ2SYyF.js +0 -18
  447. package/build/server/chunks/error.svelte-DUZ2SYyF.js.map +0 -1
  448. package/build/server/chunks/filters-B3U8Nh9P.js.map +0 -1
  449. package/build/server/chunks/index-CtYzvcG6.js.map +0 -1
  450. package/build/server/chunks/index2-B0RgZaJY.js.map +0 -1
  451. package/build/server/chunks/mongo-B92d7zNj.js.map +0 -1
  452. package/build/server/chunks/remote-xxtqbu-CDChJkWc.js.map +0 -1
  453. package/build/server/chunks/root-otUAnOAR.js.map +0 -1
  454. package/build/server/chunks/servers.remote-CGenkEHX.js.map +0 -1
  455. package/src/routes/servers/[server]/databases/[database]/collections/[collection]/documents/+page.ts +0 -11
  456. package/src/routes/servers/[server]/databases/[database]/collections/[collection]/indexes/+page.ts +0 -11
  457. package/src/routes/servers/[server]/databases/[database]/collections/[collection]/mappings/+page.ts +0 -11
  458. package/src/routes/servers/[server]/databases/[database]/collections/[collection]/schema/+page.ts +0 -11
@@ -1,9 +1,10 @@
1
1
  import { env } from "$env/dynamic/private";
2
2
  import { logger } from "$lib/server/logger";
3
- import type { CollectionJSON, CollectionMappings, Mappings } from "$lib/types";
3
+ import type { CollectionJSON, CollectionMappings, Mappings, ShardingInfo } from "$lib/types";
4
+ import type { ShardKey } from "$lib/utils/shardKey";
4
5
  import { resolveSrv } from "dns/promises";
5
6
  import { MongoClient, ReadPreference, type Collection } from "mongodb";
6
- import { URL } from "url";
7
+ import { buildDirectConnectionUri, mongoHostKey, parseMongoUri } from "./connectionString";
7
8
  import { HostsManager } from "./HostsManager";
8
9
 
9
10
  export async function getCollectionJson(
@@ -95,33 +96,29 @@ export async function getCollectionJson(
95
96
  * Handles both mongodb:// and mongodb+srv:// formats
96
97
  */
97
98
  export async function extractNodesFromConnectionString(connectionString: string): Promise<string[]> {
98
- const url = new URL(connectionString);
99
+ const parsed = parseMongoUri(connectionString);
99
100
 
100
- if (url.protocol === "mongodb+srv:") {
101
- // For SRV, resolve DNS records
102
- const hostname = url.hostname;
101
+ if (parsed.protocol === "mongodb+srv:") {
102
+ // For SRV, resolve DNS records (a single hostname, no port)
103
+ const hostname = parsed.hosts[0]?.split(":")[0];
104
+ if (!hostname) {
105
+ throw new Error("No hostname found in SRV connection string");
106
+ }
103
107
  const srvRecords = await resolveSrv(`_mongodb._tcp.${hostname}`);
104
108
  return srvRecords
105
109
  .sort((a, b) => a.priority - b.priority || b.weight - a.weight)
106
110
  .map((record) => `${record.name}:${record.port}`)
107
111
  .sort();
108
112
  }
109
- if (url.protocol === "mongodb:") {
110
- // For standard mongodb://, extract hosts from the connection string
111
- // Format: mongodb://[username:password@]host1[:port1][,host2[:port2],...]/[database][?options]
112
- const hostsString = url.host;
113
- if (!hostsString) {
113
+ if (parsed.protocol === "mongodb:") {
114
+ // For standard mongodb://, the hosts are the comma-separated list, e.g.
115
+ // mongodb://[user:pass@]host1[:port1][,host2[:port2],...]/[db][?options]
116
+ if (parsed.hosts.length === 0) {
114
117
  throw new Error("No hosts found in connection string");
115
118
  }
116
-
117
- // Split by comma to get all hosts and sort lexically
118
- return hostsString
119
- .split(",")
120
- .map((host) => host.trim())
121
- .filter((host) => host.length > 0)
122
- .sort();
119
+ return [...parsed.hosts].sort();
123
120
  }
124
- throw new TypeError(`Unsupported protocol: ${url.protocol}`);
121
+ throw new TypeError(`Unsupported protocol: ${parsed.protocol}`);
125
122
  }
126
123
 
127
124
  export type IndexKey = Record<string, 1 | -1 | string>;
@@ -250,8 +247,7 @@ class MongoConnections {
250
247
  for (const host of hosts) {
251
248
  const urlStr = host.path.startsWith("mongodb") ? host.path : `mongodb://${host.path}`;
252
249
  try {
253
- const url = new URL(urlStr);
254
- const hostname = url.host || host.path;
250
+ const hostname = mongoHostKey(urlStr) || host.path;
255
251
 
256
252
  if (!this.clients.has(hostname)) {
257
253
  const client = new MongoClientWithMappings(urlStr, host._id, hostname, this.readPreference);
@@ -305,8 +301,7 @@ class MongoConnections {
305
301
  // Add the new server client
306
302
  const urlStr = hostPath.startsWith("mongodb") ? hostPath : `mongodb://${hostPath}`;
307
303
  try {
308
- const url = new URL(urlStr);
309
- const hostname = url.host || hostPath;
304
+ const hostname = mongoHostKey(urlStr) || hostPath;
310
305
 
311
306
  if (!this.clients.has(hostname)) {
312
307
  const client = new MongoClientWithMappings(urlStr, id, hostname, this.readPreference);
@@ -371,25 +366,16 @@ class MongoConnections {
371
366
  collection: string,
372
367
  ): Promise<Record<string, { ops: number; since: Date; host: string }>> {
373
368
  const client = this.getClient(serverId);
374
- const url = new URL(client.url);
375
-
376
- // Build direct connection URL
377
- // Keep credentials and other params, but set the host to the specific node
378
- const directUrl = new URL(url.toString());
379
- directUrl.protocol = "mongodb:";
380
- directUrl.host = node;
381
- directUrl.searchParams.set("directConnection", "true");
382
-
383
- // Keep TLS if it was in the original URL
384
- if (url.searchParams.has("tls") || url.searchParams.has("ssl") || url.protocol === "mongodb+srv:") {
385
- directUrl.searchParams.set("tls", "true");
386
- }
369
+
370
+ // Build a single-host direct-connection URI (multi-host safe), keeping
371
+ // credentials, TLS and other options from the original connection string.
372
+ const directUri = buildDirectConnectionUri(client.url, node);
387
373
 
388
374
  // Create a temporary client for this specific node
389
375
  let nodeClient: MongoClient | null = null;
390
376
  // todo: use await using when possible
391
377
  try {
392
- nodeClient = new MongoClient(directUrl.toString());
378
+ nodeClient = new MongoClient(directUri);
393
379
  await nodeClient.connect();
394
380
 
395
381
  const coll = nodeClient.db(database).collection(collection);
@@ -413,6 +399,191 @@ class MongoConnections {
413
399
  }
414
400
  }
415
401
  }
402
+
403
+ /**
404
+ * Return the shard key for every sharded collection in a database, in a single
405
+ * query against `config.collections`. Read-only.
406
+ *
407
+ * Returns a map of collectionName -> shard key. Collections that are not
408
+ * sharded (or on non-sharded clusters) are simply absent from the map.
409
+ * Designed to be cheap enough to call once for a whole collection list.
410
+ */
411
+ async getDatabaseShardKeys(serverId: string, database: string): Promise<Record<string, ShardKey>> {
412
+ const client = this.getClient(serverId);
413
+ const configDb = client.db("config");
414
+ const result: Record<string, ShardKey> = {};
415
+
416
+ try {
417
+ // _id of config.collections is the namespace "db.coll".
418
+ // Match all namespaces in this database via a prefix regex.
419
+ const prefix = `${database}.`;
420
+ const docs = (await configDb
421
+ .collection("collections")
422
+ .find({
423
+ _id: { $regex: `^${prefix.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}` },
424
+ } as unknown as Record<string, unknown>)
425
+ .project({ _id: 1, key: 1, dropped: 1 })
426
+ .toArray()) as unknown as Array<{
427
+ _id: string;
428
+ key?: ShardKey;
429
+ dropped?: boolean;
430
+ }>;
431
+
432
+ for (const doc of docs) {
433
+ if (doc.dropped || !doc.key) {
434
+ continue;
435
+ }
436
+ const name = doc._id.slice(prefix.length);
437
+ result[name] = doc.key;
438
+ }
439
+ } catch (err) {
440
+ logger.error("Error reading config.collections for shard keys:", err);
441
+ }
442
+
443
+ return result;
444
+ }
445
+
446
+ /**
447
+ * Gather sharding information for a collection.
448
+ *
449
+ * Everything here is read-only: it reads the `config` database
450
+ * (config.collections / config.chunks / config.shards) and runs `$collStats`.
451
+ * On a non-sharded (standalone / replica set) deployment, the `config`
452
+ * collections won't exist and we return `shardingEnabled: false`.
453
+ */
454
+ async getShardingInfo(serverId: string, database: string, collection: string): Promise<ShardingInfo> {
455
+ const client = this.getClient(serverId);
456
+ const ns = `${database}.${collection}`;
457
+
458
+ const info: ShardingInfo = {
459
+ shardingEnabled: false,
460
+ sharded: false,
461
+ shardKey: null,
462
+ hashed: false,
463
+ unique: false,
464
+ totalChunks: 0,
465
+ shards: [],
466
+ balancerEnabled: true,
467
+ warning: null,
468
+ };
469
+
470
+ const configDb = client.db("config");
471
+
472
+ // Detect whether this is a sharded cluster at all by looking for the
473
+ // config.shards collection. On a plain replica set this throws / is empty.
474
+ let shardDocs: Array<{ _id: string; host: string }> = [];
475
+ try {
476
+ shardDocs = (await configDb.collection("shards").find({}).toArray()) as unknown as Array<{
477
+ _id: string;
478
+ host: string;
479
+ }>;
480
+ } catch (err) {
481
+ logger.error("Error reading config.shards (not a sharded cluster?):", err);
482
+ return info; // shardingEnabled stays false
483
+ }
484
+
485
+ if (shardDocs.length === 0) {
486
+ // No shards => not connected through mongos / not a sharded cluster.
487
+ return info;
488
+ }
489
+
490
+ info.shardingEnabled = true;
491
+
492
+ // Look up this collection's sharding metadata.
493
+ // In MongoDB the _id of config.collections is the namespace "db.coll".
494
+ type CollConfig = {
495
+ _id: string;
496
+ key?: Record<string, 1 | -1 | string>;
497
+ unique?: boolean;
498
+ dropped?: boolean;
499
+ noBalance?: boolean;
500
+ uuid?: unknown;
501
+ };
502
+ let collConfig: CollConfig | null = null;
503
+ try {
504
+ collConfig = (await configDb
505
+ .collection("collections")
506
+ .findOne({ _id: ns } as unknown as Record<string, unknown>)) as CollConfig | null;
507
+ } catch (err) {
508
+ logger.error("Error reading config.collections:", err);
509
+ info.warning = "Could not read config.collections";
510
+ }
511
+
512
+ // Per-shard storage/document stats from $collStats (works whether sharded or not).
513
+ const perShard = new Map<string, { documents: number | null; size: number | null }>();
514
+ try {
515
+ const statsResults = await client
516
+ .db(database)
517
+ .collection(collection)
518
+ .aggregate([{ $collStats: { storageStats: {} } }])
519
+ .toArray();
520
+ for (const stat of statsResults) {
521
+ const shardId = (stat.shard as string) || shardDocs[0]?._id || "unknown";
522
+ perShard.set(shardId, {
523
+ documents: (stat.storageStats?.count as number) ?? null,
524
+ size: (stat.storageStats?.size as number) ?? null,
525
+ });
526
+ }
527
+ } catch (err) {
528
+ logger.error("Error reading $collStats for sharding info:", err);
529
+ }
530
+
531
+ if (collConfig && !collConfig.dropped && collConfig.key) {
532
+ info.sharded = true;
533
+ info.shardKey = collConfig.key;
534
+ info.hashed = Object.values(collConfig.key).some((v) => v === "hashed");
535
+ info.unique = !!collConfig.unique;
536
+ info.balancerEnabled = !collConfig.noBalance;
537
+
538
+ // Count chunks per shard for this namespace.
539
+ // Newer MongoDB keys config.chunks by `uuid`, older ones by `ns`.
540
+ try {
541
+ let chunkFilter: Record<string, unknown> = { ns };
542
+ if (collConfig.uuid !== undefined) {
543
+ chunkFilter = { uuid: collConfig.uuid };
544
+ }
545
+ const chunkCounts = await configDb
546
+ .collection("chunks")
547
+ .aggregate([{ $match: chunkFilter }, { $group: { _id: "$shard", count: { $sum: 1 } } }])
548
+ .toArray();
549
+ const chunkMap = new Map<string, number>(chunkCounts.map((c) => [c._id as string, c.count as number]));
550
+ info.totalChunks = chunkCounts.reduce((acc, c) => acc + (c.count as number), 0);
551
+
552
+ info.shards = shardDocs.map((shard) => ({
553
+ shardId: shard._id,
554
+ host: shard.host,
555
+ chunks: chunkMap.get(shard._id) ?? 0,
556
+ documents: perShard.get(shard._id)?.documents ?? null,
557
+ size: perShard.get(shard._id)?.size ?? null,
558
+ }));
559
+ } catch (err) {
560
+ logger.error("Error reading config.chunks:", err);
561
+ info.warning = "Could not read chunk distribution";
562
+ info.shards = shardDocs.map((shard) => ({
563
+ shardId: shard._id,
564
+ host: shard.host,
565
+ chunks: 0,
566
+ documents: perShard.get(shard._id)?.documents ?? null,
567
+ size: perShard.get(shard._id)?.size ?? null,
568
+ }));
569
+ }
570
+ } else {
571
+ // Unsharded collection on a sharded cluster: it lives on its primary shard.
572
+ info.sharded = false;
573
+ info.shards = [...perShard.entries()].map(([shardId, stats]) => {
574
+ const shard = shardDocs.find((s) => s._id === shardId);
575
+ return {
576
+ shardId,
577
+ host: shard?.host ?? shardId,
578
+ chunks: 0,
579
+ documents: stats.documents,
580
+ size: stats.size,
581
+ };
582
+ });
583
+ }
584
+
585
+ return info;
586
+ }
416
587
  }
417
588
 
418
589
  // Singleton instance
package/src/lib/types.ts CHANGED
@@ -57,6 +57,40 @@ export interface CollectionJSON {
57
57
  }>;
58
58
  }
59
59
 
60
+ /**
61
+ * Sharding information for a collection, gathered from the `config` database
62
+ * and `$collStats`. All queries are read-only.
63
+ */
64
+ export interface ShardingInfo {
65
+ /** Whether the cluster is a sharded cluster (mongos) at all. */
66
+ shardingEnabled: boolean;
67
+ /** Whether this specific collection is sharded. */
68
+ sharded: boolean;
69
+ /** The shard key, e.g. { userId: 1, _id: "hashed" }. Null if unsharded. */
70
+ shardKey: Record<string, 1 | -1 | string> | null;
71
+ /** Whether the shard key uses hashed sharding. */
72
+ hashed: boolean;
73
+ /** Whether the collection uses unique shard key. */
74
+ unique: boolean;
75
+ /** Total number of chunks across all shards. */
76
+ totalChunks: number;
77
+ /** The list of all shards known to the cluster. */
78
+ shards: Array<{
79
+ shardId: string;
80
+ host: string;
81
+ /** Number of chunks for this collection on this shard. */
82
+ chunks: number;
83
+ /** Number of documents for this collection on this shard (from $collStats). */
84
+ documents: number | null;
85
+ /** Storage size in bytes for this collection on this shard. */
86
+ size: number | null;
87
+ }>;
88
+ /** Whether balancing is currently enabled for the collection (noBalance flag). */
89
+ balancerEnabled: boolean;
90
+ /** Any non-fatal error/warning encountered while gathering info. */
91
+ warning: string | null;
92
+ }
93
+
60
94
  export const ALLOWED_AGGREGATION_STAGES = new Set([
61
95
  "$addFields",
62
96
  "$bucket",
@@ -1,3 +1,5 @@
1
+ import { mongoDisplayName } from "$lib/utils/mongoUri";
2
+
1
3
  export function formatBytes(bytes: number): string {
2
4
  if (bytes === 0) {
3
5
  return "0 B";
@@ -22,14 +24,10 @@ export function formatNumber(num: number): string {
22
24
  }
23
25
 
24
26
  export function serverName(name: string): string {
25
- // Extract hostname from MongoDB connection string
27
+ // Extract a short, friendly hostname from a MongoDB connection string.
28
+ // Multi-host safe (mongos / replica-set URIs won't produce giant names).
26
29
  if (name.startsWith("mongodb://") || name.startsWith("mongodb+srv://")) {
27
- try {
28
- const url = new URL(name);
29
- return url.hostname;
30
- } catch {
31
- return name;
32
- }
30
+ return mongoDisplayName(name);
33
31
  }
34
32
  return name;
35
33
  }
@@ -0,0 +1,164 @@
1
+ /**
2
+ * Isomorphic helpers for parsing MongoDB connection strings (safe on both
3
+ * client and server — pure string operations, no node-only imports).
4
+ *
5
+ * The WHATWG `URL` class cannot parse multi-host MongoDB URIs like
6
+ * mongodb://user:pass@hostA:27017,hostB:27017,hostC:27017/db?replicaSet=rs0
7
+ * because the commas in the authority make it throw `TypeError: Invalid URL`.
8
+ * These helpers understand the comma-separated host list that MongoDB allows.
9
+ *
10
+ * Reference grammar:
11
+ * mongodb://[username:password@]host1[:port1][,host2[:port2],...][/[db][?opts]]
12
+ * mongodb+srv://[username:password@]host[/[db][?opts]] (single host, no port)
13
+ */
14
+
15
+ export interface ParsedMongoUri {
16
+ /** "mongodb:" or "mongodb+srv:" */
17
+ protocol: string;
18
+ username: string;
19
+ password: string;
20
+ /** The raw comma-joined host list, e.g. "a:27017,b:27017". */
21
+ hostsRaw: string;
22
+ /** Individual hosts, each possibly "host:port". */
23
+ hosts: string[];
24
+ /** Path after the hosts, including leading "/" if present (db name etc.). */
25
+ pathname: string;
26
+ /** Query string without the leading "?", or "". */
27
+ search: string;
28
+ }
29
+
30
+ /**
31
+ * Parse a MongoDB connection string into its parts, tolerating multi-host URIs.
32
+ * Throws a TypeError for strings that don't start with a mongodb scheme.
33
+ */
34
+ export function parseMongoUri(connectionString: string): ParsedMongoUri {
35
+ const schemeMatch = connectionString.match(/^(mongodb(?:\+srv)?):\/\//);
36
+ if (!schemeMatch) {
37
+ throw new TypeError(`Unsupported MongoDB connection string: ${connectionString}`);
38
+ }
39
+ const protocol = `${schemeMatch[1]}:`;
40
+ const rest = connectionString.slice(schemeMatch[0].length);
41
+
42
+ // Authority ends at the first "/" (path), or end of string.
43
+ const afterAuthDelimiter = rest.indexOf("/");
44
+ const authorityEnd = afterAuthDelimiter === -1 ? rest.length : afterAuthDelimiter;
45
+ const authority = rest.slice(0, authorityEnd);
46
+ const tail = rest.slice(authorityEnd); // starts with "/" or ""
47
+
48
+ let credentials = "";
49
+ let hostsRaw = authority;
50
+ const atIndex = authority.lastIndexOf("@");
51
+ if (atIndex !== -1) {
52
+ credentials = authority.slice(0, atIndex);
53
+ hostsRaw = authority.slice(atIndex + 1);
54
+ }
55
+
56
+ let username = "";
57
+ let password = "";
58
+ if (credentials) {
59
+ const colon = credentials.indexOf(":");
60
+ if (colon === -1) {
61
+ username = credentials;
62
+ } else {
63
+ username = credentials.slice(0, colon);
64
+ password = credentials.slice(colon + 1);
65
+ }
66
+ }
67
+
68
+ // Split pathname and query from the tail.
69
+ const queryIndex = tail.indexOf("?");
70
+ const pathname = queryIndex === -1 ? tail : tail.slice(0, queryIndex);
71
+ const search = queryIndex === -1 ? "" : tail.slice(queryIndex + 1);
72
+
73
+ const hosts = hostsRaw
74
+ .split(",")
75
+ .map((h) => h.trim())
76
+ .filter((h) => h.length > 0);
77
+
78
+ return { protocol, username, password, hostsRaw, hosts, pathname, search };
79
+ }
80
+
81
+ /**
82
+ * A stable key identifying a server connection, derived from its host list.
83
+ * Equivalent to the old `new URL(uri).host` but multi-host safe.
84
+ */
85
+ export function mongoHostKey(connectionString: string): string {
86
+ return parseMongoUri(connectionString).hostsRaw;
87
+ }
88
+
89
+ /**
90
+ * Produce a short, human-friendly display name for a connection string.
91
+ *
92
+ * Strips credentials, ports, query options and the db path, and for multi-host
93
+ * URIs collapses the comma list to the shared hostname (when the hosts only
94
+ * differ by a leading "<something>-N." prefix) so we don't render giant names.
95
+ * Returns the input unchanged if it isn't a mongodb URI.
96
+ */
97
+ export function mongoDisplayName(connectionString: string): string {
98
+ let parsed: ParsedMongoUri;
99
+ try {
100
+ parsed = parseMongoUri(connectionString);
101
+ } catch {
102
+ return connectionString;
103
+ }
104
+
105
+ // Hostnames without ports.
106
+ const hostnames = parsed.hosts.map((h) => stripPort(h)).filter((h) => h.length > 0);
107
+ if (hostnames.length === 0) {
108
+ return connectionString;
109
+ }
110
+ if (hostnames.length === 1) {
111
+ return hostnames[0];
112
+ }
113
+
114
+ // Multiple hosts (e.g. a mongos/replica-set list). If they share a common
115
+ // domain suffix, show that with a count; otherwise just the first + count.
116
+ const suffix = commonDomainSuffix(hostnames);
117
+ if (suffix) {
118
+ return `${suffix} (${hostnames.length} hosts)`;
119
+ }
120
+ return `${hostnames[0]} (+${hostnames.length - 1})`;
121
+ }
122
+
123
+ function stripPort(host: string): string {
124
+ // Don't strip ports off IPv6 ("[::1]:27017") — keep it simple: only strip a
125
+ // trailing ":<digits>" when there's a single colon (hostname:port).
126
+ const lastColon = host.lastIndexOf(":");
127
+ if (lastColon === -1) {
128
+ return host;
129
+ }
130
+ const maybePort = host.slice(lastColon + 1);
131
+ if (/^\d+$/.test(maybePort) && !host.slice(0, lastColon).includes(":")) {
132
+ return host.slice(0, lastColon);
133
+ }
134
+ return host;
135
+ }
136
+
137
+ /**
138
+ * Given hosts like
139
+ * mongodb-mongos-0.moonlanding-bucket-prod.mongodb.internal
140
+ * mongodb-mongos-1.moonlanding-bucket-prod.mongodb.internal
141
+ * return the shared part after the first differing label, e.g.
142
+ * moonlanding-bucket-prod.mongodb.internal
143
+ * Returns "" if there's no meaningful shared suffix.
144
+ */
145
+ function commonDomainSuffix(hostnames: string[]): string {
146
+ const split = hostnames.map((h) => h.split("."));
147
+ const minLen = Math.min(...split.map((s) => s.length));
148
+ let shared = 0;
149
+ for (let i = 1; i <= minLen; i++) {
150
+ const labels = split.map((s) => s[s.length - i]);
151
+ if (labels.every((l) => l === labels[0])) {
152
+ shared = i;
153
+ } else {
154
+ break;
155
+ }
156
+ }
157
+ // Require at least 2 shared labels — a lone TLD ("com") isn't a useful name.
158
+ if (shared < 2 || shared === minLen) {
159
+ // No meaningful shared suffix, or the hosts are identical.
160
+ return shared === minLen ? hostnames[0] : "";
161
+ }
162
+ const labels = split[0];
163
+ return labels.slice(labels.length - shared).join(".");
164
+ }
@@ -0,0 +1,16 @@
1
+ export type ShardKey = Record<string, 1 | -1 | string>;
2
+
3
+ /**
4
+ * Render a shard key into a compact human-readable string.
5
+ * e.g. { userId: 1, _id: "hashed" } -> "userId: ↑, _id: hashed"
6
+ */
7
+ export function formatShardKey(key: ShardKey): string {
8
+ return Object.entries(key)
9
+ .map(([field, dir]) => {
10
+ if (dir === "hashed") {
11
+ return `${field}: hashed`;
12
+ }
13
+ return `${field}: ${dir === 1 ? "↑" : dir === -1 ? "↓" : dir}`;
14
+ })
15
+ .join(", ");
16
+ }
@@ -137,7 +137,7 @@
137
137
  {serverName(server.name)}
138
138
  </span>
139
139
  {:else}
140
- <a href={resolve(`/servers/${encodeURIComponent(serverName(server.name))}/databases`)}>
140
+ <a href={resolve(`/servers/${encodeURIComponent(server.name)}/databases`)}>
141
141
  {serverName(server.name)}
142
142
  </a>
143
143
  {/if}
@@ -13,7 +13,12 @@ export const load: PageServerLoad = async ({ params }) => {
13
13
  details: getCollectionJson(db.collection(c.name), c.type).catch(() => null),
14
14
  }));
15
15
 
16
+ // Single read against config.collections for the whole DB. Streamed so the
17
+ // table renders immediately and the badges fill in when this resolves.
18
+ const shardKeys = mongo.getDatabaseShardKeys(params.server, params.database).catch(() => ({}));
19
+
16
20
  return {
17
21
  collections: collectionsWithDetails,
22
+ shardKeys,
18
23
  };
19
24
  };
@@ -4,15 +4,41 @@
4
4
  import { resolve } from "$app/paths";
5
5
  import Modal from "$lib/components/Modal.svelte";
6
6
  import Panel from "$lib/components/Panel.svelte";
7
+ import ShardBadge from "$lib/components/ShardBadge.svelte";
7
8
  import TooltipTable from "$lib/components/TooltipTable.svelte";
8
9
  import { notificationStore } from "$lib/stores/notifications.svelte";
9
10
  import { formatBytes, formatNumber } from "$lib/utils/filters";
11
+ import type { ShardKey } from "$lib/utils/shardKey";
10
12
  import type { PageData } from "./$types";
11
13
 
12
14
  let { data }: { data: PageData } = $props();
13
15
 
14
16
  type Collection = PageData["collections"][number];
15
17
 
18
+ // Resolve the streamed shard keys, guarding against out-of-order responses:
19
+ // when navigating between databases, a slow previous request must not
20
+ // overwrite the current one. We key on the promise identity (reassigned by
21
+ // the loader on each navigation) and drop any result from a stale promise.
22
+ let shardKeys = $state<Record<string, ShardKey>>({});
23
+
24
+ $effect(() => {
25
+ const promise = data.shardKeys;
26
+ // Reset immediately so badges from the previous database disappear while
27
+ // the new request is in flight.
28
+ shardKeys = {};
29
+ let cancelled = false;
30
+ // Silently ignore failures (e.g. no read access to the config database):
31
+ // the load already degrades to {}, and this just leaves badges off.
32
+ promise.then((keys) => {
33
+ if (!cancelled) {
34
+ shardKeys = keys;
35
+ }
36
+ });
37
+ return () => {
38
+ cancelled = true;
39
+ };
40
+ });
41
+
16
42
  let showDropModal = $state(false);
17
43
  let collectionToDrop = $state<Collection | null>(null);
18
44
  let isDropping = $state(false);
@@ -67,15 +93,27 @@
67
93
  {#each data.collections as collection (collection.name)}
68
94
  <tr class="group">
69
95
  <td>
70
- <a
71
- href={resolve(
72
- `/servers/${encodeURIComponent(data.server)}/databases/${encodeURIComponent(
73
- data.database,
74
- )}/collections/${encodeURIComponent(collection.name)}/documents`,
75
- )}
76
- >
77
- {collection.name}
78
- </a>
96
+ <div class="flex items-center gap-2">
97
+ <a
98
+ href={resolve(
99
+ `/servers/${encodeURIComponent(data.server)}/databases/${encodeURIComponent(
100
+ data.database,
101
+ )}/collections/${encodeURIComponent(collection.name)}/documents`,
102
+ )}
103
+ >
104
+ {collection.name}
105
+ </a>
106
+ {#if shardKeys[collection.name]}
107
+ <ShardBadge
108
+ shardKey={shardKeys[collection.name]}
109
+ href={resolve(
110
+ `/servers/${encodeURIComponent(data.server)}/databases/${encodeURIComponent(
111
+ data.database,
112
+ )}/collections/${encodeURIComponent(collection.name)}/sharding`,
113
+ )}
114
+ />
115
+ {/if}
116
+ </div>
79
117
  </td>
80
118
  <td>
81
119
  {#await collection.details}
@@ -1,6 +1,9 @@
1
+ import { COLLECTION_CATEGORIES } from "$lib/collectionCategories";
2
+
1
3
  export const load = async (event) => {
2
4
  return {
3
5
  collection: event.params.collection,
6
+ categories: COLLECTION_CATEGORIES,
4
7
  breadcrumbs: [
5
8
  ...(await event.parent()).breadcrumbs,
6
9
  { label: event.params.collection, path: `/${event.params.collection}/documents` },