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
package/src/app.css CHANGED
@@ -6,10 +6,11 @@
6
6
  @tailwind components;
7
7
  @tailwind utilities;
8
8
 
9
- :root {
9
+ /* Dark mode (default) */
10
+ :root[data-theme="dark"] {
10
11
  --color-1: hsl(216, 26%, 15%);
11
12
  --color-1-5: hsl(218, 25%, 18%);
12
- --color-2: hsl(220, 23%, 21%);
13
+ --light-background: hsl(220, 23%, 21%);
13
14
  --color-3: hsl(217, 20%, 25%);
14
15
  --color-4: hsl(220, 20%, 30%);
15
16
 
@@ -20,6 +21,7 @@
20
21
  --text-inverse: hsl(0, 0%, 12%);
21
22
  --text-darker: hsl(0, 0%, 57%);
22
23
  --text-lighter: hsl(0, 0%, 100%);
24
+ --text-secondary: hsl(0, 0%, 60%);
23
25
  --link: hsl(211, 100%, 89%);
24
26
 
25
27
  --error: hsl(0, 78%, 28%);
@@ -29,6 +31,87 @@
29
31
  --button-success: #008000;
30
32
  --button-success-l: #4e994e;
31
33
  --button-light: hsl(0, 0%, 88%);
34
+ --button-light-hover: hsl(0, 0%, 100%);
35
+
36
+ --code-namespace: #9cdcfe;
37
+ --code-boolean: #569cd6;
38
+ --code-null: #569cd6;
39
+ --code-numbers: #b5cea8;
40
+ --code-string: #ce9178;
41
+ --code-links: #4e94ce;
42
+ --code-summary: #6a9955;
43
+ --code-regexp: #ce696b;
44
+ --code-function: #dcdcaa;
45
+
46
+ --border: 1px solid var(--color-3);
47
+ }
48
+
49
+ /* Light mode */
50
+ :root[data-theme="light"] {
51
+ --color-1: hsl(0, 0%, 98%);
52
+ --color-1-5: hsl(0, 0%, 96%);
53
+ --light-background: hsl(0, 0%, 94%);
54
+ --color-3: hsl(0, 0%, 88%);
55
+ --color-4: hsl(0, 0%, 80%);
56
+
57
+ --background-color: var(--color-1);
58
+ --border-color: var(--color-3);
59
+
60
+ --text: hsl(0, 0%, 12%);
61
+ --text-inverse: hsl(0, 0%, 88%);
62
+ --text-darker: hsl(0, 0%, 43%);
63
+ --text-lighter: hsl(0, 0%, 0%);
64
+ --text-secondary: hsl(0, 0%, 40%);
65
+ --link: hsl(211, 100%, 35%);
66
+
67
+ --error: hsl(0, 78%, 50%);
68
+
69
+ --button-danger: #d13438;
70
+ --button-danger-l: #e57373;
71
+ --button-success: #2e7d32;
72
+ --button-success-l: #66bb6a;
73
+ --button-light: hsl(0, 0%, 25%);
74
+ --button-light-hover: hsl(0, 0%, 15%);
75
+
76
+ --code-namespace: #0070c1;
77
+ --code-boolean: #0000ff;
78
+ --code-null: #0000ff;
79
+ --code-numbers: #098658;
80
+ --code-string: #a31515;
81
+ --code-links: #0451a5;
82
+ --code-summary: #008000;
83
+ --code-regexp: #d16969;
84
+ --code-function: #795e26;
85
+
86
+ --border: 1px solid var(--color-3);
87
+ }
88
+
89
+ /* Fallback for initial load before script runs */
90
+ :root:not([data-theme]) {
91
+ --color-1: hsl(216, 26%, 15%);
92
+ --color-1-5: hsl(218, 25%, 18%);
93
+ --light-background: hsl(220, 23%, 21%);
94
+ --color-3: hsl(217, 20%, 25%);
95
+ --color-4: hsl(220, 20%, 30%);
96
+
97
+ --background-color: var(--color-1);
98
+ --border-color: var(--color-3);
99
+
100
+ --text: hsl(0, 0%, 88%);
101
+ --text-inverse: hsl(0, 0%, 12%);
102
+ --text-darker: hsl(0, 0%, 57%);
103
+ --text-lighter: hsl(0, 0%, 100%);
104
+ --text-secondary: hsl(0, 0%, 60%);
105
+ --link: hsl(211, 100%, 89%);
106
+
107
+ --error: hsl(0, 78%, 28%);
108
+
109
+ --button-danger: #a31515;
110
+ --button-danger-l: #a54c4c;
111
+ --button-success: #008000;
112
+ --button-success-l: #4e994e;
113
+ --button-light: hsl(0, 0%, 88%);
114
+ --button-light-hover: hsl(0, 0%, 100%);
32
115
 
33
116
  --code-namespace: #9cdcfe;
34
117
  --code-boolean: #569cd6;
@@ -49,6 +132,7 @@
49
132
  font-family: "Rajdhani", sans-serif;
50
133
  color: var(--text);
51
134
  min-height: 100vh;
135
+ tab-size: 2;
52
136
  }
53
137
 
54
138
  a:hover {
@@ -144,6 +228,17 @@
144
228
  color: var(--text-lighter);
145
229
  }
146
230
 
231
+ .btn-outline-light {
232
+ background: transparent;
233
+ color: var(--button-light);
234
+ border-color: var(--button-light);
235
+ }
236
+
237
+ .btn-outline-light:hover {
238
+ background-color: var(--color-4);
239
+ color: var(--button-light-hover);
240
+ }
241
+
147
242
  .btn:disabled {
148
243
  opacity: 0.5;
149
244
  cursor: not-allowed;
@@ -201,7 +296,7 @@
201
296
  }
202
297
 
203
298
  .modal {
204
- background-color: var(--color-2);
299
+ background-color: var(--light-background);
205
300
  border: 1px solid var(--color-3);
206
301
  border-radius: 4px;
207
302
  max-width: 500px;
package/src/app.html CHANGED
@@ -3,6 +3,21 @@
3
3
  <head>
4
4
  <meta charset="utf-8" />
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1" />
6
+ <script>
7
+ // Immediately set theme to prevent flash
8
+ (function () {
9
+ const theme = localStorage.getItem("theme") || "dark";
10
+ let actualTheme;
11
+
12
+ if (theme === "system") {
13
+ actualTheme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
14
+ } else {
15
+ actualTheme = theme;
16
+ }
17
+
18
+ document.documentElement.setAttribute("data-theme", actualTheme);
19
+ })();
20
+ </script>
6
21
  %sveltekit.head%
7
22
  </head>
8
23
  <body data-sveltekit-preload-data="hover">
@@ -1,3 +1,4 @@
1
+ import { logger } from "$lib/utils/logger";
1
2
  import type { Handle, HandleServerError } from "@sveltejs/kit";
2
3
  import { MongoError } from "mongodb";
3
4
 
@@ -5,12 +6,28 @@ import { MongoError } from "mongodb";
5
6
  Error.stackTraceLimit = 100;
6
7
 
7
8
  export const handle: Handle = async ({ event, resolve }) => {
9
+ const authBasic = process.env.MONGOKU_AUTH_BASIC;
10
+ if (authBasic) {
11
+ const [username, password] = authBasic.split(":");
12
+ const basicAuth = event.request.headers.get("Authorization");
13
+ if (
14
+ !basicAuth?.toLowerCase().startsWith("basic ") ||
15
+ basicAuth.slice("basic ".length) !== Buffer.from(`${username}:${password}`).toString("base64")
16
+ ) {
17
+ return new Response("Unauthorized", {
18
+ status: 401,
19
+ headers: {
20
+ "WWW-Authenticate": "Basic",
21
+ },
22
+ });
23
+ }
24
+ }
8
25
  return resolve(event);
9
26
  };
10
27
 
11
28
  export const handleError: HandleServerError = ({ error }) => {
12
29
  // Log the error server-side
13
- console.error(error);
30
+ logger.error(error);
14
31
 
15
32
  // Handle MongoDB errors specifically
16
33
  if (error instanceof MongoError) {
@@ -0,0 +1,395 @@
1
+ import type { Action } from "svelte/action";
2
+
3
+ interface JsonTextareaParams {
4
+ onsubmit?: () => void;
5
+ onescape?: () => void;
6
+ }
7
+
8
+ function getIndentation(text: string): string {
9
+ const match = text.match(/^(\s*)/);
10
+ return match ? match[1] : "";
11
+ }
12
+
13
+ function handleSkipClosing(
14
+ event: KeyboardEvent,
15
+ target: HTMLTextAreaElement,
16
+ textValue: string,
17
+ selectionStart: number,
18
+ selectionEnd: number,
19
+ ): boolean {
20
+ // Skip if any modifier keys or there's a selection
21
+ if (event.ctrlKey || event.altKey || event.metaKey || selectionStart !== selectionEnd) return false;
22
+
23
+ const closingChars = ["}", "]", ")", '"', "'", "`"];
24
+ if (!closingChars.includes(event.key)) return false;
25
+
26
+ // Check if next character is the same as what we're typing
27
+ const nextChar = textValue[selectionStart];
28
+ if (nextChar !== event.key) return false;
29
+
30
+ event.preventDefault();
31
+
32
+ // Just move cursor forward one position
33
+ requestAnimationFrame(() => {
34
+ target.setSelectionRange(selectionStart + 1, selectionStart + 1);
35
+ });
36
+ return true;
37
+ }
38
+
39
+ function handleAutoPairing(
40
+ event: KeyboardEvent,
41
+ target: HTMLTextAreaElement,
42
+ textValue: string,
43
+ selectionStart: number,
44
+ selectionEnd: number,
45
+ ): boolean {
46
+ // Skip if any modifier keys (except shift for shift+2 = @, etc.)
47
+ if (event.ctrlKey || event.altKey || event.metaKey) return false;
48
+
49
+ const pairs: Record<string, string> = {
50
+ "{": "}",
51
+ "[": "]",
52
+ "(": ")",
53
+ '"': '"',
54
+ "'": "'",
55
+ "`": "`",
56
+ };
57
+
58
+ const closingChar = pairs[event.key];
59
+ if (!closingChar) return false;
60
+
61
+ event.preventDefault();
62
+
63
+ // If there's a selection, wrap it with the pair
64
+ if (selectionStart !== selectionEnd) {
65
+ const selectedText = textValue.substring(selectionStart, selectionEnd);
66
+ const newValue =
67
+ textValue.substring(0, selectionStart) +
68
+ event.key +
69
+ selectedText +
70
+ closingChar +
71
+ textValue.substring(selectionEnd);
72
+ target.value = newValue;
73
+ target.dispatchEvent(new Event("input", { bubbles: true }));
74
+
75
+ // Select the wrapped text (excluding the added characters)
76
+ requestAnimationFrame(() => {
77
+ target.setSelectionRange(selectionStart + 1, selectionEnd + 1);
78
+ });
79
+ return true;
80
+ }
81
+
82
+ // Insert both opening and closing characters
83
+ const newValue = textValue.substring(0, selectionStart) + event.key + closingChar + textValue.substring(selectionEnd);
84
+ target.value = newValue;
85
+ target.dispatchEvent(new Event("input", { bubbles: true }));
86
+
87
+ // Position cursor between the pair
88
+ requestAnimationFrame(() => {
89
+ target.setSelectionRange(selectionStart + 1, selectionStart + 1);
90
+ });
91
+ return true;
92
+ }
93
+
94
+ function handleDeindent(target: HTMLTextAreaElement, textValue: string, selectionStart: number, selectionEnd: number) {
95
+ // Single cursor position
96
+ if (selectionStart === selectionEnd) {
97
+ const lineStart = textValue.lastIndexOf("\n", selectionStart - 1) + 1;
98
+ const lineText = textValue.substring(lineStart, selectionStart);
99
+ const leadingWhitespace = lineText.match(/^(\s*)/)?.[1] || "";
100
+
101
+ if (leadingWhitespace.length === 0) return;
102
+
103
+ // Remove one tab or up to 2 spaces
104
+ let charsToRemove = 1;
105
+ if (leadingWhitespace.startsWith("\t")) {
106
+ charsToRemove = 1;
107
+ } else if (leadingWhitespace.startsWith(" ")) {
108
+ charsToRemove = 2;
109
+ } else if (leadingWhitespace.startsWith(" ")) {
110
+ charsToRemove = 1;
111
+ }
112
+
113
+ const newValue = textValue.substring(0, lineStart) + textValue.substring(lineStart + charsToRemove);
114
+ target.value = newValue;
115
+ target.dispatchEvent(new Event("input", { bubbles: true }));
116
+
117
+ // Move cursor back
118
+ requestAnimationFrame(() => {
119
+ target.setSelectionRange(selectionStart - charsToRemove, selectionStart - charsToRemove);
120
+ });
121
+ return;
122
+ }
123
+
124
+ // Selection: deindent all lines
125
+ const beforeSelection = textValue.substring(0, selectionStart);
126
+ const afterSelection = textValue.substring(selectionEnd);
127
+
128
+ const lineStartPos = beforeSelection.lastIndexOf("\n") + 1;
129
+ const fullSelection = textValue.substring(lineStartPos, selectionEnd);
130
+ const fullLines = fullSelection.split("\n");
131
+
132
+ const deindentedLines = fullLines.map((line) => {
133
+ const leadingWhitespace = line.match(/^(\s*)/)?.[1] || "";
134
+ if (leadingWhitespace.length === 0) return line;
135
+
136
+ if (leadingWhitespace.startsWith("\t")) {
137
+ return line.substring(1);
138
+ }
139
+ if (leadingWhitespace.startsWith(" ")) {
140
+ return line.substring(2);
141
+ }
142
+ if (leadingWhitespace.startsWith(" ")) {
143
+ return line.substring(1);
144
+ }
145
+ return line;
146
+ });
147
+
148
+ const newValue = textValue.substring(0, lineStartPos) + deindentedLines.join("\n") + afterSelection;
149
+ target.value = newValue;
150
+ target.dispatchEvent(new Event("input", { bubbles: true }));
151
+
152
+ // Maintain selection
153
+ requestAnimationFrame(() => {
154
+ const newSelectionStart = lineStartPos;
155
+ const newSelectionEnd = lineStartPos + deindentedLines.join("\n").length;
156
+ target.setSelectionRange(newSelectionStart, newSelectionEnd);
157
+ });
158
+ }
159
+
160
+ function handleIndent(target: HTMLTextAreaElement, textValue: string, selectionStart: number, selectionEnd: number) {
161
+ // Single cursor: insert tab at cursor
162
+ if (selectionStart === selectionEnd) {
163
+ const newValue = textValue.substring(0, selectionStart) + "\t" + textValue.substring(selectionEnd);
164
+ target.value = newValue;
165
+ target.dispatchEvent(new Event("input", { bubbles: true }));
166
+
167
+ // Move cursor after tab
168
+ requestAnimationFrame(() => {
169
+ target.setSelectionRange(selectionStart + 1, selectionStart + 1);
170
+ });
171
+ return;
172
+ }
173
+
174
+ // Selection: indent all lines
175
+ const beforeSelection = textValue.substring(0, selectionStart);
176
+ const afterSelection = textValue.substring(selectionEnd);
177
+
178
+ const lineStartPos = beforeSelection.lastIndexOf("\n") + 1;
179
+ const fullSelection = textValue.substring(lineStartPos, selectionEnd);
180
+ const lines = fullSelection.split("\n");
181
+
182
+ const indentedLines = lines.map((line) => "\t" + line);
183
+
184
+ const newValue = textValue.substring(0, lineStartPos) + indentedLines.join("\n") + afterSelection;
185
+ target.value = newValue;
186
+ target.dispatchEvent(new Event("input", { bubbles: true }));
187
+
188
+ // Maintain selection
189
+ requestAnimationFrame(() => {
190
+ const newSelectionStart = lineStartPos;
191
+ const newSelectionEnd = lineStartPos + indentedLines.join("\n").length;
192
+ target.setSelectionRange(newSelectionStart, newSelectionEnd);
193
+ });
194
+ }
195
+
196
+ function handleEnterKey(
197
+ event: KeyboardEvent,
198
+ target: HTMLTextAreaElement,
199
+ textValue: string,
200
+ selectionStart: number,
201
+ selectionEnd: number,
202
+ ) {
203
+ event.preventDefault();
204
+
205
+ // Get current line
206
+ const lineStart = textValue.lastIndexOf("\n", selectionStart - 1) + 1;
207
+ const lineEnd = textValue.indexOf("\n", selectionStart);
208
+ const currentLine = textValue.substring(lineStart, lineEnd === -1 ? textValue.length : lineEnd);
209
+
210
+ // Get current indentation
211
+ const currentIndent = getIndentation(currentLine);
212
+
213
+ // Check if previous character is { or [
214
+ const charBeforeCursor = textValue[selectionStart - 1];
215
+ const charAfterCursor = textValue[selectionStart];
216
+
217
+ if (charBeforeCursor !== "{" && charBeforeCursor !== "[") {
218
+ // Just insert newline with same indentation
219
+ const insertion = "\n" + currentIndent;
220
+ const newValue = textValue.substring(0, selectionStart) + insertion + textValue.substring(selectionEnd);
221
+ target.value = newValue;
222
+ target.dispatchEvent(new Event("input", { bubbles: true }));
223
+
224
+ requestAnimationFrame(() => {
225
+ target.setSelectionRange(selectionStart + insertion.length, selectionStart + insertion.length);
226
+ });
227
+ return;
228
+ }
229
+
230
+ // Insert newline with increased indent, then another newline with current indent
231
+ const extraIndent = "\t";
232
+ let insertion = "\n" + currentIndent + extraIndent;
233
+ const cursorOffset = insertion.length;
234
+
235
+ // If next char is } or ], add closing line
236
+ if (charAfterCursor === "}" || charAfterCursor === "]") {
237
+ insertion += "\n" + currentIndent;
238
+ }
239
+
240
+ const newValue = textValue.substring(0, selectionStart) + insertion + textValue.substring(selectionEnd);
241
+ target.value = newValue;
242
+ target.dispatchEvent(new Event("input", { bubbles: true }));
243
+
244
+ requestAnimationFrame(() => {
245
+ target.setSelectionRange(selectionStart + cursorOffset, selectionStart + cursorOffset);
246
+ });
247
+ }
248
+
249
+ function handleClosingBrace(
250
+ event: KeyboardEvent,
251
+ target: HTMLTextAreaElement,
252
+ textValue: string,
253
+ selectionStart: number,
254
+ selectionEnd: number,
255
+ ) {
256
+ // Get current line up to cursor
257
+ const lineStart = textValue.lastIndexOf("\n", selectionStart - 1) + 1;
258
+ const lineBeforeCursor = textValue.substring(lineStart, selectionStart);
259
+
260
+ // Check if line only contains whitespace
261
+ if (!/^\s*$/.test(lineBeforeCursor) || lineBeforeCursor.length === 0) return;
262
+
263
+ event.preventDefault();
264
+
265
+ const closingChar = event.key; // Either } or ]
266
+
267
+ // Remove one level of indentation
268
+ const indentMatch = lineBeforeCursor.match(/^(\s*)/);
269
+ const indent = indentMatch ? indentMatch[1] : "";
270
+
271
+ if (indent.length === 0) {
272
+ // No indentation to remove, just insert closing character
273
+ const newValue = textValue.substring(0, selectionStart) + closingChar + textValue.substring(selectionEnd);
274
+ target.value = newValue;
275
+ target.dispatchEvent(new Event("input", { bubbles: true }));
276
+
277
+ requestAnimationFrame(() => {
278
+ target.setSelectionRange(selectionStart + 1, selectionStart + 1);
279
+ });
280
+ return;
281
+ }
282
+
283
+ let charsToRemove = 1;
284
+ if (indent.endsWith("\t")) {
285
+ charsToRemove = 1;
286
+ } else if (indent.length >= 2 && indent.endsWith(" ")) {
287
+ charsToRemove = 2;
288
+ } else if (indent.endsWith(" ")) {
289
+ charsToRemove = 1;
290
+ }
291
+
292
+ // Remove indentation and add closing character
293
+ const newValue =
294
+ textValue.substring(0, selectionStart - charsToRemove) + closingChar + textValue.substring(selectionEnd);
295
+ target.value = newValue;
296
+ target.dispatchEvent(new Event("input", { bubbles: true }));
297
+
298
+ requestAnimationFrame(() => {
299
+ target.setSelectionRange(selectionStart - charsToRemove + 1, selectionStart - charsToRemove + 1);
300
+ });
301
+ }
302
+
303
+ export const jsonTextarea: Action<HTMLTextAreaElement, JsonTextareaParams | undefined> = (node, params) => {
304
+ function handleKeydown(event: KeyboardEvent) {
305
+ const target = event.target as HTMLTextAreaElement;
306
+ const { selectionStart, selectionEnd, value: textValue } = target;
307
+
308
+ // Escape to blur and move to next/previous focusable element
309
+ if (event.key === "Escape") {
310
+ event.preventDefault();
311
+
312
+ // Call custom escape handler if provided
313
+ if (params?.onescape) {
314
+ params.onescape();
315
+ return;
316
+ }
317
+
318
+ target.blur();
319
+
320
+ // Find all focusable elements
321
+ const focusableElements = Array.from(
322
+ document.querySelectorAll<HTMLElement>(
323
+ 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])',
324
+ ),
325
+ ).filter((el) => !el.hasAttribute("disabled") && el.offsetParent !== null);
326
+
327
+ const currentIndex = focusableElements.indexOf(target);
328
+
329
+ // Shift+Escape goes backward, Escape goes forward
330
+ const targetElement = event.shiftKey ? focusableElements[currentIndex - 1] : focusableElements[currentIndex + 1];
331
+
332
+ if (targetElement) {
333
+ targetElement.focus();
334
+ }
335
+ return;
336
+ }
337
+
338
+ // Ctrl+Enter to submit
339
+ if (event.ctrlKey && event.key === "Enter") {
340
+ event.preventDefault();
341
+ params?.onsubmit?.();
342
+ return;
343
+ }
344
+
345
+ // Skip over closing characters if they're already there
346
+ if (handleSkipClosing(event, target, textValue, selectionStart, selectionEnd)) {
347
+ return;
348
+ }
349
+
350
+ // Auto-pairing for quotes and braces
351
+ if (handleAutoPairing(event, target, textValue, selectionStart, selectionEnd)) {
352
+ return;
353
+ }
354
+
355
+ // Tab key handling
356
+ if (event.key !== "Tab" || event.ctrlKey || event.altKey || event.metaKey) {
357
+ // Enter key handling
358
+ if (event.key === "Enter" && !event.ctrlKey && !event.shiftKey && !event.altKey && !event.metaKey) {
359
+ handleEnterKey(event, target, textValue, selectionStart, selectionEnd);
360
+ return;
361
+ }
362
+
363
+ // } and ] key handling - auto-deindent
364
+ if (
365
+ (event.key === "}" || event.key === "]") &&
366
+ !event.ctrlKey &&
367
+ !event.shiftKey &&
368
+ !event.altKey &&
369
+ !event.metaKey
370
+ ) {
371
+ handleClosingBrace(event, target, textValue, selectionStart, selectionEnd);
372
+ }
373
+ return;
374
+ }
375
+
376
+ event.preventDefault();
377
+
378
+ // Shift+Tab: deindent
379
+ if (event.shiftKey) {
380
+ handleDeindent(target, textValue, selectionStart, selectionEnd);
381
+ return;
382
+ }
383
+
384
+ // Tab: indent
385
+ handleIndent(target, textValue, selectionStart, selectionEnd);
386
+ }
387
+
388
+ node.addEventListener("keydown", handleKeydown);
389
+
390
+ return {
391
+ destroy() {
392
+ node.removeEventListener("keydown", handleKeydown);
393
+ },
394
+ };
395
+ };
@@ -1,71 +1,20 @@
1
1
  <script lang="ts">
2
2
  import { resolve } from "$app/paths";
3
3
  import { page } from "$app/state";
4
- import { serverName } from "$lib/utils/filters";
5
4
 
6
5
  interface BreadcrumbItem {
7
6
  label: string;
8
7
  href?: string;
9
8
  }
10
9
 
11
- function getBreadcrumbs(pathname: string, params: Record<string, string>): BreadcrumbItem[] {
12
- const breadcrumbs: BreadcrumbItem[] = [];
10
+ const breadcrumbs = $derived.by(() => {
11
+ const list = (page.data.breadcrumbs ?? []) as Array<{ label: string; path: string }>;
13
12
 
14
- // Parse the path segments
15
- const segments = pathname.split("/").filter(Boolean);
16
-
17
- if (segments.length === 0) {
18
- // We're at home, no breadcrumbs needed
19
- return [];
20
- }
21
-
22
- if (segments[0] === "servers" && segments.length >= 3) {
23
- const server = decodeURIComponent(params.server || "");
24
- const serverDisplayName = serverName(server);
25
-
26
- if (segments[2] === "databases") {
27
- // /servers/{server}/databases
28
- breadcrumbs.push({
29
- label: serverDisplayName,
30
- href: `/servers/${encodeURIComponent(server)}/databases`,
31
- });
32
-
33
- if (segments.length >= 5 && segments[3] && segments[4] === "collections") {
34
- const database = decodeURIComponent(params.database || "");
35
- // /servers/{server}/databases/{database}/collections
36
- breadcrumbs.push({
37
- label: database,
38
- href: `/servers/${encodeURIComponent(server)}/databases/${encodeURIComponent(database)}/collections`,
39
- });
40
-
41
- if (segments.length >= 6 && segments[5]) {
42
- const collection = decodeURIComponent(params.collection || "");
43
-
44
- if (segments.length === 6) {
45
- // /servers/{server}/databases/{database}/collections/{collection}
46
- breadcrumbs.push({
47
- label: collection,
48
- });
49
- } else if (segments.length >= 7 && segments[6] === "documents" && segments[7]) {
50
- // /servers/{server}/databases/{database}/collections/{collection}/documents/{document}
51
- breadcrumbs.push({
52
- label: collection,
53
- href: `/servers/${encodeURIComponent(server)}/databases/${encodeURIComponent(database)}/collections/${encodeURIComponent(collection)}`,
54
- });
55
-
56
- breadcrumbs.push({
57
- label: decodeURIComponent(params.document || "[Document]"),
58
- });
59
- }
60
- }
61
- }
62
- }
63
- }
64
-
65
- return breadcrumbs;
66
- }
67
-
68
- const breadcrumbs = $derived(getBreadcrumbs(page.url.pathname, page.params));
13
+ return list.reduce<BreadcrumbItem[]>(
14
+ (prev, curr) => [...prev, { label: curr.label, href: `${prev.at(-1)?.href ?? ""}${curr.path}` }],
15
+ [],
16
+ );
17
+ });
69
18
  </script>
70
19
 
71
20
  {#if breadcrumbs.length > 0}