mongoku 2.0.4 → 2.1.1
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.
- package/README.md +18 -4
- package/build/client/_app/immutable/assets/0.egX7ddQL.css +1 -0
- package/build/client/_app/immutable/assets/0.egX7ddQL.css.br +0 -0
- package/build/client/_app/immutable/assets/0.egX7ddQL.css.gz +0 -0
- package/build/client/_app/immutable/assets/10.59aTjJn9.css +1 -0
- package/build/client/_app/immutable/assets/10.59aTjJn9.css.br +0 -0
- package/build/client/_app/immutable/assets/10.59aTjJn9.css.gz +0 -0
- package/build/client/_app/immutable/assets/11.CEtFGlZU.css +1 -0
- package/build/client/_app/immutable/assets/11.CEtFGlZU.css.br +1 -0
- package/build/client/_app/immutable/assets/11.CEtFGlZU.css.gz +0 -0
- package/build/client/_app/immutable/assets/12.BdCOhvz0.css +1 -0
- package/build/client/_app/immutable/assets/12.BdCOhvz0.css.br +0 -0
- package/build/client/_app/immutable/assets/12.BdCOhvz0.css.gz +0 -0
- package/build/client/_app/immutable/assets/JsonValue.BEbzuWqZ.css +1 -0
- package/build/client/_app/immutable/assets/JsonValue.BEbzuWqZ.css.br +0 -0
- package/build/client/_app/immutable/assets/JsonValue.BEbzuWqZ.css.gz +0 -0
- package/build/client/_app/immutable/assets/Modal.DIIFkbGB.css +1 -0
- package/build/client/_app/immutable/assets/Modal.DIIFkbGB.css.br +0 -0
- package/build/client/_app/immutable/assets/Modal.DIIFkbGB.css.gz +0 -0
- package/build/client/_app/immutable/assets/Panel.B3aWupye.css +1 -0
- package/build/client/_app/immutable/assets/Panel.B3aWupye.css.br +0 -0
- package/build/client/_app/immutable/assets/Panel.B3aWupye.css.gz +0 -0
- package/build/client/_app/immutable/chunks/3iRu_dUj.js +2 -0
- package/build/client/_app/immutable/chunks/3iRu_dUj.js.br +0 -0
- package/build/client/_app/immutable/chunks/3iRu_dUj.js.gz +0 -0
- package/build/client/_app/immutable/chunks/{ChWB6xnu.js → 4l_AWZos.js} +1 -1
- package/build/client/_app/immutable/chunks/4l_AWZos.js.br +0 -0
- package/build/client/_app/immutable/chunks/4l_AWZos.js.gz +0 -0
- package/build/client/_app/immutable/chunks/5nAxkTTP.js +1 -0
- package/build/client/_app/immutable/chunks/5nAxkTTP.js.br +5 -0
- package/build/client/_app/immutable/chunks/5nAxkTTP.js.gz +0 -0
- package/build/client/_app/immutable/chunks/BBg-V8FE.js +1 -0
- package/build/client/_app/immutable/chunks/BBg-V8FE.js.br +0 -0
- package/build/client/_app/immutable/chunks/BBg-V8FE.js.gz +0 -0
- package/build/client/_app/immutable/chunks/BE8UzJuY.js +1 -0
- package/build/client/_app/immutable/chunks/BE8UzJuY.js.br +0 -0
- package/build/client/_app/immutable/chunks/BE8UzJuY.js.gz +0 -0
- package/build/client/_app/immutable/chunks/BUNgwIS0.js +1 -0
- package/build/client/_app/immutable/chunks/BUNgwIS0.js.br +0 -0
- package/build/client/_app/immutable/chunks/BUNgwIS0.js.gz +0 -0
- package/build/client/_app/immutable/chunks/BjzB4NFq.js +1 -0
- package/build/client/_app/immutable/chunks/BjzB4NFq.js.br +0 -0
- package/build/client/_app/immutable/chunks/BjzB4NFq.js.gz +0 -0
- package/build/client/_app/immutable/chunks/BtCOrwSt.js +1 -0
- package/build/client/_app/immutable/chunks/BtCOrwSt.js.br +0 -0
- package/build/client/_app/immutable/chunks/BtCOrwSt.js.gz +0 -0
- package/build/client/_app/immutable/chunks/BvKY81hz.js +1 -0
- package/build/client/_app/immutable/chunks/BvKY81hz.js.br +0 -0
- package/build/client/_app/immutable/chunks/BvKY81hz.js.gz +0 -0
- package/build/client/_app/immutable/chunks/{DQkpHJGc.js → C0PCwpqt.js} +1 -1
- package/build/client/_app/immutable/chunks/C0PCwpqt.js.br +0 -0
- package/build/client/_app/immutable/chunks/C0PCwpqt.js.gz +0 -0
- package/build/client/_app/immutable/chunks/C82Rp5eQ.js +1 -0
- package/build/client/_app/immutable/chunks/C82Rp5eQ.js.br +0 -0
- package/build/client/_app/immutable/chunks/C82Rp5eQ.js.gz +0 -0
- package/build/client/_app/immutable/chunks/CEvYYWlm.js +2 -0
- package/build/client/_app/immutable/chunks/CEvYYWlm.js.br +0 -0
- package/build/client/_app/immutable/chunks/CEvYYWlm.js.gz +0 -0
- package/build/client/_app/immutable/chunks/CT5SFbzp.js +1 -0
- package/build/client/_app/immutable/chunks/CT5SFbzp.js.br +0 -0
- package/build/client/_app/immutable/chunks/CT5SFbzp.js.gz +0 -0
- package/build/client/_app/immutable/chunks/CcyPStn-.js +1 -0
- package/build/client/_app/immutable/chunks/CcyPStn-.js.br +0 -0
- package/build/client/_app/immutable/chunks/CcyPStn-.js.gz +0 -0
- package/build/client/_app/immutable/chunks/Cx2cA4gg.js +1 -0
- package/build/client/_app/immutable/chunks/Cx2cA4gg.js.br +0 -0
- package/build/client/_app/immutable/chunks/Cx2cA4gg.js.gz +0 -0
- package/build/client/_app/immutable/chunks/D5ccpaXt.js +1 -0
- package/build/client/_app/immutable/chunks/D5ccpaXt.js.br +0 -0
- package/build/client/_app/immutable/chunks/D5ccpaXt.js.gz +0 -0
- package/build/client/_app/immutable/chunks/D64wQeYi.js +1 -0
- package/build/client/_app/immutable/chunks/D64wQeYi.js.br +0 -0
- package/build/client/_app/immutable/chunks/D64wQeYi.js.gz +0 -0
- package/build/client/_app/immutable/chunks/D7E46CWw.js +1 -0
- package/build/client/_app/immutable/chunks/D7E46CWw.js.br +0 -0
- package/build/client/_app/immutable/chunks/D7E46CWw.js.gz +0 -0
- package/build/client/_app/immutable/chunks/DR9xdhsg.js +1 -0
- package/build/client/_app/immutable/chunks/DR9xdhsg.js.br +0 -0
- package/build/client/_app/immutable/chunks/DR9xdhsg.js.gz +0 -0
- package/build/client/_app/immutable/chunks/DVJuGan7.js +1 -0
- package/build/client/_app/immutable/chunks/DVJuGan7.js.br +0 -0
- package/build/client/_app/immutable/chunks/DVJuGan7.js.gz +0 -0
- package/build/client/_app/immutable/chunks/Dx86XS0G.js +1 -0
- package/build/client/_app/immutable/chunks/Dx86XS0G.js.br +4 -0
- package/build/client/_app/immutable/chunks/Dx86XS0G.js.gz +0 -0
- package/build/client/_app/immutable/chunks/lkkUcQuO.js +29 -0
- package/build/client/_app/immutable/chunks/lkkUcQuO.js.br +0 -0
- package/build/client/_app/immutable/chunks/lkkUcQuO.js.gz +0 -0
- package/build/client/_app/immutable/chunks/nVJvgG3c.js +4 -0
- package/build/client/_app/immutable/chunks/nVJvgG3c.js.br +0 -0
- package/build/client/_app/immutable/chunks/nVJvgG3c.js.gz +0 -0
- package/build/client/_app/immutable/entry/app.g5qLQ5x2.js +2 -0
- package/build/client/_app/immutable/entry/app.g5qLQ5x2.js.br +0 -0
- package/build/client/_app/immutable/entry/app.g5qLQ5x2.js.gz +0 -0
- package/build/client/_app/immutable/entry/start.C1uqw3sp.js +1 -0
- package/build/client/_app/immutable/entry/start.C1uqw3sp.js.br +2 -0
- package/build/client/_app/immutable/entry/start.C1uqw3sp.js.gz +0 -0
- package/build/client/_app/immutable/nodes/0.CD9yR-49.js +5 -0
- package/build/client/_app/immutable/nodes/0.CD9yR-49.js.br +0 -0
- package/build/client/_app/immutable/nodes/0.CD9yR-49.js.gz +0 -0
- package/build/client/_app/immutable/nodes/1.DztuiMqq.js +1 -0
- package/build/client/_app/immutable/nodes/1.DztuiMqq.js.br +0 -0
- package/build/client/_app/immutable/nodes/1.DztuiMqq.js.gz +0 -0
- package/build/client/_app/immutable/nodes/10.CWMFKPcE.js +2 -0
- package/build/client/_app/immutable/nodes/10.CWMFKPcE.js.br +0 -0
- package/build/client/_app/immutable/nodes/10.CWMFKPcE.js.gz +0 -0
- package/build/client/_app/immutable/nodes/11.-Y7Cu3Uv.js +1 -0
- package/build/client/_app/immutable/nodes/11.-Y7Cu3Uv.js.br +0 -0
- package/build/client/_app/immutable/nodes/11.-Y7Cu3Uv.js.gz +0 -0
- package/build/client/_app/immutable/nodes/12.wxif1TtN.js +1 -0
- package/build/client/_app/immutable/nodes/12.wxif1TtN.js.br +0 -0
- package/build/client/_app/immutable/nodes/12.wxif1TtN.js.gz +0 -0
- package/build/client/_app/immutable/nodes/13.CpyTaRSN.js +66 -0
- package/build/client/_app/immutable/nodes/13.CpyTaRSN.js.br +0 -0
- package/build/client/_app/immutable/nodes/13.CpyTaRSN.js.gz +0 -0
- package/build/client/_app/immutable/nodes/2.DwwrLLW4.js +1 -0
- package/build/client/_app/immutable/nodes/2.DwwrLLW4.js.br +1 -0
- package/build/client/_app/immutable/nodes/2.DwwrLLW4.js.gz +0 -0
- package/build/client/_app/immutable/nodes/3.t20GootO.js +1 -0
- package/build/client/_app/immutable/nodes/3.t20GootO.js.br +0 -0
- package/build/client/_app/immutable/nodes/3.t20GootO.js.gz +0 -0
- package/build/client/_app/immutable/nodes/4.CXHjkPtf.js +1 -0
- package/build/client/_app/immutable/nodes/4.CXHjkPtf.js.br +0 -0
- package/build/client/_app/immutable/nodes/4.CXHjkPtf.js.gz +0 -0
- package/build/client/_app/immutable/nodes/5.C9tcr5B0.js +1 -0
- package/build/client/_app/immutable/nodes/5.C9tcr5B0.js.br +0 -0
- package/build/client/_app/immutable/nodes/5.C9tcr5B0.js.gz +0 -0
- package/build/client/_app/immutable/nodes/7.DoT-dNUk.js +1 -0
- package/build/client/_app/immutable/nodes/7.DoT-dNUk.js.br +0 -0
- package/build/client/_app/immutable/nodes/7.DoT-dNUk.js.gz +0 -0
- package/build/client/_app/immutable/nodes/8.BFPkGTSl.js +1 -0
- package/build/client/_app/immutable/nodes/8.BFPkGTSl.js.br +0 -0
- package/build/client/_app/immutable/nodes/8.BFPkGTSl.js.gz +0 -0
- package/build/client/_app/immutable/nodes/9.Bk397TaK.js +2 -0
- package/build/client/_app/immutable/nodes/9.Bk397TaK.js.br +0 -0
- package/build/client/_app/immutable/nodes/9.Bk397TaK.js.gz +0 -0
- package/build/client/_app/version.json +1 -1
- package/build/client/_app/version.json.br +0 -0
- package/build/client/_app/version.json.gz +0 -0
- package/build/handler.js +14 -0
- package/build/server/chunks/{0-Cb5ytlMI.js → 0-hDOo8HzQ.js} +7 -6
- package/build/server/chunks/0-hDOo8HzQ.js.map +1 -0
- package/build/server/chunks/1-Dsw_dVjH.js +9 -0
- package/build/server/chunks/1-Dsw_dVjH.js.map +1 -0
- package/build/server/chunks/10-Xy0rxLNm.js +213 -0
- package/build/server/chunks/10-Xy0rxLNm.js.map +1 -0
- package/build/server/chunks/11-DBYsQ3ww.js +42 -0
- package/build/server/chunks/11-DBYsQ3ww.js.map +1 -0
- package/build/server/chunks/12-D4aSEhYN.js +102 -0
- package/build/server/chunks/12-D4aSEhYN.js.map +1 -0
- package/build/server/chunks/13-CNu_Hz8r.js +52 -0
- package/build/server/chunks/13-CNu_Hz8r.js.map +1 -0
- package/build/server/chunks/2-ClkERMhY.js +24 -0
- package/build/server/chunks/2-ClkERMhY.js.map +1 -0
- package/build/server/chunks/3-CTpqmxdo.js +25 -0
- package/build/server/chunks/3-CTpqmxdo.js.map +1 -0
- package/build/server/chunks/4-CUH4fZn8.js +25 -0
- package/build/server/chunks/4-CUH4fZn8.js.map +1 -0
- package/build/server/chunks/5-BSEdxfut.js +25 -0
- package/build/server/chunks/5-BSEdxfut.js.map +1 -0
- package/build/server/chunks/{2-B39zPvzn.js → 6-ifXBeMPA.js} +2 -2
- package/build/server/chunks/{2-B39zPvzn.js.map → 6-ifXBeMPA.js.map} +1 -1
- package/build/server/chunks/7-CJJMTAtJ.js +82 -0
- package/build/server/chunks/7-CJJMTAtJ.js.map +1 -0
- package/build/server/chunks/{4-DzHoLo__.js → 8-jBgxYwFg.js} +19 -10
- package/build/server/chunks/8-jBgxYwFg.js.map +1 -0
- package/build/server/chunks/{5-CCWbCDpk.js → 9-U8SAVx43.js} +7 -8
- package/build/server/chunks/9-U8SAVx43.js.map +1 -0
- package/build/server/chunks/JsonValue-B5gcBFcA.js +290 -0
- package/build/server/chunks/JsonValue-B5gcBFcA.js.map +1 -0
- package/build/server/chunks/Modal-zVnoAfFx.js +36 -0
- package/build/server/chunks/Modal-zVnoAfFx.js.map +1 -0
- package/build/server/chunks/{Panel-Bz0b85EW.js → Panel-yg5YKL4d.js} +4 -3
- package/build/server/chunks/Panel-yg5YKL4d.js.map +1 -0
- package/build/server/chunks/PrettyJson-mXYQacEL.js +137 -0
- package/build/server/chunks/PrettyJson-mXYQacEL.js.map +1 -0
- package/build/server/chunks/Tooltip-DflJLumT.js +38 -0
- package/build/server/chunks/Tooltip-DflJLumT.js.map +1 -0
- package/build/server/chunks/TooltipTable-BPMzcmqQ.js +60 -0
- package/build/server/chunks/TooltipTable-BPMzcmqQ.js.map +1 -0
- package/build/server/chunks/_layout.svelte-DMm1Ill8.js +168 -0
- package/build/server/chunks/_layout.svelte-DMm1Ill8.js.map +1 -0
- package/build/server/chunks/_page.svelte-B-dLNs2Q.js +199 -0
- package/build/server/chunks/_page.svelte-B-dLNs2Q.js.map +1 -0
- package/build/server/chunks/{_page.svelte-FLzHOuyK.js → _page.svelte-BBpDrOEz.js} +40 -22
- package/build/server/chunks/_page.svelte-BBpDrOEz.js.map +1 -0
- package/build/server/chunks/_page.svelte-C9OCv4Hv.js +204 -0
- package/build/server/chunks/_page.svelte-C9OCv4Hv.js.map +1 -0
- package/build/server/chunks/{_page.svelte-w9cxGvUf.js → _page.svelte-CvWJ35oO.js} +33 -13
- package/build/server/chunks/_page.svelte-CvWJ35oO.js.map +1 -0
- package/build/server/chunks/_page.svelte-DYHUokXG.js +297 -0
- package/build/server/chunks/_page.svelte-DYHUokXG.js.map +1 -0
- package/build/server/chunks/{_page.svelte-FIp-IsOo.js → _page.svelte-Ds1-yUh2.js} +64 -13
- package/build/server/chunks/_page.svelte-Ds1-yUh2.js.map +1 -0
- package/build/server/chunks/{_page.svelte-jxFKbZdN.js → _page.svelte-DzPMpozq.js} +9 -6
- package/build/server/chunks/_page.svelte-DzPMpozq.js.map +1 -0
- package/build/server/chunks/_server.ts-06lGoPp8.js +8 -0
- package/build/server/chunks/_server.ts-06lGoPp8.js.map +1 -0
- package/build/server/chunks/async-lVJA8xJZ.js +9 -0
- package/build/server/chunks/async-lVJA8xJZ.js.map +1 -0
- package/build/server/chunks/client-BFlyU7ZU.js +7 -0
- package/build/server/chunks/{client-bj7sePQc.js.map → client-BFlyU7ZU.js.map} +1 -1
- package/build/server/chunks/{client2-BX4-xbM4.js → client2-DYaMKWrc.js} +4 -4
- package/build/server/chunks/{client2-BX4-xbM4.js.map → client2-DYaMKWrc.js.map} +1 -1
- package/build/server/chunks/{async-BfR0vYHo.js → context-C22hLSHK.js} +2 -8
- package/build/server/chunks/context-C22hLSHK.js.map +1 -0
- package/build/server/chunks/error.svelte-BENdaVOT.js +19 -0
- package/build/server/chunks/error.svelte-BENdaVOT.js.map +1 -0
- package/build/server/chunks/event-DVH-6ISX.js.map +1 -1
- package/build/server/chunks/hooks.server-CagAPNr2.js +40 -0
- package/build/server/chunks/hooks.server-CagAPNr2.js.map +1 -0
- package/build/server/chunks/{index-EKt9-9bV.js → index-DFXVwu6p.js} +2 -2
- package/build/server/chunks/{index-EKt9-9bV.js.map → index-DFXVwu6p.js.map} +1 -1
- package/build/server/chunks/index-Djsj11qr.js.map +1 -1
- package/build/server/chunks/index-server-Bf-hP5gL.js +5 -0
- package/build/server/chunks/index-server-Bf-hP5gL.js.map +1 -0
- package/build/server/chunks/{routing-DcR4fCSD.js → index2-DBFlGzWV.js} +23 -100
- package/build/server/chunks/index2-DBFlGzWV.js.map +1 -0
- package/build/server/chunks/{index3-DquTjlmp.js → index3-CoOO2o9t.js} +6 -6
- package/build/server/chunks/index3-CoOO2o9t.js.map +1 -0
- package/build/server/chunks/jsonParser-CraFXJs8.js +174 -0
- package/build/server/chunks/jsonParser-CraFXJs8.js.map +1 -0
- package/build/server/chunks/layout.svelte-CJcHX-Na.js +10 -0
- package/build/server/chunks/layout.svelte-CJcHX-Na.js.map +1 -0
- package/build/server/chunks/logger-D71iWOkl.js +36 -0
- package/build/server/chunks/logger-D71iWOkl.js.map +1 -0
- package/build/server/chunks/{mongo-dLmCShL_.js → mongo-BogiTfnG.js} +54 -12
- package/build/server/chunks/mongo-BogiTfnG.js.map +1 -0
- package/build/server/chunks/remote-xxtqbu-BJDSUh3k.js +17 -0
- package/build/server/chunks/remote-xxtqbu-BJDSUh3k.js.map +1 -0
- package/build/server/chunks/routing-e10vGH37.js +81 -0
- package/build/server/chunks/routing-e10vGH37.js.map +1 -0
- package/build/server/chunks/{server2-BiqGvkCy.js → server2-_mGVuBoG.js} +2 -2
- package/build/server/chunks/{server2-BiqGvkCy.js.map → server2-_mGVuBoG.js.map} +1 -1
- package/build/server/chunks/servers.remote-C2HuT43p.js +690 -0
- package/build/server/chunks/servers.remote-C2HuT43p.js.map +1 -0
- package/build/server/chunks/shared-Buki-xt5.js +506 -0
- package/build/server/chunks/shared-Buki-xt5.js.map +1 -0
- package/build/server/chunks/{state.svelte-CRHA9yov.js → state.svelte-C8IWmp_n.js} +2 -2
- package/build/server/chunks/{state.svelte-CRHA9yov.js.map → state.svelte-C8IWmp_n.js.map} +1 -1
- package/build/server/chunks/{utils-DGYJFmnf.js → utils-kjxf7BZO.js} +2 -2
- package/build/server/chunks/{utils-DGYJFmnf.js.map → utils-kjxf7BZO.js.map} +1 -1
- package/build/server/index.js +189 -610
- package/build/server/index.js.map +1 -1
- package/build/server/manifest.js +45 -18
- package/build/server/manifest.js.map +1 -1
- package/package.json +13 -2
- package/src/api/servers.remote.ts +381 -20
- package/src/app.css +98 -3
- package/src/app.html +15 -0
- package/src/hooks.server.ts +18 -1
- package/src/lib/actions/jsonTextarea.ts +395 -0
- package/src/lib/components/Breadcrumbs.svelte +7 -58
- package/src/lib/components/JsonValue.svelte +279 -85
- package/src/lib/components/Modal.svelte +59 -0
- package/src/lib/components/OriginWarning.svelte +109 -0
- package/src/lib/components/PageSwitcher.svelte +37 -0
- package/src/lib/components/Panel.svelte +1 -1
- package/src/lib/components/PrettyJson.svelte +112 -36
- package/src/lib/components/SearchBox.svelte +161 -97
- package/src/lib/components/ThemeSwitcher.svelte +66 -0
- package/src/lib/components/Tooltip.svelte +83 -0
- package/src/lib/components/TooltipTable.svelte +45 -102
- package/src/lib/server/HostsManager.ts +4 -0
- package/src/lib/server/aggregation.ts +62 -0
- package/src/lib/server/mongo.ts +78 -15
- package/src/lib/types.ts +60 -0
- package/src/lib/utils/isEmptyObject.ts +6 -0
- package/src/lib/utils/jsonParser.ts +9 -1
- package/src/lib/utils/logger.ts +42 -0
- package/src/lib/utils/omit.ts +3 -0
- package/src/routes/+layout.server.ts +2 -1
- package/src/routes/+layout.svelte +15 -2
- package/src/routes/favicon.ico/+server.ts +8 -0
- package/src/routes/servers/+page.server.ts +23 -10
- package/src/routes/servers/+page.svelte +44 -10
- package/src/routes/servers/[server]/databases/+layout.ts +8 -0
- package/src/routes/servers/[server]/databases/+page.server.ts +15 -4
- package/src/routes/servers/[server]/databases/[database]/collections/+layout.ts +9 -0
- package/src/routes/servers/[server]/databases/[database]/collections/+page.server.ts +0 -2
- package/src/routes/servers/[server]/databases/[database]/collections/+page.svelte +67 -8
- package/src/routes/servers/[server]/databases/[database]/collections/[collection]/+layout.ts +9 -0
- package/src/routes/servers/[server]/databases/[database]/collections/[collection]/documents/+page.server.ts +217 -0
- package/src/routes/servers/[server]/databases/[database]/collections/[collection]/documents/+page.svelte +342 -0
- package/src/routes/servers/[server]/databases/[database]/collections/[collection]/documents/+page.ts +10 -0
- package/src/routes/servers/[server]/databases/[database]/collections/[collection]/documents/[document]/+layout.ts +9 -0
- package/src/routes/servers/[server]/databases/[database]/collections/[collection]/documents/[document]/+page.server.ts +15 -12
- package/src/routes/servers/[server]/databases/[database]/collections/[collection]/documents/[document]/+page.svelte +81 -7
- package/src/routes/servers/[server]/databases/[database]/collections/[collection]/indexes/+page.server.ts +88 -0
- package/src/routes/servers/[server]/databases/[database]/collections/[collection]/indexes/+page.svelte +333 -0
- package/src/routes/servers/[server]/databases/[database]/collections/[collection]/indexes/+page.ts +10 -0
- package/src/routes/servers/[server]/databases/[database]/collections/[collection]/mappings/+page.server.ts +18 -0
- package/src/routes/servers/[server]/databases/[database]/collections/[collection]/mappings/+page.svelte +378 -0
- package/src/routes/servers/[server]/databases/[database]/collections/[collection]/mappings/+page.ts +10 -0
- package/src/tests/api/aggregation.test.ts +125 -0
- package/build/client/_app/immutable/assets/0.CEsPYTp2.css +0 -1
- package/build/client/_app/immutable/assets/0.CEsPYTp2.css.br +0 -0
- package/build/client/_app/immutable/assets/0.CEsPYTp2.css.gz +0 -0
- package/build/client/_app/immutable/assets/6.DawdmtJd.css +0 -1
- package/build/client/_app/immutable/assets/6.DawdmtJd.css.br +0 -2
- package/build/client/_app/immutable/assets/6.DawdmtJd.css.gz +0 -0
- package/build/client/_app/immutable/assets/Panel.BDHMtO-3.css +0 -1
- package/build/client/_app/immutable/assets/Panel.BDHMtO-3.css.br +0 -0
- package/build/client/_app/immutable/assets/Panel.BDHMtO-3.css.gz +0 -0
- package/build/client/_app/immutable/assets/PrettyJson.CtngcfyW.css +0 -1
- package/build/client/_app/immutable/assets/PrettyJson.CtngcfyW.css.br +0 -0
- package/build/client/_app/immutable/assets/PrettyJson.CtngcfyW.css.gz +0 -0
- package/build/client/_app/immutable/chunks/B2-iEFN3.js +0 -2
- package/build/client/_app/immutable/chunks/B2-iEFN3.js.br +0 -0
- package/build/client/_app/immutable/chunks/B2-iEFN3.js.gz +0 -0
- package/build/client/_app/immutable/chunks/B5y2vsNr.js +0 -1
- package/build/client/_app/immutable/chunks/B5y2vsNr.js.br +0 -0
- package/build/client/_app/immutable/chunks/B5y2vsNr.js.gz +0 -0
- package/build/client/_app/immutable/chunks/BN_N9-2s.js +0 -1
- package/build/client/_app/immutable/chunks/BN_N9-2s.js.br +0 -0
- package/build/client/_app/immutable/chunks/BN_N9-2s.js.gz +0 -0
- package/build/client/_app/immutable/chunks/C1z4TjN7.js +0 -1
- package/build/client/_app/immutable/chunks/C1z4TjN7.js.br +0 -0
- package/build/client/_app/immutable/chunks/C1z4TjN7.js.gz +0 -0
- package/build/client/_app/immutable/chunks/CQBaNlA9.js +0 -1
- package/build/client/_app/immutable/chunks/CQBaNlA9.js.br +0 -0
- package/build/client/_app/immutable/chunks/CQBaNlA9.js.gz +0 -0
- package/build/client/_app/immutable/chunks/CVoOGazw.js +0 -4
- package/build/client/_app/immutable/chunks/CVoOGazw.js.br +0 -0
- package/build/client/_app/immutable/chunks/CVoOGazw.js.gz +0 -0
- package/build/client/_app/immutable/chunks/CapOg2jD.js +0 -1
- package/build/client/_app/immutable/chunks/CapOg2jD.js.br +0 -0
- package/build/client/_app/immutable/chunks/CapOg2jD.js.gz +0 -0
- package/build/client/_app/immutable/chunks/ChWB6xnu.js.br +0 -0
- package/build/client/_app/immutable/chunks/ChWB6xnu.js.gz +0 -0
- package/build/client/_app/immutable/chunks/CqnBT2zJ.js +0 -1
- package/build/client/_app/immutable/chunks/CqnBT2zJ.js.br +0 -0
- package/build/client/_app/immutable/chunks/CqnBT2zJ.js.gz +0 -0
- package/build/client/_app/immutable/chunks/D069mncP.js +0 -1
- package/build/client/_app/immutable/chunks/D069mncP.js.br +0 -0
- package/build/client/_app/immutable/chunks/D069mncP.js.gz +0 -0
- package/build/client/_app/immutable/chunks/DACrOfV_.js +0 -14
- package/build/client/_app/immutable/chunks/DACrOfV_.js.br +0 -0
- package/build/client/_app/immutable/chunks/DACrOfV_.js.gz +0 -0
- package/build/client/_app/immutable/chunks/DQkpHJGc.js.br +0 -0
- package/build/client/_app/immutable/chunks/DQkpHJGc.js.gz +0 -0
- package/build/client/_app/immutable/chunks/DSDD_hFT.js +0 -1
- package/build/client/_app/immutable/chunks/DSDD_hFT.js.br +0 -0
- package/build/client/_app/immutable/chunks/DSDD_hFT.js.gz +0 -0
- package/build/client/_app/immutable/chunks/D_aTX_ol.js +0 -1
- package/build/client/_app/immutable/chunks/D_aTX_ol.js.br +0 -0
- package/build/client/_app/immutable/chunks/D_aTX_ol.js.gz +0 -0
- package/build/client/_app/immutable/chunks/Dg3qHExF.js +0 -1
- package/build/client/_app/immutable/chunks/Dg3qHExF.js.br +0 -0
- package/build/client/_app/immutable/chunks/Dg3qHExF.js.gz +0 -0
- package/build/client/_app/immutable/chunks/Dt6-JRym.js +0 -2
- package/build/client/_app/immutable/chunks/Dt6-JRym.js.br +0 -0
- package/build/client/_app/immutable/chunks/Dt6-JRym.js.gz +0 -0
- package/build/client/_app/immutable/chunks/QoKxaG0e.js +0 -1
- package/build/client/_app/immutable/chunks/QoKxaG0e.js.br +0 -2
- package/build/client/_app/immutable/chunks/QoKxaG0e.js.gz +0 -0
- package/build/client/_app/immutable/chunks/rtveiEyS.js +0 -1
- package/build/client/_app/immutable/chunks/rtveiEyS.js.br +0 -0
- package/build/client/_app/immutable/chunks/rtveiEyS.js.gz +0 -0
- package/build/client/_app/immutable/entry/app.Cc1FNLNH.js +0 -2
- package/build/client/_app/immutable/entry/app.Cc1FNLNH.js.br +0 -0
- package/build/client/_app/immutable/entry/app.Cc1FNLNH.js.gz +0 -0
- package/build/client/_app/immutable/entry/start.CwqlbFyy.js +0 -1
- package/build/client/_app/immutable/entry/start.CwqlbFyy.js.br +0 -2
- package/build/client/_app/immutable/entry/start.CwqlbFyy.js.gz +0 -0
- package/build/client/_app/immutable/nodes/0.wBQEpdjZ.js +0 -1
- package/build/client/_app/immutable/nodes/0.wBQEpdjZ.js.br +0 -0
- package/build/client/_app/immutable/nodes/0.wBQEpdjZ.js.gz +0 -0
- package/build/client/_app/immutable/nodes/1.K6-n7D0b.js +0 -1
- package/build/client/_app/immutable/nodes/1.K6-n7D0b.js.br +0 -0
- package/build/client/_app/immutable/nodes/1.K6-n7D0b.js.gz +0 -0
- package/build/client/_app/immutable/nodes/3.DkGcIF98.js +0 -1
- package/build/client/_app/immutable/nodes/3.DkGcIF98.js.br +0 -0
- package/build/client/_app/immutable/nodes/3.DkGcIF98.js.gz +0 -0
- package/build/client/_app/immutable/nodes/4.C_NxbT98.js +0 -1
- package/build/client/_app/immutable/nodes/4.C_NxbT98.js.br +0 -0
- package/build/client/_app/immutable/nodes/4.C_NxbT98.js.gz +0 -0
- package/build/client/_app/immutable/nodes/5.CFvfYaLM.js +0 -1
- package/build/client/_app/immutable/nodes/5.CFvfYaLM.js.br +0 -0
- package/build/client/_app/immutable/nodes/5.CFvfYaLM.js.gz +0 -0
- package/build/client/_app/immutable/nodes/6.h34Zyorq.js +0 -1
- package/build/client/_app/immutable/nodes/6.h34Zyorq.js.br +0 -0
- package/build/client/_app/immutable/nodes/6.h34Zyorq.js.gz +0 -0
- package/build/client/_app/immutable/nodes/7.BVJmNbU5.js +0 -1
- package/build/client/_app/immutable/nodes/7.BVJmNbU5.js.br +0 -0
- package/build/client/_app/immutable/nodes/7.BVJmNbU5.js.gz +0 -0
- package/build/server/chunks/0-Cb5ytlMI.js.map +0 -1
- package/build/server/chunks/1-Cpb7zRtJ.js +0 -9
- package/build/server/chunks/1-Cpb7zRtJ.js.map +0 -1
- package/build/server/chunks/3-B_DkgZkc.js +0 -69
- package/build/server/chunks/3-B_DkgZkc.js.map +0 -1
- package/build/server/chunks/4-DzHoLo__.js.map +0 -1
- package/build/server/chunks/5-CCWbCDpk.js.map +0 -1
- package/build/server/chunks/6-Dok8svjB.js +0 -202
- package/build/server/chunks/6-Dok8svjB.js.map +0 -1
- package/build/server/chunks/7-CmgJSG2j.js +0 -42
- package/build/server/chunks/7-CmgJSG2j.js.map +0 -1
- package/build/server/chunks/Panel-Bz0b85EW.js.map +0 -1
- package/build/server/chunks/PrettyJson-CX6-dNsW.js +0 -291
- package/build/server/chunks/PrettyJson-CX6-dNsW.js.map +0 -1
- package/build/server/chunks/TooltipTable-0z4HkHlH.js +0 -17
- package/build/server/chunks/TooltipTable-0z4HkHlH.js.map +0 -1
- package/build/server/chunks/_layout.svelte-UiDiCQEz.js +0 -111
- package/build/server/chunks/_layout.svelte-UiDiCQEz.js.map +0 -1
- package/build/server/chunks/_page.svelte-FIp-IsOo.js.map +0 -1
- package/build/server/chunks/_page.svelte-FLzHOuyK.js.map +0 -1
- package/build/server/chunks/_page.svelte-jxFKbZdN.js.map +0 -1
- package/build/server/chunks/_page.svelte-k8avSQW1.js +0 -215
- package/build/server/chunks/_page.svelte-k8avSQW1.js.map +0 -1
- package/build/server/chunks/_page.svelte-w9cxGvUf.js.map +0 -1
- package/build/server/chunks/async-BfR0vYHo.js.map +0 -1
- package/build/server/chunks/client-bj7sePQc.js +0 -7
- package/build/server/chunks/error.svelte-D5sIJv3P.js +0 -18
- package/build/server/chunks/error.svelte-D5sIJv3P.js.map +0 -1
- package/build/server/chunks/hooks.server-_TKfdzGA.js +0 -26
- package/build/server/chunks/hooks.server-_TKfdzGA.js.map +0 -1
- package/build/server/chunks/index3-DquTjlmp.js.map +0 -1
- package/build/server/chunks/mongo-dLmCShL_.js.map +0 -1
- package/build/server/chunks/remote-xxtqbu-BFzaWXy0.js +0 -234
- package/build/server/chunks/remote-xxtqbu-BFzaWXy0.js.map +0 -1
- package/build/server/chunks/routing-DcR4fCSD.js.map +0 -1
- package/src/routes/servers/[server]/databases/[database]/collections/[collection]/+page.server.ts +0 -106
- package/src/routes/servers/[server]/databases/[database]/collections/[collection]/+page.svelte +0 -174
- /package/build/client/_app/immutable/assets/{3.CRKE8WvY.css → 7.CRKE8WvY.css} +0 -0
- /package/build/client/_app/immutable/assets/{3.CRKE8WvY.css.br → 7.CRKE8WvY.css.br} +0 -0
- /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 {
|
|
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
|
-
<
|
|
87
|
-
|
|
88
|
-
{
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
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
|
+
}
|
package/src/lib/server/mongo.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type { CollectionJSON } from "$lib/types";
|
|
1
|
+
import type { CollectionJSON, CollectionMappings, Mappings } from "$lib/types";
|
|
2
|
+
import { logger } from "$lib/utils/logger";
|
|
2
3
|
import { MongoClient, type Collection } from "mongodb";
|
|
3
4
|
import { URL } from "url";
|
|
4
5
|
import { HostsManager } from "./HostsManager";
|
|
@@ -87,18 +88,48 @@ export async function getCollectionJson(
|
|
|
87
88
|
};
|
|
88
89
|
}
|
|
89
90
|
|
|
91
|
+
class MongoClientWithMappings extends MongoClient {
|
|
92
|
+
mappings: Record<string, Record<string, Mappings>> = {};
|
|
93
|
+
|
|
94
|
+
async getMappings(dbName: string, collectionName: string, opts?: { forceRefresh?: boolean }): Promise<Mappings> {
|
|
95
|
+
if (opts?.forceRefresh || !this.mappings[dbName]?.[collectionName]) {
|
|
96
|
+
const mappings = await this.db(dbName)
|
|
97
|
+
.collection<CollectionMappings>("mongoku.mappings")
|
|
98
|
+
.findOne({ _id: collectionName });
|
|
99
|
+
this.mappings[dbName] ??= {};
|
|
100
|
+
this.mappings[dbName][collectionName] = mappings?.mappings ?? {};
|
|
101
|
+
}
|
|
102
|
+
return this.mappings[dbName][collectionName];
|
|
103
|
+
}
|
|
104
|
+
clearMappingsCache(dbName: string, collectionName: string) {
|
|
105
|
+
delete this.mappings[dbName][collectionName];
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
90
109
|
class MongoConnections {
|
|
91
110
|
/**
|
|
92
111
|
* Todo: better system where we can have mutiple servers with same hostname, and labels for each server that
|
|
93
112
|
* would be displayed in the UI instead of the hostname.
|
|
94
113
|
*/
|
|
95
|
-
private clients: Map<string,
|
|
114
|
+
private clients: Map<string, MongoClientWithMappings> = new Map();
|
|
96
115
|
private clientIds: Map<string, string> = new Map(); // hostname -> _id
|
|
97
116
|
private hostsManager: HostsManager;
|
|
98
|
-
private countTimeout = parseInt(process.env.MONGOKU_COUNT_TIMEOUT!, 10) ||
|
|
117
|
+
private countTimeout = parseInt(process.env.MONGOKU_COUNT_TIMEOUT!, 10) || 30_000;
|
|
118
|
+
private queryTimeout = process.env.MONGOKU_QUERY_TIMEOUT
|
|
119
|
+
? parseInt(process.env.MONGOKU_QUERY_TIMEOUT, 10)
|
|
120
|
+
: undefined;
|
|
121
|
+
private excludedDatabases: Set<string>;
|
|
99
122
|
|
|
100
123
|
constructor() {
|
|
101
124
|
this.hostsManager = new HostsManager();
|
|
125
|
+
// Parse MONGOKU_EXCLUDE_DATABASES env var (comma-separated list)
|
|
126
|
+
const excludeEnv = process.env.MONGOKU_EXCLUDE_DATABASES || "";
|
|
127
|
+
this.excludedDatabases = new Set(
|
|
128
|
+
excludeEnv
|
|
129
|
+
.split(",")
|
|
130
|
+
.map((db) => db.trim())
|
|
131
|
+
.filter((db) => db.length > 0),
|
|
132
|
+
);
|
|
102
133
|
}
|
|
103
134
|
|
|
104
135
|
async initialize() {
|
|
@@ -113,20 +144,20 @@ class MongoConnections {
|
|
|
113
144
|
const hostname = url.host || host.path;
|
|
114
145
|
|
|
115
146
|
if (!this.clients.has(hostname)) {
|
|
116
|
-
const client = new
|
|
147
|
+
const client = new MongoClientWithMappings(urlStr);
|
|
117
148
|
this.clients.set(hostname, client);
|
|
118
149
|
this.clientIds.set(hostname, host._id);
|
|
119
150
|
}
|
|
120
151
|
} catch (err) {
|
|
121
|
-
|
|
152
|
+
logger.error(`Failed to parse URL for host ${host.path}:`, err);
|
|
122
153
|
}
|
|
123
154
|
}
|
|
124
155
|
}
|
|
125
156
|
|
|
126
|
-
getClient(name: string):
|
|
157
|
+
getClient(name: string): MongoClientWithMappings {
|
|
127
158
|
const client = this.clients.get(name) || this.clients.get(`${name}:27017`);
|
|
128
159
|
if (!client) {
|
|
129
|
-
throw new Error(
|
|
160
|
+
throw new Error(`Client not found: ${name}`);
|
|
130
161
|
}
|
|
131
162
|
return client;
|
|
132
163
|
}
|
|
@@ -141,16 +172,21 @@ class MongoConnections {
|
|
|
141
172
|
}));
|
|
142
173
|
}
|
|
143
174
|
|
|
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
175
|
getCountTimeout() {
|
|
151
176
|
return this.countTimeout;
|
|
152
177
|
}
|
|
153
178
|
|
|
179
|
+
getQueryTimeout() {
|
|
180
|
+
return this.queryTimeout;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
filterDatabases<T extends { name: string }>(databases: T[]): T[] {
|
|
184
|
+
if (this.excludedDatabases.size === 0) {
|
|
185
|
+
return databases;
|
|
186
|
+
}
|
|
187
|
+
return databases.filter((db) => !this.excludedDatabases.has(db.name));
|
|
188
|
+
}
|
|
189
|
+
|
|
154
190
|
async addServer(hostPath: string) {
|
|
155
191
|
const id = await this.hostsManager.add(hostPath);
|
|
156
192
|
|
|
@@ -161,21 +197,48 @@ class MongoConnections {
|
|
|
161
197
|
const hostname = url.host || hostPath;
|
|
162
198
|
|
|
163
199
|
if (!this.clients.has(hostname)) {
|
|
164
|
-
const client = new
|
|
200
|
+
const client = new MongoClientWithMappings(urlStr);
|
|
165
201
|
this.clients.set(hostname, client);
|
|
166
202
|
this.clientIds.set(hostname, id);
|
|
167
203
|
}
|
|
168
204
|
} catch (err) {
|
|
169
|
-
|
|
205
|
+
logger.error(`Failed to parse URL for host ${hostPath}:`, err);
|
|
170
206
|
throw err;
|
|
171
207
|
}
|
|
172
208
|
}
|
|
173
209
|
|
|
174
210
|
async removeServer(name: string) {
|
|
175
211
|
await this.hostsManager.remove(name);
|
|
212
|
+
|
|
213
|
+
this.clients
|
|
214
|
+
.get(name)
|
|
215
|
+
?.close()
|
|
216
|
+
.catch((err) => logger.error(`Error closing client ${name}:`, err));
|
|
176
217
|
this.clients.delete(name);
|
|
177
218
|
this.clientIds.delete(name);
|
|
178
219
|
}
|
|
220
|
+
|
|
221
|
+
async reconnectClient(name: string) {
|
|
222
|
+
// Try to find the connection string with the same logic as getClient
|
|
223
|
+
const connectionString = this.hostsManager.getHost(name);
|
|
224
|
+
|
|
225
|
+
if (!connectionString) {
|
|
226
|
+
throw new Error(`Connection string not found for client: ${name}`);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
// Close the old client
|
|
230
|
+
const oldClient = this.clients.get(name);
|
|
231
|
+
if (oldClient) {
|
|
232
|
+
oldClient.close()?.catch((err) => logger.error(`Error closing old client ${name}:`, err));
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// Create a new client
|
|
236
|
+
const newClient = new MongoClientWithMappings(connectionString);
|
|
237
|
+
this.clients.set(name, newClient);
|
|
238
|
+
|
|
239
|
+
// Test the connection
|
|
240
|
+
await newClient.connect();
|
|
241
|
+
}
|
|
179
242
|
}
|
|
180
243
|
|
|
181
244
|
// 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
|
+
}
|
|
@@ -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,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Logger class that wraps console methods for centralized logging
|
|
3
|
+
*/
|
|
4
|
+
class Logger {
|
|
5
|
+
/**
|
|
6
|
+
* Log an informational message
|
|
7
|
+
*/
|
|
8
|
+
log(...args: unknown[]): void {
|
|
9
|
+
console.log(...args);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Log an informational message (alias for log)
|
|
14
|
+
*/
|
|
15
|
+
info(...args: unknown[]): void {
|
|
16
|
+
console.log(...args);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Log an error message
|
|
21
|
+
*/
|
|
22
|
+
error(...args: unknown[]): void {
|
|
23
|
+
console.error(...args);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Log a warning message
|
|
28
|
+
*/
|
|
29
|
+
warn(...args: unknown[]): void {
|
|
30
|
+
console.warn(...args);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Log a debug message
|
|
35
|
+
*/
|
|
36
|
+
debug(...args: unknown[]): void {
|
|
37
|
+
console.debug(...args);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Export a singleton instance
|
|
42
|
+
export const logger = new Logger();
|
|
@@ -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,30 @@
|
|
|
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
|
|
|
13
|
+
<svelte:head>
|
|
14
|
+
<title>Mongoku</title>
|
|
15
|
+
</svelte:head>
|
|
16
|
+
|
|
10
17
|
<div style="min-height: 100vh">
|
|
11
18
|
<nav class="navbar px-6 py-4 flex items-center">
|
|
12
19
|
<a href={resolve("/")} class="text-2xl font-medium">Mongoku</a>
|
|
13
20
|
<Breadcrumbs />
|
|
21
|
+
<div class="ml-auto flex items-center gap-2">
|
|
22
|
+
<PageSwitcher class="" />
|
|
23
|
+
<ThemeSwitcher />
|
|
24
|
+
</div>
|
|
14
25
|
</nav>
|
|
15
26
|
|
|
27
|
+
<OriginWarning serverOrigin={data.serverOrigin} readOnly={data.readOnly} />
|
|
28
|
+
|
|
16
29
|
<div class="px-6 py-6 flex flex-col gap-6">
|
|
17
30
|
<Notifications />
|
|
18
31
|
{@render children()}
|
|
@@ -21,7 +34,7 @@
|
|
|
21
34
|
|
|
22
35
|
<style lang="postcss">
|
|
23
36
|
.navbar {
|
|
24
|
-
background-color: var(--
|
|
37
|
+
background-color: var(--light-background);
|
|
25
38
|
border-bottom: var(--border);
|
|
26
39
|
}
|
|
27
40
|
</style>
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { getMongo } from "$lib/server/mongo";
|
|
2
2
|
import type { DatabaseStats } from "$lib/types";
|
|
3
|
+
import { logger } from "$lib/utils/logger";
|
|
3
4
|
import type { PageServerLoad } from "./$types";
|
|
4
5
|
|
|
5
6
|
export const load: PageServerLoad = async () => {
|
|
@@ -12,16 +13,24 @@ export const load: PageServerLoad = async () => {
|
|
|
12
13
|
try {
|
|
13
14
|
const adminDb = client.db("test").admin();
|
|
14
15
|
const results = await adminDb.listDatabases();
|
|
16
|
+
const filteredDatabases = mongo.filterDatabases(results.databases);
|
|
15
17
|
const collectionsCount = await Promise.all(
|
|
16
|
-
|
|
18
|
+
filteredDatabases.map(async (d) => {
|
|
17
19
|
const db = client.db(d.name);
|
|
18
|
-
const dbStats =
|
|
20
|
+
const dbStats: Pick<DatabaseStats, "collections"> = await (db.stats() as Promise<DatabaseStats>).catch(
|
|
21
|
+
() => {
|
|
22
|
+
logger.error(`Error getting stats for database ${d.name} on server ${name}`);
|
|
23
|
+
return {
|
|
24
|
+
collections: 0,
|
|
25
|
+
};
|
|
26
|
+
},
|
|
27
|
+
);
|
|
19
28
|
return dbStats.collections;
|
|
20
29
|
}),
|
|
21
30
|
);
|
|
22
31
|
|
|
23
32
|
return {
|
|
24
|
-
databases:
|
|
33
|
+
databases: filteredDatabases.map((d, index) => ({
|
|
25
34
|
name: d.name,
|
|
26
35
|
size: d.sizeOnDisk ?? 0,
|
|
27
36
|
collections: collectionsCount[index],
|
|
@@ -29,6 +38,7 @@ export const load: PageServerLoad = async () => {
|
|
|
29
38
|
size: results.totalSize ?? 0,
|
|
30
39
|
};
|
|
31
40
|
} catch (err) {
|
|
41
|
+
logger.error(`Error getting details for server ${name}:`, err);
|
|
32
42
|
return {
|
|
33
43
|
error: {
|
|
34
44
|
code: err instanceof Error && "code" in err ? err.code : undefined,
|
|
@@ -37,13 +47,16 @@ export const load: PageServerLoad = async () => {
|
|
|
37
47
|
},
|
|
38
48
|
};
|
|
39
49
|
}
|
|
40
|
-
})().catch((err) =>
|
|
41
|
-
error
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
50
|
+
})().catch((err) => {
|
|
51
|
+
logger.error(`Error getting details for server ${name}:`, err);
|
|
52
|
+
return {
|
|
53
|
+
error: {
|
|
54
|
+
code: err instanceof Error && "code" in err ? err.code : undefined,
|
|
55
|
+
name: err instanceof Error ? err.name : "Error",
|
|
56
|
+
message: err instanceof Error ? err.message : String(err),
|
|
57
|
+
},
|
|
58
|
+
};
|
|
59
|
+
}),
|
|
47
60
|
}));
|
|
48
61
|
|
|
49
62
|
servers.sort((a, b) => a.name.localeCompare(b.name));
|