most-box 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -2
- 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.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/00-u5nq76f0.j.js +1 -0
- package/out/_next/static/chunks/00d9h1tddnnnd.js +1 -0
- package/out/_next/static/chunks/00fm8lijienf1.js +1 -0
- package/out/_next/static/chunks/00o9ht.f2qm00.css +4 -0
- package/out/_next/static/chunks/00tkdqwxch-3s.js +1 -0
- package/out/_next/static/chunks/00zi-erhjrny2.js +2 -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/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/08.72abkgwy9g.js +1 -0
- package/out/_next/static/chunks/084xf0edl9sfo.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/09f1gfke9m5wg.css +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/09xyi6fpro_d-.css +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_npg_pcoywti.js +5 -0
- package/out/_next/static/chunks/0_r_mk1~6bosc.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/0ao1lbi4b.sfa.js +1 -0
- package/out/_next/static/chunks/0arm0a6adt7cc.css +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/{0e_h0d3ekzks8.css → 0c9j3eq_14vv2.css} +1 -1
- 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/0d4bueddmcnca.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/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_fpgh7drfda.js +1 -0
- package/out/_next/static/chunks/0gtwvy1z9ksa7.css +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/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/0j27tcmtt4ly7.js +1 -0
- package/out/_next/static/chunks/0j3v4mq67wtnh.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/0l682p362d-5w.js +1 -0
- package/out/_next/static/chunks/0lkmf5ry.s_7w.js +1 -0
- package/out/_next/static/chunks/0m68p9txef5rs.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/0n.qlfk~z7o.6.js +1 -0
- package/out/_next/static/chunks/0n4t80gjc3q5h.js +1 -0
- package/out/_next/static/chunks/{0n~dq4kpx9xxx.js → 0o6lrkxy4jwag.js} +1 -1
- package/out/_next/static/chunks/0o98f1yq..o.8.js +1 -0
- package/out/_next/static/chunks/0oz3yl6_-716p.js +1 -0
- package/out/_next/static/chunks/0p486m03-zfoi.js +1 -0
- package/out/_next/static/chunks/0qou.u2e2dy48.css +24 -0
- package/out/_next/static/chunks/0qqupeexg83u7.js +1 -0
- package/out/_next/static/chunks/0r1~k82nji8sf.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/0usvo~vu7r8np.js +736 -0
- package/out/_next/static/chunks/0v68pdrp54lb-.js +1 -0
- package/out/_next/static/chunks/0v7qp4hv-_._r.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/0wuwlgcn6gxqt.js +1 -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/0xl5_avhu._i8.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/10kvl8vj_plm-.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/1380op_pfk.qo.js +1 -0
- package/out/_next/static/chunks/146oiw1bggtn4.js +1 -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/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/16m27azcs4k6w.js +1 -0
- package/out/_next/static/chunks/16u9f35gylw8l.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-0xs6mybc~5t_3.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/changelog/__next._full.txt +24 -21
- package/out/changelog/__next._head.txt +3 -3
- package/out/changelog/__next._index.txt +8 -6
- package/out/changelog/__next._tree.txt +5 -3
- package/out/changelog/__next.changelog.__PAGE__.txt +5 -5
- package/out/changelog/__next.changelog.txt +3 -3
- package/out/changelog/index.html +2 -2
- package/out/changelog/index.txt +24 -21
- 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/docs/__next._full.txt +24 -21
- package/out/docs/__next._head.txt +3 -3
- package/out/docs/__next._index.txt +8 -6
- package/out/docs/__next._tree.txt +5 -3
- package/out/docs/__next.docs.__PAGE__.txt +5 -5
- package/out/docs/__next.docs.txt +3 -3
- package/out/docs/getting-started/__next._full.txt +24 -21
- package/out/docs/getting-started/__next._head.txt +3 -3
- package/out/docs/getting-started/__next._index.txt +8 -6
- package/out/docs/getting-started/__next._tree.txt +5 -3
- package/out/docs/getting-started/__next.docs.getting-started.__PAGE__.txt +5 -5
- package/out/docs/getting-started/__next.docs.getting-started.txt +3 -3
- package/out/docs/getting-started/__next.docs.txt +3 -3
- package/out/docs/getting-started/index.html +2 -2
- package/out/docs/getting-started/index.txt +24 -21
- package/out/docs/index.html +2 -2
- package/out/docs/index.txt +24 -21
- package/out/download/__next._full.txt +33 -32
- package/out/download/__next._head.txt +3 -3
- package/out/download/__next._index.txt +8 -6
- package/out/download/__next._tree.txt +5 -3
- package/out/download/__next.download.__PAGE__.txt +10 -11
- package/out/download/__next.download.txt +3 -3
- package/out/download/index.html +2 -2
- package/out/download/index.txt +33 -32
- package/out/index.html +2 -2
- package/out/index.txt +23 -20
- package/out/note/__next._full.txt +24 -0
- package/out/note/__next._head.txt +5 -0
- 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/edit/__next._full.txt +24 -0
- package/out/note/edit/__next._head.txt +5 -0
- package/out/note/edit/__next._index.txt +9 -0
- package/out/note/edit/__next._tree.txt +4 -0
- package/out/note/edit/__next.note.edit.__PAGE__.txt +9 -0
- package/out/note/edit/__next.note.edit.txt +5 -0
- package/out/note/edit/__next.note.txt +5 -0
- package/out/note/edit/index.html +15 -0
- package/out/note/edit/index.txt +24 -0
- package/out/note/index.html +15 -0
- package/out/note/index.txt +24 -0
- package/out/ping/__next._full.txt +22 -19
- package/out/ping/__next._head.txt +3 -3
- package/out/ping/__next._index.txt +8 -6
- package/out/ping/__next._tree.txt +5 -3
- package/out/ping/__next.ping.__PAGE__.txt +5 -5
- package/out/ping/__next.ping.txt +3 -3
- package/out/ping/index.html +2 -2
- package/out/ping/index.txt +22 -19
- 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 +12 -5
- package/server/index.js +558 -101
- package/server/src/config.js +4 -0
- package/server/src/core/cid.js +53 -32
- package/server/src/index.js +772 -122
- package/server/src/node/config.js +159 -0
- package/server/src/node/logs.js +94 -0
- package/server/src/utils/api.js +80 -2
- package/server/src/utils/errors.js +7 -0
- package/server/src/utils/mostWallet.js +34 -1
- package/server/src/utils/noteBackup.js +119 -0
- package/server/src/utils/noteUtils.js +120 -0
- package/server/src/utils/userIdentity.js +8 -60
- 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/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/_next/static/{iOB2EBwOGZ0iYW7Lbg9u_ → sIuUKxnnGU7K9Tu9UDKE8}/_buildManifest.js +0 -0
- /package/out/_next/static/{iOB2EBwOGZ0iYW7Lbg9u_ → sIuUKxnnGU7K9Tu9UDKE8}/_clientMiddlewareManifest.js +0 -0
- /package/out/_next/static/{iOB2EBwOGZ0iYW7Lbg9u_ → sIuUKxnnGU7K9Tu9UDKE8}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,159 @@
|
|
|
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
|
+
|
|
10
|
+
export function getDefaultConfigDir() {
|
|
11
|
+
return process.env.MOSTBOX_CONFIG_DIR
|
|
12
|
+
? path.resolve(process.env.MOSTBOX_CONFIG_DIR)
|
|
13
|
+
: 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
|
+
capacityBytes: DEFAULT_CAPACITY_BYTES,
|
|
24
|
+
maxFileSizeBytes: MAX_FILE_SIZE,
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function normalizeNodeConfig(raw = {}) {
|
|
29
|
+
const defaults = getDefaultNodeConfig()
|
|
30
|
+
const rawNode = raw.node && typeof raw.node === 'object' ? raw.node : {}
|
|
31
|
+
|
|
32
|
+
const capacityBytes = normalizePositiveInteger(
|
|
33
|
+
rawNode.capacityBytes ?? raw.capacityBytes,
|
|
34
|
+
defaults.capacityBytes
|
|
35
|
+
)
|
|
36
|
+
const maxFileSizeBytes = normalizePositiveInteger(
|
|
37
|
+
rawNode.maxFileSizeBytes ?? raw.maxFileSizeBytes,
|
|
38
|
+
defaults.maxFileSizeBytes
|
|
39
|
+
)
|
|
40
|
+
return {
|
|
41
|
+
dataPath:
|
|
42
|
+
typeof raw.dataPath === 'string'
|
|
43
|
+
? raw.dataPath.trim()
|
|
44
|
+
: defaults.dataPath,
|
|
45
|
+
capacityBytes,
|
|
46
|
+
maxFileSizeBytes,
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function createNodeConfigStore(configDir = getDefaultConfigDir()) {
|
|
51
|
+
const resolvedConfigDir = path.resolve(configDir)
|
|
52
|
+
const configFile = path.join(resolvedConfigDir, 'config.json')
|
|
53
|
+
|
|
54
|
+
function loadRawConfig() {
|
|
55
|
+
try {
|
|
56
|
+
if (fs.existsSync(configFile)) {
|
|
57
|
+
return JSON.parse(fs.readFileSync(configFile, 'utf-8'))
|
|
58
|
+
}
|
|
59
|
+
} catch (err) {
|
|
60
|
+
console.error('[Config] Load error:', err.message)
|
|
61
|
+
}
|
|
62
|
+
return {}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function saveRawConfig(config) {
|
|
66
|
+
try {
|
|
67
|
+
if (!fs.existsSync(resolvedConfigDir)) {
|
|
68
|
+
fs.mkdirSync(resolvedConfigDir, { recursive: true })
|
|
69
|
+
}
|
|
70
|
+
const tmpPath = configFile + '.tmp'
|
|
71
|
+
fs.writeFileSync(tmpPath, JSON.stringify(config, null, 2), 'utf-8')
|
|
72
|
+
fs.renameSync(tmpPath, configFile)
|
|
73
|
+
return true
|
|
74
|
+
} catch (err) {
|
|
75
|
+
console.error('[Config] Save error:', err.message)
|
|
76
|
+
return false
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function getNodeConfig() {
|
|
81
|
+
return normalizeNodeConfig(loadRawConfig())
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function getDataPath() {
|
|
85
|
+
if (process.env.MOSTBOX_DATA_PATH) {
|
|
86
|
+
return process.env.MOSTBOX_DATA_PATH
|
|
87
|
+
}
|
|
88
|
+
return getNodeConfig().dataPath || getDefaultDataPath()
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function saveNodeConfigPatch(patch = {}) {
|
|
92
|
+
const raw = loadRawConfig()
|
|
93
|
+
const current = normalizeNodeConfig(raw)
|
|
94
|
+
const next = normalizeNodeConfig({
|
|
95
|
+
...raw,
|
|
96
|
+
dataPath:
|
|
97
|
+
patch.dataPath === undefined ? current.dataPath : patch.dataPath,
|
|
98
|
+
node: {
|
|
99
|
+
...(raw.node && typeof raw.node === 'object' ? raw.node : {}),
|
|
100
|
+
capacityBytes:
|
|
101
|
+
patch.capacityBytes === undefined
|
|
102
|
+
? current.capacityBytes
|
|
103
|
+
: patch.capacityBytes,
|
|
104
|
+
maxFileSizeBytes:
|
|
105
|
+
patch.maxFileSizeBytes === undefined
|
|
106
|
+
? current.maxFileSizeBytes
|
|
107
|
+
: patch.maxFileSizeBytes,
|
|
108
|
+
},
|
|
109
|
+
})
|
|
110
|
+
|
|
111
|
+
const saved = {
|
|
112
|
+
dataPath: next.dataPath,
|
|
113
|
+
node: {
|
|
114
|
+
capacityBytes: next.capacityBytes,
|
|
115
|
+
maxFileSizeBytes: next.maxFileSizeBytes,
|
|
116
|
+
updatedAt: new Date().toISOString(),
|
|
117
|
+
},
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
return { success: saveRawConfig(saved), config: normalizeNodeConfig(saved) }
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return {
|
|
124
|
+
configDir: resolvedConfigDir,
|
|
125
|
+
configFile,
|
|
126
|
+
loadRawConfig,
|
|
127
|
+
saveRawConfig,
|
|
128
|
+
getNodeConfig,
|
|
129
|
+
getDataPath,
|
|
130
|
+
saveNodeConfigPatch,
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
export function evaluateStorageLimits(config, input = {}) {
|
|
135
|
+
const size = Number(input.size ?? input.fileSize ?? 0)
|
|
136
|
+
const reasons = []
|
|
137
|
+
|
|
138
|
+
if (!Number.isFinite(size) || size < 0) {
|
|
139
|
+
reasons.push('invalid-size')
|
|
140
|
+
} else if (size > config.maxFileSizeBytes) {
|
|
141
|
+
reasons.push('file-too-large')
|
|
142
|
+
} else if (size > config.capacityBytes) {
|
|
143
|
+
reasons.push('capacity-too-small')
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
return {
|
|
147
|
+
accepted: reasons.length === 0,
|
|
148
|
+
reasons,
|
|
149
|
+
policy: config,
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function normalizePositiveInteger(value, fallback) {
|
|
154
|
+
const parsed = Number(value)
|
|
155
|
+
if (!Number.isFinite(parsed) || parsed < 0) {
|
|
156
|
+
return fallback
|
|
157
|
+
}
|
|
158
|
+
return Math.floor(parsed)
|
|
159
|
+
}
|
|
@@ -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,10 +1,28 @@
|
|
|
1
1
|
import ky from 'ky'
|
|
2
2
|
|
|
3
3
|
const STORAGE_KEY = 'mostbox_backend_url'
|
|
4
|
+
const LOCALHOST_BACKEND_URL = 'http://localhost:1976'
|
|
5
|
+
|
|
6
|
+
function isLocalFrontendOrigin() {
|
|
7
|
+
if (typeof window === 'undefined') return false
|
|
8
|
+
|
|
9
|
+
return (
|
|
10
|
+
['localhost', '127.0.0.1'].includes(window.location.hostname) &&
|
|
11
|
+
window.location.port === '3000'
|
|
12
|
+
)
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function getDefaultBackendUrl() {
|
|
16
|
+
return isLocalFrontendOrigin() ? LOCALHOST_BACKEND_URL : ''
|
|
17
|
+
}
|
|
4
18
|
|
|
5
19
|
function getBackendUrl() {
|
|
6
20
|
if (typeof window === 'undefined') return ''
|
|
7
|
-
return localStorage.getItem(STORAGE_KEY) ||
|
|
21
|
+
return localStorage.getItem(STORAGE_KEY) || getDefaultBackendUrl()
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function normalizePath(path) {
|
|
25
|
+
return path.startsWith('/') ? path : `/${path}`
|
|
8
26
|
}
|
|
9
27
|
|
|
10
28
|
function createApiInstance() {
|
|
@@ -16,6 +34,50 @@ function createApiInstance() {
|
|
|
16
34
|
|
|
17
35
|
export let api = createApiInstance()
|
|
18
36
|
|
|
37
|
+
export async function getApiErrorPayload(err) {
|
|
38
|
+
const response =
|
|
39
|
+
err && typeof err === 'object' && 'response' in err
|
|
40
|
+
? err.response
|
|
41
|
+
: err instanceof Response
|
|
42
|
+
? err
|
|
43
|
+
: null
|
|
44
|
+
|
|
45
|
+
if (!response) return {}
|
|
46
|
+
|
|
47
|
+
const data = response.bodyUsed
|
|
48
|
+
? null
|
|
49
|
+
: await response
|
|
50
|
+
.clone()
|
|
51
|
+
.json()
|
|
52
|
+
.catch(() => null)
|
|
53
|
+
|
|
54
|
+
return {
|
|
55
|
+
status: response.status,
|
|
56
|
+
code: typeof data?.code === 'string' ? data.code : undefined,
|
|
57
|
+
error:
|
|
58
|
+
typeof data?.error === 'string'
|
|
59
|
+
? data.error
|
|
60
|
+
: typeof data?.message === 'string'
|
|
61
|
+
? data.message
|
|
62
|
+
: undefined,
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export async function getApiErrorMessage(err, fallback = '请求失败') {
|
|
67
|
+
const data = await getApiErrorPayload(err)
|
|
68
|
+
if (data.error) return data.error
|
|
69
|
+
|
|
70
|
+
const errorName =
|
|
71
|
+
err && typeof err === 'object' && 'name' in err ? String(err.name) : ''
|
|
72
|
+
if (errorName === 'TimeoutError') return '请求超时,请稍后重试'
|
|
73
|
+
|
|
74
|
+
if (!data.status && err instanceof Error && err.message) {
|
|
75
|
+
return err.message
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return fallback
|
|
79
|
+
}
|
|
80
|
+
|
|
19
81
|
export function setBackendUrl(url) {
|
|
20
82
|
const cleaned = (url || '').trim().replace(/\/+$/, '')
|
|
21
83
|
if (cleaned) {
|
|
@@ -30,6 +92,20 @@ export function getBackendUrlExport() {
|
|
|
30
92
|
return getBackendUrl()
|
|
31
93
|
}
|
|
32
94
|
|
|
95
|
+
export function getApiUrl(path) {
|
|
96
|
+
const url = getBackendUrl()
|
|
97
|
+
return `${url}${normalizePath(path)}`
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export function getWebSocketUrl(path = '/ws') {
|
|
101
|
+
if (typeof window === 'undefined') return normalizePath(path)
|
|
102
|
+
|
|
103
|
+
const base = getBackendUrl() || window.location.origin
|
|
104
|
+
const url = new URL(normalizePath(path), base)
|
|
105
|
+
url.protocol = url.protocol === 'https:' ? 'wss:' : 'ws:'
|
|
106
|
+
return url.toString()
|
|
107
|
+
}
|
|
108
|
+
|
|
33
109
|
export async function checkBackendConnection() {
|
|
34
110
|
const url = getBackendUrl()
|
|
35
111
|
try {
|
|
@@ -44,6 +120,8 @@ export async function checkBackendConnection() {
|
|
|
44
120
|
}
|
|
45
121
|
|
|
46
122
|
export async function detectSameOriginBackend() {
|
|
123
|
+
if (isLocalFrontendOrigin()) return false
|
|
124
|
+
|
|
47
125
|
try {
|
|
48
126
|
const res = await fetch('/api/node-id', {
|
|
49
127
|
method: 'GET',
|
|
@@ -57,7 +135,7 @@ export async function detectSameOriginBackend() {
|
|
|
57
135
|
|
|
58
136
|
export async function detectLocalhostBackend() {
|
|
59
137
|
try {
|
|
60
|
-
const res = await fetch(
|
|
138
|
+
const res = await fetch(`${LOCALHOST_BACKEND_URL}/api/node-id`, {
|
|
61
139
|
method: 'GET',
|
|
62
140
|
signal: AbortSignal.timeout(2000),
|
|
63
141
|
})
|
|
@@ -58,6 +58,13 @@ export class PermissionError extends AppError {
|
|
|
58
58
|
}
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
+
export class ConflictError extends AppError {
|
|
62
|
+
constructor(message = 'Resource conflict') {
|
|
63
|
+
super(message, 'CONFLICT')
|
|
64
|
+
this.name = 'ConflictError'
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
61
68
|
export class EngineNotInitializedError extends AppError {
|
|
62
69
|
constructor(message = 'Engine not initialized. Call start() first.') {
|
|
63
70
|
super(message, 'ENGINE_NOT_INITIALIZED')
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
|
+
decodeBase64,
|
|
3
|
+
encodeBase64,
|
|
2
4
|
pbkdf2,
|
|
3
5
|
sha256,
|
|
4
6
|
getBytes,
|
|
@@ -10,7 +12,7 @@ import {
|
|
|
10
12
|
import nacl from 'tweetnacl'
|
|
11
13
|
|
|
12
14
|
const SALT_PREFIX = '/most.box/'
|
|
13
|
-
const PBKDF2_ITERATIONS =
|
|
15
|
+
const PBKDF2_ITERATIONS = 50_000
|
|
14
16
|
const PBKDF2_KEY_LENGTH = 32
|
|
15
17
|
|
|
16
18
|
export function mostWallet(username, password) {
|
|
@@ -40,3 +42,34 @@ export function most25519(danger) {
|
|
|
40
42
|
ed_public_key: hexlify(ed25519KeyPair.publicKey),
|
|
41
43
|
}
|
|
42
44
|
}
|
|
45
|
+
|
|
46
|
+
export async function mostSignMessage(danger, message) {
|
|
47
|
+
const account = HDNodeWallet.fromPhrase(mostMnemonic(danger))
|
|
48
|
+
return {
|
|
49
|
+
address: account.address,
|
|
50
|
+
signature: await account.signMessage(message),
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export function mostEncode(text, danger) {
|
|
55
|
+
const bytes = new TextEncoder().encode(text)
|
|
56
|
+
const nonce = nacl.randomBytes(nacl.secretbox.nonceLength)
|
|
57
|
+
const key = getBytes(danger).slice(0, nacl.secretbox.keyLength)
|
|
58
|
+
const encrypted = nacl.secretbox(bytes, nonce, key)
|
|
59
|
+
|
|
60
|
+
return ['mp://1', encodeBase64(nonce), encodeBase64(encrypted)].join('.')
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export function mostDecode(data, danger) {
|
|
64
|
+
const [prefix, nonce64, encrypted64] = String(data || '').split('.')
|
|
65
|
+
if (prefix !== 'mp://1' || !nonce64 || !encrypted64) return ''
|
|
66
|
+
|
|
67
|
+
const key = getBytes(danger).slice(0, nacl.secretbox.keyLength)
|
|
68
|
+
const decrypted = nacl.secretbox.open(
|
|
69
|
+
decodeBase64(encrypted64),
|
|
70
|
+
decodeBase64(nonce64),
|
|
71
|
+
key
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
return decrypted ? new TextDecoder().decode(decrypted) : ''
|
|
75
|
+
}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { mostDecode, mostEncode, mostSignMessage } from './mostWallet.js'
|
|
2
|
+
import { calculateNoteCid } from './noteUtils.js'
|
|
3
|
+
|
|
4
|
+
export const NOTE_BACKUP_API_URL = 'https://api.most.box/api/backup'
|
|
5
|
+
|
|
6
|
+
async function readBackupApiError(response, fallback) {
|
|
7
|
+
const data = await response
|
|
8
|
+
.clone()
|
|
9
|
+
.json()
|
|
10
|
+
.catch(() => null)
|
|
11
|
+
return data?.error || fallback
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function encryptNotesBackup(notes, danger) {
|
|
15
|
+
return mostEncode(JSON.stringify({ notes: notes || [] }), danger)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function decryptNotesBackup(content, danger) {
|
|
19
|
+
if (!String(content || '').startsWith('mp://1')) {
|
|
20
|
+
throw new Error('无效的备份数据格式')
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const decrypted = mostDecode(content, danger)
|
|
24
|
+
if (!decrypted) {
|
|
25
|
+
throw new Error('解密失败,请确认当前 Web3 登录账号正确')
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const data = JSON.parse(decrypted)
|
|
29
|
+
if (!Array.isArray(data.notes)) {
|
|
30
|
+
throw new Error('备份数据缺少 notes')
|
|
31
|
+
}
|
|
32
|
+
return data
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export async function calculateNotesBackupCid(notes) {
|
|
36
|
+
return calculateNoteCid(JSON.stringify({ notes: notes || [] }))
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export async function getBackupAuthHeaders(
|
|
40
|
+
wallet,
|
|
41
|
+
method,
|
|
42
|
+
url = NOTE_BACKUP_API_URL
|
|
43
|
+
) {
|
|
44
|
+
const timestamp = Date.now().toString()
|
|
45
|
+
const path = new URL(url).pathname
|
|
46
|
+
const message = `${timestamp}:${String(method).toUpperCase()}:${path}`
|
|
47
|
+
const { address, signature } = await mostSignMessage(wallet.danger, message)
|
|
48
|
+
return {
|
|
49
|
+
Authorization: `${address},${timestamp},${signature}`,
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export async function buildNotesBackupUpload(wallet, notes) {
|
|
54
|
+
const payload = JSON.stringify({ notes: notes || [] })
|
|
55
|
+
const cid = await calculateNoteCid(payload)
|
|
56
|
+
const encrypted = encryptNotesBackup(notes, wallet.danger)
|
|
57
|
+
return {
|
|
58
|
+
cid,
|
|
59
|
+
body: encrypted,
|
|
60
|
+
headers: {
|
|
61
|
+
'Content-Type': 'text/plain',
|
|
62
|
+
'x-backup-cid': cid,
|
|
63
|
+
...(await getBackupAuthHeaders(wallet, 'PUT', NOTE_BACKUP_API_URL)),
|
|
64
|
+
},
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export async function uploadNotesBackup(
|
|
69
|
+
wallet,
|
|
70
|
+
notes,
|
|
71
|
+
url = NOTE_BACKUP_API_URL
|
|
72
|
+
) {
|
|
73
|
+
const upload = await buildNotesBackupUpload(wallet, notes)
|
|
74
|
+
const response = await fetch(url, {
|
|
75
|
+
method: 'PUT',
|
|
76
|
+
headers: upload.headers,
|
|
77
|
+
body: upload.body,
|
|
78
|
+
})
|
|
79
|
+
if (!response.ok) {
|
|
80
|
+
throw new Error(await readBackupApiError(response, '云备份失败'))
|
|
81
|
+
}
|
|
82
|
+
return {
|
|
83
|
+
cid: upload.cid,
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export async function downloadNotesBackup(
|
|
88
|
+
wallet,
|
|
89
|
+
url = NOTE_BACKUP_API_URL
|
|
90
|
+
) {
|
|
91
|
+
const response = await fetch(url, {
|
|
92
|
+
method: 'GET',
|
|
93
|
+
headers: await getBackupAuthHeaders(wallet, 'GET', url),
|
|
94
|
+
})
|
|
95
|
+
if (response.status === 404) {
|
|
96
|
+
return {
|
|
97
|
+
found: false,
|
|
98
|
+
cid: '',
|
|
99
|
+
time: 0,
|
|
100
|
+
notes: [],
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
if (!response.ok) {
|
|
104
|
+
throw new Error(await readBackupApiError(response, '云端恢复失败'))
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const encrypted = await response.text()
|
|
108
|
+
if (!encrypted) {
|
|
109
|
+
throw new Error('云端无备份数据')
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const data = decryptNotesBackup(encrypted, wallet.danger)
|
|
113
|
+
return {
|
|
114
|
+
found: true,
|
|
115
|
+
cid: response.headers.get('x-backup-cid') || '',
|
|
116
|
+
time: Number(response.headers.get('x-backup-time') || 0),
|
|
117
|
+
notes: data.notes,
|
|
118
|
+
}
|
|
119
|
+
}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { CID } from 'multiformats/cid'
|
|
2
|
+
import * as raw from 'multiformats/codecs/raw'
|
|
3
|
+
import { sha256 } from 'multiformats/hashes/sha2'
|
|
4
|
+
|
|
5
|
+
export function normalizeNotePath(input = '') {
|
|
6
|
+
return String(input)
|
|
7
|
+
.replace(/\\/g, '/')
|
|
8
|
+
.split('/')
|
|
9
|
+
.map(part => part.trim())
|
|
10
|
+
.filter(part => part && part !== '.')
|
|
11
|
+
.filter(part => part !== '..')
|
|
12
|
+
.join('/')
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function getNoteFullPath(note) {
|
|
16
|
+
const path = normalizeNotePath(note?.path || '')
|
|
17
|
+
const name = String(note?.name || '').trim()
|
|
18
|
+
return path ? `${path}/${name}` : name
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function validateNoteName(name) {
|
|
22
|
+
const value = String(name || '').trim()
|
|
23
|
+
if (!value) return { valid: false, error: '请输入名称' }
|
|
24
|
+
if (value.includes('/')) return { valid: false, error: '名称不能包含 /' }
|
|
25
|
+
if (value.includes('\\')) return { valid: false, error: '名称不能包含 \\' }
|
|
26
|
+
return { valid: true, name: value }
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export async function calculateNoteCid(content = '') {
|
|
30
|
+
const bytes = new TextEncoder().encode(String(content))
|
|
31
|
+
const hash = await sha256.digest(bytes)
|
|
32
|
+
return CID.create(1, raw.code, hash).toString()
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function filterNotesByPath(notes, currentPath = '', query = '') {
|
|
36
|
+
const normalizedCurrentPath = normalizeNotePath(currentPath)
|
|
37
|
+
const normalizedQuery = query.trim().toLowerCase()
|
|
38
|
+
const files = Array.isArray(notes) ? notes : []
|
|
39
|
+
|
|
40
|
+
if (normalizedQuery) {
|
|
41
|
+
return files
|
|
42
|
+
.filter(note => String(note.name || '').toLowerCase().includes(normalizedQuery))
|
|
43
|
+
.sort(sortNotesForExplorer)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const directItems = []
|
|
47
|
+
const inferredDirs = new Map()
|
|
48
|
+
|
|
49
|
+
for (const note of files) {
|
|
50
|
+
const notePath = normalizeNotePath(note.path || '')
|
|
51
|
+
|
|
52
|
+
if (notePath === normalizedCurrentPath) {
|
|
53
|
+
directItems.push(note)
|
|
54
|
+
continue
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (
|
|
58
|
+
normalizedCurrentPath === '' ||
|
|
59
|
+
notePath.startsWith(`${normalizedCurrentPath}/`)
|
|
60
|
+
) {
|
|
61
|
+
const relativePath =
|
|
62
|
+
normalizedCurrentPath === ''
|
|
63
|
+
? notePath
|
|
64
|
+
: notePath.slice(normalizedCurrentPath.length + 1)
|
|
65
|
+
const firstSegment = relativePath.split('/').filter(Boolean)[0]
|
|
66
|
+
|
|
67
|
+
if (firstSegment && !inferredDirs.has(firstSegment)) {
|
|
68
|
+
inferredDirs.set(firstSegment, {
|
|
69
|
+
name: firstSegment,
|
|
70
|
+
type: 'directory',
|
|
71
|
+
path: normalizedCurrentPath,
|
|
72
|
+
size: 0,
|
|
73
|
+
cid: `__dir__${normalizedCurrentPath}/${firstSegment}`,
|
|
74
|
+
created_at: note.created_at || Date.now(),
|
|
75
|
+
updated_at: note.updated_at || note.created_at || Date.now(),
|
|
76
|
+
})
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return [...inferredDirs.values(), ...directItems].sort(sortNotesForExplorer)
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export function renameNotesByPath(notes, oldFullPath, targetPath, targetName) {
|
|
85
|
+
const oldPath = normalizeNotePath(oldFullPath)
|
|
86
|
+
const newPath = normalizeNotePath(targetPath)
|
|
87
|
+
const cleanName = String(targetName || '').trim()
|
|
88
|
+
const targetFullPath = normalizeNotePath(
|
|
89
|
+
newPath ? `${newPath}/${cleanName}` : cleanName
|
|
90
|
+
)
|
|
91
|
+
const now = Date.now()
|
|
92
|
+
|
|
93
|
+
return notes.map(note => {
|
|
94
|
+
const fullPath = getNoteFullPath(note)
|
|
95
|
+
|
|
96
|
+
if (fullPath === oldPath) {
|
|
97
|
+
return { ...note, path: newPath, name: cleanName, updated_at: now }
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if (fullPath.startsWith(`${oldPath}/`)) {
|
|
101
|
+
const relativePath = fullPath.slice(oldPath.length + 1)
|
|
102
|
+
const nextFullPath = normalizeNotePath(`${targetFullPath}/${relativePath}`)
|
|
103
|
+
const lastSlash = nextFullPath.lastIndexOf('/')
|
|
104
|
+
return {
|
|
105
|
+
...note,
|
|
106
|
+
path: lastSlash === -1 ? '' : nextFullPath.slice(0, lastSlash),
|
|
107
|
+
name: nextFullPath.slice(lastSlash + 1),
|
|
108
|
+
updated_at: now,
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
return note
|
|
113
|
+
})
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function sortNotesForExplorer(a, b) {
|
|
117
|
+
if (a.type === 'directory' && b.type !== 'directory') return -1
|
|
118
|
+
if (a.type !== 'directory' && b.type === 'directory') return 1
|
|
119
|
+
return (b.updated_at || b.created_at || 0) - (a.updated_at || a.created_at || 0)
|
|
120
|
+
}
|