@dylanpiercey/work 0.1.0 → 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 +45 -5
- package/bin/work.mjs +449 -10
- package/dist/_BO3_WJb5.js +169 -0
- package/dist/{_Bq7to522.js → _CzOrFOdN.js} +527 -56
- package/dist/_DiOv9AKj.js +2 -0
- package/dist/index.mjs +8916 -7891
- package/dist/public/assets/{_Dytf99zx.js → _3hcTpTUc.js} +1 -1
- package/dist/public/assets/_3hcTpTUc.js.br +0 -0
- package/dist/public/assets/_88jVvZ6C.js +1 -0
- package/dist/public/assets/{_DrIgZJzN.js → _B0FtZL3L.js} +1 -1
- package/dist/public/assets/_B0FtZL3L.js.br +0 -0
- package/dist/public/assets/{_C0_s45qg.js → _B0rj5kOY.js} +1 -1
- package/dist/public/assets/_B0rj5kOY.js.br +0 -0
- package/dist/public/assets/{_BNW5Jiec.js → _B3aw0q8p.js} +1 -1
- package/dist/public/assets/_B3aw0q8p.js.br +0 -0
- package/dist/public/assets/{_Bhx319Hi.js → _B42XfAog.js} +1 -1
- package/dist/public/assets/_B42XfAog.js.br +0 -0
- package/dist/public/assets/_B5Ih3Lwt.js +1 -0
- package/dist/public/assets/_B6jh-_o_.js +1 -0
- package/dist/public/assets/_B8FHVXDZ.js +1 -0
- package/dist/public/assets/_BBJYNk03.js +1 -0
- package/dist/public/assets/{_D4q8XSMI.js → _BBk5_vEh.js} +1 -1
- package/dist/public/assets/_BBk5_vEh.js.br +0 -0
- package/dist/public/assets/_BCS_gQxR.js +15 -0
- package/dist/public/assets/_BCS_gQxR.js.br +0 -0
- package/dist/public/assets/{_BvXp6HpX.js → _BDBxSbjY.js} +1 -1
- package/dist/public/assets/_BDBxSbjY.js.br +0 -0
- package/dist/public/assets/_BDkqB224.js +1 -0
- package/dist/public/assets/{_SGDxiwE1.js → _BEtl4C9q.js} +1 -1
- package/dist/public/assets/_BEtl4C9q.js.br +0 -0
- package/dist/public/assets/{_DDl8KSWJ.js → _BJZwk-Pf.js} +1 -1
- package/dist/public/assets/_BJZwk-Pf.js.br +0 -0
- package/dist/public/assets/{_CpjSCB1I.js → _BM8qop28.js} +1 -1
- package/dist/public/assets/_BM8qop28.js.br +0 -0
- package/dist/public/assets/_BNL2e5az.js +1 -0
- package/dist/public/assets/{_CEXHZd73.js → _BODl5Jdc.js} +1 -1
- package/dist/public/assets/_BODl5Jdc.js.br +0 -0
- package/dist/public/assets/{_De7P3jUH.js → _BOe3voZI.js} +1 -1
- package/dist/public/assets/_BOe3voZI.js.br +0 -0
- package/dist/public/assets/{_eoa1EOU-.js → _BPW-OoaM.js} +1 -1
- package/dist/public/assets/_BPW-OoaM.js.br +0 -0
- package/dist/public/assets/{_BE_Jyvqd.js → _BSHUa-H0.js} +1 -1
- package/dist/public/assets/_BSHUa-H0.js.br +0 -0
- package/dist/public/assets/_BTXURtlK.js +1 -0
- package/dist/public/assets/{_Bp8-V8yl.js → _BU4lH-F3.js} +1 -1
- package/dist/public/assets/_BU4lH-F3.js.br +0 -0
- package/dist/public/assets/{_wcshV0sZ.js → _BVGSrb9C.js} +1 -1
- package/dist/public/assets/_BVGSrb9C.js.br +0 -0
- package/dist/public/assets/{_CTINBWaG.js → _BXyDScMX.js} +1 -1
- package/dist/public/assets/_BXyDScMX.js.br +0 -0
- package/dist/public/assets/{_Bm4SHrNp.js → _BZXtyNwD.js} +1 -1
- package/dist/public/assets/_BZXtyNwD.js.br +0 -0
- package/dist/public/assets/{_DfI982PI.js → _B_iUZxSk.js} +1 -1
- package/dist/public/assets/_B_iUZxSk.js.br +0 -0
- package/dist/public/assets/_B_klvcQs.js +1 -0
- package/dist/public/assets/{_CHuLFr1f.js → _BaNsw5pr.js} +1 -1
- package/dist/public/assets/_BaNsw5pr.js.br +0 -0
- package/dist/public/assets/_BbPq34k8.js +1 -0
- package/dist/public/assets/{_CAkPJLeF.js → _BfDaM2KU.js} +1 -1
- package/dist/public/assets/{_CAkPJLeF.js.br → _BfDaM2KU.js.br} +0 -0
- package/dist/public/assets/_Bk1naXp4.js +1 -0
- package/dist/public/assets/{_BOGkzMx9.js → _BkNKadGd.js} +1 -1
- package/dist/public/assets/_BkNKadGd.js.br +0 -0
- package/dist/public/assets/_BkztnqUW.js +1 -0
- package/dist/public/assets/_BkztnqUW.js.br +0 -0
- package/dist/public/assets/_BlNBDTvP.js +1 -0
- package/dist/public/assets/_BlNBDTvP.js.br +0 -0
- package/dist/public/assets/_BlUmx1wN.js +1 -0
- package/dist/public/assets/_Ble8b9gd.js +1 -0
- package/dist/public/assets/{_BDa-iwuj.js → _BpEvAl9E.js} +1 -1
- package/dist/public/assets/_BpEvAl9E.js.br +0 -0
- package/dist/public/assets/_Bqyvdrqf.js +1 -0
- package/dist/public/assets/_BsA2bpua.js +1 -0
- package/dist/public/assets/_BsA2bpua.js.br +0 -0
- package/dist/public/assets/_BsAVia13.js +1 -0
- package/dist/public/assets/_BtxLmMRq.js +1 -0
- package/dist/public/assets/{_ClldMY37.js → _Byfemjjt.js} +1 -1
- package/dist/public/assets/_Byfemjjt.js.br +0 -0
- package/dist/public/assets/{_MCwIJAuJ.js → _Bz94qqXL.js} +1 -1
- package/dist/public/assets/_Bz94qqXL.js.br +0 -0
- package/dist/public/assets/_C-HIZYIZ.js +1 -0
- package/dist/public/assets/{_D4quFMVQ.js → _C-UGjoFi.js} +1 -1
- package/dist/public/assets/_C-UGjoFi.js.br +0 -0
- package/dist/public/assets/{_wXDh-Z2N.js → _C-jXvDAe.js} +1 -1
- package/dist/public/assets/_C-jXvDAe.js.br +0 -0
- package/dist/public/assets/{_Ct3RF80L.js → _C2b1kmvc.js} +1 -1
- package/dist/public/assets/_C2b1kmvc.js.br +0 -0
- package/dist/public/assets/{_CIb7xw_1.js → _C3PIXMJF.js} +1 -1
- package/dist/public/assets/_C3PIXMJF.js.br +0 -0
- package/dist/public/assets/_C6eXJBpX.js +1 -0
- package/dist/public/assets/{_C654p96Z.js → _C7Xd05b1.js} +1 -1
- package/dist/public/assets/_C7Xd05b1.js.br +0 -0
- package/dist/public/assets/_C8jPP8tm.js +1 -0
- package/dist/public/assets/{_CamWDaoG.js → _CB9BGKKP.js} +1 -1
- package/dist/public/assets/_CB9BGKKP.js.br +0 -0
- package/dist/public/assets/{_bcsuBP7T.js → _CD44YUtO.js} +1 -1
- package/dist/public/assets/_CD44YUtO.js.br +0 -0
- package/dist/public/assets/{_D6kktUFn.js → _CEXagH_p.js} +1 -1
- package/dist/public/assets/_CEXagH_p.js.br +0 -0
- package/dist/public/assets/_CFOiLJdu.js +1 -0
- package/dist/public/assets/_CFOiLJdu.js.br +0 -0
- package/dist/public/assets/{_D1uRW1qz.js → _CGrClLsS.js} +1 -1
- package/dist/public/assets/_CGrClLsS.js.br +0 -0
- package/dist/public/assets/_CHJuzFIS.js +1 -0
- package/dist/public/assets/{_DC-78WeM.js → _CJ7DGNLC.js} +1 -1
- package/dist/public/assets/_CJ7DGNLC.js.br +0 -0
- package/dist/public/assets/_CJG7LF4o.js +1 -0
- package/dist/public/assets/_CK0tdQ6M.js +1591 -0
- package/dist/public/assets/_CK0tdQ6M.js.br +0 -0
- package/dist/public/assets/{_CMSBfO6u.js → _CKcab_6c.js} +1 -1
- package/dist/public/assets/_CKcab_6c.js.br +0 -0
- package/dist/public/assets/{_8G2Mv7jG.js → _CKpSd2DN.js} +1 -1
- package/dist/public/assets/_CKpSd2DN.js.br +0 -0
- package/dist/public/assets/{_zSAfqXcm.js → _CKy2HduV.js} +1 -1
- package/dist/public/assets/_CKy2HduV.js.br +0 -0
- package/dist/public/assets/{_BUvqweu0.js → _CLikwAg5.js} +1 -1
- package/dist/public/assets/_CLikwAg5.js.br +0 -0
- package/dist/public/assets/{_CxAPL49a.js → _CM-AIl7T.js} +1 -1
- package/dist/public/assets/_CM-AIl7T.js.br +0 -0
- package/dist/public/assets/_CMwrJ1ju.js +1 -0
- package/dist/public/assets/_CMwrJ1ju.js.br +0 -0
- package/dist/public/assets/_CQG-EbMi.js +1 -0
- package/dist/public/assets/_CUl36Gcx.js +1 -0
- package/dist/public/assets/{_BwP07uVS.js → _CUq2djIT.js} +1 -1
- package/dist/public/assets/_CUq2djIT.js.br +0 -0
- package/dist/public/assets/{_DFWOMF-B.js → _CWSGdqC2.js} +1 -1
- package/dist/public/assets/_CWSGdqC2.js.br +0 -0
- package/dist/public/assets/_CXK3AUqn.js +1 -0
- package/dist/public/assets/{_d5u7EI97.js → _CYYRiJuo.js} +1 -1
- package/dist/public/assets/_CYYRiJuo.js.br +0 -0
- package/dist/public/assets/_CYr8GcJI.js +1 -0
- package/dist/public/assets/{_8dvK2NDJ.js → _CaFhYr8X.js} +1 -1
- package/dist/public/assets/_CaFhYr8X.js.br +0 -0
- package/dist/public/assets/_CbzGfu_I.js +1 -0
- package/dist/public/assets/{_CZ_OWtIT.js → _Cd85Xtd1.js} +1 -1
- package/dist/public/assets/_Cd85Xtd1.js.br +0 -0
- package/dist/public/assets/_Ch-bwiFD.js +1 -0
- package/dist/public/assets/_ClGAsZdo.js +1 -0
- package/dist/public/assets/_ClGAsZdo.js.br +0 -0
- package/dist/public/assets/_ClhDmYWO.js +1 -0
- package/dist/public/assets/_ClhDmYWO.js.br +0 -0
- package/dist/public/assets/{_9kX9D09B.js → _Cm85V2m3.js} +1 -1
- package/dist/public/assets/_Cm85V2m3.js.br +0 -0
- package/dist/public/assets/_Cp4ZjGeg.js +1 -0
- package/dist/public/assets/{_C_37_B6u.js → _CsRnEvC3.js} +1 -1
- package/dist/public/assets/_CsRnEvC3.js.br +0 -0
- package/dist/public/assets/_CtFo1511.js +1 -0
- package/dist/public/assets/{_DcMIlvz-.js → _CtIpOiCk.js} +1 -1
- package/dist/public/assets/_CtIpOiCk.js.br +0 -0
- package/dist/public/assets/{_D4rOX-Fa.js → _CwOgQx7H.js} +1 -1
- package/dist/public/assets/_CwOgQx7H.js.br +0 -0
- package/dist/public/assets/_CwtVecVY.js +1 -0
- package/dist/public/assets/_Cxuln-KJ.js +1 -0
- package/dist/public/assets/_CyYNC4Ow.js +1 -0
- package/dist/public/assets/{_Dd6X3e7w.js → _Cy_g0woP.js} +1 -1
- package/dist/public/assets/_Cy_g0woP.js.br +0 -0
- package/dist/public/assets/{_COcePo2y.js → _CzDRlITT.js} +1 -1
- package/dist/public/assets/_CzDRlITT.js.br +0 -0
- package/dist/public/assets/_Czq9fyjZ.js +1 -0
- package/dist/public/assets/{_B582D2rg.js → _D1Rh4MKD.js} +1 -1
- package/dist/public/assets/_D2edy8B-.js +1 -0
- package/dist/public/assets/_D2edy8B-.js.br +0 -0
- package/dist/public/assets/_D2pdXUO3.js +1 -0
- package/dist/public/assets/_D4M5BFEU.js +1 -0
- package/dist/public/assets/{_D0aoEFRx.js → _D749nUfQ.js} +1 -1
- package/dist/public/assets/_D749nUfQ.js.br +0 -0
- package/dist/public/assets/_D7mcWce0.js +2 -0
- package/dist/public/assets/_D7mcWce0.js.br +0 -0
- package/dist/public/assets/{_BpoeUr5j.js → _D81sIY4I.js} +1 -1
- package/dist/public/assets/_D81sIY4I.js.br +0 -0
- package/dist/public/assets/{_D9sS4J_w.js → _D8Opg0DA.js} +1 -1
- package/dist/public/assets/_D8Opg0DA.js.br +0 -0
- package/dist/public/assets/{_B7GwDeKK.js → _DCJrZQ6J.js} +1 -1
- package/dist/public/assets/_DEPHQNx4.js +1 -0
- package/dist/public/assets/_DEtYVOe1.js +1 -0
- package/dist/public/assets/_DJ4gN7dQ.js +1 -0
- package/dist/public/assets/_DJ9NEjwG.js +1 -0
- package/dist/public/assets/{_xyw_DS5P.js → _DJUeUZKF.js} +1 -1
- package/dist/public/assets/_DJUeUZKF.js.br +0 -0
- package/dist/public/assets/_DLZswhbS.js +1 -0
- package/dist/public/assets/{_BywcP-As.js → _DMEtxMrc.js} +1 -1
- package/dist/public/assets/_DMEtxMrc.js.br +0 -0
- package/dist/public/assets/{_DqhphdU4.js → _DOr6ubI-.js} +1 -1
- package/dist/public/assets/_DOr6ubI-.js.br +0 -0
- package/dist/public/assets/{_ch_yXAap.js → _DQu5M2GV.js} +1 -1
- package/dist/public/assets/_DQu5M2GV.js.br +0 -0
- package/dist/public/assets/_DUvup9ew.js +1 -0
- package/dist/public/assets/{_CEJUcePr.js → _DWrhUk5T.js} +1 -1
- package/dist/public/assets/_DWrhUk5T.js.br +0 -0
- package/dist/public/assets/{_Bv3qNE1b.js → _DXOx4zKx.js} +1 -1
- package/dist/public/assets/_D_1b7pob.js +1 -0
- package/dist/public/assets/_Daap2skI.js +1 -0
- package/dist/public/assets/{_CUXajOKj.js → _DcktT8yN.js} +1 -1
- package/dist/public/assets/_DcktT8yN.js.br +0 -0
- package/dist/public/assets/{_D2un443j.js → _Ddc9Y9a_.js} +1 -1
- package/dist/public/assets/_Ddc9Y9a_.js.br +0 -0
- package/dist/public/assets/{_BBWaxDkO.js → _Dfjlzo9W.js} +1 -1
- package/dist/public/assets/_Dfjlzo9W.js.br +0 -0
- package/dist/public/assets/_Dh30YzVM.js +1 -0
- package/dist/public/assets/_DhohfuPc.js +1 -0
- package/dist/public/assets/_DjQz8h-q.js +1 -0
- package/dist/public/assets/_DjX1BGKn.js +1 -0
- package/dist/public/assets/_DjiaxzEs.js +1 -0
- package/dist/public/assets/_Dkg-QEnz.js +1 -0
- package/dist/public/assets/{_Bx1CW-sF.js → _Dl46-33v.js} +1 -1
- package/dist/public/assets/_Dl46-33v.js.br +0 -0
- package/dist/public/assets/_DlvIY6aE.js +1 -0
- package/dist/public/assets/{_DxEm-Gwj.js → _Dmi6AQP3.js} +1 -1
- package/dist/public/assets/_Dmi6AQP3.js.br +0 -0
- package/dist/public/assets/{_BbbOvNRH.js → _Dmj0vHNs.js} +1 -1
- package/dist/public/assets/{_BbbOvNRH.js.br → _Dmj0vHNs.js.br} +0 -0
- package/dist/public/assets/{_DSVLaMWS.js → _DnYboxB9.js} +1 -1
- package/dist/public/assets/_DnYboxB9.js.br +0 -0
- package/dist/public/assets/{_Cz5BPBG8.js → _Do6MGycg.js} +1 -1
- package/dist/public/assets/_Do6MGycg.js.br +0 -0
- package/dist/public/assets/{_DkCaEf_h.js → _DtZ-vebM.js} +1 -1
- package/dist/public/assets/_DtZ-vebM.js.br +0 -0
- package/dist/public/assets/_DuNisSjT.js +1 -0
- package/dist/public/assets/_Dvk-TlMq.js +1 -0
- package/dist/public/assets/_Dvk-TlMq.js.br +0 -0
- package/dist/public/assets/_DwdnhMjL.js +1 -0
- package/dist/public/assets/_DwydmxSi.js +1 -0
- package/dist/public/assets/_DzgHDUu0.js +1 -0
- package/dist/public/assets/{_Dp3IZdH8.js → _G-e2JHHS.js} +1 -1
- package/dist/public/assets/_G-e2JHHS.js.br +0 -0
- package/dist/public/assets/_IOS0xG1B.js +1 -0
- package/dist/public/assets/_IiZnk_jc.js +1 -0
- package/dist/public/assets/{_DaMVRI8f.js → _KYdxhRVL.js} +1 -1
- package/dist/public/assets/_KYdxhRVL.js.br +0 -0
- package/dist/public/assets/_LY1sEEvJ.js +1 -0
- package/dist/public/assets/_MATnTPAL.js +1 -0
- package/dist/public/assets/_MATnTPAL.js.br +0 -0
- package/dist/public/assets/_OVl4e0V3.js +1 -0
- package/dist/public/assets/{_Bf8WYPfh.js → _Sv1HjkeK.js} +1 -1
- package/dist/public/assets/_Sv1HjkeK.js.br +0 -0
- package/dist/public/assets/_Syg4UyQU.js +86 -0
- package/dist/public/assets/_Syg4UyQU.js.br +0 -0
- package/dist/public/assets/_TJCslr2g.js +1 -0
- package/dist/public/assets/_UcXY-7XH.js +2 -0
- package/dist/public/assets/_UcXY-7XH.js.br +0 -0
- package/dist/public/assets/{_j2tDSMvo.js → _VM9JbUGP.js} +1 -1
- package/dist/public/assets/_VM9JbUGP.js.br +0 -0
- package/dist/public/assets/_YOjtJWMK.js +1 -0
- package/dist/public/assets/_YOjtJWMK.js.br +10 -0
- package/dist/public/assets/_YPt61819.js +1 -0
- package/dist/public/assets/{_DbvaGqOl.js → _Zh4-3iG-.js} +1 -1
- package/dist/public/assets/_Zh4-3iG-.js.br +0 -0
- package/dist/public/assets/{_D4dJ2qEE.js → _ZptG1LQC.js} +1 -1
- package/dist/public/assets/_brnakAIx.js +1 -0
- package/dist/public/assets/_bsxJ1YDE.js +1 -0
- package/dist/public/assets/_f5wPpUkq.js +1 -0
- package/dist/public/assets/_fPqLhj85.js +1 -0
- package/dist/public/assets/_g3oXW6NQ.js +1 -0
- package/dist/public/assets/_iHPPeFV7.js +1 -0
- package/dist/public/assets/_iJwEKWn1.js +1 -0
- package/dist/public/assets/_jtFrcV5d.js +1 -0
- package/dist/public/assets/{_Bv3e3rg8.js → _kQ9qYC7a.js} +1 -1
- package/dist/public/assets/_kQ9qYC7a.js.br +0 -0
- package/dist/public/assets/_kQki_UDN.js +1 -0
- package/dist/public/assets/_lRRU15CX.js +1 -0
- package/dist/public/assets/_lRRU15CX.js.br +0 -0
- package/dist/public/assets/_mKx7UwEC.js +1 -0
- package/dist/public/assets/_nnKb_fyX.js +6 -0
- package/dist/public/assets/_nnKb_fyX.js.br +0 -0
- package/dist/public/assets/_p44jCyhe.js +1 -0
- package/dist/public/assets/_pAx6IPLY.js +1 -0
- package/dist/public/assets/_psqSIrEM.js +1 -0
- package/dist/public/assets/{_CyBCIknf.js → _w_IRrfdL.js} +1 -1
- package/dist/public/assets/_w_IRrfdL.js.br +0 -0
- package/dist/public/assets/_wxSNlWQ_.js +1 -0
- package/dist/public/assets/_xPBJn0Hx.js +1 -0
- package/dist/public/assets/_xPBJn0Hx.js.br +0 -0
- package/dist/public/assets/_yP2G9NCR.js +1 -0
- package/dist/public/assets/app-shell-CVYlktwa.css +1 -0
- package/dist/public/assets/app-shell-CVYlktwa.css.br +0 -0
- package/dist/public/assets/files-view-SzdFekvc.js +2 -0
- package/dist/public/assets/manage-workspace-DIY2p0qY.js +2 -0
- package/dist/public/assets/new-dBLsQZ5Y.js +1 -0
- package/dist/public/assets/new-workspace-D6YmZcwM.js +2 -0
- package/dist/public/assets/review-view-Dr5gLqyl.js +2 -0
- package/dist/public/assets/settings-dBLsQZ5Y.js +1 -0
- package/dist/public/assets/settings-page-COg15zf5.js +2 -0
- package/dist/public/assets/styles-DqimleOa.css +1 -0
- package/dist/public/assets/styles-DqimleOa.css.br +0 -0
- package/dist/public/assets/w-dBLsQZ5Y.js +1 -0
- package/dist/public/assets/w._-BbJyr8oS.js +1 -0
- package/dist/public/assets/w._-Bbhvn-OV.js +1 -0
- package/dist/public/assets/w._-dBLsQZ5Y.js +1 -0
- package/dist/rtc-helper.mjs +1170 -0
- package/lib/preview/media.mjs +5 -4
- package/lib/setup/doctor.d.mts +23 -1
- package/lib/setup/doctor.mjs +75 -9
- package/lib/setup/firewall.d.mts +76 -0
- package/lib/setup/firewall.mjs +598 -0
- package/lib/setup/tailscale.d.mts +53 -0
- package/lib/setup/tailscale.mjs +179 -0
- package/package.json +3 -2
- package/dist/_CkwTsHKB.js +0 -2
- package/dist/public/assets/_1RHVsAcK.js +0 -1
- package/dist/public/assets/_4CShjaLP.js +0 -1
- package/dist/public/assets/_68JtNDO1.js +0 -1
- package/dist/public/assets/_8G2Mv7jG.js.br +0 -0
- package/dist/public/assets/_8dvK2NDJ.js.br +0 -0
- package/dist/public/assets/_94L2SIJF.js +0 -1
- package/dist/public/assets/_9AnDb3YH.js +0 -1
- package/dist/public/assets/_9kX9D09B.js.br +0 -0
- package/dist/public/assets/_9lErVegn.js +0 -1
- package/dist/public/assets/_B0oyGUU5.js +0 -1
- package/dist/public/assets/_B0oyGUU5.js.br +0 -0
- package/dist/public/assets/_B1mPnLlp.js +0 -1
- package/dist/public/assets/_B4fi2SSA.js +0 -1
- package/dist/public/assets/_B7Qx25UP.js +0 -1
- package/dist/public/assets/_B7b8EVjA.js +0 -1
- package/dist/public/assets/_BBWaxDkO.js.br +0 -0
- package/dist/public/assets/_BDa-iwuj.js.br +0 -0
- package/dist/public/assets/_BEKHKNmM.js +0 -1
- package/dist/public/assets/_BE_Jyvqd.js.br +0 -0
- package/dist/public/assets/_BFU-kJkk.js +0 -1
- package/dist/public/assets/_BIJ2O2oU.js +0 -1
- package/dist/public/assets/_BJ59XAZ9.js +0 -1
- package/dist/public/assets/_BKqRYfOI.js +0 -15
- package/dist/public/assets/_BKqRYfOI.js.br +0 -0
- package/dist/public/assets/_BKr9Dzz1.js +0 -1
- package/dist/public/assets/_BN7xvxS_.js +0 -1
- package/dist/public/assets/_BNQTVBlH.js +0 -1
- package/dist/public/assets/_BNW5Jiec.js.br +0 -0
- package/dist/public/assets/_BOGkzMx9.js.br +0 -0
- package/dist/public/assets/_BUEpqQ_m.js +0 -1
- package/dist/public/assets/_BUvqweu0.js.br +0 -0
- package/dist/public/assets/_BZKB4fhr.js +0 -1
- package/dist/public/assets/_BZKB4fhr.js.br +0 -0
- package/dist/public/assets/_BZo9BjDF.js +0 -1
- package/dist/public/assets/_BdUNnSlC.js +0 -1
- package/dist/public/assets/_Bf8WYPfh.js.br +0 -0
- package/dist/public/assets/_Bhx319Hi.js.br +0 -0
- package/dist/public/assets/_Bm4SHrNp.js.br +0 -0
- package/dist/public/assets/_Bmrqq8Ro.js +0 -2
- package/dist/public/assets/_Bmrqq8Ro.js.br +0 -0
- package/dist/public/assets/_BnHZ6Npj.js +0 -1
- package/dist/public/assets/_BoDxRJLS.js +0 -1
- package/dist/public/assets/_BoDxRJLS.js.br +0 -0
- package/dist/public/assets/_BoPk1gXL.js +0 -1
- package/dist/public/assets/_Bo_Ru664.js +0 -1
- package/dist/public/assets/_Bp8-V8yl.js.br +0 -0
- package/dist/public/assets/_BpoeUr5j.js.br +0 -0
- package/dist/public/assets/_Bq2G_Tid.js +0 -1
- package/dist/public/assets/_BsyoLB_D.js +0 -1
- package/dist/public/assets/_Bv3e3rg8.js.br +0 -0
- package/dist/public/assets/_BvXp6HpX.js.br +0 -0
- package/dist/public/assets/_BwP07uVS.js.br +0 -0
- package/dist/public/assets/_Bx1CW-sF.js.br +0 -0
- package/dist/public/assets/_BywcP-As.js.br +0 -0
- package/dist/public/assets/_Bzgtwt3G.js +0 -1
- package/dist/public/assets/_Bzgtwt3G.js.br +0 -0
- package/dist/public/assets/_C0_s45qg.js.br +0 -0
- package/dist/public/assets/_C0ePgF6b.js +0 -1
- package/dist/public/assets/_C0oVtTqO.js +0 -1
- package/dist/public/assets/_C0oVtTqO.js.br +0 -0
- package/dist/public/assets/_C654p96Z.js.br +0 -0
- package/dist/public/assets/_C8_1Y2-z.js +0 -1
- package/dist/public/assets/_C8_1Y2-z.js.br +0 -0
- package/dist/public/assets/_C8v1AZFP.js +0 -1
- package/dist/public/assets/_CB0D5cRH.js +0 -1
- package/dist/public/assets/_CD05JUTh.js +0 -1
- package/dist/public/assets/_CEJUcePr.js.br +0 -0
- package/dist/public/assets/_CEXHZd73.js.br +0 -0
- package/dist/public/assets/_CHcUMVR7.js +0 -1
- package/dist/public/assets/_CHuLFr1f.js.br +0 -0
- package/dist/public/assets/_CIb7xw_1.js.br +0 -0
- package/dist/public/assets/_CMSBfO6u.js.br +0 -0
- package/dist/public/assets/_CN7GPyBo.js +0 -1
- package/dist/public/assets/_COcePo2y.js.br +0 -0
- package/dist/public/assets/_CTINBWaG.js.br +0 -0
- package/dist/public/assets/_CTWrnAbz.js +0 -1
- package/dist/public/assets/_CUXajOKj.js.br +0 -0
- package/dist/public/assets/_CVru3vzC.js +0 -1
- package/dist/public/assets/_CYjE__ml.js +0 -1
- package/dist/public/assets/_CYjE__ml.js.br +0 -0
- package/dist/public/assets/_CZ_OWtIT.js.br +0 -0
- package/dist/public/assets/_C_37_B6u.js.br +0 -0
- package/dist/public/assets/_C_CIQL7J.js +0 -1
- package/dist/public/assets/_C_CIQL7J.js.br +0 -0
- package/dist/public/assets/_C_WdpYbK.js +0 -1
- package/dist/public/assets/_CaiH3VN9.js +0 -1
- package/dist/public/assets/_CamWDaoG.js.br +0 -0
- package/dist/public/assets/_CdDElA0V.js +0 -1
- package/dist/public/assets/_CfnsClzZ.js +0 -1
- package/dist/public/assets/_Cgo1fRhJ.js +0 -1
- package/dist/public/assets/_Cgo1fRhJ.js.br +0 -0
- package/dist/public/assets/_CjhGrlf3.js +0 -1
- package/dist/public/assets/_CjlbL4C_.js +0 -1
- package/dist/public/assets/_CjogTUXK.js +0 -1
- package/dist/public/assets/_ClldMY37.js.br +0 -0
- package/dist/public/assets/_CmFq6Gtp.js +0 -1
- package/dist/public/assets/_CoAPOKiP.js +0 -1
- package/dist/public/assets/_CoUUgh9P.js +0 -1
- package/dist/public/assets/_CpjSCB1I.js.br +0 -0
- package/dist/public/assets/_Ct3RF80L.js.br +0 -0
- package/dist/public/assets/_CtYy5eZs.js +0 -1
- package/dist/public/assets/_CxAPL49a.js.br +0 -0
- package/dist/public/assets/_CyBCIknf.js.br +0 -0
- package/dist/public/assets/_Cz5BPBG8.js.br +0 -0
- package/dist/public/assets/_D-eEFXaI.js +0 -1
- package/dist/public/assets/_D0aoEFRx.js.br +0 -0
- package/dist/public/assets/_D1uRW1qz.js.br +0 -0
- package/dist/public/assets/_D2oIr2T2.js +0 -1
- package/dist/public/assets/_D2un443j.js.br +0 -0
- package/dist/public/assets/_D3MPx4-f.js +0 -1
- package/dist/public/assets/_D4q8XSMI.js.br +0 -0
- package/dist/public/assets/_D4quFMVQ.js.br +0 -0
- package/dist/public/assets/_D4rOX-Fa.js.br +0 -0
- package/dist/public/assets/_D5edrSyA.js +0 -1
- package/dist/public/assets/_D6kktUFn.js.br +0 -0
- package/dist/public/assets/_D80-qtVY.js +0 -1
- package/dist/public/assets/_D9-3EVA4.js +0 -1
- package/dist/public/assets/_D9sS4J_w.js.br +0 -0
- package/dist/public/assets/_DBLpxTDi.js +0 -1
- package/dist/public/assets/_DByHQ7nW.js +0 -1591
- package/dist/public/assets/_DByHQ7nW.js.br +0 -0
- package/dist/public/assets/_DC-78WeM.js.br +0 -0
- package/dist/public/assets/_DDl8KSWJ.js.br +0 -0
- package/dist/public/assets/_DFWOMF-B.js.br +0 -0
- package/dist/public/assets/_DKb-rt9n.js +0 -1
- package/dist/public/assets/_DMnSJCF_.js +0 -1
- package/dist/public/assets/_DOOIlrPh.js +0 -1
- package/dist/public/assets/_DPW-0yKP.js +0 -1
- package/dist/public/assets/_DR3BmvWU.js +0 -1
- package/dist/public/assets/_DSVLaMWS.js.br +0 -0
- package/dist/public/assets/_DYNGNKLk.js +0 -1
- package/dist/public/assets/_DZnEgCbj.js +0 -1
- package/dist/public/assets/_DaMVRI8f.js.br +0 -0
- package/dist/public/assets/_DbvaGqOl.js.br +0 -0
- package/dist/public/assets/_DcMIlvz-.js.br +0 -0
- package/dist/public/assets/_Dd6X3e7w.js.br +0 -0
- package/dist/public/assets/_De7P3jUH.js.br +0 -0
- package/dist/public/assets/_DeiFEAar.js +0 -1
- package/dist/public/assets/_DfI982PI.js.br +0 -0
- package/dist/public/assets/_DfZ6emcw.js +0 -1
- package/dist/public/assets/_Dj1lZ1pa.js +0 -86
- package/dist/public/assets/_Dj1lZ1pa.js.br +0 -0
- package/dist/public/assets/_DkCaEf_h.js.br +0 -0
- package/dist/public/assets/_DonAis0J.js +0 -1
- package/dist/public/assets/_Dp3IZdH8.js.br +0 -0
- package/dist/public/assets/_DqYih4xk.js +0 -1
- package/dist/public/assets/_DqYih4xk.js.br +0 -0
- package/dist/public/assets/_DqhphdU4.js.br +0 -0
- package/dist/public/assets/_DrIgZJzN.js.br +0 -0
- package/dist/public/assets/_Dt4hHR05.js +0 -1
- package/dist/public/assets/_DtTbTraA.js +0 -1
- package/dist/public/assets/_DwMxAJKP.js +0 -1
- package/dist/public/assets/_DxEm-Gwj.js.br +0 -0
- package/dist/public/assets/_Dytf99zx.js.br +0 -0
- package/dist/public/assets/_EAgv5jR9.js +0 -1
- package/dist/public/assets/_Iecpd0kS.js +0 -1
- package/dist/public/assets/_Iecpd0kS.js.br +0 -0
- package/dist/public/assets/_MCwIJAuJ.js.br +0 -0
- package/dist/public/assets/_NM79Lu3L.js +0 -6
- package/dist/public/assets/_NM79Lu3L.js.br +0 -0
- package/dist/public/assets/_QpNKKuS9.js +0 -1
- package/dist/public/assets/_SGDxiwE1.js.br +0 -0
- package/dist/public/assets/_TA8pE7z9.js +0 -1
- package/dist/public/assets/_bE4sNDeU.js +0 -1
- package/dist/public/assets/_bcsuBP7T.js.br +0 -0
- package/dist/public/assets/_cdcAU4yY.js +0 -1
- package/dist/public/assets/_ch_yXAap.js.br +0 -0
- package/dist/public/assets/_d5u7EI97.js.br +0 -0
- package/dist/public/assets/_eoa1EOU-.js.br +0 -0
- package/dist/public/assets/_j2tDSMvo.js.br +0 -0
- package/dist/public/assets/_jNhIFgbc.js +0 -1
- package/dist/public/assets/_kDYiTaag.js +0 -1
- package/dist/public/assets/_lNMVVbUx.js +0 -1
- package/dist/public/assets/_nwJ7Hu3S.js +0 -1
- package/dist/public/assets/_tmDtUACa.js +0 -1
- package/dist/public/assets/_tmDtUACa.js.br +0 -0
- package/dist/public/assets/_wXDh-Z2N.js.br +0 -0
- package/dist/public/assets/_wcshV0sZ.js.br +0 -0
- package/dist/public/assets/_x-NwqgCn.js +0 -1
- package/dist/public/assets/_xyw_DS5P.js.br +0 -0
- package/dist/public/assets/_zSAfqXcm.js.br +0 -0
- package/dist/public/assets/app-shell-ChQoVC5b.css +0 -1
- package/dist/public/assets/app-shell-ChQoVC5b.css.br +0 -0
- package/dist/public/assets/files-view-CLtLp_BW.js +0 -2
- package/dist/public/assets/files-view-CNHQapdI.css +0 -1
- package/dist/public/assets/files-view-CNHQapdI.css.br +0 -0
- package/dist/public/assets/group.css.ts-BG82htKb.css +0 -1
- package/dist/public/assets/group.css.ts-BG82htKb.css.br +0 -0
- package/dist/public/assets/icon-folder-DJOHuEpD.css +0 -1
- package/dist/public/assets/icon-folder-DJOHuEpD.css.br +0 -0
- package/dist/public/assets/icon-search-DsJuFXUJ.css +0 -1
- package/dist/public/assets/icon-search-DsJuFXUJ.css.br +0 -0
- package/dist/public/assets/manage-workspace-NBcFDyrB.js +0 -2
- package/dist/public/assets/manage-workspace-f_Np32TD.css +0 -1
- package/dist/public/assets/modal-view-KVNBpNYi.css +0 -1
- package/dist/public/assets/modal-view-KVNBpNYi.css.br +0 -0
- package/dist/public/assets/new-DHI77GvL.js +0 -1
- package/dist/public/assets/new-workspace-BFE-HpD_.css +0 -1
- package/dist/public/assets/new-workspace-BFE-HpD_.css.br +0 -0
- package/dist/public/assets/new-workspace-BRzimdd5.js +0 -2
- package/dist/public/assets/port-chip-CUUIDOVM.css +0 -1
- package/dist/public/assets/port-chip-CUUIDOVM.css.br +0 -0
- package/dist/public/assets/prompt-dialog-BGs6RXOV.css +0 -1
- package/dist/public/assets/prompt-dialog-BGs6RXOV.css.br +0 -0
- package/dist/public/assets/quick-open-Gx4so1bl.css +0 -1
- package/dist/public/assets/quick-open-Gx4so1bl.css.br +0 -0
- package/dist/public/assets/repo-picker-CUhd0vJN.css +0 -1
- package/dist/public/assets/repo-picker-CUhd0vJN.css.br +0 -4
- package/dist/public/assets/review-view-DFEK9VBa.js +0 -2
- package/dist/public/assets/review-view-deUY3OE5.css +0 -1
- package/dist/public/assets/review-view-deUY3OE5.css.br +0 -0
- package/dist/public/assets/section-CziSOSBR.css +0 -1
- package/dist/public/assets/section-CziSOSBR.css.br +0 -0
- package/dist/public/assets/settings-DHI77GvL.js +0 -1
- package/dist/public/assets/settings-page-OOtPOzIn.js +0 -2
- package/dist/public/assets/settings-page-wZhd7FLi.css +0 -1
- package/dist/public/assets/settings-page-wZhd7FLi.css.br +0 -0
- package/dist/public/assets/skill-row-BoCyFIXg.css +0 -1
- package/dist/public/assets/sso-auth-DV76tTpE.css +0 -1
- package/dist/public/assets/sso-auth-DV76tTpE.css.br +0 -0
- package/dist/public/assets/w-DHI77GvL.js +0 -1
- package/dist/public/assets/w._-DHI77GvL.js +0 -1
- package/dist/public/assets/w._-DsTgq3-C.js +0 -1
- package/dist/public/assets/w._-igEOSPR-.js +0 -1
|
@@ -182,7 +182,7 @@ try {
|
|
|
182
182
|
* open terminal. */
|
|
183
183
|
var TMUX_SOCKET = process.env.WORK_TMUX_SOCKET || "work";
|
|
184
184
|
var execFileAsync = promisify(execFile);
|
|
185
|
-
async function run$
|
|
185
|
+
async function run$2(cmd, args, cwd, env, opts = {}) {
|
|
186
186
|
const child = execFileAsync(cmd, args, {
|
|
187
187
|
cwd,
|
|
188
188
|
env,
|
|
@@ -230,7 +230,7 @@ var git = async (args, cwd) => {
|
|
|
230
230
|
const verb = args.find((a) => !a.startsWith("-")) ?? "";
|
|
231
231
|
const timeoutMs = GIT_NETWORK_MS[verb];
|
|
232
232
|
try {
|
|
233
|
-
return await run$
|
|
233
|
+
return await run$2("git", args, cwd, gitEnv(), timeoutMs ? { timeoutMs } : void 0);
|
|
234
234
|
} catch (err) {
|
|
235
235
|
if (timeoutMs && err.killed) throw new Error(`git ${verb} timed out after ${Math.round(timeoutMs / 1e3)}s`);
|
|
236
236
|
throw err;
|
|
@@ -248,7 +248,7 @@ var gh = async (args, host) => {
|
|
|
248
248
|
const verb = args[0] ?? "";
|
|
249
249
|
const timeoutMs = GH_MS[verb] ?? GH_DEFAULT_MS;
|
|
250
250
|
try {
|
|
251
|
-
return await run$
|
|
251
|
+
return await run$2("gh", args, void 0, host ? {
|
|
252
252
|
...process.env,
|
|
253
253
|
GH_HOST: host
|
|
254
254
|
} : void 0, { timeoutMs });
|
|
@@ -257,7 +257,7 @@ var gh = async (args, host) => {
|
|
|
257
257
|
throw err;
|
|
258
258
|
}
|
|
259
259
|
};
|
|
260
|
-
var tmux = (args, env, opts) => run$
|
|
260
|
+
var tmux = (args, env, opts) => run$2("tmux", [
|
|
261
261
|
"-L",
|
|
262
262
|
TMUX_SOCKET,
|
|
263
263
|
...args
|
|
@@ -347,11 +347,12 @@ function bridgeForServer(dataDir) {
|
|
|
347
347
|
}
|
|
348
348
|
//#endregion
|
|
349
349
|
//#region src/server/migrations.ts
|
|
350
|
-
var STEPS = [
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
db
|
|
350
|
+
var STEPS = [
|
|
351
|
+
{
|
|
352
|
+
version: 1,
|
|
353
|
+
name: "baseline",
|
|
354
|
+
up(db) {
|
|
355
|
+
db.exec(`
|
|
355
356
|
CREATE TABLE workspaces (
|
|
356
357
|
id TEXT PRIMARY KEY,
|
|
357
358
|
name TEXT NOT NULL,
|
|
@@ -421,49 +422,58 @@ var STEPS = [{
|
|
|
421
422
|
PRIMARY KEY (workspace_id, worktree, branch, path)
|
|
422
423
|
);
|
|
423
424
|
`);
|
|
424
|
-
|
|
425
|
-
},
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
db
|
|
425
|
+
}
|
|
426
|
+
},
|
|
427
|
+
{
|
|
428
|
+
version: 2,
|
|
429
|
+
name: "drop what 0.0.x kept for its upgrades",
|
|
430
|
+
up(db) {
|
|
431
|
+
db.exec(`
|
|
430
432
|
DELETE FROM review_marks WHERE path = '';
|
|
431
433
|
DELETE FROM settings
|
|
432
434
|
WHERE key IN ('review-cleared-diff-v2', 'ui.diff-uncommitted', 'diff-uncommitted')
|
|
433
435
|
OR key GLOB 'review.seen:*';
|
|
434
436
|
`);
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
437
|
+
for (const name of [
|
|
438
|
+
"tab",
|
|
439
|
+
"diff-filter",
|
|
440
|
+
"diff-folded",
|
|
441
|
+
"diff-collapsed",
|
|
442
|
+
"diff-focus",
|
|
443
|
+
"diff-pos",
|
|
444
|
+
"files-recent"
|
|
445
|
+
]) {
|
|
446
|
+
const prefix = `ui.${name}:`;
|
|
447
|
+
db.prepare("DELETE FROM settings WHERE key GLOB ? AND substr(key, ?) NOT IN (SELECT id FROM workspaces)").run(`${prefix}*`, prefix.length + 1);
|
|
448
|
+
}
|
|
449
|
+
const pref = (key) => db.prepare("SELECT value FROM settings WHERE key = ?").get(key)?.value;
|
|
450
|
+
const parse = (text) => {
|
|
451
|
+
try {
|
|
452
|
+
return text === void 0 ? void 0 : JSON.parse(text);
|
|
453
|
+
} catch {
|
|
454
|
+
return;
|
|
455
|
+
}
|
|
456
|
+
};
|
|
457
|
+
const font = parse(pref("ui.term-font"));
|
|
458
|
+
if (font && typeof font === "object") {
|
|
459
|
+
for (const device of ["desktop", "touch"]) if (Number.isInteger(font[device])) db.prepare("INSERT OR IGNORE INTO settings (key, value) VALUES (?, ?)").run(`ui.term-font-${device}`, String(font[device]));
|
|
460
|
+
}
|
|
461
|
+
db.exec("DELETE FROM settings WHERE key = 'ui.term-font'");
|
|
462
|
+
const keys = parse(pref("ui.phone-keys"));
|
|
463
|
+
if (Array.isArray(keys)) db.prepare("UPDATE settings SET value = ? WHERE key = 'ui.phone-keys'").run(JSON.stringify({
|
|
464
|
+
base: [],
|
|
465
|
+
extra: keys
|
|
466
|
+
}));
|
|
446
467
|
}
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
}
|
|
454
|
-
};
|
|
455
|
-
const font = parse(pref("ui.term-font"));
|
|
456
|
-
if (font && typeof font === "object") {
|
|
457
|
-
for (const device of ["desktop", "touch"]) if (Number.isInteger(font[device])) db.prepare("INSERT OR IGNORE INTO settings (key, value) VALUES (?, ?)").run(`ui.term-font-${device}`, String(font[device]));
|
|
468
|
+
},
|
|
469
|
+
{
|
|
470
|
+
version: 3,
|
|
471
|
+
name: "drop the typing-prediction pref",
|
|
472
|
+
up(db) {
|
|
473
|
+
db.exec("DELETE FROM settings WHERE key = 'ui.term-predict'");
|
|
458
474
|
}
|
|
459
|
-
db.exec("DELETE FROM settings WHERE key = 'ui.term-font'");
|
|
460
|
-
const keys = parse(pref("ui.phone-keys"));
|
|
461
|
-
if (Array.isArray(keys)) db.prepare("UPDATE settings SET value = ? WHERE key = 'ui.phone-keys'").run(JSON.stringify({
|
|
462
|
-
base: [],
|
|
463
|
-
extra: keys
|
|
464
|
-
}));
|
|
465
475
|
}
|
|
466
|
-
|
|
476
|
+
];
|
|
467
477
|
var LATEST = STEPS.at(-1).version;
|
|
468
478
|
/** The database at `file`, at the latest version: an empty one is built by
|
|
469
479
|
* every step, an existing one gets those it lacks — each in a transaction
|
|
@@ -979,6 +989,418 @@ function agentLabel$1(id) {
|
|
|
979
989
|
const parsed = parseAgentId(id);
|
|
980
990
|
return parsed ? `${parsed.family.label}${parsed.suffix ? ` ${parsed.suffix}` : ""}` : id;
|
|
981
991
|
}
|
|
992
|
+
/** `tailscale version` prints the short version first (`1.76.1`, or
|
|
993
|
+
* `1.77.30` on an unstable track), then commit lines. */
|
|
994
|
+
function parseVersion(text) {
|
|
995
|
+
return /\b(\d+)\.(\d+)\.(\d+)\b/.exec(text || "")?.[0] ?? null;
|
|
996
|
+
}
|
|
997
|
+
function atLeast(version, min) {
|
|
998
|
+
const a = version.split(".").map(Number);
|
|
999
|
+
const b = min.split(".").map(Number);
|
|
1000
|
+
for (let i = 0; i < 3; i++) if (a[i] !== b[i]) return a[i] > b[i];
|
|
1001
|
+
return true;
|
|
1002
|
+
}
|
|
1003
|
+
/** The target the CLI writes (`http://127.0.0.1:7171`) or one a hand-made
|
|
1004
|
+
* or older config holds (`localhost:7171`, `http://[::1]:7171`, `7171`),
|
|
1005
|
+
* when it is work's port on this machine. */
|
|
1006
|
+
function targetsPort(proxy, port) {
|
|
1007
|
+
if (/^\d+$/.test(proxy)) return proxy === String(port);
|
|
1008
|
+
let url;
|
|
1009
|
+
try {
|
|
1010
|
+
url = new URL(proxy.includes("://") ? proxy : `http://${proxy}`);
|
|
1011
|
+
} catch {
|
|
1012
|
+
return false;
|
|
1013
|
+
}
|
|
1014
|
+
return url.protocol === "http:" && [
|
|
1015
|
+
"127.0.0.1",
|
|
1016
|
+
"localhost",
|
|
1017
|
+
"[::1]"
|
|
1018
|
+
].includes(url.hostname) && url.port === String(port);
|
|
1019
|
+
}
|
|
1020
|
+
/** The URL a `Web` entry (`<name>:<port>`) is opened at: https unless its
|
|
1021
|
+
* port is served as plain HTTP (`--http=<port>`). */
|
|
1022
|
+
function webUrl(config, hostPort) {
|
|
1023
|
+
const i = hostPort.lastIndexOf(":");
|
|
1024
|
+
const host = hostPort.slice(0, i);
|
|
1025
|
+
const port = hostPort.slice(i + 1);
|
|
1026
|
+
const tls = !config.TCP?.[port]?.HTTP;
|
|
1027
|
+
return `${tls ? "https" : "http"}://${host}${port === (tls ? "443" : "80") ? "" : `:${port}`}/`;
|
|
1028
|
+
}
|
|
1029
|
+
/** Where `tailscale serve status --json` (an ipn.ServeConfig; `{}` or
|
|
1030
|
+
* `null` when empty) serves work's port, and whether Funnel publishes that
|
|
1031
|
+
* to the internet — or null. Only a handler at `/` counts: work serves
|
|
1032
|
+
* every page, asset and websocket from the root. */
|
|
1033
|
+
function serveOf(config, port) {
|
|
1034
|
+
for (const [hostPort, web] of Object.entries(config?.Web || {})) {
|
|
1035
|
+
const proxy = web?.Handlers?.["/"]?.Proxy;
|
|
1036
|
+
if (!proxy || !targetsPort(proxy, port)) continue;
|
|
1037
|
+
const url = webUrl(config, hostPort);
|
|
1038
|
+
return {
|
|
1039
|
+
url,
|
|
1040
|
+
host: new URL(url).hostname,
|
|
1041
|
+
funnel: !!config.AllowFunnel?.[hostPort]
|
|
1042
|
+
};
|
|
1043
|
+
}
|
|
1044
|
+
return null;
|
|
1045
|
+
}
|
|
1046
|
+
function hosts(value) {
|
|
1047
|
+
return (value || "").split(",").map((s) => s.trim()).filter(Boolean);
|
|
1048
|
+
}
|
|
1049
|
+
/**
|
|
1050
|
+
* The probe `work doctor` and `work setup` read, from the CLI's output:
|
|
1051
|
+
* `version` (`tailscale version`), `status` (`tailscale status --json`,
|
|
1052
|
+
* null when tailscaled did not answer) and `serve` (`tailscale serve
|
|
1053
|
+
* status --json`). `allowedHosts` is the WORK_ALLOWED_HOSTS the service
|
|
1054
|
+
* runs with.
|
|
1055
|
+
*/
|
|
1056
|
+
function readTailscale({ path, version: versionText, status, serve }, { port, allowedHosts }) {
|
|
1057
|
+
const version = parseVersion(versionText);
|
|
1058
|
+
const name = String(status?.Self?.DNSName || "").replace(/\.$/, "").toLowerCase() || null;
|
|
1059
|
+
const certs = status?.CertDomains;
|
|
1060
|
+
const https = Array.isArray(certs) ? certs.some((d) => d.toLowerCase() === name) : status && "CertDomains" in status ? false : null;
|
|
1061
|
+
const served = serveOf(serve, port);
|
|
1062
|
+
const root = name ? serve?.Web?.[`${name}:443`]?.Handlers?.["/"] : null;
|
|
1063
|
+
return {
|
|
1064
|
+
installed: true,
|
|
1065
|
+
path,
|
|
1066
|
+
version,
|
|
1067
|
+
serveCli: !!version && atLeast(version, "1.52.0"),
|
|
1068
|
+
state: status?.BackendState ?? null,
|
|
1069
|
+
running: status?.BackendState === "Running" && !!name,
|
|
1070
|
+
name,
|
|
1071
|
+
https,
|
|
1072
|
+
port: String(port),
|
|
1073
|
+
serve: served && {
|
|
1074
|
+
...served,
|
|
1075
|
+
allowed: hosts(allowedHosts).some((h) => h.toLowerCase() === served.host)
|
|
1076
|
+
},
|
|
1077
|
+
rootTaken: !served && root ? root.Proxy || root.Path || root.Redirect || "text" : null
|
|
1078
|
+
};
|
|
1079
|
+
}
|
|
1080
|
+
//#endregion
|
|
1081
|
+
//#region lib/setup/firewall.mjs
|
|
1082
|
+
/** The name work's own rule goes by: a firewalld service, a ufw comment. */
|
|
1083
|
+
var RULE = "work";
|
|
1084
|
+
var SOCKETFILTERFW = "usr/libexec/ApplicationFirewall/socketfilterfw";
|
|
1085
|
+
var CODESIGN = "usr/bin/codesign";
|
|
1086
|
+
/**
|
|
1087
|
+
* The active host firewall and whether it admits UDP `rtcPort`, or null
|
|
1088
|
+
* when none is active (or direct connections are off, `rtc` = "off").
|
|
1089
|
+
* `appPort` joins the rule when `listen` is beyond this machine, since the
|
|
1090
|
+
* app's own TCP port then has to be reachable too. `node` is the program
|
|
1091
|
+
* macOS's firewall is asked about (this process's by default: the server
|
|
1092
|
+
* asking for itself). `root` is where /etc and /usr are read from, and
|
|
1093
|
+
* `platform` the system taken for this one (a test's stand-ins).
|
|
1094
|
+
*/
|
|
1095
|
+
async function firewallProbe({ rtcPort, appPort, listen = "127.0.0.1", rtc, node = process.execPath, root = "/", platform = process.platform } = {}) {
|
|
1096
|
+
if (rtc === "off") return null;
|
|
1097
|
+
const port = Number(rtcPort) || Number(appPort) || 7171;
|
|
1098
|
+
const tcp = loopback(listen) ? null : Number(appPort) || port;
|
|
1099
|
+
const at = (p) => path.join(root, p);
|
|
1100
|
+
if (platform === "darwin") return macos(port, node, at);
|
|
1101
|
+
return await firewalld(port, tcp, at) ?? ufw(port, tcp, at);
|
|
1102
|
+
}
|
|
1103
|
+
async function firewalld(port, tcp, at) {
|
|
1104
|
+
const bin = findBin("firewall-cmd");
|
|
1105
|
+
if (!bin) return null;
|
|
1106
|
+
const active = await run$1(bin, ["--get-active-zones"]);
|
|
1107
|
+
if (!active.ok || !active.stdout.trim()) return null;
|
|
1108
|
+
const zones = active.stdout.split("\n").filter((line) => line && !/^\s/.test(line)).map((line) => line.trim().split(/\s+/)[0]);
|
|
1109
|
+
const byDefault = /^(\S+)\s+\(default\)/m.exec(active.stdout)?.[1];
|
|
1110
|
+
const zone = byDefault && zones.includes(byDefault) ? byDefault : zones[0];
|
|
1111
|
+
const services = await run$1(bin, ["--get-services"]);
|
|
1112
|
+
const ruled = services.ok && services.stdout.split(/\s+/).includes("work");
|
|
1113
|
+
const changed = readXml(at(`etc/firewalld/zones/${zone}.xml`));
|
|
1114
|
+
const def = changed ?? readXml(at(`usr/lib/firewalld/zones/${zone}.xml`));
|
|
1115
|
+
const exact = changed !== null;
|
|
1116
|
+
const admits = ruled || def !== null && zoneAdmits(def, port, at);
|
|
1117
|
+
const likely = !admits;
|
|
1118
|
+
const plan = [
|
|
1119
|
+
...ruled ? [] : [sudo("firewall-cmd", "--permanent", `--new-service=${RULE}`), sudo("firewall-cmd", "--permanent", `--service=${RULE}`, `--set-short=${RULE}`)],
|
|
1120
|
+
sudo("firewall-cmd", "--permanent", `--service=${RULE}`, `--add-port=${port}/udp`),
|
|
1121
|
+
...tcp ? [sudo("firewall-cmd", "--permanent", `--service=${RULE}`, `--add-port=${tcp}/tcp`)] : [],
|
|
1122
|
+
sudo("firewall-cmd", "--permanent", `--zone=${zone}`, `--add-service=${RULE}`),
|
|
1123
|
+
sudo("firewall-cmd", "--reload")
|
|
1124
|
+
];
|
|
1125
|
+
return result({
|
|
1126
|
+
kind: "firewalld",
|
|
1127
|
+
what: `firewalld (zone ${zone})`,
|
|
1128
|
+
zone,
|
|
1129
|
+
port,
|
|
1130
|
+
admits,
|
|
1131
|
+
likely,
|
|
1132
|
+
exact,
|
|
1133
|
+
ruled,
|
|
1134
|
+
why: admits || exact ? null : "by the zone's definition as shipped",
|
|
1135
|
+
plan: admits ? [] : plan
|
|
1136
|
+
});
|
|
1137
|
+
}
|
|
1138
|
+
function ufw(port, tcp, at) {
|
|
1139
|
+
let conf = "";
|
|
1140
|
+
try {
|
|
1141
|
+
conf = fs.readFileSync(at("etc/ufw/ufw.conf"), "utf8");
|
|
1142
|
+
} catch {
|
|
1143
|
+
return null;
|
|
1144
|
+
}
|
|
1145
|
+
if (!/^\s*ENABLED\s*=\s*yes/m.test(conf)) return null;
|
|
1146
|
+
let policy = "DROP";
|
|
1147
|
+
try {
|
|
1148
|
+
policy = /^\s*DEFAULT_INPUT_POLICY\s*=\s*"?(\w+)/m.exec(fs.readFileSync(at("etc/default/ufw"), "utf8"))?.[1] ?? policy;
|
|
1149
|
+
} catch {}
|
|
1150
|
+
let rules = null;
|
|
1151
|
+
try {
|
|
1152
|
+
rules = fs.readFileSync(at("etc/ufw/user.rules"), "utf8");
|
|
1153
|
+
} catch {}
|
|
1154
|
+
const ruled = !!rules && new RegExp(`### tuple ### allow udp ${port} \\S+ \\S+ \\S+ in\\b`).test(rules);
|
|
1155
|
+
const admits = policy === "ACCEPT" || ruled;
|
|
1156
|
+
const plan = [sudo("ufw", "allow", `${port}/udp`, "comment", RULE), ...tcp ? [sudo("ufw", "allow", `${tcp}/tcp`, "comment", RULE)] : []];
|
|
1157
|
+
return result({
|
|
1158
|
+
kind: "ufw",
|
|
1159
|
+
what: "ufw",
|
|
1160
|
+
port,
|
|
1161
|
+
admits,
|
|
1162
|
+
likely: !admits,
|
|
1163
|
+
exact: rules !== null,
|
|
1164
|
+
ruled,
|
|
1165
|
+
why: admits || rules !== null ? null : `by its default input policy, ${policy}`,
|
|
1166
|
+
plan: admits ? [] : plan
|
|
1167
|
+
});
|
|
1168
|
+
}
|
|
1169
|
+
/** macOS's application firewall filters by program, not port: what counts
|
|
1170
|
+
* is whether the node the server runs (`node`) may take connections. All
|
|
1171
|
+
* of it reads without root — the switch, "Block all incoming
|
|
1172
|
+
* connections", whether signed software is let in by itself, node's own
|
|
1173
|
+
* entry, and node's signature — and each parser takes what it can
|
|
1174
|
+
* recognise and leaves the rest unknown (`macosVerdict`), since the
|
|
1175
|
+
* wording has changed across releases. */
|
|
1176
|
+
async function macos(port, node, at) {
|
|
1177
|
+
const bin = at(SOCKETFILTERFW);
|
|
1178
|
+
if (!fs.existsSync(bin)) return null;
|
|
1179
|
+
const real = realpath(node);
|
|
1180
|
+
const said = (r) => `${r.stdout}\n${r.stderr}`;
|
|
1181
|
+
const [state, blockAll, signed, blocked, apps, sign] = await Promise.all([
|
|
1182
|
+
["--getglobalstate"],
|
|
1183
|
+
["--getblockall"],
|
|
1184
|
+
["--getallowsigned"],
|
|
1185
|
+
["--getappblocked", real],
|
|
1186
|
+
["--listapps"]
|
|
1187
|
+
].map((a) => run$1(bin, a).then(said)).concat(run$1(at(CODESIGN), ["-dv", real]).then(said)));
|
|
1188
|
+
const v = macosVerdict({
|
|
1189
|
+
state,
|
|
1190
|
+
blockAll,
|
|
1191
|
+
signed,
|
|
1192
|
+
blocked,
|
|
1193
|
+
apps,
|
|
1194
|
+
sign,
|
|
1195
|
+
paths: [.../* @__PURE__ */ new Set([node, real])]
|
|
1196
|
+
});
|
|
1197
|
+
if (!v) return null;
|
|
1198
|
+
const sfw = (...a) => sudo(bin, ...a);
|
|
1199
|
+
const plan = v.needs === "unblock" ? [sfw("--unblockapp", real)] : v.needs === "add" ? [sfw("--add", real), sfw("--unblockapp", real)] : [];
|
|
1200
|
+
return result({
|
|
1201
|
+
kind: "macos",
|
|
1202
|
+
what: "the macOS firewall",
|
|
1203
|
+
port,
|
|
1204
|
+
admits: v.admits,
|
|
1205
|
+
likely: !v.admits,
|
|
1206
|
+
exact: v.exact,
|
|
1207
|
+
ruled: false,
|
|
1208
|
+
why: v.why,
|
|
1209
|
+
node: real,
|
|
1210
|
+
plan,
|
|
1211
|
+
fix: v.needs === "blockall" ? BLOCK_ALL_FIX : void 0
|
|
1212
|
+
});
|
|
1213
|
+
}
|
|
1214
|
+
var BLOCK_ALL_FIX = "turn off “Block all incoming connections” (System Settings → Network → Firewall → Options); no rule for one program opens anything while it is on";
|
|
1215
|
+
/**
|
|
1216
|
+
* The macOS firewall's verdict on node from what socketfilterfw and
|
|
1217
|
+
* codesign said (their stdout and stderr, as text): null when the firewall
|
|
1218
|
+
* is off or its state could not be read. `needs` names the fix: `blockall`
|
|
1219
|
+
* (a setting only the user should change), `unblock` (node is listed and
|
|
1220
|
+
* blocked), `add` (node is not listed).
|
|
1221
|
+
*/
|
|
1222
|
+
function macosVerdict({ state, blockAll, signed, blocked, apps, sign, paths }) {
|
|
1223
|
+
if (globalOn(state) !== true) return null;
|
|
1224
|
+
if (blockAllOn(blockAll) ?? /State\s*=\s*2\b/.test(state)) return {
|
|
1225
|
+
admits: false,
|
|
1226
|
+
exact: true,
|
|
1227
|
+
why: "“Block all incoming connections” is on",
|
|
1228
|
+
needs: "blockall"
|
|
1229
|
+
};
|
|
1230
|
+
const entry = listedAs(apps, paths) ?? appBlocked(blocked);
|
|
1231
|
+
if (entry === "block") return {
|
|
1232
|
+
admits: false,
|
|
1233
|
+
exact: true,
|
|
1234
|
+
why: "node is blocked in it",
|
|
1235
|
+
needs: "unblock"
|
|
1236
|
+
};
|
|
1237
|
+
if (entry === "allow") return {
|
|
1238
|
+
admits: true,
|
|
1239
|
+
exact: true,
|
|
1240
|
+
why: "node is allowed in it",
|
|
1241
|
+
needs: null
|
|
1242
|
+
};
|
|
1243
|
+
const signature = signatureOf(sign);
|
|
1244
|
+
const auto = allowSigned(signed);
|
|
1245
|
+
if (signature === "developer-id" && auto.downloaded || signature === "apple" && auto.builtIn) return {
|
|
1246
|
+
admits: true,
|
|
1247
|
+
exact: false,
|
|
1248
|
+
why: `node is not listed, but it is ${signature === "apple" ? "Apple" : "Developer ID"}-signed and signed ${signature === "apple" ? "built-in" : "downloaded"} software is let in`,
|
|
1249
|
+
needs: null
|
|
1250
|
+
};
|
|
1251
|
+
return {
|
|
1252
|
+
admits: false,
|
|
1253
|
+
exact: false,
|
|
1254
|
+
why: `node is not listed, and ${signature === "developer-id" || signature === "apple" ? "signed software is not let in by itself" : signature === "adhoc" ? "an ad-hoc-signed program is not let in by itself" : signature === "unsigned" ? "an unsigned program is not let in by itself" : signature ? "a program not Developer ID-signed is not let in by itself" : "its signature could not be read"}, so its connections are dropped or asked about on the Mac's screen`,
|
|
1255
|
+
needs: "add"
|
|
1256
|
+
};
|
|
1257
|
+
}
|
|
1258
|
+
/** `--getglobalstate`: "Firewall is enabled. (State = 1)", "Firewall is
|
|
1259
|
+
* disabled. (State = 0)"; 2 is on with everything blocked. */
|
|
1260
|
+
function globalOn(text = "") {
|
|
1261
|
+
const n = /State\s*=\s*(\d)/i.exec(text);
|
|
1262
|
+
if (n) return n[1] !== "0";
|
|
1263
|
+
if (/\bdisabled\b|\boff\b/i.test(text)) return false;
|
|
1264
|
+
if (/\benabled\b|\bon\b/i.test(text)) return true;
|
|
1265
|
+
return null;
|
|
1266
|
+
}
|
|
1267
|
+
/** `--getblockall`: "Block all ENABLED!" / "Block all DISABLED!", or
|
|
1268
|
+
* "Firewall has block all state set to enabled." / "… disabled." */
|
|
1269
|
+
function blockAllOn(text = "") {
|
|
1270
|
+
if (!/block\s*all/i.test(text)) return null;
|
|
1271
|
+
if (/\bdisabled\b|\boff\b/i.test(text)) return false;
|
|
1272
|
+
if (/\benabled\b|\bon\b/i.test(text)) return true;
|
|
1273
|
+
return null;
|
|
1274
|
+
}
|
|
1275
|
+
/** `--getallowsigned`: "Automatically allow built-in signed software
|
|
1276
|
+
* ENABLED." and "Automatically allow downloaded signed software
|
|
1277
|
+
* ENABLED." (older: "… allow signed built-in software …", or one "… allow
|
|
1278
|
+
* signed software …" switch for both). */
|
|
1279
|
+
function allowSigned(text = "") {
|
|
1280
|
+
const out = {
|
|
1281
|
+
builtIn: null,
|
|
1282
|
+
downloaded: null
|
|
1283
|
+
};
|
|
1284
|
+
for (const line of text.split("\n")) {
|
|
1285
|
+
if (!/signed/i.test(line)) continue;
|
|
1286
|
+
const on = /\bdisabled\b|\boff\b/i.test(line) ? false : /\benabled\b|\bon\b/i.test(line) ? true : null;
|
|
1287
|
+
if (on === null) continue;
|
|
1288
|
+
if (/download/i.test(line)) out.downloaded = on;
|
|
1289
|
+
else if (/built-?\s?in/i.test(line)) out.builtIn = on;
|
|
1290
|
+
else out.builtIn = out.downloaded = on;
|
|
1291
|
+
}
|
|
1292
|
+
return out;
|
|
1293
|
+
}
|
|
1294
|
+
/** `--listapps`: "ALF: total number of apps = 2", then per app "1 :
|
|
1295
|
+
* /path" and, on its next line or after the path, "( Allow incoming
|
|
1296
|
+
* connections )" or "( Block incoming connections )". */
|
|
1297
|
+
function listedAs(text = "", paths = []) {
|
|
1298
|
+
const lines = text.split("\n");
|
|
1299
|
+
for (let i = 0; i < lines.length; i++) {
|
|
1300
|
+
const m = /^\s*\d+\s*:\s*(.+?)\s*(?:\(([^)]*)\))?\s*$/.exec(lines[i]);
|
|
1301
|
+
if (!m || !paths.includes(m[1].trim())) continue;
|
|
1302
|
+
for (const said of [m[2] ?? "", ...lines.slice(i + 1, i + 4)]) {
|
|
1303
|
+
if (/^\s*\d+\s*:/.test(said)) break;
|
|
1304
|
+
if (/\bblock/i.test(said)) return "block";
|
|
1305
|
+
if (/\b(allow|permit)/i.test(said)) return "allow";
|
|
1306
|
+
}
|
|
1307
|
+
}
|
|
1308
|
+
return null;
|
|
1309
|
+
}
|
|
1310
|
+
/** `--getappblocked <path>`: "… is permitted" / "… is blocked", or that it
|
|
1311
|
+
* is not part of the firewall (not listed). */
|
|
1312
|
+
function appBlocked(text = "") {
|
|
1313
|
+
if (/not part of|isn['’]?t part|not (?:a )?(?:listed|found|in the)|no such|does not exist/i.test(text)) return null;
|
|
1314
|
+
if (/\bpermitted\b|\ballowed\b|\bunblocked\b|\bnot blocked\b/i.test(text)) return "allow";
|
|
1315
|
+
if (/\bblocked\b/i.test(text)) return "block";
|
|
1316
|
+
return null;
|
|
1317
|
+
}
|
|
1318
|
+
/** `codesign -dv <path>` (on stderr): "Authority=Developer ID
|
|
1319
|
+
* Application: …", Apple's own ("Authority=Software Signing"),
|
|
1320
|
+
* "Signature=adhoc", or "code object is not signed at all". */
|
|
1321
|
+
function signatureOf(text = "") {
|
|
1322
|
+
if (/not signed at all/i.test(text)) return "unsigned";
|
|
1323
|
+
if (/^Authority=Developer ID Application\b/im.test(text)) return "developer-id";
|
|
1324
|
+
if (/^Authority=(Software Signing|Apple Code Signing|Apple Mac OS Application Signing)\b/im.test(text)) return "apple";
|
|
1325
|
+
if (/^Signature=adhoc\b|\badhoc\b/im.test(text)) return "adhoc";
|
|
1326
|
+
if (/^Authority=/im.test(text)) return "other";
|
|
1327
|
+
return null;
|
|
1328
|
+
}
|
|
1329
|
+
function result(r) {
|
|
1330
|
+
return {
|
|
1331
|
+
...r,
|
|
1332
|
+
fix: r.fix ?? (r.plan.length ? r.plan.map(shell).join(" && ") : null)
|
|
1333
|
+
};
|
|
1334
|
+
}
|
|
1335
|
+
/** Whether a firewalld zone definition lets UDP `port` in: by its target,
|
|
1336
|
+
* a port range of its own, or a service it names (a readable one). */
|
|
1337
|
+
function zoneAdmits(xml, port, at) {
|
|
1338
|
+
if (/<zone[^>]*\btarget="ACCEPT"/.test(xml)) return true;
|
|
1339
|
+
if (portsAdmit(xml, port)) return true;
|
|
1340
|
+
for (const [, name] of xml.matchAll(/<service\s+name="([^"]+)"/g)) {
|
|
1341
|
+
const svc = readXml(at(`etc/firewalld/services/${name}.xml`)) ?? readXml(at(`usr/lib/firewalld/services/${name}.xml`));
|
|
1342
|
+
if (svc && portsAdmit(svc, port)) return true;
|
|
1343
|
+
}
|
|
1344
|
+
return false;
|
|
1345
|
+
}
|
|
1346
|
+
function portsAdmit(xml, port) {
|
|
1347
|
+
for (const [tag] of xml.matchAll(/<port\b[^>]*>/g)) {
|
|
1348
|
+
const proto = /protocol="(\w+)"/.exec(tag)?.[1];
|
|
1349
|
+
const range = /port="(\d+)(?:-(\d+))?"/.exec(tag);
|
|
1350
|
+
if (proto !== "udp" || !range) continue;
|
|
1351
|
+
const lo = Number(range[1]);
|
|
1352
|
+
const hi = Number(range[2] ?? range[1]);
|
|
1353
|
+
if (port >= lo && port <= hi) return true;
|
|
1354
|
+
}
|
|
1355
|
+
return false;
|
|
1356
|
+
}
|
|
1357
|
+
function realpath(file) {
|
|
1358
|
+
try {
|
|
1359
|
+
return fs.realpathSync(file);
|
|
1360
|
+
} catch {
|
|
1361
|
+
return file;
|
|
1362
|
+
}
|
|
1363
|
+
}
|
|
1364
|
+
function sudo(...args) {
|
|
1365
|
+
return ["sudo", ...args];
|
|
1366
|
+
}
|
|
1367
|
+
function shell(argv) {
|
|
1368
|
+
return argv.map((a) => /^[\w@%+=:,./-]+$/.test(a) ? a : `'${a.replace(/'/g, "'\\''")}'`).join(" ");
|
|
1369
|
+
}
|
|
1370
|
+
function loopback(listen) {
|
|
1371
|
+
return !listen || listen === "::1" || /^127\./.test(listen) || listen === "localhost";
|
|
1372
|
+
}
|
|
1373
|
+
function readXml(file) {
|
|
1374
|
+
try {
|
|
1375
|
+
return fs.readFileSync(file, "utf8");
|
|
1376
|
+
} catch {
|
|
1377
|
+
return null;
|
|
1378
|
+
}
|
|
1379
|
+
}
|
|
1380
|
+
/** A program on PATH, or in the sbin directories a user's PATH can leave
|
|
1381
|
+
* out. */
|
|
1382
|
+
function findBin(name) {
|
|
1383
|
+
const dirs = [
|
|
1384
|
+
...(process.env.PATH || "").split(path.delimiter),
|
|
1385
|
+
"/usr/sbin",
|
|
1386
|
+
"/sbin"
|
|
1387
|
+
];
|
|
1388
|
+
for (const dir of dirs) {
|
|
1389
|
+
if (!dir) continue;
|
|
1390
|
+
const full = path.join(dir, name);
|
|
1391
|
+
try {
|
|
1392
|
+
if (fs.statSync(full).isFile()) return full;
|
|
1393
|
+
} catch {}
|
|
1394
|
+
}
|
|
1395
|
+
return null;
|
|
1396
|
+
}
|
|
1397
|
+
function run$1(cmd, args) {
|
|
1398
|
+
return new Promise((resolve) => execFile(cmd, args, { timeout: 5e3 }, (err, stdout, stderr) => resolve({
|
|
1399
|
+
ok: !err,
|
|
1400
|
+
stdout: String(stdout || ""),
|
|
1401
|
+
stderr: String(stderr || "")
|
|
1402
|
+
})));
|
|
1403
|
+
}
|
|
982
1404
|
//#endregion
|
|
983
1405
|
//#region lib/setup/doctor.mjs
|
|
984
1406
|
var home = os.homedir();
|
|
@@ -1282,11 +1704,51 @@ async function ghExtensions() {
|
|
|
1282
1704
|
}
|
|
1283
1705
|
return out;
|
|
1284
1706
|
}
|
|
1707
|
+
function parseJson(text) {
|
|
1708
|
+
try {
|
|
1709
|
+
return JSON.parse(text);
|
|
1710
|
+
} catch {
|
|
1711
|
+
return null;
|
|
1712
|
+
}
|
|
1713
|
+
}
|
|
1714
|
+
/** Tailscale here and what its serve config does with work's port
|
|
1715
|
+
* (lib/setup/tailscale.mjs), from read-only commands. `port` and
|
|
1716
|
+
* `allowedHosts` default to this process's own, which are the server's
|
|
1717
|
+
* when the server asks. */
|
|
1718
|
+
async function tailscaleProbe({ port, allowedHosts } = {}) {
|
|
1719
|
+
const bin = which("tailscale");
|
|
1720
|
+
if (!bin) return { installed: false };
|
|
1721
|
+
const [version, status, serve] = await Promise.all([
|
|
1722
|
+
run(bin, ["version"], { timeout: 5e3 }),
|
|
1723
|
+
run(bin, [
|
|
1724
|
+
"status",
|
|
1725
|
+
"--json",
|
|
1726
|
+
"--peers=false"
|
|
1727
|
+
], { timeout: 5e3 }),
|
|
1728
|
+
run(bin, [
|
|
1729
|
+
"serve",
|
|
1730
|
+
"status",
|
|
1731
|
+
"--json"
|
|
1732
|
+
], { timeout: 5e3 })
|
|
1733
|
+
]);
|
|
1734
|
+
return readTailscale({
|
|
1735
|
+
path: tilde(bin),
|
|
1736
|
+
version: version.stdout,
|
|
1737
|
+
status: status.ok ? parseJson(status.stdout) : null,
|
|
1738
|
+
serve: serve.ok ? parseJson(serve.stdout) : null
|
|
1739
|
+
}, {
|
|
1740
|
+
port: port || process.env.PORT || process.env.WORK_APP_PORT || "7171",
|
|
1741
|
+
allowedHosts: allowedHosts ?? process.env.WORK_ALLOWED_HOSTS
|
|
1742
|
+
});
|
|
1743
|
+
}
|
|
1285
1744
|
/**
|
|
1286
1745
|
* Full readiness snapshot.
|
|
1287
1746
|
*
|
|
1288
|
-
* @param {{ hosts?: string[] }} [opts]
|
|
1289
|
-
* github.com and any host gh is
|
|
1747
|
+
* @param {{ hosts?: string[], port?: string, allowedHosts?: string }} [opts]
|
|
1748
|
+
* configured GitHub hosts (settings); github.com and any host gh is
|
|
1749
|
+
* already signed in to are always included. `port` and `allowedHosts`
|
|
1750
|
+
* are the service's, for the Tailscale probe; `firewall`, when given, is
|
|
1751
|
+
* the service's own firewall reading (`serviceFirewall` in the CLI).
|
|
1290
1752
|
*/
|
|
1291
1753
|
async function doctor(opts = {}) {
|
|
1292
1754
|
const hostSet = /* @__PURE__ */ new Set([
|
|
@@ -1294,12 +1756,19 @@ async function doctor(opts = {}) {
|
|
|
1294
1756
|
...opts.hosts || [],
|
|
1295
1757
|
...ghKnownHosts()
|
|
1296
1758
|
]);
|
|
1297
|
-
const [versions, github, awake, extensions, helpers] = await Promise.all([
|
|
1759
|
+
const [versions, github, awake, extensions, helpers, tailscale, firewall] = await Promise.all([
|
|
1298
1760
|
miseVersions(),
|
|
1299
1761
|
Promise.all([...hostSet].map(githubHostStatus)),
|
|
1300
1762
|
canStayAwake(),
|
|
1301
1763
|
ghExtensions(),
|
|
1302
|
-
staleGhHelpers()
|
|
1764
|
+
staleGhHelpers(),
|
|
1765
|
+
tailscaleProbe(opts),
|
|
1766
|
+
opts.firewall !== void 0 ? opts.firewall : firewallProbe({
|
|
1767
|
+
rtcPort: opts.rtcPort ?? process.env.WORK_RTC_PORT,
|
|
1768
|
+
appPort: opts.port || process.env.PORT || process.env.WORK_APP_PORT || "7171",
|
|
1769
|
+
listen: opts.listen ?? process.env.WORK_LISTEN,
|
|
1770
|
+
rtc: opts.rtc ?? process.env.WORK_RTC
|
|
1771
|
+
})
|
|
1303
1772
|
]);
|
|
1304
1773
|
const tools = TOOLS.map((t) => {
|
|
1305
1774
|
if (t.ghExtension) {
|
|
@@ -1341,7 +1810,9 @@ async function doctor(opts = {}) {
|
|
|
1341
1810
|
agents,
|
|
1342
1811
|
github,
|
|
1343
1812
|
awake,
|
|
1344
|
-
staleGhHelpers: helpers
|
|
1813
|
+
staleGhHelpers: helpers,
|
|
1814
|
+
tailscale,
|
|
1815
|
+
firewall
|
|
1345
1816
|
};
|
|
1346
1817
|
}
|
|
1347
1818
|
//#endregion
|
|
@@ -5862,7 +6333,7 @@ var require_vapid_helper = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
5862
6333
|
var crypto$3 = __require("crypto");
|
|
5863
6334
|
var asn1 = require_asn1();
|
|
5864
6335
|
var jws = require_jws();
|
|
5865
|
-
var { URL } = __require("url");
|
|
6336
|
+
var { URL: URL$1 } = __require("url");
|
|
5866
6337
|
var WebPushConstants = require_web_push_constants();
|
|
5867
6338
|
var urlBase64Helper = require_urlsafe_base64_helper();
|
|
5868
6339
|
/**
|
|
@@ -5913,7 +6384,7 @@ var require_vapid_helper = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
5913
6384
|
if (typeof subject !== "string" || subject.length === 0) throw new Error("The subject value must be a string containing an https: URL or mailto: address. " + subject);
|
|
5914
6385
|
let subjectParseResult = null;
|
|
5915
6386
|
try {
|
|
5916
|
-
subjectParseResult = new URL(subject);
|
|
6387
|
+
subjectParseResult = new URL$1(subject);
|
|
5917
6388
|
} catch (err) {
|
|
5918
6389
|
throw new Error("Vapid subject is not a valid URL. " + subject);
|
|
5919
6390
|
}
|
|
@@ -5975,7 +6446,7 @@ var require_vapid_helper = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
5975
6446
|
if (!audience) throw new Error("No audience could be generated for VAPID.");
|
|
5976
6447
|
if (typeof audience !== "string" || audience.length === 0) throw new Error("The audience value must be a string containing the origin of a push service. " + audience);
|
|
5977
6448
|
try {
|
|
5978
|
-
new URL(audience);
|
|
6449
|
+
new URL$1(audience);
|
|
5979
6450
|
} catch (err) {
|
|
5980
6451
|
throw new Error("VAPID audience is not a url. " + audience);
|
|
5981
6452
|
}
|
|
@@ -7606,7 +8077,7 @@ function publishChange(sessionId) {
|
|
|
7606
8077
|
const row = get("SELECT workspace_id FROM sessions WHERE id = ?", sessionId);
|
|
7607
8078
|
if (row?.workspace_id) {
|
|
7608
8079
|
const workspaceId = row.workspace_id;
|
|
7609
|
-
import("./
|
|
8080
|
+
import("./_DiOv9AKj.js").then((m) => m.notifySessionsChanged(workspaceId));
|
|
7610
8081
|
return;
|
|
7611
8082
|
}
|
|
7612
8083
|
publish("sessions.changed");
|
|
@@ -8549,7 +9020,7 @@ async function token() {
|
|
|
8549
9020
|
const fromHosts = hostsToken();
|
|
8550
9021
|
if (fromHosts) return fromHosts;
|
|
8551
9022
|
try {
|
|
8552
|
-
return await run$
|
|
9023
|
+
return await run$2("gh", ["auth", "token"]) || null;
|
|
8553
9024
|
} catch {
|
|
8554
9025
|
return null;
|
|
8555
9026
|
}
|
|
@@ -9843,7 +10314,7 @@ async function listPanesNow() {
|
|
|
9843
10314
|
* (tmux exits when its last session closes). */
|
|
9844
10315
|
async function ensureTmuxServer() {
|
|
9845
10316
|
if (await tmux(["has-session"]).then(() => true, () => false)) return;
|
|
9846
|
-
await run$
|
|
10317
|
+
await run$2("systemd-run", [
|
|
9847
10318
|
"--user",
|
|
9848
10319
|
`--unit=${TMUX_SOCKET === "work" ? "work-tmux" : `work-tmux-${TMUX_SOCKET.replace(/[^\w.:-]/g, "_")}`}`,
|
|
9849
10320
|
"--service-type=forking",
|
|
@@ -10115,4 +10586,4 @@ function sleep(ms) {
|
|
|
10115
10586
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
10116
10587
|
}
|
|
10117
10588
|
//#endregion
|
|
10118
|
-
export { saveSubscription as $,
|
|
10589
|
+
export { saveSubscription as $, shared as $t, clearAgentPhase as A, PROJECT_TOOLS as At, agentBadge as B, httpError as Bt, readHookPayload as C, miseVersions as Ct, realInsideSync as D, which as Dt, realInside as E, tilde as Et, onPhaseChange as F, toolById as Ft, ACCENT_RE as G, workspacePath as Gt, agentFromCommand as H, all as Ht, setAgentPhase as I, applyPrefChange as It, manifest as J, git as Jt, getInstance as K, TMUX_SOCKET as Kt, setScrapedPhase as L, FRAME_ANCESTORS as Lt, hookReportedAt as M, agentById as Mt, noteBackground as N, agentLabel$1 as Nt, blankRow as O, firewallProbe as Ot, noteUserAnswered as P, catalogPin as Pt, pushPublicKey as Q, config as Qt, setSessionViewers as R, FRAME_HEADERS as Rt, AGENTS as S, miseInstalls as St, inside as T, stableGh as Tt, agentLabel as U, db as Ut, agentFamily as V, readBody as Vt, agentMeta as W, get as Wt, setInstance as X, run$2 as Xt, normalizeAccent as Y, gitEnv as Yt, deleteSubscription as Z, tmux as Zt, renameSession as _, setPref as _t, ensureTmuxServer as a, subscriberCount as at, tmuxName as b, doctor as bt, killSession as c, agentChoices as ct, listPanesWithin as d, deleteWorkspacePrefs as dt, swr as en, sendPush as et, listSessions as f, disabledAgents as ft, panePids as g, setDisabledAgents as gt, notifySessionsChanged as h, preferredAgent as ht, disposeSessions as i, subscribe as it, hookPhase as j, TOOLS as jt, agentPhase as k, DEFAULT_GITHUB_HOST as kt, killWorkspaceSessions as l, allPrefs as lt, newSessionArgs as m, getSetting as mt, clearTmuxStarted as n, publish as nt, forgetPanes as o, PREF_MAX as ot, markTmuxStarted as p, enabledAgents as pt, iconSvg as q, gh as qt, createSession as r, publishJson as rt, getSession as s, WORKSPACE_PREFS as st, cleanEnv as t, withLock as tn, validSubscription as tt, listPanes as u, changePref as ut, sendToSession as v, setSetting as vt, reportsWorking as w, setupPath as wt, tmuxWasStarted as x, ghKnownHosts as xt, sessionStates as y, discoverAgents as yt, settleQuietWorking as z, checked as zt };
|