cajonzero 0.0.0-stage → 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +73 -2
- package/dist/bin/cj0.d.ts +1 -0
- package/dist/bin/cj0.js +477 -0
- package/dist/bin/cj0.js.map +1 -0
- package/dist/config-BiQK9O_0.d.ts +278 -0
- package/dist/core.d.ts +109 -0
- package/dist/core.js +17918 -0
- package/dist/core.js.map +1 -0
- package/dist/index.d.ts +133 -0
- package/dist/index.js +27210 -0
- package/dist/index.js.map +1 -0
- package/dist/room-BVwLGGkm.d.ts +5225 -0
- package/dist/scaffold.d.ts +150 -0
- package/dist/scaffold.js +294 -0
- package/dist/scaffold.js.map +1 -0
- package/dist/serve.d.ts +113 -0
- package/dist/serve.js +27215 -0
- package/dist/serve.js.map +1 -0
- package/dist/ui/assets/A-BFmQQnEZ.png +0 -0
- package/dist/ui/assets/B-7CK86GBa.png +0 -0
- package/dist/ui/assets/Code-New-Roman-Bold-DHej6F6U.woff +0 -0
- package/dist/ui/assets/arrow-4n-TatjQ.png +0 -0
- package/dist/ui/assets/crouch-2Aeej1uw.png +0 -0
- package/dist/ui/assets/fly-Dl5t170A.png +0 -0
- package/dist/ui/assets/fly-reversed-E3sWxK74.png +0 -0
- package/dist/ui/assets/index-CsaJDw8o.js +4405 -0
- package/dist/ui/assets/index-W1HlDaw6.css +2 -0
- package/dist/ui/assets/jump-Al-21z7o.png +0 -0
- package/dist/ui/assets/main-BgFJ4-4_.js +7108 -0
- package/dist/ui/assets/particle.worker-D6dE_8ka.js +1 -0
- package/dist/ui/assets/photo-image-N0oLY1qP.png +0 -0
- package/dist/ui/assets/rubik-v20-latin-regular-B0q52jxy.woff2 +0 -0
- package/dist/ui/assets/script-D_l9sqM8.js +1 -0
- package/dist/ui/assets/voxel.worker-CvX1GY4o.js +1 -0
- package/dist/ui/cajonzero-assets/blobs/-4Z3u_vlCPmpCRsG-tr5eLI4On13qNTpgnT-DArvjPo +0 -0
- package/dist/ui/cajonzero-assets/blobs/-PwWZ9AEpzk377FQDI94jsphx1MzasVJd5s4zFZDhcU +0 -0
- package/dist/ui/cajonzero-assets/blobs/0uyvWiAlEwsxmi0aHE_bJEt2Czve3sfSpfF5T-8zWEo +0 -0
- package/dist/ui/cajonzero-assets/blobs/17CzAKUuiO68ymvOPlXf7da1QdhU78fcsKHtC6l850k +0 -0
- package/dist/ui/cajonzero-assets/blobs/1Sz9b2RJLB_LTdrWxGCy_1gx051sihM7Msn1OPg1uZY +0 -0
- package/dist/ui/cajonzero-assets/blobs/2SICLQuRD8nYoThtljS24xnVHMMaMFVQkTqT7YpUWyo +0 -0
- package/dist/ui/cajonzero-assets/blobs/2re1r3Sq3BW4g_kYo-2WC_u07vNXFYEn5fhUJDmD_lA +0 -0
- package/dist/ui/cajonzero-assets/blobs/3TITLhARLguVu71MnxN91pt5s8g301Ox3XPzzEbQ6bE +0 -0
- package/dist/ui/cajonzero-assets/blobs/3t4Jqs6gaJacqhnYDgqZ2vYS7JaPgRlUHB-By0rvqGI +0 -0
- package/dist/ui/cajonzero-assets/blobs/3wkhe7Ans_MZGGPsPTvtS7-q_pZdwHwChZJqcGH2Cr4 +0 -0
- package/dist/ui/cajonzero-assets/blobs/4EalxePRBTvHC2WVL7jWpab9vk7znXwq-tk0wZM3zAw +0 -0
- package/dist/ui/cajonzero-assets/blobs/4jRcLv0pBJE9AjT8Jc9jZDDeUfc_RHzVfsJZyeMuaok +0 -0
- package/dist/ui/cajonzero-assets/blobs/4otrUC6iqWA4J7gzPlGy9MbuPzYpYEUKcKMkaNDcRtw +0 -0
- package/dist/ui/cajonzero-assets/blobs/57m8K7_P-oRkudRkii4mjK2HgQ1qRL5DSVn1JRHCrUc +0 -0
- package/dist/ui/cajonzero-assets/blobs/5cwYkZ2jXAx4nXS0eZ4Rf6pInNuohcrZJzePgx_WkzU +0 -0
- package/dist/ui/cajonzero-assets/blobs/5oJbXf0svH-YNSfnjXrPtuq9bY6XYa4gcagb_5a9rQc +0 -0
- package/dist/ui/cajonzero-assets/blobs/6Vv-ANt6YO7b-e8gUkS1T4eDXPeMDv3sSS1Fys_h0S8 +0 -0
- package/dist/ui/cajonzero-assets/blobs/6rwaXC7s1n3549pYT9Eh_9qeBK3R_p6rKBLHt7BPcsU +0 -0
- package/dist/ui/cajonzero-assets/blobs/7xhQlsJCS24FVMSPcr62lAC83e5Xeg_Z77kAa2Cai3U +0 -0
- package/dist/ui/cajonzero-assets/blobs/9gtCoNxXqTSG7QKR1FpbpF0ySeNvA-JMrlq17Qm-L2k +0 -0
- package/dist/ui/cajonzero-assets/blobs/AfkW1bfj2sZ2x0QleyXGTAAICRTtJynxj9qYFftu0cc +0 -0
- package/dist/ui/cajonzero-assets/blobs/BtoygkjjKTbFkCz-YqoBuYw26F6Bm6ZYGQYe_j9Ll44 +0 -0
- package/dist/ui/cajonzero-assets/blobs/CjzpqeDMGwTW4rwJnDVa7L_-ZMPXB83GZIDbDY7cWCM +0 -0
- package/dist/ui/cajonzero-assets/blobs/DJB3mDs16RuGcdOKCCjMMXwyI6p5lZrbgPjY_L6Uk7Q +0 -0
- package/dist/ui/cajonzero-assets/blobs/DtP529xgwDaffRCOkb2XVsG6HqkPHlbcrklgpT-As_8 +0 -0
- package/dist/ui/cajonzero-assets/blobs/Ehfy317KJDTCmpuXWLRcS5Ljl7CvRBnVCE4S-nr8O0M +0 -0
- package/dist/ui/cajonzero-assets/blobs/F4c5IJb4dFkgAUxJ0r7Jw_U3u-k7MrpFcpkKSle-P2k +0 -0
- package/dist/ui/cajonzero-assets/blobs/FTlABwbChFrePJf9WWAYf1tVorJpT9qdgAfS0xQtxdM +0 -0
- package/dist/ui/cajonzero-assets/blobs/FXWQtkvKoY33JwIpKVbPNlKs542KIEbQ4INP6VknKTE +0 -0
- package/dist/ui/cajonzero-assets/blobs/GTuRfQ8lo5UVNwVRkX0pffhoTDLnsj_hdgCl0hFPlxk +0 -0
- package/dist/ui/cajonzero-assets/blobs/GnW35Ac04sg4J8H2mKIwAfNbtzNuVHM3TVICOTNx_jQ +0 -0
- package/dist/ui/cajonzero-assets/blobs/GzV7zUemaTlJlNSuvN_A38PtKnuihTHjPpc0l5Dx_aU +0 -0
- package/dist/ui/cajonzero-assets/blobs/HdmOGRHGe3rUiEAvtIPlU2-ou76v7FLYGIIKIcu_rOs +0 -0
- package/dist/ui/cajonzero-assets/blobs/I4_DYrkbGGvsGQoptmNOn5ZVJ_ShkU-105VIJq2eXrc +0 -0
- package/dist/ui/cajonzero-assets/blobs/IMPYtbLaJ3KYgGN0RrgUGSy2wrJhfY7DNzfhE96S_WY +0 -0
- package/dist/ui/cajonzero-assets/blobs/IxW-SXDozs0JBS_q3CftTLVxGI1O8j63AGTBOFSv3Ck +0 -0
- package/dist/ui/cajonzero-assets/blobs/KpmKCcqs55T8Ge4r9qk_v9OaUSiTnb1quPj2RAHY7hU +0 -0
- package/dist/ui/cajonzero-assets/blobs/KvktHZAiSMrblY_XLWh_yHCtsfv3jLmqRgt-zGu2HR0 +0 -0
- package/dist/ui/cajonzero-assets/blobs/L97ARUcIR9G1_lSv1c8-d_qhr-qB15A3Ew4UJ1FnhAY +0 -0
- package/dist/ui/cajonzero-assets/blobs/LDdpinDyYwd0nQBnv1o81bQEZET_IzlYwghWyw6VG7Q +0 -0
- package/dist/ui/cajonzero-assets/blobs/LIIiMuy_uWeS45Hy_9Hvk1AihC5wguY2eGlfaMGb38k +0 -0
- package/dist/ui/cajonzero-assets/blobs/M5L_6hoJaAVEh2olpp0jlhlE6awG_QCmAMPyuIDjY1c +0 -0
- package/dist/ui/cajonzero-assets/blobs/MI21yB2DhnLlllbB8CQJtTaH24CL944CDz-RSe05kqA +0 -0
- package/dist/ui/cajonzero-assets/blobs/MKXaSqTVklFqaVL1AmWCzzeOsk-pe6Nc4xU8VwH8Zlk +0 -0
- package/dist/ui/cajonzero-assets/blobs/MQtnqyF5NPGjICV8o3LaJkf7bVXmGCfZfcxIIoJ9JSo +0 -0
- package/dist/ui/cajonzero-assets/blobs/N79jLwnB0Kzh14itL-F-M2fTm3-hAwATe-6AG_IIG8Y +0 -0
- package/dist/ui/cajonzero-assets/blobs/P01aphf0Yi8p9JgmbIM1cnZWdlmdXQ1IchBT0zUt8BY +0 -0
- package/dist/ui/cajonzero-assets/blobs/PvWei7AAs5UIWUPoZSq21E1abNJ7CakCZHkqq9JdD50 +0 -0
- package/dist/ui/cajonzero-assets/blobs/Px0I6b2Moqpmd_wPzbx7iIdoMo--LYwFs4vOX3DIEzE +0 -0
- package/dist/ui/cajonzero-assets/blobs/QkjGc5q5hFFv6nk338copZyNAOkmUxMJoXbOO3o9OFA +0 -0
- package/dist/ui/cajonzero-assets/blobs/QmPQknmf2oEh2jqbTmodWmYk5efxh2tUH82G8436NyJrcw +0 -0
- package/dist/ui/cajonzero-assets/blobs/QmPXZBKX2AzkpfGzFFwLxT2W5Bx9ZQZf8druHJM9dH24eX +0 -0
- package/dist/ui/cajonzero-assets/blobs/QmQNdCWfckFcMqQsPEgzhtogS6RcCxVGXXdVuMc3T6aEop +0 -0
- package/dist/ui/cajonzero-assets/blobs/QmQzVFuxXyhr8jq2y9ffB6UT1qrL1Aj2mKtk1ozvzxq7gV +0 -0
- package/dist/ui/cajonzero-assets/blobs/QmRxn3YzyYcJqwaup7jNtFgRs8NFqbY32GLDSegjz33Zhb +0 -0
- package/dist/ui/cajonzero-assets/blobs/QmS8fXohiXa2hMXa19ZegWMFHt5JKu2cZzyYLSdYRwEF4N +0 -0
- package/dist/ui/cajonzero-assets/blobs/QmT2jX7MZToEeK5Xh7NcVMArcPygaggqhdKoV17MBfRrWS +0 -0
- package/dist/ui/cajonzero-assets/blobs/QmU5nobMghwRPUpqLEpqdFg44iVRwhwQ31THcaaJzkMCDM +0 -0
- package/dist/ui/cajonzero-assets/blobs/QmV3hSe9mPsHZ33wqeAg8P3xcHfNgXNyuBW8Z56AoyytNZ +0 -0
- package/dist/ui/cajonzero-assets/blobs/QmYC3jWpfvAKMnv34CnhRUjPgZBouaVPySoV7MVMxYgnVG +0 -0
- package/dist/ui/cajonzero-assets/blobs/QmYDKCsFcxJ2JnmwaWLL9irVhTh31hEeL96Pd3Z1XL8A4H +0 -0
- package/dist/ui/cajonzero-assets/blobs/QmYzvFSBhJ1phKQxHAsT3qq3aJFG1MaKxuRrA43tFXEP1W +1 -0
- package/dist/ui/cajonzero-assets/blobs/QmZBk7rEoQJznXRLT81aM8xjj97nwb3fPY5Hp3qAtenqbw +1 -0
- package/dist/ui/cajonzero-assets/blobs/QmZhiM1oCKYpR2FdrL9LebRHuAmDPXx6Dn7rhGxjKzKQkk +1 -0
- package/dist/ui/cajonzero-assets/blobs/Qmaavi38pp2oU1Ui4WYCAjezGzoDUbk8VPnt2LM2whg1xW +0 -0
- package/dist/ui/cajonzero-assets/blobs/Qmbyf9vm2V2qE2GhUq8duNCc9ndPiLmXejkFdNPej3HuEj +0 -0
- package/dist/ui/cajonzero-assets/blobs/Qmcaq7qeDrnGD3xZvvAM6qcLKeN7v2mpsK2G5T22fgwWMn +0 -0
- package/dist/ui/cajonzero-assets/blobs/QmcuRgtLmk3cZToiCVHHvpgmvo9UV9a9mNry4qcmRh9s7q +0 -0
- package/dist/ui/cajonzero-assets/blobs/RD-J5rgF2xqGvZmFOoZT-DW-LMHZh9f8o9a7dgPMUlw +0 -0
- package/dist/ui/cajonzero-assets/blobs/RfOhWqMStI91CRsJ_fj1tKZVRgIi1xY9Ct35f49VCjI +0 -0
- package/dist/ui/cajonzero-assets/blobs/SQMg9VR2DwDmaNXhA0FfkTNdWoomRqUlZzm7LdEem0o +0 -0
- package/dist/ui/cajonzero-assets/blobs/T7ltKgCfHRWDh8DvYWwjTLUm_jyyXGIin8YEQYezqRE +0 -0
- package/dist/ui/cajonzero-assets/blobs/Tm6iY1tjlBCxIFVkH6fQ6WSCGItCwgp1qhnV2MSmDAc +0 -0
- package/dist/ui/cajonzero-assets/blobs/TygomLARFBxhswYiAEi5onCeMIi6eInfdlt1GTPEzA8 +0 -0
- package/dist/ui/cajonzero-assets/blobs/V5w0v22x0_urNk-w77v-F_CTuT_K8ncnQd45-WM_lWM +0 -0
- package/dist/ui/cajonzero-assets/blobs/VE8cmDpuiYV41JTNf1-8p6baecUlhPX7BwCuiKjuNN0 +0 -0
- package/dist/ui/cajonzero-assets/blobs/Vv6pflLQz9Z06hMF0-3GOPKmEH8ryCECiT6Wnl5tlb8 +0 -0
- package/dist/ui/cajonzero-assets/blobs/WnbegyWLVz-LHMQgdlz-Rv3L8knTzkcPxUSGtPegEWE +0 -0
- package/dist/ui/cajonzero-assets/blobs/WpRk7YsCv_Ymkrq4efmQOJJMD2pgvveZeiRTXm_ovD4 +0 -0
- package/dist/ui/cajonzero-assets/blobs/XmPKwf7XjsDoYuNkjDQrWPzLIu1aTOYnby2bUmQChE4 +0 -0
- package/dist/ui/cajonzero-assets/blobs/Xr1Okz2DqOdp07Npx5uH0N3LUScFDdF1hGIPsEBQW3g +0 -0
- package/dist/ui/cajonzero-assets/blobs/Y3HX8Arsj45Iuy0qL7woY8qP5QF-W6pbOsNF6oos6zY +0 -0
- package/dist/ui/cajonzero-assets/blobs/Ze4mssXcrX1e7z185MAXCZRtMAtwB-zLj1GYyRcMU2c +0 -0
- package/dist/ui/cajonzero-assets/blobs/a0b1PSB2YTZGwTGrIhD8RDjboL-_etaKPh9XtBUNXfc +0 -0
- package/dist/ui/cajonzero-assets/blobs/aAphssqiPi93r7mAMudYFtFxRuGvLWKyikJifiacQEA +0 -0
- package/dist/ui/cajonzero-assets/blobs/an3K4TsulJYxsVVoj8S8kyM4MrGJkz1esWCXafdBu28 +0 -0
- package/dist/ui/cajonzero-assets/blobs/b9aYkFSPn7bQXejl_yFahA3JjD33jl2-tn0l0LJ0SIg +0 -0
- package/dist/ui/cajonzero-assets/blobs/bV82dxWlxRigqf6FVABNJp5vj9zABVeYHyMlEHwlHN4 +0 -0
- package/dist/ui/cajonzero-assets/blobs/bVlJLQq2KPX9d-_pggKAjN1lLNzGcDkAx8Ecd7ZZXtc +0 -0
- package/dist/ui/cajonzero-assets/blobs/dFZks4pYaRJ6kU-VDzQv6kIsFhOYZ43-wik950M_x1U +0 -0
- package/dist/ui/cajonzero-assets/blobs/e1ZzIyGdOZxAsKAHToSr1Rohek9p9knQoE5r6bssVjQ +0 -0
- package/dist/ui/cajonzero-assets/blobs/e4RaMqkk8wRFTc2RbHz6BQkIrjcmYTLnE0IBySs5wFs +0 -0
- package/dist/ui/cajonzero-assets/blobs/f3VtPxT0ASkPa5x-e-vX_99ONPxvK_TFPCq_uxrrwb8 +0 -0
- package/dist/ui/cajonzero-assets/blobs/f6IcOLssuXmeRXHvfv8HbsBXyUVjQIX1vC1PT0l4ygs +0 -0
- package/dist/ui/cajonzero-assets/blobs/fFzXwES0_SIA4gtPnY1rAjJRiZ8PnP7WewMOuDzQRiE +0 -0
- package/dist/ui/cajonzero-assets/blobs/fY_KWg63ZqAvBXvX0edrPGD_GevpTGdOeZkcd4ami-8 +0 -0
- package/dist/ui/cajonzero-assets/blobs/fw__JzWRTPb8TeUFb0yzX_RAw8HdngVnmkca_GGCwK8 +0 -0
- package/dist/ui/cajonzero-assets/blobs/fz8YT7RQVR-jpW4u1ERGHT2GO0AhgkR7nXfypKDLHKQ +0 -0
- package/dist/ui/cajonzero-assets/blobs/gHVEVf5jOoe2HepTjoZNvaPkpiFXyI-k-DGn_i7lBik +0 -0
- package/dist/ui/cajonzero-assets/blobs/glwjp5nxcyvdUtzLmX3LHoRAtUny01vIlzPyRWlar6U +0 -0
- package/dist/ui/cajonzero-assets/blobs/h4Zdd0HdCZR8aOa2FmRmBdxCLwkPDcSXAdEsUAHr0WA +0 -0
- package/dist/ui/cajonzero-assets/blobs/hH_d1ycJuEOUg5s2e78mRmVfgDMkmwgCljijPPNJWMw +0 -0
- package/dist/ui/cajonzero-assets/blobs/iKKTTHOTy9iBaaozmprN83iLh2W2baZfTXuLu6uaLIw +0 -0
- package/dist/ui/cajonzero-assets/blobs/jDW1gLMHdMU77AL4Gpu3OFkm4Z5XOGThqoM-NNx12DY +0 -0
- package/dist/ui/cajonzero-assets/blobs/jLETB0_-nLp_xpSomvdz2N82FA067ZjrydzMFDjfhkg +0 -0
- package/dist/ui/cajonzero-assets/blobs/j_VxLyyA8FBWp7kHniJSaxTb5A1PsoSRCgLG0Qwz6fY +0 -0
- package/dist/ui/cajonzero-assets/blobs/k6DpMny-A1lfQF9IS7s6tr5zdEt1OF8JD_9z-gB8BQk +0 -0
- package/dist/ui/cajonzero-assets/blobs/kO9_IinZ9d4EY2FmTEX6oMv2EN-sT8Xq8dcrUWt8nHA +0 -0
- package/dist/ui/cajonzero-assets/blobs/l2Z50N8XgMp2foRaY-qCcDoJWe-xd8W2Nztv6A4mxp0 +0 -0
- package/dist/ui/cajonzero-assets/blobs/lTD6g8p4M9v6m8li59Kmmunz2L-57QYc7zPFDZ-W-Es +0 -0
- package/dist/ui/cajonzero-assets/blobs/mG9tCWEoogpQXIYE8nxwLE8c_VOcFuO_XgnaldjJQ60 +0 -0
- package/dist/ui/cajonzero-assets/blobs/n1sBpQmApVlGP4i5qo5KJtx54zUpQsge54pcNzo-MDE +0 -0
- package/dist/ui/cajonzero-assets/blobs/nfL8PKk7NDrnhqTH1YMqdx_3KAzzeRfhVu9K5old5ZM +0 -0
- package/dist/ui/cajonzero-assets/blobs/nmKC5PJeNwzmF-Idb-Jl6Iuee4aCzwAFm50SjZOB8J0 +1 -0
- package/dist/ui/cajonzero-assets/blobs/ntt0GRn7ynGaqPL4sJqRls9E0GQaxE6IYLyw_qp-B9Q +0 -0
- package/dist/ui/cajonzero-assets/blobs/o0yyYt7q1aPpjzws0fy35amGvo_KZPHEnbTfUShpx3U +0 -0
- package/dist/ui/cajonzero-assets/blobs/oQQX0yM43YWL1vera6TSHhZthZgMnXNhIrGipFvG6No +0 -0
- package/dist/ui/cajonzero-assets/blobs/oShx_uIQ-4YZKR6uoZRYHL0lMeSyN1nSJfaAaSP2MiI +1 -0
- package/dist/ui/cajonzero-assets/blobs/owSnNxCwon5FLARj6_vN93kAouq8LDotGEwNFqRx92s +0 -0
- package/dist/ui/cajonzero-assets/blobs/p0hlunSNmKVR7psYDbGVbl2g55I_GklMquQVTtw_Hng +0 -0
- package/dist/ui/cajonzero-assets/blobs/p6ltFaLV93PxC96Tfnpcsd0vZezteR3krx7rTlvhNmQ +0 -0
- package/dist/ui/cajonzero-assets/blobs/paRPXEE1Gj4n2JnW1d-qQAAECA9fmA6rWwX6cx5XFhE +0 -0
- package/dist/ui/cajonzero-assets/blobs/qFAdwDi7V1l1dyrzd38MX7ncFpbDXCPnrp3-ojx7uiw +0 -0
- package/dist/ui/cajonzero-assets/blobs/qNXdY_ukcevLHz6PfB4YebcVKm5ymKkc4RmmNACt58U +1 -0
- package/dist/ui/cajonzero-assets/blobs/qkONdDiirNiCzAweq2r9YmPTM6sJo0kFnrzk-_6gpHc +0 -0
- package/dist/ui/cajonzero-assets/blobs/rE7gZfK-ViZf-NNWbddA9GiL8jqhZ5BZv5s6PlgoEEc +0 -0
- package/dist/ui/cajonzero-assets/blobs/rkXRGaG-CfvGeVCpnVMywGTvb-DH8H2YqpVJWSKXhdw +0 -0
- package/dist/ui/cajonzero-assets/blobs/sOgyrN2KX2usg51tbNNxBFrJ9iPPW0CKN91A9za09Tk +0 -0
- package/dist/ui/cajonzero-assets/blobs/tAHLZ9uvlsTjN5iAeXczO381B2OSNJ69O95M2YYfcN8 +0 -0
- package/dist/ui/cajonzero-assets/blobs/tsr6R4oV7j6XmTitibKMLHwONeTKJ-SZcP9pnBv4Ubk +0 -0
- package/dist/ui/cajonzero-assets/blobs/vS95Ll6sl63_jDkyvfifk2BTVyB5WOqjStVP_QYb_Go +0 -0
- package/dist/ui/cajonzero-assets/blobs/vlGDb_MDYEWqVbJgC3-f3A_SWm6JuN3ZTBKlmwoDW-o +0 -0
- package/dist/ui/cajonzero-assets/blobs/xfFBUN4QqGjaz3Jk20X5tqGfVP0n5pWFhCisMvNKcZw +0 -0
- package/dist/ui/cajonzero-assets/blobs/xiNu5A-wieB-673yUKGMq18e_Wty7auBZ5fkArWD-u4 +0 -0
- package/dist/ui/cajonzero-assets/blobs/xyo3QwTg87Hhx0oWLkGYnrY_gDqFDPgEXhjxweay1-k +0 -0
- package/dist/ui/cajonzero-assets/blobs/xyoDpJvOfUDsOythWBxubACAeEpJBFU6X4gD6UtWDcI +0 -0
- package/dist/ui/cajonzero-assets/blobs/y2jNDEAVWMql33MI7A9MetZoMzoYZ3OQkfpE_ttnZpA +0 -0
- package/dist/ui/cajonzero-assets/blobs/yP1TmmOwXInzjarE0CKhGb0wrgyP8mb6cBDktdlxSIU +0 -0
- package/dist/ui/cajonzero-assets/blobs/z7PzcCMU5mgfNHEC1sglsERnwrO5r_eMXeR6zSN78Os +0 -0
- package/dist/ui/cajonzero-assets/blobs/zBd-L4rx5mRaCLXMVzf1YNsKFxhABcx9AXlw8uEmpq8 +0 -0
- package/dist/ui/cajonzero-assets/blobs/zr-Gim06sJj1VyQIdDh1Kp0j8A4gfKoRjsQTHGdgcZQ +0 -0
- package/dist/ui/index.html +14 -0
- package/dist/ui/skins/chinese-doll.png +0 -0
- package/dist/ui/skins/christmas-girl.png +0 -0
- package/dist/ui/skins/cowboy.png +0 -0
- package/dist/ui/skins/explorer.png +0 -0
- package/dist/ui/skins/little-prince.png +0 -0
- package/dist/ui/skins/maid.png +0 -0
- package/dist/ui/skins/pilot.png +0 -0
- package/dist/ui/skins/pink-girl.png +0 -0
- package/package.json +94 -6
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Toby Lai
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,74 @@
|
|
|
1
|
-
#
|
|
1
|
+
# cajonzero
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Serverless(Cloudflare)的 BOX3 **仅 Play 端**引擎:内置账号系统,房间跑在
|
|
4
|
+
Durable Object 上,地图放在 OSS/CDN。
|
|
5
|
+
|
|
6
|
+
## 安装
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
npm install cajonzero
|
|
10
|
+
npx cj0 --help
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## 本地运行
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm install
|
|
17
|
+
npm run build # 构建大厅/后台
|
|
18
|
+
npm run demo # http://127.0.0.1:8787
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
打开页面后注册账号、选一张地图即可进入房间。
|
|
22
|
+
管理后台在 `/admin/login`,演示令牌为 `cajonzero-demo-admin-token`。
|
|
23
|
+
|
|
24
|
+
## 创建自己的服务
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
cj0 create my-server
|
|
28
|
+
cd my-server
|
|
29
|
+
npm install
|
|
30
|
+
npm run dev # 本地预览
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
部署前配置三项:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
npx wrangler kv namespace create CAJONZERO_KV # 把返回的 id 填进 wrangler.jsonc
|
|
37
|
+
npx wrangler secret put CAJONZERO_SESSION_SECRET # 会话签名密钥
|
|
38
|
+
npx wrangler secret put BOX_PLAY_ADMIN_TOKEN # 管理后台令牌
|
|
39
|
+
npm run deploy
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## 配置地图
|
|
43
|
+
|
|
44
|
+
地图不随 worker 上传。把解包后的 `.boxplay` 目录传到 OSS/S3/CDN,
|
|
45
|
+
再在 `cajonzero/maps.json` 中登记:
|
|
46
|
+
|
|
47
|
+
```json
|
|
48
|
+
{
|
|
49
|
+
"version": 1,
|
|
50
|
+
"maps": [
|
|
51
|
+
{
|
|
52
|
+
"slug": "race",
|
|
53
|
+
"root": "https://<你的 CDN>/box3/race/",
|
|
54
|
+
"worldId": "<世界 id>",
|
|
55
|
+
"name": "显示名",
|
|
56
|
+
"etag": "v1"
|
|
57
|
+
}
|
|
58
|
+
]
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
地图内容更新时记得提升 `etag`(否则会命中 KV 里的旧缓存)。
|
|
63
|
+
房间参数、地图拉取策略等在 `cajonzero/config.json` 中调整。
|
|
64
|
+
|
|
65
|
+
## 常用命令
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
cj0 serve [--port <port>] [--host <host>] # 本地启动
|
|
69
|
+
cj0 create <folder> # 生成部署项目
|
|
70
|
+
npm test # 运行测试
|
|
71
|
+
npm run ci:gates # 完整检查(类型/测试/构建)
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
更多细节见 [`docs/`](./docs/) 与 [`demo/`](./demo/README.md)。
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
package/dist/bin/cj0.js
ADDED
|
@@ -0,0 +1,477 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { mkdirSync, existsSync, statSync, writeFileSync, readdirSync, readFileSync } from 'fs';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import { fileURLToPath } from 'url';
|
|
5
|
+
|
|
6
|
+
// src/scaffold/templates.ts
|
|
7
|
+
var SCAFFOLD_ENTRY_PATH = "src/index.ts";
|
|
8
|
+
var SCAFFOLD_COMPATIBILITY_DATE = "2026-09-01";
|
|
9
|
+
var SCAFFOLD_KV_PLACEHOLDER_ID = "PLACEHOLDER_KV_ID";
|
|
10
|
+
var SCAFFOLD_ENTRY_CONTENT = [
|
|
11
|
+
'import config from "../cajonzero/config.json";',
|
|
12
|
+
'import maps from "../cajonzero/maps.json";',
|
|
13
|
+
"",
|
|
14
|
+
'import { serve } from "cajonzero/serve";',
|
|
15
|
+
"",
|
|
16
|
+
"export default serve({ config, maps });",
|
|
17
|
+
'export { Room } from "cajonzero";',
|
|
18
|
+
""
|
|
19
|
+
].join("\n");
|
|
20
|
+
var SCAFFOLD_CONFIG_CONTENT = `${JSON.stringify(
|
|
21
|
+
{
|
|
22
|
+
name: "<project-name>",
|
|
23
|
+
admin: { path: "/admin" },
|
|
24
|
+
room: { tickRate: 64, emptyGraceMs: 48e4 },
|
|
25
|
+
maps: {
|
|
26
|
+
cacheTtlSeconds: 86400,
|
|
27
|
+
maxDownloadBytes: 33554432,
|
|
28
|
+
concurrency: 8,
|
|
29
|
+
requestTimeoutMs: 15e3
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
null,
|
|
33
|
+
2
|
|
34
|
+
)}
|
|
35
|
+
`;
|
|
36
|
+
var SCAFFOLD_MAPS_CONTENT = `${JSON.stringify({ version: 1, maps: [] }, null, 2)}
|
|
37
|
+
`;
|
|
38
|
+
var SHIP_UI_SCRIPT = `node -e "const fs=require('node:fs'),p=require('node:path');fs.cpSync(p.join(p.dirname(require.resolve('cajonzero/package.json')),'dist','ui'),p.join('dist','ui'),{recursive:true,force:true})"`;
|
|
39
|
+
function packageJson(options) {
|
|
40
|
+
const manifest = {
|
|
41
|
+
name: options.packageName,
|
|
42
|
+
version: "0.0.0",
|
|
43
|
+
private: true,
|
|
44
|
+
type: "module",
|
|
45
|
+
scripts: {
|
|
46
|
+
dev: `${SHIP_UI_SCRIPT} && wrangler dev`,
|
|
47
|
+
build: `${SHIP_UI_SCRIPT} && wrangler deploy --dry-run`,
|
|
48
|
+
deploy: `${SHIP_UI_SCRIPT} && wrangler deploy`,
|
|
49
|
+
// `prepare` also runs after `npm install`, so a plain install leaves a
|
|
50
|
+
// ready-to-deploy project.
|
|
51
|
+
prepare: SHIP_UI_SCRIPT
|
|
52
|
+
},
|
|
53
|
+
dependencies: {
|
|
54
|
+
cajonzero: options.cajonzeroRange,
|
|
55
|
+
unstorage: options.unstorageRange
|
|
56
|
+
},
|
|
57
|
+
devDependencies: {
|
|
58
|
+
wrangler: options.wranglerRange
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
return `${JSON.stringify(manifest, null, 2)}
|
|
62
|
+
`;
|
|
63
|
+
}
|
|
64
|
+
function wranglerConfig(options) {
|
|
65
|
+
return [
|
|
66
|
+
"{",
|
|
67
|
+
" // cajonzero-created project \u2014 Cloudflare Workers config.",
|
|
68
|
+
" // `main` is the thin worker entry; wrangler bundles it (and cajonzero) on",
|
|
69
|
+
" // the fly, so there is no separate worker build step.",
|
|
70
|
+
' "$schema": "./node_modules/wrangler/config-schema.json",',
|
|
71
|
+
` "name": ${JSON.stringify(options.packageName)},`,
|
|
72
|
+
` "main": ${JSON.stringify(SCAFFOLD_ENTRY_PATH)},`,
|
|
73
|
+
` "compatibility_date": ${JSON.stringify(options.compatibilityDate)},`,
|
|
74
|
+
" // Deliberately NO `nodejs_compat`: cajonzero's worker path is Node-free.",
|
|
75
|
+
' "compatibility_flags": [],',
|
|
76
|
+
" // Static UI (play lobby + owner admin console) served by the worker.",
|
|
77
|
+
" // cajonzero ships the built assets into this directory.",
|
|
78
|
+
' "assets": {',
|
|
79
|
+
' "directory": "dist/ui",',
|
|
80
|
+
" // History routing: deep links (/play/x, /admin/bans) boot index.html.",
|
|
81
|
+
' "not_found_handling": "single-page-application",',
|
|
82
|
+
' "run_worker_first": ["/api/*", "/runtime/*"]',
|
|
83
|
+
" },",
|
|
84
|
+
" // Non-secret deployment label. Secrets are set with `wrangler secret put`:",
|
|
85
|
+
" // CAJONZERO_SESSION_SECRET, BOX_PLAY_ADMIN_TOKEN",
|
|
86
|
+
' "vars": {',
|
|
87
|
+
' "CAJONZERO_ENV": "development"',
|
|
88
|
+
" },",
|
|
89
|
+
' "kv_namespaces": [',
|
|
90
|
+
" {",
|
|
91
|
+
" // Player/account data + map-script KV + resolved map-seed cache.",
|
|
92
|
+
' "binding": "CAJONZERO_KV",',
|
|
93
|
+
" // Replace with `wrangler kv namespace create CAJONZERO_KV` output.",
|
|
94
|
+
` "id": ${JSON.stringify(SCAFFOLD_KV_PLACEHOLDER_ID)}`,
|
|
95
|
+
" }",
|
|
96
|
+
" ],",
|
|
97
|
+
' "durable_objects": {',
|
|
98
|
+
' "bindings": [',
|
|
99
|
+
" {",
|
|
100
|
+
" // Per-room actor namespace. `Room` is re-exported by the entry.",
|
|
101
|
+
' "name": "ROOMS",',
|
|
102
|
+
' "class_name": "Room"',
|
|
103
|
+
" }",
|
|
104
|
+
" ]",
|
|
105
|
+
" },",
|
|
106
|
+
' "migrations": [',
|
|
107
|
+
" {",
|
|
108
|
+
' "tag": "v1",',
|
|
109
|
+
' "new_sqlite_classes": ["Room"]',
|
|
110
|
+
" }",
|
|
111
|
+
" ]",
|
|
112
|
+
"}",
|
|
113
|
+
""
|
|
114
|
+
].join("\n");
|
|
115
|
+
}
|
|
116
|
+
function gitignore() {
|
|
117
|
+
return ["node_modules", "dist", ".wrangler", ".dev.vars", ""].join("\n");
|
|
118
|
+
}
|
|
119
|
+
function readme(options) {
|
|
120
|
+
return [
|
|
121
|
+
`# ${options.packageName}`,
|
|
122
|
+
"",
|
|
123
|
+
"A serverless (Cloudflare Workers) BOX3 **play** server, scaffolded by",
|
|
124
|
+
"[`cajonzero`](https://www.npmjs.com/package/cajonzero).",
|
|
125
|
+
"",
|
|
126
|
+
"This project contains **no engine source code** \u2014 configuration plus a short",
|
|
127
|
+
"worker entry that hands `cajonzero/config.json` and `cajonzero/maps.json` to the",
|
|
128
|
+
"runtime:",
|
|
129
|
+
"",
|
|
130
|
+
"```ts",
|
|
131
|
+
'import config from "../cajonzero/config.json";',
|
|
132
|
+
'import maps from "../cajonzero/maps.json";',
|
|
133
|
+
'import { serve } from "cajonzero/serve";',
|
|
134
|
+
"",
|
|
135
|
+
"export default serve({ config, maps });",
|
|
136
|
+
'export { Room } from "cajonzero";',
|
|
137
|
+
"```",
|
|
138
|
+
"",
|
|
139
|
+
"## Quick start",
|
|
140
|
+
"",
|
|
141
|
+
"```bash",
|
|
142
|
+
"npm install # also syncs cajonzero's prebuilt lobby/console into dist/ui",
|
|
143
|
+
"npm run dev # wrangler dev \u2192 http://localhost:8787",
|
|
144
|
+
"```",
|
|
145
|
+
"",
|
|
146
|
+
"`npm run build` validates the deploy by bundling the worker without",
|
|
147
|
+
"publishing (`wrangler deploy --dry-run`).",
|
|
148
|
+
"",
|
|
149
|
+
"## Required secrets",
|
|
150
|
+
"",
|
|
151
|
+
"Set both secrets with Wrangler (never commit them):",
|
|
152
|
+
"",
|
|
153
|
+
"```bash",
|
|
154
|
+
"npx wrangler secret put CAJONZERO_SESSION_SECRET # signs player session proofs",
|
|
155
|
+
"npx wrangler secret put BOX_PLAY_ADMIN_TOKEN # owner token for the admin API",
|
|
156
|
+
"```",
|
|
157
|
+
"",
|
|
158
|
+
"## Maps (object storage)",
|
|
159
|
+
"",
|
|
160
|
+
"Maps are **not** uploaded with the worker and are never unpacked at runtime.",
|
|
161
|
+
"Unpack the `.boxplay` yourself and upload the resulting directory to OSS/S3/CDN",
|
|
162
|
+
"with the archive layout preserved:",
|
|
163
|
+
"",
|
|
164
|
+
"```text",
|
|
165
|
+
"<root>/bundle.json",
|
|
166
|
+
"<root>/worlds/<worldId>/manifest.json",
|
|
167
|
+
"<root>/worlds/<worldId>/data/project-state.json",
|
|
168
|
+
"<root>/worlds/<worldId>/data/blobs/<cid>",
|
|
169
|
+
"```",
|
|
170
|
+
"",
|
|
171
|
+
"Then add an entry to `cajonzero/maps.json`:",
|
|
172
|
+
"",
|
|
173
|
+
"```json",
|
|
174
|
+
"{",
|
|
175
|
+
' "version": 1,',
|
|
176
|
+
' "maps": [',
|
|
177
|
+
" {",
|
|
178
|
+
' "slug": "omega",',
|
|
179
|
+
' "root": "https://cdn.example.com/cajonzero/omega/",',
|
|
180
|
+
' "worldId": "project-omega",',
|
|
181
|
+
' "name": "Omega City Reloaded",',
|
|
182
|
+
' "version": "1.0.4",',
|
|
183
|
+
' "etag": "v1.0.4"',
|
|
184
|
+
" }",
|
|
185
|
+
" ]",
|
|
186
|
+
"}",
|
|
187
|
+
"```",
|
|
188
|
+
"",
|
|
189
|
+
"- `root` must be the unpacked map directory and end with `/`.",
|
|
190
|
+
"- `etag` (or `version`) is the seed-cache revision: bump it whenever you",
|
|
191
|
+
" re-upload the map, otherwise the cached world stays stale.",
|
|
192
|
+
"- The bucket may be public-read; the server fetches it, so no CORS is needed",
|
|
193
|
+
" for gameplay. Enable CORS only if the browser loads assets from it.",
|
|
194
|
+
"",
|
|
195
|
+
"## Where things live",
|
|
196
|
+
"",
|
|
197
|
+
"- **Play lobby** \u2014 the worker serves the lobby at `/`.",
|
|
198
|
+
"- **Admin console** \u2014 at `/admin` (sign in with `BOX_PLAY_ADMIN_TOKEN`) for",
|
|
199
|
+
" player bans and runtime settings; its JSON API is under `/api/admin/*`.",
|
|
200
|
+
"- **Map catalog** \u2014 `GET /api/maps` returns the entries from `maps.json`.",
|
|
201
|
+
"",
|
|
202
|
+
"## Deploy",
|
|
203
|
+
"",
|
|
204
|
+
"```bash",
|
|
205
|
+
"npm run deploy # wrangler deploy",
|
|
206
|
+
"```",
|
|
207
|
+
""
|
|
208
|
+
].join("\n");
|
|
209
|
+
}
|
|
210
|
+
function buildScaffoldFiles(options) {
|
|
211
|
+
return [
|
|
212
|
+
{ path: "package.json", content: packageJson(options) },
|
|
213
|
+
{ path: "wrangler.jsonc", content: wranglerConfig(options) },
|
|
214
|
+
{ path: SCAFFOLD_ENTRY_PATH, content: SCAFFOLD_ENTRY_CONTENT },
|
|
215
|
+
{
|
|
216
|
+
path: "cajonzero/config.json",
|
|
217
|
+
content: SCAFFOLD_CONFIG_CONTENT.replace("<project-name>", options.packageName)
|
|
218
|
+
},
|
|
219
|
+
{ path: "cajonzero/maps.json", content: SCAFFOLD_MAPS_CONTENT },
|
|
220
|
+
{ path: ".gitignore", content: gitignore() },
|
|
221
|
+
{ path: "README.md", content: readme(options) }
|
|
222
|
+
];
|
|
223
|
+
}
|
|
224
|
+
var CAJONZERO_RANGE_PREFIX = "^";
|
|
225
|
+
var FALLBACK_WRANGLER_RANGE = "^4.151.1";
|
|
226
|
+
var FALLBACK_UNSTORAGE_RANGE = "^1.17.6";
|
|
227
|
+
var PACKAGE_JSON_URL = new URL("../../package.json", import.meta.url);
|
|
228
|
+
var ScaffoldError = class extends Error {
|
|
229
|
+
code;
|
|
230
|
+
constructor(code, message) {
|
|
231
|
+
super(message);
|
|
232
|
+
this.name = "ScaffoldError";
|
|
233
|
+
this.code = code;
|
|
234
|
+
}
|
|
235
|
+
};
|
|
236
|
+
function readCajonzeroPackage(manifestPath) {
|
|
237
|
+
const filePath = fileURLToPath(PACKAGE_JSON_URL);
|
|
238
|
+
const raw = readFileSync(filePath, "utf8");
|
|
239
|
+
const parsed = JSON.parse(raw);
|
|
240
|
+
const version = typeof parsed.version === "string" && parsed.version.length > 0 ? parsed.version : "0.0.0";
|
|
241
|
+
const wrangler = parsed.devDependencies?.["wrangler"];
|
|
242
|
+
const wranglerRange = typeof wrangler === "string" && wrangler.length > 0 ? wrangler : FALLBACK_WRANGLER_RANGE;
|
|
243
|
+
const unstorage = parsed.dependencies?.["unstorage"];
|
|
244
|
+
const unstorageRange = typeof unstorage === "string" && unstorage.length > 0 ? unstorage : FALLBACK_UNSTORAGE_RANGE;
|
|
245
|
+
return { version, wranglerRange, unstorageRange };
|
|
246
|
+
}
|
|
247
|
+
function toPackageName(folder) {
|
|
248
|
+
const base = path.basename(folder);
|
|
249
|
+
const slug = base.toLowerCase().replace(/[^a-z0-9._-]+/g, "-").replace(/^[-._]+/, "").replace(/[-._]+$/, "");
|
|
250
|
+
return slug.length > 0 ? slug : "cajonzero-app";
|
|
251
|
+
}
|
|
252
|
+
function isNonEmptyDirectory(dir) {
|
|
253
|
+
if (!existsSync(dir)) return false;
|
|
254
|
+
if (!statSync(dir).isDirectory()) return false;
|
|
255
|
+
return readdirSync(dir).length > 0;
|
|
256
|
+
}
|
|
257
|
+
function createProject(folder, options = {}) {
|
|
258
|
+
const name = typeof folder === "string" ? folder.trim() : "";
|
|
259
|
+
if (name.length === 0) {
|
|
260
|
+
throw new ScaffoldError("INVALID_TARGET", "create requires a target folder");
|
|
261
|
+
}
|
|
262
|
+
const cwd = options.cwd ?? process.cwd();
|
|
263
|
+
const target = path.resolve(cwd, name);
|
|
264
|
+
if (existsSync(target) && !statSync(target).isDirectory()) {
|
|
265
|
+
throw new ScaffoldError("INVALID_TARGET", `target exists and is not a directory: ${target}`);
|
|
266
|
+
}
|
|
267
|
+
if (isNonEmptyDirectory(target)) {
|
|
268
|
+
throw new ScaffoldError(
|
|
269
|
+
"TARGET_NOT_EMPTY",
|
|
270
|
+
`target directory already exists and is not empty: ${target} (refusing to overwrite)`
|
|
271
|
+
);
|
|
272
|
+
}
|
|
273
|
+
const manifest = options.version !== void 0 ? void 0 : readCajonzeroPackage();
|
|
274
|
+
const version = options.version ?? manifest?.version ?? "0.0.0";
|
|
275
|
+
const wranglerRange = options.wranglerRange ?? manifest?.wranglerRange ?? FALLBACK_WRANGLER_RANGE;
|
|
276
|
+
const unstorageRange = options.unstorageRange ?? manifest?.unstorageRange ?? FALLBACK_UNSTORAGE_RANGE;
|
|
277
|
+
const files = buildScaffoldFiles({
|
|
278
|
+
packageName: toPackageName(target),
|
|
279
|
+
cajonzeroRange: `${CAJONZERO_RANGE_PREFIX}${version}`,
|
|
280
|
+
unstorageRange,
|
|
281
|
+
wranglerRange,
|
|
282
|
+
compatibilityDate: options.compatibilityDate ?? SCAFFOLD_COMPATIBILITY_DATE
|
|
283
|
+
});
|
|
284
|
+
mkdirSync(target, { recursive: true });
|
|
285
|
+
for (const file of files) {
|
|
286
|
+
const fullPath = path.join(target, file.path);
|
|
287
|
+
mkdirSync(path.dirname(fullPath), { recursive: true });
|
|
288
|
+
writeFileSync(fullPath, file.content, "utf8");
|
|
289
|
+
}
|
|
290
|
+
return { target, files: files.map((file) => file.path) };
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
// src/bin/cj0.ts
|
|
294
|
+
var USAGE = `cj0 \u2014 serverless (Cloudflare) play-only BOX3 engine
|
|
295
|
+
|
|
296
|
+
Usage:
|
|
297
|
+
cj0 <command> [options]
|
|
298
|
+
|
|
299
|
+
Commands:
|
|
300
|
+
create <folder> Scaffold a deployable project
|
|
301
|
+
serve [--port <port>] [--host <host>] Run the cajonzero server locally (workerd)
|
|
302
|
+
|
|
303
|
+
Serve options:
|
|
304
|
+
--port <port> Listener port (default: 8787)
|
|
305
|
+
--host <host> Listener host (default: 127.0.0.1)
|
|
306
|
+
--config <file> Wrangler config (default: wrangler.jsonc)
|
|
307
|
+
-h, --help Show this help
|
|
308
|
+
|
|
309
|
+
Maps: unpack the .boxplay, upload the directory to OSS/CDN, and list its root
|
|
310
|
+
in cajonzero/maps.json. The CLI does not import map archives.
|
|
311
|
+
`;
|
|
312
|
+
var DEFAULT_SERVE_PORT = 8787;
|
|
313
|
+
var DEFAULT_SERVE_HOST = "127.0.0.1";
|
|
314
|
+
var DEFAULT_CONFIG = "wrangler.jsonc";
|
|
315
|
+
var LOCAL_DEV_SECRETS = ["CAJONZERO_SESSION_SECRET", "BOX_PLAY_ADMIN_TOKEN"];
|
|
316
|
+
function localDevVars() {
|
|
317
|
+
const vars = {};
|
|
318
|
+
for (const name of LOCAL_DEV_SECRETS) {
|
|
319
|
+
const value = process.env[name];
|
|
320
|
+
if (value !== void 0 && value.length > 0) {
|
|
321
|
+
vars[name] = value;
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
return Object.keys(vars).length > 0 ? vars : void 0;
|
|
325
|
+
}
|
|
326
|
+
function printUsage() {
|
|
327
|
+
process.stdout.write(USAGE);
|
|
328
|
+
}
|
|
329
|
+
function fail(message) {
|
|
330
|
+
process.stderr.write(`cajonzero: ${message}
|
|
331
|
+
`);
|
|
332
|
+
process.exitCode = 1;
|
|
333
|
+
}
|
|
334
|
+
function errorLabel(error) {
|
|
335
|
+
if (error instanceof ScaffoldError) {
|
|
336
|
+
return `${error.code}: ${error.message}`;
|
|
337
|
+
}
|
|
338
|
+
return error instanceof Error ? error.message : String(error);
|
|
339
|
+
}
|
|
340
|
+
function runCreate(args) {
|
|
341
|
+
const [folder] = args;
|
|
342
|
+
if (folder === void 0) {
|
|
343
|
+
fail("create requires: cj0 create <folder>");
|
|
344
|
+
return;
|
|
345
|
+
}
|
|
346
|
+
const result = createProject(folder);
|
|
347
|
+
process.stdout.write(
|
|
348
|
+
`created project in ${result.target} (${result.files.length} files)
|
|
349
|
+
${result.files.join(", ")}
|
|
350
|
+
next: cd ${folder} && npm install && npm run dev
|
|
351
|
+
`
|
|
352
|
+
);
|
|
353
|
+
}
|
|
354
|
+
function readFlagValue(args, index, flag) {
|
|
355
|
+
const inline = args[index];
|
|
356
|
+
if (inline !== void 0 && inline.startsWith(`${flag}=`)) {
|
|
357
|
+
return inline.slice(flag.length + 1);
|
|
358
|
+
}
|
|
359
|
+
const value = args[index + 1];
|
|
360
|
+
if (value === void 0 || value.startsWith("-")) {
|
|
361
|
+
throw new Error(`${flag} requires a value`);
|
|
362
|
+
}
|
|
363
|
+
return value;
|
|
364
|
+
}
|
|
365
|
+
function parseServeFlags(args) {
|
|
366
|
+
let port = DEFAULT_SERVE_PORT;
|
|
367
|
+
let host = DEFAULT_SERVE_HOST;
|
|
368
|
+
let config = DEFAULT_CONFIG;
|
|
369
|
+
for (let i = 0; i < args.length; i += 1) {
|
|
370
|
+
const arg = args[i];
|
|
371
|
+
if (arg === void 0) continue;
|
|
372
|
+
if (arg === "--port" || arg.startsWith("--port=")) {
|
|
373
|
+
const raw = readFlagValue(args, i, "--port");
|
|
374
|
+
const parsed = Number(raw);
|
|
375
|
+
if (!Number.isInteger(parsed) || parsed < 0 || parsed > 65535) {
|
|
376
|
+
throw new Error(`--port must be an integer in [0, 65535] (got "${raw}")`);
|
|
377
|
+
}
|
|
378
|
+
port = parsed;
|
|
379
|
+
if (!arg.includes("=")) i += 1;
|
|
380
|
+
} else if (arg === "--host" || arg.startsWith("--host=")) {
|
|
381
|
+
host = readFlagValue(args, i, "--host");
|
|
382
|
+
if (!arg.includes("=")) i += 1;
|
|
383
|
+
} else if (arg === "--config" || arg.startsWith("--config=")) {
|
|
384
|
+
config = readFlagValue(args, i, "--config");
|
|
385
|
+
if (!arg.includes("=")) i += 1;
|
|
386
|
+
} else {
|
|
387
|
+
throw new Error(`unexpected serve option "${arg}"`);
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
return { port, host, config };
|
|
391
|
+
}
|
|
392
|
+
async function runServe(args) {
|
|
393
|
+
const flags = parseServeFlags(args);
|
|
394
|
+
const { unstable_dev, unstable_readConfig } = await import('wrangler');
|
|
395
|
+
const config = unstable_readConfig({ config: flags.config });
|
|
396
|
+
const entry = config.main;
|
|
397
|
+
if (entry === void 0 || entry.length === 0) {
|
|
398
|
+
throw new Error(`no worker entry ("main") found in ${flags.config}`);
|
|
399
|
+
}
|
|
400
|
+
const assetsDir = config.assets?.directory;
|
|
401
|
+
if (typeof assetsDir === "string" && assetsDir.length > 0) {
|
|
402
|
+
const configDir = path.dirname(path.resolve(process.cwd(), flags.config));
|
|
403
|
+
mkdirSync(path.resolve(configDir, assetsDir), { recursive: true });
|
|
404
|
+
}
|
|
405
|
+
const secrets = localDevVars();
|
|
406
|
+
const worker = await unstable_dev(entry, {
|
|
407
|
+
config: flags.config,
|
|
408
|
+
ip: flags.host,
|
|
409
|
+
port: flags.port,
|
|
410
|
+
local: true,
|
|
411
|
+
logLevel: "info",
|
|
412
|
+
// Inject local-dev secrets (from the environment) on top of the config
|
|
413
|
+
// `vars` so auth/session work locally without `wrangler secret put`.
|
|
414
|
+
...secrets !== void 0 ? { vars: { ...config.vars ?? {}, ...secrets } } : {},
|
|
415
|
+
experimental: {
|
|
416
|
+
disableExperimentalWarning: true,
|
|
417
|
+
disableDevRegistry: true,
|
|
418
|
+
showInteractiveDevSession: false
|
|
419
|
+
}
|
|
420
|
+
});
|
|
421
|
+
process.stdout.write(
|
|
422
|
+
`cj0 serve listening on http://${worker.address}:${worker.port}
|
|
423
|
+
(workerd via wrangler dev \xB7 config ${flags.config} \xB7 DO/KV/assets bound)
|
|
424
|
+
` + (secrets !== void 0 ? ` (local dev secrets injected: ${Object.keys(secrets).join(", ")})
|
|
425
|
+
` : "")
|
|
426
|
+
);
|
|
427
|
+
let stopping = false;
|
|
428
|
+
const shutdown = async (signal) => {
|
|
429
|
+
if (stopping) return;
|
|
430
|
+
stopping = true;
|
|
431
|
+
process.stdout.write(`
|
|
432
|
+
cajonzero: received ${signal}, shutting down
|
|
433
|
+
`);
|
|
434
|
+
try {
|
|
435
|
+
await worker.stop();
|
|
436
|
+
} finally {
|
|
437
|
+
process.exit(0);
|
|
438
|
+
}
|
|
439
|
+
};
|
|
440
|
+
process.on("SIGINT", () => {
|
|
441
|
+
void shutdown("SIGINT");
|
|
442
|
+
});
|
|
443
|
+
process.on("SIGTERM", () => {
|
|
444
|
+
void shutdown("SIGTERM");
|
|
445
|
+
});
|
|
446
|
+
await worker.waitUntilExit();
|
|
447
|
+
}
|
|
448
|
+
async function main(argv) {
|
|
449
|
+
const [command, ...rest] = argv;
|
|
450
|
+
if (command === void 0 || command === "--help" || command === "-h" || command === "help") {
|
|
451
|
+
printUsage();
|
|
452
|
+
return;
|
|
453
|
+
}
|
|
454
|
+
try {
|
|
455
|
+
switch (command) {
|
|
456
|
+
case "serve":
|
|
457
|
+
await runServe(rest);
|
|
458
|
+
return;
|
|
459
|
+
case "create":
|
|
460
|
+
runCreate(rest);
|
|
461
|
+
return;
|
|
462
|
+
default:
|
|
463
|
+
process.stderr.write(`cajonzero: unknown command "${command}"
|
|
464
|
+
|
|
465
|
+
`);
|
|
466
|
+
printUsage();
|
|
467
|
+
process.exitCode = 1;
|
|
468
|
+
}
|
|
469
|
+
} catch (error) {
|
|
470
|
+
fail(errorLabel(error));
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
main(process.argv.slice(2)).catch((error) => {
|
|
474
|
+
fail(errorLabel(error));
|
|
475
|
+
});
|
|
476
|
+
//# sourceMappingURL=cj0.js.map
|
|
477
|
+
//# sourceMappingURL=cj0.js.map
|