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.
Files changed (375) hide show
  1. package/README.md +3 -2
  2. package/out/404/index.html +2 -2
  3. package/out/404.html +2 -2
  4. package/out/__next.__PAGE__.txt +6 -6
  5. package/out/__next._full.txt +23 -20
  6. package/out/__next._head.txt +3 -3
  7. package/out/__next._index.txt +8 -6
  8. package/out/__next._tree.txt +6 -4
  9. package/out/_next/static/chunks/0-n3pg7th.zza.js +1 -0
  10. package/out/_next/static/chunks/0.4j.0k5a64vg.js +1 -0
  11. package/out/_next/static/chunks/0.ozi1_x2.m.~.js +1 -0
  12. package/out/_next/static/chunks/0.t5wlt51zou5.js +1 -0
  13. package/out/_next/static/chunks/0.w4hkvap~bva.js +1 -0
  14. package/out/_next/static/chunks/00-u5nq76f0.j.js +1 -0
  15. package/out/_next/static/chunks/00d9h1tddnnnd.js +1 -0
  16. package/out/_next/static/chunks/00fm8lijienf1.js +1 -0
  17. package/out/_next/static/chunks/00o9ht.f2qm00.css +4 -0
  18. package/out/_next/static/chunks/00tkdqwxch-3s.js +1 -0
  19. package/out/_next/static/chunks/00zi-erhjrny2.js +2 -0
  20. package/out/_next/static/chunks/01l3o90g~1z42.js +1 -0
  21. package/out/_next/static/chunks/01mfky9camw6i.js +1 -0
  22. package/out/_next/static/chunks/01r.v-pqs1vrm.js +1 -0
  23. package/out/_next/static/chunks/03edqrb4zdj~g.js +31 -0
  24. package/out/_next/static/chunks/03h_6oo-gqkhz.js +1 -0
  25. package/out/_next/static/chunks/04hcgsanv1hhu.js +1 -0
  26. package/out/_next/static/chunks/05g2q0w5b34.g.js +1 -0
  27. package/out/_next/static/chunks/05of77xycbt8~.js +1 -0
  28. package/out/_next/static/chunks/05zwemzfjx3sh.js +1 -0
  29. package/out/_next/static/chunks/06dpc5df94.v1.js +1 -0
  30. package/out/_next/static/chunks/06e1~1-z_ic9a.js +1 -0
  31. package/out/_next/static/chunks/075s7sn.ns~u5.js +1 -0
  32. package/out/_next/static/chunks/07dynrbvd3.f4.js +1 -0
  33. package/out/_next/static/chunks/07p~uva5pwgwe.js +1 -0
  34. package/out/_next/static/chunks/07r9nn-pzlgg1.js +1 -0
  35. package/out/_next/static/chunks/08.72abkgwy9g.js +1 -0
  36. package/out/_next/static/chunks/084xf0edl9sfo.js +1 -0
  37. package/out/_next/static/chunks/08576xhv~~jck.js +1 -0
  38. package/out/_next/static/chunks/08u211~k~qu52.js +1 -0
  39. package/out/_next/static/chunks/098.p.2-zm4p7.js +1 -0
  40. package/out/_next/static/chunks/09f1gfke9m5wg.css +1 -0
  41. package/out/_next/static/chunks/09ngvtajm7e5y.js +1 -0
  42. package/out/_next/static/chunks/09ps~-43n5qyo.js +1 -0
  43. package/out/_next/static/chunks/09v7_0gclxr46.js +1 -0
  44. package/out/_next/static/chunks/09xyi6fpro_d-.css +1 -0
  45. package/out/_next/static/chunks/09yql86dir9c4.js +1 -0
  46. package/out/_next/static/chunks/09zmlfljowj1~.js +1 -0
  47. package/out/_next/static/chunks/0_npg_pcoywti.js +5 -0
  48. package/out/_next/static/chunks/0_r_mk1~6bosc.js +1 -0
  49. package/out/_next/static/chunks/0_s~ebb-7b2hr.js +1 -0
  50. package/out/_next/static/chunks/0_w-0-2z5oqd_.js +1 -0
  51. package/out/_next/static/chunks/0ao1lbi4b.sfa.js +1 -0
  52. package/out/_next/static/chunks/0arm0a6adt7cc.css +1 -0
  53. package/out/_next/static/chunks/0bld2u_ld~va2.js +1 -0
  54. package/out/_next/static/chunks/0bliugh5lxw55.js +1 -0
  55. package/out/_next/static/chunks/{0e_h0d3ekzks8.css → 0c9j3eq_14vv2.css} +1 -1
  56. package/out/_next/static/chunks/0cn9a7aimbdzq.js +1 -0
  57. package/out/_next/static/chunks/0d3f-nk3c.2re.js +1 -0
  58. package/out/_next/static/chunks/0d4bueddmcnca.js +1 -0
  59. package/out/_next/static/chunks/0dtohpf7~3d12.js +1 -0
  60. package/out/_next/static/chunks/0e-3e8h7g99yf.js +1 -0
  61. package/out/_next/static/chunks/0e531nije_ln2.js +1 -0
  62. package/out/_next/static/chunks/0e5zvj_rh0z3m.js +1 -0
  63. package/out/_next/static/chunks/0f4y~rkk-n81e.js +1 -0
  64. package/out/_next/static/chunks/0fk~0~p7ivfn1.js +1 -0
  65. package/out/_next/static/chunks/0fw6juc~lsj3z.js +1 -0
  66. package/out/_next/static/chunks/0g0u7785a73vo.js +1 -0
  67. package/out/_next/static/chunks/0g_fpgh7drfda.js +1 -0
  68. package/out/_next/static/chunks/0gtwvy1z9ksa7.css +1 -0
  69. package/out/_next/static/chunks/0gze5uso1mbe9.js +1 -0
  70. package/out/_next/static/chunks/0h4r.qtmpa6eh.js +1 -0
  71. package/out/_next/static/chunks/0hf.aosc-7172.js +1 -0
  72. package/out/_next/static/chunks/0hgz35c1ejbs9.js +1 -0
  73. package/out/_next/static/chunks/0hrw-r.xmvmsq.js +1 -0
  74. package/out/_next/static/chunks/0hzg4al.v~8~m.js +1 -0
  75. package/out/_next/static/chunks/0ip9xrols_83o.js +1 -0
  76. package/out/_next/static/chunks/0j27tcmtt4ly7.js +1 -0
  77. package/out/_next/static/chunks/0j3v4mq67wtnh.js +1 -0
  78. package/out/_next/static/chunks/0j4-d0qf.v~kn.js +1 -0
  79. package/out/_next/static/chunks/0jhdeq.j9_02m.js +1 -0
  80. package/out/_next/static/chunks/0jy63h3i-y69i.js +1 -0
  81. package/out/_next/static/chunks/0kdnx_u-60k9s.js +1 -0
  82. package/out/_next/static/chunks/0kq~edq42o1-c.js +1 -0
  83. package/out/_next/static/chunks/0l682p362d-5w.js +1 -0
  84. package/out/_next/static/chunks/0lkmf5ry.s_7w.js +1 -0
  85. package/out/_next/static/chunks/0m68p9txef5rs.js +1 -0
  86. package/out/_next/static/chunks/0mme-fm5d2oz2.js +1 -0
  87. package/out/_next/static/chunks/0myp4sjagr~h0.js +1 -0
  88. package/out/_next/static/chunks/0n.qlfk~z7o.6.js +1 -0
  89. package/out/_next/static/chunks/0n4t80gjc3q5h.js +1 -0
  90. package/out/_next/static/chunks/{0n~dq4kpx9xxx.js → 0o6lrkxy4jwag.js} +1 -1
  91. package/out/_next/static/chunks/0o98f1yq..o.8.js +1 -0
  92. package/out/_next/static/chunks/0oz3yl6_-716p.js +1 -0
  93. package/out/_next/static/chunks/0p486m03-zfoi.js +1 -0
  94. package/out/_next/static/chunks/0qou.u2e2dy48.css +24 -0
  95. package/out/_next/static/chunks/0qqupeexg83u7.js +1 -0
  96. package/out/_next/static/chunks/0r1~k82nji8sf.js +1 -0
  97. package/out/_next/static/chunks/0rb-ri481.kc9.js +1 -0
  98. package/out/_next/static/chunks/0rsnmahfd.59p.js +1 -0
  99. package/out/_next/static/chunks/0rt6rgnvr-s_p.js +1 -0
  100. package/out/_next/static/chunks/0runh28p_gg6..js +1 -0
  101. package/out/_next/static/chunks/0shy.t1fwqcev.js +1 -0
  102. package/out/_next/static/chunks/{0d3shmwh5_nmn.js → 0t2xr05rlu96l.js} +1 -1
  103. package/out/_next/static/chunks/0t6h56rhg1y5i.js +1 -0
  104. package/out/_next/static/chunks/0tdqd1zunusgk.js +1 -0
  105. package/out/_next/static/chunks/0ujbnp38x63ek.js +1 -0
  106. package/out/_next/static/chunks/0usvo~vu7r8np.js +736 -0
  107. package/out/_next/static/chunks/0v68pdrp54lb-.js +1 -0
  108. package/out/_next/static/chunks/0v7qp4hv-_._r.js +1 -0
  109. package/out/_next/static/chunks/0vsm0m5sxrb.3.js +1 -0
  110. package/out/_next/static/chunks/0vzlz.iboqo3c.js +1 -0
  111. package/out/_next/static/chunks/0w87vbpkf-ogd.js +1 -0
  112. package/out/_next/static/chunks/0wuwlgcn6gxqt.js +1 -0
  113. package/out/_next/static/chunks/0xgg0~kmf3gd-.js +1 -0
  114. package/out/_next/static/chunks/0xj24-70ptdzp.js +1 -0
  115. package/out/_next/static/chunks/0xl5_avhu._i8.js +1 -0
  116. package/out/_next/static/chunks/0xxlx772fr3x4.js +1 -0
  117. package/out/_next/static/chunks/0y.li-~3oybew.js +1 -0
  118. package/out/_next/static/chunks/0yl2t7cs-n_ng.js +1 -0
  119. package/out/_next/static/chunks/0yq3kh.hchtm_.js +1 -0
  120. package/out/_next/static/chunks/0ys0l5au.9c2c.js +1 -0
  121. package/out/_next/static/chunks/0z48pmi6buytt.js +1 -0
  122. package/out/_next/static/chunks/0zapnvgy89mg..js +1 -0
  123. package/out/_next/static/chunks/0~.-vxi5oc.r0.js +1 -0
  124. package/out/_next/static/chunks/0~3ik-hfp9s-7.js +1 -0
  125. package/out/_next/static/chunks/0~4f5p6tvn1lq.js +1 -0
  126. package/out/_next/static/chunks/0~_0ys.2whxbw.js +1 -0
  127. package/out/_next/static/chunks/0~_ui9l7.2sxf.js +1 -0
  128. package/out/_next/static/chunks/1037jlyw5~7ht.js +1 -0
  129. package/out/_next/static/chunks/1045hfzu533z0.js +1 -0
  130. package/out/_next/static/chunks/104e5nmc.c-pl.js +1 -0
  131. package/out/_next/static/chunks/109taw1pbh-0b.js +1 -0
  132. package/out/_next/static/chunks/10kvl8vj_plm-.js +1 -0
  133. package/out/_next/static/chunks/10x7~onqwp338.js +1 -0
  134. package/out/_next/static/chunks/10ynz1dy483wf.js +1 -0
  135. package/out/_next/static/chunks/11hds.mg~4_r-.js +1 -0
  136. package/out/_next/static/chunks/11ibzaklcauw~.js +1 -0
  137. package/out/_next/static/chunks/11z.0s6.42b.p.js +1 -0
  138. package/out/_next/static/chunks/12-9n56l0y3yr.js +1 -0
  139. package/out/_next/static/chunks/126enaq~f7scl.js +1 -0
  140. package/out/_next/static/chunks/1380op_pfk.qo.js +1 -0
  141. package/out/_next/static/chunks/146oiw1bggtn4.js +1 -0
  142. package/out/_next/static/chunks/14_po2rb_arn4.js +1 -0
  143. package/out/_next/static/chunks/14a4fwbiq.l3z.js +1 -0
  144. package/out/_next/static/chunks/14cowsqn95m1k.js +1 -0
  145. package/out/_next/static/chunks/14dtd3l03v.kx.js +1 -0
  146. package/out/_next/static/chunks/14tm3qa-v9o-4.js +1 -0
  147. package/out/_next/static/chunks/15-o4kb-evqd7.js +1 -0
  148. package/out/_next/static/chunks/157z7bowux3xj.js +1 -0
  149. package/out/_next/static/chunks/15m1_677az2cm.js +1 -0
  150. package/out/_next/static/chunks/15v.~.ne6ogkk.js +1 -0
  151. package/out/_next/static/chunks/16i.qbk8t8gf_.js +1 -0
  152. package/out/_next/static/chunks/16m27azcs4k6w.js +1 -0
  153. package/out/_next/static/chunks/16u9f35gylw8l.js +1 -0
  154. package/out/_next/static/chunks/17ajyb5ogk5yj.js +1 -0
  155. package/out/_next/static/chunks/17dyfxbq8yz8n.js +1 -0
  156. package/out/_next/static/chunks/180zln9pcq9ih.js +1 -0
  157. package/out/_next/static/chunks/1814izi5gh.kp.js +1 -0
  158. package/out/_next/static/chunks/turbopack-0xs6mybc~5t_3.js +1 -0
  159. package/out/_next/static/media/KaTeX_AMS-Regular.0b~8ki5y928w2.woff +0 -0
  160. package/out/_next/static/media/KaTeX_AMS-Regular.0p1vbqd84i2~o.woff2 +0 -0
  161. package/out/_next/static/media/KaTeX_AMS-Regular.173t6ktr7uf-w.ttf +0 -0
  162. package/out/_next/static/media/KaTeX_Caligraphic-Bold.01-pzluls4zgb.woff2 +0 -0
  163. package/out/_next/static/media/KaTeX_Caligraphic-Bold.0x2v1lwn~880f.woff +0 -0
  164. package/out/_next/static/media/KaTeX_Caligraphic-Bold.16zv5fax0h0ka.ttf +0 -0
  165. package/out/_next/static/media/KaTeX_Caligraphic-Regular.02i3z7wig438t.ttf +0 -0
  166. package/out/_next/static/media/KaTeX_Caligraphic-Regular.0rysu1t-ncjq8.woff2 +0 -0
  167. package/out/_next/static/media/KaTeX_Caligraphic-Regular.10927swgekwun.woff +0 -0
  168. package/out/_next/static/media/KaTeX_Fraktur-Bold.0e-16u10iuyyf.woff +0 -0
  169. package/out/_next/static/media/KaTeX_Fraktur-Bold.0et27v~3~4uhe.ttf +0 -0
  170. package/out/_next/static/media/KaTeX_Fraktur-Bold.0w23i72~hprpq.woff2 +0 -0
  171. package/out/_next/static/media/KaTeX_Fraktur-Regular.0b.riegzdfue2.woff +0 -0
  172. package/out/_next/static/media/KaTeX_Fraktur-Regular.0rekyoa-52fj_.woff2 +0 -0
  173. package/out/_next/static/media/KaTeX_Fraktur-Regular.0vjwa15znhk~4.ttf +0 -0
  174. package/out/_next/static/media/KaTeX_Main-Bold.09i7~607shf-h.ttf +0 -0
  175. package/out/_next/static/media/KaTeX_Main-Bold.09lmynrorhcbw.woff +0 -0
  176. package/out/_next/static/media/KaTeX_Main-Bold.16pfc63_du6mx.woff2 +0 -0
  177. package/out/_next/static/media/KaTeX_Main-BoldItalic.0cp37g7x1q8h6.woff +0 -0
  178. package/out/_next/static/media/KaTeX_Main-BoldItalic.0d54rk08rx11s.woff2 +0 -0
  179. package/out/_next/static/media/KaTeX_Main-BoldItalic.15j6k~hix2t_0.ttf +0 -0
  180. package/out/_next/static/media/KaTeX_Main-Italic.0382gqciexmbu.woff +0 -0
  181. package/out/_next/static/media/KaTeX_Main-Italic.06o5nq0_91v60.woff2 +0 -0
  182. package/out/_next/static/media/KaTeX_Main-Italic.0su4i6mm18-wo.ttf +0 -0
  183. package/out/_next/static/media/KaTeX_Main-Regular.08zh8z.7shijf.ttf +0 -0
  184. package/out/_next/static/media/KaTeX_Main-Regular.0diheg01zyoph.woff +0 -0
  185. package/out/_next/static/media/KaTeX_Main-Regular.0kaf-ag2_wkm-.woff2 +0 -0
  186. package/out/_next/static/media/KaTeX_Math-BoldItalic.0ajzxypnbx1h1.ttf +0 -0
  187. package/out/_next/static/media/KaTeX_Math-BoldItalic.0ck1myuerwyqw.woff +0 -0
  188. package/out/_next/static/media/KaTeX_Math-BoldItalic.0ja97dn.cpc87.woff2 +0 -0
  189. package/out/_next/static/media/KaTeX_Math-Italic.09xkhecjcn5r9.woff +0 -0
  190. package/out/_next/static/media/KaTeX_Math-Italic.0x23a-bmp-5tg.ttf +0 -0
  191. package/out/_next/static/media/KaTeX_Math-Italic.0zrha2c4sl2je.woff2 +0 -0
  192. package/out/_next/static/media/KaTeX_SansSerif-Bold.05a9.pc1j_zx9.woff2 +0 -0
  193. package/out/_next/static/media/KaTeX_SansSerif-Bold.0jcl-ayi1uun0.woff +0 -0
  194. package/out/_next/static/media/KaTeX_SansSerif-Bold.0re8y.dm7.mt5.ttf +0 -0
  195. package/out/_next/static/media/KaTeX_SansSerif-Italic.0a0234dc3s62j.woff2 +0 -0
  196. package/out/_next/static/media/KaTeX_SansSerif-Italic.0judofdln9731.woff +0 -0
  197. package/out/_next/static/media/KaTeX_SansSerif-Italic.10z1iap9pfus8.ttf +0 -0
  198. package/out/_next/static/media/KaTeX_SansSerif-Regular.0h9yjlugq4q_e.woff +0 -0
  199. package/out/_next/static/media/KaTeX_SansSerif-Regular.0v6gcj32-czft.woff2 +0 -0
  200. package/out/_next/static/media/KaTeX_SansSerif-Regular.0zm18kga42ebc.ttf +0 -0
  201. package/out/_next/static/media/KaTeX_Script-Regular.0c4.h-mer83d_.woff2 +0 -0
  202. package/out/_next/static/media/KaTeX_Script-Regular.0q14y6zkzlpob.ttf +0 -0
  203. package/out/_next/static/media/KaTeX_Script-Regular.0ze6v4r_-99oy.woff +0 -0
  204. package/out/_next/static/media/KaTeX_Size1-Regular.013x6a4ierotp.woff2 +0 -0
  205. package/out/_next/static/media/KaTeX_Size1-Regular.0kidw0oi.m68o.woff +0 -0
  206. package/out/_next/static/media/KaTeX_Size1-Regular.0m6y-i6wfokni.ttf +0 -0
  207. package/out/_next/static/media/KaTeX_Size2-Regular.0blpmluwilgbg.woff +0 -0
  208. package/out/_next/static/media/KaTeX_Size2-Regular.0d5inmyp-tyv3.woff2 +0 -0
  209. package/out/_next/static/media/KaTeX_Size2-Regular.0wnhnvj-.k9d5.ttf +0 -0
  210. package/out/_next/static/media/KaTeX_Size3-Regular.01h0xm_sfctj3.woff +0 -0
  211. package/out/_next/static/media/KaTeX_Size3-Regular.0iukctyhw5j56.woff2 +0 -0
  212. package/out/_next/static/media/KaTeX_Size3-Regular.0jl8mqyf4gzpn.ttf +0 -0
  213. package/out/_next/static/media/KaTeX_Size4-Regular.0w3.rb_c4stzk.woff2 +0 -0
  214. package/out/_next/static/media/KaTeX_Size4-Regular.0wr_9l81-mu06.ttf +0 -0
  215. package/out/_next/static/media/KaTeX_Size4-Regular.12tvaesf3.zl3.woff +0 -0
  216. package/out/_next/static/media/KaTeX_Typewriter-Regular.0c4zdxz~8frhm.woff2 +0 -0
  217. package/out/_next/static/media/KaTeX_Typewriter-Regular.0cgrzn5l3kao5.woff +0 -0
  218. package/out/_next/static/media/KaTeX_Typewriter-Regular.128~qc3858otl.ttf +0 -0
  219. package/out/_not-found/__next._full.txt +21 -19
  220. package/out/_not-found/__next._head.txt +3 -3
  221. package/out/_not-found/__next._index.txt +8 -6
  222. package/out/_not-found/__next._not-found.__PAGE__.txt +4 -4
  223. package/out/_not-found/__next._not-found.txt +3 -3
  224. package/out/_not-found/__next._tree.txt +3 -2
  225. package/out/_not-found/index.html +2 -2
  226. package/out/_not-found/index.txt +21 -19
  227. package/out/admin/__next._full.txt +23 -0
  228. package/out/admin/__next._head.txt +5 -0
  229. package/out/admin/__next._index.txt +9 -0
  230. package/out/admin/__next._tree.txt +5 -0
  231. package/out/admin/__next.admin.__PAGE__.txt +9 -0
  232. package/out/admin/__next.admin.txt +5 -0
  233. package/out/admin/index.html +15 -0
  234. package/out/admin/index.txt +23 -0
  235. package/out/app/__next._full.txt +15 -13
  236. package/out/app/__next._head.txt +3 -3
  237. package/out/app/__next._index.txt +8 -6
  238. package/out/app/__next._tree.txt +4 -2
  239. package/out/app/__next.app.__PAGE__.txt +4 -4
  240. package/out/app/__next.app.txt +3 -4
  241. package/out/app/index.html +2 -2
  242. package/out/app/index.txt +15 -13
  243. package/out/changelog/__next._full.txt +24 -21
  244. package/out/changelog/__next._head.txt +3 -3
  245. package/out/changelog/__next._index.txt +8 -6
  246. package/out/changelog/__next._tree.txt +5 -3
  247. package/out/changelog/__next.changelog.__PAGE__.txt +5 -5
  248. package/out/changelog/__next.changelog.txt +3 -3
  249. package/out/changelog/index.html +2 -2
  250. package/out/changelog/index.txt +24 -21
  251. package/out/chat/__next._full.txt +16 -14
  252. package/out/chat/__next._head.txt +3 -3
  253. package/out/chat/__next._index.txt +8 -6
  254. package/out/chat/__next._tree.txt +5 -3
  255. package/out/chat/__next.chat.__PAGE__.txt +4 -4
  256. package/out/chat/__next.chat.txt +4 -5
  257. package/out/chat/index.html +2 -2
  258. package/out/chat/index.txt +16 -14
  259. package/out/docs/__next._full.txt +24 -21
  260. package/out/docs/__next._head.txt +3 -3
  261. package/out/docs/__next._index.txt +8 -6
  262. package/out/docs/__next._tree.txt +5 -3
  263. package/out/docs/__next.docs.__PAGE__.txt +5 -5
  264. package/out/docs/__next.docs.txt +3 -3
  265. package/out/docs/getting-started/__next._full.txt +24 -21
  266. package/out/docs/getting-started/__next._head.txt +3 -3
  267. package/out/docs/getting-started/__next._index.txt +8 -6
  268. package/out/docs/getting-started/__next._tree.txt +5 -3
  269. package/out/docs/getting-started/__next.docs.getting-started.__PAGE__.txt +5 -5
  270. package/out/docs/getting-started/__next.docs.getting-started.txt +3 -3
  271. package/out/docs/getting-started/__next.docs.txt +3 -3
  272. package/out/docs/getting-started/index.html +2 -2
  273. package/out/docs/getting-started/index.txt +24 -21
  274. package/out/docs/index.html +2 -2
  275. package/out/docs/index.txt +24 -21
  276. package/out/download/__next._full.txt +33 -32
  277. package/out/download/__next._head.txt +3 -3
  278. package/out/download/__next._index.txt +8 -6
  279. package/out/download/__next._tree.txt +5 -3
  280. package/out/download/__next.download.__PAGE__.txt +10 -11
  281. package/out/download/__next.download.txt +3 -3
  282. package/out/download/index.html +2 -2
  283. package/out/download/index.txt +33 -32
  284. package/out/index.html +2 -2
  285. package/out/index.txt +23 -20
  286. package/out/note/__next._full.txt +24 -0
  287. package/out/note/__next._head.txt +5 -0
  288. package/out/note/__next._index.txt +9 -0
  289. package/out/note/__next._tree.txt +4 -0
  290. package/out/note/__next.note.__PAGE__.txt +9 -0
  291. package/out/note/__next.note.txt +5 -0
  292. package/out/note/edit/__next._full.txt +24 -0
  293. package/out/note/edit/__next._head.txt +5 -0
  294. package/out/note/edit/__next._index.txt +9 -0
  295. package/out/note/edit/__next._tree.txt +4 -0
  296. package/out/note/edit/__next.note.edit.__PAGE__.txt +9 -0
  297. package/out/note/edit/__next.note.edit.txt +5 -0
  298. package/out/note/edit/__next.note.txt +5 -0
  299. package/out/note/edit/index.html +15 -0
  300. package/out/note/edit/index.txt +24 -0
  301. package/out/note/index.html +15 -0
  302. package/out/note/index.txt +24 -0
  303. package/out/ping/__next._full.txt +22 -19
  304. package/out/ping/__next._head.txt +3 -3
  305. package/out/ping/__next._index.txt +8 -6
  306. package/out/ping/__next._tree.txt +5 -3
  307. package/out/ping/__next.ping.__PAGE__.txt +5 -5
  308. package/out/ping/__next.ping.txt +3 -3
  309. package/out/ping/index.html +2 -2
  310. package/out/ping/index.txt +22 -19
  311. package/out/web3/__next._full.txt +16 -14
  312. package/out/web3/__next._head.txt +3 -3
  313. package/out/web3/__next._index.txt +8 -6
  314. package/out/web3/__next._tree.txt +5 -3
  315. package/out/web3/__next.web3.__PAGE__.txt +4 -4
  316. package/out/web3/__next.web3.txt +4 -5
  317. package/out/web3/ed25519/__next._full.txt +14 -12
  318. package/out/web3/ed25519/__next._head.txt +3 -3
  319. package/out/web3/ed25519/__next._index.txt +8 -6
  320. package/out/web3/ed25519/__next._tree.txt +5 -3
  321. package/out/web3/ed25519/__next.web3.ed25519.__PAGE__.txt +2 -2
  322. package/out/web3/ed25519/__next.web3.ed25519.txt +3 -3
  323. package/out/web3/ed25519/__next.web3.txt +4 -5
  324. package/out/web3/ed25519/index.html +1 -1
  325. package/out/web3/ed25519/index.txt +14 -12
  326. package/out/web3/index.html +2 -2
  327. package/out/web3/index.txt +16 -14
  328. package/out/web3/tools/__next._full.txt +14 -12
  329. package/out/web3/tools/__next._head.txt +3 -3
  330. package/out/web3/tools/__next._index.txt +8 -6
  331. package/out/web3/tools/__next._tree.txt +5 -3
  332. package/out/web3/tools/__next.web3.tools.__PAGE__.txt +2 -2
  333. package/out/web3/tools/__next.web3.tools.txt +3 -3
  334. package/out/web3/tools/__next.web3.txt +4 -5
  335. package/out/web3/tools/index.html +1 -1
  336. package/out/web3/tools/index.txt +14 -12
  337. package/package.json +12 -5
  338. package/server/index.js +558 -101
  339. package/server/src/config.js +4 -0
  340. package/server/src/core/cid.js +53 -32
  341. package/server/src/index.js +772 -122
  342. package/server/src/node/config.js +159 -0
  343. package/server/src/node/logs.js +94 -0
  344. package/server/src/utils/api.js +80 -2
  345. package/server/src/utils/errors.js +7 -0
  346. package/server/src/utils/mostWallet.js +34 -1
  347. package/server/src/utils/noteBackup.js +119 -0
  348. package/server/src/utils/noteUtils.js +120 -0
  349. package/server/src/utils/userIdentity.js +8 -60
  350. package/out/_next/static/chunks/003jnm.v5tzw5.js +0 -1
  351. package/out/_next/static/chunks/00re8v.gbcywn.js +0 -1
  352. package/out/_next/static/chunks/00s106sbq8t9v.js +0 -1
  353. package/out/_next/static/chunks/012hi627qrdnn.js +0 -1
  354. package/out/_next/static/chunks/0174xh3wfsjm1.js +0 -2
  355. package/out/_next/static/chunks/02~o2nmo5pmy1.js +0 -1
  356. package/out/_next/static/chunks/07t.dhhokszz5.css +0 -1
  357. package/out/_next/static/chunks/0_wia9ofmsi1c.css +0 -2
  358. package/out/_next/static/chunks/0ah8fihozo2_u.js +0 -5
  359. package/out/_next/static/chunks/0bzupvr5gt3k9.js +0 -31
  360. package/out/_next/static/chunks/0gdluj423gso1.js +0 -1
  361. package/out/_next/static/chunks/0gmoiq06srjay.css +0 -1
  362. package/out/_next/static/chunks/0imkasy7kb67u.js +0 -1
  363. package/out/_next/static/chunks/0jjc_b9q_ldi2.js +0 -1
  364. package/out/_next/static/chunks/0jl~j62iz2uvr.js +0 -1
  365. package/out/_next/static/chunks/0lqslm813wk_h.js +0 -1
  366. package/out/_next/static/chunks/0q782fxxd0lx~.js +0 -1
  367. package/out/_next/static/chunks/0slwj0c46k5cu.js +0 -1
  368. package/out/_next/static/chunks/0sorqk.oc6b7j.css +0 -1
  369. package/out/_next/static/chunks/0tapzqc6hgvx-.js +0 -1
  370. package/out/_next/static/chunks/0xsc7z5x8n7wg.js +0 -1
  371. package/out/_next/static/chunks/0zm~gys2jwl0g.js +0 -1
  372. package/out/_next/static/chunks/turbopack-0a_g3u0ud~jb8.js +0 -1
  373. /package/out/_next/static/{iOB2EBwOGZ0iYW7Lbg9u_ → sIuUKxnnGU7K9Tu9UDKE8}/_buildManifest.js +0 -0
  374. /package/out/_next/static/{iOB2EBwOGZ0iYW7Lbg9u_ → sIuUKxnnGU7K9Tu9UDKE8}/_clientMiddlewareManifest.js +0 -0
  375. /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
+ }
@@ -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('http://localhost:1976/api/node-id', {
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 = 3
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
+ }