mongoku 2.0.4 → 2.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (426) hide show
  1. package/README.md +18 -4
  2. package/build/client/_app/immutable/assets/0.egX7ddQL.css +1 -0
  3. package/build/client/_app/immutable/assets/0.egX7ddQL.css.br +0 -0
  4. package/build/client/_app/immutable/assets/0.egX7ddQL.css.gz +0 -0
  5. package/build/client/_app/immutable/assets/10.59aTjJn9.css +1 -0
  6. package/build/client/_app/immutable/assets/10.59aTjJn9.css.br +0 -0
  7. package/build/client/_app/immutable/assets/10.59aTjJn9.css.gz +0 -0
  8. package/build/client/_app/immutable/assets/11.CEtFGlZU.css +1 -0
  9. package/build/client/_app/immutable/assets/11.CEtFGlZU.css.br +1 -0
  10. package/build/client/_app/immutable/assets/11.CEtFGlZU.css.gz +0 -0
  11. package/build/client/_app/immutable/assets/12.BdCOhvz0.css +1 -0
  12. package/build/client/_app/immutable/assets/12.BdCOhvz0.css.br +0 -0
  13. package/build/client/_app/immutable/assets/12.BdCOhvz0.css.gz +0 -0
  14. package/build/client/_app/immutable/assets/JsonValue.BEbzuWqZ.css +1 -0
  15. package/build/client/_app/immutable/assets/JsonValue.BEbzuWqZ.css.br +0 -0
  16. package/build/client/_app/immutable/assets/JsonValue.BEbzuWqZ.css.gz +0 -0
  17. package/build/client/_app/immutable/assets/Modal.DIIFkbGB.css +1 -0
  18. package/build/client/_app/immutable/assets/Modal.DIIFkbGB.css.br +0 -0
  19. package/build/client/_app/immutable/assets/Modal.DIIFkbGB.css.gz +0 -0
  20. package/build/client/_app/immutable/assets/Panel.B3aWupye.css +1 -0
  21. package/build/client/_app/immutable/assets/Panel.B3aWupye.css.br +0 -0
  22. package/build/client/_app/immutable/assets/Panel.B3aWupye.css.gz +0 -0
  23. package/build/client/_app/immutable/chunks/3iRu_dUj.js +2 -0
  24. package/build/client/_app/immutable/chunks/3iRu_dUj.js.br +0 -0
  25. package/build/client/_app/immutable/chunks/3iRu_dUj.js.gz +0 -0
  26. package/build/client/_app/immutable/chunks/{ChWB6xnu.js → 4l_AWZos.js} +1 -1
  27. package/build/client/_app/immutable/chunks/4l_AWZos.js.br +0 -0
  28. package/build/client/_app/immutable/chunks/4l_AWZos.js.gz +0 -0
  29. package/build/client/_app/immutable/chunks/5nAxkTTP.js +1 -0
  30. package/build/client/_app/immutable/chunks/5nAxkTTP.js.br +5 -0
  31. package/build/client/_app/immutable/chunks/5nAxkTTP.js.gz +0 -0
  32. package/build/client/_app/immutable/chunks/BBg-V8FE.js +1 -0
  33. package/build/client/_app/immutable/chunks/BBg-V8FE.js.br +0 -0
  34. package/build/client/_app/immutable/chunks/BBg-V8FE.js.gz +0 -0
  35. package/build/client/_app/immutable/chunks/BE8UzJuY.js +1 -0
  36. package/build/client/_app/immutable/chunks/BE8UzJuY.js.br +0 -0
  37. package/build/client/_app/immutable/chunks/BE8UzJuY.js.gz +0 -0
  38. package/build/client/_app/immutable/chunks/BUNgwIS0.js +1 -0
  39. package/build/client/_app/immutable/chunks/BUNgwIS0.js.br +0 -0
  40. package/build/client/_app/immutable/chunks/BUNgwIS0.js.gz +0 -0
  41. package/build/client/_app/immutable/chunks/BjzB4NFq.js +1 -0
  42. package/build/client/_app/immutable/chunks/BjzB4NFq.js.br +0 -0
  43. package/build/client/_app/immutable/chunks/BjzB4NFq.js.gz +0 -0
  44. package/build/client/_app/immutable/chunks/BtCOrwSt.js +1 -0
  45. package/build/client/_app/immutable/chunks/BtCOrwSt.js.br +0 -0
  46. package/build/client/_app/immutable/chunks/BtCOrwSt.js.gz +0 -0
  47. package/build/client/_app/immutable/chunks/BvKY81hz.js +1 -0
  48. package/build/client/_app/immutable/chunks/BvKY81hz.js.br +0 -0
  49. package/build/client/_app/immutable/chunks/BvKY81hz.js.gz +0 -0
  50. package/build/client/_app/immutable/chunks/{DQkpHJGc.js → C0PCwpqt.js} +1 -1
  51. package/build/client/_app/immutable/chunks/C0PCwpqt.js.br +0 -0
  52. package/build/client/_app/immutable/chunks/C0PCwpqt.js.gz +0 -0
  53. package/build/client/_app/immutable/chunks/C82Rp5eQ.js +1 -0
  54. package/build/client/_app/immutable/chunks/C82Rp5eQ.js.br +0 -0
  55. package/build/client/_app/immutable/chunks/C82Rp5eQ.js.gz +0 -0
  56. package/build/client/_app/immutable/chunks/CEvYYWlm.js +2 -0
  57. package/build/client/_app/immutable/chunks/CEvYYWlm.js.br +0 -0
  58. package/build/client/_app/immutable/chunks/CEvYYWlm.js.gz +0 -0
  59. package/build/client/_app/immutable/chunks/CT5SFbzp.js +1 -0
  60. package/build/client/_app/immutable/chunks/CT5SFbzp.js.br +0 -0
  61. package/build/client/_app/immutable/chunks/CT5SFbzp.js.gz +0 -0
  62. package/build/client/_app/immutable/chunks/CcyPStn-.js +1 -0
  63. package/build/client/_app/immutable/chunks/CcyPStn-.js.br +0 -0
  64. package/build/client/_app/immutable/chunks/CcyPStn-.js.gz +0 -0
  65. package/build/client/_app/immutable/chunks/Cx2cA4gg.js +1 -0
  66. package/build/client/_app/immutable/chunks/Cx2cA4gg.js.br +0 -0
  67. package/build/client/_app/immutable/chunks/Cx2cA4gg.js.gz +0 -0
  68. package/build/client/_app/immutable/chunks/D5ccpaXt.js +1 -0
  69. package/build/client/_app/immutable/chunks/D5ccpaXt.js.br +0 -0
  70. package/build/client/_app/immutable/chunks/D5ccpaXt.js.gz +0 -0
  71. package/build/client/_app/immutable/chunks/D64wQeYi.js +1 -0
  72. package/build/client/_app/immutable/chunks/D64wQeYi.js.br +0 -0
  73. package/build/client/_app/immutable/chunks/D64wQeYi.js.gz +0 -0
  74. package/build/client/_app/immutable/chunks/D7E46CWw.js +1 -0
  75. package/build/client/_app/immutable/chunks/D7E46CWw.js.br +0 -0
  76. package/build/client/_app/immutable/chunks/D7E46CWw.js.gz +0 -0
  77. package/build/client/_app/immutable/chunks/DR9xdhsg.js +1 -0
  78. package/build/client/_app/immutable/chunks/DR9xdhsg.js.br +0 -0
  79. package/build/client/_app/immutable/chunks/DR9xdhsg.js.gz +0 -0
  80. package/build/client/_app/immutable/chunks/DVJuGan7.js +1 -0
  81. package/build/client/_app/immutable/chunks/DVJuGan7.js.br +0 -0
  82. package/build/client/_app/immutable/chunks/DVJuGan7.js.gz +0 -0
  83. package/build/client/_app/immutable/chunks/Dx86XS0G.js +1 -0
  84. package/build/client/_app/immutable/chunks/Dx86XS0G.js.br +4 -0
  85. package/build/client/_app/immutable/chunks/Dx86XS0G.js.gz +0 -0
  86. package/build/client/_app/immutable/chunks/lkkUcQuO.js +29 -0
  87. package/build/client/_app/immutable/chunks/lkkUcQuO.js.br +0 -0
  88. package/build/client/_app/immutable/chunks/lkkUcQuO.js.gz +0 -0
  89. package/build/client/_app/immutable/chunks/nVJvgG3c.js +4 -0
  90. package/build/client/_app/immutable/chunks/nVJvgG3c.js.br +0 -0
  91. package/build/client/_app/immutable/chunks/nVJvgG3c.js.gz +0 -0
  92. package/build/client/_app/immutable/entry/app.g5qLQ5x2.js +2 -0
  93. package/build/client/_app/immutable/entry/app.g5qLQ5x2.js.br +0 -0
  94. package/build/client/_app/immutable/entry/app.g5qLQ5x2.js.gz +0 -0
  95. package/build/client/_app/immutable/entry/start.C1uqw3sp.js +1 -0
  96. package/build/client/_app/immutable/entry/start.C1uqw3sp.js.br +2 -0
  97. package/build/client/_app/immutable/entry/start.C1uqw3sp.js.gz +0 -0
  98. package/build/client/_app/immutable/nodes/0.CD9yR-49.js +5 -0
  99. package/build/client/_app/immutable/nodes/0.CD9yR-49.js.br +0 -0
  100. package/build/client/_app/immutable/nodes/0.CD9yR-49.js.gz +0 -0
  101. package/build/client/_app/immutable/nodes/1.DztuiMqq.js +1 -0
  102. package/build/client/_app/immutable/nodes/1.DztuiMqq.js.br +0 -0
  103. package/build/client/_app/immutable/nodes/1.DztuiMqq.js.gz +0 -0
  104. package/build/client/_app/immutable/nodes/10.CWMFKPcE.js +2 -0
  105. package/build/client/_app/immutable/nodes/10.CWMFKPcE.js.br +0 -0
  106. package/build/client/_app/immutable/nodes/10.CWMFKPcE.js.gz +0 -0
  107. package/build/client/_app/immutable/nodes/11.-Y7Cu3Uv.js +1 -0
  108. package/build/client/_app/immutable/nodes/11.-Y7Cu3Uv.js.br +0 -0
  109. package/build/client/_app/immutable/nodes/11.-Y7Cu3Uv.js.gz +0 -0
  110. package/build/client/_app/immutable/nodes/12.wxif1TtN.js +1 -0
  111. package/build/client/_app/immutable/nodes/12.wxif1TtN.js.br +0 -0
  112. package/build/client/_app/immutable/nodes/12.wxif1TtN.js.gz +0 -0
  113. package/build/client/_app/immutable/nodes/13.CpyTaRSN.js +66 -0
  114. package/build/client/_app/immutable/nodes/13.CpyTaRSN.js.br +0 -0
  115. package/build/client/_app/immutable/nodes/13.CpyTaRSN.js.gz +0 -0
  116. package/build/client/_app/immutable/nodes/2.DwwrLLW4.js +1 -0
  117. package/build/client/_app/immutable/nodes/2.DwwrLLW4.js.br +1 -0
  118. package/build/client/_app/immutable/nodes/2.DwwrLLW4.js.gz +0 -0
  119. package/build/client/_app/immutable/nodes/3.t20GootO.js +1 -0
  120. package/build/client/_app/immutable/nodes/3.t20GootO.js.br +0 -0
  121. package/build/client/_app/immutable/nodes/3.t20GootO.js.gz +0 -0
  122. package/build/client/_app/immutable/nodes/4.CXHjkPtf.js +1 -0
  123. package/build/client/_app/immutable/nodes/4.CXHjkPtf.js.br +0 -0
  124. package/build/client/_app/immutable/nodes/4.CXHjkPtf.js.gz +0 -0
  125. package/build/client/_app/immutable/nodes/5.C9tcr5B0.js +1 -0
  126. package/build/client/_app/immutable/nodes/5.C9tcr5B0.js.br +0 -0
  127. package/build/client/_app/immutable/nodes/5.C9tcr5B0.js.gz +0 -0
  128. package/build/client/_app/immutable/nodes/7.DoT-dNUk.js +1 -0
  129. package/build/client/_app/immutable/nodes/7.DoT-dNUk.js.br +0 -0
  130. package/build/client/_app/immutable/nodes/7.DoT-dNUk.js.gz +0 -0
  131. package/build/client/_app/immutable/nodes/8.BFPkGTSl.js +1 -0
  132. package/build/client/_app/immutable/nodes/8.BFPkGTSl.js.br +0 -0
  133. package/build/client/_app/immutable/nodes/8.BFPkGTSl.js.gz +0 -0
  134. package/build/client/_app/immutable/nodes/9.Bk397TaK.js +2 -0
  135. package/build/client/_app/immutable/nodes/9.Bk397TaK.js.br +0 -0
  136. package/build/client/_app/immutable/nodes/9.Bk397TaK.js.gz +0 -0
  137. package/build/client/_app/version.json +1 -1
  138. package/build/client/_app/version.json.br +0 -0
  139. package/build/client/_app/version.json.gz +0 -0
  140. package/build/handler.js +14 -0
  141. package/build/server/chunks/{0-Cb5ytlMI.js → 0-hDOo8HzQ.js} +7 -6
  142. package/build/server/chunks/0-hDOo8HzQ.js.map +1 -0
  143. package/build/server/chunks/1-Dsw_dVjH.js +9 -0
  144. package/build/server/chunks/1-Dsw_dVjH.js.map +1 -0
  145. package/build/server/chunks/10-Xy0rxLNm.js +213 -0
  146. package/build/server/chunks/10-Xy0rxLNm.js.map +1 -0
  147. package/build/server/chunks/11-DBYsQ3ww.js +42 -0
  148. package/build/server/chunks/11-DBYsQ3ww.js.map +1 -0
  149. package/build/server/chunks/12-D4aSEhYN.js +102 -0
  150. package/build/server/chunks/12-D4aSEhYN.js.map +1 -0
  151. package/build/server/chunks/13-CNu_Hz8r.js +52 -0
  152. package/build/server/chunks/13-CNu_Hz8r.js.map +1 -0
  153. package/build/server/chunks/2-ClkERMhY.js +24 -0
  154. package/build/server/chunks/2-ClkERMhY.js.map +1 -0
  155. package/build/server/chunks/3-CTpqmxdo.js +25 -0
  156. package/build/server/chunks/3-CTpqmxdo.js.map +1 -0
  157. package/build/server/chunks/4-CUH4fZn8.js +25 -0
  158. package/build/server/chunks/4-CUH4fZn8.js.map +1 -0
  159. package/build/server/chunks/5-BSEdxfut.js +25 -0
  160. package/build/server/chunks/5-BSEdxfut.js.map +1 -0
  161. package/build/server/chunks/{2-B39zPvzn.js → 6-ifXBeMPA.js} +2 -2
  162. package/build/server/chunks/{2-B39zPvzn.js.map → 6-ifXBeMPA.js.map} +1 -1
  163. package/build/server/chunks/7-CJJMTAtJ.js +82 -0
  164. package/build/server/chunks/7-CJJMTAtJ.js.map +1 -0
  165. package/build/server/chunks/{4-DzHoLo__.js → 8-jBgxYwFg.js} +19 -10
  166. package/build/server/chunks/8-jBgxYwFg.js.map +1 -0
  167. package/build/server/chunks/{5-CCWbCDpk.js → 9-U8SAVx43.js} +7 -8
  168. package/build/server/chunks/9-U8SAVx43.js.map +1 -0
  169. package/build/server/chunks/JsonValue-B5gcBFcA.js +290 -0
  170. package/build/server/chunks/JsonValue-B5gcBFcA.js.map +1 -0
  171. package/build/server/chunks/Modal-zVnoAfFx.js +36 -0
  172. package/build/server/chunks/Modal-zVnoAfFx.js.map +1 -0
  173. package/build/server/chunks/{Panel-Bz0b85EW.js → Panel-yg5YKL4d.js} +4 -3
  174. package/build/server/chunks/Panel-yg5YKL4d.js.map +1 -0
  175. package/build/server/chunks/PrettyJson-mXYQacEL.js +137 -0
  176. package/build/server/chunks/PrettyJson-mXYQacEL.js.map +1 -0
  177. package/build/server/chunks/Tooltip-DflJLumT.js +38 -0
  178. package/build/server/chunks/Tooltip-DflJLumT.js.map +1 -0
  179. package/build/server/chunks/TooltipTable-BPMzcmqQ.js +60 -0
  180. package/build/server/chunks/TooltipTable-BPMzcmqQ.js.map +1 -0
  181. package/build/server/chunks/_layout.svelte-DMm1Ill8.js +168 -0
  182. package/build/server/chunks/_layout.svelte-DMm1Ill8.js.map +1 -0
  183. package/build/server/chunks/_page.svelte-B-dLNs2Q.js +199 -0
  184. package/build/server/chunks/_page.svelte-B-dLNs2Q.js.map +1 -0
  185. package/build/server/chunks/{_page.svelte-FLzHOuyK.js → _page.svelte-BBpDrOEz.js} +40 -22
  186. package/build/server/chunks/_page.svelte-BBpDrOEz.js.map +1 -0
  187. package/build/server/chunks/_page.svelte-C9OCv4Hv.js +204 -0
  188. package/build/server/chunks/_page.svelte-C9OCv4Hv.js.map +1 -0
  189. package/build/server/chunks/{_page.svelte-w9cxGvUf.js → _page.svelte-CvWJ35oO.js} +33 -13
  190. package/build/server/chunks/_page.svelte-CvWJ35oO.js.map +1 -0
  191. package/build/server/chunks/_page.svelte-DYHUokXG.js +297 -0
  192. package/build/server/chunks/_page.svelte-DYHUokXG.js.map +1 -0
  193. package/build/server/chunks/{_page.svelte-FIp-IsOo.js → _page.svelte-Ds1-yUh2.js} +64 -13
  194. package/build/server/chunks/_page.svelte-Ds1-yUh2.js.map +1 -0
  195. package/build/server/chunks/{_page.svelte-jxFKbZdN.js → _page.svelte-DzPMpozq.js} +9 -6
  196. package/build/server/chunks/_page.svelte-DzPMpozq.js.map +1 -0
  197. package/build/server/chunks/_server.ts-06lGoPp8.js +8 -0
  198. package/build/server/chunks/_server.ts-06lGoPp8.js.map +1 -0
  199. package/build/server/chunks/async-lVJA8xJZ.js +9 -0
  200. package/build/server/chunks/async-lVJA8xJZ.js.map +1 -0
  201. package/build/server/chunks/client-BFlyU7ZU.js +7 -0
  202. package/build/server/chunks/{client-bj7sePQc.js.map → client-BFlyU7ZU.js.map} +1 -1
  203. package/build/server/chunks/{client2-BX4-xbM4.js → client2-DYaMKWrc.js} +4 -4
  204. package/build/server/chunks/{client2-BX4-xbM4.js.map → client2-DYaMKWrc.js.map} +1 -1
  205. package/build/server/chunks/{async-BfR0vYHo.js → context-C22hLSHK.js} +2 -8
  206. package/build/server/chunks/context-C22hLSHK.js.map +1 -0
  207. package/build/server/chunks/error.svelte-BENdaVOT.js +19 -0
  208. package/build/server/chunks/error.svelte-BENdaVOT.js.map +1 -0
  209. package/build/server/chunks/event-DVH-6ISX.js.map +1 -1
  210. package/build/server/chunks/hooks.server-CagAPNr2.js +40 -0
  211. package/build/server/chunks/hooks.server-CagAPNr2.js.map +1 -0
  212. package/build/server/chunks/{index-EKt9-9bV.js → index-DFXVwu6p.js} +2 -2
  213. package/build/server/chunks/{index-EKt9-9bV.js.map → index-DFXVwu6p.js.map} +1 -1
  214. package/build/server/chunks/index-Djsj11qr.js.map +1 -1
  215. package/build/server/chunks/index-server-Bf-hP5gL.js +5 -0
  216. package/build/server/chunks/index-server-Bf-hP5gL.js.map +1 -0
  217. package/build/server/chunks/{routing-DcR4fCSD.js → index2-DBFlGzWV.js} +23 -100
  218. package/build/server/chunks/index2-DBFlGzWV.js.map +1 -0
  219. package/build/server/chunks/{index3-DquTjlmp.js → index3-CoOO2o9t.js} +6 -6
  220. package/build/server/chunks/index3-CoOO2o9t.js.map +1 -0
  221. package/build/server/chunks/jsonParser-CraFXJs8.js +174 -0
  222. package/build/server/chunks/jsonParser-CraFXJs8.js.map +1 -0
  223. package/build/server/chunks/layout.svelte-CJcHX-Na.js +10 -0
  224. package/build/server/chunks/layout.svelte-CJcHX-Na.js.map +1 -0
  225. package/build/server/chunks/logger-D71iWOkl.js +36 -0
  226. package/build/server/chunks/logger-D71iWOkl.js.map +1 -0
  227. package/build/server/chunks/{mongo-dLmCShL_.js → mongo-BogiTfnG.js} +54 -12
  228. package/build/server/chunks/mongo-BogiTfnG.js.map +1 -0
  229. package/build/server/chunks/remote-xxtqbu-BJDSUh3k.js +17 -0
  230. package/build/server/chunks/remote-xxtqbu-BJDSUh3k.js.map +1 -0
  231. package/build/server/chunks/routing-e10vGH37.js +81 -0
  232. package/build/server/chunks/routing-e10vGH37.js.map +1 -0
  233. package/build/server/chunks/{server2-BiqGvkCy.js → server2-_mGVuBoG.js} +2 -2
  234. package/build/server/chunks/{server2-BiqGvkCy.js.map → server2-_mGVuBoG.js.map} +1 -1
  235. package/build/server/chunks/servers.remote-C2HuT43p.js +690 -0
  236. package/build/server/chunks/servers.remote-C2HuT43p.js.map +1 -0
  237. package/build/server/chunks/shared-Buki-xt5.js +506 -0
  238. package/build/server/chunks/shared-Buki-xt5.js.map +1 -0
  239. package/build/server/chunks/{state.svelte-CRHA9yov.js → state.svelte-C8IWmp_n.js} +2 -2
  240. package/build/server/chunks/{state.svelte-CRHA9yov.js.map → state.svelte-C8IWmp_n.js.map} +1 -1
  241. package/build/server/chunks/{utils-DGYJFmnf.js → utils-kjxf7BZO.js} +2 -2
  242. package/build/server/chunks/{utils-DGYJFmnf.js.map → utils-kjxf7BZO.js.map} +1 -1
  243. package/build/server/index.js +189 -610
  244. package/build/server/index.js.map +1 -1
  245. package/build/server/manifest.js +45 -18
  246. package/build/server/manifest.js.map +1 -1
  247. package/package.json +13 -2
  248. package/src/api/servers.remote.ts +381 -20
  249. package/src/app.css +98 -3
  250. package/src/app.html +15 -0
  251. package/src/hooks.server.ts +18 -1
  252. package/src/lib/actions/jsonTextarea.ts +395 -0
  253. package/src/lib/components/Breadcrumbs.svelte +7 -58
  254. package/src/lib/components/JsonValue.svelte +279 -85
  255. package/src/lib/components/Modal.svelte +59 -0
  256. package/src/lib/components/OriginWarning.svelte +109 -0
  257. package/src/lib/components/PageSwitcher.svelte +37 -0
  258. package/src/lib/components/Panel.svelte +1 -1
  259. package/src/lib/components/PrettyJson.svelte +112 -36
  260. package/src/lib/components/SearchBox.svelte +161 -97
  261. package/src/lib/components/ThemeSwitcher.svelte +66 -0
  262. package/src/lib/components/Tooltip.svelte +83 -0
  263. package/src/lib/components/TooltipTable.svelte +45 -102
  264. package/src/lib/server/HostsManager.ts +4 -0
  265. package/src/lib/server/aggregation.ts +62 -0
  266. package/src/lib/server/mongo.ts +78 -15
  267. package/src/lib/types.ts +60 -0
  268. package/src/lib/utils/isEmptyObject.ts +6 -0
  269. package/src/lib/utils/jsonParser.ts +9 -1
  270. package/src/lib/utils/logger.ts +42 -0
  271. package/src/lib/utils/omit.ts +3 -0
  272. package/src/routes/+layout.server.ts +2 -1
  273. package/src/routes/+layout.svelte +15 -2
  274. package/src/routes/favicon.ico/+server.ts +8 -0
  275. package/src/routes/servers/+page.server.ts +23 -10
  276. package/src/routes/servers/+page.svelte +44 -10
  277. package/src/routes/servers/[server]/databases/+layout.ts +8 -0
  278. package/src/routes/servers/[server]/databases/+page.server.ts +15 -4
  279. package/src/routes/servers/[server]/databases/[database]/collections/+layout.ts +9 -0
  280. package/src/routes/servers/[server]/databases/[database]/collections/+page.server.ts +0 -2
  281. package/src/routes/servers/[server]/databases/[database]/collections/+page.svelte +67 -8
  282. package/src/routes/servers/[server]/databases/[database]/collections/[collection]/+layout.ts +9 -0
  283. package/src/routes/servers/[server]/databases/[database]/collections/[collection]/documents/+page.server.ts +217 -0
  284. package/src/routes/servers/[server]/databases/[database]/collections/[collection]/documents/+page.svelte +342 -0
  285. package/src/routes/servers/[server]/databases/[database]/collections/[collection]/documents/+page.ts +10 -0
  286. package/src/routes/servers/[server]/databases/[database]/collections/[collection]/documents/[document]/+layout.ts +9 -0
  287. package/src/routes/servers/[server]/databases/[database]/collections/[collection]/documents/[document]/+page.server.ts +15 -12
  288. package/src/routes/servers/[server]/databases/[database]/collections/[collection]/documents/[document]/+page.svelte +81 -7
  289. package/src/routes/servers/[server]/databases/[database]/collections/[collection]/indexes/+page.server.ts +88 -0
  290. package/src/routes/servers/[server]/databases/[database]/collections/[collection]/indexes/+page.svelte +333 -0
  291. package/src/routes/servers/[server]/databases/[database]/collections/[collection]/indexes/+page.ts +10 -0
  292. package/src/routes/servers/[server]/databases/[database]/collections/[collection]/mappings/+page.server.ts +18 -0
  293. package/src/routes/servers/[server]/databases/[database]/collections/[collection]/mappings/+page.svelte +378 -0
  294. package/src/routes/servers/[server]/databases/[database]/collections/[collection]/mappings/+page.ts +10 -0
  295. package/src/tests/api/aggregation.test.ts +125 -0
  296. package/build/client/_app/immutable/assets/0.CEsPYTp2.css +0 -1
  297. package/build/client/_app/immutable/assets/0.CEsPYTp2.css.br +0 -0
  298. package/build/client/_app/immutable/assets/0.CEsPYTp2.css.gz +0 -0
  299. package/build/client/_app/immutable/assets/6.DawdmtJd.css +0 -1
  300. package/build/client/_app/immutable/assets/6.DawdmtJd.css.br +0 -2
  301. package/build/client/_app/immutable/assets/6.DawdmtJd.css.gz +0 -0
  302. package/build/client/_app/immutable/assets/Panel.BDHMtO-3.css +0 -1
  303. package/build/client/_app/immutable/assets/Panel.BDHMtO-3.css.br +0 -0
  304. package/build/client/_app/immutable/assets/Panel.BDHMtO-3.css.gz +0 -0
  305. package/build/client/_app/immutable/assets/PrettyJson.CtngcfyW.css +0 -1
  306. package/build/client/_app/immutable/assets/PrettyJson.CtngcfyW.css.br +0 -0
  307. package/build/client/_app/immutable/assets/PrettyJson.CtngcfyW.css.gz +0 -0
  308. package/build/client/_app/immutable/chunks/B2-iEFN3.js +0 -2
  309. package/build/client/_app/immutable/chunks/B2-iEFN3.js.br +0 -0
  310. package/build/client/_app/immutable/chunks/B2-iEFN3.js.gz +0 -0
  311. package/build/client/_app/immutable/chunks/B5y2vsNr.js +0 -1
  312. package/build/client/_app/immutable/chunks/B5y2vsNr.js.br +0 -0
  313. package/build/client/_app/immutable/chunks/B5y2vsNr.js.gz +0 -0
  314. package/build/client/_app/immutable/chunks/BN_N9-2s.js +0 -1
  315. package/build/client/_app/immutable/chunks/BN_N9-2s.js.br +0 -0
  316. package/build/client/_app/immutable/chunks/BN_N9-2s.js.gz +0 -0
  317. package/build/client/_app/immutable/chunks/C1z4TjN7.js +0 -1
  318. package/build/client/_app/immutable/chunks/C1z4TjN7.js.br +0 -0
  319. package/build/client/_app/immutable/chunks/C1z4TjN7.js.gz +0 -0
  320. package/build/client/_app/immutable/chunks/CQBaNlA9.js +0 -1
  321. package/build/client/_app/immutable/chunks/CQBaNlA9.js.br +0 -0
  322. package/build/client/_app/immutable/chunks/CQBaNlA9.js.gz +0 -0
  323. package/build/client/_app/immutable/chunks/CVoOGazw.js +0 -4
  324. package/build/client/_app/immutable/chunks/CVoOGazw.js.br +0 -0
  325. package/build/client/_app/immutable/chunks/CVoOGazw.js.gz +0 -0
  326. package/build/client/_app/immutable/chunks/CapOg2jD.js +0 -1
  327. package/build/client/_app/immutable/chunks/CapOg2jD.js.br +0 -0
  328. package/build/client/_app/immutable/chunks/CapOg2jD.js.gz +0 -0
  329. package/build/client/_app/immutable/chunks/ChWB6xnu.js.br +0 -0
  330. package/build/client/_app/immutable/chunks/ChWB6xnu.js.gz +0 -0
  331. package/build/client/_app/immutable/chunks/CqnBT2zJ.js +0 -1
  332. package/build/client/_app/immutable/chunks/CqnBT2zJ.js.br +0 -0
  333. package/build/client/_app/immutable/chunks/CqnBT2zJ.js.gz +0 -0
  334. package/build/client/_app/immutable/chunks/D069mncP.js +0 -1
  335. package/build/client/_app/immutable/chunks/D069mncP.js.br +0 -0
  336. package/build/client/_app/immutable/chunks/D069mncP.js.gz +0 -0
  337. package/build/client/_app/immutable/chunks/DACrOfV_.js +0 -14
  338. package/build/client/_app/immutable/chunks/DACrOfV_.js.br +0 -0
  339. package/build/client/_app/immutable/chunks/DACrOfV_.js.gz +0 -0
  340. package/build/client/_app/immutable/chunks/DQkpHJGc.js.br +0 -0
  341. package/build/client/_app/immutable/chunks/DQkpHJGc.js.gz +0 -0
  342. package/build/client/_app/immutable/chunks/DSDD_hFT.js +0 -1
  343. package/build/client/_app/immutable/chunks/DSDD_hFT.js.br +0 -0
  344. package/build/client/_app/immutable/chunks/DSDD_hFT.js.gz +0 -0
  345. package/build/client/_app/immutable/chunks/D_aTX_ol.js +0 -1
  346. package/build/client/_app/immutable/chunks/D_aTX_ol.js.br +0 -0
  347. package/build/client/_app/immutable/chunks/D_aTX_ol.js.gz +0 -0
  348. package/build/client/_app/immutable/chunks/Dg3qHExF.js +0 -1
  349. package/build/client/_app/immutable/chunks/Dg3qHExF.js.br +0 -0
  350. package/build/client/_app/immutable/chunks/Dg3qHExF.js.gz +0 -0
  351. package/build/client/_app/immutable/chunks/Dt6-JRym.js +0 -2
  352. package/build/client/_app/immutable/chunks/Dt6-JRym.js.br +0 -0
  353. package/build/client/_app/immutable/chunks/Dt6-JRym.js.gz +0 -0
  354. package/build/client/_app/immutable/chunks/QoKxaG0e.js +0 -1
  355. package/build/client/_app/immutable/chunks/QoKxaG0e.js.br +0 -2
  356. package/build/client/_app/immutable/chunks/QoKxaG0e.js.gz +0 -0
  357. package/build/client/_app/immutable/chunks/rtveiEyS.js +0 -1
  358. package/build/client/_app/immutable/chunks/rtveiEyS.js.br +0 -0
  359. package/build/client/_app/immutable/chunks/rtveiEyS.js.gz +0 -0
  360. package/build/client/_app/immutable/entry/app.Cc1FNLNH.js +0 -2
  361. package/build/client/_app/immutable/entry/app.Cc1FNLNH.js.br +0 -0
  362. package/build/client/_app/immutable/entry/app.Cc1FNLNH.js.gz +0 -0
  363. package/build/client/_app/immutable/entry/start.CwqlbFyy.js +0 -1
  364. package/build/client/_app/immutable/entry/start.CwqlbFyy.js.br +0 -2
  365. package/build/client/_app/immutable/entry/start.CwqlbFyy.js.gz +0 -0
  366. package/build/client/_app/immutable/nodes/0.wBQEpdjZ.js +0 -1
  367. package/build/client/_app/immutable/nodes/0.wBQEpdjZ.js.br +0 -0
  368. package/build/client/_app/immutable/nodes/0.wBQEpdjZ.js.gz +0 -0
  369. package/build/client/_app/immutable/nodes/1.K6-n7D0b.js +0 -1
  370. package/build/client/_app/immutable/nodes/1.K6-n7D0b.js.br +0 -0
  371. package/build/client/_app/immutable/nodes/1.K6-n7D0b.js.gz +0 -0
  372. package/build/client/_app/immutable/nodes/3.DkGcIF98.js +0 -1
  373. package/build/client/_app/immutable/nodes/3.DkGcIF98.js.br +0 -0
  374. package/build/client/_app/immutable/nodes/3.DkGcIF98.js.gz +0 -0
  375. package/build/client/_app/immutable/nodes/4.C_NxbT98.js +0 -1
  376. package/build/client/_app/immutable/nodes/4.C_NxbT98.js.br +0 -0
  377. package/build/client/_app/immutable/nodes/4.C_NxbT98.js.gz +0 -0
  378. package/build/client/_app/immutable/nodes/5.CFvfYaLM.js +0 -1
  379. package/build/client/_app/immutable/nodes/5.CFvfYaLM.js.br +0 -0
  380. package/build/client/_app/immutable/nodes/5.CFvfYaLM.js.gz +0 -0
  381. package/build/client/_app/immutable/nodes/6.h34Zyorq.js +0 -1
  382. package/build/client/_app/immutable/nodes/6.h34Zyorq.js.br +0 -0
  383. package/build/client/_app/immutable/nodes/6.h34Zyorq.js.gz +0 -0
  384. package/build/client/_app/immutable/nodes/7.BVJmNbU5.js +0 -1
  385. package/build/client/_app/immutable/nodes/7.BVJmNbU5.js.br +0 -0
  386. package/build/client/_app/immutable/nodes/7.BVJmNbU5.js.gz +0 -0
  387. package/build/server/chunks/0-Cb5ytlMI.js.map +0 -1
  388. package/build/server/chunks/1-Cpb7zRtJ.js +0 -9
  389. package/build/server/chunks/1-Cpb7zRtJ.js.map +0 -1
  390. package/build/server/chunks/3-B_DkgZkc.js +0 -69
  391. package/build/server/chunks/3-B_DkgZkc.js.map +0 -1
  392. package/build/server/chunks/4-DzHoLo__.js.map +0 -1
  393. package/build/server/chunks/5-CCWbCDpk.js.map +0 -1
  394. package/build/server/chunks/6-Dok8svjB.js +0 -202
  395. package/build/server/chunks/6-Dok8svjB.js.map +0 -1
  396. package/build/server/chunks/7-CmgJSG2j.js +0 -42
  397. package/build/server/chunks/7-CmgJSG2j.js.map +0 -1
  398. package/build/server/chunks/Panel-Bz0b85EW.js.map +0 -1
  399. package/build/server/chunks/PrettyJson-CX6-dNsW.js +0 -291
  400. package/build/server/chunks/PrettyJson-CX6-dNsW.js.map +0 -1
  401. package/build/server/chunks/TooltipTable-0z4HkHlH.js +0 -17
  402. package/build/server/chunks/TooltipTable-0z4HkHlH.js.map +0 -1
  403. package/build/server/chunks/_layout.svelte-UiDiCQEz.js +0 -111
  404. package/build/server/chunks/_layout.svelte-UiDiCQEz.js.map +0 -1
  405. package/build/server/chunks/_page.svelte-FIp-IsOo.js.map +0 -1
  406. package/build/server/chunks/_page.svelte-FLzHOuyK.js.map +0 -1
  407. package/build/server/chunks/_page.svelte-jxFKbZdN.js.map +0 -1
  408. package/build/server/chunks/_page.svelte-k8avSQW1.js +0 -215
  409. package/build/server/chunks/_page.svelte-k8avSQW1.js.map +0 -1
  410. package/build/server/chunks/_page.svelte-w9cxGvUf.js.map +0 -1
  411. package/build/server/chunks/async-BfR0vYHo.js.map +0 -1
  412. package/build/server/chunks/client-bj7sePQc.js +0 -7
  413. package/build/server/chunks/error.svelte-D5sIJv3P.js +0 -18
  414. package/build/server/chunks/error.svelte-D5sIJv3P.js.map +0 -1
  415. package/build/server/chunks/hooks.server-_TKfdzGA.js +0 -26
  416. package/build/server/chunks/hooks.server-_TKfdzGA.js.map +0 -1
  417. package/build/server/chunks/index3-DquTjlmp.js.map +0 -1
  418. package/build/server/chunks/mongo-dLmCShL_.js.map +0 -1
  419. package/build/server/chunks/remote-xxtqbu-BFzaWXy0.js +0 -234
  420. package/build/server/chunks/remote-xxtqbu-BFzaWXy0.js.map +0 -1
  421. package/build/server/chunks/routing-DcR4fCSD.js.map +0 -1
  422. package/src/routes/servers/[server]/databases/[database]/collections/[collection]/+page.server.ts +0 -106
  423. package/src/routes/servers/[server]/databases/[database]/collections/[collection]/+page.svelte +0 -174
  424. /package/build/client/_app/immutable/assets/{3.CRKE8WvY.css → 7.CRKE8WvY.css} +0 -0
  425. /package/build/client/_app/immutable/assets/{3.CRKE8WvY.css.br → 7.CRKE8WvY.css.br} +0 -0
  426. /package/build/client/_app/immutable/assets/{3.CRKE8WvY.css.gz → 7.CRKE8WvY.css.gz} +0 -0
@@ -1,7 +1,9 @@
1
1
  <script lang="ts">
2
+ import { fetchMappedDocument as fetchMappedDocumentRemote } from "$api/servers.remote";
2
3
  import { resolve } from "$app/paths";
4
+ import { jsonTextarea } from "$lib/actions/jsonTextarea";
3
5
  import { notificationStore } from "$lib/stores/notifications.svelte";
4
- import type { MongoDocument } from "$lib/types";
6
+ import type { Mappings, MongoDocument } from "$lib/types";
5
7
  import { parseJSON } from "$lib/utils/jsonParser";
6
8
  import JsonValue from "./JsonValue.svelte";
7
9
  import Panel from "./Panel.svelte";
@@ -11,29 +13,82 @@
11
13
  interface Props {
12
14
  json: MongoDocument;
13
15
  autoCollapse?: boolean;
14
- readOnly?: boolean;
15
16
  onedit?: (json: any) => void;
16
17
  onremove?: () => void;
17
18
  server: string;
18
19
  database: string;
19
20
  collection: string;
21
+ mappings?: Mappings;
22
+ startInEditMode?: boolean;
20
23
  }
21
24
 
22
25
  let {
23
26
  json,
24
27
  autoCollapse = false,
25
- readOnly = false,
26
28
  onedit,
27
29
  onremove,
28
30
  server,
29
31
  database,
30
32
  collection,
33
+ mappings,
34
+ startInEditMode = false,
31
35
  }: Props = $props();
32
36
 
37
+ // Helper to get ID value from any type
38
+ function getIdValue(val: any): string | null {
39
+ if (val === null || val === undefined) return null;
40
+ if (typeof val === "string" || typeof val === "number") return String(val);
41
+ if (val.$type === "ObjectId" && val.$value) return val.$value;
42
+ return null;
43
+ }
44
+
45
+ // Check if a key path has a mapping
46
+ function isKeyMapped(path: string): boolean {
47
+ return !!mappings?.[path] && (Array.isArray(mappings[path]) ? mappings[path].length > 0 : true);
48
+ }
49
+
50
+ // Fetch mapped document and return it with its navigation URL
51
+ async function fetchMappedDocument(
52
+ path: string,
53
+ value: any,
54
+ ): Promise<{ document: MongoDocument | null; url: string | null; collection: string | null }> {
55
+ if (!mappings || !mappings[path] || (Array.isArray(mappings[path]) && mappings[path].length === 0)) {
56
+ return { document: null, url: null, collection: null };
57
+ }
58
+
59
+ const idValue = getIdValue(value);
60
+
61
+ if (!idValue) {
62
+ return { document: null, url: null, collection: null };
63
+ }
64
+
65
+ // Fetch the document - remote function will try all mappings and return first match
66
+ try {
67
+ const result = await fetchMappedDocumentRemote({
68
+ server,
69
+ database,
70
+ mappings: Array.isArray(mappings[path]) ? mappings[path] : [mappings[path]],
71
+ value,
72
+ });
73
+
74
+ if (result.error || !result.data || !result.collection) {
75
+ return { document: null, url: null, collection: null };
76
+ }
77
+
78
+ // Generate URL for navigation
79
+ const url = resolve(
80
+ `/servers/${encodeURIComponent(server)}/databases/${encodeURIComponent(database)}/collections/${encodeURIComponent(result.collection)}/documents/${encodeURIComponent(idValue)}`,
81
+ );
82
+
83
+ return { document: result.data, url, collection: result.collection };
84
+ } catch {
85
+ return { document: null, url: null, collection: null };
86
+ }
87
+ }
88
+
33
89
  let editorVisible = $state(false);
34
90
  let editJson = $state("");
35
91
  let removing = $state(false);
36
- let editorRef = $state<HTMLTextAreaElement>();
37
92
  let contentContainerRef = $state<HTMLDivElement>();
38
93
  let editorHeight = $state<string>("300px");
39
94
 
@@ -50,8 +105,8 @@
50
105
 
51
106
  // Custom serializer that converts ObjectId objects back to new ObjectId() format
52
107
  function serializeForEditing(obj: any, depth = 0): string {
53
- const indent = " ".repeat(depth);
54
- const nextIndent = " ".repeat(depth + 1);
108
+ const indent = "\t".repeat(depth);
109
+ const nextIndent = "\t".repeat(depth + 1);
55
110
 
56
111
  if (obj === null) return "null";
57
112
  if (obj === undefined) return "undefined";
@@ -106,6 +161,13 @@
106
161
  editorVisible = true;
107
162
  }
108
163
 
164
+ // Automatically enable editor if startInEditMode is true
165
+ $effect(() => {
166
+ if (startInEditMode && !editorVisible && contentContainerRef) {
167
+ enableEditor();
168
+ }
169
+ });
170
+
109
171
  function disableEditor() {
110
172
  editorVisible = false;
111
173
  editJson = "";
@@ -132,43 +194,57 @@
132
194
  function confirmRemove() {
133
195
  onremove?.();
134
196
  }
197
+
198
+ async function copyToClipboard() {
199
+ try {
200
+ const jsonString = serializeForEditing(json);
201
+ await navigator.clipboard.writeText(jsonString);
202
+ notificationStore.notifySuccess("Document copied to clipboard");
203
+ } catch (err) {
204
+ notificationStore.notifyError(err, "Failed to copy to clipboard");
205
+ }
206
+ }
135
207
  </script>
136
208
 
137
- <Panel class="group">
138
- {#snippet title()}
139
- {#if json._id}
140
- <div class="">
141
- <a
142
- type="button"
143
- class="bg-transparent border-none text-[var(--text)] no-underline cursor-pointer text-xl font-inherit p-0 hover:underline"
144
- href={resolve(
145
- `/servers/${encodeURIComponent(server)}/databases/${encodeURIComponent(database)}/collections/${encodeURIComponent(collection)}/documents/${json._id?.$value}`,
146
- )}
147
- >
148
- {json._id?.$value}
149
- </a>
150
- {#if json._id?.$value}
151
- {@const timestamp = getTimestampFromObjectId(json._id.$value)}
152
- {#if timestamp}
153
- <span class="ml-2 text-md text-[var(--text-secondary,#888)]">{timestamp.toLocaleString()}</span>
154
- {/if}
209
+ {#snippet title()}
210
+ {#if json._id}
211
+ {@const idValue = json._id.$value ?? json._id}
212
+ <div class="">
213
+ <a
214
+ type="button"
215
+ class="bg-transparent border-none text-[var(--text)] no-underline cursor-pointer text-xl font-inherit p-0 hover:underline normal-case"
216
+ href={resolve(
217
+ `/servers/${encodeURIComponent(server)}/databases/${encodeURIComponent(database)}/collections/${encodeURIComponent(collection)}/documents/${idValue}`,
218
+ )}
219
+ >
220
+ {idValue}
221
+ </a>
222
+ {#if json._id.$value}
223
+ {@const timestamp = getTimestampFromObjectId(json._id.$value)}
224
+ {#if timestamp}
225
+ <span class="ml-2 text-md text-[var(--text-secondary,#888)]">{timestamp.toLocaleString()}</span>
155
226
  {/if}
156
- </div>
157
- {/if}
158
- {/snippet}
227
+ {/if}
228
+ </div>
229
+ {/if}
230
+ {/snippet}
159
231
 
160
- {#snippet actions()}
161
- {#if !readOnly}
162
- <div class="hidden group-hover:block">
163
- <button class="btn btn-outline-light btn-sm ml-2 -my-2" onclick={enableEditor}>Edit</button>
164
- <button class="btn btn-outline-danger btn-sm ml-2 -my-2" onclick={showRemove}>Remove</button>
165
- </div>
232
+ {#snippet actions()}
233
+ <div class="hidden group-hover:block">
234
+ <button class="btn btn-outline-light btn-sm ml-2 -my-2" onclick={copyToClipboard}>Copy</button>
235
+ {#if onedit}
236
+ <button class="btn btn-outline-light btn-sm ml-2 -my-2" onclick={enableEditor}>Edit</button>
237
+ {/if}
238
+ {#if onremove}
239
+ <button class="btn btn-outline-danger btn-sm ml-2 -my-2" onclick={showRemove}>Remove</button>
166
240
  {/if}
167
- {/snippet}
241
+ </div>
242
+ {/snippet}
168
243
 
244
+ <Panel class="group" title={json._id ? title : undefined} {actions}>
169
245
  <div bind:this={contentContainerRef} class="p-4 relative border-t border-[var(--border-color)]">
170
246
  <div class="font-mono text-sm leading-tight whitespace-pre-wrap break-words relative">
171
- <JsonValue value={json} {autoCollapse} collapsed={false} />
247
+ <JsonValue value={json} {autoCollapse} collapsed={false} {isKeyMapped} {fetchMappedDocument} />
172
248
  </div>
173
249
 
174
250
  <div class="absolute h-full z-[100] w-full top-0 left-0" class:hidden={!editorVisible} class:block={editorVisible}>
@@ -177,9 +253,9 @@
177
253
  <button class="btn btn-default ml-2" onclick={disableEditor}>Cancel</button>
178
254
  </div>
179
255
  <textarea
180
- bind:this={editorRef}
181
256
  bind:value={editJson}
182
257
  style="height: {editorHeight};"
258
+ use:jsonTextarea={{ onsubmit: save, onescape: disableEditor }}
183
259
  class="w-full font-mono text-sm leading-relaxed p-2.5 bg-[var(--color-1)] text-[var(--text)] border border-[var(--border-color)] rounded resize-y"
184
260
  ></textarea>
185
261
  </div>
@@ -2,13 +2,16 @@
2
2
  import { goto } from "$app/navigation";
3
3
  import { resolve } from "$app/paths";
4
4
  import { page } from "$app/state";
5
+ import { jsonTextarea } from "$lib/actions/jsonTextarea";
5
6
  import type { SearchParams } from "$lib/types";
6
7
 
7
8
  interface Props {
8
9
  params: SearchParams;
10
+ editMode?: boolean;
11
+ readonly: boolean;
9
12
  }
10
13
 
11
- let { params = $bindable() }: Props = $props();
14
+ let { params = $bindable(), editMode = $bindable(false), readonly = $bindable(false) }: Props = $props();
12
15
 
13
16
  // Show optional fields - start with all hidden
14
17
  let showOptionalFields = $state(
@@ -17,7 +20,17 @@
17
20
 
18
21
  let counter = $state(Math.random());
19
22
 
20
- let queryInput: HTMLInputElement | undefined;
23
+ let queryInput = $state<HTMLInputElement | HTMLTextAreaElement | undefined>(undefined);
24
+
25
+ // Detect if query is an aggregation (starts with [)
26
+ let isAggregation = $derived(params.query?.trimStart().startsWith("["));
27
+
28
+ // Disable edit mode when switching to aggregation mode
29
+ $effect(() => {
30
+ if (isAggregation && editMode) {
31
+ editMode = false;
32
+ }
33
+ });
21
34
 
22
35
  $effect(() => {
23
36
  if (queryInput) {
@@ -45,116 +58,167 @@
45
58
  );
46
59
  }
47
60
 
48
- let form: HTMLFormElement | undefined;
61
+ let form = $state<HTMLFormElement | undefined>(undefined);
49
62
  </script>
50
63
 
51
- <form class="flex items-stretch w-full" method="GET" action="?" onsubmit={submit} bind:this={form}>
52
- <!-- Parameters group -->
53
- <div class="flex-grow">
54
- <!-- Query input (always shown) -->
55
- <div class="flex items-stretch w-full h-10">
56
- <div
57
- class="min-w-[100px] flex justify-center items-center border border-[var(--color-4)] {!showOptionalFields
58
- ? 'border-b rounded-bl-md'
59
- : 'border-b-0'} bg-[var(--color-1)] rounded-tl-md"
60
- >
61
- Query:
62
- </div>
63
- <input
64
- type="text"
65
- bind:this={queryInput}
66
- bind:value={params.query}
67
- placeholder={"{}"}
68
- name="query"
69
- class="flex-grow border-0 bg-[var(--color-3)] pl-2.5 font-mono"
70
- />
71
- </div>
72
-
73
- <input type="hidden" value={counter} name="v" />
74
- <!-- Sort input -->
75
- {#if showOptionalFields}
76
- <div class="flex items-stretch w-full h-10">
64
+ <div>
65
+ <form class="flex items-stretch w-full" method="GET" action="?" onsubmit={submit} bind:this={form}>
66
+ <!-- Parameters group -->
67
+ <div class="flex-grow">
68
+ <!-- Query input (always shown) -->
69
+ <div class="flex items-stretch w-full {isAggregation ? 'min-h-10' : 'h-10'}">
77
70
  <div
78
- class="min-w-[100px] flex justify-center items-center border border-[var(--color-4)] border-b-0 bg-[var(--color-1)]"
71
+ class="min-w-[100px] flex justify-center items-center border border-[var(--color-4)] {!showOptionalFields
72
+ ? 'border-b rounded-bl-md'
73
+ : 'border-b-0'} bg-[var(--color-1)] rounded-tl-md"
79
74
  >
80
- Sort:
75
+ {isAggregation ? "Aggregation:" : "Query:"}
81
76
  </div>
82
- <input
83
- type="text"
84
- bind:value={params.sort}
85
- name="sort"
86
- placeholder={"{}"}
87
- class="flex-grow border-0 border-t border-[var(--color-4)] bg-[var(--color-3)] pl-2.5 font-mono"
88
- />
77
+ {#if isAggregation}
78
+ <textarea
79
+ bind:this={queryInput}
80
+ bind:value={params.query}
81
+ placeholder="[]"
82
+ name="query"
83
+ rows="5"
84
+ use:jsonTextarea={{ onsubmit: () => form?.requestSubmit() }}
85
+ class="flex-grow border-0 bg-[var(--color-3)] pl-2.5 font-mono py-2 resize-y"
86
+ ></textarea>
87
+ {:else}
88
+ <input
89
+ type="text"
90
+ bind:this={queryInput}
91
+ bind:value={params.query}
92
+ placeholder={"{}"}
93
+ name="query"
94
+ class="flex-grow border-0 bg-[var(--color-3)] pl-2.5 font-mono"
95
+ />
96
+ {/if}
89
97
  </div>
90
98
 
91
- <!-- Skip input -->
92
- <div class="flex items-stretch w-full h-10">
93
- <div
94
- class="min-w-[100px] flex justify-center items-center border border-[var(--color-4)] border-b-0 bg-[var(--color-1)]"
95
- >
96
- Skip:
99
+ <input type="hidden" value={counter} name="v" />
100
+ <!-- Sort input -->
101
+ {#if showOptionalFields}
102
+ <div class="flex items-stretch w-full h-10">
103
+ <div
104
+ class="min-w-[100px] flex justify-center items-center border border-[var(--color-4)] border-b-0 bg-[var(--color-1)]"
105
+ >
106
+ Sort:
107
+ </div>
108
+ <input
109
+ type="text"
110
+ bind:value={params.sort}
111
+ name="sort"
112
+ placeholder={"{}"}
113
+ class="flex-grow border-0 border-t border-[var(--color-4)] bg-[var(--color-3)] pl-2.5 font-mono"
114
+ />
97
115
  </div>
98
- <input
99
- type="number"
100
- bind:value={params.skip}
101
- name="skip"
102
- min="0"
103
- class="flex-grow border-0 border-t border-[var(--color-4)] bg-[var(--color-3)] pl-2.5 font-mono"
104
- />
105
- </div>
106
116
 
107
- <!-- Limit input -->
108
- <div class="flex items-stretch w-full h-10">
109
- <div
110
- class="min-w-[100px] flex justify-center items-center border border-[var(--color-4)] border-b-0 bg-[var(--color-1)]"
111
- >
112
- Limit:
117
+ <!-- Skip input -->
118
+ <div class="flex items-stretch w-full h-10">
119
+ <div
120
+ class="min-w-[100px] flex justify-center items-center border border-[var(--color-4)] border-b-0 bg-[var(--color-1)]"
121
+ >
122
+ Skip:
123
+ </div>
124
+ <input
125
+ type="number"
126
+ bind:value={params.skip}
127
+ name="skip"
128
+ min="0"
129
+ class="flex-grow border-0 border-t border-[var(--color-4)] bg-[var(--color-3)] pl-2.5 font-mono"
130
+ />
113
131
  </div>
114
- <input
115
- type="number"
116
- bind:value={params.limit}
117
- name="limit"
118
- min="1"
119
- class="flex-grow border-0 border-t border-[var(--color-4)] bg-[var(--color-3)] pl-2.5 font-mono"
120
- />
121
- </div>
122
132
 
123
- <!-- Project input -->
124
- <div class="flex items-stretch w-full h-10">
125
- <div
126
- class="min-w-[100px] flex justify-center items-center border border-[var(--color-4)] border-b bg-[var(--color-1)] rounded-bl-md"
127
- >
128
- Project:
133
+ <!-- Limit input -->
134
+ <div class="flex items-stretch w-full h-10">
135
+ <div
136
+ class="min-w-[100px] flex justify-center items-center border border-[var(--color-4)] border-b-0 bg-[var(--color-1)]"
137
+ >
138
+ Limit:
139
+ </div>
140
+ <input
141
+ type="number"
142
+ bind:value={params.limit}
143
+ name="limit"
144
+ min="1"
145
+ class="flex-grow border-0 border-t border-[var(--color-4)] bg-[var(--color-3)] pl-2.5 font-mono"
146
+ />
129
147
  </div>
130
- <input
131
- type="text"
132
- bind:value={params.project}
133
- name="project"
134
- placeholder={"{}"}
135
- class="flex-grow border-0 border-t border-[var(--color-4)] bg-[var(--color-3)] pl-2.5 font-mono"
136
- />
137
- </div>
148
+
149
+ <!-- Project input -->
150
+ <div class="flex items-stretch w-full h-10">
151
+ <div
152
+ class="min-w-[100px] flex justify-center items-center border border-[var(--color-4)] border-b bg-[var(--color-1)] rounded-bl-md"
153
+ >
154
+ Project:
155
+ </div>
156
+ <input
157
+ type="text"
158
+ bind:value={params.project}
159
+ name="project"
160
+ placeholder={"{}"}
161
+ class="flex-grow border-0 border-t border-[var(--color-4)] bg-[var(--color-3)] pl-2.5 font-mono"
162
+ />
163
+ </div>
164
+ {/if}
165
+ </div>
166
+
167
+ <!-- Toggle optional fields button -->
168
+ <button
169
+ class="btn btn-default !w-12 !rounded-none !border-r-0 text-2xl leading-none font-bold !py-1.5"
170
+ type="button"
171
+ onclick={() => {
172
+ showOptionalFields = !showOptionalFields;
173
+ }}
174
+ >
175
+ {showOptionalFields ? "−" : "+"}
176
+ </button>
177
+
178
+ <!-- Edit/Update button -->
179
+ {#if !readonly}
180
+ <button
181
+ class="btn btn-default !w-12 !rounded-none !border-r-0 text-lg leading-none font-bold !py-1.5"
182
+ type="button"
183
+ title={isAggregation ? "Update not available in aggregation mode" : "Update multiple documents"}
184
+ disabled={isAggregation}
185
+ onclick={() => {
186
+ editMode = !editMode;
187
+ }}
188
+ >
189
+ <svg
190
+ xmlns="http://www.w3.org/2000/svg"
191
+ width="18"
192
+ height="18"
193
+ viewBox="0 0 24 24"
194
+ fill="none"
195
+ stroke="currentColor"
196
+ stroke-width="2"
197
+ stroke-linecap="round"
198
+ stroke-linejoin="round"
199
+ >
200
+ <path d="M17 3a2.85 2.83 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5Z"></path>
201
+ <path d="m15 5 4 4"></path>
202
+ </svg>
203
+ </button>
138
204
  {/if}
139
- </div>
140
-
141
- <!-- Toggle optional fields button -->
142
- <button
143
- class="btn btn-default !w-12 !rounded-none !border-r-0 text-2xl leading-none font-bold !py-1.5"
144
- type="button"
145
- onclick={() => {
146
- showOptionalFields = !showOptionalFields;
147
- }}
148
- >
149
- {showOptionalFields ? "−" : "+"}
150
- </button>
151
-
152
- <!-- Search button -->
153
- <button class="btn btn-success !rounded-l-none !rounded-r-md font-bold !py-1.5" type="submit"> GO! </button>
154
- </form>
205
+
206
+ <!-- Search button -->
207
+ <button class="btn btn-success !rounded-l-none !rounded-r-md font-bold !py-1.5" type="submit"> GO! </button>
208
+ </form>
209
+
210
+ <!-- Help text when collapsed -->
211
+ {#if !showOptionalFields && !isAggregation && params.query === "{}"}
212
+ <div class="text-xs mt-1 ml-1" style="color: var(--text-secondary);">
213
+ Tip: Use <code class="bg-[var(--color-3)] px-1 py-0.5 rounded font-mono">[{"{...}"}]</code> to switch to aggregation
214
+ mode
215
+ </div>
216
+ {/if}
217
+ </div>
155
218
 
156
219
  <style lang="postcss">
157
- input {
220
+ input,
221
+ textarea {
158
222
  border-radius: 0;
159
223
  }
160
224
  </style>
@@ -0,0 +1,66 @@
1
+ <script lang="ts">
2
+ type Theme = "system" | "light" | "dark";
3
+
4
+ let currentTheme = $state<Theme>("dark");
5
+
6
+ // Load theme from localStorage on mount
7
+ $effect(() => {
8
+ if (typeof window !== "undefined") {
9
+ const stored = localStorage.getItem("theme") as Theme | null;
10
+ currentTheme = stored || "dark";
11
+ }
12
+ });
13
+
14
+ function setTheme(theme: Theme) {
15
+ currentTheme = theme;
16
+ localStorage.setItem("theme", theme);
17
+
18
+ const root = document.documentElement;
19
+
20
+ if (theme === "system") {
21
+ const prefersDark = window.matchMedia("(prefers-color-scheme: dark)").matches;
22
+ root.setAttribute("data-theme", prefersDark ? "dark" : "light");
23
+ } else {
24
+ root.setAttribute("data-theme", theme);
25
+ }
26
+ }
27
+
28
+ function cycleTheme() {
29
+ const themes: Theme[] = ["system", "light", "dark"];
30
+ const currentIndex = themes.indexOf(currentTheme);
31
+ const nextTheme = themes[(currentIndex + 1) % themes.length];
32
+ setTheme(nextTheme);
33
+ }
34
+
35
+ const icon = $derived.by(() => {
36
+ switch (currentTheme) {
37
+ case "light":
38
+ return "☀️";
39
+ case "dark":
40
+ return "🌙";
41
+ case "system":
42
+ return "💻";
43
+ }
44
+ });
45
+
46
+ const label = $derived.by(() => {
47
+ switch (currentTheme) {
48
+ case "light":
49
+ return "Light";
50
+ case "dark":
51
+ return "Dark";
52
+ case "system":
53
+ return "System";
54
+ }
55
+ });
56
+ </script>
57
+
58
+ <button
59
+ onclick={cycleTheme}
60
+ class="btn btn-default btn-sm flex items-center gap-2"
61
+ title="Change theme (current: {label})"
62
+ aria-label="Change theme"
63
+ >
64
+ <span class="text-base">{icon}</span>
65
+ <span class="hidden sm:inline">{label}</span>
66
+ </button>
@@ -0,0 +1,83 @@
1
+ <script lang="ts">
2
+ import { tick, type Snippet } from "svelte";
3
+
4
+ interface Props {
5
+ /** Content to trigger the tooltip */
6
+ trigger: Snippet;
7
+ /** Content to display in the tooltip */
8
+ content: Snippet;
9
+ /** Whether the tooltip is visible */
10
+ show?: boolean;
11
+ /** Additional class for the tooltip container */
12
+ tooltipClass?: string;
13
+ }
14
+
15
+ let { trigger, content, show = false, tooltipClass = "" }: Props = $props();
16
+
17
+ let tooltipElement = $state<HTMLDivElement>();
18
+ let containerElement = $state<HTMLDivElement>();
19
+
20
+ let tooltipPosition = $state({
21
+ left: "",
22
+ right: "",
23
+ top: "",
24
+ bottom: "",
25
+ marginTop: "",
26
+ marginBottom: "",
27
+ });
28
+
29
+ $effect(() => {
30
+ if (show && tooltipElement && containerElement) {
31
+ tick().then(() => {
32
+ if (!containerElement || !tooltipElement) return;
33
+
34
+ const tooltipRect = tooltipElement.getBoundingClientRect();
35
+ const viewportWidth = window.innerWidth;
36
+ const viewportHeight = window.innerHeight;
37
+
38
+ // Reset positioning
39
+ tooltipPosition = {
40
+ left: "",
41
+ right: "",
42
+ top: "",
43
+ bottom: "",
44
+ marginTop: "",
45
+ marginBottom: "",
46
+ };
47
+
48
+ // Position horizontally
49
+ if (tooltipRect.right > viewportWidth) {
50
+ tooltipPosition.right = "0";
51
+ } else {
52
+ tooltipPosition.left = "0";
53
+ }
54
+
55
+ // Position vertically
56
+ if (tooltipRect.bottom > viewportHeight) {
57
+ tooltipPosition.bottom = "100%";
58
+ tooltipPosition.marginBottom = "5px";
59
+ } else {
60
+ tooltipPosition.top = "100%";
61
+ tooltipPosition.marginTop = "5px";
62
+ }
63
+ });
64
+ }
65
+ });
66
+ </script>
67
+
68
+ <div class="relative inline-block" bind:this={containerElement}>
69
+ {@render trigger()}{#if show}
70
+ <div
71
+ class="absolute bg-[var(--light-background)] border border-[var(--color-3)] rounded z-[1000] shadow-lg {tooltipClass}"
72
+ bind:this={tooltipElement}
73
+ style:left={tooltipPosition.left}
74
+ style:right={tooltipPosition.right}
75
+ style:top={tooltipPosition.top}
76
+ style:bottom={tooltipPosition.bottom}
77
+ style:margin-top={tooltipPosition.marginTop}
78
+ style:margin-bottom={tooltipPosition.marginBottom}
79
+ >
80
+ {@render content()}
81
+ </div>
82
+ {/if}
83
+ </div>