mongoku 2.0.4 → 2.1.0

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 (414) hide show
  1. package/README.md +14 -2
  2. package/build/client/_app/immutable/assets/0.egX7ddQL.css +1 -0
  3. package/build/client/_app/immutable/assets/0.egX7ddQL.css.br +0 -0
  4. package/build/client/_app/immutable/assets/0.egX7ddQL.css.gz +0 -0
  5. package/build/client/_app/immutable/assets/10.59aTjJn9.css +1 -0
  6. package/build/client/_app/immutable/assets/10.59aTjJn9.css.br +0 -0
  7. package/build/client/_app/immutable/assets/10.59aTjJn9.css.gz +0 -0
  8. package/build/client/_app/immutable/assets/11.CEtFGlZU.css +1 -0
  9. package/build/client/_app/immutable/assets/11.CEtFGlZU.css.br +1 -0
  10. package/build/client/_app/immutable/assets/11.CEtFGlZU.css.gz +0 -0
  11. package/build/client/_app/immutable/assets/12.BdCOhvz0.css +1 -0
  12. package/build/client/_app/immutable/assets/12.BdCOhvz0.css.br +0 -0
  13. package/build/client/_app/immutable/assets/12.BdCOhvz0.css.gz +0 -0
  14. package/build/client/_app/immutable/assets/JsonValue.BEbzuWqZ.css +1 -0
  15. package/build/client/_app/immutable/assets/JsonValue.BEbzuWqZ.css.br +0 -0
  16. package/build/client/_app/immutable/assets/JsonValue.BEbzuWqZ.css.gz +0 -0
  17. package/build/client/_app/immutable/assets/Modal.DIIFkbGB.css +1 -0
  18. package/build/client/_app/immutable/assets/Modal.DIIFkbGB.css.br +0 -0
  19. package/build/client/_app/immutable/assets/Modal.DIIFkbGB.css.gz +0 -0
  20. package/build/client/_app/immutable/assets/Panel.B3aWupye.css +1 -0
  21. package/build/client/_app/immutable/assets/Panel.B3aWupye.css.br +0 -0
  22. package/build/client/_app/immutable/assets/Panel.B3aWupye.css.gz +0 -0
  23. package/build/client/_app/immutable/chunks/7rjwS0Fa.js +1 -0
  24. package/build/client/_app/immutable/chunks/7rjwS0Fa.js.br +0 -0
  25. package/build/client/_app/immutable/chunks/7rjwS0Fa.js.gz +0 -0
  26. package/build/client/_app/immutable/chunks/BLDrwdCC.js +1 -0
  27. package/build/client/_app/immutable/chunks/BLDrwdCC.js.br +0 -0
  28. package/build/client/_app/immutable/chunks/BLDrwdCC.js.gz +0 -0
  29. package/build/client/_app/immutable/chunks/BNpv6iz_.js +1 -0
  30. package/build/client/_app/immutable/chunks/BNpv6iz_.js.br +0 -0
  31. package/build/client/_app/immutable/chunks/BNpv6iz_.js.gz +0 -0
  32. package/build/client/_app/immutable/chunks/BY7rCWFm.js +1 -0
  33. package/build/client/_app/immutable/chunks/BY7rCWFm.js.br +0 -0
  34. package/build/client/_app/immutable/chunks/BY7rCWFm.js.gz +0 -0
  35. package/build/client/_app/immutable/chunks/BirzSxMb.js +2 -0
  36. package/build/client/_app/immutable/chunks/BirzSxMb.js.br +0 -0
  37. package/build/client/_app/immutable/chunks/BirzSxMb.js.gz +0 -0
  38. package/build/client/_app/immutable/chunks/BsxVnnsB.js +1 -0
  39. package/build/client/_app/immutable/chunks/BsxVnnsB.js.br +0 -0
  40. package/build/client/_app/immutable/chunks/BsxVnnsB.js.gz +0 -0
  41. package/build/client/_app/immutable/chunks/BtVcRw28.js +29 -0
  42. package/build/client/_app/immutable/chunks/BtVcRw28.js.br +0 -0
  43. package/build/client/_app/immutable/chunks/BtVcRw28.js.gz +0 -0
  44. package/build/client/_app/immutable/chunks/CdQ4HxbR.js +2 -0
  45. package/build/client/_app/immutable/chunks/CdQ4HxbR.js.br +0 -0
  46. package/build/client/_app/immutable/chunks/CdQ4HxbR.js.gz +0 -0
  47. package/build/client/_app/immutable/chunks/CeUVbZ2h.js +1 -0
  48. package/build/client/_app/immutable/chunks/CeUVbZ2h.js.br +0 -0
  49. package/build/client/_app/immutable/chunks/CeUVbZ2h.js.gz +0 -0
  50. package/build/client/_app/immutable/chunks/CsO4V9Pl.js +1 -0
  51. package/build/client/_app/immutable/chunks/CsO4V9Pl.js.br +0 -0
  52. package/build/client/_app/immutable/chunks/CsO4V9Pl.js.gz +0 -0
  53. package/build/client/_app/immutable/chunks/Cy5AtpEx.js +1 -0
  54. package/build/client/_app/immutable/chunks/Cy5AtpEx.js.br +0 -0
  55. package/build/client/_app/immutable/chunks/Cy5AtpEx.js.gz +0 -0
  56. package/build/client/_app/immutable/chunks/DD3Ma7mI.js +1 -0
  57. package/build/client/_app/immutable/chunks/DD3Ma7mI.js.br +1 -0
  58. package/build/client/_app/immutable/chunks/DD3Ma7mI.js.gz +0 -0
  59. package/build/client/_app/immutable/chunks/DDOxwa8G.js +1 -0
  60. package/build/client/_app/immutable/chunks/DDOxwa8G.js.br +0 -0
  61. package/build/client/_app/immutable/chunks/DDOxwa8G.js.gz +0 -0
  62. package/build/client/_app/immutable/chunks/DPilZ31q.js +4 -0
  63. package/build/client/_app/immutable/chunks/DPilZ31q.js.br +0 -0
  64. package/build/client/_app/immutable/chunks/DPilZ31q.js.gz +0 -0
  65. package/build/client/_app/immutable/chunks/DkcM24tw.js +1 -0
  66. package/build/client/_app/immutable/chunks/DkcM24tw.js.br +0 -0
  67. package/build/client/_app/immutable/chunks/DkcM24tw.js.gz +0 -0
  68. package/build/client/_app/immutable/chunks/{ChWB6xnu.js → DzIzGsAN.js} +1 -1
  69. package/build/client/_app/immutable/chunks/DzIzGsAN.js.br +0 -0
  70. package/build/client/_app/immutable/chunks/DzIzGsAN.js.gz +0 -0
  71. package/build/client/_app/immutable/chunks/Dzn375RV.js +1 -0
  72. package/build/client/_app/immutable/chunks/Dzn375RV.js.br +0 -0
  73. package/build/client/_app/immutable/chunks/Dzn375RV.js.gz +0 -0
  74. package/build/client/_app/immutable/chunks/hzkOq89z.js +1 -0
  75. package/build/client/_app/immutable/chunks/hzkOq89z.js.br +0 -0
  76. package/build/client/_app/immutable/chunks/hzkOq89z.js.gz +0 -0
  77. package/build/client/_app/immutable/chunks/myWOS8Ad.js +1 -0
  78. package/build/client/_app/immutable/chunks/myWOS8Ad.js.br +0 -0
  79. package/build/client/_app/immutable/chunks/myWOS8Ad.js.gz +0 -0
  80. package/build/client/_app/immutable/chunks/{DQkpHJGc.js → pwiEVMhR.js} +1 -1
  81. package/build/client/_app/immutable/chunks/pwiEVMhR.js.br +0 -0
  82. package/build/client/_app/immutable/chunks/pwiEVMhR.js.gz +0 -0
  83. package/build/client/_app/immutable/chunks/woTmcqT7.js +1 -0
  84. package/build/client/_app/immutable/chunks/woTmcqT7.js.br +0 -0
  85. package/build/client/_app/immutable/chunks/woTmcqT7.js.gz +0 -0
  86. package/build/client/_app/immutable/chunks/zDi6mm3o.js +1 -0
  87. package/build/client/_app/immutable/chunks/zDi6mm3o.js.br +0 -0
  88. package/build/client/_app/immutable/chunks/zDi6mm3o.js.gz +0 -0
  89. package/build/client/_app/immutable/entry/app.CxQNYOR7.js +2 -0
  90. package/build/client/_app/immutable/entry/app.CxQNYOR7.js.br +0 -0
  91. package/build/client/_app/immutable/entry/app.CxQNYOR7.js.gz +0 -0
  92. package/build/client/_app/immutable/entry/start.CUo1ZpWZ.js +1 -0
  93. package/build/client/_app/immutable/entry/start.CUo1ZpWZ.js.br +2 -0
  94. package/build/client/_app/immutable/entry/start.CUo1ZpWZ.js.gz +0 -0
  95. package/build/client/_app/immutable/nodes/0.NM9sLghd.js +5 -0
  96. package/build/client/_app/immutable/nodes/0.NM9sLghd.js.br +0 -0
  97. package/build/client/_app/immutable/nodes/0.NM9sLghd.js.gz +0 -0
  98. package/build/client/_app/immutable/nodes/1.DbC3260o.js +1 -0
  99. package/build/client/_app/immutable/nodes/1.DbC3260o.js.br +2 -0
  100. package/build/client/_app/immutable/nodes/1.DbC3260o.js.gz +0 -0
  101. package/build/client/_app/immutable/nodes/10.BVQvX3m0.js +2 -0
  102. package/build/client/_app/immutable/nodes/10.BVQvX3m0.js.br +0 -0
  103. package/build/client/_app/immutable/nodes/10.BVQvX3m0.js.gz +0 -0
  104. package/build/client/_app/immutable/nodes/11.Bxvf_-yk.js +1 -0
  105. package/build/client/_app/immutable/nodes/11.Bxvf_-yk.js.br +0 -0
  106. package/build/client/_app/immutable/nodes/11.Bxvf_-yk.js.gz +0 -0
  107. package/build/client/_app/immutable/nodes/12.Prhpx9Ma.js +1 -0
  108. package/build/client/_app/immutable/nodes/12.Prhpx9Ma.js.br +0 -0
  109. package/build/client/_app/immutable/nodes/12.Prhpx9Ma.js.gz +0 -0
  110. package/build/client/_app/immutable/nodes/13.Bgj5oOSN.js +66 -0
  111. package/build/client/_app/immutable/nodes/13.Bgj5oOSN.js.br +0 -0
  112. package/build/client/_app/immutable/nodes/13.Bgj5oOSN.js.gz +0 -0
  113. package/build/client/_app/immutable/nodes/2.UoL1FlSn.js +1 -0
  114. package/build/client/_app/immutable/nodes/2.UoL1FlSn.js.br +1 -0
  115. package/build/client/_app/immutable/nodes/2.UoL1FlSn.js.gz +0 -0
  116. package/build/client/_app/immutable/nodes/3.oJ7_29Md.js +1 -0
  117. package/build/client/_app/immutable/nodes/3.oJ7_29Md.js.br +0 -0
  118. package/build/client/_app/immutable/nodes/3.oJ7_29Md.js.gz +0 -0
  119. package/build/client/_app/immutable/nodes/4.BbmkM0ZH.js +1 -0
  120. package/build/client/_app/immutable/nodes/4.BbmkM0ZH.js.br +0 -0
  121. package/build/client/_app/immutable/nodes/4.BbmkM0ZH.js.gz +0 -0
  122. package/build/client/_app/immutable/nodes/5.CUeb6mKm.js +1 -0
  123. package/build/client/_app/immutable/nodes/5.CUeb6mKm.js.br +0 -0
  124. package/build/client/_app/immutable/nodes/5.CUeb6mKm.js.gz +0 -0
  125. package/build/client/_app/immutable/nodes/7.BiyUd38g.js +1 -0
  126. package/build/client/_app/immutable/nodes/7.BiyUd38g.js.br +0 -0
  127. package/build/client/_app/immutable/nodes/7.BiyUd38g.js.gz +0 -0
  128. package/build/client/_app/immutable/nodes/8.DhezXfEp.js +1 -0
  129. package/build/client/_app/immutable/nodes/8.DhezXfEp.js.br +0 -0
  130. package/build/client/_app/immutable/nodes/8.DhezXfEp.js.gz +0 -0
  131. package/build/client/_app/immutable/nodes/9.tIbM6W_7.js +2 -0
  132. package/build/client/_app/immutable/nodes/9.tIbM6W_7.js.br +0 -0
  133. package/build/client/_app/immutable/nodes/9.tIbM6W_7.js.gz +0 -0
  134. package/build/client/_app/version.json +1 -1
  135. package/build/client/_app/version.json.br +0 -0
  136. package/build/client/_app/version.json.gz +0 -0
  137. package/build/handler.js +14 -0
  138. package/build/server/chunks/{0-Cb5ytlMI.js → 0-Xn_28PLT.js} +7 -6
  139. package/build/server/chunks/0-Xn_28PLT.js.map +1 -0
  140. package/build/server/chunks/1-CBgVE2FQ.js +9 -0
  141. package/build/server/chunks/1-CBgVE2FQ.js.map +1 -0
  142. package/build/server/chunks/10-nsD-CCn7.js +212 -0
  143. package/build/server/chunks/10-nsD-CCn7.js.map +1 -0
  144. package/build/server/chunks/11-BmqLuLNb.js +41 -0
  145. package/build/server/chunks/11-BmqLuLNb.js.map +1 -0
  146. package/build/server/chunks/12-PgTuaplb.js +101 -0
  147. package/build/server/chunks/12-PgTuaplb.js.map +1 -0
  148. package/build/server/chunks/13-BSGYMCpC.js +51 -0
  149. package/build/server/chunks/13-BSGYMCpC.js.map +1 -0
  150. package/build/server/chunks/2-BJxJqjul.js +24 -0
  151. package/build/server/chunks/2-BJxJqjul.js.map +1 -0
  152. package/build/server/chunks/3-D2ftoQkX.js +25 -0
  153. package/build/server/chunks/3-D2ftoQkX.js.map +1 -0
  154. package/build/server/chunks/4-CdkZadEU.js +25 -0
  155. package/build/server/chunks/4-CdkZadEU.js.map +1 -0
  156. package/build/server/chunks/5-ClD9AjJX.js +25 -0
  157. package/build/server/chunks/5-ClD9AjJX.js.map +1 -0
  158. package/build/server/chunks/{2-B39zPvzn.js → 6-ifXBeMPA.js} +2 -2
  159. package/build/server/chunks/{2-B39zPvzn.js.map → 6-ifXBeMPA.js.map} +1 -1
  160. package/build/server/chunks/7-D0jTAIl_.js +81 -0
  161. package/build/server/chunks/7-D0jTAIl_.js.map +1 -0
  162. package/build/server/chunks/{4-DzHoLo__.js → 8-CgDL2fiA.js} +18 -10
  163. package/build/server/chunks/8-CgDL2fiA.js.map +1 -0
  164. package/build/server/chunks/{5-CCWbCDpk.js → 9-Dn6eMY6x.js} +6 -8
  165. package/build/server/chunks/9-Dn6eMY6x.js.map +1 -0
  166. package/build/server/chunks/JsonValue-DjUulYwg.js +290 -0
  167. package/build/server/chunks/JsonValue-DjUulYwg.js.map +1 -0
  168. package/build/server/chunks/Modal-zVnoAfFx.js +36 -0
  169. package/build/server/chunks/Modal-zVnoAfFx.js.map +1 -0
  170. package/build/server/chunks/{Panel-Bz0b85EW.js → Panel-BM545RWK.js} +4 -3
  171. package/build/server/chunks/Panel-BM545RWK.js.map +1 -0
  172. package/build/server/chunks/PrettyJson-CVemKT9n.js +137 -0
  173. package/build/server/chunks/PrettyJson-CVemKT9n.js.map +1 -0
  174. package/build/server/chunks/Tooltip-ByN2a8nn.js +38 -0
  175. package/build/server/chunks/Tooltip-ByN2a8nn.js.map +1 -0
  176. package/build/server/chunks/TooltipTable-CftpgkMV.js +60 -0
  177. package/build/server/chunks/TooltipTable-CftpgkMV.js.map +1 -0
  178. package/build/server/chunks/_layout.svelte-D8Erqrch.js +163 -0
  179. package/build/server/chunks/_layout.svelte-D8Erqrch.js.map +1 -0
  180. package/build/server/chunks/{_page.svelte-w9cxGvUf.js → _page.svelte-BZL67-Tl.js} +32 -13
  181. package/build/server/chunks/_page.svelte-BZL67-Tl.js.map +1 -0
  182. package/build/server/chunks/{_page.svelte-FIp-IsOo.js → _page.svelte-BwdDcghe.js} +63 -13
  183. package/build/server/chunks/_page.svelte-BwdDcghe.js.map +1 -0
  184. package/build/server/chunks/{_page.svelte-jxFKbZdN.js → _page.svelte-CwGhs70Z.js} +9 -6
  185. package/build/server/chunks/_page.svelte-CwGhs70Z.js.map +1 -0
  186. package/build/server/chunks/_page.svelte-DI3cZxuK.js +197 -0
  187. package/build/server/chunks/_page.svelte-DI3cZxuK.js.map +1 -0
  188. package/build/server/chunks/_page.svelte-DPUr13fG.js +203 -0
  189. package/build/server/chunks/_page.svelte-DPUr13fG.js.map +1 -0
  190. package/build/server/chunks/{_page.svelte-FLzHOuyK.js → _page.svelte-mO3b8YSb.js} +37 -20
  191. package/build/server/chunks/_page.svelte-mO3b8YSb.js.map +1 -0
  192. package/build/server/chunks/{_page.svelte-k8avSQW1.js → _page.svelte-mPOsEew6.js} +105 -30
  193. package/build/server/chunks/_page.svelte-mPOsEew6.js.map +1 -0
  194. package/build/server/chunks/_server.ts-06lGoPp8.js +8 -0
  195. package/build/server/chunks/_server.ts-06lGoPp8.js.map +1 -0
  196. package/build/server/chunks/async-lVJA8xJZ.js +9 -0
  197. package/build/server/chunks/async-lVJA8xJZ.js.map +1 -0
  198. package/build/server/chunks/client-BFlyU7ZU.js +7 -0
  199. package/build/server/chunks/{client-bj7sePQc.js.map → client-BFlyU7ZU.js.map} +1 -1
  200. package/build/server/chunks/{client2-BX4-xbM4.js → client2-DYaMKWrc.js} +4 -4
  201. package/build/server/chunks/{client2-BX4-xbM4.js.map → client2-DYaMKWrc.js.map} +1 -1
  202. package/build/server/chunks/{async-BfR0vYHo.js → context-C22hLSHK.js} +2 -8
  203. package/build/server/chunks/context-C22hLSHK.js.map +1 -0
  204. package/build/server/chunks/error.svelte-BENdaVOT.js +19 -0
  205. package/build/server/chunks/error.svelte-BENdaVOT.js.map +1 -0
  206. package/build/server/chunks/event-DVH-6ISX.js.map +1 -1
  207. package/build/server/chunks/{index-EKt9-9bV.js → index-DFXVwu6p.js} +2 -2
  208. package/build/server/chunks/{index-EKt9-9bV.js.map → index-DFXVwu6p.js.map} +1 -1
  209. package/build/server/chunks/index-Djsj11qr.js.map +1 -1
  210. package/build/server/chunks/index-server-Bf-hP5gL.js +5 -0
  211. package/build/server/chunks/index-server-Bf-hP5gL.js.map +1 -0
  212. package/build/server/chunks/{routing-DcR4fCSD.js → index2-d4SCF7oA.js} +4 -88
  213. package/build/server/chunks/index2-d4SCF7oA.js.map +1 -0
  214. package/build/server/chunks/{index3-DquTjlmp.js → index3-CoOO2o9t.js} +6 -6
  215. package/build/server/chunks/index3-CoOO2o9t.js.map +1 -0
  216. package/build/server/chunks/jsonParser-CraFXJs8.js +174 -0
  217. package/build/server/chunks/jsonParser-CraFXJs8.js.map +1 -0
  218. package/build/server/chunks/layout.svelte-CJcHX-Na.js +10 -0
  219. package/build/server/chunks/layout.svelte-CJcHX-Na.js.map +1 -0
  220. package/build/server/chunks/{mongo-dLmCShL_.js → mongo-DMG2RTBR.js} +51 -10
  221. package/build/server/chunks/mongo-DMG2RTBR.js.map +1 -0
  222. package/build/server/chunks/remote-xxtqbu-BUzBKv3P.js +16 -0
  223. package/build/server/chunks/remote-xxtqbu-BUzBKv3P.js.map +1 -0
  224. package/build/server/chunks/routing-e10vGH37.js +81 -0
  225. package/build/server/chunks/routing-e10vGH37.js.map +1 -0
  226. package/build/server/chunks/{server2-BiqGvkCy.js → server2-_mGVuBoG.js} +2 -2
  227. package/build/server/chunks/{server2-BiqGvkCy.js.map → server2-_mGVuBoG.js.map} +1 -1
  228. package/build/server/chunks/servers.remote-DKhy8wTJ.js +678 -0
  229. package/build/server/chunks/servers.remote-DKhy8wTJ.js.map +1 -0
  230. package/build/server/chunks/shared-Buki-xt5.js +506 -0
  231. package/build/server/chunks/shared-Buki-xt5.js.map +1 -0
  232. package/build/server/chunks/{state.svelte-CRHA9yov.js → state.svelte-C8IWmp_n.js} +2 -2
  233. package/build/server/chunks/{state.svelte-CRHA9yov.js.map → state.svelte-C8IWmp_n.js.map} +1 -1
  234. package/build/server/chunks/{utils-DGYJFmnf.js → utils-kjxf7BZO.js} +2 -2
  235. package/build/server/chunks/{utils-DGYJFmnf.js.map → utils-kjxf7BZO.js.map} +1 -1
  236. package/build/server/index.js +188 -609
  237. package/build/server/index.js.map +1 -1
  238. package/build/server/manifest.js +45 -18
  239. package/build/server/manifest.js.map +1 -1
  240. package/package.json +13 -2
  241. package/src/api/servers.remote.ts +369 -20
  242. package/src/app.css +98 -3
  243. package/src/app.html +15 -0
  244. package/src/lib/actions/jsonTextarea.ts +395 -0
  245. package/src/lib/components/Breadcrumbs.svelte +7 -58
  246. package/src/lib/components/JsonValue.svelte +279 -85
  247. package/src/lib/components/Modal.svelte +59 -0
  248. package/src/lib/components/OriginWarning.svelte +109 -0
  249. package/src/lib/components/PageSwitcher.svelte +37 -0
  250. package/src/lib/components/Panel.svelte +1 -1
  251. package/src/lib/components/PrettyJson.svelte +112 -36
  252. package/src/lib/components/SearchBox.svelte +161 -97
  253. package/src/lib/components/ThemeSwitcher.svelte +66 -0
  254. package/src/lib/components/Tooltip.svelte +83 -0
  255. package/src/lib/components/TooltipTable.svelte +45 -102
  256. package/src/lib/server/HostsManager.ts +4 -0
  257. package/src/lib/server/aggregation.ts +62 -0
  258. package/src/lib/server/mongo.ts +75 -13
  259. package/src/lib/types.ts +60 -0
  260. package/src/lib/utils/isEmptyObject.ts +6 -0
  261. package/src/lib/utils/jsonParser.ts +9 -1
  262. package/src/lib/utils/omit.ts +3 -0
  263. package/src/routes/+layout.server.ts +2 -1
  264. package/src/routes/+layout.svelte +11 -2
  265. package/src/routes/favicon.ico/+server.ts +8 -0
  266. package/src/routes/servers/+page.server.ts +22 -10
  267. package/src/routes/servers/+page.svelte +44 -10
  268. package/src/routes/servers/[server]/databases/+layout.ts +8 -0
  269. package/src/routes/servers/[server]/databases/+page.server.ts +14 -4
  270. package/src/routes/servers/[server]/databases/[database]/collections/+layout.ts +9 -0
  271. package/src/routes/servers/[server]/databases/[database]/collections/+page.server.ts +0 -2
  272. package/src/routes/servers/[server]/databases/[database]/collections/+page.svelte +67 -8
  273. package/src/routes/servers/[server]/databases/[database]/collections/[collection]/+layout.ts +9 -0
  274. package/src/routes/servers/[server]/databases/[database]/collections/[collection]/documents/+page.server.ts +216 -0
  275. package/src/routes/servers/[server]/databases/[database]/collections/[collection]/documents/+page.svelte +337 -0
  276. package/src/routes/servers/[server]/databases/[database]/collections/[collection]/documents/+page.ts +10 -0
  277. package/src/routes/servers/[server]/databases/[database]/collections/[collection]/documents/[document]/+layout.ts +9 -0
  278. package/src/routes/servers/[server]/databases/[database]/collections/[collection]/documents/[document]/+page.server.ts +15 -12
  279. package/src/routes/servers/[server]/databases/[database]/collections/[collection]/documents/[document]/+page.svelte +79 -5
  280. package/src/routes/servers/[server]/databases/[database]/collections/[collection]/indexes/+page.server.ts +87 -0
  281. package/src/routes/servers/[server]/databases/[database]/collections/[collection]/indexes/+page.svelte +333 -0
  282. package/src/routes/servers/[server]/databases/[database]/collections/[collection]/indexes/+page.ts +10 -0
  283. package/src/routes/servers/[server]/databases/[database]/collections/[collection]/mappings/+page.server.ts +18 -0
  284. package/src/routes/servers/[server]/databases/[database]/collections/[collection]/mappings/+page.svelte +377 -0
  285. package/src/routes/servers/[server]/databases/[database]/collections/[collection]/mappings/+page.ts +10 -0
  286. package/src/tests/api/aggregation.test.ts +125 -0
  287. package/build/client/_app/immutable/assets/0.CEsPYTp2.css +0 -1
  288. package/build/client/_app/immutable/assets/0.CEsPYTp2.css.br +0 -0
  289. package/build/client/_app/immutable/assets/0.CEsPYTp2.css.gz +0 -0
  290. package/build/client/_app/immutable/assets/6.DawdmtJd.css +0 -1
  291. package/build/client/_app/immutable/assets/6.DawdmtJd.css.br +0 -2
  292. package/build/client/_app/immutable/assets/6.DawdmtJd.css.gz +0 -0
  293. package/build/client/_app/immutable/assets/Panel.BDHMtO-3.css +0 -1
  294. package/build/client/_app/immutable/assets/Panel.BDHMtO-3.css.br +0 -0
  295. package/build/client/_app/immutable/assets/Panel.BDHMtO-3.css.gz +0 -0
  296. package/build/client/_app/immutable/assets/PrettyJson.CtngcfyW.css +0 -1
  297. package/build/client/_app/immutable/assets/PrettyJson.CtngcfyW.css.br +0 -0
  298. package/build/client/_app/immutable/assets/PrettyJson.CtngcfyW.css.gz +0 -0
  299. package/build/client/_app/immutable/chunks/B2-iEFN3.js +0 -2
  300. package/build/client/_app/immutable/chunks/B2-iEFN3.js.br +0 -0
  301. package/build/client/_app/immutable/chunks/B2-iEFN3.js.gz +0 -0
  302. package/build/client/_app/immutable/chunks/B5y2vsNr.js +0 -1
  303. package/build/client/_app/immutable/chunks/B5y2vsNr.js.br +0 -0
  304. package/build/client/_app/immutable/chunks/B5y2vsNr.js.gz +0 -0
  305. package/build/client/_app/immutable/chunks/BN_N9-2s.js +0 -1
  306. package/build/client/_app/immutable/chunks/BN_N9-2s.js.br +0 -0
  307. package/build/client/_app/immutable/chunks/BN_N9-2s.js.gz +0 -0
  308. package/build/client/_app/immutable/chunks/C1z4TjN7.js +0 -1
  309. package/build/client/_app/immutable/chunks/C1z4TjN7.js.br +0 -0
  310. package/build/client/_app/immutable/chunks/C1z4TjN7.js.gz +0 -0
  311. package/build/client/_app/immutable/chunks/CQBaNlA9.js +0 -1
  312. package/build/client/_app/immutable/chunks/CQBaNlA9.js.br +0 -0
  313. package/build/client/_app/immutable/chunks/CQBaNlA9.js.gz +0 -0
  314. package/build/client/_app/immutable/chunks/CVoOGazw.js +0 -4
  315. package/build/client/_app/immutable/chunks/CVoOGazw.js.br +0 -0
  316. package/build/client/_app/immutable/chunks/CVoOGazw.js.gz +0 -0
  317. package/build/client/_app/immutable/chunks/CapOg2jD.js +0 -1
  318. package/build/client/_app/immutable/chunks/CapOg2jD.js.br +0 -0
  319. package/build/client/_app/immutable/chunks/CapOg2jD.js.gz +0 -0
  320. package/build/client/_app/immutable/chunks/ChWB6xnu.js.br +0 -0
  321. package/build/client/_app/immutable/chunks/ChWB6xnu.js.gz +0 -0
  322. package/build/client/_app/immutable/chunks/CqnBT2zJ.js +0 -1
  323. package/build/client/_app/immutable/chunks/CqnBT2zJ.js.br +0 -0
  324. package/build/client/_app/immutable/chunks/CqnBT2zJ.js.gz +0 -0
  325. package/build/client/_app/immutable/chunks/D069mncP.js +0 -1
  326. package/build/client/_app/immutable/chunks/D069mncP.js.br +0 -0
  327. package/build/client/_app/immutable/chunks/D069mncP.js.gz +0 -0
  328. package/build/client/_app/immutable/chunks/DACrOfV_.js +0 -14
  329. package/build/client/_app/immutable/chunks/DACrOfV_.js.br +0 -0
  330. package/build/client/_app/immutable/chunks/DACrOfV_.js.gz +0 -0
  331. package/build/client/_app/immutable/chunks/DQkpHJGc.js.br +0 -0
  332. package/build/client/_app/immutable/chunks/DQkpHJGc.js.gz +0 -0
  333. package/build/client/_app/immutable/chunks/DSDD_hFT.js +0 -1
  334. package/build/client/_app/immutable/chunks/DSDD_hFT.js.br +0 -0
  335. package/build/client/_app/immutable/chunks/DSDD_hFT.js.gz +0 -0
  336. package/build/client/_app/immutable/chunks/D_aTX_ol.js +0 -1
  337. package/build/client/_app/immutable/chunks/D_aTX_ol.js.br +0 -0
  338. package/build/client/_app/immutable/chunks/D_aTX_ol.js.gz +0 -0
  339. package/build/client/_app/immutable/chunks/Dg3qHExF.js +0 -1
  340. package/build/client/_app/immutable/chunks/Dg3qHExF.js.br +0 -0
  341. package/build/client/_app/immutable/chunks/Dg3qHExF.js.gz +0 -0
  342. package/build/client/_app/immutable/chunks/Dt6-JRym.js +0 -2
  343. package/build/client/_app/immutable/chunks/Dt6-JRym.js.br +0 -0
  344. package/build/client/_app/immutable/chunks/Dt6-JRym.js.gz +0 -0
  345. package/build/client/_app/immutable/chunks/QoKxaG0e.js +0 -1
  346. package/build/client/_app/immutable/chunks/QoKxaG0e.js.br +0 -2
  347. package/build/client/_app/immutable/chunks/QoKxaG0e.js.gz +0 -0
  348. package/build/client/_app/immutable/chunks/rtveiEyS.js +0 -1
  349. package/build/client/_app/immutable/chunks/rtveiEyS.js.br +0 -0
  350. package/build/client/_app/immutable/chunks/rtveiEyS.js.gz +0 -0
  351. package/build/client/_app/immutable/entry/app.Cc1FNLNH.js +0 -2
  352. package/build/client/_app/immutable/entry/app.Cc1FNLNH.js.br +0 -0
  353. package/build/client/_app/immutable/entry/app.Cc1FNLNH.js.gz +0 -0
  354. package/build/client/_app/immutable/entry/start.CwqlbFyy.js +0 -1
  355. package/build/client/_app/immutable/entry/start.CwqlbFyy.js.br +0 -2
  356. package/build/client/_app/immutable/entry/start.CwqlbFyy.js.gz +0 -0
  357. package/build/client/_app/immutable/nodes/0.wBQEpdjZ.js +0 -1
  358. package/build/client/_app/immutable/nodes/0.wBQEpdjZ.js.br +0 -0
  359. package/build/client/_app/immutable/nodes/0.wBQEpdjZ.js.gz +0 -0
  360. package/build/client/_app/immutable/nodes/1.K6-n7D0b.js +0 -1
  361. package/build/client/_app/immutable/nodes/1.K6-n7D0b.js.br +0 -0
  362. package/build/client/_app/immutable/nodes/1.K6-n7D0b.js.gz +0 -0
  363. package/build/client/_app/immutable/nodes/3.DkGcIF98.js +0 -1
  364. package/build/client/_app/immutable/nodes/3.DkGcIF98.js.br +0 -0
  365. package/build/client/_app/immutable/nodes/3.DkGcIF98.js.gz +0 -0
  366. package/build/client/_app/immutable/nodes/4.C_NxbT98.js +0 -1
  367. package/build/client/_app/immutable/nodes/4.C_NxbT98.js.br +0 -0
  368. package/build/client/_app/immutable/nodes/4.C_NxbT98.js.gz +0 -0
  369. package/build/client/_app/immutable/nodes/5.CFvfYaLM.js +0 -1
  370. package/build/client/_app/immutable/nodes/5.CFvfYaLM.js.br +0 -0
  371. package/build/client/_app/immutable/nodes/5.CFvfYaLM.js.gz +0 -0
  372. package/build/client/_app/immutable/nodes/6.h34Zyorq.js +0 -1
  373. package/build/client/_app/immutable/nodes/6.h34Zyorq.js.br +0 -0
  374. package/build/client/_app/immutable/nodes/6.h34Zyorq.js.gz +0 -0
  375. package/build/client/_app/immutable/nodes/7.BVJmNbU5.js +0 -1
  376. package/build/client/_app/immutable/nodes/7.BVJmNbU5.js.br +0 -0
  377. package/build/client/_app/immutable/nodes/7.BVJmNbU5.js.gz +0 -0
  378. package/build/server/chunks/0-Cb5ytlMI.js.map +0 -1
  379. package/build/server/chunks/1-Cpb7zRtJ.js +0 -9
  380. package/build/server/chunks/1-Cpb7zRtJ.js.map +0 -1
  381. package/build/server/chunks/3-B_DkgZkc.js +0 -69
  382. package/build/server/chunks/3-B_DkgZkc.js.map +0 -1
  383. package/build/server/chunks/4-DzHoLo__.js.map +0 -1
  384. package/build/server/chunks/5-CCWbCDpk.js.map +0 -1
  385. package/build/server/chunks/6-Dok8svjB.js +0 -202
  386. package/build/server/chunks/6-Dok8svjB.js.map +0 -1
  387. package/build/server/chunks/7-CmgJSG2j.js +0 -42
  388. package/build/server/chunks/7-CmgJSG2j.js.map +0 -1
  389. package/build/server/chunks/Panel-Bz0b85EW.js.map +0 -1
  390. package/build/server/chunks/PrettyJson-CX6-dNsW.js +0 -291
  391. package/build/server/chunks/PrettyJson-CX6-dNsW.js.map +0 -1
  392. package/build/server/chunks/TooltipTable-0z4HkHlH.js +0 -17
  393. package/build/server/chunks/TooltipTable-0z4HkHlH.js.map +0 -1
  394. package/build/server/chunks/_layout.svelte-UiDiCQEz.js +0 -111
  395. package/build/server/chunks/_layout.svelte-UiDiCQEz.js.map +0 -1
  396. package/build/server/chunks/_page.svelte-FIp-IsOo.js.map +0 -1
  397. package/build/server/chunks/_page.svelte-FLzHOuyK.js.map +0 -1
  398. package/build/server/chunks/_page.svelte-jxFKbZdN.js.map +0 -1
  399. package/build/server/chunks/_page.svelte-k8avSQW1.js.map +0 -1
  400. package/build/server/chunks/_page.svelte-w9cxGvUf.js.map +0 -1
  401. package/build/server/chunks/async-BfR0vYHo.js.map +0 -1
  402. package/build/server/chunks/client-bj7sePQc.js +0 -7
  403. package/build/server/chunks/error.svelte-D5sIJv3P.js +0 -18
  404. package/build/server/chunks/error.svelte-D5sIJv3P.js.map +0 -1
  405. package/build/server/chunks/index3-DquTjlmp.js.map +0 -1
  406. package/build/server/chunks/mongo-dLmCShL_.js.map +0 -1
  407. package/build/server/chunks/remote-xxtqbu-BFzaWXy0.js +0 -234
  408. package/build/server/chunks/remote-xxtqbu-BFzaWXy0.js.map +0 -1
  409. package/build/server/chunks/routing-DcR4fCSD.js.map +0 -1
  410. package/src/routes/servers/[server]/databases/[database]/collections/[collection]/+page.server.ts +0 -106
  411. package/src/routes/servers/[server]/databases/[database]/collections/[collection]/+page.svelte +0 -174
  412. /package/build/client/_app/immutable/assets/{3.CRKE8WvY.css → 7.CRKE8WvY.css} +0 -0
  413. /package/build/client/_app/immutable/assets/{3.CRKE8WvY.css.br → 7.CRKE8WvY.css.br} +0 -0
  414. /package/build/client/_app/immutable/assets/{3.CRKE8WvY.css.gz → 7.CRKE8WvY.css.gz} +0 -0
@@ -1,5 +1,6 @@
1
1
  <script lang="ts">
2
- import { tick, type Snippet } from "svelte";
2
+ import type { Snippet } from "svelte";
3
+ import Tooltip from "./Tooltip.svelte";
3
4
 
4
5
  interface TableColumn {
5
6
  header: string;
@@ -24,17 +25,6 @@
24
25
  } = $props();
25
26
 
26
27
  let showTooltip = $state(false);
27
- let tooltipElement = $state<HTMLDivElement>();
28
- let containerElement = $state<HTMLDivElement>();
29
-
30
- let tooltipPosition = $state({
31
- left: "",
32
- right: "",
33
- top: "",
34
- bottom: "",
35
- marginTop: "",
36
- marginBottom: "",
37
- });
38
28
 
39
29
  function handleMouseEnter() {
40
30
  showTooltip = true;
@@ -43,95 +33,48 @@
43
33
  function handleMouseLeave() {
44
34
  showTooltip = false;
45
35
  }
46
-
47
- $effect(() => {
48
- if (showTooltip && tooltipElement && containerElement) {
49
- tick().then(() => {
50
- if (!containerElement || !tooltipElement) return;
51
-
52
- const tooltipRect = tooltipElement.getBoundingClientRect();
53
- const viewportWidth = window.innerWidth;
54
- const viewportHeight = window.innerHeight;
55
-
56
- // Reset positioning
57
- tooltipPosition = {
58
- left: "",
59
- right: "",
60
- top: "",
61
- bottom: "",
62
- marginTop: "",
63
- marginBottom: "",
64
- };
65
-
66
- // Position horizontally
67
- if (tooltipRect.right > viewportWidth) {
68
- tooltipPosition.right = "0";
69
- } else {
70
- tooltipPosition.left = "0";
71
- }
72
-
73
- // Position vertically
74
- if (tooltipRect.bottom > viewportHeight) {
75
- tooltipPosition.bottom = "100%";
76
- tooltipPosition.marginBottom = "5px";
77
- } else {
78
- tooltipPosition.top = "100%";
79
- tooltipPosition.marginTop = "5px";
80
- }
81
- });
82
- }
83
- });
84
36
  </script>
85
37
 
86
- <div class="relative inline-block" bind:this={containerElement}>
87
- <button class="dotted text-center" onmouseenter={handleMouseEnter} onmouseleave={handleMouseLeave}>
88
- {@render children?.()}
89
- </button>
90
- {#if showTooltip}
91
- <div
92
- class="absolute bg-[var(--color-2)] border border-[var(--color-3)] rounded p-0 z-[1000] whitespace-nowrap shadow-lg"
93
- bind:this={tooltipElement}
94
- style:left={tooltipPosition.left}
95
- style:right={tooltipPosition.right}
96
- style:top={tooltipPosition.top}
97
- style:bottom={tooltipPosition.bottom}
98
- style:margin-top={tooltipPosition.marginTop}
99
- style:margin-bottom={tooltipPosition.marginBottom}
100
- >
101
- <table class="w-full border-collapse text-base font-medium">
102
- {#if !hideHeader}
103
- <thead>
104
- <tr>
105
- {#each columns as column, index (index)}
106
- <th
107
- class="px-2 py-1 border-b border-[var(--color-3)] bg-[var(--color-4)] font-bold"
108
- class:text-left={column.align === "left" || !column.align}
109
- class:text-right={column.align === "right"}
110
- class:text-center={column.align === "center"}
111
- >
112
- {column.header}
113
- </th>
114
- {/each}
115
- </tr>
116
- </thead>
117
- {/if}
118
- <tbody>
119
- {#each rows as row, index (index)}
120
- <tr>
121
- {#each columns as column, index (index)}
122
- <td
123
- class="px-2 py-1 border-b border-[var(--color-3)]"
124
- class:text-left={column.align === "left" || !column.align}
125
- class:text-right={column.align === "right"}
126
- class:text-center={column.align === "center"}
127
- >
128
- {row[column.key]}
129
- </td>
130
- {/each}
131
- </tr>
132
- {/each}
133
- </tbody>
134
- </table>
135
- </div>
136
- {/if}
137
- </div>
38
+ <Tooltip show={showTooltip} tooltipClass="p-0 whitespace-nowrap">
39
+ {#snippet trigger()}
40
+ <button class="dotted text-center" onmouseenter={handleMouseEnter} onmouseleave={handleMouseLeave}>
41
+ {@render children?.()}
42
+ </button>
43
+ {/snippet}
44
+ {#snippet content()}
45
+ <table class="w-full border-collapse text-base font-medium">
46
+ {#if !hideHeader}
47
+ <thead>
48
+ <tr>
49
+ {#each columns as column, index (index)}
50
+ <th
51
+ class="px-2 py-1 border-b border-[var(--color-3)] bg-[var(--color-4)] font-bold"
52
+ class:text-left={column.align === "left" || !column.align}
53
+ class:text-right={column.align === "right"}
54
+ class:text-center={column.align === "center"}
55
+ >
56
+ {column.header}
57
+ </th>
58
+ {/each}
59
+ </tr>
60
+ </thead>
61
+ {/if}
62
+ <tbody>
63
+ {#each rows as row, index (index)}
64
+ <tr>
65
+ {#each columns as column, index (index)}
66
+ <td
67
+ class="px-2 py-1 border-b border-[var(--color-3)]"
68
+ class:text-left={column.align === "left" || !column.align}
69
+ class:text-right={column.align === "right"}
70
+ class:text-center={column.align === "center"}
71
+ >
72
+ {row[column.key]}
73
+ </td>
74
+ {/each}
75
+ </tr>
76
+ {/each}
77
+ </tbody>
78
+ </table>
79
+ {/snippet}
80
+ </Tooltip>
@@ -74,6 +74,10 @@ export class HostsManager {
74
74
  return Array.from(this._hosts).map(([hostPath, id]) => ({ path: hostPath, _id: id }));
75
75
  }
76
76
 
77
+ getHost(name: string): string | undefined {
78
+ return this._hosts.get(name);
79
+ }
80
+
77
81
  async add(hostPath: string): Promise<string> {
78
82
  // Use existing ID if host already exists, generate new one if not
79
83
  let id = this._hosts.get(hostPath);
@@ -0,0 +1,62 @@
1
+ export const ALLOWED_AGGREGATION_STAGES = new Set([
2
+ "$addFields",
3
+ "$bucket",
4
+ "$bucketAuto",
5
+ "$collStats",
6
+ "$count",
7
+ "$densify",
8
+ "$documents",
9
+ "$facet",
10
+ "$fill",
11
+ "$geoNear",
12
+ "$graphLookup",
13
+ "$group",
14
+ "$indexStats",
15
+ "$limit",
16
+ "$listClusterCatalog",
17
+ "$listSampledQueries",
18
+ "$listSearchIndexes",
19
+ "$listSessions",
20
+ "$lookup",
21
+ "$match",
22
+ "$project",
23
+ "$querySettings",
24
+ "$queryStats",
25
+ "$rankFusion",
26
+ "$redact",
27
+ "$replaceRoot",
28
+ "$replaceWith",
29
+ "$sample",
30
+ "$search",
31
+ "$searchMeta",
32
+ "$set",
33
+ "$setWindowFields",
34
+ "$skip",
35
+ "$sort",
36
+ "$sortByCount",
37
+ "$unionWith",
38
+ "$unset",
39
+ "$unwind",
40
+ "$vectorSearch",
41
+ ]);
42
+
43
+ export function validateAggregationPipeline(pipeline: unknown[]): void {
44
+ for (let i = 0; i < pipeline.length; i++) {
45
+ const stage = pipeline[i];
46
+ if (!stage || typeof stage !== "object") {
47
+ throw new Error(`Invalid stage at index ${i}: must be an object`);
48
+ }
49
+
50
+ const stageKeys = Object.keys(stage);
51
+ if (stageKeys.length !== 1) {
52
+ throw new Error(`Invalid stage at index ${i}: must have exactly one key, found ${stageKeys.length}`);
53
+ }
54
+
55
+ const stageOperator = stageKeys[0];
56
+ if (!ALLOWED_AGGREGATION_STAGES.has(stageOperator)) {
57
+ throw new Error(
58
+ `Disallowed stage operator at index ${i}: "${stageOperator}". Only allowed stages are permitted, to avoid future write stages like '$merge' or '$out'.`,
59
+ );
60
+ }
61
+ }
62
+ }
@@ -1,4 +1,4 @@
1
- import type { CollectionJSON } from "$lib/types";
1
+ import type { CollectionJSON, CollectionMappings, Mappings } from "$lib/types";
2
2
  import { MongoClient, type Collection } from "mongodb";
3
3
  import { URL } from "url";
4
4
  import { HostsManager } from "./HostsManager";
@@ -87,18 +87,48 @@ export async function getCollectionJson(
87
87
  };
88
88
  }
89
89
 
90
+ class MongoClientWithMappings extends MongoClient {
91
+ mappings: Record<string, Record<string, Mappings>> = {};
92
+
93
+ async getMappings(dbName: string, collectionName: string, opts?: { forceRefresh?: boolean }): Promise<Mappings> {
94
+ if (opts?.forceRefresh || !this.mappings[dbName]?.[collectionName]) {
95
+ const mappings = await this.db(dbName)
96
+ .collection<CollectionMappings>("mongoku.mappings")
97
+ .findOne({ _id: collectionName });
98
+ this.mappings[dbName] ??= {};
99
+ this.mappings[dbName][collectionName] = mappings?.mappings ?? {};
100
+ }
101
+ return this.mappings[dbName][collectionName];
102
+ }
103
+ clearMappingsCache(dbName: string, collectionName: string) {
104
+ delete this.mappings[dbName][collectionName];
105
+ }
106
+ }
107
+
90
108
  class MongoConnections {
91
109
  /**
92
110
  * Todo: better system where we can have mutiple servers with same hostname, and labels for each server that
93
111
  * would be displayed in the UI instead of the hostname.
94
112
  */
95
- private clients: Map<string, MongoClient> = new Map();
113
+ private clients: Map<string, MongoClientWithMappings> = new Map();
96
114
  private clientIds: Map<string, string> = new Map(); // hostname -> _id
97
115
  private hostsManager: HostsManager;
98
- private countTimeout = parseInt(process.env.MONGOKU_COUNT_TIMEOUT!, 10) || 5000;
116
+ private countTimeout = parseInt(process.env.MONGOKU_COUNT_TIMEOUT!, 10) || 30_000;
117
+ private queryTimeout = process.env.MONGOKU_QUERY_TIMEOUT
118
+ ? parseInt(process.env.MONGOKU_QUERY_TIMEOUT, 10)
119
+ : undefined;
120
+ private excludedDatabases: Set<string>;
99
121
 
100
122
  constructor() {
101
123
  this.hostsManager = new HostsManager();
124
+ // Parse MONGOKU_EXCLUDE_DATABASES env var (comma-separated list)
125
+ const excludeEnv = process.env.MONGOKU_EXCLUDE_DATABASES || "";
126
+ this.excludedDatabases = new Set(
127
+ excludeEnv
128
+ .split(",")
129
+ .map((db) => db.trim())
130
+ .filter((db) => db.length > 0),
131
+ );
102
132
  }
103
133
 
104
134
  async initialize() {
@@ -113,7 +143,7 @@ class MongoConnections {
113
143
  const hostname = url.host || host.path;
114
144
 
115
145
  if (!this.clients.has(hostname)) {
116
- const client = new MongoClient(urlStr);
146
+ const client = new MongoClientWithMappings(urlStr);
117
147
  this.clients.set(hostname, client);
118
148
  this.clientIds.set(hostname, host._id);
119
149
  }
@@ -123,10 +153,10 @@ class MongoConnections {
123
153
  }
124
154
  }
125
155
 
126
- getClient(name: string): MongoClient {
156
+ getClient(name: string): MongoClientWithMappings {
127
157
  const client = this.clients.get(name) || this.clients.get(`${name}:27017`);
128
158
  if (!client) {
129
- throw new Error("Server does not exist");
159
+ throw new Error(`Client not found: ${name}`);
130
160
  }
131
161
  return client;
132
162
  }
@@ -141,16 +171,21 @@ class MongoConnections {
141
171
  }));
142
172
  }
143
173
 
144
- getCollection(serverName: string, databaseName: string, collectionName: string) {
145
- const client = this.getClient(serverName);
146
- const db = client.db(databaseName);
147
- return db.collection(collectionName);
148
- }
149
-
150
174
  getCountTimeout() {
151
175
  return this.countTimeout;
152
176
  }
153
177
 
178
+ getQueryTimeout() {
179
+ return this.queryTimeout;
180
+ }
181
+
182
+ filterDatabases<T extends { name: string }>(databases: T[]): T[] {
183
+ if (this.excludedDatabases.size === 0) {
184
+ return databases;
185
+ }
186
+ return databases.filter((db) => !this.excludedDatabases.has(db.name));
187
+ }
188
+
154
189
  async addServer(hostPath: string) {
155
190
  const id = await this.hostsManager.add(hostPath);
156
191
 
@@ -161,7 +196,7 @@ class MongoConnections {
161
196
  const hostname = url.host || hostPath;
162
197
 
163
198
  if (!this.clients.has(hostname)) {
164
- const client = new MongoClient(urlStr);
199
+ const client = new MongoClientWithMappings(urlStr);
165
200
  this.clients.set(hostname, client);
166
201
  this.clientIds.set(hostname, id);
167
202
  }
@@ -173,9 +208,36 @@ class MongoConnections {
173
208
 
174
209
  async removeServer(name: string) {
175
210
  await this.hostsManager.remove(name);
211
+
212
+ this.clients
213
+ .get(name)
214
+ ?.close()
215
+ .catch((err) => console.error(`Error closing client ${name}:`, err));
176
216
  this.clients.delete(name);
177
217
  this.clientIds.delete(name);
178
218
  }
219
+
220
+ async reconnectClient(name: string) {
221
+ // Try to find the connection string with the same logic as getClient
222
+ const connectionString = this.hostsManager.getHost(name);
223
+
224
+ if (!connectionString) {
225
+ throw new Error(`Connection string not found for client: ${name}`);
226
+ }
227
+
228
+ // Close the old client
229
+ const oldClient = this.clients.get(name);
230
+ if (oldClient) {
231
+ oldClient.close()?.catch((err) => console.error(`Error closing old client ${name}:`, err));
232
+ }
233
+
234
+ // Create a new client
235
+ const newClient = new MongoClientWithMappings(connectionString);
236
+ this.clients.set(name, newClient);
237
+
238
+ // Test the connection
239
+ await newClient.connect();
240
+ }
179
241
  }
180
242
 
181
243
  // Singleton instance
package/src/lib/types.ts CHANGED
@@ -54,3 +54,63 @@ export interface CollectionJSON {
54
54
  size: number;
55
55
  }>;
56
56
  }
57
+
58
+ export const ALLOWED_AGGREGATION_STAGES = new Set([
59
+ "$addFields",
60
+ "$bucket",
61
+ "$bucketAuto",
62
+ "$collStats",
63
+ "$count",
64
+ "$densify",
65
+ "$documents",
66
+ "$facet",
67
+ "$fill",
68
+ "$geoNear",
69
+ "$graphLookup",
70
+ "$group",
71
+ "$indexStats",
72
+ "$limit",
73
+ "$listClusterCatalog",
74
+ "$listSampledQueries",
75
+ "$listSearchIndexes",
76
+ "$listSessions",
77
+ "$lookup",
78
+ "$match",
79
+ "$project",
80
+ "$querySettings",
81
+ "$queryStats",
82
+ "$rankFusion",
83
+ "$redact",
84
+ "$replaceRoot",
85
+ "$replaceWith",
86
+ "$sample",
87
+ "$search",
88
+ "$searchMeta",
89
+ "$set",
90
+ "$setWindowFields",
91
+ "$skip",
92
+ "$sort",
93
+ "$sortByCount",
94
+ "$unionWith",
95
+ "$unset",
96
+ "$unwind",
97
+ "$vectorSearch",
98
+ ]);
99
+
100
+ /**
101
+ * A single mapping target - defines which collection and field to lookup
102
+ */
103
+ export interface MappingTarget {
104
+ collection: string;
105
+ on: string;
106
+ }
107
+
108
+ export type Mappings = Record<string, MappingTarget[] | MappingTarget>;
109
+
110
+ /**
111
+ * Collection mappings document structure as stored in mongoku.mappings
112
+ */
113
+ export interface CollectionMappings {
114
+ _id: string; // collection name
115
+ mappings: Mappings;
116
+ }
@@ -0,0 +1,6 @@
1
+ export function isEmptyObject(obj: object): boolean {
2
+ for (const key in obj) {
3
+ return false;
4
+ }
5
+ return true;
6
+ }
@@ -98,6 +98,9 @@ function buildObject(node: Node | Expression): unknown {
98
98
  if (node.name === "undefined") {
99
99
  return undefined;
100
100
  }
101
+ if (node.name === "Infinity") {
102
+ return Infinity;
103
+ }
101
104
  throw `Unknown identifier: ${node.name}`;
102
105
  }
103
106
 
@@ -106,7 +109,7 @@ function buildObject(node: Node | Expression): unknown {
106
109
  }
107
110
  }
108
111
 
109
- export function parseJSON(text: string): unknown {
112
+ export function parseJSON(text: string, opts?: { allowArray?: boolean }): unknown {
110
113
  const tree = parseScript(`var __JSON__ = ${text};`, {
111
114
  tolerant: true,
112
115
  });
@@ -117,6 +120,11 @@ export function parseJSON(text: string): unknown {
117
120
  }
118
121
 
119
122
  const objExpression = varDeclaration.declarations[0].init;
123
+
124
+ if (opts?.allowArray && objExpression?.type === "ArrayExpression") {
125
+ return buildObject(objExpression);
126
+ }
127
+
120
128
  if (objExpression?.type !== "ObjectExpression") {
121
129
  throw new Error("Expected ObjectExpression but received: " + objExpression?.type);
122
130
  }
@@ -0,0 +1,3 @@
1
+ export function omit<T extends object, K extends keyof T>(obj: T, keys: K[]): Omit<T, K> {
2
+ return Object.fromEntries(Object.entries(obj).filter(([key]) => !keys.includes(key as K))) as Omit<T, K>;
3
+ }
@@ -1,7 +1,8 @@
1
1
  import type { LayoutServerLoad } from "./$types";
2
2
 
3
- export const load: LayoutServerLoad = async () => {
3
+ export const load: LayoutServerLoad = async (event) => {
4
4
  return {
5
5
  readOnly: process.env.MONGOKU_READ_ONLY_MODE === "true",
6
+ serverOrigin: event.url.origin,
6
7
  };
7
8
  };
@@ -2,17 +2,26 @@
2
2
  import { resolve } from "$app/paths";
3
3
  import Breadcrumbs from "$lib/components/Breadcrumbs.svelte";
4
4
  import Notifications from "$lib/components/Notifications.svelte";
5
+ import OriginWarning from "$lib/components/OriginWarning.svelte";
6
+ import PageSwitcher from "$lib/components/PageSwitcher.svelte";
7
+ import ThemeSwitcher from "$lib/components/ThemeSwitcher.svelte";
5
8
  import "../app.css";
6
9
 
7
- let { children } = $props();
10
+ let { children, data } = $props();
8
11
  </script>
9
12
 
10
13
  <div style="min-height: 100vh">
11
14
  <nav class="navbar px-6 py-4 flex items-center">
12
15
  <a href={resolve("/")} class="text-2xl font-medium">Mongoku</a>
13
16
  <Breadcrumbs />
17
+ <div class="ml-auto flex items-center gap-2">
18
+ <PageSwitcher class="" />
19
+ <ThemeSwitcher />
20
+ </div>
14
21
  </nav>
15
22
 
23
+ <OriginWarning serverOrigin={data.serverOrigin} readOnly={data.readOnly} />
24
+
16
25
  <div class="px-6 py-6 flex flex-col gap-6">
17
26
  <Notifications />
18
27
  {@render children()}
@@ -21,7 +30,7 @@
21
30
 
22
31
  <style lang="postcss">
23
32
  .navbar {
24
- background-color: var(--color-2);
33
+ background-color: var(--light-background);
25
34
  border-bottom: var(--border);
26
35
  }
27
36
  </style>
@@ -0,0 +1,8 @@
1
+ import type { RequestHandler } from "./$types";
2
+
3
+ // No official icon yet, avoid sveltekite errors
4
+ export const GET: RequestHandler = async () => {
5
+ return new Response(null, {
6
+ status: 404,
7
+ });
8
+ };
@@ -12,16 +12,24 @@ export const load: PageServerLoad = async () => {
12
12
  try {
13
13
  const adminDb = client.db("test").admin();
14
14
  const results = await adminDb.listDatabases();
15
+ const filteredDatabases = mongo.filterDatabases(results.databases);
15
16
  const collectionsCount = await Promise.all(
16
- results.databases.map(async (d) => {
17
+ filteredDatabases.map(async (d) => {
17
18
  const db = client.db(d.name);
18
- const dbStats = (await db.stats()) as DatabaseStats;
19
+ const dbStats: Pick<DatabaseStats, "collections"> = await (db.stats() as Promise<DatabaseStats>).catch(
20
+ () => {
21
+ console.error(`Error getting stats for database ${d.name} on server ${name}`);
22
+ return {
23
+ collections: 0,
24
+ };
25
+ },
26
+ );
19
27
  return dbStats.collections;
20
28
  }),
21
29
  );
22
30
 
23
31
  return {
24
- databases: results.databases.map((d, index) => ({
32
+ databases: filteredDatabases.map((d, index) => ({
25
33
  name: d.name,
26
34
  size: d.sizeOnDisk ?? 0,
27
35
  collections: collectionsCount[index],
@@ -29,6 +37,7 @@ export const load: PageServerLoad = async () => {
29
37
  size: results.totalSize ?? 0,
30
38
  };
31
39
  } catch (err) {
40
+ console.error(`Error getting details for server ${name}:`, err);
32
41
  return {
33
42
  error: {
34
43
  code: err instanceof Error && "code" in err ? err.code : undefined,
@@ -37,13 +46,16 @@ export const load: PageServerLoad = async () => {
37
46
  },
38
47
  };
39
48
  }
40
- })().catch((err) => ({
41
- error: {
42
- code: err instanceof Error && "code" in err ? err.code : undefined,
43
- name: err instanceof Error ? err.name : "Error",
44
- message: err instanceof Error ? err.message : String(err),
45
- },
46
- })),
49
+ })().catch((err) => {
50
+ console.error(`Error getting details for server ${name}:`, err);
51
+ return {
52
+ error: {
53
+ code: err instanceof Error && "code" in err ? err.code : undefined,
54
+ name: err instanceof Error ? err.name : "Error",
55
+ message: err instanceof Error ? err.message : String(err),
56
+ },
57
+ };
58
+ }),
47
59
  }));
48
60
 
49
61
  servers.sort((a, b) => a.name.localeCompare(b.name));