mongoku 2.8.1 → 2.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/client/_app/immutable/assets/0.DTh4C4pw.css +1 -0
- package/build/client/_app/immutable/assets/0.DTh4C4pw.css.br +0 -0
- package/build/client/_app/immutable/assets/0.DTh4C4pw.css.gz +0 -0
- package/build/client/_app/immutable/chunks/-jLNyJzC.js +1 -0
- package/build/client/_app/immutable/chunks/-jLNyJzC.js.br +0 -0
- package/build/client/_app/immutable/chunks/-jLNyJzC.js.gz +0 -0
- package/build/client/_app/immutable/chunks/B-0CauNF.js +1 -0
- package/build/client/_app/immutable/chunks/B-0CauNF.js.br +0 -0
- package/build/client/_app/immutable/chunks/B-0CauNF.js.gz +0 -0
- package/build/client/_app/immutable/chunks/B-TH2U-E.js +1 -0
- package/build/client/_app/immutable/chunks/B-TH2U-E.js.br +0 -0
- package/build/client/_app/immutable/chunks/B-TH2U-E.js.gz +0 -0
- package/build/client/_app/immutable/chunks/BaCQ7DA8.js +66 -0
- package/build/client/_app/immutable/chunks/BaCQ7DA8.js.br +0 -0
- package/build/client/_app/immutable/chunks/BaCQ7DA8.js.gz +0 -0
- package/build/client/_app/immutable/chunks/BfsQcfVI.js +1 -0
- package/build/client/_app/immutable/chunks/BfsQcfVI.js.br +0 -0
- package/build/client/_app/immutable/chunks/BfsQcfVI.js.gz +0 -0
- package/build/client/_app/immutable/chunks/{Dbu5gl04.js → BnRtSpxa.js} +1 -1
- package/build/client/_app/immutable/chunks/BnRtSpxa.js.br +0 -0
- package/build/client/_app/immutable/chunks/BnRtSpxa.js.gz +0 -0
- package/build/client/_app/immutable/chunks/{B_7uoCj-.js → CWVg1wU_.js} +2 -2
- package/build/client/_app/immutable/chunks/CWVg1wU_.js.br +0 -0
- package/build/client/_app/immutable/chunks/CWVg1wU_.js.gz +0 -0
- package/build/client/_app/immutable/chunks/Cl89kjea.js +1 -0
- package/build/client/_app/immutable/chunks/Cl89kjea.js.br +0 -0
- package/build/client/_app/immutable/chunks/Cl89kjea.js.gz +0 -0
- package/build/client/_app/immutable/chunks/CynGo-ch.js +1 -0
- package/build/client/_app/immutable/chunks/CynGo-ch.js.br +0 -0
- package/build/client/_app/immutable/chunks/CynGo-ch.js.gz +0 -0
- package/build/client/_app/immutable/chunks/{DZ3j8h_f.js → CzuLYUff.js} +1 -1
- package/build/client/_app/immutable/chunks/CzuLYUff.js.br +0 -0
- package/build/client/_app/immutable/chunks/CzuLYUff.js.gz +0 -0
- package/build/client/_app/immutable/chunks/D1_vCvEb.js +1 -0
- package/build/client/_app/immutable/chunks/D1_vCvEb.js.br +0 -0
- package/build/client/_app/immutable/chunks/D1_vCvEb.js.gz +0 -0
- package/build/client/_app/immutable/chunks/D2Q18L5i.js +1 -0
- package/build/client/_app/immutable/chunks/D2Q18L5i.js.br +0 -0
- package/build/client/_app/immutable/chunks/D2Q18L5i.js.gz +0 -0
- package/build/client/_app/immutable/chunks/D899Ie42.js +1 -0
- package/build/client/_app/immutable/chunks/D899Ie42.js.br +0 -0
- package/build/client/_app/immutable/chunks/D899Ie42.js.gz +0 -0
- package/build/client/_app/immutable/chunks/DIjqwnsi.js +1 -0
- package/build/client/_app/immutable/chunks/DIjqwnsi.js.br +0 -0
- package/build/client/_app/immutable/chunks/DIjqwnsi.js.gz +0 -0
- package/build/client/_app/immutable/chunks/{CafiCU8Z.js → DaDQ7m8i.js} +9 -9
- package/build/client/_app/immutable/chunks/DaDQ7m8i.js.br +0 -0
- package/build/client/_app/immutable/chunks/DaDQ7m8i.js.gz +0 -0
- package/build/client/_app/immutable/chunks/{ULh2o3ji.js → DjUt71lH.js} +1 -1
- package/build/client/_app/immutable/chunks/DjUt71lH.js.br +0 -0
- package/build/client/_app/immutable/chunks/DjUt71lH.js.gz +0 -0
- package/build/client/_app/immutable/chunks/DkIGOVHS.js +4 -0
- package/build/client/_app/immutable/chunks/DkIGOVHS.js.br +0 -0
- package/build/client/_app/immutable/chunks/DkIGOVHS.js.gz +0 -0
- package/build/client/_app/immutable/chunks/Hg2DaShQ.js +1 -0
- package/build/client/_app/immutable/chunks/Hg2DaShQ.js.br +3 -0
- package/build/client/_app/immutable/chunks/Hg2DaShQ.js.gz +0 -0
- package/build/client/_app/immutable/chunks/KvnnxfV5.js +1 -0
- package/build/client/_app/immutable/chunks/KvnnxfV5.js.br +0 -0
- package/build/client/_app/immutable/chunks/KvnnxfV5.js.gz +0 -0
- package/build/client/_app/immutable/chunks/{CETiZ6GF.js → NycVVWZD.js} +1 -1
- package/build/client/_app/immutable/chunks/NycVVWZD.js.br +0 -0
- package/build/client/_app/immutable/chunks/NycVVWZD.js.gz +0 -0
- package/build/client/_app/immutable/chunks/{Dv9wDVNU.js → TfiCUZYY.js} +1 -1
- package/build/client/_app/immutable/chunks/TfiCUZYY.js.br +0 -0
- package/build/client/_app/immutable/chunks/TfiCUZYY.js.gz +0 -0
- package/build/client/_app/immutable/chunks/TxmsiDxf.js +1 -0
- package/build/client/_app/immutable/chunks/TxmsiDxf.js.br +0 -0
- package/build/client/_app/immutable/chunks/TxmsiDxf.js.gz +0 -0
- package/build/client/_app/immutable/chunks/ogOVEqzG.js +1 -0
- package/build/client/_app/immutable/chunks/ogOVEqzG.js.br +0 -0
- package/build/client/_app/immutable/chunks/ogOVEqzG.js.gz +0 -0
- package/build/client/_app/immutable/chunks/tqAjkrD5.js +1 -0
- package/build/client/_app/immutable/chunks/tqAjkrD5.js.br +0 -0
- package/build/client/_app/immutable/chunks/tqAjkrD5.js.gz +0 -0
- package/build/client/_app/immutable/chunks/wZ9dd4xr.js +2 -0
- package/build/client/_app/immutable/chunks/wZ9dd4xr.js.br +0 -0
- package/build/client/_app/immutable/chunks/wZ9dd4xr.js.gz +0 -0
- package/build/client/_app/immutable/entry/app.DKM881FC.js +2 -0
- package/build/client/_app/immutable/entry/app.DKM881FC.js.br +0 -0
- package/build/client/_app/immutable/entry/app.DKM881FC.js.gz +0 -0
- package/build/client/_app/immutable/entry/start.BMV36X_I.js +1 -0
- package/build/client/_app/immutable/entry/start.BMV36X_I.js.br +0 -0
- package/build/client/_app/immutable/entry/start.BMV36X_I.js.gz +0 -0
- package/build/client/_app/immutable/nodes/0.xAEfnyVv.js +1 -0
- package/build/client/_app/immutable/nodes/0.xAEfnyVv.js.br +0 -0
- package/build/client/_app/immutable/nodes/0.xAEfnyVv.js.gz +0 -0
- package/build/client/_app/immutable/nodes/1.DJI4SFHI.js +1 -0
- package/build/client/_app/immutable/nodes/1.DJI4SFHI.js.br +0 -0
- package/build/client/_app/immutable/nodes/1.DJI4SFHI.js.gz +0 -0
- package/build/client/_app/immutable/nodes/10.B9mmyl9C.js +2 -0
- package/build/client/_app/immutable/nodes/10.B9mmyl9C.js.br +0 -0
- package/build/client/_app/immutable/nodes/10.B9mmyl9C.js.gz +0 -0
- package/build/client/_app/immutable/nodes/11.BJVYZRNF.js +6 -0
- package/build/client/_app/immutable/nodes/11.BJVYZRNF.js.br +0 -0
- package/build/client/_app/immutable/nodes/11.BJVYZRNF.js.gz +0 -0
- package/build/client/_app/immutable/nodes/{12.PoZV4wBT.js → 12.BIVbh2K8.js} +1 -1
- package/build/client/_app/immutable/nodes/12.BIVbh2K8.js.br +0 -0
- package/build/client/_app/immutable/nodes/12.BIVbh2K8.js.gz +0 -0
- package/build/client/_app/immutable/nodes/13.CuqM9sa_.js +1 -0
- package/build/client/_app/immutable/nodes/13.CuqM9sa_.js.br +0 -0
- package/build/client/_app/immutable/nodes/13.CuqM9sa_.js.gz +0 -0
- package/build/client/_app/immutable/nodes/14.Cku4UiID.js +65 -0
- package/build/client/_app/immutable/nodes/14.Cku4UiID.js.br +0 -0
- package/build/client/_app/immutable/nodes/14.Cku4UiID.js.gz +0 -0
- package/build/client/_app/immutable/nodes/15.CFozZIMA.js +1 -0
- package/build/client/_app/immutable/nodes/15.CFozZIMA.js.br +0 -0
- package/build/client/_app/immutable/nodes/15.CFozZIMA.js.gz +0 -0
- package/build/client/_app/immutable/nodes/{2.C6NzDBVE.js → 2.CdWjCbJf.js} +1 -1
- package/build/client/_app/immutable/nodes/2.CdWjCbJf.js.br +0 -0
- package/build/client/_app/immutable/nodes/2.CdWjCbJf.js.gz +0 -0
- package/build/client/_app/immutable/nodes/{3.CZJqJ4La.js → 3.BIfBaSHs.js} +1 -1
- package/build/client/_app/immutable/nodes/3.BIfBaSHs.js.br +1 -0
- package/build/client/_app/immutable/nodes/3.BIfBaSHs.js.gz +0 -0
- package/build/client/_app/immutable/nodes/{4.CNe3XPNo.js → 4.D_Olflem.js} +1 -1
- package/build/client/_app/immutable/nodes/4.D_Olflem.js.br +0 -0
- package/build/client/_app/immutable/nodes/4.D_Olflem.js.gz +0 -0
- package/build/client/_app/immutable/nodes/{5.BWhhv567.js → 5.BjQaqBuw.js} +1 -1
- package/build/client/_app/immutable/nodes/5.BjQaqBuw.js.br +0 -0
- package/build/client/_app/immutable/nodes/5.BjQaqBuw.js.gz +0 -0
- package/build/client/_app/immutable/nodes/{7.CTCgtWr5.js → 7.B2HL850y.js} +1 -1
- package/build/client/_app/immutable/nodes/7.B2HL850y.js.br +0 -0
- package/build/client/_app/immutable/nodes/7.B2HL850y.js.gz +0 -0
- package/build/client/_app/immutable/nodes/8.R4oSBMsW.js +2 -0
- package/build/client/_app/immutable/nodes/8.R4oSBMsW.js.br +0 -0
- package/build/client/_app/immutable/nodes/8.R4oSBMsW.js.gz +0 -0
- package/build/client/_app/immutable/nodes/{9.DgUUrJMM.js → 9.gCKAeDLD.js} +1 -1
- package/build/client/_app/immutable/nodes/9.gCKAeDLD.js.br +0 -0
- package/build/client/_app/immutable/nodes/9.gCKAeDLD.js.gz +0 -0
- package/build/client/_app/version.json +1 -1
- package/build/client/_app/version.json.br +0 -0
- package/build/client/_app/version.json.gz +0 -0
- package/build/server/chunks/0-DHpbgO4k.js +31 -0
- package/build/server/chunks/{0-CKG6FzOP.js.map → 0-DHpbgO4k.js.map} +1 -1
- package/build/server/chunks/1-qCdcNckL.js +9 -0
- package/build/server/chunks/1-qCdcNckL.js.map +1 -0
- package/build/server/chunks/{10-DhUkYynY.js → 10-DADbl5RU.js} +3 -3
- package/build/server/chunks/{10-DhUkYynY.js.map → 10-DADbl5RU.js.map} +1 -1
- package/build/server/chunks/{11-BNbY7gn2.js → 11-B5XzpQJ2.js} +5 -4
- package/build/server/chunks/11-B5XzpQJ2.js.map +1 -0
- package/build/server/chunks/{12-DBj8btwS.js → 12-DvEgVREo.js} +3 -3
- package/build/server/chunks/{12-DBj8btwS.js.map → 12-DvEgVREo.js.map} +1 -1
- package/build/server/chunks/{13-EXQa77Y1.js → 13-BhmqzR8h.js} +5 -4
- package/build/server/chunks/13-BhmqzR8h.js.map +1 -0
- package/build/server/chunks/{14-DHzR9sir.js → 14-BfgW3WwW.js} +5 -4
- package/build/server/chunks/14-BfgW3WwW.js.map +1 -0
- package/build/server/chunks/15-EvY9zrFS.js +67 -0
- package/build/server/chunks/15-EvY9zrFS.js.map +1 -0
- package/build/server/chunks/{2-BNTmkYSf.js → 2-5hqMVf4i.js} +3 -3
- package/build/server/chunks/{2-BNTmkYSf.js.map → 2-5hqMVf4i.js.map} +1 -1
- package/build/server/chunks/{3-ClKd4dXQ.js → 3-DIscxOEl.js} +3 -3
- package/build/server/chunks/{3-ClKd4dXQ.js.map → 3-DIscxOEl.js.map} +1 -1
- package/build/server/chunks/{4-BSPVNKkN.js → 4-_oEOFnHF.js} +3 -3
- package/build/server/chunks/{4-BSPVNKkN.js.map → 4-_oEOFnHF.js.map} +1 -1
- package/build/server/chunks/{5-BzxZlQk0.js → 5-qiB9L-y2.js} +3 -3
- package/build/server/chunks/{5-BzxZlQk0.js.map → 5-qiB9L-y2.js.map} +1 -1
- package/build/server/chunks/{6-Bw8JUxiD.js → 6-eXO6RVDu.js} +4 -4
- package/build/server/chunks/{6-Bw8JUxiD.js.map → 6-eXO6RVDu.js.map} +1 -1
- package/build/server/chunks/{7-QcJoMaSg.js → 7-DVs6miRk.js} +7 -7
- package/build/server/chunks/{7-QcJoMaSg.js.map → 7-DVs6miRk.js.map} +1 -1
- package/build/server/chunks/{8-UCTaZB_Z.js → 8-DsmWMnBl.js} +3 -3
- package/build/server/chunks/{8-UCTaZB_Z.js.map → 8-DsmWMnBl.js.map} +1 -1
- package/build/server/chunks/{9-C0szOSjZ.js → 9-DOuKepr0.js} +3 -3
- package/build/server/chunks/{9-C0szOSjZ.js.map → 9-DOuKepr0.js.map} +1 -1
- package/build/server/chunks/{JsonValue-CTg4aH_w.js → JsonValue-CGVfzyTL.js} +32 -32
- package/build/server/chunks/JsonValue-CGVfzyTL.js.map +1 -0
- package/build/server/chunks/{Modal-yO0qzufQ.js → Modal-D2E5OLRi.js} +9 -9
- package/build/server/chunks/Modal-D2E5OLRi.js.map +1 -0
- package/build/server/chunks/{Panel-D9GzVDDt.js → Panel-C6VWd6JD.js} +9 -9
- package/build/server/chunks/Panel-C6VWd6JD.js.map +1 -0
- package/build/server/chunks/{PrettyJson-BVgLycwy.js → PrettyJson-0NvyC3vB.js} +43 -21
- package/build/server/chunks/PrettyJson-0NvyC3vB.js.map +1 -0
- package/build/server/chunks/{Tooltip-D2BX7dwq.js → Tooltip-OVylvwfb.js} +5 -5
- package/build/server/chunks/Tooltip-OVylvwfb.js.map +1 -0
- package/build/server/chunks/{TooltipTable-91W9LxGR.js → TooltipTable-CLglfpck.js} +6 -6
- package/build/server/chunks/TooltipTable-CLglfpck.js.map +1 -0
- package/build/server/chunks/{_layout.svelte-BFxKanne.js → _layout.svelte-CLPxHDiP.js} +24 -24
- package/build/server/chunks/_layout.svelte-CLPxHDiP.js.map +1 -0
- package/build/server/chunks/{_page.svelte-CYgL8X_3.js → _page.svelte-BPcsZPKb.js} +21 -20
- package/build/server/chunks/_page.svelte-BPcsZPKb.js.map +1 -0
- package/build/server/chunks/{_page.svelte-BkyGMJtY.js → _page.svelte-BS4_Zesn.js} +27 -26
- package/build/server/chunks/_page.svelte-BS4_Zesn.js.map +1 -0
- package/build/server/chunks/{_page.svelte-Q0qOjc1K.js → _page.svelte-Bx5MBXSd.js} +23 -22
- package/build/server/chunks/_page.svelte-Bx5MBXSd.js.map +1 -0
- package/build/server/chunks/{_page.svelte-CSuE9bVi.js → _page.svelte-C3QVwl-z.js} +5 -5
- package/build/server/chunks/{_page.svelte-CSuE9bVi.js.map → _page.svelte-C3QVwl-z.js.map} +1 -1
- package/build/server/chunks/{_page.svelte-DybQp3Hh.js → _page.svelte-CM6QtCvm.js} +26 -25
- package/build/server/chunks/_page.svelte-CM6QtCvm.js.map +1 -0
- package/build/server/chunks/{_page.svelte-DEuOrgce.js → _page.svelte-Cai_1P5J.js} +58 -57
- package/build/server/chunks/_page.svelte-Cai_1P5J.js.map +1 -0
- package/build/server/chunks/_page.svelte-Cy0ShxWk.js +135 -0
- package/build/server/chunks/_page.svelte-Cy0ShxWk.js.map +1 -0
- package/build/server/chunks/{_page.svelte-BE3IXD7W.js → _page.svelte-DFg9NEZU.js} +52 -51
- package/build/server/chunks/_page.svelte-DFg9NEZU.js.map +1 -0
- package/build/server/chunks/{_page.svelte-BimaUmmG.js → _page.svelte-yY_cbSNt.js} +27 -26
- package/build/server/chunks/_page.svelte-yY_cbSNt.js.map +1 -0
- package/build/server/chunks/{_server.ts-CNiqI4C6.js → _server.ts-CEBmCzTO.js} +5 -5
- package/build/server/chunks/{_server.ts-CNiqI4C6.js.map → _server.ts-CEBmCzTO.js.map} +1 -1
- package/build/server/chunks/{_server.ts-OSPJ0dek.js → _server.ts-CoUHVeKI.js} +5 -5
- package/build/server/chunks/{_server.ts-OSPJ0dek.js.map → _server.ts-CoUHVeKI.js.map} +1 -1
- package/build/server/chunks/{_server.ts-CHqxLmE4.js → _server.ts-i-glbZtX.js} +4 -4
- package/build/server/chunks/{_server.ts-CHqxLmE4.js.map → _server.ts-i-glbZtX.js.map} +1 -1
- package/build/server/chunks/{async-lVJA8xJZ.js → async-DUoD1OpG.js} +2 -1
- package/build/server/chunks/async-DUoD1OpG.js.map +1 -0
- package/build/server/chunks/client-COtw9Xqw.js +7 -0
- package/build/server/chunks/{client-C7bEwskR.js.map → client-COtw9Xqw.js.map} +1 -1
- package/build/server/chunks/{client2-DcCKOWWC.js → client2-BIa3wTXU.js} +5 -5
- package/build/server/chunks/client2-BIa3wTXU.js.map +1 -0
- package/build/server/chunks/error.svelte-DUZ2SYyF.js +18 -0
- package/build/server/chunks/{error.svelte-Bk-0XnBt.js.map → error.svelte-DUZ2SYyF.js.map} +1 -1
- package/build/server/chunks/{hooks.server-ChbJBVwm.js → hooks.server-BiUSRqj1.js} +4 -4
- package/build/server/chunks/{hooks.server-ChbJBVwm.js.map → hooks.server-BiUSRqj1.js.map} +1 -1
- package/build/server/chunks/{index-CC9WtE-y.js → index-CtYzvcG6.js} +2 -2
- package/build/server/chunks/index-CtYzvcG6.js.map +1 -0
- package/build/server/chunks/{index-wpIsICWW.js → index-NcxaM188.js} +21 -4
- package/build/server/chunks/index-NcxaM188.js.map +1 -0
- package/build/server/chunks/{index2-DMabdSHV.js → index2-B0RgZaJY.js} +3 -3
- package/build/server/chunks/{index2-DMabdSHV.js.map → index2-B0RgZaJY.js.map} +1 -1
- package/build/server/chunks/{layout.svelte-CJcHX-Na.js → layout.svelte-PFROMnUZ.js} +2 -2
- package/build/server/chunks/{layout.svelte-CJcHX-Na.js.map → layout.svelte-PFROMnUZ.js.map} +1 -1
- package/build/server/chunks/{oauth-BbSyq_Sb.js → oauth-D6jTWKFd.js} +2 -2
- package/build/server/chunks/{oauth-BbSyq_Sb.js.map → oauth-D6jTWKFd.js.map} +1 -1
- package/build/server/chunks/{remote-xxtqbu-DU1VUIfB.js → remote-xxtqbu-CmaCzxbq.js} +8 -7
- package/build/server/chunks/remote-xxtqbu-CmaCzxbq.js.map +1 -0
- package/build/server/chunks/{url-hmE1zcJ6.js → root-otUAnOAR.js} +1771 -1355
- package/build/server/chunks/root-otUAnOAR.js.map +1 -0
- package/build/server/chunks/{routing-CYknP78v.js → routing-EDfUNu8L.js} +2 -2
- package/build/server/chunks/{routing-CYknP78v.js.map → routing-EDfUNu8L.js.map} +1 -1
- package/build/server/chunks/schema-BZonjzNJ.js +315 -0
- package/build/server/chunks/schema-BZonjzNJ.js.map +1 -0
- package/build/server/chunks/{server2-uigtM6st.js → server2-D_y4YbpC.js} +8 -3
- package/build/server/chunks/server2-D_y4YbpC.js.map +1 -0
- package/build/server/chunks/{servers.remote-ChLjCujn.js → servers.remote-W2x65uTK.js} +407 -100
- package/build/server/chunks/servers.remote-W2x65uTK.js.map +1 -0
- package/build/server/chunks/{shared-BqTYMAzZ.js → shared-DlqhoNLb.js} +321 -127
- package/build/server/chunks/shared-DlqhoNLb.js.map +1 -0
- package/build/server/chunks/state.svelte-Bj5yxNNk.js +10 -0
- package/build/server/chunks/state.svelte-Bj5yxNNk.js.map +1 -0
- package/build/server/chunks/{utils2-kjxf7BZO.js → utils-BQzn9ikS.js} +2 -3
- package/build/server/chunks/utils-BQzn9ikS.js.map +1 -0
- package/build/server/index.js +322 -117
- package/build/server/index.js.map +1 -1
- package/build/server/manifest.js +28 -20
- package/build/server/manifest.js.map +1 -1
- package/package.json +5 -2
- package/src/api/servers.remote.ts +60 -0
- package/src/lib/components/PrettyJson.svelte +33 -10
- package/src/lib/server/mongo.ts +1 -1
- package/src/lib/server/schema.ts +499 -0
- package/src/routes/servers/[server]/databases/[database]/collections/[collection]/documents/+page.ts +1 -0
- package/src/routes/servers/[server]/databases/[database]/collections/[collection]/indexes/+page.ts +1 -0
- package/src/routes/servers/[server]/databases/[database]/collections/[collection]/mappings/+page.ts +1 -0
- package/src/routes/servers/[server]/databases/[database]/collections/[collection]/schema/+page.server.ts +25 -0
- package/src/routes/servers/[server]/databases/[database]/collections/[collection]/schema/+page.svelte +429 -0
- package/src/routes/servers/[server]/databases/[database]/collections/[collection]/schema/+page.ts +11 -0
- package/build/client/_app/immutable/assets/0.CdYhspVa.css +0 -1
- package/build/client/_app/immutable/assets/0.CdYhspVa.css.br +0 -0
- package/build/client/_app/immutable/assets/0.CdYhspVa.css.gz +0 -0
- package/build/client/_app/immutable/chunks/B-uukkkJ.js +0 -1
- package/build/client/_app/immutable/chunks/B-uukkkJ.js.br +0 -0
- package/build/client/_app/immutable/chunks/B-uukkkJ.js.gz +0 -0
- package/build/client/_app/immutable/chunks/B59nRjE7.js +0 -1
- package/build/client/_app/immutable/chunks/B59nRjE7.js.br +0 -2
- package/build/client/_app/immutable/chunks/B59nRjE7.js.gz +0 -0
- package/build/client/_app/immutable/chunks/B_7uoCj-.js.br +0 -0
- package/build/client/_app/immutable/chunks/B_7uoCj-.js.gz +0 -0
- package/build/client/_app/immutable/chunks/BxKxqkS7.js +0 -4
- package/build/client/_app/immutable/chunks/BxKxqkS7.js.br +0 -0
- package/build/client/_app/immutable/chunks/BxKxqkS7.js.gz +0 -0
- package/build/client/_app/immutable/chunks/C1s4M21f.js +0 -1
- package/build/client/_app/immutable/chunks/C1s4M21f.js.br +0 -0
- package/build/client/_app/immutable/chunks/C1s4M21f.js.gz +0 -0
- package/build/client/_app/immutable/chunks/C6nv_pni.js +0 -1
- package/build/client/_app/immutable/chunks/C6nv_pni.js.br +0 -0
- package/build/client/_app/immutable/chunks/C6nv_pni.js.gz +0 -0
- package/build/client/_app/immutable/chunks/CETiZ6GF.js.br +0 -0
- package/build/client/_app/immutable/chunks/CETiZ6GF.js.gz +0 -0
- package/build/client/_app/immutable/chunks/CX0xC2bt.js +0 -1
- package/build/client/_app/immutable/chunks/CX0xC2bt.js.br +0 -0
- package/build/client/_app/immutable/chunks/CX0xC2bt.js.gz +0 -0
- package/build/client/_app/immutable/chunks/CafiCU8Z.js.br +0 -0
- package/build/client/_app/immutable/chunks/CafiCU8Z.js.gz +0 -0
- package/build/client/_app/immutable/chunks/DJHYr09v.js +0 -1
- package/build/client/_app/immutable/chunks/DJHYr09v.js.br +0 -0
- package/build/client/_app/immutable/chunks/DJHYr09v.js.gz +0 -0
- package/build/client/_app/immutable/chunks/DZ3j8h_f.js.br +0 -0
- package/build/client/_app/immutable/chunks/DZ3j8h_f.js.gz +0 -0
- package/build/client/_app/immutable/chunks/DZxZehvI.js +0 -1
- package/build/client/_app/immutable/chunks/DZxZehvI.js.br +0 -0
- package/build/client/_app/immutable/chunks/DZxZehvI.js.gz +0 -0
- package/build/client/_app/immutable/chunks/DaNl6Y92.js +0 -2
- package/build/client/_app/immutable/chunks/DaNl6Y92.js.br +0 -0
- package/build/client/_app/immutable/chunks/DaNl6Y92.js.gz +0 -0
- package/build/client/_app/immutable/chunks/Dbu5gl04.js.br +0 -0
- package/build/client/_app/immutable/chunks/Dbu5gl04.js.gz +0 -0
- package/build/client/_app/immutable/chunks/DczwA5Ds.js +0 -1
- package/build/client/_app/immutable/chunks/DczwA5Ds.js.br +0 -0
- package/build/client/_app/immutable/chunks/DczwA5Ds.js.gz +0 -0
- package/build/client/_app/immutable/chunks/DjlV9yev.js +0 -1
- package/build/client/_app/immutable/chunks/DjlV9yev.js.br +0 -0
- package/build/client/_app/immutable/chunks/DjlV9yev.js.gz +0 -0
- package/build/client/_app/immutable/chunks/DqCgzOHl.js +0 -1
- package/build/client/_app/immutable/chunks/DqCgzOHl.js.br +0 -0
- package/build/client/_app/immutable/chunks/DqCgzOHl.js.gz +0 -0
- package/build/client/_app/immutable/chunks/DskkUG-R.js +0 -41
- package/build/client/_app/immutable/chunks/DskkUG-R.js.br +0 -0
- package/build/client/_app/immutable/chunks/DskkUG-R.js.gz +0 -0
- package/build/client/_app/immutable/chunks/Dv9wDVNU.js.br +0 -0
- package/build/client/_app/immutable/chunks/Dv9wDVNU.js.gz +0 -0
- package/build/client/_app/immutable/chunks/DwvJoC1a.js +0 -1
- package/build/client/_app/immutable/chunks/DwvJoC1a.js.br +0 -0
- package/build/client/_app/immutable/chunks/DwvJoC1a.js.gz +0 -0
- package/build/client/_app/immutable/chunks/ULh2o3ji.js.br +0 -0
- package/build/client/_app/immutable/chunks/ULh2o3ji.js.gz +0 -0
- package/build/client/_app/immutable/chunks/V1mdyEl2.js +0 -1
- package/build/client/_app/immutable/chunks/V1mdyEl2.js.br +0 -0
- package/build/client/_app/immutable/chunks/V1mdyEl2.js.gz +0 -0
- package/build/client/_app/immutable/chunks/gjWX2x82.js +0 -1
- package/build/client/_app/immutable/chunks/gjWX2x82.js.br +0 -0
- package/build/client/_app/immutable/chunks/gjWX2x82.js.gz +0 -0
- package/build/client/_app/immutable/chunks/y5L2Na-S.js +0 -1
- package/build/client/_app/immutable/chunks/y5L2Na-S.js.br +0 -0
- package/build/client/_app/immutable/chunks/y5L2Na-S.js.gz +0 -0
- package/build/client/_app/immutable/entry/app.CobTjvr8.js +0 -2
- package/build/client/_app/immutable/entry/app.CobTjvr8.js.br +0 -0
- package/build/client/_app/immutable/entry/app.CobTjvr8.js.gz +0 -0
- package/build/client/_app/immutable/entry/start.BD32Z2Yy.js +0 -1
- package/build/client/_app/immutable/entry/start.BD32Z2Yy.js.br +0 -0
- package/build/client/_app/immutable/entry/start.BD32Z2Yy.js.gz +0 -0
- package/build/client/_app/immutable/nodes/0.CTNDfBi_.js +0 -1
- package/build/client/_app/immutable/nodes/0.CTNDfBi_.js.br +0 -0
- package/build/client/_app/immutable/nodes/0.CTNDfBi_.js.gz +0 -0
- package/build/client/_app/immutable/nodes/1.B0G4JtnR.js +0 -1
- package/build/client/_app/immutable/nodes/1.B0G4JtnR.js.br +0 -0
- package/build/client/_app/immutable/nodes/1.B0G4JtnR.js.gz +0 -0
- package/build/client/_app/immutable/nodes/10.DiOFtMHY.js +0 -2
- package/build/client/_app/immutable/nodes/10.DiOFtMHY.js.br +0 -0
- package/build/client/_app/immutable/nodes/10.DiOFtMHY.js.gz +0 -0
- package/build/client/_app/immutable/nodes/11.CcFuKX19.js +0 -6
- package/build/client/_app/immutable/nodes/11.CcFuKX19.js.br +0 -0
- package/build/client/_app/immutable/nodes/11.CcFuKX19.js.gz +0 -0
- package/build/client/_app/immutable/nodes/12.PoZV4wBT.js.br +0 -0
- package/build/client/_app/immutable/nodes/12.PoZV4wBT.js.gz +0 -0
- package/build/client/_app/immutable/nodes/13.BIZ8AY9M.js +0 -1
- package/build/client/_app/immutable/nodes/13.BIZ8AY9M.js.br +0 -0
- package/build/client/_app/immutable/nodes/13.BIZ8AY9M.js.gz +0 -0
- package/build/client/_app/immutable/nodes/14.DfoPNHw_.js +0 -65
- package/build/client/_app/immutable/nodes/14.DfoPNHw_.js.br +0 -0
- package/build/client/_app/immutable/nodes/14.DfoPNHw_.js.gz +0 -0
- package/build/client/_app/immutable/nodes/2.C6NzDBVE.js.br +0 -2
- package/build/client/_app/immutable/nodes/2.C6NzDBVE.js.gz +0 -0
- package/build/client/_app/immutable/nodes/3.CZJqJ4La.js.br +0 -0
- package/build/client/_app/immutable/nodes/3.CZJqJ4La.js.gz +0 -0
- package/build/client/_app/immutable/nodes/4.CNe3XPNo.js.br +0 -0
- package/build/client/_app/immutable/nodes/4.CNe3XPNo.js.gz +0 -0
- package/build/client/_app/immutable/nodes/5.BWhhv567.js.br +0 -0
- package/build/client/_app/immutable/nodes/5.BWhhv567.js.gz +0 -0
- package/build/client/_app/immutable/nodes/7.CTCgtWr5.js.br +0 -0
- package/build/client/_app/immutable/nodes/7.CTCgtWr5.js.gz +0 -0
- package/build/client/_app/immutable/nodes/8.B9VIkjMO.js +0 -2
- package/build/client/_app/immutable/nodes/8.B9VIkjMO.js.br +0 -0
- package/build/client/_app/immutable/nodes/8.B9VIkjMO.js.gz +0 -0
- package/build/client/_app/immutable/nodes/9.DgUUrJMM.js.br +0 -0
- package/build/client/_app/immutable/nodes/9.DgUUrJMM.js.gz +0 -0
- package/build/server/chunks/0-CKG6FzOP.js +0 -31
- package/build/server/chunks/1-BobnPu2T.js +0 -9
- package/build/server/chunks/1-BobnPu2T.js.map +0 -1
- package/build/server/chunks/11-BNbY7gn2.js.map +0 -1
- package/build/server/chunks/13-EXQa77Y1.js.map +0 -1
- package/build/server/chunks/14-DHzR9sir.js.map +0 -1
- package/build/server/chunks/JsonValue-CTg4aH_w.js.map +0 -1
- package/build/server/chunks/Modal-yO0qzufQ.js.map +0 -1
- package/build/server/chunks/Panel-D9GzVDDt.js.map +0 -1
- package/build/server/chunks/PrettyJson-BVgLycwy.js.map +0 -1
- package/build/server/chunks/Tooltip-D2BX7dwq.js.map +0 -1
- package/build/server/chunks/TooltipTable-91W9LxGR.js.map +0 -1
- package/build/server/chunks/_layout.svelte-BFxKanne.js.map +0 -1
- package/build/server/chunks/_page.svelte-BE3IXD7W.js.map +0 -1
- package/build/server/chunks/_page.svelte-BimaUmmG.js.map +0 -1
- package/build/server/chunks/_page.svelte-BkyGMJtY.js.map +0 -1
- package/build/server/chunks/_page.svelte-CYgL8X_3.js.map +0 -1
- package/build/server/chunks/_page.svelte-DEuOrgce.js.map +0 -1
- package/build/server/chunks/_page.svelte-DybQp3Hh.js.map +0 -1
- package/build/server/chunks/_page.svelte-Q0qOjc1K.js.map +0 -1
- package/build/server/chunks/async-lVJA8xJZ.js.map +0 -1
- package/build/server/chunks/client-C7bEwskR.js +0 -7
- package/build/server/chunks/client2-DcCKOWWC.js.map +0 -1
- package/build/server/chunks/error.svelte-Bk-0XnBt.js +0 -18
- package/build/server/chunks/index-CC9WtE-y.js.map +0 -1
- package/build/server/chunks/index-wpIsICWW.js.map +0 -1
- package/build/server/chunks/remote-xxtqbu-DU1VUIfB.js.map +0 -1
- package/build/server/chunks/server2-uigtM6st.js.map +0 -1
- package/build/server/chunks/servers.remote-ChLjCujn.js.map +0 -1
- package/build/server/chunks/shared-BqTYMAzZ.js.map +0 -1
- package/build/server/chunks/state.svelte-Dzb7Lf2r.js +0 -9
- package/build/server/chunks/state.svelte-Dzb7Lf2r.js.map +0 -1
- package/build/server/chunks/url-hmE1zcJ6.js.map +0 -1
- package/build/server/chunks/utils2-kjxf7BZO.js.map +0 -1
|
@@ -0,0 +1,499 @@
|
|
|
1
|
+
import type { MongoClientWithMappings } from "$lib/server/mongo";
|
|
2
|
+
import { ReadPreference } from "mongodb";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
|
|
5
|
+
export interface CollectionSchemaInfo {
|
|
6
|
+
hasSchema: boolean;
|
|
7
|
+
validator: Record<string, unknown> | null;
|
|
8
|
+
validationLevel: string | null;
|
|
9
|
+
validationAction: string | null;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface SchemaAuditResult {
|
|
13
|
+
nrecords: number;
|
|
14
|
+
nInvalidDocuments: number;
|
|
15
|
+
nValidDocuments: number;
|
|
16
|
+
compliancePct: number;
|
|
17
|
+
errors: Array<{
|
|
18
|
+
message: string;
|
|
19
|
+
docId?: unknown;
|
|
20
|
+
/** The full document that failed validation (encoded via JsonEncoder) */
|
|
21
|
+
document?: unknown;
|
|
22
|
+
}>;
|
|
23
|
+
warnings: string[];
|
|
24
|
+
hasSchema: boolean;
|
|
25
|
+
tookMs: number;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Fetch the JSON Schema validator configuration for a collection.
|
|
30
|
+
*/
|
|
31
|
+
export async function getCollectionSchema(
|
|
32
|
+
client: MongoClientWithMappings,
|
|
33
|
+
dbName: string,
|
|
34
|
+
colName: string,
|
|
35
|
+
): Promise<CollectionSchemaInfo> {
|
|
36
|
+
const db = client.db(dbName);
|
|
37
|
+
const collections = await db.listCollections({ name: colName }, { nameOnly: false }).toArray();
|
|
38
|
+
|
|
39
|
+
const colInfo = collections[0];
|
|
40
|
+
if (!colInfo) {
|
|
41
|
+
return { hasSchema: false, validator: null, validationLevel: null, validationAction: null };
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const options = (colInfo as { options?: Record<string, unknown> }).options ?? {};
|
|
45
|
+
|
|
46
|
+
const validator = (options.validator as Record<string, unknown>) ?? null;
|
|
47
|
+
const validationLevel = (options.validationLevel as string) ?? "strict";
|
|
48
|
+
const validationAction = (options.validationAction as string) ?? "error";
|
|
49
|
+
|
|
50
|
+
return {
|
|
51
|
+
hasSchema: !!validator && Object.keys(validator).length > 0,
|
|
52
|
+
validator,
|
|
53
|
+
validationLevel,
|
|
54
|
+
validationAction,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Extract the inner JSON Schema object from a MongoDB validator document.
|
|
60
|
+
* Validators are typically `{ $jsonSchema: { ... } }` but may also be wrapped
|
|
61
|
+
* in `$and`/`$or` or combined with other operators.
|
|
62
|
+
*/
|
|
63
|
+
function extractJsonSchema(validator: Record<string, unknown>): Record<string, unknown> | null {
|
|
64
|
+
// Direct $jsonSchema (most common)
|
|
65
|
+
if (validator.$jsonSchema && typeof validator.$jsonSchema === "object") {
|
|
66
|
+
return validator.$jsonSchema as Record<string, unknown>;
|
|
67
|
+
}
|
|
68
|
+
// $and: [{ $jsonSchema: ... }, ...]
|
|
69
|
+
if (Array.isArray(validator.$and)) {
|
|
70
|
+
for (const clause of validator.$and) {
|
|
71
|
+
const extracted = extractJsonSchema(clause as Record<string, unknown>);
|
|
72
|
+
if (extracted) {
|
|
73
|
+
return extracted;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/** Standard JSON Schema type names that zod's fromJSONSchema supports. */
|
|
81
|
+
const STANDARD_TYPES = new Set(["string", "number", "integer", "boolean", "object", "array", "null"]);
|
|
82
|
+
|
|
83
|
+
/** Map MongoDB bsonType aliases to standard JSON Schema types. */
|
|
84
|
+
const BSON_TYPE_MAP: Record<string, string> = {
|
|
85
|
+
int: "integer",
|
|
86
|
+
long: "integer",
|
|
87
|
+
double: "number",
|
|
88
|
+
bool: "boolean",
|
|
89
|
+
decimal: "number",
|
|
90
|
+
objectId: "objectId",
|
|
91
|
+
date: "date",
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* JSON Schema keywords that, when present, give the schema actual semantics.
|
|
96
|
+
* If none of these are set, the schema is `z.any()`-equivalent under zod's
|
|
97
|
+
* `fromJSONSchema`, which means it silently accepts `undefined` even when
|
|
98
|
+
* the parent's `required` list includes the property.
|
|
99
|
+
*/
|
|
100
|
+
const CONSTRAINT_KEYWORDS = [
|
|
101
|
+
"type",
|
|
102
|
+
"bsonType",
|
|
103
|
+
"enum",
|
|
104
|
+
"const",
|
|
105
|
+
"anyOf",
|
|
106
|
+
"oneOf",
|
|
107
|
+
"allOf",
|
|
108
|
+
"$ref",
|
|
109
|
+
"properties",
|
|
110
|
+
"patternProperties",
|
|
111
|
+
"additionalProperties",
|
|
112
|
+
"items",
|
|
113
|
+
"prefixItems",
|
|
114
|
+
"additionalItems",
|
|
115
|
+
"not",
|
|
116
|
+
"required",
|
|
117
|
+
"propertyNames",
|
|
118
|
+
];
|
|
119
|
+
|
|
120
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
121
|
+
function isEffectivelyAnySchema(schema: any): boolean {
|
|
122
|
+
if (typeof schema !== "object" || schema === null) {
|
|
123
|
+
return false;
|
|
124
|
+
}
|
|
125
|
+
return !CONSTRAINT_KEYWORDS.some((k) => schema[k] !== undefined);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Replacement for empty `{}` sub-schemas under a required property: a union
|
|
130
|
+
* of every JSON-representable type. This lets the value be anything (mirroring
|
|
131
|
+
* the original "any" intent) while still rejecting `undefined`, so the parent
|
|
132
|
+
* object's `required` check fires when the field is missing.
|
|
133
|
+
*/
|
|
134
|
+
const ANY_NON_UNDEFINED_SCHEMA = {
|
|
135
|
+
anyOf: [
|
|
136
|
+
{ type: "string" },
|
|
137
|
+
{ type: "number" },
|
|
138
|
+
{ type: "boolean" },
|
|
139
|
+
{ type: "object" },
|
|
140
|
+
{ type: "array" },
|
|
141
|
+
{ type: "null" },
|
|
142
|
+
],
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Convert a MongoDB $jsonSchema (which uses `bsonType` instead of `type`) into
|
|
147
|
+
* standard JSON Schema Draft-07 that zod's `fromJSONSchema` can enforce.
|
|
148
|
+
*
|
|
149
|
+
* MongoDB-specific types are mapped to EJSON wrapper shapes so zod can
|
|
150
|
+
* perform precise structural validation:
|
|
151
|
+
* bsonType: "objectId" → { type: "object", required: ["$oid"], properties: { $oid: { type: "string" } } }
|
|
152
|
+
* bsonType: "date" → { type: "object", required: ["$date"], properties: { $date: { type: "string" } } }
|
|
153
|
+
*
|
|
154
|
+
* Documents are likewise normalized via `normalizeBsonValue()` so ObjectId
|
|
155
|
+
* instances become `{ $oid: "hex" }` and Date instances become `{ $date: "ISO" }`
|
|
156
|
+
* before validation.
|
|
157
|
+
*
|
|
158
|
+
* Supports bsonType as a string or array (e.g., `["string", "null"]` for nullable).
|
|
159
|
+
*/
|
|
160
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
161
|
+
function bsonSchemaToStandard(schema: any): any {
|
|
162
|
+
if (typeof schema !== "object" || schema === null) {
|
|
163
|
+
return schema;
|
|
164
|
+
}
|
|
165
|
+
const out: Record<string, unknown> = { ...schema };
|
|
166
|
+
if (out.bsonType) {
|
|
167
|
+
const bsonTypeVal = out.bsonType;
|
|
168
|
+
delete out.bsonType;
|
|
169
|
+
// Handle array of types (nullable fields): bsonType: ["string", "null"]
|
|
170
|
+
const types: string[] = Array.isArray(bsonTypeVal) ? bsonTypeVal : [bsonTypeVal as string];
|
|
171
|
+
const mapped = types
|
|
172
|
+
.map((t) => BSON_TYPE_MAP[t] ?? (STANDARD_TYPES.has(t) ? t : null))
|
|
173
|
+
.filter((t): t is string => t !== null);
|
|
174
|
+
if (mapped.length === 0) {
|
|
175
|
+
// All types were unknown (binData, regex, etc.) — drop type constraint
|
|
176
|
+
} else if (mapped.length === 1) {
|
|
177
|
+
const bson = mapped[0];
|
|
178
|
+
if (bson === "objectId") {
|
|
179
|
+
out.type = "object";
|
|
180
|
+
out.required = ["$oid"];
|
|
181
|
+
out.properties = { $oid: { type: "string" } };
|
|
182
|
+
return out;
|
|
183
|
+
}
|
|
184
|
+
if (bson === "date") {
|
|
185
|
+
out.type = "object";
|
|
186
|
+
out.required = ["$date"];
|
|
187
|
+
out.properties = { $date: { type: "string" } };
|
|
188
|
+
return out;
|
|
189
|
+
}
|
|
190
|
+
out.type = bson;
|
|
191
|
+
} else {
|
|
192
|
+
// Multiple types — use anyOf. Don't return early; still need to recurse
|
|
193
|
+
// into properties/items/etc. for any object types in the union.
|
|
194
|
+
out.anyOf = mapped.map((t) => {
|
|
195
|
+
if (t === "objectId") {
|
|
196
|
+
return { type: "object", required: ["$oid"], properties: { $oid: { type: "string" } } };
|
|
197
|
+
}
|
|
198
|
+
if (t === "date") {
|
|
199
|
+
return { type: "object", required: ["$date"], properties: { $date: { type: "string" } } };
|
|
200
|
+
}
|
|
201
|
+
return { type: t };
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
// binData, regex, timestamp, etc. — drop the type so zod uses z.any()
|
|
205
|
+
}
|
|
206
|
+
if (out.properties) {
|
|
207
|
+
const requiredKeys = new Set(Array.isArray(out.required) ? (out.required as string[]) : []);
|
|
208
|
+
out.properties = Object.fromEntries(
|
|
209
|
+
Object.entries(out.properties as Record<string, unknown>).map(([k, v]) => {
|
|
210
|
+
const converted = bsonSchemaToStandard(v);
|
|
211
|
+
// If a required property has no real constraints, zod's
|
|
212
|
+
// fromJSONSchema collapses it to `z.any()` — which silently
|
|
213
|
+
// accepts `undefined` and defeats the `required` check.
|
|
214
|
+
// Replace with an explicit any-of-any-non-undefined union.
|
|
215
|
+
if (requiredKeys.has(k) && isEffectivelyAnySchema(converted)) {
|
|
216
|
+
return [k, ANY_NON_UNDEFINED_SCHEMA];
|
|
217
|
+
}
|
|
218
|
+
return [k, converted];
|
|
219
|
+
}),
|
|
220
|
+
);
|
|
221
|
+
}
|
|
222
|
+
if (out.additionalProperties && typeof out.additionalProperties === "object") {
|
|
223
|
+
out.additionalProperties = bsonSchemaToStandard(out.additionalProperties);
|
|
224
|
+
}
|
|
225
|
+
if (Array.isArray(out.oneOf)) {
|
|
226
|
+
out.oneOf = (out.oneOf as Array<unknown>).map((v) => bsonSchemaToStandard(v));
|
|
227
|
+
}
|
|
228
|
+
if (Array.isArray(out.anyOf)) {
|
|
229
|
+
out.anyOf = (out.anyOf as Array<unknown>).map((v) => bsonSchemaToStandard(v));
|
|
230
|
+
}
|
|
231
|
+
if (Array.isArray(out.allOf)) {
|
|
232
|
+
out.allOf = (out.allOf as Array<unknown>).map((v) => bsonSchemaToStandard(v));
|
|
233
|
+
}
|
|
234
|
+
if (out.items) {
|
|
235
|
+
out.items = Array.isArray(out.items)
|
|
236
|
+
? (out.items as Array<unknown>).map((v) => bsonSchemaToStandard(v))
|
|
237
|
+
: bsonSchemaToStandard(out.items);
|
|
238
|
+
}
|
|
239
|
+
return out;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* Recursively normalise BSON types in a document to their EJSON wrapper
|
|
244
|
+
* representations so zod can structurally validate them against a schema
|
|
245
|
+
* that has been converted to expect those wrappers.
|
|
246
|
+
*
|
|
247
|
+
* ObjectId → { $oid: "...hex..." }
|
|
248
|
+
* Date → { $date: "...ISO..." }
|
|
249
|
+
* Decimal128 → { $numberDecimal: "...string..." }
|
|
250
|
+
* Long → { $numberLong: "...string..." }
|
|
251
|
+
*/
|
|
252
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
253
|
+
function normalizeBsonValue(value: any): any {
|
|
254
|
+
if (value === null || value === undefined) {
|
|
255
|
+
return value;
|
|
256
|
+
}
|
|
257
|
+
if (typeof value !== "object") {
|
|
258
|
+
return value;
|
|
259
|
+
}
|
|
260
|
+
if (value instanceof Date) {
|
|
261
|
+
return { $date: value.toISOString() };
|
|
262
|
+
}
|
|
263
|
+
// ObjectId
|
|
264
|
+
if (value.constructor?.name === "ObjectId" && typeof value.toHexString === "function") {
|
|
265
|
+
return { $oid: value.toHexString() };
|
|
266
|
+
}
|
|
267
|
+
// Decimal128
|
|
268
|
+
if (value.constructor?.name === "Decimal128" && typeof value.toString === "function") {
|
|
269
|
+
return { $numberDecimal: value.toString() };
|
|
270
|
+
}
|
|
271
|
+
// Long
|
|
272
|
+
if (value.constructor?.name === "Long" && typeof value.toString === "function") {
|
|
273
|
+
return { $numberLong: value.toString() };
|
|
274
|
+
}
|
|
275
|
+
if (Array.isArray(value)) {
|
|
276
|
+
return value.map(normalizeBsonValue);
|
|
277
|
+
}
|
|
278
|
+
const out: Record<string, unknown> = {};
|
|
279
|
+
for (const [k, v] of Object.entries(value)) {
|
|
280
|
+
out[k] = normalizeBsonValue(v);
|
|
281
|
+
}
|
|
282
|
+
return out;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
/**
|
|
286
|
+
* BSON numeric types that have no faithful representation in JavaScript:
|
|
287
|
+
* MongoDB distinguishes int/long/double/decimal at the storage layer, but
|
|
288
|
+
* when a document is returned through the Node driver they all surface as
|
|
289
|
+
* `number` (or wrapped Long/Decimal128 for ranges that don't fit).
|
|
290
|
+
*
|
|
291
|
+
* If a validator constrains a field to one of these, our zod-based audit
|
|
292
|
+
* cannot reliably detect violations — so we use this to produce a more
|
|
293
|
+
* helpful fallback message when we know specific feedback isn't possible.
|
|
294
|
+
*/
|
|
295
|
+
const PRECISE_BSON_NUMERIC_TYPES = new Set(["int", "long", "double", "decimal"]);
|
|
296
|
+
|
|
297
|
+
/** Walk the schema tree and check whether any field uses a precise BSON numeric type. */
|
|
298
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
299
|
+
function schemaUsesPreciseBsonTypes(schema: any): boolean {
|
|
300
|
+
if (typeof schema !== "object" || schema === null) {
|
|
301
|
+
return false;
|
|
302
|
+
}
|
|
303
|
+
if (schema.bsonType) {
|
|
304
|
+
const types = Array.isArray(schema.bsonType) ? schema.bsonType : [schema.bsonType];
|
|
305
|
+
if (types.some((t: unknown) => typeof t === "string" && PRECISE_BSON_NUMERIC_TYPES.has(t))) {
|
|
306
|
+
return true;
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
for (const key of ["properties", "patternProperties"]) {
|
|
310
|
+
const props = schema[key];
|
|
311
|
+
if (props && typeof props === "object") {
|
|
312
|
+
for (const v of Object.values(props)) {
|
|
313
|
+
if (schemaUsesPreciseBsonTypes(v)) {
|
|
314
|
+
return true;
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
for (const key of ["items", "additionalProperties", "additionalItems"]) {
|
|
320
|
+
const v = schema[key];
|
|
321
|
+
if (v && typeof v === "object" && schemaUsesPreciseBsonTypes(v)) {
|
|
322
|
+
return true;
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
for (const key of ["oneOf", "anyOf", "allOf"]) {
|
|
326
|
+
const arr = schema[key];
|
|
327
|
+
if (Array.isArray(arr) && arr.some((v) => schemaUsesPreciseBsonTypes(v))) {
|
|
328
|
+
return true;
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
return false;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
/**
|
|
335
|
+
* Build a reusable per-document validator from a MongoDB `$jsonSchema`.
|
|
336
|
+
*
|
|
337
|
+
* The conversion + `z.fromJSONSchema` compilation is non-trivial for nested
|
|
338
|
+
* schemas, so we do it once per audit run and reuse the resulting closure
|
|
339
|
+
* for every sampled document.
|
|
340
|
+
*
|
|
341
|
+
* Returns a function that, given a raw MongoDB document, returns an array of
|
|
342
|
+
* human-readable failure messages (empty if the doc matches the schema, or a
|
|
343
|
+
* single fallback message if the validator itself couldn't be built).
|
|
344
|
+
*/
|
|
345
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
346
|
+
function buildDocumentValidator(schema: Record<string, unknown>): (doc: any) => string[] {
|
|
347
|
+
let validator: ReturnType<typeof z.fromJSONSchema> | null = null;
|
|
348
|
+
try {
|
|
349
|
+
const standardSchema = bsonSchemaToStandard(schema);
|
|
350
|
+
validator = z.fromJSONSchema(standardSchema);
|
|
351
|
+
} catch {
|
|
352
|
+
// Conversion / compilation failed — every doc will get the fallback.
|
|
353
|
+
validator = null;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
357
|
+
return (doc: any): string[] => {
|
|
358
|
+
if (!validator) {
|
|
359
|
+
return ["document does not match schema (could not parse schema with zod)"];
|
|
360
|
+
}
|
|
361
|
+
try {
|
|
362
|
+
const normalized = normalizeBsonValue(doc);
|
|
363
|
+
const result = validator.safeParse(normalized);
|
|
364
|
+
if (result.success) {
|
|
365
|
+
return [];
|
|
366
|
+
}
|
|
367
|
+
return [z.prettifyError(result.error)];
|
|
368
|
+
} catch {
|
|
369
|
+
return ["document does not match schema (could not parse schema with zod)"];
|
|
370
|
+
}
|
|
371
|
+
};
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
/**
|
|
375
|
+
* Audit schema compliance for a collection.
|
|
376
|
+
*
|
|
377
|
+
* Uses aggregation with the `$jsonSchema` operator rather than `db.validate()`
|
|
378
|
+
* because validate() does not reliably return `nInvalidDocuments` counts in
|
|
379
|
+
* MongoDB 8.x (always returns 0, only logs a warning to the server log).
|
|
380
|
+
*/
|
|
381
|
+
export async function auditSchemaCompliance(
|
|
382
|
+
client: MongoClientWithMappings,
|
|
383
|
+
dbName: string,
|
|
384
|
+
colName: string,
|
|
385
|
+
opts?: {
|
|
386
|
+
readPreference?: ReadPreference;
|
|
387
|
+
maxTimeMS?: number;
|
|
388
|
+
},
|
|
389
|
+
): Promise<SchemaAuditResult> {
|
|
390
|
+
const coll = client.db(dbName).collection(colName);
|
|
391
|
+
|
|
392
|
+
const schemaInfo = await getCollectionSchema(client, dbName, colName);
|
|
393
|
+
|
|
394
|
+
if (!schemaInfo.hasSchema || !schemaInfo.validator) {
|
|
395
|
+
return {
|
|
396
|
+
nrecords: 0,
|
|
397
|
+
nInvalidDocuments: 0,
|
|
398
|
+
nValidDocuments: 0,
|
|
399
|
+
compliancePct: 100,
|
|
400
|
+
errors: [],
|
|
401
|
+
warnings: [],
|
|
402
|
+
hasSchema: false,
|
|
403
|
+
tookMs: 0,
|
|
404
|
+
};
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
const jsonSchema = extractJsonSchema(schemaInfo.validator);
|
|
408
|
+
if (!jsonSchema) {
|
|
409
|
+
return {
|
|
410
|
+
nrecords: 0,
|
|
411
|
+
nInvalidDocuments: 0,
|
|
412
|
+
nValidDocuments: 0,
|
|
413
|
+
compliancePct: 100,
|
|
414
|
+
errors: [],
|
|
415
|
+
warnings: [
|
|
416
|
+
"Validator is present but could not extract a $jsonSchema for auditing — validator may use non-schema operators",
|
|
417
|
+
],
|
|
418
|
+
hasSchema: true,
|
|
419
|
+
tookMs: 0,
|
|
420
|
+
};
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
const start = performance.now();
|
|
424
|
+
|
|
425
|
+
const aggOptions: Record<string, unknown> = {};
|
|
426
|
+
if (opts?.readPreference) {
|
|
427
|
+
aggOptions.readPreference = opts.readPreference;
|
|
428
|
+
}
|
|
429
|
+
if (opts?.maxTimeMS) {
|
|
430
|
+
aggOptions.maxTimeMS = opts.maxTimeMS;
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
const total = await coll.countDocuments({}, aggOptions);
|
|
434
|
+
|
|
435
|
+
// Count non-matching documents.
|
|
436
|
+
// $nor + $jsonSchema identifies docs that don't conform.
|
|
437
|
+
const nonMatchingResult = await coll
|
|
438
|
+
.aggregate([{ $match: { $nor: [{ $jsonSchema: jsonSchema }] } }, { $count: "c" }], aggOptions)
|
|
439
|
+
.next()
|
|
440
|
+
.then((r) => (r as { c: number } | null)?.c ?? 0)
|
|
441
|
+
.catch(() => null);
|
|
442
|
+
|
|
443
|
+
if (nonMatchingResult === null) {
|
|
444
|
+
return {
|
|
445
|
+
nrecords: total,
|
|
446
|
+
nInvalidDocuments: 0,
|
|
447
|
+
nValidDocuments: total,
|
|
448
|
+
compliancePct: 100,
|
|
449
|
+
errors: [],
|
|
450
|
+
warnings: ["Unable to count non-matching documents (aggregation failed)"],
|
|
451
|
+
hasSchema: true,
|
|
452
|
+
tookMs: Math.round(performance.now() - start),
|
|
453
|
+
};
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
const nInvalidDocuments = nonMatchingResult;
|
|
457
|
+
const nValidDocuments = total - nInvalidDocuments;
|
|
458
|
+
const compliancePct = total > 0 ? (nValidDocuments * 100) / total : 100;
|
|
459
|
+
|
|
460
|
+
// Sample non-matching documents (up to 20)
|
|
461
|
+
const sampleDocs = await coll
|
|
462
|
+
.aggregate([{ $match: { $nor: [{ $jsonSchema: jsonSchema }] } }, { $limit: 20 }], aggOptions)
|
|
463
|
+
.toArray();
|
|
464
|
+
|
|
465
|
+
// Compare each non-matching doc against individual $jsonSchema constraints
|
|
466
|
+
// to produce specific error messages rather than a generic "does not match".
|
|
467
|
+
// When zod can't pinpoint the failure (returns no issues), it usually means
|
|
468
|
+
// the violation is a BSON-specific type distinction that isn't visible from
|
|
469
|
+
// the JS value alone (e.g. `bsonType: "double"` where the doc has an int).
|
|
470
|
+
const fallbackMessage = schemaUsesPreciseBsonTypes(jsonSchema)
|
|
471
|
+
? "The validator uses BSON-specific numeric types (int/long/double/decimal) which cannot be distinguished from a JavaScript value alone — try inspecting the document directly in MongoDB."
|
|
472
|
+
: "Failed to detect validation error";
|
|
473
|
+
|
|
474
|
+
// Build the per-document validator once: the schema is identical across
|
|
475
|
+
// every sample, so there's no need to re-run bsonSchemaToStandard /
|
|
476
|
+
// z.fromJSONSchema for each doc.
|
|
477
|
+
const validateOne = buildDocumentValidator(jsonSchema);
|
|
478
|
+
const errors: SchemaAuditResult["errors"] = sampleDocs.map((doc) => {
|
|
479
|
+
const failures = validateOne(doc);
|
|
480
|
+
return {
|
|
481
|
+
message: failures.length > 0 ? failures.join("; ") : fallbackMessage,
|
|
482
|
+
docId: doc._id,
|
|
483
|
+
document: doc,
|
|
484
|
+
};
|
|
485
|
+
});
|
|
486
|
+
|
|
487
|
+
const tookMs = Math.round(performance.now() - start);
|
|
488
|
+
|
|
489
|
+
return {
|
|
490
|
+
nrecords: total,
|
|
491
|
+
nInvalidDocuments,
|
|
492
|
+
nValidDocuments,
|
|
493
|
+
compliancePct,
|
|
494
|
+
errors,
|
|
495
|
+
warnings: [],
|
|
496
|
+
hasSchema: true,
|
|
497
|
+
tookMs,
|
|
498
|
+
};
|
|
499
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { getCollectionSchema } from "$lib/server/schema";
|
|
2
|
+
import { getMongo } from "$lib/server/mongo";
|
|
3
|
+
import type { PageServerLoad } from "./$types";
|
|
4
|
+
|
|
5
|
+
export const load: PageServerLoad = async ({ params }) => {
|
|
6
|
+
const mongo = await getMongo();
|
|
7
|
+
const client = mongo.getClient(params.server);
|
|
8
|
+
|
|
9
|
+
try {
|
|
10
|
+
const schemaInfo = await getCollectionSchema(client, params.database, params.collection);
|
|
11
|
+
|
|
12
|
+
return {
|
|
13
|
+
schemaInfo,
|
|
14
|
+
};
|
|
15
|
+
} catch {
|
|
16
|
+
return {
|
|
17
|
+
schemaInfo: {
|
|
18
|
+
hasSchema: false,
|
|
19
|
+
validator: null,
|
|
20
|
+
validationLevel: null,
|
|
21
|
+
validationAction: null,
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
};
|