most-box 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +24 -16
- package/electron/main.js +72 -8
- package/electron/preload.js +6 -0
- package/out/404/index.html +2 -2
- package/out/404.html +2 -2
- package/out/__next.__PAGE__.txt +6 -6
- package/out/__next._full.txt +23 -20
- package/out/__next._head.txt +3 -3
- package/out/__next._index.txt +8 -6
- package/out/__next._tree.txt +6 -4
- package/out/_next/static/chunks/0-n3pg7th.zza.js +1 -0
- package/out/_next/static/chunks/0.4j.0k5a64vg.js +1 -0
- package/out/_next/static/chunks/0.e2avjgna_b2.js +1 -0
- package/out/_next/static/chunks/0.ozi1_x2.m.~.js +1 -0
- package/out/_next/static/chunks/0.t5wlt51zou5.js +1 -0
- package/out/_next/static/chunks/0.w4hkvap~bva.js +1 -0
- package/out/_next/static/chunks/00d9h1tddnnnd.js +1 -0
- package/out/_next/static/chunks/00tkdqwxch-3s.js +1 -0
- package/out/_next/static/chunks/01l3o90g~1z42.js +1 -0
- package/out/_next/static/chunks/01mfky9camw6i.js +1 -0
- package/out/_next/static/chunks/01r.v-pqs1vrm.js +1 -0
- package/out/_next/static/chunks/03edqrb4zdj~g.js +31 -0
- package/out/_next/static/chunks/03h_6oo-gqkhz.js +1 -0
- package/out/_next/static/chunks/{0ho~log~~-jwp.css → 03h~nhgj0hv3p.css} +1 -1
- package/out/_next/static/chunks/04hcgsanv1hhu.js +1 -0
- package/out/_next/static/chunks/05g2q0w5b34.g.js +1 -0
- package/out/_next/static/chunks/05of77xycbt8~.js +1 -0
- package/out/_next/static/chunks/05zwemzfjx3sh.js +1 -0
- package/out/_next/static/chunks/06dpc5df94.v1.js +1 -0
- package/out/_next/static/chunks/06e1~1-z_ic9a.js +1 -0
- package/out/_next/static/chunks/075s7sn.ns~u5.js +1 -0
- package/out/_next/static/chunks/07dynrbvd3.f4.js +1 -0
- package/out/_next/static/chunks/07p~uva5pwgwe.js +1 -0
- package/out/_next/static/chunks/07r9nn-pzlgg1.js +1 -0
- package/out/_next/static/chunks/07td.jq7xff84.css +1 -0
- package/out/_next/static/chunks/08.72abkgwy9g.js +1 -0
- package/out/_next/static/chunks/08576xhv~~jck.js +1 -0
- package/out/_next/static/chunks/08u211~k~qu52.js +1 -0
- package/out/_next/static/chunks/098.p.2-zm4p7.js +1 -0
- package/out/_next/static/chunks/09ngvtajm7e5y.js +1 -0
- package/out/_next/static/chunks/09ps~-43n5qyo.js +1 -0
- package/out/_next/static/chunks/09v7_0gclxr46.js +1 -0
- package/out/_next/static/chunks/09yql86dir9c4.js +1 -0
- package/out/_next/static/chunks/09zmlfljowj1~.js +1 -0
- package/out/_next/static/chunks/0_s~ebb-7b2hr.js +1 -0
- package/out/_next/static/chunks/0_w-0-2z5oqd_.js +1 -0
- package/out/_next/static/chunks/0adx~d-j05c9d.css +24 -0
- package/out/_next/static/chunks/0ao1lbi4b.sfa.js +1 -0
- package/out/_next/static/chunks/0aq.rc9woa2nz.js +1 -0
- package/out/_next/static/chunks/0bld2u_ld~va2.js +1 -0
- package/out/_next/static/chunks/0bliugh5lxw55.js +1 -0
- package/out/_next/static/chunks/0cn9a7aimbdzq.js +1 -0
- package/out/_next/static/chunks/0d3f-nk3c.2re.js +1 -0
- package/out/_next/static/chunks/0dtohpf7~3d12.js +1 -0
- package/out/_next/static/chunks/0e-3e8h7g99yf.js +1 -0
- package/out/_next/static/chunks/0e531nije_ln2.js +1 -0
- package/out/_next/static/chunks/0e5zvj_rh0z3m.js +1 -0
- package/out/_next/static/chunks/0etes81d_cihn.js +1 -0
- package/out/_next/static/chunks/0f4y~rkk-n81e.js +1 -0
- package/out/_next/static/chunks/0fk~0~p7ivfn1.js +1 -0
- package/out/_next/static/chunks/0fw6juc~lsj3z.js +1 -0
- package/out/_next/static/chunks/0g0u7785a73vo.js +1 -0
- package/out/_next/static/chunks/0g_a~e050bgzg.css +1 -0
- package/out/_next/static/chunks/0g_fpgh7drfda.js +1 -0
- package/out/_next/static/chunks/{0n~dq4kpx9xxx.js → 0gcsdf57gcm6h.js} +1 -1
- package/out/_next/static/chunks/0gwian.hp3-92.js +1 -0
- package/out/_next/static/chunks/0gze5uso1mbe9.js +1 -0
- package/out/_next/static/chunks/0h4r.qtmpa6eh.js +1 -0
- package/out/_next/static/chunks/0hf.aosc-7172.js +1 -0
- package/out/_next/static/chunks/0hgz35c1ejbs9.js +1 -0
- package/out/_next/static/chunks/0hpev4am9jpmu.css +1 -0
- package/out/_next/static/chunks/0hrw-r.xmvmsq.js +1 -0
- package/out/_next/static/chunks/0hzg4al.v~8~m.js +1 -0
- package/out/_next/static/chunks/0ip9xrols_83o.js +1 -0
- package/out/_next/static/chunks/0j4-d0qf.v~kn.js +1 -0
- package/out/_next/static/chunks/0jhdeq.j9_02m.js +1 -0
- package/out/_next/static/chunks/0jy63h3i-y69i.js +1 -0
- package/out/_next/static/chunks/0kdnx_u-60k9s.js +1 -0
- package/out/_next/static/chunks/0kq~edq42o1-c.js +1 -0
- package/out/_next/static/chunks/0l5_.uqb-uqb8.js +1 -0
- package/out/_next/static/chunks/0l682p362d-5w.js +1 -0
- package/out/_next/static/chunks/0m68p9txef5rs.js +1 -0
- package/out/_next/static/chunks/0mex8svsiv-2l.js +1 -0
- package/out/_next/static/chunks/0mme-fm5d2oz2.js +1 -0
- package/out/_next/static/chunks/0myp4sjagr~h0.js +1 -0
- package/out/_next/static/chunks/0myq9gs8szydh.js +1 -0
- package/out/_next/static/chunks/0n.qlfk~z7o.6.js +1 -0
- package/out/_next/static/chunks/0n4t80gjc3q5h.js +1 -0
- package/out/_next/static/chunks/0o9ce4cyf76by.js +736 -0
- package/out/_next/static/chunks/0oz3yl6_-716p.js +1 -0
- package/out/_next/static/chunks/0p0sv~fuddvgr.js +1 -0
- package/out/_next/static/chunks/0pt.5cg1t09qs.js +1 -0
- package/out/_next/static/chunks/0q0ksgxg98xgd.js +1 -0
- package/out/_next/static/chunks/0qgx9t4jx16ua.css +1 -0
- package/out/_next/static/chunks/0qqupeexg83u7.js +1 -0
- package/out/_next/static/chunks/0rb-ri481.kc9.js +1 -0
- package/out/_next/static/chunks/0rsnmahfd.59p.js +1 -0
- package/out/_next/static/chunks/0rt6rgnvr-s_p.js +1 -0
- package/out/_next/static/chunks/0runh28p_gg6..js +1 -0
- package/out/_next/static/chunks/0shy.t1fwqcev.js +1 -0
- package/out/_next/static/chunks/{0d3shmwh5_nmn.js → 0t2xr05rlu96l.js} +1 -1
- package/out/_next/static/chunks/0t6h56rhg1y5i.js +1 -0
- package/out/_next/static/chunks/0tdqd1zunusgk.js +1 -0
- package/out/_next/static/chunks/0ujbnp38x63ek.js +1 -0
- package/out/_next/static/chunks/0ukyg~tkm~h2m.css +1 -0
- package/out/_next/static/chunks/0v68pdrp54lb-.js +1 -0
- package/out/_next/static/chunks/0vsm0m5sxrb.3.js +1 -0
- package/out/_next/static/chunks/0vzlz.iboqo3c.js +1 -0
- package/out/_next/static/chunks/0w87vbpkf-ogd.js +1 -0
- package/out/_next/static/chunks/0wtf0xsiicxx6.js +1 -0
- package/out/_next/static/chunks/0xdwau5k2augv.css +4 -0
- package/out/_next/static/chunks/0xgg0~kmf3gd-.js +1 -0
- package/out/_next/static/chunks/0xj24-70ptdzp.js +1 -0
- package/out/_next/static/chunks/0xxlx772fr3x4.js +1 -0
- package/out/_next/static/chunks/0y.li-~3oybew.js +1 -0
- package/out/_next/static/chunks/0yl2t7cs-n_ng.js +1 -0
- package/out/_next/static/chunks/0yq3kh.hchtm_.js +1 -0
- package/out/_next/static/chunks/0ys0l5au.9c2c.js +1 -0
- package/out/_next/static/chunks/0z48pmi6buytt.js +1 -0
- package/out/_next/static/chunks/0zapnvgy89mg..js +1 -0
- package/out/_next/static/chunks/0~.-vxi5oc.r0.js +1 -0
- package/out/_next/static/chunks/0~3ik-hfp9s-7.js +1 -0
- package/out/_next/static/chunks/0~4f5p6tvn1lq.js +1 -0
- package/out/_next/static/chunks/0~_0ys.2whxbw.js +1 -0
- package/out/_next/static/chunks/0~_ui9l7.2sxf.js +1 -0
- package/out/_next/static/chunks/1037jlyw5~7ht.js +1 -0
- package/out/_next/static/chunks/1045hfzu533z0.js +1 -0
- package/out/_next/static/chunks/104e5nmc.c-pl.js +1 -0
- package/out/_next/static/chunks/109taw1pbh-0b.js +1 -0
- package/out/_next/static/chunks/10x7~onqwp338.js +1 -0
- package/out/_next/static/chunks/10ynz1dy483wf.js +1 -0
- package/out/_next/static/chunks/11hds.mg~4_r-.js +1 -0
- package/out/_next/static/chunks/11ibzaklcauw~.js +1 -0
- package/out/_next/static/chunks/11z.0s6.42b.p.js +1 -0
- package/out/_next/static/chunks/12-9n56l0y3yr.js +1 -0
- package/out/_next/static/chunks/126enaq~f7scl.js +1 -0
- package/out/_next/static/chunks/12nr19.nnn6s3.js +5 -0
- package/out/_next/static/chunks/{0qub_r0x_r-e9.css → 12pep-2t-qg4n.css} +1 -1
- package/out/_next/static/chunks/1380op_pfk.qo.js +1 -0
- package/out/_next/static/chunks/146oiw1bggtn4.js +1 -0
- package/out/_next/static/chunks/14_inksek_rth.js +2 -0
- package/out/_next/static/chunks/14_po2rb_arn4.js +1 -0
- package/out/_next/static/chunks/14a4fwbiq.l3z.js +1 -0
- package/out/_next/static/chunks/14cowsqn95m1k.js +1 -0
- package/out/_next/static/chunks/14dtd3l03v.kx.js +1 -0
- package/out/_next/static/chunks/14tm3qa-v9o-4.js +1 -0
- package/out/_next/static/chunks/15-o4kb-evqd7.js +1 -0
- package/out/_next/static/chunks/153-sz7s.qml2.js +1 -0
- package/out/_next/static/chunks/157z7bowux3xj.js +1 -0
- package/out/_next/static/chunks/15m1_677az2cm.js +1 -0
- package/out/_next/static/chunks/15v.~.ne6ogkk.js +1 -0
- package/out/_next/static/chunks/16i.qbk8t8gf_.js +1 -0
- package/out/_next/static/chunks/16u9f35gylw8l.js +1 -0
- package/out/_next/static/chunks/16xls5tt_68lx.js +1 -0
- package/out/_next/static/chunks/17ajyb5ogk5yj.js +1 -0
- package/out/_next/static/chunks/17dyfxbq8yz8n.js +1 -0
- package/out/_next/static/chunks/180zln9pcq9ih.js +1 -0
- package/out/_next/static/chunks/1814izi5gh.kp.js +1 -0
- package/out/_next/static/chunks/turbopack-0xta0kqwzkf28.js +1 -0
- package/out/_next/static/media/KaTeX_AMS-Regular.0b~8ki5y928w2.woff +0 -0
- package/out/_next/static/media/KaTeX_AMS-Regular.0p1vbqd84i2~o.woff2 +0 -0
- package/out/_next/static/media/KaTeX_AMS-Regular.173t6ktr7uf-w.ttf +0 -0
- package/out/_next/static/media/KaTeX_Caligraphic-Bold.01-pzluls4zgb.woff2 +0 -0
- package/out/_next/static/media/KaTeX_Caligraphic-Bold.0x2v1lwn~880f.woff +0 -0
- package/out/_next/static/media/KaTeX_Caligraphic-Bold.16zv5fax0h0ka.ttf +0 -0
- package/out/_next/static/media/KaTeX_Caligraphic-Regular.02i3z7wig438t.ttf +0 -0
- package/out/_next/static/media/KaTeX_Caligraphic-Regular.0rysu1t-ncjq8.woff2 +0 -0
- package/out/_next/static/media/KaTeX_Caligraphic-Regular.10927swgekwun.woff +0 -0
- package/out/_next/static/media/KaTeX_Fraktur-Bold.0e-16u10iuyyf.woff +0 -0
- package/out/_next/static/media/KaTeX_Fraktur-Bold.0et27v~3~4uhe.ttf +0 -0
- package/out/_next/static/media/KaTeX_Fraktur-Bold.0w23i72~hprpq.woff2 +0 -0
- package/out/_next/static/media/KaTeX_Fraktur-Regular.0b.riegzdfue2.woff +0 -0
- package/out/_next/static/media/KaTeX_Fraktur-Regular.0rekyoa-52fj_.woff2 +0 -0
- package/out/_next/static/media/KaTeX_Fraktur-Regular.0vjwa15znhk~4.ttf +0 -0
- package/out/_next/static/media/KaTeX_Main-Bold.09i7~607shf-h.ttf +0 -0
- package/out/_next/static/media/KaTeX_Main-Bold.09lmynrorhcbw.woff +0 -0
- package/out/_next/static/media/KaTeX_Main-Bold.16pfc63_du6mx.woff2 +0 -0
- package/out/_next/static/media/KaTeX_Main-BoldItalic.0cp37g7x1q8h6.woff +0 -0
- package/out/_next/static/media/KaTeX_Main-BoldItalic.0d54rk08rx11s.woff2 +0 -0
- package/out/_next/static/media/KaTeX_Main-BoldItalic.15j6k~hix2t_0.ttf +0 -0
- package/out/_next/static/media/KaTeX_Main-Italic.0382gqciexmbu.woff +0 -0
- package/out/_next/static/media/KaTeX_Main-Italic.06o5nq0_91v60.woff2 +0 -0
- package/out/_next/static/media/KaTeX_Main-Italic.0su4i6mm18-wo.ttf +0 -0
- package/out/_next/static/media/KaTeX_Main-Regular.08zh8z.7shijf.ttf +0 -0
- package/out/_next/static/media/KaTeX_Main-Regular.0diheg01zyoph.woff +0 -0
- package/out/_next/static/media/KaTeX_Main-Regular.0kaf-ag2_wkm-.woff2 +0 -0
- package/out/_next/static/media/KaTeX_Math-BoldItalic.0ajzxypnbx1h1.ttf +0 -0
- package/out/_next/static/media/KaTeX_Math-BoldItalic.0ck1myuerwyqw.woff +0 -0
- package/out/_next/static/media/KaTeX_Math-BoldItalic.0ja97dn.cpc87.woff2 +0 -0
- package/out/_next/static/media/KaTeX_Math-Italic.09xkhecjcn5r9.woff +0 -0
- package/out/_next/static/media/KaTeX_Math-Italic.0x23a-bmp-5tg.ttf +0 -0
- package/out/_next/static/media/KaTeX_Math-Italic.0zrha2c4sl2je.woff2 +0 -0
- package/out/_next/static/media/KaTeX_SansSerif-Bold.05a9.pc1j_zx9.woff2 +0 -0
- package/out/_next/static/media/KaTeX_SansSerif-Bold.0jcl-ayi1uun0.woff +0 -0
- package/out/_next/static/media/KaTeX_SansSerif-Bold.0re8y.dm7.mt5.ttf +0 -0
- package/out/_next/static/media/KaTeX_SansSerif-Italic.0a0234dc3s62j.woff2 +0 -0
- package/out/_next/static/media/KaTeX_SansSerif-Italic.0judofdln9731.woff +0 -0
- package/out/_next/static/media/KaTeX_SansSerif-Italic.10z1iap9pfus8.ttf +0 -0
- package/out/_next/static/media/KaTeX_SansSerif-Regular.0h9yjlugq4q_e.woff +0 -0
- package/out/_next/static/media/KaTeX_SansSerif-Regular.0v6gcj32-czft.woff2 +0 -0
- package/out/_next/static/media/KaTeX_SansSerif-Regular.0zm18kga42ebc.ttf +0 -0
- package/out/_next/static/media/KaTeX_Script-Regular.0c4.h-mer83d_.woff2 +0 -0
- package/out/_next/static/media/KaTeX_Script-Regular.0q14y6zkzlpob.ttf +0 -0
- package/out/_next/static/media/KaTeX_Script-Regular.0ze6v4r_-99oy.woff +0 -0
- package/out/_next/static/media/KaTeX_Size1-Regular.013x6a4ierotp.woff2 +0 -0
- package/out/_next/static/media/KaTeX_Size1-Regular.0kidw0oi.m68o.woff +0 -0
- package/out/_next/static/media/KaTeX_Size1-Regular.0m6y-i6wfokni.ttf +0 -0
- package/out/_next/static/media/KaTeX_Size2-Regular.0blpmluwilgbg.woff +0 -0
- package/out/_next/static/media/KaTeX_Size2-Regular.0d5inmyp-tyv3.woff2 +0 -0
- package/out/_next/static/media/KaTeX_Size2-Regular.0wnhnvj-.k9d5.ttf +0 -0
- package/out/_next/static/media/KaTeX_Size3-Regular.01h0xm_sfctj3.woff +0 -0
- package/out/_next/static/media/KaTeX_Size3-Regular.0iukctyhw5j56.woff2 +0 -0
- package/out/_next/static/media/KaTeX_Size3-Regular.0jl8mqyf4gzpn.ttf +0 -0
- package/out/_next/static/media/KaTeX_Size4-Regular.0w3.rb_c4stzk.woff2 +0 -0
- package/out/_next/static/media/KaTeX_Size4-Regular.0wr_9l81-mu06.ttf +0 -0
- package/out/_next/static/media/KaTeX_Size4-Regular.12tvaesf3.zl3.woff +0 -0
- package/out/_next/static/media/KaTeX_Typewriter-Regular.0c4zdxz~8frhm.woff2 +0 -0
- package/out/_next/static/media/KaTeX_Typewriter-Regular.0cgrzn5l3kao5.woff +0 -0
- package/out/_next/static/media/KaTeX_Typewriter-Regular.128~qc3858otl.ttf +0 -0
- package/out/_not-found/__next._full.txt +21 -19
- package/out/_not-found/__next._head.txt +3 -3
- package/out/_not-found/__next._index.txt +8 -6
- package/out/_not-found/__next._not-found.__PAGE__.txt +4 -4
- package/out/_not-found/__next._not-found.txt +3 -3
- package/out/_not-found/__next._tree.txt +3 -2
- package/out/_not-found/index.html +2 -2
- package/out/_not-found/index.txt +21 -19
- package/out/admin/__next._full.txt +23 -0
- package/out/admin/__next._head.txt +5 -0
- package/out/admin/__next._index.txt +9 -0
- package/out/admin/__next._tree.txt +5 -0
- package/out/admin/__next.admin.__PAGE__.txt +9 -0
- package/out/admin/__next.admin.txt +5 -0
- package/out/admin/index.html +15 -0
- package/out/admin/index.txt +23 -0
- package/out/app/__next._full.txt +15 -13
- package/out/app/__next._head.txt +3 -3
- package/out/app/__next._index.txt +8 -6
- package/out/app/__next._tree.txt +4 -2
- package/out/app/__next.app.__PAGE__.txt +4 -4
- package/out/app/__next.app.txt +3 -4
- package/out/app/index.html +2 -2
- package/out/app/index.txt +15 -13
- package/out/chat/__next._full.txt +16 -14
- package/out/chat/__next._head.txt +3 -3
- package/out/chat/__next._index.txt +8 -6
- package/out/chat/__next._tree.txt +5 -3
- package/out/chat/__next.chat.__PAGE__.txt +4 -4
- package/out/chat/__next.chat.txt +4 -5
- package/out/chat/index.html +2 -2
- package/out/chat/index.txt +16 -14
- package/out/chat/join/__next._full.txt +25 -0
- package/out/chat/join/__next._head.txt +5 -0
- package/out/chat/join/__next._index.txt +9 -0
- package/out/chat/join/__next._tree.txt +5 -0
- package/out/chat/join/__next.chat.join.__PAGE__.txt +9 -0
- package/out/chat/join/__next.chat.join.txt +5 -0
- package/out/chat/join/__next.chat.txt +5 -0
- package/out/chat/join/index.html +15 -0
- package/out/chat/join/index.txt +25 -0
- package/out/download/__next._full.txt +34 -33
- package/out/download/__next._head.txt +3 -3
- package/out/download/__next._index.txt +8 -6
- package/out/download/__next._tree.txt +6 -4
- package/out/download/__next.download.__PAGE__.txt +13 -14
- package/out/download/__next.download.txt +3 -3
- package/out/download/index.html +2 -2
- package/out/download/index.txt +34 -33
- package/out/index.html +2 -2
- package/out/index.txt +23 -20
- package/out/note/__next._full.txt +24 -0
- package/out/{changelog → note}/__next._head.txt +3 -3
- package/out/note/__next._index.txt +9 -0
- package/out/note/__next._tree.txt +4 -0
- package/out/note/__next.note.__PAGE__.txt +9 -0
- package/out/note/__next.note.txt +5 -0
- package/out/note/index.html +15 -0
- package/out/note/index.txt +24 -0
- package/out/ping/__next._full.txt +23 -20
- package/out/ping/__next._head.txt +3 -3
- package/out/ping/__next._index.txt +8 -6
- package/out/ping/__next._tree.txt +6 -4
- package/out/ping/__next.ping.__PAGE__.txt +5 -5
- package/out/ping/__next.ping.txt +4 -4
- package/out/ping/index.html +2 -2
- package/out/ping/index.txt +23 -20
- package/out/web3/__next._full.txt +16 -14
- package/out/web3/__next._head.txt +3 -3
- package/out/web3/__next._index.txt +8 -6
- package/out/web3/__next._tree.txt +5 -3
- package/out/web3/__next.web3.__PAGE__.txt +4 -4
- package/out/web3/__next.web3.txt +4 -5
- package/out/web3/ed25519/__next._full.txt +14 -12
- package/out/web3/ed25519/__next._head.txt +3 -3
- package/out/web3/ed25519/__next._index.txt +8 -6
- package/out/web3/ed25519/__next._tree.txt +5 -3
- package/out/web3/ed25519/__next.web3.ed25519.__PAGE__.txt +2 -2
- package/out/web3/ed25519/__next.web3.ed25519.txt +3 -3
- package/out/web3/ed25519/__next.web3.txt +4 -5
- package/out/web3/ed25519/index.html +1 -1
- package/out/web3/ed25519/index.txt +14 -12
- package/out/web3/index.html +2 -2
- package/out/web3/index.txt +16 -14
- package/out/web3/tools/__next._full.txt +14 -12
- package/out/web3/tools/__next._head.txt +3 -3
- package/out/web3/tools/__next._index.txt +8 -6
- package/out/web3/tools/__next._tree.txt +5 -3
- package/out/web3/tools/__next.web3.tools.__PAGE__.txt +2 -2
- package/out/web3/tools/__next.web3.tools.txt +3 -3
- package/out/web3/tools/__next.web3.txt +4 -5
- package/out/web3/tools/index.html +1 -1
- package/out/web3/tools/index.txt +14 -12
- package/package.json +30 -13
- package/server/index.js +188 -901
- package/server/src/config.js +5 -1
- package/server/src/core/channelAttachment.js +68 -0
- package/server/src/core/cid.js +6 -71
- package/server/src/core/cidTopic.js +29 -0
- package/server/src/core/mostLink.js +88 -0
- package/server/src/http/access.js +123 -0
- package/server/src/http/app.js +1095 -0
- package/server/src/http/errors.js +35 -0
- package/server/src/http/nodeLogs.js +53 -0
- package/server/src/http/nodeStatus.js +146 -0
- package/server/src/http/staticFiles.js +84 -0
- package/server/src/http/uploads.js +114 -0
- package/server/src/index.js +1539 -301
- package/server/src/node/config.js +191 -0
- package/server/src/node/logs.js +94 -0
- package/server/src/utils/api.js +359 -8
- package/server/src/utils/auth.js +63 -0
- package/server/src/utils/dateTime.js +30 -0
- package/server/src/utils/downloadMessages.js +89 -0
- package/server/src/utils/errors.js +14 -0
- package/server/src/utils/mostWallet.js +185 -1
- package/server/src/utils/mp.js +2 -26
- package/server/src/utils/noteBackup.js +116 -0
- package/server/src/utils/noteUtils.js +128 -0
- package/server/src/utils/userIdentity.js +8 -61
- package/out/_next/static/chunks/003jnm.v5tzw5.js +0 -1
- package/out/_next/static/chunks/00re8v.gbcywn.js +0 -1
- package/out/_next/static/chunks/00s106sbq8t9v.js +0 -1
- package/out/_next/static/chunks/012hi627qrdnn.js +0 -1
- package/out/_next/static/chunks/0174xh3wfsjm1.js +0 -2
- package/out/_next/static/chunks/02~o2nmo5pmy1.js +0 -1
- package/out/_next/static/chunks/07t.dhhokszz5.css +0 -1
- package/out/_next/static/chunks/0_wia9ofmsi1c.css +0 -2
- package/out/_next/static/chunks/0ah8fihozo2_u.js +0 -5
- package/out/_next/static/chunks/0bzupvr5gt3k9.js +0 -31
- package/out/_next/static/chunks/0e_h0d3ekzks8.css +0 -1
- package/out/_next/static/chunks/0gdluj423gso1.js +0 -1
- package/out/_next/static/chunks/0gmoiq06srjay.css +0 -1
- package/out/_next/static/chunks/0imkasy7kb67u.js +0 -1
- package/out/_next/static/chunks/0jjc_b9q_ldi2.js +0 -1
- package/out/_next/static/chunks/0jl~j62iz2uvr.js +0 -1
- package/out/_next/static/chunks/0lqslm813wk_h.js +0 -1
- package/out/_next/static/chunks/0q782fxxd0lx~.js +0 -1
- package/out/_next/static/chunks/0slwj0c46k5cu.js +0 -1
- package/out/_next/static/chunks/0sorqk.oc6b7j.css +0 -1
- package/out/_next/static/chunks/0tapzqc6hgvx-.js +0 -1
- package/out/_next/static/chunks/0xsc7z5x8n7wg.js +0 -1
- package/out/_next/static/chunks/0zm~gys2jwl0g.js +0 -1
- package/out/_next/static/chunks/turbopack-0a_g3u0ud~jb8.js +0 -1
- package/out/changelog/__next._full.txt +0 -22
- package/out/changelog/__next._index.txt +0 -7
- package/out/changelog/__next._tree.txt +0 -3
- package/out/changelog/__next.changelog.__PAGE__.txt +0 -10
- package/out/changelog/__next.changelog.txt +0 -5
- package/out/changelog/index.html +0 -15
- package/out/changelog/index.txt +0 -22
- package/out/docs/__next._full.txt +0 -22
- package/out/docs/__next._head.txt +0 -5
- package/out/docs/__next._index.txt +0 -7
- package/out/docs/__next._tree.txt +0 -3
- package/out/docs/__next.docs.__PAGE__.txt +0 -10
- package/out/docs/__next.docs.txt +0 -5
- package/out/docs/getting-started/__next._full.txt +0 -22
- package/out/docs/getting-started/__next._head.txt +0 -5
- package/out/docs/getting-started/__next._index.txt +0 -7
- package/out/docs/getting-started/__next._tree.txt +0 -3
- package/out/docs/getting-started/__next.docs.getting-started.__PAGE__.txt +0 -10
- package/out/docs/getting-started/__next.docs.getting-started.txt +0 -5
- package/out/docs/getting-started/__next.docs.txt +0 -5
- package/out/docs/getting-started/index.html +0 -15
- package/out/docs/getting-started/index.txt +0 -22
- package/out/docs/index.html +0 -15
- package/out/docs/index.txt +0 -22
- /package/out/_next/static/{iOB2EBwOGZ0iYW7Lbg9u_ → t7ZIeQpVvjz4a7-5Tt-VK}/_buildManifest.js +0 -0
- /package/out/_next/static/{iOB2EBwOGZ0iYW7Lbg9u_ → t7ZIeQpVvjz4a7-5Tt-VK}/_clientMiddlewareManifest.js +0 -0
- /package/out/_next/static/{iOB2EBwOGZ0iYW7Lbg9u_ → t7ZIeQpVvjz4a7-5Tt-VK}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import fs from 'node:fs'
|
|
2
|
+
import os from 'node:os'
|
|
3
|
+
import path from 'node:path'
|
|
4
|
+
import { MAX_FILE_SIZE } from '../config.js'
|
|
5
|
+
|
|
6
|
+
const DEFAULT_CONFIG_DIR_NAME = '.most-box'
|
|
7
|
+
const DEFAULT_DATA_DIR_NAME = 'most-data'
|
|
8
|
+
const DEFAULT_CAPACITY_BYTES = 100 * 1024 * 1024 * 1024
|
|
9
|
+
export const DEFAULT_NODE_PORT = 1976
|
|
10
|
+
export const DEFAULT_NODE_HOST = '127.0.0.1'
|
|
11
|
+
|
|
12
|
+
export function getDefaultConfigDir() {
|
|
13
|
+
return path.join(os.homedir(), DEFAULT_CONFIG_DIR_NAME)
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function getDefaultDataPath() {
|
|
17
|
+
return path.join(os.homedir(), DEFAULT_DATA_DIR_NAME)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function getDefaultNodeConfig() {
|
|
21
|
+
return {
|
|
22
|
+
dataPath: '',
|
|
23
|
+
host: DEFAULT_NODE_HOST,
|
|
24
|
+
port: DEFAULT_NODE_PORT,
|
|
25
|
+
capacityBytes: DEFAULT_CAPACITY_BYTES,
|
|
26
|
+
maxFileSizeBytes: MAX_FILE_SIZE,
|
|
27
|
+
remoteInvites: [],
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function normalizeRemoteInvites(value = []) {
|
|
32
|
+
const items = Array.isArray(value) ? value : String(value || '').split(',')
|
|
33
|
+
return Array.from(
|
|
34
|
+
new Set(items.map(item => String(item || '').trim()).filter(Boolean))
|
|
35
|
+
)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function normalizeNodeConfig(raw = {}) {
|
|
39
|
+
const defaults = getDefaultNodeConfig()
|
|
40
|
+
const rawNode = raw.node && typeof raw.node === 'object' ? raw.node : {}
|
|
41
|
+
|
|
42
|
+
const capacityBytes = normalizePositiveInteger(
|
|
43
|
+
rawNode.capacityBytes ?? raw.capacityBytes,
|
|
44
|
+
defaults.capacityBytes
|
|
45
|
+
)
|
|
46
|
+
const maxFileSizeBytes = normalizePositiveInteger(
|
|
47
|
+
rawNode.maxFileSizeBytes ?? raw.maxFileSizeBytes,
|
|
48
|
+
defaults.maxFileSizeBytes
|
|
49
|
+
)
|
|
50
|
+
const remoteInvites = normalizeRemoteInvites(
|
|
51
|
+
rawNode.remoteInvites ?? raw.remoteInvites ?? defaults.remoteInvites
|
|
52
|
+
)
|
|
53
|
+
const host = normalizeHost(rawNode.host ?? raw.host, defaults.host)
|
|
54
|
+
const port = normalizePositiveInteger(
|
|
55
|
+
rawNode.port ?? raw.port,
|
|
56
|
+
defaults.port
|
|
57
|
+
)
|
|
58
|
+
return {
|
|
59
|
+
dataPath:
|
|
60
|
+
typeof raw.dataPath === 'string'
|
|
61
|
+
? raw.dataPath.trim()
|
|
62
|
+
: defaults.dataPath,
|
|
63
|
+
host,
|
|
64
|
+
port,
|
|
65
|
+
capacityBytes,
|
|
66
|
+
maxFileSizeBytes,
|
|
67
|
+
remoteInvites,
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export function createNodeConfigStore(configDir = getDefaultConfigDir()) {
|
|
72
|
+
const resolvedConfigDir = path.resolve(configDir)
|
|
73
|
+
const configFile = path.join(resolvedConfigDir, 'config.json')
|
|
74
|
+
|
|
75
|
+
function loadRawConfig() {
|
|
76
|
+
try {
|
|
77
|
+
if (fs.existsSync(configFile)) {
|
|
78
|
+
return JSON.parse(fs.readFileSync(configFile, 'utf-8'))
|
|
79
|
+
}
|
|
80
|
+
} catch (err) {
|
|
81
|
+
console.error('[Config] Load error:', err.message)
|
|
82
|
+
}
|
|
83
|
+
return {}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function saveRawConfig(config) {
|
|
87
|
+
try {
|
|
88
|
+
if (!fs.existsSync(resolvedConfigDir)) {
|
|
89
|
+
fs.mkdirSync(resolvedConfigDir, { recursive: true })
|
|
90
|
+
}
|
|
91
|
+
const tmpPath = configFile + '.tmp'
|
|
92
|
+
fs.writeFileSync(tmpPath, JSON.stringify(config, null, 2), 'utf-8')
|
|
93
|
+
fs.renameSync(tmpPath, configFile)
|
|
94
|
+
return true
|
|
95
|
+
} catch (err) {
|
|
96
|
+
console.error('[Config] Save error:', err.message)
|
|
97
|
+
return false
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function getNodeConfig() {
|
|
102
|
+
return normalizeNodeConfig(loadRawConfig())
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function getDataPath() {
|
|
106
|
+
return getNodeConfig().dataPath || getDefaultDataPath()
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function saveNodeConfigPatch(patch = {}) {
|
|
110
|
+
const raw = loadRawConfig()
|
|
111
|
+
const current = normalizeNodeConfig(raw)
|
|
112
|
+
const next = normalizeNodeConfig({
|
|
113
|
+
...raw,
|
|
114
|
+
dataPath:
|
|
115
|
+
patch.dataPath === undefined ? current.dataPath : patch.dataPath,
|
|
116
|
+
node: {
|
|
117
|
+
...(raw.node && typeof raw.node === 'object' ? raw.node : {}),
|
|
118
|
+
host: patch.host === undefined ? current.host : patch.host,
|
|
119
|
+
port: patch.port === undefined ? current.port : patch.port,
|
|
120
|
+
capacityBytes:
|
|
121
|
+
patch.capacityBytes === undefined
|
|
122
|
+
? current.capacityBytes
|
|
123
|
+
: patch.capacityBytes,
|
|
124
|
+
maxFileSizeBytes:
|
|
125
|
+
patch.maxFileSizeBytes === undefined
|
|
126
|
+
? current.maxFileSizeBytes
|
|
127
|
+
: patch.maxFileSizeBytes,
|
|
128
|
+
remoteInvites:
|
|
129
|
+
patch.remoteInvites === undefined
|
|
130
|
+
? current.remoteInvites
|
|
131
|
+
: patch.remoteInvites,
|
|
132
|
+
},
|
|
133
|
+
})
|
|
134
|
+
|
|
135
|
+
const saved = {
|
|
136
|
+
dataPath: next.dataPath,
|
|
137
|
+
node: {
|
|
138
|
+
host: next.host,
|
|
139
|
+
port: next.port,
|
|
140
|
+
capacityBytes: next.capacityBytes,
|
|
141
|
+
maxFileSizeBytes: next.maxFileSizeBytes,
|
|
142
|
+
remoteInvites: next.remoteInvites,
|
|
143
|
+
updatedAt: new Date().toISOString(),
|
|
144
|
+
},
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
return { success: saveRawConfig(saved), config: normalizeNodeConfig(saved) }
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
return {
|
|
151
|
+
configDir: resolvedConfigDir,
|
|
152
|
+
configFile,
|
|
153
|
+
loadRawConfig,
|
|
154
|
+
saveRawConfig,
|
|
155
|
+
getNodeConfig,
|
|
156
|
+
getDataPath,
|
|
157
|
+
saveNodeConfigPatch,
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
export function evaluateStorageLimits(config, input = {}) {
|
|
162
|
+
const size = Number(input.size ?? input.fileSize ?? 0)
|
|
163
|
+
const reasons = []
|
|
164
|
+
|
|
165
|
+
if (!Number.isFinite(size) || size < 0) {
|
|
166
|
+
reasons.push('invalid-size')
|
|
167
|
+
} else if (size > config.maxFileSizeBytes) {
|
|
168
|
+
reasons.push('file-too-large')
|
|
169
|
+
} else if (size > config.capacityBytes) {
|
|
170
|
+
reasons.push('capacity-too-small')
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
return {
|
|
174
|
+
accepted: reasons.length === 0,
|
|
175
|
+
reasons,
|
|
176
|
+
policy: config,
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
function normalizePositiveInteger(value, fallback) {
|
|
181
|
+
const parsed = Number(value)
|
|
182
|
+
if (!Number.isFinite(parsed) || parsed < 0) {
|
|
183
|
+
return fallback
|
|
184
|
+
}
|
|
185
|
+
return Math.floor(parsed)
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
function normalizeHost(value, fallback) {
|
|
189
|
+
const host = String(value || '').trim()
|
|
190
|
+
return host || fallback
|
|
191
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import fs from 'node:fs'
|
|
2
|
+
import path from 'node:path'
|
|
3
|
+
|
|
4
|
+
const DEFAULT_MAX_LOG_LINES = 1000
|
|
5
|
+
|
|
6
|
+
export function createNodeLogger(configDir, options = {}) {
|
|
7
|
+
const maxLines = options.maxLines || DEFAULT_MAX_LOG_LINES
|
|
8
|
+
const logFile = options.logFile || path.join(configDir, 'node-events.log')
|
|
9
|
+
|
|
10
|
+
function append(input = {}) {
|
|
11
|
+
const entry = {
|
|
12
|
+
id: `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
|
|
13
|
+
ts: new Date().toISOString(),
|
|
14
|
+
level: input.level || 'info',
|
|
15
|
+
event: input.event || 'node:event',
|
|
16
|
+
message: input.message || input.event || 'Node event',
|
|
17
|
+
data: input.data || {},
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
try {
|
|
21
|
+
const logDir = path.dirname(logFile)
|
|
22
|
+
if (!fs.existsSync(logDir)) {
|
|
23
|
+
fs.mkdirSync(logDir, { recursive: true })
|
|
24
|
+
}
|
|
25
|
+
fs.appendFileSync(logFile, `${JSON.stringify(entry)}\n`, 'utf-8')
|
|
26
|
+
trimLogFile()
|
|
27
|
+
} catch (err) {
|
|
28
|
+
console.warn('[NodeLog] Failed to append:', err.message)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return entry
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function list(limit = 100) {
|
|
35
|
+
try {
|
|
36
|
+
if (!fs.existsSync(logFile)) return []
|
|
37
|
+
const lines = fs
|
|
38
|
+
.readFileSync(logFile, 'utf-8')
|
|
39
|
+
.split('\n')
|
|
40
|
+
.filter(Boolean)
|
|
41
|
+
return lines
|
|
42
|
+
.slice(-Math.max(1, Math.min(Number(limit) || 100, maxLines)))
|
|
43
|
+
.map(line => {
|
|
44
|
+
try {
|
|
45
|
+
return JSON.parse(line)
|
|
46
|
+
} catch {
|
|
47
|
+
return null
|
|
48
|
+
}
|
|
49
|
+
})
|
|
50
|
+
.filter(Boolean)
|
|
51
|
+
.reverse()
|
|
52
|
+
} catch (err) {
|
|
53
|
+
console.warn('[NodeLog] Failed to read:', err.message)
|
|
54
|
+
return []
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function clear() {
|
|
59
|
+
try {
|
|
60
|
+
const logDir = path.dirname(logFile)
|
|
61
|
+
if (!fs.existsSync(logDir)) {
|
|
62
|
+
fs.mkdirSync(logDir, { recursive: true })
|
|
63
|
+
}
|
|
64
|
+
fs.writeFileSync(logFile, '', 'utf-8')
|
|
65
|
+
return true
|
|
66
|
+
} catch (err) {
|
|
67
|
+
console.warn('[NodeLog] Failed to clear:', err.message)
|
|
68
|
+
return false
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function trimLogFile() {
|
|
73
|
+
try {
|
|
74
|
+
if (!fs.existsSync(logFile)) return
|
|
75
|
+
const lines = fs
|
|
76
|
+
.readFileSync(logFile, 'utf-8')
|
|
77
|
+
.split('\n')
|
|
78
|
+
.filter(Boolean)
|
|
79
|
+
if (lines.length <= maxLines) return
|
|
80
|
+
fs.writeFileSync(
|
|
81
|
+
logFile,
|
|
82
|
+
`${lines.slice(-maxLines).join('\n')}\n`,
|
|
83
|
+
'utf-8'
|
|
84
|
+
)
|
|
85
|
+
} catch {}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return {
|
|
89
|
+
logFile,
|
|
90
|
+
append,
|
|
91
|
+
list,
|
|
92
|
+
clear,
|
|
93
|
+
}
|
|
94
|
+
}
|
package/server/src/utils/api.js
CHANGED
|
@@ -1,23 +1,189 @@
|
|
|
1
1
|
import ky from 'ky'
|
|
2
|
+
import { buildAuthHeaders, normalizeAuthPath } from './auth.js'
|
|
2
3
|
|
|
3
4
|
const STORAGE_KEY = 'mostbox_backend_url'
|
|
5
|
+
const INVITE_STORAGE_KEY = 'mostbox_backend_invite'
|
|
6
|
+
const LOCALHOST_BACKEND_URL = 'http://localhost:1976'
|
|
7
|
+
|
|
8
|
+
function isLocalFrontendOrigin() {
|
|
9
|
+
if (typeof window === 'undefined') return false
|
|
10
|
+
|
|
11
|
+
return ['localhost', '127.0.0.1'].includes(window.location.hostname)
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function getDefaultBackendUrl() {
|
|
15
|
+
return isLocalFrontendOrigin() ? LOCALHOST_BACKEND_URL : ''
|
|
16
|
+
}
|
|
4
17
|
|
|
5
18
|
function getBackendUrl() {
|
|
19
|
+
if (typeof window === 'undefined') return ''
|
|
20
|
+
return localStorage.getItem(STORAGE_KEY) || getDefaultBackendUrl()
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function getConfiguredBackendUrl() {
|
|
6
24
|
if (typeof window === 'undefined') return ''
|
|
7
25
|
return localStorage.getItem(STORAGE_KEY) || ''
|
|
8
26
|
}
|
|
9
27
|
|
|
28
|
+
function getRemoteBackendUrl() {
|
|
29
|
+
const configured = getConfiguredBackendUrl()
|
|
30
|
+
if (!configured) return ''
|
|
31
|
+
try {
|
|
32
|
+
const { hostname } = new URL(configured)
|
|
33
|
+
return ['localhost', '127.0.0.1', '::1'].includes(hostname)
|
|
34
|
+
? ''
|
|
35
|
+
: configured
|
|
36
|
+
} catch {
|
|
37
|
+
return configured
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function getBackendInvite() {
|
|
42
|
+
if (typeof window === 'undefined') return ''
|
|
43
|
+
return localStorage.getItem(INVITE_STORAGE_KEY) || ''
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function normalizeBackendUrl(url) {
|
|
47
|
+
return (url || '').trim().replace(/\/+$/, '')
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function isLocalBackendUrl(url) {
|
|
51
|
+
const value = normalizeBackendUrl(url)
|
|
52
|
+
if (!value) return false
|
|
53
|
+
try {
|
|
54
|
+
const { hostname } = new URL(value)
|
|
55
|
+
const normalized = hostname.toLowerCase()
|
|
56
|
+
return (
|
|
57
|
+
normalized === 'localhost' ||
|
|
58
|
+
normalized === '::1' ||
|
|
59
|
+
normalized === '[::1]' ||
|
|
60
|
+
normalized === '127.0.0.1' ||
|
|
61
|
+
normalized.startsWith('127.')
|
|
62
|
+
)
|
|
63
|
+
} catch {
|
|
64
|
+
return false
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function shouldAttachBackendInvite(url = getBackendUrl()) {
|
|
69
|
+
return Boolean(getBackendInvite()) && !isLocalBackendUrl(url)
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function getStoredIdentity() {
|
|
73
|
+
if (typeof window === 'undefined') return null
|
|
74
|
+
try {
|
|
75
|
+
const raw = localStorage.getItem('mostbox_identity')
|
|
76
|
+
return raw ? JSON.parse(raw) : null
|
|
77
|
+
} catch {
|
|
78
|
+
return null
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function normalizePath(path) {
|
|
83
|
+
return path.startsWith('/') ? path : `/${path}`
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function buildWebSocketUrl(base, wsPath = '/ws') {
|
|
87
|
+
const url = new URL(base)
|
|
88
|
+
const wsProtocol = url.protocol === 'https:' ? 'wss:' : 'ws:'
|
|
89
|
+
const basePath = url.pathname.replace(/\/+$/, '')
|
|
90
|
+
return `${wsProtocol}//${url.host}${basePath}${normalizePath(wsPath)}`
|
|
91
|
+
}
|
|
92
|
+
|
|
10
93
|
function createApiInstance() {
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
|
|
94
|
+
const client = ky.create({
|
|
95
|
+
hooks: {
|
|
96
|
+
beforeRequest: [
|
|
97
|
+
async ({ request }) => {
|
|
98
|
+
const headers = new Headers(request.headers || {})
|
|
99
|
+
const invite = getBackendInvite()
|
|
100
|
+
if (invite && shouldAttachBackendInvite(request.url)) {
|
|
101
|
+
headers.set('x-mostbox-invite', invite)
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const identity = getStoredIdentity()
|
|
105
|
+
if (identity?.danger) {
|
|
106
|
+
try {
|
|
107
|
+
const authHeaders = await buildAuthHeaders(
|
|
108
|
+
identity,
|
|
109
|
+
request.method,
|
|
110
|
+
normalizeAuthPath(request.url)
|
|
111
|
+
)
|
|
112
|
+
for (const [key, value] of Object.entries(authHeaders)) {
|
|
113
|
+
headers.set(key, value)
|
|
114
|
+
}
|
|
115
|
+
} catch {
|
|
116
|
+
// Ignore invalid legacy identity data for public/backend probes.
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
return new Request(request, { headers })
|
|
120
|
+
},
|
|
121
|
+
],
|
|
122
|
+
},
|
|
123
|
+
})
|
|
124
|
+
|
|
125
|
+
return new Proxy(client, {
|
|
126
|
+
get(target, prop, receiver) {
|
|
127
|
+
const value = Reflect.get(target, prop, receiver)
|
|
128
|
+
if (!['get', 'post', 'put', 'patch', 'delete', 'head'].includes(prop)) {
|
|
129
|
+
return value
|
|
130
|
+
}
|
|
131
|
+
return (input, options) => {
|
|
132
|
+
const nextInput = typeof input === 'string' ? getApiUrl(input) : input
|
|
133
|
+
return value.call(target, nextInput, options)
|
|
134
|
+
}
|
|
135
|
+
},
|
|
14
136
|
})
|
|
15
137
|
}
|
|
16
138
|
|
|
17
139
|
export let api = createApiInstance()
|
|
18
140
|
|
|
141
|
+
export async function getApiErrorPayload(err) {
|
|
142
|
+
const response =
|
|
143
|
+
err && typeof err === 'object' && 'response' in err
|
|
144
|
+
? err.response
|
|
145
|
+
: err instanceof Response
|
|
146
|
+
? err
|
|
147
|
+
: null
|
|
148
|
+
|
|
149
|
+
if (!response) return {}
|
|
150
|
+
|
|
151
|
+
const data = response.bodyUsed
|
|
152
|
+
? null
|
|
153
|
+
: await response
|
|
154
|
+
.clone()
|
|
155
|
+
.json()
|
|
156
|
+
.catch(() => null)
|
|
157
|
+
|
|
158
|
+
return {
|
|
159
|
+
status: response.status,
|
|
160
|
+
code: typeof data?.code === 'string' ? data.code : undefined,
|
|
161
|
+
error:
|
|
162
|
+
typeof data?.error === 'string'
|
|
163
|
+
? data.error
|
|
164
|
+
: typeof data?.message === 'string'
|
|
165
|
+
? data.message
|
|
166
|
+
: undefined,
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
export async function getApiErrorMessage(err, fallback = '请求失败') {
|
|
171
|
+
const data = await getApiErrorPayload(err)
|
|
172
|
+
if (data.error) return data.error
|
|
173
|
+
|
|
174
|
+
const errorName =
|
|
175
|
+
err && typeof err === 'object' && 'name' in err ? String(err.name) : ''
|
|
176
|
+
if (errorName === 'TimeoutError') return '请求超时,请稍后重试'
|
|
177
|
+
|
|
178
|
+
if (err instanceof Error && err.message) {
|
|
179
|
+
return err.message
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
return fallback
|
|
183
|
+
}
|
|
184
|
+
|
|
19
185
|
export function setBackendUrl(url) {
|
|
20
|
-
const cleaned = (url
|
|
186
|
+
const cleaned = normalizeBackendUrl(url)
|
|
21
187
|
if (cleaned) {
|
|
22
188
|
localStorage.setItem(STORAGE_KEY, cleaned)
|
|
23
189
|
} else {
|
|
@@ -26,24 +192,209 @@ export function setBackendUrl(url) {
|
|
|
26
192
|
api = createApiInstance()
|
|
27
193
|
}
|
|
28
194
|
|
|
195
|
+
export function setBackendInvite(invite) {
|
|
196
|
+
const cleaned = (invite || '').trim()
|
|
197
|
+
if (cleaned) {
|
|
198
|
+
localStorage.setItem(INVITE_STORAGE_KEY, cleaned)
|
|
199
|
+
} else {
|
|
200
|
+
localStorage.removeItem(INVITE_STORAGE_KEY)
|
|
201
|
+
}
|
|
202
|
+
api = createApiInstance()
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
export function configureBackend({ url, invite }) {
|
|
206
|
+
setBackendUrl(url)
|
|
207
|
+
setBackendInvite(invite)
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
export function clearBackendConnection() {
|
|
211
|
+
setBackendUrl('')
|
|
212
|
+
setBackendInvite('')
|
|
213
|
+
}
|
|
214
|
+
|
|
29
215
|
export function getBackendUrlExport() {
|
|
30
216
|
return getBackendUrl()
|
|
31
217
|
}
|
|
32
218
|
|
|
219
|
+
export function getRemoteBackendUrlExport() {
|
|
220
|
+
return getRemoteBackendUrl()
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
export function getBackendInviteExport() {
|
|
224
|
+
return getBackendInvite()
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
export function getApiUrl(path) {
|
|
228
|
+
const url = getBackendUrl()
|
|
229
|
+
return `${url}${normalizePath(path)}`
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
export async function getApiRequestHeaders(method = 'GET', path = '/') {
|
|
233
|
+
/** @type {Record<string, string>} */
|
|
234
|
+
const headers = {}
|
|
235
|
+
const invite = getBackendInvite()
|
|
236
|
+
if (invite && shouldAttachBackendInvite()) {
|
|
237
|
+
headers['x-mostbox-invite'] = invite
|
|
238
|
+
}
|
|
239
|
+
try {
|
|
240
|
+
Object.assign(
|
|
241
|
+
headers,
|
|
242
|
+
await buildAuthHeaders(
|
|
243
|
+
getStoredIdentity(),
|
|
244
|
+
method,
|
|
245
|
+
normalizeAuthPath(path)
|
|
246
|
+
)
|
|
247
|
+
)
|
|
248
|
+
} catch {
|
|
249
|
+
// Callers that require auth will receive the server's 401 response.
|
|
250
|
+
}
|
|
251
|
+
return headers
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
export function getWebSocketUrl(path = '/ws') {
|
|
255
|
+
if (typeof window === 'undefined') return normalizePath(path)
|
|
256
|
+
|
|
257
|
+
const base = getBackendUrl() || window.location.origin
|
|
258
|
+
return buildWebSocketUrl(base, path)
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
export async function getAuthenticatedWebSocketUrl(path = '/ws') {
|
|
262
|
+
if (typeof window === 'undefined') return normalizePath(path)
|
|
263
|
+
|
|
264
|
+
const base = getBackendUrl() || window.location.origin
|
|
265
|
+
const url = new URL(buildWebSocketUrl(base, path))
|
|
266
|
+
|
|
267
|
+
const invite = getBackendInvite()
|
|
268
|
+
if (invite && shouldAttachBackendInvite(url.toString())) {
|
|
269
|
+
url.searchParams.set('invite', invite)
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
const identity = getStoredIdentity()
|
|
273
|
+
if (identity?.danger) {
|
|
274
|
+
try {
|
|
275
|
+
const auth = await buildAuthHeaders(
|
|
276
|
+
identity,
|
|
277
|
+
'GET',
|
|
278
|
+
normalizeAuthPath(path)
|
|
279
|
+
)
|
|
280
|
+
const [address, timestamp, signature] = String(
|
|
281
|
+
auth.Authorization || ''
|
|
282
|
+
).split(',')
|
|
283
|
+
if (address && signature) {
|
|
284
|
+
url.searchParams.set('address', address)
|
|
285
|
+
url.searchParams.set('timestamp', timestamp)
|
|
286
|
+
url.searchParams.set('signature', signature)
|
|
287
|
+
}
|
|
288
|
+
} catch {
|
|
289
|
+
// Leave WebSocket unauthenticated when local identity data is invalid.
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
return url.toString()
|
|
294
|
+
}
|
|
295
|
+
|
|
33
296
|
export async function checkBackendConnection() {
|
|
34
297
|
const url = getBackendUrl()
|
|
298
|
+
const invite = shouldAttachBackendInvite(url) ? getBackendInvite() : ''
|
|
299
|
+
return checkBackendConnectionTarget({ url, invite })
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
async function probeHttp(cleanedUrl, invite, identity) {
|
|
35
303
|
try {
|
|
36
|
-
const
|
|
304
|
+
const headers = {}
|
|
305
|
+
if (invite) headers['x-mostbox-invite'] = invite
|
|
306
|
+
try {
|
|
307
|
+
Object.assign(
|
|
308
|
+
headers,
|
|
309
|
+
await buildAuthHeaders(identity, 'GET', '/api/remote/capabilities')
|
|
310
|
+
)
|
|
311
|
+
} catch {
|
|
312
|
+
// Backend detection should still work when old identity data is invalid.
|
|
313
|
+
}
|
|
314
|
+
const res = await fetch(`${cleanedUrl}/api/remote/capabilities`, {
|
|
37
315
|
method: 'GET',
|
|
316
|
+
headers,
|
|
38
317
|
signal: AbortSignal.timeout(3000),
|
|
39
318
|
})
|
|
40
|
-
|
|
319
|
+
if (!res.ok) return { ok: false, reason: 'http' }
|
|
320
|
+
return { ok: true }
|
|
41
321
|
} catch {
|
|
42
|
-
return false
|
|
322
|
+
return { ok: false, reason: 'http' }
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
async function probeWebSocket(cleanedUrl, invite, identity) {
|
|
327
|
+
if (typeof WebSocket === 'undefined') return { ok: true }
|
|
328
|
+
|
|
329
|
+
try {
|
|
330
|
+
const wsUrl = new URL(buildWebSocketUrl(cleanedUrl))
|
|
331
|
+
|
|
332
|
+
if (invite) {
|
|
333
|
+
wsUrl.searchParams.set('invite', invite)
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
if (identity?.danger) {
|
|
337
|
+
try {
|
|
338
|
+
const auth = await buildAuthHeaders(
|
|
339
|
+
identity,
|
|
340
|
+
'GET',
|
|
341
|
+
normalizeAuthPath('/ws')
|
|
342
|
+
)
|
|
343
|
+
const [address, timestamp, signature] = String(
|
|
344
|
+
auth.Authorization || ''
|
|
345
|
+
).split(',')
|
|
346
|
+
if (address && signature) {
|
|
347
|
+
wsUrl.searchParams.set('address', address)
|
|
348
|
+
wsUrl.searchParams.set('timestamp', timestamp)
|
|
349
|
+
wsUrl.searchParams.set('signature', signature)
|
|
350
|
+
}
|
|
351
|
+
} catch {
|
|
352
|
+
// Leave WebSocket unauthenticated when local identity data is invalid.
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
return await new Promise(resolve => {
|
|
357
|
+
const ws = new WebSocket(wsUrl.toString())
|
|
358
|
+
const timeout = setTimeout(() => {
|
|
359
|
+
ws.close()
|
|
360
|
+
resolve({ ok: false, reason: 'ws' })
|
|
361
|
+
}, 4000)
|
|
362
|
+
|
|
363
|
+
ws.onopen = () => {
|
|
364
|
+
clearTimeout(timeout)
|
|
365
|
+
ws.close()
|
|
366
|
+
resolve({ ok: true })
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
ws.onerror = () => {
|
|
370
|
+
clearTimeout(timeout)
|
|
371
|
+
resolve({ ok: false, reason: 'ws' })
|
|
372
|
+
}
|
|
373
|
+
})
|
|
374
|
+
} catch {
|
|
375
|
+
return { ok: false, reason: 'ws' }
|
|
43
376
|
}
|
|
44
377
|
}
|
|
45
378
|
|
|
379
|
+
export async function checkBackendConnectionTarget({ url, invite = '' }) {
|
|
380
|
+
const cleanedUrl = normalizeBackendUrl(url)
|
|
381
|
+
if (!cleanedUrl) return { ok: false, reason: 'http' }
|
|
382
|
+
|
|
383
|
+
const identity = getStoredIdentity()
|
|
384
|
+
|
|
385
|
+
const [httpResult, wsResult] = await Promise.all([
|
|
386
|
+
probeHttp(cleanedUrl, invite, identity),
|
|
387
|
+
probeWebSocket(cleanedUrl, invite, identity),
|
|
388
|
+
])
|
|
389
|
+
|
|
390
|
+
if (!httpResult.ok) return httpResult
|
|
391
|
+
if (!wsResult.ok) return wsResult
|
|
392
|
+
return { ok: true }
|
|
393
|
+
}
|
|
394
|
+
|
|
46
395
|
export async function detectSameOriginBackend() {
|
|
396
|
+
if (isLocalFrontendOrigin()) return false
|
|
397
|
+
|
|
47
398
|
try {
|
|
48
399
|
const res = await fetch('/api/node-id', {
|
|
49
400
|
method: 'GET',
|
|
@@ -57,7 +408,7 @@ export async function detectSameOriginBackend() {
|
|
|
57
408
|
|
|
58
409
|
export async function detectLocalhostBackend() {
|
|
59
410
|
try {
|
|
60
|
-
const res = await fetch(
|
|
411
|
+
const res = await fetch(`${LOCALHOST_BACKEND_URL}/api/node-id`, {
|
|
61
412
|
method: 'GET',
|
|
62
413
|
signal: AbortSignal.timeout(2000),
|
|
63
414
|
})
|