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.
Files changed (300) hide show
  1. package/README.md +15 -0
  2. package/build/client/_app/immutable/assets/0.C_geP4pp.css +1 -0
  3. package/build/client/_app/immutable/assets/0.C_geP4pp.css.br +0 -0
  4. package/build/client/_app/immutable/assets/0.C_geP4pp.css.gz +0 -0
  5. package/build/client/_app/immutable/assets/10.Wc4MTSzM.css +1 -0
  6. package/build/client/_app/immutable/assets/10.Wc4MTSzM.css.br +0 -0
  7. package/build/client/_app/immutable/assets/10.Wc4MTSzM.css.gz +0 -0
  8. package/build/client/_app/immutable/assets/{Modal.zD4dMMyk.css → Modal.CZgFKXkP.css} +1 -1
  9. package/build/client/_app/immutable/assets/Modal.CZgFKXkP.css.br +0 -0
  10. package/build/client/_app/immutable/assets/Modal.CZgFKXkP.css.gz +0 -0
  11. package/build/client/_app/immutable/chunks/B27BoO92.js +1 -0
  12. package/build/client/_app/immutable/chunks/B27BoO92.js.br +0 -0
  13. package/build/client/_app/immutable/chunks/B27BoO92.js.gz +0 -0
  14. package/build/client/_app/immutable/chunks/{reNJcONQ.js → BLB7WU0x.js} +1 -1
  15. package/build/client/_app/immutable/chunks/BLB7WU0x.js.br +0 -0
  16. package/build/client/_app/immutable/chunks/{reNJcONQ.js.gz → BLB7WU0x.js.gz} +0 -0
  17. package/build/client/_app/immutable/chunks/{DvuSce6Q.js → BTDPx7wo.js} +1 -1
  18. package/build/client/_app/immutable/chunks/BTDPx7wo.js.br +0 -0
  19. package/build/client/_app/immutable/chunks/BTDPx7wo.js.gz +0 -0
  20. package/build/client/_app/immutable/chunks/{CQi92wY1.js → BV1jCwWf.js} +1 -1
  21. package/build/client/_app/immutable/chunks/BV1jCwWf.js.br +0 -0
  22. package/build/client/_app/immutable/chunks/BV1jCwWf.js.gz +0 -0
  23. package/build/client/_app/immutable/chunks/Bp2iD_PL.js +1 -0
  24. package/build/client/_app/immutable/chunks/Bp2iD_PL.js.br +0 -0
  25. package/build/client/_app/immutable/chunks/Bp2iD_PL.js.gz +0 -0
  26. package/build/client/_app/immutable/chunks/CItzKczS.js +1 -0
  27. package/build/client/_app/immutable/chunks/CItzKczS.js.br +0 -0
  28. package/build/client/_app/immutable/chunks/CItzKczS.js.gz +0 -0
  29. package/build/client/_app/immutable/chunks/{CjbrLxJm.js → Ce084HhL.js} +1 -1
  30. package/build/client/_app/immutable/chunks/Ce084HhL.js.br +0 -0
  31. package/build/client/_app/immutable/chunks/Ce084HhL.js.gz +0 -0
  32. package/build/client/_app/immutable/chunks/{DIw4Wyr4.js → CqFYS5AV.js} +1 -1
  33. package/build/client/_app/immutable/chunks/CqFYS5AV.js.br +0 -0
  34. package/build/client/_app/immutable/chunks/CqFYS5AV.js.gz +0 -0
  35. package/build/client/_app/immutable/chunks/{Cs_Y8eC2.js → DC13l09X.js} +6 -6
  36. package/build/client/_app/immutable/chunks/DC13l09X.js.br +0 -0
  37. package/build/client/_app/immutable/chunks/DC13l09X.js.gz +0 -0
  38. package/build/client/_app/immutable/chunks/{Dqjuk_9f.js → DXWJTsg6.js} +1 -1
  39. package/build/client/_app/immutable/chunks/DXWJTsg6.js.br +0 -0
  40. package/build/client/_app/immutable/chunks/DXWJTsg6.js.gz +0 -0
  41. package/build/client/_app/immutable/chunks/Dip-8jE5.js +1 -0
  42. package/build/client/_app/immutable/chunks/Dip-8jE5.js.br +0 -0
  43. package/build/client/_app/immutable/chunks/Dip-8jE5.js.gz +0 -0
  44. package/build/client/_app/immutable/chunks/Dr_XE7iR.js +2 -0
  45. package/build/client/_app/immutable/chunks/Dr_XE7iR.js.br +0 -0
  46. package/build/client/_app/immutable/chunks/Dr_XE7iR.js.gz +0 -0
  47. package/build/client/_app/immutable/chunks/DuLpG1zT.js +1 -0
  48. package/build/client/_app/immutable/chunks/DuLpG1zT.js.br +0 -0
  49. package/build/client/_app/immutable/chunks/DuLpG1zT.js.gz +0 -0
  50. package/build/client/_app/immutable/chunks/{Dn0_-jEe.js → DyfVYlRP.js} +1 -1
  51. package/build/client/_app/immutable/chunks/DyfVYlRP.js.br +0 -0
  52. package/build/client/_app/immutable/chunks/DyfVYlRP.js.gz +0 -0
  53. package/build/client/_app/immutable/chunks/{BXUq66wC.js → OTbFjzBQ.js} +1 -1
  54. package/build/client/_app/immutable/chunks/OTbFjzBQ.js.br +0 -0
  55. package/build/client/_app/immutable/chunks/OTbFjzBQ.js.gz +0 -0
  56. package/build/client/_app/immutable/chunks/{UJuWD2W4.js → TQ9V_LBO.js} +1 -1
  57. package/build/client/_app/immutable/chunks/TQ9V_LBO.js.br +0 -0
  58. package/build/client/_app/immutable/chunks/TQ9V_LBO.js.gz +0 -0
  59. package/build/client/_app/immutable/chunks/{B3q3gQD5.js → p4lxgeXU.js} +3 -3
  60. package/build/client/_app/immutable/chunks/p4lxgeXU.js.br +0 -0
  61. package/build/client/_app/immutable/chunks/p4lxgeXU.js.gz +0 -0
  62. package/build/client/_app/immutable/chunks/pXcSrKpr.js +1 -0
  63. package/build/client/_app/immutable/chunks/pXcSrKpr.js.br +0 -0
  64. package/build/client/_app/immutable/chunks/pXcSrKpr.js.gz +0 -0
  65. package/build/client/_app/immutable/chunks/xuMwtvm-.js +16 -0
  66. package/build/client/_app/immutable/chunks/xuMwtvm-.js.br +0 -0
  67. package/build/client/_app/immutable/chunks/xuMwtvm-.js.gz +0 -0
  68. package/build/client/_app/immutable/entry/app.B7JBkmJ2.js +2 -0
  69. package/build/client/_app/immutable/entry/app.B7JBkmJ2.js.br +0 -0
  70. package/build/client/_app/immutable/entry/app.B7JBkmJ2.js.gz +0 -0
  71. package/build/client/_app/immutable/entry/start.C35Eiz23.js +1 -0
  72. package/build/client/_app/immutable/entry/start.C35Eiz23.js.br +2 -0
  73. package/build/client/_app/immutable/entry/start.C35Eiz23.js.gz +0 -0
  74. package/build/client/_app/immutable/nodes/0.U3Wc2t11.js +1 -0
  75. package/build/client/_app/immutable/nodes/0.U3Wc2t11.js.br +0 -0
  76. package/build/client/_app/immutable/nodes/0.U3Wc2t11.js.gz +0 -0
  77. package/build/client/_app/immutable/nodes/1.YN6Ljj2X.js +1 -0
  78. package/build/client/_app/immutable/nodes/1.YN6Ljj2X.js.br +2 -0
  79. package/build/client/_app/immutable/nodes/1.YN6Ljj2X.js.gz +0 -0
  80. package/build/client/_app/immutable/nodes/10.E5c2rVVT.js +3 -0
  81. package/build/client/_app/immutable/nodes/10.E5c2rVVT.js.br +0 -0
  82. package/build/client/_app/immutable/nodes/10.E5c2rVVT.js.gz +0 -0
  83. package/build/client/_app/immutable/nodes/{11.CDi4i_Wb.js → 11.CwiIDBVl.js} +1 -1
  84. package/build/client/_app/immutable/nodes/11.CwiIDBVl.js.br +0 -0
  85. package/build/client/_app/immutable/nodes/11.CwiIDBVl.js.gz +0 -0
  86. package/build/client/_app/immutable/nodes/12.BF4KBraU.js +1 -0
  87. package/build/client/_app/immutable/nodes/12.BF4KBraU.js.br +0 -0
  88. package/build/client/_app/immutable/nodes/12.BF4KBraU.js.gz +0 -0
  89. package/build/client/_app/immutable/nodes/13.BNgciqug.js +65 -0
  90. package/build/client/_app/immutable/nodes/13.BNgciqug.js.br +0 -0
  91. package/build/client/_app/immutable/nodes/13.BNgciqug.js.gz +0 -0
  92. package/build/client/_app/immutable/nodes/{2.DqvBb3C7.js → 2.Byf6opOr.js} +1 -1
  93. package/build/client/_app/immutable/nodes/2.Byf6opOr.js.br +0 -0
  94. package/build/client/_app/immutable/nodes/2.Byf6opOr.js.gz +0 -0
  95. package/build/client/_app/immutable/nodes/{3.27swwcG4.js → 3.B3j0bAgy.js} +1 -1
  96. package/build/client/_app/immutable/nodes/3.B3j0bAgy.js.br +0 -0
  97. package/build/client/_app/immutable/nodes/3.B3j0bAgy.js.gz +0 -0
  98. package/build/client/_app/immutable/nodes/{4.CcholrFe.js → 4.6dtz57ii.js} +1 -1
  99. package/build/client/_app/immutable/nodes/4.6dtz57ii.js.br +0 -0
  100. package/build/client/_app/immutable/nodes/4.6dtz57ii.js.gz +0 -0
  101. package/build/client/_app/immutable/nodes/{5.CzudN9q-.js → 5.COHVaEDo.js} +1 -1
  102. package/build/client/_app/immutable/nodes/5.COHVaEDo.js.br +0 -0
  103. package/build/client/_app/immutable/nodes/5.COHVaEDo.js.gz +0 -0
  104. package/build/client/_app/immutable/nodes/{7.Bmco0vbT.js → 7.Cecp1nCH.js} +1 -1
  105. package/build/client/_app/immutable/nodes/7.Cecp1nCH.js.br +0 -0
  106. package/build/client/_app/immutable/nodes/7.Cecp1nCH.js.gz +0 -0
  107. package/build/client/_app/immutable/nodes/{8.DZLMUPtG.js → 8.DFk2Y9sL.js} +1 -1
  108. package/build/client/_app/immutable/nodes/8.DFk2Y9sL.js.br +0 -0
  109. package/build/client/_app/immutable/nodes/8.DFk2Y9sL.js.gz +0 -0
  110. package/build/client/_app/immutable/nodes/{9.CFkMGjd0.js → 9.W4l2xsEF.js} +1 -1
  111. package/build/client/_app/immutable/nodes/9.W4l2xsEF.js.br +0 -0
  112. package/build/client/_app/immutable/nodes/9.W4l2xsEF.js.gz +0 -0
  113. package/build/client/_app/version.json +1 -1
  114. package/build/client/_app/version.json.br +0 -0
  115. package/build/client/_app/version.json.gz +0 -0
  116. package/build/server/chunks/0-CuiS31Ys.js +22 -0
  117. package/build/server/chunks/{0-BwUdZ0Qi.js.map → 0-CuiS31Ys.js.map} +1 -1
  118. package/build/server/chunks/1-C9TxPuQ0.js +9 -0
  119. package/build/server/chunks/{1-CSzb5YUp.js.map → 1-C9TxPuQ0.js.map} +1 -1
  120. package/build/server/chunks/{10-CKou-YOv.js → 10-PX9d-jhv.js} +5 -5
  121. package/build/server/chunks/10-PX9d-jhv.js.map +1 -0
  122. package/build/server/chunks/{11-CFhS7tPn.js → 11-Bhv-UeEo.js} +4 -4
  123. package/build/server/chunks/{11-CFhS7tPn.js.map → 11-Bhv-UeEo.js.map} +1 -1
  124. package/build/server/chunks/{12-Cj8MHbvu.js → 12-BuNmW-Vp.js} +5 -5
  125. package/build/server/chunks/{12-Cj8MHbvu.js.map → 12-BuNmW-Vp.js.map} +1 -1
  126. package/build/server/chunks/{13-BuraZ7Jc.js → 13-CAI7Pyhf.js} +4 -4
  127. package/build/server/chunks/{13-BuraZ7Jc.js.map → 13-CAI7Pyhf.js.map} +1 -1
  128. package/build/server/chunks/{2-BheEgghx.js → 2-Bx656tbc.js} +2 -2
  129. package/build/server/chunks/{2-BheEgghx.js.map → 2-Bx656tbc.js.map} +1 -1
  130. package/build/server/chunks/{3-BwrTscBH.js → 3-B-zRiOJV.js} +2 -2
  131. package/build/server/chunks/{3-BwrTscBH.js.map → 3-B-zRiOJV.js.map} +1 -1
  132. package/build/server/chunks/{4-D28kbpdN.js → 4-BBCE4OIo.js} +2 -2
  133. package/build/server/chunks/{4-D28kbpdN.js.map → 4-BBCE4OIo.js.map} +1 -1
  134. package/build/server/chunks/{5--wY8V1OC.js → 5-D68X5smv.js} +2 -2
  135. package/build/server/chunks/{5--wY8V1OC.js.map → 5-D68X5smv.js.map} +1 -1
  136. package/build/server/chunks/{7-BwceH8Q7.js → 7-C8AZjmDc.js} +4 -4
  137. package/build/server/chunks/{7-BwceH8Q7.js.map → 7-C8AZjmDc.js.map} +1 -1
  138. package/build/server/chunks/{8-DyIhulUv.js → 8-CGRiuqYX.js} +5 -5
  139. package/build/server/chunks/{8-DyIhulUv.js.map → 8-CGRiuqYX.js.map} +1 -1
  140. package/build/server/chunks/{9-DGNm1JRG.js → 9-CBzIf4Vj.js} +5 -5
  141. package/build/server/chunks/{9-DGNm1JRG.js.map → 9-CBzIf4Vj.js.map} +1 -1
  142. package/build/server/chunks/{JsonValue-Cexm3jGT.js → JsonValue-EppVzWzE.js} +88 -36
  143. package/build/server/chunks/JsonValue-EppVzWzE.js.map +1 -0
  144. package/build/server/chunks/{Modal-BzZ9u6V6.js → Modal-eRpc5lqR.js} +4 -3
  145. package/build/server/chunks/Modal-eRpc5lqR.js.map +1 -0
  146. package/build/server/chunks/{Panel-BHGtM9Vw.js → Panel-HO9t9Spv.js} +2 -2
  147. package/build/server/chunks/{Panel-BHGtM9Vw.js.map → Panel-HO9t9Spv.js.map} +1 -1
  148. package/build/server/chunks/{PrettyJson-tOt0PqjF.js → PrettyJson-F3fqxkqU.js} +7 -6
  149. package/build/server/chunks/PrettyJson-F3fqxkqU.js.map +1 -0
  150. package/build/server/chunks/{Tooltip-DAE2mkm6.js → Tooltip-Dd-Bzogp.js} +2 -2
  151. package/build/server/chunks/{Tooltip-DAE2mkm6.js.map → Tooltip-Dd-Bzogp.js.map} +1 -1
  152. package/build/server/chunks/{TooltipTable-xo_OEG9c.js → TooltipTable-jHWezlEs.js} +3 -3
  153. package/build/server/chunks/{TooltipTable-xo_OEG9c.js.map → TooltipTable-jHWezlEs.js.map} +1 -1
  154. package/build/server/chunks/{_layout.svelte-Dji2JJ9X.js → _layout.svelte-CKGgUBvr.js} +9 -3
  155. package/build/server/chunks/_layout.svelte-CKGgUBvr.js.map +1 -0
  156. package/build/server/chunks/_page.svelte-BlmdSnTh.js +245 -0
  157. package/build/server/chunks/_page.svelte-BlmdSnTh.js.map +1 -0
  158. package/build/server/chunks/{_page.svelte-x1L5xjgQ.js → _page.svelte-ClZj6yzK.js} +7 -7
  159. package/build/server/chunks/{_page.svelte-x1L5xjgQ.js.map → _page.svelte-ClZj6yzK.js.map} +1 -1
  160. package/build/server/chunks/{_page.svelte-be8sxgGt.js → _page.svelte-D50SWEhd.js} +8 -8
  161. package/build/server/chunks/{_page.svelte-be8sxgGt.js.map → _page.svelte-D50SWEhd.js.map} +1 -1
  162. package/build/server/chunks/{_page.svelte-D-23v2Aa.js → _page.svelte-D8GSKYqN.js} +223 -12
  163. package/build/server/chunks/_page.svelte-D8GSKYqN.js.map +1 -0
  164. package/build/server/chunks/{_page.svelte-D9IvgJO5.js → _page.svelte-DBcsXxML.js} +8 -8
  165. package/build/server/chunks/{_page.svelte-D9IvgJO5.js.map → _page.svelte-DBcsXxML.js.map} +1 -1
  166. package/build/server/chunks/{_page.svelte-aT9hOnbL.js → _page.svelte-DFzKfImt.js} +8 -8
  167. package/build/server/chunks/{_page.svelte-aT9hOnbL.js.map → _page.svelte-DFzKfImt.js.map} +1 -1
  168. package/build/server/chunks/{_page.svelte-D5-pMskg.js → _page.svelte-ZYW4iSHn.js} +8 -8
  169. package/build/server/chunks/{_page.svelte-D5-pMskg.js.map → _page.svelte-ZYW4iSHn.js.map} +1 -1
  170. package/build/server/chunks/{index2-eSFyMQpS.js → index2-DBFlGzWV.js} +2 -2
  171. package/build/server/chunks/{index2-eSFyMQpS.js.map → index2-DBFlGzWV.js.map} +1 -1
  172. package/build/server/chunks/{mongo-BHk5yAj9.js → mongo-Ndoh6fs5.js} +21 -7
  173. package/build/server/chunks/mongo-Ndoh6fs5.js.map +1 -0
  174. package/build/server/chunks/{remote-xxtqbu-ETLGkdRu.js → remote-xxtqbu-fbBqzvFu.js} +3 -3
  175. package/build/server/chunks/remote-xxtqbu-fbBqzvFu.js.map +1 -0
  176. package/build/server/chunks/{servers.remote-CGies_Na.js → servers.remote-B1eorl4A.js} +163 -12
  177. package/build/server/chunks/servers.remote-B1eorl4A.js.map +1 -0
  178. package/build/server/index.js +2 -2
  179. package/build/server/index.js.map +1 -1
  180. package/build/server/manifest.js +15 -15
  181. package/build/server/manifest.js.map +1 -1
  182. package/package.json +1 -1
  183. package/src/api/servers.remote.ts +196 -10
  184. package/src/app.css +3 -6
  185. package/src/lib/components/ExplainPanel.svelte +273 -0
  186. package/src/lib/components/JsonValue.svelte +51 -6
  187. package/src/lib/components/Modal.svelte +7 -2
  188. package/src/lib/components/Notifications.svelte +3 -15
  189. package/src/lib/components/PrettyJson.svelte +1 -1
  190. package/src/lib/components/SearchBox.svelte +160 -5
  191. package/src/lib/components/TimeRangeStats.svelte +269 -0
  192. package/src/lib/icons/IconClose.svelte +21 -0
  193. package/src/lib/icons/IconExternalLink.svelte +22 -0
  194. package/src/lib/server/mongo.ts +31 -6
  195. package/src/lib/types.ts +16 -5
  196. package/src/routes/servers/[server]/databases/[database]/collections/[collection]/documents/+page.svelte +49 -1
  197. package/src/routes/servers/[server]/databases/[database]/collections/[collection]/mappings/+page.svelte +219 -79
  198. package/build/client/_app/immutable/assets/0.CEIWAdGZ.css +0 -1
  199. package/build/client/_app/immutable/assets/0.CEIWAdGZ.css.br +0 -0
  200. package/build/client/_app/immutable/assets/0.CEIWAdGZ.css.gz +0 -0
  201. package/build/client/_app/immutable/assets/10.BrydhPds.css +0 -1
  202. package/build/client/_app/immutable/assets/10.BrydhPds.css.br +0 -0
  203. package/build/client/_app/immutable/assets/10.BrydhPds.css.gz +0 -0
  204. package/build/client/_app/immutable/assets/Modal.zD4dMMyk.css.br +0 -0
  205. package/build/client/_app/immutable/assets/Modal.zD4dMMyk.css.gz +0 -0
  206. package/build/client/_app/immutable/chunks/0oUK0vJa.js +0 -1
  207. package/build/client/_app/immutable/chunks/0oUK0vJa.js.br +0 -0
  208. package/build/client/_app/immutable/chunks/0oUK0vJa.js.gz +0 -0
  209. package/build/client/_app/immutable/chunks/B3q3gQD5.js.br +0 -0
  210. package/build/client/_app/immutable/chunks/B3q3gQD5.js.gz +0 -0
  211. package/build/client/_app/immutable/chunks/BGXqurs_.js +0 -1
  212. package/build/client/_app/immutable/chunks/BGXqurs_.js.br +0 -0
  213. package/build/client/_app/immutable/chunks/BGXqurs_.js.gz +0 -0
  214. package/build/client/_app/immutable/chunks/BPbCnJEo.js +0 -1
  215. package/build/client/_app/immutable/chunks/BPbCnJEo.js.br +0 -0
  216. package/build/client/_app/immutable/chunks/BPbCnJEo.js.gz +0 -0
  217. package/build/client/_app/immutable/chunks/BXUq66wC.js.br +0 -0
  218. package/build/client/_app/immutable/chunks/BXUq66wC.js.gz +0 -0
  219. package/build/client/_app/immutable/chunks/BxoAxRg6.js +0 -1
  220. package/build/client/_app/immutable/chunks/BxoAxRg6.js.br +0 -0
  221. package/build/client/_app/immutable/chunks/BxoAxRg6.js.gz +0 -0
  222. package/build/client/_app/immutable/chunks/ByCRZ7zS.js +0 -2
  223. package/build/client/_app/immutable/chunks/ByCRZ7zS.js.br +0 -0
  224. package/build/client/_app/immutable/chunks/ByCRZ7zS.js.gz +0 -0
  225. package/build/client/_app/immutable/chunks/BybrNGke.js +0 -16
  226. package/build/client/_app/immutable/chunks/BybrNGke.js.br +0 -0
  227. package/build/client/_app/immutable/chunks/BybrNGke.js.gz +0 -0
  228. package/build/client/_app/immutable/chunks/CQi92wY1.js.br +0 -0
  229. package/build/client/_app/immutable/chunks/CQi92wY1.js.gz +0 -0
  230. package/build/client/_app/immutable/chunks/CjbrLxJm.js.br +0 -0
  231. package/build/client/_app/immutable/chunks/CjbrLxJm.js.gz +0 -0
  232. package/build/client/_app/immutable/chunks/Cs_Y8eC2.js.br +0 -0
  233. package/build/client/_app/immutable/chunks/Cs_Y8eC2.js.gz +0 -0
  234. package/build/client/_app/immutable/chunks/DIw4Wyr4.js.br +0 -0
  235. package/build/client/_app/immutable/chunks/DIw4Wyr4.js.gz +0 -0
  236. package/build/client/_app/immutable/chunks/Dn0_-jEe.js.br +0 -0
  237. package/build/client/_app/immutable/chunks/Dn0_-jEe.js.gz +0 -0
  238. package/build/client/_app/immutable/chunks/Dqjuk_9f.js.br +0 -0
  239. package/build/client/_app/immutable/chunks/Dqjuk_9f.js.gz +0 -0
  240. package/build/client/_app/immutable/chunks/DvuSce6Q.js.br +0 -0
  241. package/build/client/_app/immutable/chunks/DvuSce6Q.js.gz +0 -0
  242. package/build/client/_app/immutable/chunks/UJuWD2W4.js.br +0 -0
  243. package/build/client/_app/immutable/chunks/UJuWD2W4.js.gz +0 -0
  244. package/build/client/_app/immutable/chunks/XRLS4Bbp.js +0 -1
  245. package/build/client/_app/immutable/chunks/XRLS4Bbp.js.br +0 -0
  246. package/build/client/_app/immutable/chunks/XRLS4Bbp.js.gz +0 -0
  247. package/build/client/_app/immutable/chunks/_kKBJjiB.js +0 -1
  248. package/build/client/_app/immutable/chunks/_kKBJjiB.js.br +0 -0
  249. package/build/client/_app/immutable/chunks/_kKBJjiB.js.gz +0 -0
  250. package/build/client/_app/immutable/chunks/reNJcONQ.js.br +0 -0
  251. package/build/client/_app/immutable/entry/app.BPKl8oaJ.js +0 -2
  252. package/build/client/_app/immutable/entry/app.BPKl8oaJ.js.br +0 -0
  253. package/build/client/_app/immutable/entry/app.BPKl8oaJ.js.gz +0 -0
  254. package/build/client/_app/immutable/entry/start.DWHdYJ-L.js +0 -1
  255. package/build/client/_app/immutable/entry/start.DWHdYJ-L.js.br +0 -2
  256. package/build/client/_app/immutable/entry/start.DWHdYJ-L.js.gz +0 -0
  257. package/build/client/_app/immutable/nodes/0.B2NjMPUg.js +0 -1
  258. package/build/client/_app/immutable/nodes/0.B2NjMPUg.js.br +0 -0
  259. package/build/client/_app/immutable/nodes/0.B2NjMPUg.js.gz +0 -0
  260. package/build/client/_app/immutable/nodes/1.DIJdjioz.js +0 -1
  261. package/build/client/_app/immutable/nodes/1.DIJdjioz.js.br +0 -1
  262. package/build/client/_app/immutable/nodes/1.DIJdjioz.js.gz +0 -0
  263. package/build/client/_app/immutable/nodes/10.DBt9LqZ5.js +0 -3
  264. package/build/client/_app/immutable/nodes/10.DBt9LqZ5.js.br +0 -0
  265. package/build/client/_app/immutable/nodes/10.DBt9LqZ5.js.gz +0 -0
  266. package/build/client/_app/immutable/nodes/11.CDi4i_Wb.js.br +0 -0
  267. package/build/client/_app/immutable/nodes/11.CDi4i_Wb.js.gz +0 -0
  268. package/build/client/_app/immutable/nodes/12.CbEEqmwu.js +0 -1
  269. package/build/client/_app/immutable/nodes/12.CbEEqmwu.js.br +0 -0
  270. package/build/client/_app/immutable/nodes/12.CbEEqmwu.js.gz +0 -0
  271. package/build/client/_app/immutable/nodes/13.DuXWHwDt.js +0 -66
  272. package/build/client/_app/immutable/nodes/13.DuXWHwDt.js.br +0 -0
  273. package/build/client/_app/immutable/nodes/13.DuXWHwDt.js.gz +0 -0
  274. package/build/client/_app/immutable/nodes/2.DqvBb3C7.js.br +0 -0
  275. package/build/client/_app/immutable/nodes/2.DqvBb3C7.js.gz +0 -0
  276. package/build/client/_app/immutable/nodes/3.27swwcG4.js.br +0 -0
  277. package/build/client/_app/immutable/nodes/3.27swwcG4.js.gz +0 -0
  278. package/build/client/_app/immutable/nodes/4.CcholrFe.js.br +0 -0
  279. package/build/client/_app/immutable/nodes/4.CcholrFe.js.gz +0 -0
  280. package/build/client/_app/immutable/nodes/5.CzudN9q-.js.br +0 -0
  281. package/build/client/_app/immutable/nodes/5.CzudN9q-.js.gz +0 -0
  282. package/build/client/_app/immutable/nodes/7.Bmco0vbT.js.br +0 -0
  283. package/build/client/_app/immutable/nodes/7.Bmco0vbT.js.gz +0 -0
  284. package/build/client/_app/immutable/nodes/8.DZLMUPtG.js.br +0 -0
  285. package/build/client/_app/immutable/nodes/8.DZLMUPtG.js.gz +0 -0
  286. package/build/client/_app/immutable/nodes/9.CFkMGjd0.js.br +0 -0
  287. package/build/client/_app/immutable/nodes/9.CFkMGjd0.js.gz +0 -0
  288. package/build/server/chunks/0-BwUdZ0Qi.js +0 -22
  289. package/build/server/chunks/1-CSzb5YUp.js +0 -9
  290. package/build/server/chunks/10-CKou-YOv.js.map +0 -1
  291. package/build/server/chunks/JsonValue-Cexm3jGT.js.map +0 -1
  292. package/build/server/chunks/Modal-BzZ9u6V6.js.map +0 -1
  293. package/build/server/chunks/PrettyJson-tOt0PqjF.js.map +0 -1
  294. package/build/server/chunks/_layout.svelte-Dji2JJ9X.js.map +0 -1
  295. package/build/server/chunks/_page.svelte-CJ5HzoD0.js +0 -203
  296. package/build/server/chunks/_page.svelte-CJ5HzoD0.js.map +0 -1
  297. package/build/server/chunks/_page.svelte-D-23v2Aa.js.map +0 -1
  298. package/build/server/chunks/mongo-BHk5yAj9.js.map +0 -1
  299. package/build/server/chunks/remote-xxtqbu-ETLGkdRu.js.map +0 -1
  300. 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>
@@ -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 which collection and field to lookup
103
+ * A single mapping target - defines either a collection lookup or URL template
104
104
  */
105
- export interface MappingTarget {
106
- collection: string;
107
- on: string;
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 bind:params bind:editMode readonly={data.readOnly} />
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
- entry.targets.push({ collection: "", on: "_id" });
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
- if (!newTargetCollection.trim()) {
112
- notificationStore.notifyError("Target collection is required");
113
- return;
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: [{ collection: newTargetCollection.trim(), on: newTargetField.trim() || "_id" }],
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) => t.collection.trim() && t.on.trim());
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 hover:bg-[var(--button-success-l)]" onclick={saveMappings}
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 and navigation on foreign key fields. This
178
- will be stored in the <code class="px-1 bg-[var(--light-background)] rounded">mongoku.mappings</code> collection
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">Example</summary>
189
- <div class="mt-2">
190
- <div class="mb-1">
191
- Document in collection <code class="px-1 bg-[var(--light-background)] rounded">posts</code>:
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
+ &#123; _id: "post1", title: "Hello", authorId: "user123", comments: [&#123;authorId: "user456", text:
242
+ "Nice!"&#125;] &#125;
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
- <code class="block px-2 py-1 bg-[var(--light-background)] rounded text-xs mb-2">
194
- &#123; _id: "post1", title: "Hello", authorId: "user123", comments: [&#123;authorId: "user456", text:
195
- "Nice!"&#125;] &#125;
196
- </code>
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
- <div>
205
- Mapping 2: Field path <code class="px-1 bg-[var(--light-background)] rounded">comments.authorId</code>,
206
- target collection <code class="px-1 bg-[var(--light-background)] rounded">users</code>, target field
207
- <code class="px-1 bg-[var(--light-background)] rounded">_id</code>
264
+ <code class="block px-2 py-1 bg-[var(--light-background)] rounded text-xs mb-2">
265
+ &#123; _id: "abc/glue", name: "GLUE Benchmark", ... &#125;
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/&#123;value&#125;</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
- Target Collection
313
+ Type
247
314
  <select
248
- bind:value={target.collection}
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="">Select collection...</option>
253
- {#each data.availableCollections as col (col)}
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
- <div class="flex-1">
260
- <label class="block text-xs mb-1">
261
- Target Field
262
- <input
263
- type="text"
264
- bind:value={target.on}
265
- placeholder="_id"
266
- class="w-full px-3 py-2 bg-[var(--color-1)] border border-[var(--border-color)] rounded text-sm mt-1"
267
- disabled={data.readOnly}
268
- />
269
- </label>
270
- </div>
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 &#123;value&#125; for interpolation)
368
+ <input
369
+ type="text"
370
+ bind:value={urlTarget.template}
371
+ placeholder="https://example.com/&#123;value&#125;"
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
- <button
286
- class="btn btn-outline-light btn-sm mt-2 ml-4 hover:bg-[var(--color-3)]"
287
- onclick={() => addTarget(entry)}
288
- >
289
- + Add Alternative Target
290
- </button>
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 hover:bg-[var(--button-success-l)]" onclick={() => (isAdding = true)}
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
- Target Collection
432
+ Mapping Type
320
433
  <select
321
- bind:value={newTargetCollection}
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="">Select collection...</option>
325
- {#each data.availableCollections as col (col)}
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
- <label class="block text-sm font-medium mb-1">
331
- Target Field
332
- <input
333
- type="text"
334
- bind:value={newTargetField}
335
- placeholder="_id"
336
- class="w-full px-3 py-2 bg-[var(--color-1)] border border-[var(--border-color)] rounded mt-1"
337
- />
338
- </label>
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/&#123;value&#125;"
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">&#123;value&#125;</code> as a placeholder for the field
475
+ value. Example: if the field is "abc/glue", and template is "https://hf.co/datasets/&#123;value&#125;",
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 hover:bg-[var(--button-success-l)]" onclick={addNewMapping}>Add</button>
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>