most-box 0.1.8 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +20 -7
- package/out/admin/index.html +0 -0
- package/out/app/index.html +0 -0
- package/out/assets/AppShell-CQhg6DJU.js +1 -0
- package/out/assets/ChatUi-BepWs-ZU.js +1 -0
- package/out/assets/LanguageToggle-CtzCCAYv.js +1 -0
- package/out/assets/LogoIcon-Dxto3Sb4.js +1 -0
- package/out/assets/MarketingLayout-BQw0IS2i.js +1 -0
- package/out/assets/MarketingThemeToggle-DBaC9bjz.js +1 -0
- package/out/assets/MilkdownEditor-BqJzntYE.js +1054 -0
- package/out/assets/MoveModal-4D9n11Kw.js +1 -0
- package/out/assets/Nav-9MDdvgNs.js +1 -0
- package/out/assets/NoteSidebar-C-rIt32H.js +1 -0
- package/out/assets/OpenSidebarButton-Dd0JmKuE.js +1 -0
- package/out/assets/PemBlock-C8dEIzu-.js +1 -0
- package/out/assets/SidebarAccount-ClS-N0lq.js +1 -0
- package/out/assets/apl-CnwPGSsG.js +1 -0
- package/out/assets/arrow-right-urE9Rd7j.js +1 -0
- package/out/assets/asciiarmor-qTkVPQu6.js +1 -0
- package/out/assets/asn1-Dr8qZg38.js +1 -0
- package/out/assets/asterisk-Bja0s6e1.js +1 -0
- package/out/assets/brainfuck-D5EjA2JK.js +1 -0
- package/out/assets/channelApi-BwQU0-h1.js +1 -0
- package/out/assets/check-DUNsD2t6.js +1 -0
- package/out/assets/chevron-down-D6mpsfv4.js +1 -0
- package/out/assets/circle-alert-W0iyN4sC.js +1 -0
- package/out/assets/clike-DHH8Ad3s.js +1 -0
- package/out/assets/clojure-BflJGmDX.js +1 -0
- package/out/assets/cloud-BMyOoC2x.js +1 -0
- package/out/assets/cmake-CyVbuzPu.js +1 -0
- package/out/assets/cobol-B_OZ4V-R.js +1 -0
- package/out/assets/code-B1Cb_Icm.js +1 -0
- package/out/assets/coffeescript-B2pKbFk8.js +1 -0
- package/out/assets/commonlisp-CcllspGY.js +1 -0
- package/out/assets/copy-C1MttOli.js +1 -0
- package/out/assets/crystal-M5-qzICs.js +1 -0
- package/out/assets/css-CYpP4FRV.js +1 -0
- package/out/assets/cypher-p9eYesGn.js +1 -0
- package/out/assets/d-BhMjBjQP.js +1 -0
- package/out/assets/dayjs.min-Dcc0B6Je.js +1 -0
- package/out/assets/diff-ChtP43wD.js +1 -0
- package/out/assets/dist-8QDHqrPN.js +1 -0
- package/out/assets/dist-B0JrbG7f.js +11 -0
- package/out/assets/dist-BAJKKN4w.js +1 -0
- package/out/assets/dist-BFSyuOuw.js +1 -0
- package/out/assets/dist-BPs0Xns9.js +2 -0
- package/out/assets/dist-Br_5lLVO.js +23 -0
- package/out/assets/dist-BzqqCPi2.js +1 -0
- package/out/assets/dist-C-Tg23jc.js +1 -0
- package/out/assets/dist-C3lbe8SW.js +9 -0
- package/out/assets/dist-CMmmtl3f.js +1 -0
- package/out/assets/dist-CbTzBiwL.js +13 -0
- package/out/assets/dist-CfU9fwWz.js +6 -0
- package/out/assets/dist-CqQavSZV.js +1 -0
- package/out/assets/dist-D94V9Zlh.js +1 -0
- package/out/assets/dist-DBnWo8ZP.js +1 -0
- package/out/assets/dist-DCX0ws1K.js +1 -0
- package/out/assets/dist-DJdv-Ma3.js +1 -0
- package/out/assets/dist-DTL5jL08.js +1 -0
- package/out/assets/dist-DvWZsW-D.js +1 -0
- package/out/assets/dist-IGpXmkFm.js +1 -0
- package/out/assets/dist-IN8WN7NI.js +1 -0
- package/out/assets/dist-chOCTzB2.js +1 -0
- package/out/assets/dist-yZ96GF-e.js +1 -0
- package/out/assets/dist-zyJb88Zz.js +1 -0
- package/out/assets/dockerfile-BLkNEvjs.js +1 -0
- package/out/assets/download-y7SZXu6E.js +1 -0
- package/out/assets/downloadValidation-B0p9Ai_9.js +1 -0
- package/out/assets/dtd-DTF72YNO.js +1 -0
- package/out/assets/dylan-C6jEEEk-.js +1 -0
- package/out/assets/ebnf-D4c0_ac3.js +1 -0
- package/out/assets/ecl-BSZaIHnp.js +1 -0
- package/out/assets/eiffel-BEjRio4Q.js +1 -0
- package/out/assets/elm-Cshzl8qu.js +1 -0
- package/out/assets/erlang-DaB2Rkuy.js +1 -0
- package/out/assets/factor-D7LVTn2l.js +1 -0
- package/out/assets/fcl-ClOhbFR7.js +1 -0
- package/out/assets/filePreview-UI9NH34f.js +1 -0
- package/out/assets/format-CR8oUWq6.js +1 -0
- package/out/assets/forth-Cezjo90N.js +1 -0
- package/out/assets/fortran-Bt6PBEDR.js +1 -0
- package/out/assets/game-CdU3xnZo.js +1 -0
- package/out/assets/gas-BHEdbvp9.js +1 -0
- package/out/assets/gherkin-oBAE_ms0.js +1 -0
- package/out/assets/groovy-BC3IOsC8.js +1 -0
- package/out/assets/hard-drive-D13Qbobu.js +1 -0
- package/out/assets/haskell-BRsoo5mP.js +1 -0
- package/out/assets/haxe-DjVOVvNP.js +1 -0
- package/out/assets/http-CLVgA2GD.js +1 -0
- package/out/assets/idl-BUZw3wgd.js +1 -0
- package/out/assets/image-DJCA16l_.js +1 -0
- package/out/assets/index-8eWJAjpY.css +1 -0
- package/out/assets/index-BZc4blbW.css +1 -0
- package/out/assets/index-BdaFEQG-.css +1 -0
- package/out/assets/index-QxXZzOUL.js +33 -0
- package/out/assets/index.lazy-BBTTFanX.js +1 -0
- package/out/assets/index.lazy-BG4ZylHD.js +2 -0
- package/out/assets/index.lazy-Bi-6ZXZX.js +1 -0
- package/out/assets/index.lazy-BixWVr0B.js +1 -0
- package/out/assets/index.lazy-BjFwNYy5.js +3 -0
- package/out/assets/index.lazy-C8EIQsXY.js +2 -0
- package/out/assets/index.lazy-CarNe2uu.js +1 -0
- package/out/assets/index.lazy-DEuGu3H3.js +1 -0
- package/out/assets/index.lazy-GPyILCA7.js +3 -0
- package/out/assets/index.lazy-I8ofndXl.js +1 -0
- package/out/assets/index.lazy-TxhWsA7y.js +1 -0
- package/out/assets/index.lazy-azfky8k7.js +1 -0
- package/out/assets/javascript-8HiN0ThV.js +1 -0
- package/out/assets/jsx-runtime-Bt-cYkS5.js +1 -0
- package/out/assets/julia-CQfgDRfP.js +1 -0
- package/out/assets/key-round-CZniN9lv.js +1 -0
- package/out/assets/livescript-BXxG0Yva.js +1 -0
- package/out/assets/lock-D5OSNhep.js +1 -0
- package/out/assets/log-out-B6phyZ5z.js +1 -0
- package/out/assets/lua-CiA1ziua.js +1 -0
- package/out/assets/mathematica-u8YMmbU0.js +1 -0
- package/out/assets/mbox-BEMVcqjs.js +1 -0
- package/out/assets/mirc-C9zpzAZU.js +1 -0
- package/out/assets/mllike-B45xgp2S.js +1 -0
- package/out/assets/modelica-CqHI_q-D.js +1 -0
- package/out/assets/mscgen-qgSLujhx.js +1 -0
- package/out/assets/mumps-CW_TBmxz.js +1 -0
- package/out/assets/music-CbUskKgg.js +1 -0
- package/out/assets/nginx-BMaDbqW3.js +1 -0
- package/out/assets/notebook-pen-DqKDQ6MJ.js +1 -0
- package/out/assets/nsis-AQ_alPln.js +1 -0
- package/out/assets/ntriples-d28e9m0E.js +1 -0
- package/out/assets/octave-D2Q8cUp1.js +1 -0
- package/out/assets/oz-BwTct_5T.js +1 -0
- package/out/assets/pascal-Dp_KdFgX.js +1 -0
- package/out/assets/perl-CdEHsPfU.js +1 -0
- package/out/assets/pig-AF4Hwhju.js +1 -0
- package/out/assets/play-BIl8q9eU.js +1 -0
- package/out/assets/plus-BxxbpH6Q.js +1 -0
- package/out/assets/powershell-CzG71I4L.js +1 -0
- package/out/assets/properties-C357ku5U.js +1 -0
- package/out/assets/protobuf-D1ij_kNL.js +1 -0
- package/out/assets/pug-DyBTKFx8.js +1 -0
- package/out/assets/puppet-B4hC2X4m.js +1 -0
- package/out/assets/python-BqYw9LYJ.js +1 -0
- package/out/assets/q-B9NhS7L_.js +1 -0
- package/out/assets/r-DADKenSm.js +1 -0
- package/out/assets/rpm-gpDK5sbt.js +1 -0
- package/out/assets/ruby-DsYpTuWg.js +1 -0
- package/out/assets/sas-C2OyD2Y6.js +1 -0
- package/out/assets/save-DkH1n_Ov.js +1 -0
- package/out/assets/scheme-CyDdOh7e.js +1 -0
- package/out/assets/search-BQi5Z0E-.js +1 -0
- package/out/assets/send-Cl6NtD2T.js +1 -0
- package/out/assets/shell-Du5Qg9im.js +1 -0
- package/out/assets/sieve-BAxa3IjF.js +1 -0
- package/out/assets/simple-mode-DRpGK0lJ.js +1 -0
- package/out/assets/smalltalk-BLp5-jwC.js +1 -0
- package/out/assets/solr-BBopId9w.js +1 -0
- package/out/assets/sparql-Dz-mlCAC.js +1 -0
- package/out/assets/spreadsheet-CTIncYxj.js +1 -0
- package/out/assets/sql-DcCJ9jop.js +1 -0
- package/out/assets/stex-sDrdk2BW.js +1 -0
- package/out/assets/stylus-DLLZ8dgm.js +1 -0
- package/out/assets/swift-DKB6_1j6.js +1 -0
- package/out/assets/tcl-BGfruO1u.js +1 -0
- package/out/assets/textile-DWBqthVk.js +1 -0
- package/out/assets/tiddlywiki-VlUiK86J.js +1 -0
- package/out/assets/tiki-CxVlf5KZ.js +1 -0
- package/out/assets/toml-LvoKBwCs.js +1 -0
- package/out/assets/trash-2-BBjpgK_f.js +1 -0
- package/out/assets/triangle-alert-l98G8u9O.js +1 -0
- package/out/assets/troff-C2dAgh7P.js +1 -0
- package/out/assets/ttcn-BePYh-hG.js +1 -0
- package/out/assets/ttcn-cfg-CY0aot7Q.js +1 -0
- package/out/assets/turtle-Cx3rYX2g.js +1 -0
- package/out/assets/upload-ByP6Ydde.js +1 -0
- package/out/assets/useChannelMessages-BgbYfF2c.js +3 -0
- package/out/assets/useGameRoom-DPmweWwe.js +1 -0
- package/out/assets/vb-BthdM_4N.js +1 -0
- package/out/assets/vbscript-D9f6rSsU.js +1 -0
- package/out/assets/velocity-CqftRsjg.js +1 -0
- package/out/assets/verilog-D-x6ne0Z.js +1 -0
- package/out/assets/vhdl-CMrOq2q1.js +1 -0
- package/out/assets/wallet-c7zIhNSM.js +1 -0
- package/out/assets/webidl-D5jiJvOU.js +1 -0
- package/out/assets/wifi-Bm4biAjc.js +1 -0
- package/out/assets/xquery-fj_R-kMw.js +1 -0
- package/out/assets/yacas-CXXgtw0p.js +1 -0
- package/out/assets/z80-CL1naaMV.js +1 -0
- package/out/chat/index.html +0 -0
- package/out/chat/join/index.html +0 -0
- package/out/demo/index.html +0 -0
- package/out/download/index.html +7 -3
- package/out/game/gandengyan/index.html +0 -0
- package/out/game/index.html +0 -0
- package/out/game/zhajinhua/index.html +0 -0
- package/out/index.html +7 -3
- package/out/note/index.html +0 -0
- package/out/ping/index.html +7 -3
- package/out/web3/index.html +0 -0
- package/package.json +14 -8
- package/server/index.js +9 -0
- package/server/src/core/channelAttachment.js +7 -3
- package/server/src/core/channelIdentity.js +50 -0
- package/server/src/core/cid.js +6 -1
- package/server/src/core/cidTopic.js +18 -4
- package/server/src/core/displayPath.js +10 -0
- package/server/src/core/gameRoom.js +2 -2
- package/server/src/core/mostLink.js +45 -25
- package/server/src/core/ownerMetadata.js +34 -0
- package/server/src/core/userSyncKeys.js +36 -0
- package/server/src/http/app.js +71 -149
- package/server/src/http/dataPath.js +26 -0
- package/server/src/http/errors.js +8 -4
- package/server/src/http/nodeStatus.js +13 -13
- package/server/src/http/rateLimit.js +39 -0
- package/server/src/http/routePolicy.js +43 -0
- package/server/src/http/staticFiles.js +1 -1
- package/server/src/index.js +1909 -759
- package/server/src/node/offlineSwarm.js +20 -0
- package/server/src/utils/api.js +1 -15
- package/server/src/utils/downloadMessages.js +17 -18
- package/server/src/utils/errors.js +3 -1
- package/server/src/utils/noteUtils.js +27 -3
- package/out/404/index.html +0 -15
- package/out/404.html +0 -15
- package/out/__next.__PAGE__.txt +0 -11
- package/out/__next._full.txt +0 -24
- package/out/__next._head.txt +0 -5
- package/out/__next._index.txt +0 -9
- package/out/__next._tree.txt +0 -6
- package/out/_next/static/TXy93SnAZQ7OQ-aVUkmHa/_buildManifest.js +0 -11
- package/out/_next/static/TXy93SnAZQ7OQ-aVUkmHa/_clientMiddlewareManifest.js +0 -1
- package/out/_next/static/TXy93SnAZQ7OQ-aVUkmHa/_ssgManifest.js +0 -1
- package/out/_next/static/chunks/0-jy8rfo075fy.js +0 -1
- package/out/_next/static/chunks/0-kczrcxjk7lc.js +0 -1
- package/out/_next/static/chunks/00t5ddkkjek9v.js +0 -1
- package/out/_next/static/chunks/012yllpioyi-k.js +0 -1
- package/out/_next/static/chunks/02f7w-ybfnvpd.js +0 -1
- package/out/_next/static/chunks/04_v8i3c2y4ni.js +0 -1
- package/out/_next/static/chunks/05-c3ty_6dwfk.js +0 -1
- package/out/_next/static/chunks/052vp9tk7oqx6.js +0 -1
- package/out/_next/static/chunks/05k6874y7n0cw.js +0 -1
- package/out/_next/static/chunks/09g8c9-u_uh1z.css +0 -1
- package/out/_next/static/chunks/0az8vxg2gfuhm.js +0 -31
- package/out/_next/static/chunks/0b899y85ei3i_.js +0 -1
- package/out/_next/static/chunks/0cz1d0mv5g_q7.js +0 -1
- package/out/_next/static/chunks/0eg1osglq6nq7.js +0 -1
- package/out/_next/static/chunks/0hlvocunlbrjs.js +0 -1
- package/out/_next/static/chunks/0hodisxqbtmye.js +0 -1
- package/out/_next/static/chunks/0i9k23rx749fx.js +0 -1
- package/out/_next/static/chunks/0j6wiyqf1637r.js +0 -1
- package/out/_next/static/chunks/0jinrmgt26crz.js +0 -1
- package/out/_next/static/chunks/0knzyzd1jvley.js +0 -1
- package/out/_next/static/chunks/0kp8ujaqwut11.js +0 -1
- package/out/_next/static/chunks/0mslhkdi-msxv.js +0 -1
- package/out/_next/static/chunks/0n92y9hb-ta0u.js +0 -1
- package/out/_next/static/chunks/0nybb-z3ufrbx.js +0 -1
- package/out/_next/static/chunks/0o-o9af-grvj8.js +0 -1
- package/out/_next/static/chunks/0oxr0r0aewn99.js +0 -1
- package/out/_next/static/chunks/0qh3b90ouc9bd.js +0 -1
- package/out/_next/static/chunks/0sh_jm8siqvek.js +0 -1
- package/out/_next/static/chunks/0t86ducxkqweb.js +0 -1
- package/out/_next/static/chunks/0u0j5i6-n4oqd.js +0 -1
- package/out/_next/static/chunks/0v73vfxjds7sj.js +0 -1
- package/out/_next/static/chunks/0ve8ixremhwy0.js +0 -1
- package/out/_next/static/chunks/0vv5cwj6kr506.js +0 -1
- package/out/_next/static/chunks/0w3wf8o-ewec9.js +0 -1
- package/out/_next/static/chunks/0w6o4o76scrb2.js +0 -1
- package/out/_next/static/chunks/1-88dio6azz54.js +0 -1
- package/out/_next/static/chunks/12zg24u7mbv4z.js +0 -1
- package/out/_next/static/chunks/14lsse587-ccf.js +0 -1
- package/out/_next/static/chunks/16qtikqm_sate.js +0 -1
- package/out/_next/static/chunks/17_ly1mk2z3q8.js +0 -1
- package/out/_next/static/chunks/181421-y2xzj7.js +0 -1
- package/out/_next/static/chunks/1_e-vuvfsntao.js +0 -1
- package/out/_next/static/chunks/1aljc62wfhqhr.js +0 -1
- package/out/_next/static/chunks/1b7mbzsylsn-m.js +0 -1
- package/out/_next/static/chunks/1cjakikh0o1tm.js +0 -1
- package/out/_next/static/chunks/1dfzez629llzh.js +0 -1
- package/out/_next/static/chunks/1e4ilit3ave6c.js +0 -1
- package/out/_next/static/chunks/1gzgcv355ziff.js +0 -1
- package/out/_next/static/chunks/1h-f81ddyfcmx.css +0 -1
- package/out/_next/static/chunks/1h0o6fj73le9_.js +0 -1
- package/out/_next/static/chunks/1in766ibz5l-p.js +0 -1
- package/out/_next/static/chunks/1ip_c70si4tj2.js +0 -1
- package/out/_next/static/chunks/1jlu197-yog_n.js +0 -1
- package/out/_next/static/chunks/1k788fny29y_j.js +0 -1
- package/out/_next/static/chunks/1lxjpnw925-0p.css +0 -1
- package/out/_next/static/chunks/1mnhfyfn52md5.js +0 -1
- package/out/_next/static/chunks/1o8brm8yipzn4.js +0 -1
- package/out/_next/static/chunks/1p8oa39bqu6ed.js +0 -1
- package/out/_next/static/chunks/1qmnmb_dutuw8.js +0 -1
- package/out/_next/static/chunks/1s6rdcw0q185p.js +0 -1
- package/out/_next/static/chunks/1ta0w8zc7tae7.js +0 -1
- package/out/_next/static/chunks/1uvi_hie0s3z5.js +0 -1
- package/out/_next/static/chunks/1v-molv0hbcjl.js +0 -1
- package/out/_next/static/chunks/1x76jmdus29em.js +0 -1
- package/out/_next/static/chunks/1y36s6sv2z7r4.js +0 -1
- package/out/_next/static/chunks/1zf4i-oj7n-ll.js +0 -1
- package/out/_next/static/chunks/2-vtwv8h_uokj.js +0 -1
- package/out/_next/static/chunks/2227enga_0c-6.js +0 -1
- package/out/_next/static/chunks/22vt64m0krmev.js +0 -1
- package/out/_next/static/chunks/24zr4q96g-eii.js +0 -1
- package/out/_next/static/chunks/258tyt1xt34p4.css +0 -1
- package/out/_next/static/chunks/266xuv6ts5889.js +0 -5
- package/out/_next/static/chunks/26hcvxjw9do9d.js +0 -1
- package/out/_next/static/chunks/27jktro2p5rq9.js +0 -4
- package/out/_next/static/chunks/2_cqphhur0a6t.js +0 -1
- package/out/_next/static/chunks/2_s88st3j0tql.js +0 -1
- package/out/_next/static/chunks/2_y6edbaubqrt.js +0 -1
- package/out/_next/static/chunks/2at8y3pbt5cue.js +0 -1
- package/out/_next/static/chunks/2cv1zex4has67.js +0 -1
- package/out/_next/static/chunks/2e6j5h4ftd4jd.js +0 -1
- package/out/_next/static/chunks/2e8b26r0td7ou.js +0 -1
- package/out/_next/static/chunks/2ecppdrjm9cs4.js +0 -1
- package/out/_next/static/chunks/2gl0wusc9zf3d.js +0 -1
- package/out/_next/static/chunks/2im7c515bo69p.js +0 -1
- package/out/_next/static/chunks/2ixaku9ie8hym.js +0 -1
- package/out/_next/static/chunks/2jhnrjgj_k2-z.js +0 -1
- package/out/_next/static/chunks/2jnstwjg45vfp.css +0 -1
- package/out/_next/static/chunks/2n6pb94vmohgf.js +0 -1
- package/out/_next/static/chunks/2o-0n-9r5u1oh.js +0 -1
- package/out/_next/static/chunks/2pdxw43rsbho0.js +0 -1
- package/out/_next/static/chunks/2pkm-6u9yq_cq.js +0 -1
- package/out/_next/static/chunks/2r6z3vlfw0ppd.js +0 -1
- package/out/_next/static/chunks/2rskzmv3skmq3.js +0 -1
- package/out/_next/static/chunks/2stoe6xiau1b3.js +0 -1
- package/out/_next/static/chunks/2uget3ephe4e3.js +0 -736
- package/out/_next/static/chunks/2va-v1iiap4zv.js +0 -1
- package/out/_next/static/chunks/2vm9uslik2wfi.css +0 -5
- package/out/_next/static/chunks/2wqoc60afpg_5.js +0 -1
- package/out/_next/static/chunks/2wyvwsayrr98o.js +0 -1
- package/out/_next/static/chunks/2y3o2mnyfnx68.js +0 -1
- package/out/_next/static/chunks/3-7y7sjol3yto.js +0 -1
- package/out/_next/static/chunks/3089gugfv3ov9.js +0 -1
- package/out/_next/static/chunks/30s3_0brd77ky.js +0 -1
- package/out/_next/static/chunks/31zdi2pl6em6-.css +0 -1
- package/out/_next/static/chunks/35idql3ziq0wz.js +0 -1
- package/out/_next/static/chunks/35unmm4isvqg5.js +0 -1
- package/out/_next/static/chunks/389wmv2b6x2nn.js +0 -1
- package/out/_next/static/chunks/39-oy5n969lo6.js +0 -1
- package/out/_next/static/chunks/393isf5crmqic.js +0 -1
- package/out/_next/static/chunks/39yvee40syj70.js +0 -1
- package/out/_next/static/chunks/3clhij8e1eul0.js +0 -1
- package/out/_next/static/chunks/3cnsdzbvm3q7p.js +0 -1
- package/out/_next/static/chunks/3cxmalqqghdac.js +0 -1
- package/out/_next/static/chunks/3d9p88evh2scq.js +0 -1
- package/out/_next/static/chunks/3e9ia0hs-pqvs.css +0 -1
- package/out/_next/static/chunks/3ej6im7cbakx3.js +0 -1
- package/out/_next/static/chunks/3ejz1mdljwwqf.css +0 -1
- package/out/_next/static/chunks/3eyprczj7yrg6.js +0 -1
- package/out/_next/static/chunks/3f9v_gtppe4hs.js +0 -1
- package/out/_next/static/chunks/3fj0amtzqae6f.js +0 -1
- package/out/_next/static/chunks/3g0c367tk4esf.js +0 -1
- package/out/_next/static/chunks/3gf98e08a-l_e.js +0 -1
- package/out/_next/static/chunks/3gi6og9m_yaak.js +0 -1
- package/out/_next/static/chunks/3giw7r1lii84y.js +0 -1
- package/out/_next/static/chunks/3gzhy1cs_f2oi.js +0 -1
- package/out/_next/static/chunks/3i_ceknny1oqt.js +0 -1
- package/out/_next/static/chunks/3iw0815ssih3b.js +0 -1
- package/out/_next/static/chunks/3kun-vwr7nzd4.js +0 -1
- package/out/_next/static/chunks/3kxm1e-b1er3_.js +0 -1
- package/out/_next/static/chunks/3m7_o1ihz8ay_.js +0 -1
- package/out/_next/static/chunks/3mc8fynmv71yg.js +0 -1
- package/out/_next/static/chunks/3n6cor2n9zyn7.js +0 -1
- package/out/_next/static/chunks/3oe03qxgd_rid.js +0 -1
- package/out/_next/static/chunks/3or2h8swxfxyj.css +0 -1
- package/out/_next/static/chunks/3ppt04b6xqz29.js +0 -1
- package/out/_next/static/chunks/3ql2pi_m5_5p_.js +0 -1
- package/out/_next/static/chunks/3qm2vbylm324o.css +0 -1
- package/out/_next/static/chunks/3r5wf57k0gys9.js +0 -1
- package/out/_next/static/chunks/3t-6u8caafiu9.js +0 -1
- package/out/_next/static/chunks/3tqdzb_n12tdm.js +0 -1
- package/out/_next/static/chunks/3u6zpg943kpst.js +0 -1
- package/out/_next/static/chunks/3uaedu2hf291z.js +0 -1
- package/out/_next/static/chunks/3uxltn4677hjy.js +0 -1
- package/out/_next/static/chunks/3vladx3wh0d4k.js +0 -1
- package/out/_next/static/chunks/3w2qk10_udrd9.js +0 -1
- package/out/_next/static/chunks/3w4o9hklow6fg.js +0 -2
- package/out/_next/static/chunks/3w56w25z6u89b.js +0 -1
- package/out/_next/static/chunks/3x1y_gkazt6kx.js +0 -1
- package/out/_next/static/chunks/3xl0fq2d3dle6.js +0 -1
- package/out/_next/static/chunks/3y7r1h96dtcov.js +0 -1
- package/out/_next/static/chunks/3yc_zd5vxq0j7.css +0 -1
- package/out/_next/static/chunks/3z0hydntmwg19.js +0 -1
- package/out/_next/static/chunks/3zhu1svjr0bc5.js +0 -1
- package/out/_next/static/chunks/404orp1erq__7.js +0 -1
- package/out/_next/static/chunks/41talcs-dc2tc.js +0 -1
- package/out/_next/static/chunks/421pn8weymo-b.js +0 -1
- package/out/_next/static/chunks/440es_b4nw-7c.css +0 -23
- package/out/_next/static/chunks/44987pmr20now.js +0 -1
- package/out/_next/static/chunks/449ygeh62gitc.js +0 -1
- package/out/_next/static/chunks/turbopack-3vvza9m6839dy.js +0 -1
- package/out/_next/static/media/KaTeX_Size3-Regular.1n1rgzz84z8r9.woff2 +0 -0
- package/out/_not-found/__next._full.txt +0 -22
- package/out/_not-found/__next._head.txt +0 -5
- package/out/_not-found/__next._index.txt +0 -9
- package/out/_not-found/__next._not-found.__PAGE__.txt +0 -9
- package/out/_not-found/__next._not-found.txt +0 -5
- package/out/_not-found/__next._tree.txt +0 -3
- package/out/_not-found/index.html +0 -15
- package/out/_not-found/index.txt +0 -22
- package/out/admin/__next._full.txt +0 -23
- package/out/admin/__next._head.txt +0 -5
- package/out/admin/__next._index.txt +0 -9
- package/out/admin/__next._tree.txt +0 -5
- package/out/admin/__next.admin.__PAGE__.txt +0 -9
- package/out/admin/__next.admin.txt +0 -5
- package/out/admin/index.txt +0 -23
- package/out/app/__next._full.txt +0 -22
- package/out/app/__next._head.txt +0 -5
- package/out/app/__next._index.txt +0 -9
- package/out/app/__next._tree.txt +0 -4
- package/out/app/__next.app.__PAGE__.txt +0 -9
- package/out/app/__next.app.txt +0 -4
- package/out/app/index.txt +0 -22
- package/out/chat/__next._full.txt +0 -23
- package/out/chat/__next._head.txt +0 -5
- package/out/chat/__next._index.txt +0 -9
- package/out/chat/__next._tree.txt +0 -5
- package/out/chat/__next.chat.__PAGE__.txt +0 -9
- package/out/chat/__next.chat.txt +0 -5
- package/out/chat/index.txt +0 -23
- package/out/chat/join/__next._full.txt +0 -25
- package/out/chat/join/__next._head.txt +0 -5
- package/out/chat/join/__next._index.txt +0 -9
- package/out/chat/join/__next._tree.txt +0 -5
- package/out/chat/join/__next.chat.join.__PAGE__.txt +0 -9
- package/out/chat/join/__next.chat.join.txt +0 -5
- package/out/chat/join/__next.chat.txt +0 -5
- package/out/chat/join/index.txt +0 -25
- package/out/demo/__next._full.txt +0 -28
- package/out/demo/__next._head.txt +0 -5
- package/out/demo/__next._index.txt +0 -9
- package/out/demo/__next._tree.txt +0 -8
- package/out/demo/__next.demo.__PAGE__.txt +0 -13
- package/out/demo/__next.demo.txt +0 -5
- package/out/demo/index.txt +0 -28
- package/out/download/__next._full.txt +0 -41
- package/out/download/__next._head.txt +0 -5
- package/out/download/__next._index.txt +0 -9
- package/out/download/__next._tree.txt +0 -6
- package/out/download/__next.download.__PAGE__.txt +0 -10
- package/out/download/__next.download.txt +0 -5
- package/out/download/index.txt +0 -41
- package/out/game/__next._full.txt +0 -20
- package/out/game/__next._head.txt +0 -5
- package/out/game/__next._index.txt +0 -9
- package/out/game/__next._tree.txt +0 -5
- package/out/game/__next.game.__PAGE__.txt +0 -6
- package/out/game/__next.game.txt +0 -5
- package/out/game/gandengyan/__next._full.txt +0 -26
- package/out/game/gandengyan/__next._head.txt +0 -5
- package/out/game/gandengyan/__next._index.txt +0 -9
- package/out/game/gandengyan/__next._tree.txt +0 -6
- package/out/game/gandengyan/__next.game.gandengyan.__PAGE__.txt +0 -10
- package/out/game/gandengyan/__next.game.gandengyan.txt +0 -5
- package/out/game/gandengyan/__next.game.txt +0 -5
- package/out/game/gandengyan/index.txt +0 -26
- package/out/game/index.txt +0 -20
- package/out/game/zhajinhua/__next._full.txt +0 -26
- package/out/game/zhajinhua/__next._head.txt +0 -5
- package/out/game/zhajinhua/__next._index.txt +0 -9
- package/out/game/zhajinhua/__next._tree.txt +0 -6
- package/out/game/zhajinhua/__next.game.txt +0 -5
- package/out/game/zhajinhua/__next.game.zhajinhua.__PAGE__.txt +0 -10
- package/out/game/zhajinhua/__next.game.zhajinhua.txt +0 -5
- package/out/game/zhajinhua/index.txt +0 -26
- package/out/index.txt +0 -24
- package/out/note/__next._full.txt +0 -24
- package/out/note/__next._head.txt +0 -5
- package/out/note/__next._index.txt +0 -9
- package/out/note/__next._tree.txt +0 -4
- package/out/note/__next.note.__PAGE__.txt +0 -9
- package/out/note/__next.note.txt +0 -5
- package/out/note/index.txt +0 -24
- package/out/ping/__next._full.txt +0 -24
- package/out/ping/__next._head.txt +0 -5
- package/out/ping/__next._index.txt +0 -9
- package/out/ping/__next._tree.txt +0 -6
- package/out/ping/__next.ping.__PAGE__.txt +0 -10
- package/out/ping/__next.ping.txt +0 -5
- package/out/ping/index.txt +0 -24
- package/out/web3/__next._full.txt +0 -23
- package/out/web3/__next._head.txt +0 -5
- package/out/web3/__next._index.txt +0 -9
- package/out/web3/__next._tree.txt +0 -5
- package/out/web3/__next.web3.__PAGE__.txt +0 -9
- package/out/web3/__next.web3.txt +0 -5
- package/out/web3/ed25519/__next._full.txt +0 -22
- package/out/web3/ed25519/__next._head.txt +0 -5
- package/out/web3/ed25519/__next._index.txt +0 -9
- package/out/web3/ed25519/__next._tree.txt +0 -5
- package/out/web3/ed25519/__next.web3.ed25519.__PAGE__.txt +0 -6
- package/out/web3/ed25519/__next.web3.ed25519.txt +0 -5
- package/out/web3/ed25519/__next.web3.txt +0 -5
- package/out/web3/ed25519/index.html +0 -1
- package/out/web3/ed25519/index.txt +0 -22
- package/out/web3/index.txt +0 -23
- package/out/web3/tools/__next._full.txt +0 -22
- package/out/web3/tools/__next._head.txt +0 -5
- package/out/web3/tools/__next._index.txt +0 -9
- package/out/web3/tools/__next._tree.txt +0 -5
- package/out/web3/tools/__next.web3.tools.__PAGE__.txt +0 -6
- package/out/web3/tools/__next.web3.tools.txt +0 -5
- package/out/web3/tools/__next.web3.txt +0 -5
- package/out/web3/tools/index.html +0 -1
- package/out/web3/tools/index.txt +0 -22
- /package/out/{_next/static/media/KaTeX_AMS-Regular.25ieegmnh38ts.woff2 → assets/KaTeX_AMS-Regular-BQhdFMY1.woff2} +0 -0
- /package/out/{_next/static/media/KaTeX_AMS-Regular.10y3kupq4t663.woff → assets/KaTeX_AMS-Regular-DMm9YOAa.woff} +0 -0
- /package/out/{_next/static/media/KaTeX_AMS-Regular.418dr7cz3fo2x.ttf → assets/KaTeX_AMS-Regular-DRggAlZN.ttf} +0 -0
- /package/out/{_next/static/media/KaTeX_Caligraphic-Bold.40ltxhe834pns.ttf → assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf} +0 -0
- /package/out/{_next/static/media/KaTeX_Caligraphic-Bold.2vmk2hva4ctha.woff → assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff} +0 -0
- /package/out/{_next/static/media/KaTeX_Caligraphic-Bold.06b-ya9t43ioz.woff2 → assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2} +0 -0
- /package/out/{_next/static/media/KaTeX_Caligraphic-Regular.3gxeetazf831f.woff → assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff} +0 -0
- /package/out/{_next/static/media/KaTeX_Caligraphic-Regular.2eph4dlhid_m9.woff2 → assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2} +0 -0
- /package/out/{_next/static/media/KaTeX_Caligraphic-Regular.07-7u27-nhn_r.ttf → assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf} +0 -0
- /package/out/{_next/static/media/KaTeX_Fraktur-Bold.19yqa_tc9d_gx.ttf → assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf} +0 -0
- /package/out/{_next/static/media/KaTeX_Fraktur-Bold.1alcy76__wdj2.woff → assets/KaTeX_Fraktur-Bold-BsDP51OF.woff} +0 -0
- /package/out/{_next/static/media/KaTeX_Fraktur-Bold.2sasz-d-jtw8y.woff2 → assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2} +0 -0
- /package/out/{_next/static/media/KaTeX_Fraktur-Regular.2qhy34r6a05dn.ttf → assets/KaTeX_Fraktur-Regular-CB_wures.ttf} +0 -0
- /package/out/{_next/static/media/KaTeX_Fraktur-Regular.2d10y4xmjvzlf.woff2 → assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2} +0 -0
- /package/out/{_next/static/media/KaTeX_Fraktur-Regular.110oo81prr9n5.woff → assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff} +0 -0
- /package/out/{_next/static/media/KaTeX_Main-Bold.3-rowy8o6_4ky.woff2 → assets/KaTeX_Main-Bold-Cx986IdX.woff2} +0 -0
- /package/out/{_next/static/media/KaTeX_Main-Bold.0v1esh257kqpe.woff → assets/KaTeX_Main-Bold-Jm3AIy58.woff} +0 -0
- /package/out/{_next/static/media/KaTeX_Main-Bold.0us_n0tnxlxu7.ttf → assets/KaTeX_Main-Bold-waoOVXN0.ttf} +0 -0
- /package/out/{_next/static/media/KaTeX_Main-BoldItalic.14r2naom8mrec.woff2 → assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2} +0 -0
- /package/out/{_next/static/media/KaTeX_Main-BoldItalic.3x_u9cepaced0.ttf → assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf} +0 -0
- /package/out/{_next/static/media/KaTeX_Main-BoldItalic.13355ck5zr48q.woff → assets/KaTeX_Main-BoldItalic-SpSLRI95.woff} +0 -0
- /package/out/{_next/static/media/KaTeX_Main-Italic.2hkw3230mfwcv.ttf → assets/KaTeX_Main-Italic-3WenGoN9.ttf} +0 -0
- /package/out/{_next/static/media/KaTeX_Main-Italic.0afv392dj4w59.woff → assets/KaTeX_Main-Italic-BMLOBm91.woff} +0 -0
- /package/out/{_next/static/media/KaTeX_Main-Italic.0lig0v9j0700p.woff2 → assets/KaTeX_Main-Italic-NWA7e6Wa.woff2} +0 -0
- /package/out/{_next/static/media/KaTeX_Main-Regular.1ryvsdzh2w1_e.woff2 → assets/KaTeX_Main-Regular-B22Nviop.woff2} +0 -0
- /package/out/{_next/static/media/KaTeX_Main-Regular.15u8r3b2y7fv4.woff → assets/KaTeX_Main-Regular-Dr94JaBh.woff} +0 -0
- /package/out/{_next/static/media/KaTeX_Main-Regular.0symfa7dqj6jd.ttf → assets/KaTeX_Main-Regular-ypZvNtVU.ttf} +0 -0
- /package/out/{_next/static/media/KaTeX_Math-BoldItalic.0y5w36a5aq__2.ttf → assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf} +0 -0
- /package/out/{_next/static/media/KaTeX_Math-BoldItalic.1oopuu636h4il.woff2 → assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2} +0 -0
- /package/out/{_next/static/media/KaTeX_Math-BoldItalic.12pl58orkw9rg.woff → assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff} +0 -0
- /package/out/{_next/static/media/KaTeX_Math-Italic.0w0b1ugh62cfr.woff → assets/KaTeX_Math-Italic-DA0__PXp.woff} +0 -0
- /package/out/{_next/static/media/KaTeX_Math-Italic.2vkekfblmz5nb.ttf → assets/KaTeX_Math-Italic-flOr_0UB.ttf} +0 -0
- /package/out/{_next/static/media/KaTeX_Math-Italic.32405s1aq8vas.woff2 → assets/KaTeX_Math-Italic-t53AETM-.woff2} +0 -0
- /package/out/{_next/static/media/KaTeX_SansSerif-Bold.2d03q85pwxpti.ttf → assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf} +0 -0
- /package/out/{_next/static/media/KaTeX_SansSerif-Bold.0h3wi2z_eouyg.woff2 → assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2} +0 -0
- /package/out/{_next/static/media/KaTeX_SansSerif-Bold.1ovw5p-yjp56g.woff → assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff} +0 -0
- /package/out/{_next/static/media/KaTeX_SansSerif-Italic.0wkjc4dm2kcit.woff2 → assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2} +0 -0
- /package/out/{_next/static/media/KaTeX_SansSerif-Italic.1qavw__2zz8gk.woff → assets/KaTeX_SansSerif-Italic-DN2j7dab.woff} +0 -0
- /package/out/{_next/static/media/KaTeX_SansSerif-Italic.3i-q087b23-m8.ttf → assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf} +0 -0
- /package/out/{_next/static/media/KaTeX_SansSerif-Regular.31pbu25feko_c.ttf → assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf} +0 -0
- /package/out/{_next/static/media/KaTeX_SansSerif-Regular.1i4afx8nk8n4r.woff → assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff} +0 -0
- /package/out/{_next/static/media/KaTeX_SansSerif-Regular.2peiewu59z3d-.woff2 → assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2} +0 -0
- /package/out/{_next/static/media/KaTeX_Script-Regular.28p_x7iz71ofe.ttf → assets/KaTeX_Script-Regular-C5JkGWo-.ttf} +0 -0
- /package/out/{_next/static/media/KaTeX_Script-Regular.11h14300o9pd0.woff2 → assets/KaTeX_Script-Regular-D3wIWfF6.woff2} +0 -0
- /package/out/{_next/static/media/KaTeX_Script-Regular.3110jb9c-bxna.woff → assets/KaTeX_Script-Regular-D5yQViql.woff} +0 -0
- /package/out/{_next/static/media/KaTeX_Size1-Regular.1slf4bh0hc6vm.woff → assets/KaTeX_Size1-Regular-C195tn64.woff} +0 -0
- /package/out/{_next/static/media/KaTeX_Size1-Regular.1y57-ck23ey8c.ttf → assets/KaTeX_Size1-Regular-Dbsnue_I.ttf} +0 -0
- /package/out/{_next/static/media/KaTeX_Size1-Regular.03lhvx36ekcou.woff2 → assets/KaTeX_Size1-Regular-mCD8mA8B.woff2} +0 -0
- /package/out/{_next/static/media/KaTeX_Size2-Regular.2u0s-b07k2o9m.ttf → assets/KaTeX_Size2-Regular-B7gKUWhC.ttf} +0 -0
- /package/out/{_next/static/media/KaTeX_Size2-Regular.14s5gg-puz6h-.woff2 → assets/KaTeX_Size2-Regular-Dy4dx90m.woff2} +0 -0
- /package/out/{_next/static/media/KaTeX_Size2-Regular.0-kwyvx03omo8.woff → assets/KaTeX_Size2-Regular-oD1tc_U0.woff} +0 -0
- /package/out/{_next/static/media/KaTeX_Size3-Regular.04o9a_02gu_e8.woff → assets/KaTeX_Size3-Regular-CTq5MqoE.woff} +0 -0
- /package/out/{_next/static/media/KaTeX_Size3-Regular.1pkn-dge4q0fv.ttf → assets/KaTeX_Size3-Regular-DgpXs0kz.ttf} +0 -0
- /package/out/{_next/static/media/KaTeX_Size4-Regular.3p2r1l7xmebxv.woff → assets/KaTeX_Size4-Regular-BF-4gkZK.woff} +0 -0
- /package/out/{_next/static/media/KaTeX_Size4-Regular.2uelkfk2yna5e.ttf → assets/KaTeX_Size4-Regular-DWFBv043.ttf} +0 -0
- /package/out/{_next/static/media/KaTeX_Size4-Regular.2sgotkdv3dcyv.woff2 → assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2} +0 -0
- /package/out/{_next/static/media/KaTeX_Typewriter-Regular.12f8myjij3617.woff → assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff} +0 -0
- /package/out/{_next/static/media/KaTeX_Typewriter-Regular.11gr2d2wuwz77.woff2 → assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2} +0 -0
- /package/out/{_next/static/media/KaTeX_Typewriter-Regular.3nee9kjfy6nm8.ttf → assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf} +0 -0
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export const DEFAULT_OWNER_BUCKET = '__local__'
|
|
2
|
+
|
|
3
|
+
export function normalizeOwnerAddress(address) {
|
|
4
|
+
const value = String(address || '').trim()
|
|
5
|
+
return /^0x[a-fA-F0-9]{40}$/.test(value) ? value.toLowerCase() : ''
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export function getOwnerBucketKey(address) {
|
|
9
|
+
return normalizeOwnerAddress(address) || DEFAULT_OWNER_BUCKET
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function normalizeMetadataBuckets(input) {
|
|
13
|
+
if (!input || typeof input !== 'object' || Array.isArray(input)) {
|
|
14
|
+
return {}
|
|
15
|
+
}
|
|
16
|
+
const buckets = {}
|
|
17
|
+
for (const [rawOwner, records] of Object.entries(input)) {
|
|
18
|
+
const ownerKey =
|
|
19
|
+
rawOwner === DEFAULT_OWNER_BUCKET
|
|
20
|
+
? DEFAULT_OWNER_BUCKET
|
|
21
|
+
: normalizeOwnerAddress(rawOwner)
|
|
22
|
+
if (!ownerKey || !Array.isArray(records)) continue
|
|
23
|
+
buckets[ownerKey] = records.map(record => ({ ...record }))
|
|
24
|
+
}
|
|
25
|
+
return buckets
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function cloneMetadataRecord(record, ownerAddress = '') {
|
|
29
|
+
return {
|
|
30
|
+
...record,
|
|
31
|
+
ownerAddress:
|
|
32
|
+
ownerAddress && ownerAddress !== DEFAULT_OWNER_BUCKET ? ownerAddress : '',
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import crypto from 'node:crypto'
|
|
2
|
+
|
|
3
|
+
export const USER_SYNC_SCHEMA_VERSION = 1
|
|
4
|
+
export const USER_SYNC_NAMESPACE_PREFIX = 'user.sync.'
|
|
5
|
+
|
|
6
|
+
const USER_SYNC_KEY_HEX_LENGTH = 64
|
|
7
|
+
|
|
8
|
+
export function normalizeUserSyncKey(input) {
|
|
9
|
+
const value = String(input || '').trim().replace(/^0x/i, '').toLowerCase()
|
|
10
|
+
return /^[0-9a-f]+$/.test(value) && value.length === USER_SYNC_KEY_HEX_LENGTH
|
|
11
|
+
? value
|
|
12
|
+
: ''
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function deriveUserSyncId(syncTopicKey) {
|
|
16
|
+
return crypto
|
|
17
|
+
.createHash('sha256')
|
|
18
|
+
.update(Buffer.from(syncTopicKey, 'hex'))
|
|
19
|
+
.digest('hex')
|
|
20
|
+
.slice(0, 24)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function getUserSyncName(syncId) {
|
|
24
|
+
return `${USER_SYNC_NAMESPACE_PREFIX}${syncId}`
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function getSyncTimestamp(input, fallback = Date.now()) {
|
|
28
|
+
const numeric = Number(input)
|
|
29
|
+
if (Number.isFinite(numeric) && numeric > 0) return Math.floor(numeric)
|
|
30
|
+
const parsed = Date.parse(String(input || ''))
|
|
31
|
+
return Number.isFinite(parsed) && parsed > 0 ? parsed : fallback
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function getNextSyncTimestamp(previous) {
|
|
35
|
+
return Math.max(Date.now(), getSyncTimestamp(previous, 0) + 1)
|
|
36
|
+
}
|
package/server/src/http/app.js
CHANGED
|
@@ -26,6 +26,7 @@ import {
|
|
|
26
26
|
remoteInviteConfigured,
|
|
27
27
|
} from './access.js'
|
|
28
28
|
import { badRequestOrAppError, errorJson } from './errors.js'
|
|
29
|
+
import { resolveDataPathForSave } from './dataPath.js'
|
|
29
30
|
import { listFilteredNodeLogs } from './nodeLogs.js'
|
|
30
31
|
import {
|
|
31
32
|
buildNodeStatus,
|
|
@@ -33,11 +34,16 @@ import {
|
|
|
33
34
|
getNetworkAddresses,
|
|
34
35
|
getPackageVersion,
|
|
35
36
|
} from './nodeStatus.js'
|
|
37
|
+
import { createRateLimitMiddleware } from './rateLimit.js'
|
|
38
|
+
import {
|
|
39
|
+
validationErrorPayload,
|
|
40
|
+
isPublicFileDownloadPath,
|
|
41
|
+
requiresUserAuth,
|
|
42
|
+
isAdminApi,
|
|
43
|
+
} from './routePolicy.js'
|
|
36
44
|
import { parseMultipartBusboy } from './uploads.js'
|
|
37
45
|
import { getMimeType, registerStaticRoutes } from './staticFiles.js'
|
|
38
46
|
|
|
39
|
-
const RATE_LIMIT_WINDOW = 60 * 1000
|
|
40
|
-
const RATE_LIMIT_MAX_REQUESTS = 120
|
|
41
47
|
export { UPLOAD_TMP_DIR } from './uploads.js'
|
|
42
48
|
|
|
43
49
|
// --- 配置 ---
|
|
@@ -46,38 +52,10 @@ const CONFIG_DIR = defaultConfigStore.configDir
|
|
|
46
52
|
const PORT = DEFAULT_NODE_PORT
|
|
47
53
|
const HOST = DEFAULT_NODE_HOST
|
|
48
54
|
|
|
49
|
-
|
|
50
|
-
|
|
51
55
|
export function getDataPath(configStore = defaultConfigStore) {
|
|
52
56
|
return configStore.getDataPath()
|
|
53
57
|
}
|
|
54
58
|
|
|
55
|
-
function resolveDataPathForSave(inputPath) {
|
|
56
|
-
let dataPath = String(inputPath || '').trim()
|
|
57
|
-
let basePath = dataPath
|
|
58
|
-
|
|
59
|
-
if (!dataPath) {
|
|
60
|
-
return { dataPath: '' }
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
if (dataPath.match(/^[A-Za-z]:\\$/)) {
|
|
64
|
-
basePath = dataPath
|
|
65
|
-
dataPath = path.join(dataPath, 'most-data')
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
if (!fs.existsSync(basePath)) {
|
|
69
|
-
return { error: '目录不存在' }
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
if (!fs.existsSync(dataPath)) {
|
|
73
|
-
fs.mkdirSync(dataPath, { recursive: true })
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
return { dataPath }
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
59
|
// --- Hono 应用工厂 ---
|
|
82
60
|
export function createApp(engine, options = {}) {
|
|
83
61
|
const appPort = options.port || PORT
|
|
@@ -95,40 +73,6 @@ export function createApp(engine, options = {}) {
|
|
|
95
73
|
return new Set(invites)
|
|
96
74
|
}
|
|
97
75
|
|
|
98
|
-
// 速率限制(每个 app 实例独立)
|
|
99
|
-
const rateLimitMap = new Map()
|
|
100
|
-
function checkRateLimit(clientIp) {
|
|
101
|
-
const now = Date.now()
|
|
102
|
-
if (!rateLimitMap.has(clientIp)) {
|
|
103
|
-
rateLimitMap.set(clientIp, [])
|
|
104
|
-
}
|
|
105
|
-
const requests = rateLimitMap.get(clientIp)
|
|
106
|
-
while (requests.length > 0 && requests[0] < now - RATE_LIMIT_WINDOW) {
|
|
107
|
-
requests.shift()
|
|
108
|
-
}
|
|
109
|
-
if (requests.length === 0) {
|
|
110
|
-
rateLimitMap.delete(clientIp)
|
|
111
|
-
}
|
|
112
|
-
if (requests.length >= RATE_LIMIT_MAX_REQUESTS) {
|
|
113
|
-
return false
|
|
114
|
-
}
|
|
115
|
-
requests.push(now)
|
|
116
|
-
return true
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
function rateLimitMiddleware() {
|
|
120
|
-
return async (c, next) => {
|
|
121
|
-
const clientIp =
|
|
122
|
-
c.req.header('x-forwarded-for') ||
|
|
123
|
-
c.env?.incoming?.socket?.remoteAddress ||
|
|
124
|
-
'unknown'
|
|
125
|
-
if (!checkRateLimit(clientIp)) {
|
|
126
|
-
return c.json({ error: 'Too many requests' }, 429)
|
|
127
|
-
}
|
|
128
|
-
await next()
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
|
|
132
76
|
function isValidInvite(c) {
|
|
133
77
|
const invite = String(c.req.header('x-mostbox-invite') || '').trim()
|
|
134
78
|
return hasValidInvite(getRemoteInviteSet(), invite)
|
|
@@ -143,43 +87,6 @@ export function createApp(engine, options = {}) {
|
|
|
143
87
|
})
|
|
144
88
|
}
|
|
145
89
|
|
|
146
|
-
function isPublicFileDownloadPath(path) {
|
|
147
|
-
return /^\/api\/files\/[^/]+\/download$/.test(path)
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
function requiresUserAuth(path) {
|
|
151
|
-
if (isPublicFileDownloadPath(path)) {
|
|
152
|
-
return false
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
return (
|
|
156
|
-
path === '/api/files' ||
|
|
157
|
-
path === '/api/publish' ||
|
|
158
|
-
path === '/api/download/check' ||
|
|
159
|
-
path === '/api/download' ||
|
|
160
|
-
path === '/api/download/cancel' ||
|
|
161
|
-
path === '/api/user/export' ||
|
|
162
|
-
path === '/api/user/import/check' ||
|
|
163
|
-
path === '/api/user/import' ||
|
|
164
|
-
path === '/api/trash' ||
|
|
165
|
-
path === '/api/move' ||
|
|
166
|
-
path === '/api/folder/rename' ||
|
|
167
|
-
path.startsWith('/api/files/') ||
|
|
168
|
-
path.startsWith('/api/trash/') ||
|
|
169
|
-
path.startsWith('/api/channels')
|
|
170
|
-
)
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
function isAdminApi(path) {
|
|
174
|
-
return (
|
|
175
|
-
path.startsWith('/api/admin/') ||
|
|
176
|
-
path === '/api/node/config' ||
|
|
177
|
-
path === '/api/node/policy' ||
|
|
178
|
-
path === '/api/node/logs' ||
|
|
179
|
-
path === '/api/shutdown'
|
|
180
|
-
)
|
|
181
|
-
}
|
|
182
|
-
|
|
183
90
|
function authMiddleware() {
|
|
184
91
|
return async (c, next) => {
|
|
185
92
|
const path = getRequestPath(c)
|
|
@@ -356,7 +263,7 @@ export function createApp(engine, options = {}) {
|
|
|
356
263
|
)
|
|
357
264
|
|
|
358
265
|
// 速率限制中间件
|
|
359
|
-
app.use('/api/*',
|
|
266
|
+
app.use('/api/*', createRateLimitMiddleware())
|
|
360
267
|
app.use('/api/*', authMiddleware())
|
|
361
268
|
|
|
362
269
|
// 全局错误处理
|
|
@@ -550,22 +457,17 @@ export function createApp(engine, options = {}) {
|
|
|
550
457
|
return c.json({ users: engine.listUsers() })
|
|
551
458
|
})
|
|
552
459
|
|
|
553
|
-
app.
|
|
554
|
-
try {
|
|
555
|
-
return c.json(engine.exportUserMetadata(c.get('userAddress')))
|
|
556
|
-
} catch (err) {
|
|
557
|
-
return errorJson(c, err)
|
|
558
|
-
}
|
|
559
|
-
})
|
|
560
|
-
|
|
561
|
-
app.post('/api/user/import/check', async c => {
|
|
460
|
+
app.post('/api/user/sync/start', async c => {
|
|
562
461
|
try {
|
|
563
462
|
const body = await c.req.json()
|
|
564
|
-
const
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
463
|
+
const result = await engine.startUserSync(c.get('userAddress'), body)
|
|
464
|
+
appendNodeLog({
|
|
465
|
+
event: 'node:user-sync:started',
|
|
466
|
+
message: 'User sync started',
|
|
467
|
+
data: {
|
|
468
|
+
ownerAddress: result.ownerAddress,
|
|
469
|
+
syncName: result.syncName,
|
|
470
|
+
},
|
|
569
471
|
})
|
|
570
472
|
return c.json({ success: true, ...result })
|
|
571
473
|
} catch (err) {
|
|
@@ -573,27 +475,9 @@ export function createApp(engine, options = {}) {
|
|
|
573
475
|
}
|
|
574
476
|
})
|
|
575
477
|
|
|
576
|
-
app.
|
|
478
|
+
app.get('/api/user/sync/status', c => {
|
|
577
479
|
try {
|
|
578
|
-
|
|
579
|
-
const timeout =
|
|
580
|
-
body.timeout === undefined ? undefined : Number(body.timeout)
|
|
581
|
-
const result = await engine.importUserMetadata(body.package || body, {
|
|
582
|
-
ownerAddress: c.get('userAddress'),
|
|
583
|
-
checkId: body.checkId,
|
|
584
|
-
timeout: Number.isFinite(timeout) && timeout > 0 ? timeout : undefined,
|
|
585
|
-
})
|
|
586
|
-
appendNodeLog({
|
|
587
|
-
event: 'node:user-data:imported',
|
|
588
|
-
message: 'User data imported',
|
|
589
|
-
data: {
|
|
590
|
-
ownerAddress: result.ownerAddress,
|
|
591
|
-
importedFiles: result.importedFiles,
|
|
592
|
-
failedFiles: result.failedFiles.length,
|
|
593
|
-
},
|
|
594
|
-
})
|
|
595
|
-
await broadcastNodeStatus()
|
|
596
|
-
return c.json(result)
|
|
480
|
+
return c.json(engine.getUserSyncStatus(c.get('userAddress')))
|
|
597
481
|
} catch (err) {
|
|
598
482
|
return errorJson(c, err)
|
|
599
483
|
}
|
|
@@ -720,8 +604,11 @@ export function createApp(engine, options = {}) {
|
|
|
720
604
|
}
|
|
721
605
|
|
|
722
606
|
const parsed = parseMostLink(body.link)
|
|
723
|
-
if (parsed.
|
|
724
|
-
return c.json(
|
|
607
|
+
if (parsed.errorCode) {
|
|
608
|
+
return c.json(
|
|
609
|
+
validationErrorPayload(parsed.errorCode, parsed.details),
|
|
610
|
+
400
|
|
611
|
+
)
|
|
725
612
|
}
|
|
726
613
|
|
|
727
614
|
const localAvailability = await engine.getLocalCidAvailability(body.link, {
|
|
@@ -770,8 +657,11 @@ export function createApp(engine, options = {}) {
|
|
|
770
657
|
const taskId = `dl_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`
|
|
771
658
|
|
|
772
659
|
const parsed = parseMostLink(body.link)
|
|
773
|
-
if (parsed.
|
|
774
|
-
return c.json(
|
|
660
|
+
if (parsed.errorCode) {
|
|
661
|
+
return c.json(
|
|
662
|
+
validationErrorPayload(parsed.errorCode, parsed.details),
|
|
663
|
+
400
|
|
664
|
+
)
|
|
775
665
|
}
|
|
776
666
|
|
|
777
667
|
const localAvailability = await engine.getLocalCidAvailability(body.link, {
|
|
@@ -827,7 +717,7 @@ export function createApp(engine, options = {}) {
|
|
|
827
717
|
const cid = c.req.param('cid')
|
|
828
718
|
const cidValidation = validateCidString(cid)
|
|
829
719
|
if (!cidValidation.valid) {
|
|
830
|
-
return c.json(
|
|
720
|
+
return c.json(validationErrorPayload(cidValidation.errorCode), 400)
|
|
831
721
|
}
|
|
832
722
|
const result = await engine.deletePublishedFile(cid, {
|
|
833
723
|
ownerAddress: c.get('userAddress'),
|
|
@@ -835,6 +725,27 @@ export function createApp(engine, options = {}) {
|
|
|
835
725
|
return c.json(result)
|
|
836
726
|
})
|
|
837
727
|
|
|
728
|
+
app.post('/api/files/:cid/cache', async c => {
|
|
729
|
+
const cid = c.req.param('cid')
|
|
730
|
+
const cidValidation = validateCidString(cid)
|
|
731
|
+
if (!cidValidation.valid) {
|
|
732
|
+
return c.json(validationErrorPayload(cidValidation.errorCode), 400)
|
|
733
|
+
}
|
|
734
|
+
try {
|
|
735
|
+
const body = await c.req.json().catch(() => ({}))
|
|
736
|
+
const timeout =
|
|
737
|
+
body.timeout === undefined ? undefined : Number(body.timeout)
|
|
738
|
+
const result = await engine.cacheFile(cid, {
|
|
739
|
+
ownerAddress: c.get('userAddress'),
|
|
740
|
+
timeout: Number.isFinite(timeout) && timeout > 0 ? timeout : undefined,
|
|
741
|
+
taskId: body.taskId,
|
|
742
|
+
})
|
|
743
|
+
return c.json({ success: true, ...result })
|
|
744
|
+
} catch (err) {
|
|
745
|
+
return badRequestOrAppError(c, err)
|
|
746
|
+
}
|
|
747
|
+
})
|
|
748
|
+
|
|
838
749
|
app.post('/api/move', async c => {
|
|
839
750
|
const body = await c.req.json()
|
|
840
751
|
if (!body.cid || !body.newFileName) {
|
|
@@ -842,7 +753,7 @@ export function createApp(engine, options = {}) {
|
|
|
842
753
|
}
|
|
843
754
|
const cidValidation = validateCidString(body.cid)
|
|
844
755
|
if (!cidValidation.valid) {
|
|
845
|
-
return c.json(
|
|
756
|
+
return c.json(validationErrorPayload(cidValidation.errorCode), 400)
|
|
846
757
|
}
|
|
847
758
|
const cleanFileName = sanitizeFilename(body.newFileName)
|
|
848
759
|
if (
|
|
@@ -866,7 +777,7 @@ export function createApp(engine, options = {}) {
|
|
|
866
777
|
const cid = c.req.param('cid')
|
|
867
778
|
const cidValidation = validateCidString(cid)
|
|
868
779
|
if (!cidValidation.valid) {
|
|
869
|
-
return c.json(
|
|
780
|
+
return c.json(validationErrorPayload(cidValidation.errorCode), 400)
|
|
870
781
|
}
|
|
871
782
|
|
|
872
783
|
const rangeHeader = c.req.header('range')
|
|
@@ -928,7 +839,7 @@ export function createApp(engine, options = {}) {
|
|
|
928
839
|
const cid = c.req.param('cid')
|
|
929
840
|
const cidValidation = validateCidString(cid)
|
|
930
841
|
if (!cidValidation.valid) {
|
|
931
|
-
return c.json(
|
|
842
|
+
return c.json(validationErrorPayload(cidValidation.errorCode), 400)
|
|
932
843
|
}
|
|
933
844
|
try {
|
|
934
845
|
const result = await engine.restoreTrashFile(cid, {
|
|
@@ -944,7 +855,7 @@ export function createApp(engine, options = {}) {
|
|
|
944
855
|
const cid = c.req.param('cid')
|
|
945
856
|
const cidValidation = validateCidString(cid)
|
|
946
857
|
if (!cidValidation.valid) {
|
|
947
|
-
return c.json(
|
|
858
|
+
return c.json(validationErrorPayload(cidValidation.errorCode), 400)
|
|
948
859
|
}
|
|
949
860
|
const result = await engine.permanentDeleteTrashFile(cid, {
|
|
950
861
|
ownerAddress: c.get('userAddress'),
|
|
@@ -964,7 +875,7 @@ export function createApp(engine, options = {}) {
|
|
|
964
875
|
const cid = c.req.param('cid')
|
|
965
876
|
const cidValidation = validateCidString(cid)
|
|
966
877
|
if (!cidValidation.valid) {
|
|
967
|
-
return c.json(
|
|
878
|
+
return c.json(validationErrorPayload(cidValidation.errorCode), 400)
|
|
968
879
|
}
|
|
969
880
|
try {
|
|
970
881
|
const result = engine.toggleStarred(cid, {
|
|
@@ -1011,9 +922,12 @@ export function createApp(engine, options = {}) {
|
|
|
1011
922
|
ownerAddress: c.get('userAddress'),
|
|
1012
923
|
displayName: body.displayName,
|
|
1013
924
|
avatar: body.avatar,
|
|
925
|
+
channelKey: body.channelKey,
|
|
926
|
+
fingerprint: body.fingerprint,
|
|
927
|
+
discover: true,
|
|
1014
928
|
}
|
|
1015
929
|
)
|
|
1016
|
-
return c.json({ success:
|
|
930
|
+
return c.json({ success: !result.conflict, ...result })
|
|
1017
931
|
} catch (err) {
|
|
1018
932
|
return c.json({ error: err.message }, 400)
|
|
1019
933
|
}
|
|
@@ -1029,8 +943,11 @@ export function createApp(engine, options = {}) {
|
|
|
1029
943
|
)
|
|
1030
944
|
})
|
|
1031
945
|
|
|
1032
|
-
|
|
1033
|
-
const name =
|
|
946
|
+
const leaveChannelForRequest = async (c, channelIdentifier) => {
|
|
947
|
+
const name = String(channelIdentifier || '').trim()
|
|
948
|
+
if (!name) {
|
|
949
|
+
return c.json({ error: '频道标识不能为空' }, 400)
|
|
950
|
+
}
|
|
1034
951
|
try {
|
|
1035
952
|
const result = await engine.leaveChannel(name, {
|
|
1036
953
|
ownerAddress: c.get('userAddress'),
|
|
@@ -1039,6 +956,11 @@ export function createApp(engine, options = {}) {
|
|
|
1039
956
|
} catch (err) {
|
|
1040
957
|
return c.json({ error: err.message }, 400)
|
|
1041
958
|
}
|
|
959
|
+
}
|
|
960
|
+
|
|
961
|
+
app.delete('/api/channels', async c => {
|
|
962
|
+
const body = await c.req.json().catch(() => ({}))
|
|
963
|
+
return leaveChannelForRequest(c, body.channelKey || body.name)
|
|
1042
964
|
})
|
|
1043
965
|
|
|
1044
966
|
app.get('/api/channels/:name/messages', async c => {
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import fs from 'node:fs'
|
|
2
|
+
import path from 'node:path'
|
|
3
|
+
|
|
4
|
+
export function resolveDataPathForSave(inputPath) {
|
|
5
|
+
let dataPath = String(inputPath || '').trim()
|
|
6
|
+
let basePath = dataPath
|
|
7
|
+
|
|
8
|
+
if (!dataPath) {
|
|
9
|
+
return { dataPath: '' }
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
if (dataPath.match(/^[A-Za-z]:\\$/)) {
|
|
13
|
+
basePath = dataPath
|
|
14
|
+
dataPath = path.join(dataPath, 'most-data')
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
if (!fs.existsSync(basePath)) {
|
|
18
|
+
return { error: '目录不存在' }
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
if (!fs.existsSync(dataPath)) {
|
|
22
|
+
fs.mkdirSync(dataPath, { recursive: true })
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return { dataPath }
|
|
26
|
+
}
|
|
@@ -20,11 +20,15 @@ export function getApiErrorStatus(err) {
|
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
export function errorJson(c, err) {
|
|
23
|
+
const payload = {
|
|
24
|
+
error: err.message,
|
|
25
|
+
code: err.code || 'UNKNOWN',
|
|
26
|
+
}
|
|
27
|
+
if (err.errorCode) payload.errorCode = err.errorCode
|
|
28
|
+
if (err.details) payload.details = err.details
|
|
29
|
+
|
|
23
30
|
return c.json(
|
|
24
|
-
|
|
25
|
-
error: err.message,
|
|
26
|
-
code: err.code || 'UNKNOWN',
|
|
27
|
-
},
|
|
31
|
+
payload,
|
|
28
32
|
getApiErrorStatus(err)
|
|
29
33
|
)
|
|
30
34
|
}
|
|
@@ -137,22 +137,16 @@ export function buildOpenApiSpec(appPort) {
|
|
|
137
137
|
responses: { 200: { description: 'Pull task result' } },
|
|
138
138
|
},
|
|
139
139
|
},
|
|
140
|
-
'/api/user/
|
|
141
|
-
get: {
|
|
142
|
-
summary: 'Export authenticated user metadata',
|
|
143
|
-
responses: { 200: { description: 'User metadata export' } },
|
|
144
|
-
},
|
|
145
|
-
},
|
|
146
|
-
'/api/user/import/check': {
|
|
140
|
+
'/api/user/sync/start': {
|
|
147
141
|
post: {
|
|
148
|
-
summary: '
|
|
149
|
-
responses: { 200: { description: '
|
|
142
|
+
summary: 'Start hidden authenticated user metadata sync',
|
|
143
|
+
responses: { 200: { description: 'User sync status' } },
|
|
150
144
|
},
|
|
151
145
|
},
|
|
152
|
-
'/api/user/
|
|
153
|
-
|
|
154
|
-
summary: '
|
|
155
|
-
responses: { 200: { description: '
|
|
146
|
+
'/api/user/sync/status': {
|
|
147
|
+
get: {
|
|
148
|
+
summary: 'Read authenticated user metadata sync status',
|
|
149
|
+
responses: { 200: { description: 'User sync status' } },
|
|
156
150
|
},
|
|
157
151
|
},
|
|
158
152
|
'/api/files': {
|
|
@@ -161,6 +155,12 @@ export function buildOpenApiSpec(appPort) {
|
|
|
161
155
|
responses: { 200: { description: 'Published file list' } },
|
|
162
156
|
},
|
|
163
157
|
},
|
|
158
|
+
'/api/files/{cid}/cache': {
|
|
159
|
+
post: {
|
|
160
|
+
summary: 'Pull a synced directory file into this node cache',
|
|
161
|
+
responses: { 200: { description: 'Cache pull result' } },
|
|
162
|
+
},
|
|
163
|
+
},
|
|
164
164
|
'/api/publish': {
|
|
165
165
|
post: {
|
|
166
166
|
summary: 'Publish a file and start seeding by CID',
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
const DEFAULT_RATE_LIMIT_WINDOW = 60 * 1000
|
|
2
|
+
const DEFAULT_RATE_LIMIT_MAX_REQUESTS = 120
|
|
3
|
+
|
|
4
|
+
export function createRateLimitMiddleware({
|
|
5
|
+
windowMs = DEFAULT_RATE_LIMIT_WINDOW,
|
|
6
|
+
maxRequests = DEFAULT_RATE_LIMIT_MAX_REQUESTS,
|
|
7
|
+
} = {}) {
|
|
8
|
+
const rateLimitMap = new Map()
|
|
9
|
+
|
|
10
|
+
function checkRateLimit(clientIp) {
|
|
11
|
+
const now = Date.now()
|
|
12
|
+
if (!rateLimitMap.has(clientIp)) {
|
|
13
|
+
rateLimitMap.set(clientIp, [])
|
|
14
|
+
}
|
|
15
|
+
const requests = rateLimitMap.get(clientIp)
|
|
16
|
+
while (requests.length > 0 && requests[0] < now - windowMs) {
|
|
17
|
+
requests.shift()
|
|
18
|
+
}
|
|
19
|
+
if (requests.length === 0) {
|
|
20
|
+
rateLimitMap.delete(clientIp)
|
|
21
|
+
}
|
|
22
|
+
if (requests.length >= maxRequests) {
|
|
23
|
+
return false
|
|
24
|
+
}
|
|
25
|
+
requests.push(now)
|
|
26
|
+
return true
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return async (c, next) => {
|
|
30
|
+
const clientIp =
|
|
31
|
+
c.req.header('x-forwarded-for') ||
|
|
32
|
+
c.env?.incoming?.socket?.remoteAddress ||
|
|
33
|
+
'unknown'
|
|
34
|
+
if (!checkRateLimit(clientIp)) {
|
|
35
|
+
return c.json({ error: 'Too many requests' }, 429)
|
|
36
|
+
}
|
|
37
|
+
await next()
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
export function validationErrorPayload(errorCode, details = undefined) {
|
|
2
|
+
return {
|
|
3
|
+
errorCode,
|
|
4
|
+
code: 'VALIDATION_ERROR',
|
|
5
|
+
...(details ? { details } : {}),
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function isPublicFileDownloadPath(path) {
|
|
10
|
+
return /^\/api\/files\/[^/]+\/download$/.test(path)
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function requiresUserAuth(path) {
|
|
14
|
+
if (isPublicFileDownloadPath(path)) {
|
|
15
|
+
return false
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
return (
|
|
19
|
+
path === '/api/files' ||
|
|
20
|
+
path === '/api/publish' ||
|
|
21
|
+
path === '/api/download/check' ||
|
|
22
|
+
path === '/api/download' ||
|
|
23
|
+
path === '/api/download/cancel' ||
|
|
24
|
+
path === '/api/user/sync/start' ||
|
|
25
|
+
path === '/api/user/sync/status' ||
|
|
26
|
+
path === '/api/trash' ||
|
|
27
|
+
path === '/api/move' ||
|
|
28
|
+
path === '/api/folder/rename' ||
|
|
29
|
+
path.startsWith('/api/files/') ||
|
|
30
|
+
path.startsWith('/api/trash/') ||
|
|
31
|
+
path.startsWith('/api/channels')
|
|
32
|
+
)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function isAdminApi(path) {
|
|
36
|
+
return (
|
|
37
|
+
path.startsWith('/api/admin/') ||
|
|
38
|
+
path === '/api/node/config' ||
|
|
39
|
+
path === '/api/node/policy' ||
|
|
40
|
+
path === '/api/node/logs' ||
|
|
41
|
+
path === '/api/shutdown'
|
|
42
|
+
)
|
|
43
|
+
}
|
|
@@ -38,8 +38,8 @@ export function getMimeType(fileName) {
|
|
|
38
38
|
export function registerStaticRoutes(app) {
|
|
39
39
|
const publicDir = path.join(__dirname, '..', '..', '..', 'out')
|
|
40
40
|
|
|
41
|
+
app.get('/assets/*', serveStatic({ root: './out' }))
|
|
41
42
|
app.get('/static/*', serveStatic({ root: './out' }))
|
|
42
|
-
app.get('/_next/*', serveStatic({ root: './out' }))
|
|
43
43
|
|
|
44
44
|
app.all('/api/*', c => {
|
|
45
45
|
return c.json({ error: 'Not found' }, 404)
|