mongoku 2.4.6-compat → 2.4.7-compat
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +15 -0
- package/build/client/_app/immutable/assets/0.C_geP4pp.css +1 -0
- package/build/client/_app/immutable/assets/0.C_geP4pp.css.br +0 -0
- package/build/client/_app/immutable/assets/0.C_geP4pp.css.gz +0 -0
- package/build/client/_app/immutable/assets/10.Wc4MTSzM.css +1 -0
- package/build/client/_app/immutable/assets/10.Wc4MTSzM.css.br +0 -0
- package/build/client/_app/immutable/assets/10.Wc4MTSzM.css.gz +0 -0
- package/build/client/_app/immutable/assets/{Modal.zD4dMMyk.css → Modal.CZgFKXkP.css} +1 -1
- package/build/client/_app/immutable/assets/Modal.CZgFKXkP.css.br +0 -0
- package/build/client/_app/immutable/assets/Modal.CZgFKXkP.css.gz +0 -0
- package/build/client/_app/immutable/chunks/B27BoO92.js +1 -0
- package/build/client/_app/immutable/chunks/B27BoO92.js.br +0 -0
- package/build/client/_app/immutable/chunks/B27BoO92.js.gz +0 -0
- package/build/client/_app/immutable/chunks/{reNJcONQ.js → BLB7WU0x.js} +1 -1
- package/build/client/_app/immutable/chunks/BLB7WU0x.js.br +0 -0
- package/build/client/_app/immutable/chunks/{reNJcONQ.js.gz → BLB7WU0x.js.gz} +0 -0
- package/build/client/_app/immutable/chunks/{DvuSce6Q.js → BTDPx7wo.js} +1 -1
- package/build/client/_app/immutable/chunks/BTDPx7wo.js.br +0 -0
- package/build/client/_app/immutable/chunks/BTDPx7wo.js.gz +0 -0
- package/build/client/_app/immutable/chunks/{CQi92wY1.js → BV1jCwWf.js} +1 -1
- package/build/client/_app/immutable/chunks/BV1jCwWf.js.br +0 -0
- package/build/client/_app/immutable/chunks/BV1jCwWf.js.gz +0 -0
- package/build/client/_app/immutable/chunks/Bp2iD_PL.js +1 -0
- package/build/client/_app/immutable/chunks/Bp2iD_PL.js.br +0 -0
- package/build/client/_app/immutable/chunks/Bp2iD_PL.js.gz +0 -0
- package/build/client/_app/immutable/chunks/CItzKczS.js +1 -0
- package/build/client/_app/immutable/chunks/CItzKczS.js.br +0 -0
- package/build/client/_app/immutable/chunks/CItzKczS.js.gz +0 -0
- package/build/client/_app/immutable/chunks/{CjbrLxJm.js → Ce084HhL.js} +1 -1
- package/build/client/_app/immutable/chunks/Ce084HhL.js.br +0 -0
- package/build/client/_app/immutable/chunks/Ce084HhL.js.gz +0 -0
- package/build/client/_app/immutable/chunks/{DIw4Wyr4.js → CqFYS5AV.js} +1 -1
- package/build/client/_app/immutable/chunks/CqFYS5AV.js.br +0 -0
- package/build/client/_app/immutable/chunks/CqFYS5AV.js.gz +0 -0
- package/build/client/_app/immutable/chunks/{Cs_Y8eC2.js → DC13l09X.js} +6 -6
- package/build/client/_app/immutable/chunks/DC13l09X.js.br +0 -0
- package/build/client/_app/immutable/chunks/DC13l09X.js.gz +0 -0
- package/build/client/_app/immutable/chunks/{Dqjuk_9f.js → DXWJTsg6.js} +1 -1
- package/build/client/_app/immutable/chunks/DXWJTsg6.js.br +0 -0
- package/build/client/_app/immutable/chunks/DXWJTsg6.js.gz +0 -0
- package/build/client/_app/immutable/chunks/Dip-8jE5.js +1 -0
- package/build/client/_app/immutable/chunks/Dip-8jE5.js.br +0 -0
- package/build/client/_app/immutable/chunks/Dip-8jE5.js.gz +0 -0
- package/build/client/_app/immutable/chunks/Dr_XE7iR.js +2 -0
- package/build/client/_app/immutable/chunks/Dr_XE7iR.js.br +0 -0
- package/build/client/_app/immutable/chunks/Dr_XE7iR.js.gz +0 -0
- package/build/client/_app/immutable/chunks/DuLpG1zT.js +1 -0
- package/build/client/_app/immutable/chunks/DuLpG1zT.js.br +0 -0
- package/build/client/_app/immutable/chunks/DuLpG1zT.js.gz +0 -0
- package/build/client/_app/immutable/chunks/{Dn0_-jEe.js → DyfVYlRP.js} +1 -1
- package/build/client/_app/immutable/chunks/DyfVYlRP.js.br +0 -0
- package/build/client/_app/immutable/chunks/DyfVYlRP.js.gz +0 -0
- package/build/client/_app/immutable/chunks/{BXUq66wC.js → OTbFjzBQ.js} +1 -1
- package/build/client/_app/immutable/chunks/OTbFjzBQ.js.br +0 -0
- package/build/client/_app/immutable/chunks/OTbFjzBQ.js.gz +0 -0
- package/build/client/_app/immutable/chunks/{UJuWD2W4.js → TQ9V_LBO.js} +1 -1
- package/build/client/_app/immutable/chunks/TQ9V_LBO.js.br +0 -0
- package/build/client/_app/immutable/chunks/TQ9V_LBO.js.gz +0 -0
- package/build/client/_app/immutable/chunks/{B3q3gQD5.js → p4lxgeXU.js} +3 -3
- package/build/client/_app/immutable/chunks/p4lxgeXU.js.br +0 -0
- package/build/client/_app/immutable/chunks/p4lxgeXU.js.gz +0 -0
- package/build/client/_app/immutable/chunks/pXcSrKpr.js +1 -0
- package/build/client/_app/immutable/chunks/pXcSrKpr.js.br +0 -0
- package/build/client/_app/immutable/chunks/pXcSrKpr.js.gz +0 -0
- package/build/client/_app/immutable/chunks/xuMwtvm-.js +16 -0
- package/build/client/_app/immutable/chunks/xuMwtvm-.js.br +0 -0
- package/build/client/_app/immutable/chunks/xuMwtvm-.js.gz +0 -0
- package/build/client/_app/immutable/entry/app.B7JBkmJ2.js +2 -0
- package/build/client/_app/immutable/entry/app.B7JBkmJ2.js.br +0 -0
- package/build/client/_app/immutable/entry/app.B7JBkmJ2.js.gz +0 -0
- package/build/client/_app/immutable/entry/start.C35Eiz23.js +1 -0
- package/build/client/_app/immutable/entry/start.C35Eiz23.js.br +2 -0
- package/build/client/_app/immutable/entry/start.C35Eiz23.js.gz +0 -0
- package/build/client/_app/immutable/nodes/0.U3Wc2t11.js +1 -0
- package/build/client/_app/immutable/nodes/0.U3Wc2t11.js.br +0 -0
- package/build/client/_app/immutable/nodes/0.U3Wc2t11.js.gz +0 -0
- package/build/client/_app/immutable/nodes/1.YN6Ljj2X.js +1 -0
- package/build/client/_app/immutable/nodes/1.YN6Ljj2X.js.br +2 -0
- package/build/client/_app/immutable/nodes/1.YN6Ljj2X.js.gz +0 -0
- package/build/client/_app/immutable/nodes/10.E5c2rVVT.js +3 -0
- package/build/client/_app/immutable/nodes/10.E5c2rVVT.js.br +0 -0
- package/build/client/_app/immutable/nodes/10.E5c2rVVT.js.gz +0 -0
- package/build/client/_app/immutable/nodes/{11.CDi4i_Wb.js → 11.CwiIDBVl.js} +1 -1
- package/build/client/_app/immutable/nodes/11.CwiIDBVl.js.br +0 -0
- package/build/client/_app/immutable/nodes/11.CwiIDBVl.js.gz +0 -0
- package/build/client/_app/immutable/nodes/12.BF4KBraU.js +1 -0
- package/build/client/_app/immutable/nodes/12.BF4KBraU.js.br +0 -0
- package/build/client/_app/immutable/nodes/12.BF4KBraU.js.gz +0 -0
- package/build/client/_app/immutable/nodes/13.BNgciqug.js +65 -0
- package/build/client/_app/immutable/nodes/13.BNgciqug.js.br +0 -0
- package/build/client/_app/immutable/nodes/13.BNgciqug.js.gz +0 -0
- package/build/client/_app/immutable/nodes/{2.DqvBb3C7.js → 2.Byf6opOr.js} +1 -1
- package/build/client/_app/immutable/nodes/2.Byf6opOr.js.br +0 -0
- package/build/client/_app/immutable/nodes/2.Byf6opOr.js.gz +0 -0
- package/build/client/_app/immutable/nodes/{3.27swwcG4.js → 3.B3j0bAgy.js} +1 -1
- package/build/client/_app/immutable/nodes/3.B3j0bAgy.js.br +0 -0
- package/build/client/_app/immutable/nodes/3.B3j0bAgy.js.gz +0 -0
- package/build/client/_app/immutable/nodes/{4.CcholrFe.js → 4.6dtz57ii.js} +1 -1
- package/build/client/_app/immutable/nodes/4.6dtz57ii.js.br +0 -0
- package/build/client/_app/immutable/nodes/4.6dtz57ii.js.gz +0 -0
- package/build/client/_app/immutable/nodes/{5.CzudN9q-.js → 5.COHVaEDo.js} +1 -1
- package/build/client/_app/immutable/nodes/5.COHVaEDo.js.br +0 -0
- package/build/client/_app/immutable/nodes/5.COHVaEDo.js.gz +0 -0
- package/build/client/_app/immutable/nodes/{7.Bmco0vbT.js → 7.Cecp1nCH.js} +1 -1
- package/build/client/_app/immutable/nodes/7.Cecp1nCH.js.br +0 -0
- package/build/client/_app/immutable/nodes/7.Cecp1nCH.js.gz +0 -0
- package/build/client/_app/immutable/nodes/{8.DZLMUPtG.js → 8.DFk2Y9sL.js} +1 -1
- package/build/client/_app/immutable/nodes/8.DFk2Y9sL.js.br +0 -0
- package/build/client/_app/immutable/nodes/8.DFk2Y9sL.js.gz +0 -0
- package/build/client/_app/immutable/nodes/{9.CFkMGjd0.js → 9.W4l2xsEF.js} +1 -1
- package/build/client/_app/immutable/nodes/9.W4l2xsEF.js.br +0 -0
- package/build/client/_app/immutable/nodes/9.W4l2xsEF.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/server/chunks/0-CuiS31Ys.js +22 -0
- package/build/server/chunks/{0-BwUdZ0Qi.js.map → 0-CuiS31Ys.js.map} +1 -1
- package/build/server/chunks/1-C9TxPuQ0.js +9 -0
- package/build/server/chunks/{1-CSzb5YUp.js.map → 1-C9TxPuQ0.js.map} +1 -1
- package/build/server/chunks/{10-CKou-YOv.js → 10-PX9d-jhv.js} +5 -5
- package/build/server/chunks/10-PX9d-jhv.js.map +1 -0
- package/build/server/chunks/{11-CFhS7tPn.js → 11-Bhv-UeEo.js} +4 -4
- package/build/server/chunks/{11-CFhS7tPn.js.map → 11-Bhv-UeEo.js.map} +1 -1
- package/build/server/chunks/{12-Cj8MHbvu.js → 12-BuNmW-Vp.js} +5 -5
- package/build/server/chunks/{12-Cj8MHbvu.js.map → 12-BuNmW-Vp.js.map} +1 -1
- package/build/server/chunks/{13-BuraZ7Jc.js → 13-CAI7Pyhf.js} +4 -4
- package/build/server/chunks/{13-BuraZ7Jc.js.map → 13-CAI7Pyhf.js.map} +1 -1
- package/build/server/chunks/{2-BheEgghx.js → 2-Bx656tbc.js} +2 -2
- package/build/server/chunks/{2-BheEgghx.js.map → 2-Bx656tbc.js.map} +1 -1
- package/build/server/chunks/{3-BwrTscBH.js → 3-B-zRiOJV.js} +2 -2
- package/build/server/chunks/{3-BwrTscBH.js.map → 3-B-zRiOJV.js.map} +1 -1
- package/build/server/chunks/{4-D28kbpdN.js → 4-BBCE4OIo.js} +2 -2
- package/build/server/chunks/{4-D28kbpdN.js.map → 4-BBCE4OIo.js.map} +1 -1
- package/build/server/chunks/{5--wY8V1OC.js → 5-D68X5smv.js} +2 -2
- package/build/server/chunks/{5--wY8V1OC.js.map → 5-D68X5smv.js.map} +1 -1
- package/build/server/chunks/{7-BwceH8Q7.js → 7-C8AZjmDc.js} +4 -4
- package/build/server/chunks/{7-BwceH8Q7.js.map → 7-C8AZjmDc.js.map} +1 -1
- package/build/server/chunks/{8-DyIhulUv.js → 8-CGRiuqYX.js} +5 -5
- package/build/server/chunks/{8-DyIhulUv.js.map → 8-CGRiuqYX.js.map} +1 -1
- package/build/server/chunks/{9-DGNm1JRG.js → 9-CBzIf4Vj.js} +5 -5
- package/build/server/chunks/{9-DGNm1JRG.js.map → 9-CBzIf4Vj.js.map} +1 -1
- package/build/server/chunks/{JsonValue-Cexm3jGT.js → JsonValue-EppVzWzE.js} +88 -36
- package/build/server/chunks/JsonValue-EppVzWzE.js.map +1 -0
- package/build/server/chunks/{Modal-BzZ9u6V6.js → Modal-eRpc5lqR.js} +4 -3
- package/build/server/chunks/Modal-eRpc5lqR.js.map +1 -0
- package/build/server/chunks/{Panel-BHGtM9Vw.js → Panel-HO9t9Spv.js} +2 -2
- package/build/server/chunks/{Panel-BHGtM9Vw.js.map → Panel-HO9t9Spv.js.map} +1 -1
- package/build/server/chunks/{PrettyJson-tOt0PqjF.js → PrettyJson-F3fqxkqU.js} +7 -6
- package/build/server/chunks/PrettyJson-F3fqxkqU.js.map +1 -0
- package/build/server/chunks/{Tooltip-DAE2mkm6.js → Tooltip-Dd-Bzogp.js} +2 -2
- package/build/server/chunks/{Tooltip-DAE2mkm6.js.map → Tooltip-Dd-Bzogp.js.map} +1 -1
- package/build/server/chunks/{TooltipTable-xo_OEG9c.js → TooltipTable-jHWezlEs.js} +3 -3
- package/build/server/chunks/{TooltipTable-xo_OEG9c.js.map → TooltipTable-jHWezlEs.js.map} +1 -1
- package/build/server/chunks/{_layout.svelte-Dji2JJ9X.js → _layout.svelte-CKGgUBvr.js} +9 -3
- package/build/server/chunks/_layout.svelte-CKGgUBvr.js.map +1 -0
- package/build/server/chunks/_page.svelte-BlmdSnTh.js +245 -0
- package/build/server/chunks/_page.svelte-BlmdSnTh.js.map +1 -0
- package/build/server/chunks/{_page.svelte-x1L5xjgQ.js → _page.svelte-ClZj6yzK.js} +7 -7
- package/build/server/chunks/{_page.svelte-x1L5xjgQ.js.map → _page.svelte-ClZj6yzK.js.map} +1 -1
- package/build/server/chunks/{_page.svelte-be8sxgGt.js → _page.svelte-D50SWEhd.js} +8 -8
- package/build/server/chunks/{_page.svelte-be8sxgGt.js.map → _page.svelte-D50SWEhd.js.map} +1 -1
- package/build/server/chunks/{_page.svelte-D-23v2Aa.js → _page.svelte-D8GSKYqN.js} +223 -12
- package/build/server/chunks/_page.svelte-D8GSKYqN.js.map +1 -0
- package/build/server/chunks/{_page.svelte-D9IvgJO5.js → _page.svelte-DBcsXxML.js} +8 -8
- package/build/server/chunks/{_page.svelte-D9IvgJO5.js.map → _page.svelte-DBcsXxML.js.map} +1 -1
- package/build/server/chunks/{_page.svelte-aT9hOnbL.js → _page.svelte-DFzKfImt.js} +8 -8
- package/build/server/chunks/{_page.svelte-aT9hOnbL.js.map → _page.svelte-DFzKfImt.js.map} +1 -1
- package/build/server/chunks/{_page.svelte-D5-pMskg.js → _page.svelte-ZYW4iSHn.js} +8 -8
- package/build/server/chunks/{_page.svelte-D5-pMskg.js.map → _page.svelte-ZYW4iSHn.js.map} +1 -1
- package/build/server/chunks/{index2-eSFyMQpS.js → index2-DBFlGzWV.js} +2 -2
- package/build/server/chunks/{index2-eSFyMQpS.js.map → index2-DBFlGzWV.js.map} +1 -1
- package/build/server/chunks/{mongo-BHk5yAj9.js → mongo-Ndoh6fs5.js} +21 -7
- package/build/server/chunks/mongo-Ndoh6fs5.js.map +1 -0
- package/build/server/chunks/{remote-xxtqbu-ETLGkdRu.js → remote-xxtqbu-fbBqzvFu.js} +3 -3
- package/build/server/chunks/remote-xxtqbu-fbBqzvFu.js.map +1 -0
- package/build/server/chunks/{servers.remote-CGies_Na.js → servers.remote-B1eorl4A.js} +163 -12
- package/build/server/chunks/servers.remote-B1eorl4A.js.map +1 -0
- package/build/server/index.js +2 -2
- package/build/server/index.js.map +1 -1
- package/build/server/manifest.js +15 -15
- package/build/server/manifest.js.map +1 -1
- package/package.json +1 -1
- package/src/api/servers.remote.ts +196 -10
- package/src/app.css +3 -6
- package/src/lib/components/ExplainPanel.svelte +273 -0
- package/src/lib/components/JsonValue.svelte +51 -6
- package/src/lib/components/Modal.svelte +7 -2
- package/src/lib/components/Notifications.svelte +3 -15
- package/src/lib/components/PrettyJson.svelte +1 -1
- package/src/lib/components/SearchBox.svelte +160 -5
- package/src/lib/components/TimeRangeStats.svelte +269 -0
- package/src/lib/icons/IconClose.svelte +21 -0
- package/src/lib/icons/IconExternalLink.svelte +22 -0
- package/src/lib/server/mongo.ts +31 -6
- package/src/lib/types.ts +16 -5
- package/src/routes/servers/[server]/databases/[database]/collections/[collection]/documents/+page.svelte +49 -1
- package/src/routes/servers/[server]/databases/[database]/collections/[collection]/mappings/+page.svelte +219 -79
- package/build/client/_app/immutable/assets/0.CEIWAdGZ.css +0 -1
- package/build/client/_app/immutable/assets/0.CEIWAdGZ.css.br +0 -0
- package/build/client/_app/immutable/assets/0.CEIWAdGZ.css.gz +0 -0
- package/build/client/_app/immutable/assets/10.BrydhPds.css +0 -1
- package/build/client/_app/immutable/assets/10.BrydhPds.css.br +0 -0
- package/build/client/_app/immutable/assets/10.BrydhPds.css.gz +0 -0
- package/build/client/_app/immutable/assets/Modal.zD4dMMyk.css.br +0 -0
- package/build/client/_app/immutable/assets/Modal.zD4dMMyk.css.gz +0 -0
- package/build/client/_app/immutable/chunks/0oUK0vJa.js +0 -1
- package/build/client/_app/immutable/chunks/0oUK0vJa.js.br +0 -0
- package/build/client/_app/immutable/chunks/0oUK0vJa.js.gz +0 -0
- package/build/client/_app/immutable/chunks/B3q3gQD5.js.br +0 -0
- package/build/client/_app/immutable/chunks/B3q3gQD5.js.gz +0 -0
- package/build/client/_app/immutable/chunks/BGXqurs_.js +0 -1
- package/build/client/_app/immutable/chunks/BGXqurs_.js.br +0 -0
- package/build/client/_app/immutable/chunks/BGXqurs_.js.gz +0 -0
- package/build/client/_app/immutable/chunks/BPbCnJEo.js +0 -1
- package/build/client/_app/immutable/chunks/BPbCnJEo.js.br +0 -0
- package/build/client/_app/immutable/chunks/BPbCnJEo.js.gz +0 -0
- package/build/client/_app/immutable/chunks/BXUq66wC.js.br +0 -0
- package/build/client/_app/immutable/chunks/BXUq66wC.js.gz +0 -0
- package/build/client/_app/immutable/chunks/BxoAxRg6.js +0 -1
- package/build/client/_app/immutable/chunks/BxoAxRg6.js.br +0 -0
- package/build/client/_app/immutable/chunks/BxoAxRg6.js.gz +0 -0
- package/build/client/_app/immutable/chunks/ByCRZ7zS.js +0 -2
- package/build/client/_app/immutable/chunks/ByCRZ7zS.js.br +0 -0
- package/build/client/_app/immutable/chunks/ByCRZ7zS.js.gz +0 -0
- package/build/client/_app/immutable/chunks/BybrNGke.js +0 -16
- package/build/client/_app/immutable/chunks/BybrNGke.js.br +0 -0
- package/build/client/_app/immutable/chunks/BybrNGke.js.gz +0 -0
- package/build/client/_app/immutable/chunks/CQi92wY1.js.br +0 -0
- package/build/client/_app/immutable/chunks/CQi92wY1.js.gz +0 -0
- package/build/client/_app/immutable/chunks/CjbrLxJm.js.br +0 -0
- package/build/client/_app/immutable/chunks/CjbrLxJm.js.gz +0 -0
- package/build/client/_app/immutable/chunks/Cs_Y8eC2.js.br +0 -0
- package/build/client/_app/immutable/chunks/Cs_Y8eC2.js.gz +0 -0
- package/build/client/_app/immutable/chunks/DIw4Wyr4.js.br +0 -0
- package/build/client/_app/immutable/chunks/DIw4Wyr4.js.gz +0 -0
- package/build/client/_app/immutable/chunks/Dn0_-jEe.js.br +0 -0
- package/build/client/_app/immutable/chunks/Dn0_-jEe.js.gz +0 -0
- package/build/client/_app/immutable/chunks/Dqjuk_9f.js.br +0 -0
- package/build/client/_app/immutable/chunks/Dqjuk_9f.js.gz +0 -0
- package/build/client/_app/immutable/chunks/DvuSce6Q.js.br +0 -0
- package/build/client/_app/immutable/chunks/DvuSce6Q.js.gz +0 -0
- package/build/client/_app/immutable/chunks/UJuWD2W4.js.br +0 -0
- package/build/client/_app/immutable/chunks/UJuWD2W4.js.gz +0 -0
- package/build/client/_app/immutable/chunks/XRLS4Bbp.js +0 -1
- package/build/client/_app/immutable/chunks/XRLS4Bbp.js.br +0 -0
- package/build/client/_app/immutable/chunks/XRLS4Bbp.js.gz +0 -0
- package/build/client/_app/immutable/chunks/_kKBJjiB.js +0 -1
- package/build/client/_app/immutable/chunks/_kKBJjiB.js.br +0 -0
- package/build/client/_app/immutable/chunks/_kKBJjiB.js.gz +0 -0
- package/build/client/_app/immutable/chunks/reNJcONQ.js.br +0 -0
- package/build/client/_app/immutable/entry/app.BPKl8oaJ.js +0 -2
- package/build/client/_app/immutable/entry/app.BPKl8oaJ.js.br +0 -0
- package/build/client/_app/immutable/entry/app.BPKl8oaJ.js.gz +0 -0
- package/build/client/_app/immutable/entry/start.DWHdYJ-L.js +0 -1
- package/build/client/_app/immutable/entry/start.DWHdYJ-L.js.br +0 -2
- package/build/client/_app/immutable/entry/start.DWHdYJ-L.js.gz +0 -0
- package/build/client/_app/immutable/nodes/0.B2NjMPUg.js +0 -1
- package/build/client/_app/immutable/nodes/0.B2NjMPUg.js.br +0 -0
- package/build/client/_app/immutable/nodes/0.B2NjMPUg.js.gz +0 -0
- package/build/client/_app/immutable/nodes/1.DIJdjioz.js +0 -1
- package/build/client/_app/immutable/nodes/1.DIJdjioz.js.br +0 -1
- package/build/client/_app/immutable/nodes/1.DIJdjioz.js.gz +0 -0
- package/build/client/_app/immutable/nodes/10.DBt9LqZ5.js +0 -3
- package/build/client/_app/immutable/nodes/10.DBt9LqZ5.js.br +0 -0
- package/build/client/_app/immutable/nodes/10.DBt9LqZ5.js.gz +0 -0
- package/build/client/_app/immutable/nodes/11.CDi4i_Wb.js.br +0 -0
- package/build/client/_app/immutable/nodes/11.CDi4i_Wb.js.gz +0 -0
- package/build/client/_app/immutable/nodes/12.CbEEqmwu.js +0 -1
- package/build/client/_app/immutable/nodes/12.CbEEqmwu.js.br +0 -0
- package/build/client/_app/immutable/nodes/12.CbEEqmwu.js.gz +0 -0
- package/build/client/_app/immutable/nodes/13.DuXWHwDt.js +0 -66
- package/build/client/_app/immutable/nodes/13.DuXWHwDt.js.br +0 -0
- package/build/client/_app/immutable/nodes/13.DuXWHwDt.js.gz +0 -0
- package/build/client/_app/immutable/nodes/2.DqvBb3C7.js.br +0 -0
- package/build/client/_app/immutable/nodes/2.DqvBb3C7.js.gz +0 -0
- package/build/client/_app/immutable/nodes/3.27swwcG4.js.br +0 -0
- package/build/client/_app/immutable/nodes/3.27swwcG4.js.gz +0 -0
- package/build/client/_app/immutable/nodes/4.CcholrFe.js.br +0 -0
- package/build/client/_app/immutable/nodes/4.CcholrFe.js.gz +0 -0
- package/build/client/_app/immutable/nodes/5.CzudN9q-.js.br +0 -0
- package/build/client/_app/immutable/nodes/5.CzudN9q-.js.gz +0 -0
- package/build/client/_app/immutable/nodes/7.Bmco0vbT.js.br +0 -0
- package/build/client/_app/immutable/nodes/7.Bmco0vbT.js.gz +0 -0
- package/build/client/_app/immutable/nodes/8.DZLMUPtG.js.br +0 -0
- package/build/client/_app/immutable/nodes/8.DZLMUPtG.js.gz +0 -0
- package/build/client/_app/immutable/nodes/9.CFkMGjd0.js.br +0 -0
- package/build/client/_app/immutable/nodes/9.CFkMGjd0.js.gz +0 -0
- package/build/server/chunks/0-BwUdZ0Qi.js +0 -22
- package/build/server/chunks/1-CSzb5YUp.js +0 -9
- package/build/server/chunks/10-CKou-YOv.js.map +0 -1
- package/build/server/chunks/JsonValue-Cexm3jGT.js.map +0 -1
- package/build/server/chunks/Modal-BzZ9u6V6.js.map +0 -1
- package/build/server/chunks/PrettyJson-tOt0PqjF.js.map +0 -1
- package/build/server/chunks/_layout.svelte-Dji2JJ9X.js.map +0 -1
- package/build/server/chunks/_page.svelte-CJ5HzoD0.js +0 -203
- package/build/server/chunks/_page.svelte-CJ5HzoD0.js.map +0 -1
- package/build/server/chunks/_page.svelte-D-23v2Aa.js.map +0 -1
- package/build/server/chunks/mongo-BHk5yAj9.js.map +0 -1
- package/build/server/chunks/remote-xxtqbu-ETLGkdRu.js.map +0 -1
- package/build/server/chunks/servers.remote-CGies_Na.js.map +0 -1
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
interface Props {
|
|
3
|
+
class?: string;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
let { class: className = "w-4 h-4" }: Props = $props();
|
|
7
|
+
</script>
|
|
8
|
+
|
|
9
|
+
<svg
|
|
10
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
11
|
+
viewBox="0 0 24 24"
|
|
12
|
+
fill="none"
|
|
13
|
+
stroke="currentColor"
|
|
14
|
+
stroke-width="2"
|
|
15
|
+
stroke-linecap="round"
|
|
16
|
+
stroke-linejoin="round"
|
|
17
|
+
class={className}
|
|
18
|
+
>
|
|
19
|
+
<line x1="18" y1="6" x2="6" y2="18"></line>
|
|
20
|
+
<line x1="6" y1="6" x2="18" y2="18"></line>
|
|
21
|
+
</svg>
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
interface Props {
|
|
3
|
+
class?: string;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
let { class: className = "w-4 h-4" }: Props = $props();
|
|
7
|
+
</script>
|
|
8
|
+
|
|
9
|
+
<svg
|
|
10
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
11
|
+
viewBox="0 0 24 24"
|
|
12
|
+
fill="none"
|
|
13
|
+
stroke="currentColor"
|
|
14
|
+
stroke-width="2"
|
|
15
|
+
stroke-linecap="round"
|
|
16
|
+
stroke-linejoin="round"
|
|
17
|
+
class={className}
|
|
18
|
+
>
|
|
19
|
+
<path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6" />
|
|
20
|
+
<polyline points="15 3 21 3 21 9" />
|
|
21
|
+
<line x1="10" x2="21" y1="14" y2="3" />
|
|
22
|
+
</svg>
|
package/src/lib/server/mongo.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { logger } from "$lib/server/logger";
|
|
2
2
|
import type { CollectionJSON, CollectionMappings, Mappings } from "$lib/types";
|
|
3
3
|
import { resolveSrv } from "dns/promises";
|
|
4
|
-
import { MongoClient, type Collection } from "mongodb";
|
|
4
|
+
import { MongoClient, ReadPreference, type Collection } from "mongodb";
|
|
5
5
|
import { URL } from "url";
|
|
6
6
|
import { HostsManager } from "./HostsManager";
|
|
7
7
|
|
|
@@ -129,8 +129,8 @@ class MongoClientWithMappings extends MongoClient {
|
|
|
129
129
|
_id: string;
|
|
130
130
|
name: string;
|
|
131
131
|
|
|
132
|
-
constructor(url: string, _id: string, name: string) {
|
|
133
|
-
super(url);
|
|
132
|
+
constructor(url: string, _id: string, name: string, readPreference?: ReadPreference) {
|
|
133
|
+
super(url, readPreference ? { readPreference } : {});
|
|
134
134
|
this.url = url;
|
|
135
135
|
this._id = _id;
|
|
136
136
|
this.name = name;
|
|
@@ -164,6 +164,7 @@ class MongoConnections {
|
|
|
164
164
|
? parseInt(process.env.MONGOKU_QUERY_TIMEOUT, 10)
|
|
165
165
|
: undefined;
|
|
166
166
|
private excludedDatabases: Set<string>;
|
|
167
|
+
private readPreference: ReadPreference | undefined;
|
|
167
168
|
|
|
168
169
|
constructor() {
|
|
169
170
|
this.hostsManager = new HostsManager();
|
|
@@ -175,6 +176,30 @@ class MongoConnections {
|
|
|
175
176
|
.map((db) => db.trim())
|
|
176
177
|
.filter((db) => db.length > 0),
|
|
177
178
|
);
|
|
179
|
+
|
|
180
|
+
// Parse read preference from env vars
|
|
181
|
+
// MONGOKU_READ_PREFERENCE: primary, primaryPreferred, secondary, secondaryPreferred, nearest
|
|
182
|
+
// MONGOKU_READ_PREFERENCE_TAGS: JSON array of tag sets, e.g. [{"nodeType":"ANALYTICS"},{}]
|
|
183
|
+
const readPrefMode = process.env.MONGOKU_READ_PREFERENCE as
|
|
184
|
+
| "primary"
|
|
185
|
+
| "primaryPreferred"
|
|
186
|
+
| "secondary"
|
|
187
|
+
| "secondaryPreferred"
|
|
188
|
+
| "nearest"
|
|
189
|
+
| undefined;
|
|
190
|
+
|
|
191
|
+
if (readPrefMode) {
|
|
192
|
+
let tags: Array<Record<string, string>> | undefined;
|
|
193
|
+
if (process.env.MONGOKU_READ_PREFERENCE_TAGS) {
|
|
194
|
+
try {
|
|
195
|
+
tags = JSON.parse(process.env.MONGOKU_READ_PREFERENCE_TAGS);
|
|
196
|
+
} catch (err) {
|
|
197
|
+
logger.error("Failed to parse MONGOKU_READ_PREFERENCE_TAGS:", err);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
this.readPreference = tags ? new ReadPreference(readPrefMode, tags) : new ReadPreference(readPrefMode);
|
|
201
|
+
logger.log(`Read preference configured: ${readPrefMode}${tags ? ` with tags ${JSON.stringify(tags)}` : ""}`);
|
|
202
|
+
}
|
|
178
203
|
}
|
|
179
204
|
|
|
180
205
|
async initialize() {
|
|
@@ -189,7 +214,7 @@ class MongoConnections {
|
|
|
189
214
|
const hostname = url.host || host.path;
|
|
190
215
|
|
|
191
216
|
if (!this.clients.has(hostname)) {
|
|
192
|
-
const client = new MongoClientWithMappings(urlStr, host._id, hostname);
|
|
217
|
+
const client = new MongoClientWithMappings(urlStr, host._id, hostname, this.readPreference);
|
|
193
218
|
this.clients.set(host._id, client);
|
|
194
219
|
this.clientIds.set(hostname, host._id);
|
|
195
220
|
}
|
|
@@ -244,7 +269,7 @@ class MongoConnections {
|
|
|
244
269
|
const hostname = url.host || hostPath;
|
|
245
270
|
|
|
246
271
|
if (!this.clients.has(hostname)) {
|
|
247
|
-
const client = new MongoClientWithMappings(urlStr, id, hostname);
|
|
272
|
+
const client = new MongoClientWithMappings(urlStr, id, hostname, this.readPreference);
|
|
248
273
|
this.clients.set(id, client);
|
|
249
274
|
this.clientIds.set(hostname, id);
|
|
250
275
|
}
|
|
@@ -275,7 +300,7 @@ class MongoConnections {
|
|
|
275
300
|
oldClient.close().catch((err) => logger.error(`Error closing old client ${id}:`, err));
|
|
276
301
|
|
|
277
302
|
// Create a new client
|
|
278
|
-
const newClient = new MongoClientWithMappings(oldClient.url, id, oldClient.name);
|
|
303
|
+
const newClient = new MongoClientWithMappings(oldClient.url, id, oldClient.name, this.readPreference);
|
|
279
304
|
this.clients.set(id, newClient);
|
|
280
305
|
|
|
281
306
|
// Test the connection
|
package/src/lib/types.ts
CHANGED
|
@@ -100,12 +100,23 @@ export const ALLOWED_AGGREGATION_STAGES = new Set([
|
|
|
100
100
|
]);
|
|
101
101
|
|
|
102
102
|
/**
|
|
103
|
-
* A single mapping target - defines
|
|
103
|
+
* A single mapping target - defines either a collection lookup or URL template
|
|
104
104
|
*/
|
|
105
|
-
export
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
105
|
+
export type MappingTarget =
|
|
106
|
+
| {
|
|
107
|
+
type: "document";
|
|
108
|
+
collection: string;
|
|
109
|
+
on: string;
|
|
110
|
+
}
|
|
111
|
+
| {
|
|
112
|
+
type: "url";
|
|
113
|
+
template: string;
|
|
114
|
+
}
|
|
115
|
+
// Legacy format (backwards compatibility) - treated as type: "document"
|
|
116
|
+
| {
|
|
117
|
+
collection: string;
|
|
118
|
+
on: string;
|
|
119
|
+
};
|
|
109
120
|
|
|
110
121
|
export type Mappings = Record<string, MappingTarget[] | MappingTarget>;
|
|
111
122
|
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
countDocuments,
|
|
4
4
|
deleteDocument as deleteDocumentCommand,
|
|
5
5
|
deleteMany as deleteManyCommand,
|
|
6
|
+
explainQuery,
|
|
6
7
|
insertDocument as insertDocumentCommand,
|
|
7
8
|
loadDocuments,
|
|
8
9
|
updateDocument as updateDocumentCommand,
|
|
@@ -11,6 +12,7 @@
|
|
|
11
12
|
import { pushState } from "$app/navigation";
|
|
12
13
|
import { resolve } from "$app/paths";
|
|
13
14
|
import { jsonTextarea } from "$lib/actions/jsonTextarea";
|
|
15
|
+
import ExplainPanel from "$lib/components/ExplainPanel.svelte";
|
|
14
16
|
import Panel from "$lib/components/Panel.svelte";
|
|
15
17
|
import PrettyJson from "$lib/components/PrettyJson.svelte";
|
|
16
18
|
import SearchBox from "$lib/components/SearchBox.svelte";
|
|
@@ -33,6 +35,11 @@
|
|
|
33
35
|
let isUpdating = $state(false);
|
|
34
36
|
let showInsertEditor = $state(false);
|
|
35
37
|
|
|
38
|
+
// Explain state
|
|
39
|
+
let explainLoading = $state(false);
|
|
40
|
+
let explainData = $state<unknown>(null);
|
|
41
|
+
let showExplain = $state(false);
|
|
42
|
+
|
|
36
43
|
let deleteState = $state({
|
|
37
44
|
countChecked: false,
|
|
38
45
|
count: null as number | null,
|
|
@@ -408,6 +415,36 @@
|
|
|
408
415
|
notificationStore.notifyError(error, "Failed to copy to clipboard");
|
|
409
416
|
}
|
|
410
417
|
}
|
|
418
|
+
|
|
419
|
+
async function handleExplain() {
|
|
420
|
+
explainLoading = true;
|
|
421
|
+
try {
|
|
422
|
+
const result = await explainQuery({
|
|
423
|
+
server: data.server,
|
|
424
|
+
database: data.database,
|
|
425
|
+
collection: data.collection,
|
|
426
|
+
query: params.query || "{}",
|
|
427
|
+
sort: params.sort || "{}",
|
|
428
|
+
project: params.project || "{}",
|
|
429
|
+
skip: params.skip,
|
|
430
|
+
limit: params.limit,
|
|
431
|
+
mode: params.mode === "aggregation" ? "aggregation" : "query",
|
|
432
|
+
verbosity: "executionStats",
|
|
433
|
+
});
|
|
434
|
+
|
|
435
|
+
if (result.error) {
|
|
436
|
+
notificationStore.notifyError(result.error);
|
|
437
|
+
} else {
|
|
438
|
+
explainData = result.data;
|
|
439
|
+
showExplain = true;
|
|
440
|
+
}
|
|
441
|
+
} catch (error) {
|
|
442
|
+
console.error(error);
|
|
443
|
+
notificationStore.notifyError(error, "Failed to explain query");
|
|
444
|
+
} finally {
|
|
445
|
+
explainLoading = false;
|
|
446
|
+
}
|
|
447
|
+
}
|
|
411
448
|
</script>
|
|
412
449
|
|
|
413
450
|
{#snippet previousButton(url: string, onClick: (e: MouseEvent) => void)}
|
|
@@ -456,7 +493,18 @@
|
|
|
456
493
|
</button>
|
|
457
494
|
{/snippet}
|
|
458
495
|
|
|
459
|
-
<SearchBox
|
|
496
|
+
<SearchBox
|
|
497
|
+
bind:params
|
|
498
|
+
bind:editMode
|
|
499
|
+
readonly={data.readOnly}
|
|
500
|
+
{explainLoading}
|
|
501
|
+
onexplain={handleExplain}
|
|
502
|
+
server={data.server}
|
|
503
|
+
database={data.database}
|
|
504
|
+
collection={data.collection}
|
|
505
|
+
/>
|
|
506
|
+
|
|
507
|
+
<ExplainPanel data={explainData} show={showExplain} onclose={() => (showExplain = false)} />
|
|
460
508
|
|
|
461
509
|
{#if editMode}
|
|
462
510
|
<Panel title="Edit Mode">
|
|
@@ -6,6 +6,15 @@
|
|
|
6
6
|
import type { MappingTarget } from "$lib/types";
|
|
7
7
|
import type { PageData } from "./$types";
|
|
8
8
|
let { data }: { data: PageData } = $props();
|
|
9
|
+
// Helper to normalize mapping target to new format
|
|
10
|
+
function normalizeMappingTarget(target: MappingTarget): MappingTarget {
|
|
11
|
+
if ("type" in target) {
|
|
12
|
+
return target;
|
|
13
|
+
}
|
|
14
|
+
// Legacy format - add type: "document"
|
|
15
|
+
return { type: "document", collection: target.collection, on: target.on };
|
|
16
|
+
}
|
|
17
|
+
|
|
9
18
|
// Convert mappings to an editable array format
|
|
10
19
|
type MappingEntry = {
|
|
11
20
|
fieldPath: string;
|
|
@@ -14,13 +23,15 @@
|
|
|
14
23
|
let mappingsArray = $state<MappingEntry[]>(
|
|
15
24
|
Object.entries(data.mappings).map(([fieldPath, targets]) => ({
|
|
16
25
|
fieldPath,
|
|
17
|
-
targets: Array.isArray(targets) ? targets : [targets],
|
|
26
|
+
targets: (Array.isArray(targets) ? targets : [targets]).map(normalizeMappingTarget),
|
|
18
27
|
})),
|
|
19
28
|
);
|
|
20
29
|
// New mapping form state
|
|
21
30
|
let newFieldPath = $state("");
|
|
31
|
+
let newMappingType = $state<"document" | "url">("document");
|
|
22
32
|
let newTargetCollection = $state("");
|
|
23
33
|
let newTargetField = $state("_id");
|
|
34
|
+
let newUrlTemplate = $state("");
|
|
24
35
|
let isAdding = $state(false);
|
|
25
36
|
let showAiPrompt = $state(false);
|
|
26
37
|
|
|
@@ -50,8 +61,8 @@ Create a file named \`${data.collection}.mappings.json\` with the following stru
|
|
|
50
61
|
{
|
|
51
62
|
"_id": "${data.collection}",
|
|
52
63
|
"mappings": {
|
|
53
|
-
"fieldPath": { "collection": "targetCollection", "on": "targetField" },
|
|
54
|
-
"nested.fieldPath": { "collection": "targetCollection", "on": "targetField" }
|
|
64
|
+
"fieldPath": { "type": "document", "collection": "targetCollection", "on": "targetField" },
|
|
65
|
+
"nested.fieldPath": { "type": "document", "collection": "targetCollection", "on": "targetField" }
|
|
55
66
|
}
|
|
56
67
|
}
|
|
57
68
|
\`\`\`
|
|
@@ -73,8 +84,8 @@ The mappings would be:
|
|
|
73
84
|
{
|
|
74
85
|
"_id": "${data.collection}",
|
|
75
86
|
"mappings": {
|
|
76
|
-
"authorId": { "collection": "users", "on": "_id" },
|
|
77
|
-
"comments.authorId": { "collection": "users", "on": "_id" }
|
|
87
|
+
"authorId": { "type": "document", "collection": "users", "on": "_id" },
|
|
88
|
+
"comments.authorId": { "type": "document", "collection": "users", "on": "_id" }
|
|
78
89
|
}
|
|
79
90
|
}
|
|
80
91
|
\`\`\`
|
|
@@ -94,8 +105,12 @@ Please analyze the codebase and database, then generate the appropriate mappings
|
|
|
94
105
|
notificationStore.notifyError(err, "Failed to copy to clipboard");
|
|
95
106
|
}
|
|
96
107
|
}
|
|
97
|
-
function addTarget(entry: MappingEntry) {
|
|
98
|
-
|
|
108
|
+
function addTarget(entry: MappingEntry, type: "document" | "url" = "document") {
|
|
109
|
+
if (type === "document") {
|
|
110
|
+
entry.targets.push({ type: "document", collection: "", on: "_id" });
|
|
111
|
+
} else {
|
|
112
|
+
entry.targets.push({ type: "url", template: "" });
|
|
113
|
+
}
|
|
99
114
|
}
|
|
100
115
|
function removeTarget(entry: MappingEntry, index: number) {
|
|
101
116
|
entry.targets.splice(index, 1);
|
|
@@ -108,24 +123,44 @@ Please analyze the codebase and database, then generate the appropriate mappings
|
|
|
108
123
|
notificationStore.notifyError("Field path is required");
|
|
109
124
|
return;
|
|
110
125
|
}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
126
|
+
|
|
127
|
+
let newTarget: MappingTarget;
|
|
128
|
+
if (newMappingType === "document") {
|
|
129
|
+
if (!newTargetCollection.trim()) {
|
|
130
|
+
notificationStore.notifyError("Target collection is required");
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
newTarget = {
|
|
134
|
+
type: "document",
|
|
135
|
+
collection: newTargetCollection.trim(),
|
|
136
|
+
on: newTargetField.trim() || "_id",
|
|
137
|
+
};
|
|
138
|
+
} else {
|
|
139
|
+
if (!newUrlTemplate.trim()) {
|
|
140
|
+
notificationStore.notifyError("URL template is required");
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
newTarget = { type: "url", template: newUrlTemplate.trim() };
|
|
114
144
|
}
|
|
145
|
+
|
|
115
146
|
mappingsArray.push({
|
|
116
147
|
fieldPath: newFieldPath.trim(),
|
|
117
|
-
targets: [
|
|
148
|
+
targets: [newTarget],
|
|
118
149
|
});
|
|
119
150
|
// Reset form
|
|
120
151
|
newFieldPath = "";
|
|
152
|
+
newMappingType = "document";
|
|
121
153
|
newTargetCollection = "";
|
|
122
154
|
newTargetField = "_id";
|
|
155
|
+
newUrlTemplate = "";
|
|
123
156
|
isAdding = false;
|
|
124
157
|
}
|
|
125
158
|
function cancelAdd() {
|
|
126
159
|
newFieldPath = "";
|
|
160
|
+
newMappingType = "document";
|
|
127
161
|
newTargetCollection = "";
|
|
128
162
|
newTargetField = "_id";
|
|
163
|
+
newUrlTemplate = "";
|
|
129
164
|
isAdding = false;
|
|
130
165
|
}
|
|
131
166
|
async function saveMappings() {
|
|
@@ -135,7 +170,19 @@ Please analyze the codebase and database, then generate the appropriate mappings
|
|
|
135
170
|
for (const entry of mappingsArray) {
|
|
136
171
|
if (entry.fieldPath.trim()) {
|
|
137
172
|
// Filter out empty targets
|
|
138
|
-
const validTargets = entry.targets.filter((t) =>
|
|
173
|
+
const validTargets = entry.targets.filter((t) => {
|
|
174
|
+
if ("type" in t) {
|
|
175
|
+
if (t.type === "document") {
|
|
176
|
+
return t.collection.trim() && t.on.trim();
|
|
177
|
+
} else if (t.type === "url") {
|
|
178
|
+
return t.template.trim();
|
|
179
|
+
}
|
|
180
|
+
} else {
|
|
181
|
+
// Legacy format
|
|
182
|
+
return t.collection.trim() && t.on.trim();
|
|
183
|
+
}
|
|
184
|
+
return false;
|
|
185
|
+
});
|
|
139
186
|
if (validTargets.length > 0) {
|
|
140
187
|
mappingsObj[entry.fieldPath] = validTargets.length === 1 ? validTargets[0] : validTargets;
|
|
141
188
|
}
|
|
@@ -165,18 +212,16 @@ Please analyze the codebase and database, then generate the appropriate mappings
|
|
|
165
212
|
🤖 AI Helper
|
|
166
213
|
</button>
|
|
167
214
|
{#if !data.readOnly}
|
|
168
|
-
<button class="btn btn-success btn-sm -my-2
|
|
169
|
-
>Save</button
|
|
170
|
-
>
|
|
215
|
+
<button class="btn btn-success btn-sm -my-2" onclick={saveMappings}>Save</button>
|
|
171
216
|
{/if}
|
|
172
217
|
{/snippet}
|
|
173
218
|
|
|
174
219
|
<div class="p-4">
|
|
175
220
|
<div class="mb-4">
|
|
176
221
|
<p class="mb-3">
|
|
177
|
-
Define relationships between collections to enable hover tooltips
|
|
178
|
-
will be stored in the
|
|
179
|
-
as a document with
|
|
222
|
+
Define relationships between collections or external URLs to enable hover tooltips, navigation on foreign key
|
|
223
|
+
fields, and clickable external links. This will be stored in the
|
|
224
|
+
<code class="px-1 bg-[var(--light-background)] rounded">mongoku.mappings</code> collection as a document with
|
|
180
225
|
<a
|
|
181
226
|
href={resolve(
|
|
182
227
|
`/servers/${data.server}/databases/${data.database}/collections/mongoku.mappings/documents/${data.collection}`,
|
|
@@ -185,26 +230,47 @@ Please analyze the codebase and database, then generate the appropriate mappings
|
|
|
185
230
|
>.
|
|
186
231
|
</p>
|
|
187
232
|
<details class="mb-2" style="color: var(--text-secondary);">
|
|
188
|
-
<summary class="cursor-pointer font-medium mb-2">
|
|
189
|
-
<div class="mt-2">
|
|
190
|
-
<div
|
|
191
|
-
|
|
233
|
+
<summary class="cursor-pointer font-medium mb-2">Examples</summary>
|
|
234
|
+
<div class="mt-2 space-y-3">
|
|
235
|
+
<div>
|
|
236
|
+
<div class="font-medium mb-1">Document Mapping Example:</div>
|
|
237
|
+
<div class="mb-1">
|
|
238
|
+
Document in collection <code class="px-1 bg-[var(--light-background)] rounded">posts</code>:
|
|
239
|
+
</div>
|
|
240
|
+
<code class="block px-2 py-1 bg-[var(--light-background)] rounded text-xs mb-2">
|
|
241
|
+
{ _id: "post1", title: "Hello", authorId: "user123", comments: [{authorId: "user456", text:
|
|
242
|
+
"Nice!"}] }
|
|
243
|
+
</code>
|
|
244
|
+
<div class="text space-y-1">
|
|
245
|
+
<div>
|
|
246
|
+
→ Mapping 1: Field path <code class="px-1 bg-[var(--light-background)] rounded">authorId</code>, type
|
|
247
|
+
<strong>document</strong>, target collection
|
|
248
|
+
<code class="px-1 bg-[var(--light-background)] rounded">users</code>, target field
|
|
249
|
+
<code class="px-1 bg-[var(--light-background)] rounded">_id</code>
|
|
250
|
+
</div>
|
|
251
|
+
<div>
|
|
252
|
+
→ Mapping 2: Field path <code class="px-1 bg-[var(--light-background)] rounded">comments.authorId</code
|
|
253
|
+
>, type <strong>document</strong>, target collection
|
|
254
|
+
<code class="px-1 bg-[var(--light-background)] rounded">users</code>, target field
|
|
255
|
+
<code class="px-1 bg-[var(--light-background)] rounded">_id</code>
|
|
256
|
+
</div>
|
|
257
|
+
</div>
|
|
192
258
|
</div>
|
|
193
|
-
<
|
|
194
|
-
|
|
195
|
-
"
|
|
196
|
-
|
|
197
|
-
<div class="text space-y-1">
|
|
198
|
-
<div>
|
|
199
|
-
→ Mapping 1: Field path <code class="px-1 bg-[var(--light-background)] rounded">authorId</code>, target
|
|
200
|
-
collection
|
|
201
|
-
<code class="px-1 bg-[var(--light-background)] rounded">users</code>, target field
|
|
202
|
-
<code class="px-1 bg-[var(--light-background)] rounded">_id</code>
|
|
259
|
+
<div>
|
|
260
|
+
<div class="font-medium mb-1">URL Mapping Example:</div>
|
|
261
|
+
<div class="mb-1">
|
|
262
|
+
Document in collection <code class="px-1 bg-[var(--light-background)] rounded">dataset_info_cache</code>:
|
|
203
263
|
</div>
|
|
204
|
-
<
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
264
|
+
<code class="block px-2 py-1 bg-[var(--light-background)] rounded text-xs mb-2">
|
|
265
|
+
{ _id: "abc/glue", name: "GLUE Benchmark", ... }
|
|
266
|
+
</code>
|
|
267
|
+
<div class="text space-y-1">
|
|
268
|
+
<div>
|
|
269
|
+
→ Mapping: Field path <code class="px-1 bg-[var(--light-background)] rounded">_id</code>, type
|
|
270
|
+
<strong>URL</strong>, template
|
|
271
|
+
<code class="px-1 bg-[var(--light-background)] rounded">https://hf.co/datasets/{value}</code>
|
|
272
|
+
</div>
|
|
273
|
+
<div class="ml-4">Result: Clicking the _id will open "https://hf.co/datasets/abc/glue" in a new tab</div>
|
|
208
274
|
</div>
|
|
209
275
|
</div>
|
|
210
276
|
</div>
|
|
@@ -240,34 +306,75 @@ Please analyze the codebase and database, then generate the appropriate mappings
|
|
|
240
306
|
|
|
241
307
|
<div class="space-y-2">
|
|
242
308
|
{#each entry.targets as target, targetIndex (targetIndex)}
|
|
309
|
+
{@const targetType = "type" in target ? target.type : "document"}
|
|
243
310
|
<div class="flex items-start gap-2 pl-4 border-l-2 border-[var(--color-3)]">
|
|
244
311
|
<div class="flex-1">
|
|
245
312
|
<label class="block text-xs mb-1">
|
|
246
|
-
|
|
313
|
+
Type
|
|
247
314
|
<select
|
|
248
|
-
|
|
315
|
+
value={targetType}
|
|
316
|
+
onchange={(e) => {
|
|
317
|
+
const newType = e.currentTarget.value as "document" | "url";
|
|
318
|
+
if (newType === "document") {
|
|
319
|
+
entry.targets[targetIndex] = { type: "document", collection: "", on: "_id" };
|
|
320
|
+
} else {
|
|
321
|
+
entry.targets[targetIndex] = { type: "url", template: "" };
|
|
322
|
+
}
|
|
323
|
+
}}
|
|
249
324
|
class="w-full px-3 py-2 bg-[var(--color-1)] border border-[var(--border-color)] rounded text-sm mt-1"
|
|
250
325
|
disabled={data.readOnly}
|
|
251
326
|
>
|
|
252
|
-
<option value="">
|
|
253
|
-
|
|
254
|
-
<option value={col}>{col}</option>
|
|
255
|
-
{/each}
|
|
327
|
+
<option value="document">Document</option>
|
|
328
|
+
<option value="url">URL</option>
|
|
256
329
|
</select>
|
|
257
330
|
</label>
|
|
258
331
|
</div>
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
332
|
+
{#if targetType === "document"}
|
|
333
|
+
{@const collectionTarget = target as
|
|
334
|
+
| { type: "document"; collection: string; on: string }
|
|
335
|
+
| { collection: string; on: string }}
|
|
336
|
+
<div class="flex-1">
|
|
337
|
+
<label class="block text-xs mb-1">
|
|
338
|
+
Target Collection
|
|
339
|
+
<select
|
|
340
|
+
bind:value={collectionTarget.collection}
|
|
341
|
+
class="w-full px-3 py-2 bg-[var(--color-1)] border border-[var(--border-color)] rounded text-sm mt-1"
|
|
342
|
+
disabled={data.readOnly}
|
|
343
|
+
>
|
|
344
|
+
<option value="">Select collection...</option>
|
|
345
|
+
{#each data.availableCollections as col (col)}
|
|
346
|
+
<option value={col}>{col}</option>
|
|
347
|
+
{/each}
|
|
348
|
+
</select>
|
|
349
|
+
</label>
|
|
350
|
+
</div>
|
|
351
|
+
<div class="flex-1">
|
|
352
|
+
<label class="block text-xs mb-1">
|
|
353
|
+
Target Field
|
|
354
|
+
<input
|
|
355
|
+
type="text"
|
|
356
|
+
bind:value={collectionTarget.on}
|
|
357
|
+
placeholder="_id"
|
|
358
|
+
class="w-full px-3 py-2 bg-[var(--color-1)] border border-[var(--border-color)] rounded text-sm mt-1"
|
|
359
|
+
disabled={data.readOnly}
|
|
360
|
+
/>
|
|
361
|
+
</label>
|
|
362
|
+
</div>
|
|
363
|
+
{:else}
|
|
364
|
+
{@const urlTarget = target as { type: "url"; template: string }}
|
|
365
|
+
<div class="flex-[2]">
|
|
366
|
+
<label class="block text-xs mb-1">
|
|
367
|
+
URL Template (use {value} for interpolation)
|
|
368
|
+
<input
|
|
369
|
+
type="text"
|
|
370
|
+
bind:value={urlTarget.template}
|
|
371
|
+
placeholder="https://example.com/{value}"
|
|
372
|
+
class="w-full px-3 py-2 bg-[var(--color-1)] border border-[var(--border-color)] rounded text-sm mt-1"
|
|
373
|
+
disabled={data.readOnly}
|
|
374
|
+
/>
|
|
375
|
+
</label>
|
|
376
|
+
</div>
|
|
377
|
+
{/if}
|
|
271
378
|
{#if !data.readOnly}
|
|
272
379
|
<button
|
|
273
380
|
class="btn btn-outline-danger btn-sm mt-5 hover:bg-[rgba(255,59,48,0.1)]"
|
|
@@ -282,12 +389,20 @@ Please analyze the codebase and database, then generate the appropriate mappings
|
|
|
282
389
|
</div>
|
|
283
390
|
|
|
284
391
|
{#if !data.readOnly}
|
|
285
|
-
<
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
392
|
+
<div class="flex gap-2 mt-2 ml-4">
|
|
393
|
+
<button
|
|
394
|
+
class="btn btn-outline-light btn-sm hover:bg-[var(--color-3)]"
|
|
395
|
+
onclick={() => addTarget(entry, "document")}
|
|
396
|
+
>
|
|
397
|
+
+ Add Document Target
|
|
398
|
+
</button>
|
|
399
|
+
<button
|
|
400
|
+
class="btn btn-outline-light btn-sm hover:bg-[var(--color-3)]"
|
|
401
|
+
onclick={() => addTarget(entry, "url")}
|
|
402
|
+
>
|
|
403
|
+
+ Add URL Target
|
|
404
|
+
</button>
|
|
405
|
+
</div>
|
|
291
406
|
{/if}
|
|
292
407
|
</div>
|
|
293
408
|
{/each}
|
|
@@ -299,9 +414,7 @@ Please analyze the codebase and database, then generate the appropriate mappings
|
|
|
299
414
|
{#if !data.readOnly}
|
|
300
415
|
<div class="mt-4">
|
|
301
416
|
{#if !isAdding}
|
|
302
|
-
<button class="btn btn-success
|
|
303
|
-
>+ Add New Mapping</button
|
|
304
|
-
>
|
|
417
|
+
<button class="btn btn-success" onclick={() => (isAdding = true)}>+ Add New Mapping</button>
|
|
305
418
|
{:else}
|
|
306
419
|
<div class="border border-[var(--border-color)] rounded p-4 bg-[var(--light-background)]">
|
|
307
420
|
<h3 class="text-lg font-medium mb-3">New Mapping</h3>
|
|
@@ -316,28 +429,55 @@ Please analyze the codebase and database, then generate the appropriate mappings
|
|
|
316
429
|
/>
|
|
317
430
|
</label>
|
|
318
431
|
<label class="block text-sm font-medium mb-1">
|
|
319
|
-
|
|
432
|
+
Mapping Type
|
|
320
433
|
<select
|
|
321
|
-
bind:value={
|
|
434
|
+
bind:value={newMappingType}
|
|
322
435
|
class="w-full px-3 py-2 bg-[var(--color-1)] border border-[var(--border-color)] rounded mt-1"
|
|
323
436
|
>
|
|
324
|
-
<option value="">
|
|
325
|
-
|
|
326
|
-
<option value={col}>{col}</option>
|
|
327
|
-
{/each}
|
|
437
|
+
<option value="document">Document</option>
|
|
438
|
+
<option value="url">URL</option>
|
|
328
439
|
</select>
|
|
329
440
|
</label>
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
441
|
+
{#if newMappingType === "document"}
|
|
442
|
+
<label class="block text-sm font-medium mb-1">
|
|
443
|
+
Target Collection
|
|
444
|
+
<select
|
|
445
|
+
bind:value={newTargetCollection}
|
|
446
|
+
class="w-full px-3 py-2 bg-[var(--color-1)] border border-[var(--border-color)] rounded mt-1"
|
|
447
|
+
>
|
|
448
|
+
<option value="">Select collection...</option>
|
|
449
|
+
{#each data.availableCollections as col (col)}
|
|
450
|
+
<option value={col}>{col}</option>
|
|
451
|
+
{/each}
|
|
452
|
+
</select>
|
|
453
|
+
</label>
|
|
454
|
+
<label class="block text-sm font-medium mb-1">
|
|
455
|
+
Target Field
|
|
456
|
+
<input
|
|
457
|
+
type="text"
|
|
458
|
+
bind:value={newTargetField}
|
|
459
|
+
placeholder="_id"
|
|
460
|
+
class="w-full px-3 py-2 bg-[var(--color-1)] border border-[var(--border-color)] rounded mt-1"
|
|
461
|
+
/>
|
|
462
|
+
</label>
|
|
463
|
+
{:else}
|
|
464
|
+
<label class="block text-sm font-medium mb-1">
|
|
465
|
+
URL Template
|
|
466
|
+
<input
|
|
467
|
+
type="text"
|
|
468
|
+
bind:value={newUrlTemplate}
|
|
469
|
+
placeholder="https://hf.co/datasets/{value}"
|
|
470
|
+
class="w-full px-3 py-2 bg-[var(--color-1)] border border-[var(--border-color)] rounded mt-1"
|
|
471
|
+
/>
|
|
472
|
+
</label>
|
|
473
|
+
<p class="text-xs" style="color: var(--text-secondary);">
|
|
474
|
+
Use <code class="px-1 bg-[var(--color-2)] rounded">{value}</code> as a placeholder for the field
|
|
475
|
+
value. Example: if the field is "abc/glue", and template is "https://hf.co/datasets/{value}",
|
|
476
|
+
the result will be "https://hf.co/datasets/abc/glue"
|
|
477
|
+
</p>
|
|
478
|
+
{/if}
|
|
339
479
|
<div class="flex gap-2">
|
|
340
|
-
<button class="btn btn-success
|
|
480
|
+
<button class="btn btn-success" onclick={addNewMapping}>Add</button>
|
|
341
481
|
<button class="btn btn-default hover:bg-[var(--color-3)]" onclick={cancelAdd}>Cancel</button>
|
|
342
482
|
</div>
|
|
343
483
|
</div>
|