termdock 1.4.341 → 1.4.343
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/THIRD_PARTY_NOTICES.md +79 -0
- package/dist/client/assets/App-DCcTIZdf.js +187 -0
- package/dist/client/assets/App-DCcTIZdf.js.br +0 -0
- package/dist/client/assets/App-DCcTIZdf.js.gz +0 -0
- package/dist/client/assets/{ArchitecturePanel-Dz0hgSdw.js → ArchitecturePanel-CcBSZoe8.js} +2 -2
- package/dist/client/assets/ArchitecturePanel-CcBSZoe8.js.br +0 -0
- package/dist/client/assets/ArchitecturePanel-CcBSZoe8.js.gz +0 -0
- package/dist/client/assets/{ChangeWalkthroughPanel-3PpmA31G.js → ChangeWalkthroughPanel-CVL-Eoqi.js} +1 -1
- package/dist/client/assets/ChangeWalkthroughPanel-CVL-Eoqi.js.br +0 -0
- package/dist/client/assets/ChangeWalkthroughPanel-CVL-Eoqi.js.gz +0 -0
- package/dist/client/assets/{CollaborationMainWorkspace-QA7cyrcg.js → CollaborationMainWorkspace-BNR6meXy.js} +1 -1
- package/dist/client/assets/CollaborationMainWorkspace-BNR6meXy.js.br +0 -0
- package/dist/client/assets/CollaborationMainWorkspace-BNR6meXy.js.gz +0 -0
- package/dist/client/assets/CollaborationTaskContent-CJBA3EUR.js +2 -0
- package/dist/client/assets/{ComputerControlView-DfKdSvrs.js → ComputerControlView-D1cRpjbf.js} +3 -3
- package/dist/client/assets/ComputerControlView-D1cRpjbf.js.br +0 -0
- package/dist/client/assets/ComputerControlView-D1cRpjbf.js.gz +0 -0
- package/dist/client/assets/{DagPlayground-IFr1ujrl.js → DagPlayground-BjtiPvYD.js} +1 -1
- package/dist/client/assets/DagPlayground-BjtiPvYD.js.br +0 -0
- package/dist/client/assets/DagPlayground-BjtiPvYD.js.gz +0 -0
- package/dist/client/assets/{DiffLab-BSQmv0td.js → DiffLab-L76RA6ma.js} +1 -1
- package/dist/client/assets/DiffLab-L76RA6ma.js.br +0 -0
- package/dist/client/assets/DiffLab-L76RA6ma.js.gz +0 -0
- package/dist/client/assets/{DiffReview-CfHl0jeF.js → DiffReview-BZ6uHzt1.js} +1 -1
- package/dist/client/assets/DiffReview-BZ6uHzt1.js.br +0 -0
- package/dist/client/assets/DiffReview-BZ6uHzt1.js.gz +0 -0
- package/dist/client/assets/{DiffReviewLab-B_zSSqde.js → DiffReviewLab-B0tXcqaf.js} +1 -1
- package/dist/client/assets/DiffReviewLab-B0tXcqaf.js.br +0 -0
- package/dist/client/assets/DiffReviewLab-B0tXcqaf.js.gz +0 -0
- package/dist/client/assets/{DiffViewer-DORR0BUb.js → DiffViewer-ClFGIsxM.js} +1 -1
- package/dist/client/assets/DiffViewer-ClFGIsxM.js.br +0 -0
- package/dist/client/assets/DiffViewer-ClFGIsxM.js.gz +0 -0
- package/dist/client/assets/{ModelPreview-QdScJljR.js → ModelPreview-B3ETe5f9.js} +1 -1
- package/dist/client/assets/ModelPreview-B3ETe5f9.js.br +0 -0
- package/dist/client/assets/ModelPreview-B3ETe5f9.js.gz +0 -0
- package/dist/client/assets/{RightSidebar-nUsJCrB9.js → RightSidebar-BSp4sFCm.js} +3 -3
- package/dist/client/assets/RightSidebar-BSp4sFCm.js.br +0 -0
- package/dist/client/assets/RightSidebar-BSp4sFCm.js.gz +0 -0
- package/dist/client/assets/{abnfDiagram-VCTEODGH-B51uxXBg.js → abnfDiagram-VCTEODGH-BYfyqXgQ.js} +1 -1
- package/dist/client/assets/abnfDiagram-VCTEODGH-BYfyqXgQ.js.br +0 -0
- package/dist/client/assets/abnfDiagram-VCTEODGH-BYfyqXgQ.js.gz +0 -0
- package/dist/client/assets/app-C0jo989F.js +35 -0
- package/dist/client/assets/app-C0jo989F.js.br +0 -0
- package/dist/client/assets/app-C0jo989F.js.gz +0 -0
- package/dist/client/assets/{arc-Bkn10vSK.js → arc-DYMjtzAT.js} +1 -1
- package/dist/client/assets/arc-DYMjtzAT.js.br +0 -0
- package/dist/client/assets/arc-DYMjtzAT.js.gz +0 -0
- package/dist/client/assets/{architectureDiagram-5GKGNRK7-CK-cIr48.js → architectureDiagram-5GKGNRK7-937uLJdY.js} +1 -1
- package/dist/client/assets/architectureDiagram-5GKGNRK7-937uLJdY.js.br +0 -0
- package/dist/client/assets/architectureDiagram-5GKGNRK7-937uLJdY.js.gz +0 -0
- package/dist/client/assets/{blockDiagram-I7D4REHJ-DzbWXcDy.js → blockDiagram-I7D4REHJ-BjMVJVHv.js} +1 -1
- package/dist/client/assets/blockDiagram-I7D4REHJ-BjMVJVHv.js.br +0 -0
- package/dist/client/assets/blockDiagram-I7D4REHJ-BjMVJVHv.js.gz +0 -0
- package/dist/client/assets/{c4Diagram-7LVT6UL2-rbi8aUz6.js → c4Diagram-7LVT6UL2-DKr1q3YZ.js} +1 -1
- package/dist/client/assets/c4Diagram-7LVT6UL2-DKr1q3YZ.js.br +0 -0
- package/dist/client/assets/c4Diagram-7LVT6UL2-DKr1q3YZ.js.gz +0 -0
- package/dist/client/assets/channel-CxYS0D6E.js +1 -0
- package/dist/client/assets/{chunk-2Q5K7J3B-CopzhZr-.js → chunk-2Q5K7J3B-Cmbm422D.js} +1 -1
- package/dist/client/assets/{chunk-5VM5RSS4-ClLaQzHk.js → chunk-5VM5RSS4-Dlrrt5X6.js} +1 -1
- package/dist/client/assets/{chunk-F27PBJKO-BSC7rK0l.js → chunk-F27PBJKO-Brplur9W.js} +1 -1
- package/dist/client/assets/chunk-F27PBJKO-Brplur9W.js.br +0 -0
- package/dist/client/assets/chunk-F27PBJKO-Brplur9W.js.gz +0 -0
- package/dist/client/assets/{chunk-IMKFNOWR-B2VXoEhN.js → chunk-IMKFNOWR-DDH-xTd_.js} +1 -1
- package/dist/client/assets/chunk-IMKFNOWR-DDH-xTd_.js.br +0 -0
- package/dist/client/assets/chunk-IMKFNOWR-DDH-xTd_.js.gz +0 -0
- package/dist/client/assets/{chunk-JWPE2WC7-BqOinZdA.js → chunk-JWPE2WC7-C-fazXnV.js} +1 -1
- package/dist/client/assets/{chunk-POPQ4Y6H-CNE45B-7.js → chunk-POPQ4Y6H-BpvA5JQ8.js} +1 -1
- package/dist/client/assets/{chunk-SVP7TREG-f0h2wclt.js → chunk-SVP7TREG-DEGdY0iE.js} +1 -1
- package/dist/client/assets/chunk-SVP7TREG-DEGdY0iE.js.br +0 -0
- package/dist/client/assets/chunk-SVP7TREG-DEGdY0iE.js.gz +0 -0
- package/dist/client/assets/{chunk-TICWLB2K-BLYE27kR.js → chunk-TICWLB2K-q48VhB5_.js} +1 -1
- package/dist/client/assets/chunk-TICWLB2K-q48VhB5_.js.br +0 -0
- package/dist/client/assets/chunk-TICWLB2K-q48VhB5_.js.gz +0 -0
- package/dist/client/assets/{chunk-XXDRQBXY-CVDDfXPc.js → chunk-XXDRQBXY-BUnK03xP.js} +1 -1
- package/dist/client/assets/classDiagram-ZZMXUADV-C7BzKXcX.js +1 -0
- package/dist/client/assets/classDiagram-v2-VYDZK3BY-C7BzKXcX.js +1 -0
- package/dist/client/assets/{cose-bilkent-JH36ORCC-64n9-rjs.js → cose-bilkent-JH36ORCC-CwORdR-o.js} +1 -1
- package/dist/client/assets/cose-bilkent-JH36ORCC-CwORdR-o.js.br +0 -0
- package/dist/client/assets/cose-bilkent-JH36ORCC-CwORdR-o.js.gz +0 -0
- package/dist/client/assets/{cynefin-OW5HDTMX-BQu4qBBj.js → cynefin-OW5HDTMX-C8zwrcdC.js} +1 -1
- package/dist/client/assets/cynefin-OW5HDTMX-C8zwrcdC.js.br +0 -0
- package/dist/client/assets/cynefin-OW5HDTMX-C8zwrcdC.js.gz +0 -0
- package/dist/client/assets/{cynefinDiagram-5FMLGOSQ-BnwaLoUi.js → cynefinDiagram-5FMLGOSQ-9TA7e2Jg.js} +1 -1
- package/dist/client/assets/cynefinDiagram-5FMLGOSQ-9TA7e2Jg.js.br +0 -0
- package/dist/client/assets/cynefinDiagram-5FMLGOSQ-9TA7e2Jg.js.gz +0 -0
- package/dist/client/assets/{dagre-GXQ25YYZ-CqFJh0CI.js → dagre-GXQ25YYZ-ozLbKQvR.js} +1 -1
- package/dist/client/assets/dagre-GXQ25YYZ-ozLbKQvR.js.br +0 -0
- package/dist/client/assets/dagre-GXQ25YYZ-ozLbKQvR.js.gz +0 -0
- package/dist/client/assets/{diagram-S7CK7UJ4-CbPoBysM.js → diagram-S7CK7UJ4-Bn4XhpI7.js} +1 -1
- package/dist/client/assets/diagram-S7CK7UJ4-Bn4XhpI7.js.br +0 -0
- package/dist/client/assets/diagram-S7CK7UJ4-Bn4XhpI7.js.gz +0 -0
- package/dist/client/assets/{diagram-UQ7AKVKN-BhBN4F33.js → diagram-UQ7AKVKN-tKpUsiXZ.js} +1 -1
- package/dist/client/assets/diagram-UQ7AKVKN-tKpUsiXZ.js.br +0 -0
- package/dist/client/assets/diagram-UQ7AKVKN-tKpUsiXZ.js.gz +0 -0
- package/dist/client/assets/{diagram-VSXAHHWV-eYeeGcK9.js → diagram-VSXAHHWV-0N9YA_4l.js} +1 -1
- package/dist/client/assets/diagram-VSXAHHWV-0N9YA_4l.js.br +0 -0
- package/dist/client/assets/diagram-VSXAHHWV-0N9YA_4l.js.gz +0 -0
- package/dist/client/assets/{diagram-VX7I27RA-BJzhPV4h.js → diagram-VX7I27RA-V2WFvWL0.js} +1 -1
- package/dist/client/assets/diagram-VX7I27RA-V2WFvWL0.js.br +0 -0
- package/dist/client/assets/diagram-VX7I27RA-V2WFvWL0.js.gz +0 -0
- package/dist/client/assets/{diagram-Z3DM3KII-CnjpNAJH.js → diagram-Z3DM3KII-50ixVRGU.js} +1 -1
- package/dist/client/assets/diagram-Z3DM3KII-50ixVRGU.js.br +0 -0
- package/dist/client/assets/diagram-Z3DM3KII-50ixVRGU.js.gz +0 -0
- package/dist/client/assets/{ebnfDiagram-PWID7BFC-BSJQBTtu.js → ebnfDiagram-PWID7BFC-DYdiLGfv.js} +1 -1
- package/dist/client/assets/ebnfDiagram-PWID7BFC-DYdiLGfv.js.br +0 -0
- package/dist/client/assets/ebnfDiagram-PWID7BFC-DYdiLGfv.js.gz +0 -0
- package/dist/client/assets/{erDiagram-RLTQ6QDP-DJ-J9MxE.js → erDiagram-RLTQ6QDP-Bglt3tsq.js} +1 -1
- package/dist/client/assets/{erDiagram-RLTQ6QDP-DJ-J9MxE.js.br → erDiagram-RLTQ6QDP-Bglt3tsq.js.br} +0 -0
- package/dist/client/assets/erDiagram-RLTQ6QDP-Bglt3tsq.js.gz +0 -0
- package/dist/client/assets/{flowDiagram-HODETNUW-BoQNTthC.js → flowDiagram-HODETNUW-QHE7V70K.js} +1 -1
- package/dist/client/assets/{flowDiagram-HODETNUW-BoQNTthC.js.br → flowDiagram-HODETNUW-QHE7V70K.js.br} +0 -0
- package/dist/client/assets/flowDiagram-HODETNUW-QHE7V70K.js.gz +0 -0
- package/dist/client/assets/{ganttDiagram-EL5Y4UJY-CFE98nzY.js → ganttDiagram-EL5Y4UJY-BiI1Cl0h.js} +1 -1
- package/dist/client/assets/{ganttDiagram-EL5Y4UJY-CFE98nzY.js.br → ganttDiagram-EL5Y4UJY-BiI1Cl0h.js.br} +0 -0
- package/dist/client/assets/ganttDiagram-EL5Y4UJY-BiI1Cl0h.js.gz +0 -0
- package/dist/client/assets/{gestureArbiter-C_3fpCXt.js → gestureArbiter-DMJfCd7R.js} +1 -1
- package/dist/client/assets/gestureArbiter-DMJfCd7R.js.br +0 -0
- package/dist/client/assets/gestureArbiter-DMJfCd7R.js.gz +0 -0
- package/dist/client/assets/{gitGraphDiagram-WWUBYQGX-DxJzGDIE.js → gitGraphDiagram-WWUBYQGX-BDh5xzL0.js} +1 -1
- package/dist/client/assets/gitGraphDiagram-WWUBYQGX-BDh5xzL0.js.br +0 -0
- package/dist/client/assets/gitGraphDiagram-WWUBYQGX-BDh5xzL0.js.gz +0 -0
- package/dist/client/assets/{infoDiagram-27XIBGKW-BZk87iJj.js → infoDiagram-27XIBGKW-BwRQvwVT.js} +1 -1
- package/dist/client/assets/{ishikawaDiagram-5VMMS53U-DVsj1R9s.js → ishikawaDiagram-5VMMS53U-D-XGlyHD.js} +1 -1
- package/dist/client/assets/ishikawaDiagram-5VMMS53U-D-XGlyHD.js.br +0 -0
- package/dist/client/assets/ishikawaDiagram-5VMMS53U-D-XGlyHD.js.gz +0 -0
- package/dist/client/assets/{journeyDiagram-3NMN7TZE-BAB2AWNl.js → journeyDiagram-3NMN7TZE-TVJdFmZO.js} +1 -1
- package/dist/client/assets/journeyDiagram-3NMN7TZE-TVJdFmZO.js.br +0 -0
- package/dist/client/assets/journeyDiagram-3NMN7TZE-TVJdFmZO.js.gz +0 -0
- package/dist/client/assets/{kanban-definition-UXKFOSKX-HPNzrFVI.js → kanban-definition-UXKFOSKX-BNKbii3u.js} +1 -1
- package/dist/client/assets/kanban-definition-UXKFOSKX-BNKbii3u.js.br +0 -0
- package/dist/client/assets/kanban-definition-UXKFOSKX-BNKbii3u.js.gz +0 -0
- package/dist/client/assets/{layout-bA7IPCWx.js → layout-BnxQZMpY.js} +1 -1
- package/dist/client/assets/layout-BnxQZMpY.js.br +0 -0
- package/dist/client/assets/{layout-bA7IPCWx.js.gz → layout-BnxQZMpY.js.gz} +0 -0
- package/dist/client/assets/{linear-Cd102271.js → linear-99NBGeCC.js} +1 -1
- package/dist/client/assets/linear-99NBGeCC.js.br +0 -0
- package/dist/client/assets/linear-99NBGeCC.js.gz +0 -0
- package/dist/client/assets/{mermaid.core-C4wd6qUT.js → mermaid.core-CmwfcYZ2.js} +5 -5
- package/dist/client/assets/mermaid.core-CmwfcYZ2.js.br +0 -0
- package/dist/client/assets/mermaid.core-CmwfcYZ2.js.gz +0 -0
- package/dist/client/assets/{mindmap-definition-YA3MSWOX-DMxZDI3z.js → mindmap-definition-YA3MSWOX-BZI6wimw.js} +1 -1
- package/dist/client/assets/mindmap-definition-YA3MSWOX-BZI6wimw.js.br +0 -0
- package/dist/client/assets/mindmap-definition-YA3MSWOX-BZI6wimw.js.gz +0 -0
- package/dist/client/assets/{passwordBootstrap-aU8HdPsL.js → passwordBootstrap-cQk2qdyF.js} +1 -1
- package/dist/client/assets/passwordBootstrap-cQk2qdyF.js.br +0 -0
- package/dist/client/assets/passwordBootstrap-cQk2qdyF.js.gz +0 -0
- package/dist/client/assets/{pegDiagram-XKGWAZYB-BliPfrj_.js → pegDiagram-XKGWAZYB-Ck6_UJCc.js} +1 -1
- package/dist/client/assets/pegDiagram-XKGWAZYB-Ck6_UJCc.js.br +0 -0
- package/dist/client/assets/pegDiagram-XKGWAZYB-Ck6_UJCc.js.gz +0 -0
- package/dist/client/assets/{pieDiagram-E7YTZNPT-esWyI6AY.js → pieDiagram-E7YTZNPT-uSt3JkUn.js} +1 -1
- package/dist/client/assets/pieDiagram-E7YTZNPT-uSt3JkUn.js.br +0 -0
- package/dist/client/assets/pieDiagram-E7YTZNPT-uSt3JkUn.js.gz +0 -0
- package/dist/client/assets/{quadrantDiagram-AXDQQJYC-CBoaEIHy.js → quadrantDiagram-AXDQQJYC-BRXYZ2tD.js} +1 -1
- package/dist/client/assets/quadrantDiagram-AXDQQJYC-BRXYZ2tD.js.br +0 -0
- package/dist/client/assets/{quadrantDiagram-AXDQQJYC-CBoaEIHy.js.gz → quadrantDiagram-AXDQQJYC-BRXYZ2tD.js.gz} +0 -0
- package/dist/client/assets/{railroadDiagram-O6MQD6OU-FB5bPmYm.js → railroadDiagram-O6MQD6OU-D6_tYmbg.js} +1 -1
- package/dist/client/assets/railroadDiagram-O6MQD6OU-D6_tYmbg.js.br +0 -0
- package/dist/client/assets/railroadDiagram-O6MQD6OU-D6_tYmbg.js.gz +0 -0
- package/dist/client/assets/{rdpSession-DnBdxkm1.js → rdpSession-rdarsKgF.js} +1 -1
- package/dist/client/assets/rdpSession-rdarsKgF.js.br +0 -0
- package/dist/client/assets/rdpSession-rdarsKgF.js.gz +0 -0
- package/dist/client/assets/{referenceLongPress-DDmic9E5.js → referenceLongPress-DttwS3Pz.js} +1 -1
- package/dist/client/assets/referenceLongPress-DttwS3Pz.js.br +0 -0
- package/dist/client/assets/referenceLongPress-DttwS3Pz.js.gz +0 -0
- package/dist/client/assets/{requirementDiagram-BXWQKSXE-CpokwhJY.js → requirementDiagram-BXWQKSXE-CLY6zGmG.js} +1 -1
- package/dist/client/assets/requirementDiagram-BXWQKSXE-CLY6zGmG.js.br +0 -0
- package/dist/client/assets/requirementDiagram-BXWQKSXE-CLY6zGmG.js.gz +0 -0
- package/dist/client/assets/{sankeyDiagram-P5KCCOFB-DXQDOMAh.js → sankeyDiagram-P5KCCOFB-CiFyFj6p.js} +1 -1
- package/dist/client/assets/sankeyDiagram-P5KCCOFB-CiFyFj6p.js.br +0 -0
- package/dist/client/assets/sankeyDiagram-P5KCCOFB-CiFyFj6p.js.gz +0 -0
- package/dist/client/assets/{sequenceDiagram-WJ2MYXX4-Dn3ZooAM.js → sequenceDiagram-WJ2MYXX4-DgI6wvE8.js} +1 -1
- package/dist/client/assets/sequenceDiagram-WJ2MYXX4-DgI6wvE8.js.br +0 -0
- package/dist/client/assets/sequenceDiagram-WJ2MYXX4-DgI6wvE8.js.gz +0 -0
- package/dist/client/assets/{sizeCapture-INFHLROL-PItE9Y1o.js → sizeCapture-INFHLROL-D89Tnq0d.js} +1 -1
- package/dist/client/assets/sizeCapture-INFHLROL-D89Tnq0d.js.br +0 -0
- package/dist/client/assets/sizeCapture-INFHLROL-D89Tnq0d.js.gz +0 -0
- package/dist/client/assets/{sparkles-BwY5qEOv.js → sparkles-BpY-2ThK.js} +1 -1
- package/dist/client/assets/{stateDiagram-D77RDMKH-BBZ01SXU.js → stateDiagram-D77RDMKH-DSRJvuE3.js} +1 -1
- package/dist/client/assets/stateDiagram-D77RDMKH-DSRJvuE3.js.br +0 -0
- package/dist/client/assets/stateDiagram-D77RDMKH-DSRJvuE3.js.gz +0 -0
- package/dist/client/assets/stateDiagram-v2-MP3YSRHH-D2I-nExx.js +1 -0
- package/dist/client/assets/{swimlanes-42K2YHIH-BY8IlbkR.js → swimlanes-42K2YHIH-D4d-t4OI.js} +1 -1
- package/dist/client/assets/swimlanes-42K2YHIH-D4d-t4OI.js.br +0 -0
- package/dist/client/assets/swimlanes-42K2YHIH-D4d-t4OI.js.gz +0 -0
- package/dist/client/assets/swimlanesDiagram-VR7AAH4N-BGk-TIBO.js +8 -0
- package/dist/client/assets/{timeline-definition-24CTP7MA-DyY9g2Hx.js → timeline-definition-24CTP7MA-BfC0WOSw.js} +1 -1
- package/dist/client/assets/timeline-definition-24CTP7MA-BfC0WOSw.js.br +0 -0
- package/dist/client/assets/timeline-definition-24CTP7MA-BfC0WOSw.js.gz +0 -0
- package/dist/client/assets/{triangle-alert-qb3d0Svx.js → triangle-alert-Bzc3OC00.js} +1 -1
- package/dist/client/assets/{vennDiagram-4TSXK5OY-Dy0PQ4-U.js → vennDiagram-4TSXK5OY-DV39_9aM.js} +1 -1
- package/dist/client/assets/vennDiagram-4TSXK5OY-DV39_9aM.js.br +0 -0
- package/dist/client/assets/vennDiagram-4TSXK5OY-DV39_9aM.js.gz +0 -0
- package/dist/client/assets/{videoCompression-BDNHhfKS.js → videoCompression-uaFA6Wsb.js} +1 -1
- package/dist/client/assets/videoCompression-uaFA6Wsb.js.br +0 -0
- package/dist/client/assets/videoCompression-uaFA6Wsb.js.gz +0 -0
- package/dist/client/assets/{wardleyDiagram-VM6X3IG4-DtBEPD3N.js → wardleyDiagram-VM6X3IG4-9l8pnAY8.js} +1 -1
- package/dist/client/assets/wardleyDiagram-VM6X3IG4-9l8pnAY8.js.br +0 -0
- package/dist/client/assets/wardleyDiagram-VM6X3IG4-9l8pnAY8.js.gz +0 -0
- package/dist/client/assets/{xychartDiagram-S5SC5T6Z-B2K1XjDQ.js → xychartDiagram-S5SC5T6Z-BnOVO5Js.js} +1 -1
- package/dist/client/assets/xychartDiagram-S5SC5T6Z-BnOVO5Js.js.br +0 -0
- package/dist/client/assets/xychartDiagram-S5SC5T6Z-BnOVO5Js.js.gz +0 -0
- package/dist/client/index.html +1 -1
- package/dist/client/index.html.br +0 -0
- package/dist/client/index.html.gz +0 -0
- package/dist/client/sw-encrypted-background.js +1 -1
- package/dist/client/sw-encrypted-background.js.br +0 -0
- package/dist/client/sw-encrypted-background.js.gz +0 -0
- package/dist/client/sw.js +1 -1
- package/dist/client/sw.js.br +0 -0
- package/dist/client/sw.js.gz +0 -0
- package/dist/server/entry.js +29 -20
- package/dist/server/federation/binaryPacket.js +28 -0
- package/dist/server/federation/packets.js +53 -7
- package/dist/server/federation/recordCompression.js +59 -0
- package/dist/server/federation/runtime.js +39 -37
- package/dist/server/federation/streamDuplex.js +62 -0
- package/dist/server/federation/transferWindow.js +50 -0
- package/dist/server/federation/webTransportCertificate.js +52 -0
- package/dist/server/federation/webTransportProtocol.js +25 -0
- package/dist/server/federation/webTransportServer.js +142 -0
- package/dist/server/routes/terminal.js +28 -16
- package/dist/server/utils/terminalInputQueue.js +57 -0
- package/package.json +7 -1
- package/runtime-manifest.json +4 -4
- package/dist/client/assets/App-Bs90VDwF.js +0 -187
- package/dist/client/assets/App-Bs90VDwF.js.br +0 -0
- package/dist/client/assets/App-Bs90VDwF.js.gz +0 -0
- package/dist/client/assets/ArchitecturePanel-Dz0hgSdw.js.br +0 -0
- package/dist/client/assets/ArchitecturePanel-Dz0hgSdw.js.gz +0 -0
- package/dist/client/assets/ChangeWalkthroughPanel-3PpmA31G.js.br +0 -0
- package/dist/client/assets/ChangeWalkthroughPanel-3PpmA31G.js.gz +0 -0
- package/dist/client/assets/CollaborationMainWorkspace-QA7cyrcg.js.br +0 -0
- package/dist/client/assets/CollaborationMainWorkspace-QA7cyrcg.js.gz +0 -0
- package/dist/client/assets/CollaborationTaskContent-Bjkxb7UF.js +0 -2
- package/dist/client/assets/ComputerControlView-DfKdSvrs.js.br +0 -0
- package/dist/client/assets/ComputerControlView-DfKdSvrs.js.gz +0 -0
- package/dist/client/assets/DagPlayground-IFr1ujrl.js.br +0 -0
- package/dist/client/assets/DagPlayground-IFr1ujrl.js.gz +0 -0
- package/dist/client/assets/DiffLab-BSQmv0td.js.br +0 -0
- package/dist/client/assets/DiffLab-BSQmv0td.js.gz +0 -0
- package/dist/client/assets/DiffReview-CfHl0jeF.js.br +0 -0
- package/dist/client/assets/DiffReview-CfHl0jeF.js.gz +0 -0
- package/dist/client/assets/DiffReviewLab-B_zSSqde.js.br +0 -0
- package/dist/client/assets/DiffReviewLab-B_zSSqde.js.gz +0 -0
- package/dist/client/assets/DiffViewer-DORR0BUb.js.br +0 -0
- package/dist/client/assets/DiffViewer-DORR0BUb.js.gz +0 -0
- package/dist/client/assets/ModelPreview-QdScJljR.js.br +0 -0
- package/dist/client/assets/ModelPreview-QdScJljR.js.gz +0 -0
- package/dist/client/assets/RightSidebar-nUsJCrB9.js.br +0 -0
- package/dist/client/assets/RightSidebar-nUsJCrB9.js.gz +0 -0
- package/dist/client/assets/abnfDiagram-VCTEODGH-B51uxXBg.js.br +0 -0
- package/dist/client/assets/abnfDiagram-VCTEODGH-B51uxXBg.js.gz +0 -0
- package/dist/client/assets/app-DIurxlSe.js +0 -35
- package/dist/client/assets/app-DIurxlSe.js.br +0 -0
- package/dist/client/assets/app-DIurxlSe.js.gz +0 -0
- package/dist/client/assets/arc-Bkn10vSK.js.br +0 -0
- package/dist/client/assets/arc-Bkn10vSK.js.gz +0 -0
- package/dist/client/assets/architectureDiagram-5GKGNRK7-CK-cIr48.js.br +0 -0
- package/dist/client/assets/architectureDiagram-5GKGNRK7-CK-cIr48.js.gz +0 -0
- package/dist/client/assets/blockDiagram-I7D4REHJ-DzbWXcDy.js.br +0 -0
- package/dist/client/assets/blockDiagram-I7D4REHJ-DzbWXcDy.js.gz +0 -0
- package/dist/client/assets/c4Diagram-7LVT6UL2-rbi8aUz6.js.br +0 -0
- package/dist/client/assets/c4Diagram-7LVT6UL2-rbi8aUz6.js.gz +0 -0
- package/dist/client/assets/channel-DWD77N0J.js +0 -1
- package/dist/client/assets/chunk-F27PBJKO-BSC7rK0l.js.br +0 -0
- package/dist/client/assets/chunk-F27PBJKO-BSC7rK0l.js.gz +0 -0
- package/dist/client/assets/chunk-IMKFNOWR-B2VXoEhN.js.br +0 -0
- package/dist/client/assets/chunk-IMKFNOWR-B2VXoEhN.js.gz +0 -0
- package/dist/client/assets/chunk-SVP7TREG-f0h2wclt.js.br +0 -0
- package/dist/client/assets/chunk-SVP7TREG-f0h2wclt.js.gz +0 -0
- package/dist/client/assets/chunk-TICWLB2K-BLYE27kR.js.br +0 -0
- package/dist/client/assets/chunk-TICWLB2K-BLYE27kR.js.gz +0 -0
- package/dist/client/assets/classDiagram-ZZMXUADV-BPUOP6TD.js +0 -1
- package/dist/client/assets/classDiagram-v2-VYDZK3BY-BPUOP6TD.js +0 -1
- package/dist/client/assets/cose-bilkent-JH36ORCC-64n9-rjs.js.br +0 -0
- package/dist/client/assets/cose-bilkent-JH36ORCC-64n9-rjs.js.gz +0 -0
- package/dist/client/assets/cynefin-OW5HDTMX-BQu4qBBj.js.br +0 -0
- package/dist/client/assets/cynefin-OW5HDTMX-BQu4qBBj.js.gz +0 -0
- package/dist/client/assets/cynefinDiagram-5FMLGOSQ-BnwaLoUi.js.br +0 -0
- package/dist/client/assets/cynefinDiagram-5FMLGOSQ-BnwaLoUi.js.gz +0 -0
- package/dist/client/assets/dagre-GXQ25YYZ-CqFJh0CI.js.br +0 -0
- package/dist/client/assets/dagre-GXQ25YYZ-CqFJh0CI.js.gz +0 -0
- package/dist/client/assets/diagram-S7CK7UJ4-CbPoBysM.js.br +0 -0
- package/dist/client/assets/diagram-S7CK7UJ4-CbPoBysM.js.gz +0 -0
- package/dist/client/assets/diagram-UQ7AKVKN-BhBN4F33.js.br +0 -0
- package/dist/client/assets/diagram-UQ7AKVKN-BhBN4F33.js.gz +0 -0
- package/dist/client/assets/diagram-VSXAHHWV-eYeeGcK9.js.br +0 -0
- package/dist/client/assets/diagram-VSXAHHWV-eYeeGcK9.js.gz +0 -0
- package/dist/client/assets/diagram-VX7I27RA-BJzhPV4h.js.br +0 -0
- package/dist/client/assets/diagram-VX7I27RA-BJzhPV4h.js.gz +0 -0
- package/dist/client/assets/diagram-Z3DM3KII-CnjpNAJH.js.br +0 -0
- package/dist/client/assets/diagram-Z3DM3KII-CnjpNAJH.js.gz +0 -0
- package/dist/client/assets/ebnfDiagram-PWID7BFC-BSJQBTtu.js.br +0 -0
- package/dist/client/assets/ebnfDiagram-PWID7BFC-BSJQBTtu.js.gz +0 -0
- package/dist/client/assets/erDiagram-RLTQ6QDP-DJ-J9MxE.js.gz +0 -0
- package/dist/client/assets/flowDiagram-HODETNUW-BoQNTthC.js.gz +0 -0
- package/dist/client/assets/ganttDiagram-EL5Y4UJY-CFE98nzY.js.gz +0 -0
- package/dist/client/assets/gestureArbiter-C_3fpCXt.js.br +0 -0
- package/dist/client/assets/gestureArbiter-C_3fpCXt.js.gz +0 -0
- package/dist/client/assets/gitGraphDiagram-WWUBYQGX-DxJzGDIE.js.br +0 -0
- package/dist/client/assets/gitGraphDiagram-WWUBYQGX-DxJzGDIE.js.gz +0 -0
- package/dist/client/assets/ishikawaDiagram-5VMMS53U-DVsj1R9s.js.br +0 -0
- package/dist/client/assets/ishikawaDiagram-5VMMS53U-DVsj1R9s.js.gz +0 -0
- package/dist/client/assets/journeyDiagram-3NMN7TZE-BAB2AWNl.js.br +0 -0
- package/dist/client/assets/journeyDiagram-3NMN7TZE-BAB2AWNl.js.gz +0 -0
- package/dist/client/assets/kanban-definition-UXKFOSKX-HPNzrFVI.js.br +0 -0
- package/dist/client/assets/kanban-definition-UXKFOSKX-HPNzrFVI.js.gz +0 -0
- package/dist/client/assets/layout-bA7IPCWx.js.br +0 -0
- package/dist/client/assets/linear-Cd102271.js.br +0 -0
- package/dist/client/assets/linear-Cd102271.js.gz +0 -0
- package/dist/client/assets/mermaid.core-C4wd6qUT.js.br +0 -0
- package/dist/client/assets/mermaid.core-C4wd6qUT.js.gz +0 -0
- package/dist/client/assets/mindmap-definition-YA3MSWOX-DMxZDI3z.js.br +0 -0
- package/dist/client/assets/mindmap-definition-YA3MSWOX-DMxZDI3z.js.gz +0 -0
- package/dist/client/assets/passwordBootstrap-aU8HdPsL.js.br +0 -0
- package/dist/client/assets/passwordBootstrap-aU8HdPsL.js.gz +0 -0
- package/dist/client/assets/pegDiagram-XKGWAZYB-BliPfrj_.js.br +0 -0
- package/dist/client/assets/pegDiagram-XKGWAZYB-BliPfrj_.js.gz +0 -0
- package/dist/client/assets/pieDiagram-E7YTZNPT-esWyI6AY.js.br +0 -0
- package/dist/client/assets/pieDiagram-E7YTZNPT-esWyI6AY.js.gz +0 -0
- package/dist/client/assets/quadrantDiagram-AXDQQJYC-CBoaEIHy.js.br +0 -0
- package/dist/client/assets/railroadDiagram-O6MQD6OU-FB5bPmYm.js.br +0 -0
- package/dist/client/assets/railroadDiagram-O6MQD6OU-FB5bPmYm.js.gz +0 -0
- package/dist/client/assets/rdpSession-DnBdxkm1.js.br +0 -0
- package/dist/client/assets/rdpSession-DnBdxkm1.js.gz +0 -0
- package/dist/client/assets/referenceLongPress-DDmic9E5.js.br +0 -0
- package/dist/client/assets/referenceLongPress-DDmic9E5.js.gz +0 -0
- package/dist/client/assets/requirementDiagram-BXWQKSXE-CpokwhJY.js.br +0 -0
- package/dist/client/assets/requirementDiagram-BXWQKSXE-CpokwhJY.js.gz +0 -0
- package/dist/client/assets/sankeyDiagram-P5KCCOFB-DXQDOMAh.js.br +0 -0
- package/dist/client/assets/sankeyDiagram-P5KCCOFB-DXQDOMAh.js.gz +0 -0
- package/dist/client/assets/sequenceDiagram-WJ2MYXX4-Dn3ZooAM.js.br +0 -0
- package/dist/client/assets/sequenceDiagram-WJ2MYXX4-Dn3ZooAM.js.gz +0 -0
- package/dist/client/assets/sizeCapture-INFHLROL-PItE9Y1o.js.br +0 -0
- package/dist/client/assets/sizeCapture-INFHLROL-PItE9Y1o.js.gz +0 -0
- package/dist/client/assets/stateDiagram-D77RDMKH-BBZ01SXU.js.br +0 -0
- package/dist/client/assets/stateDiagram-D77RDMKH-BBZ01SXU.js.gz +0 -0
- package/dist/client/assets/stateDiagram-v2-MP3YSRHH-BHm-8VYK.js +0 -1
- package/dist/client/assets/swimlanes-42K2YHIH-BY8IlbkR.js.br +0 -0
- package/dist/client/assets/swimlanes-42K2YHIH-BY8IlbkR.js.gz +0 -0
- package/dist/client/assets/swimlanesDiagram-VR7AAH4N-BuCvfzGX.js +0 -8
- package/dist/client/assets/timeline-definition-24CTP7MA-DyY9g2Hx.js.br +0 -0
- package/dist/client/assets/timeline-definition-24CTP7MA-DyY9g2Hx.js.gz +0 -0
- package/dist/client/assets/vennDiagram-4TSXK5OY-Dy0PQ4-U.js.br +0 -0
- package/dist/client/assets/vennDiagram-4TSXK5OY-Dy0PQ4-U.js.gz +0 -0
- package/dist/client/assets/videoCompression-BDNHhfKS.js.br +0 -0
- package/dist/client/assets/videoCompression-BDNHhfKS.js.gz +0 -0
- package/dist/client/assets/wardleyDiagram-VM6X3IG4-DtBEPD3N.js.br +0 -0
- package/dist/client/assets/wardleyDiagram-VM6X3IG4-DtBEPD3N.js.gz +0 -0
- package/dist/client/assets/xychartDiagram-S5SC5T6Z-B2K1XjDQ.js.br +0 -0
- package/dist/client/assets/xychartDiagram-S5SC5T6Z-B2K1XjDQ.js.gz +0 -0
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/** Application flow control inside Noise. Old peers retain one chunk in flight. */
|
|
2
|
+
export const TRANSFER_CHUNK_BYTES = 64 * 1024;
|
|
3
|
+
export const MAX_TRANSFER_WINDOW = 8;
|
|
4
|
+
export function transferWindow(value) {
|
|
5
|
+
return typeof value === 'number' && Number.isSafeInteger(value) && value >= 1
|
|
6
|
+
? Math.min(value, MAX_TRANSFER_WINDOW) : 1;
|
|
7
|
+
}
|
|
8
|
+
/** One producer and ordered acknowledgements; unsolicited ACKs grant no credit. */
|
|
9
|
+
export class TransferWindow {
|
|
10
|
+
limit;
|
|
11
|
+
signal;
|
|
12
|
+
outstanding = 0;
|
|
13
|
+
wake;
|
|
14
|
+
constructor(limit, signal) {
|
|
15
|
+
this.limit = limit;
|
|
16
|
+
this.signal = signal;
|
|
17
|
+
}
|
|
18
|
+
sent() {
|
|
19
|
+
if (this.outstanding >= this.limit)
|
|
20
|
+
throw new Error('Transfer window exceeded');
|
|
21
|
+
this.outstanding++;
|
|
22
|
+
}
|
|
23
|
+
acknowledge() {
|
|
24
|
+
if (this.outstanding === 0)
|
|
25
|
+
return;
|
|
26
|
+
this.outstanding--;
|
|
27
|
+
this.wake?.();
|
|
28
|
+
}
|
|
29
|
+
async wait(drained = false) {
|
|
30
|
+
while (true) {
|
|
31
|
+
if (this.signal.aborted)
|
|
32
|
+
throw this.signal.reason ?? new Error('CANCELLED');
|
|
33
|
+
if (this.outstanding < (drained ? 1 : this.limit))
|
|
34
|
+
return;
|
|
35
|
+
await new Promise((resolve, reject) => {
|
|
36
|
+
const cleanup = () => {
|
|
37
|
+
clearTimeout(timer);
|
|
38
|
+
this.signal.removeEventListener('abort', abort);
|
|
39
|
+
this.wake = undefined;
|
|
40
|
+
};
|
|
41
|
+
const abort = () => { cleanup(); reject(this.signal.reason ?? new Error('CANCELLED')); };
|
|
42
|
+
const timer = setTimeout(() => { cleanup(); reject(new Error('CONSUMER_TIMEOUT')); }, 30_000);
|
|
43
|
+
this.wake = () => { cleanup(); resolve(); };
|
|
44
|
+
this.signal.addEventListener('abort', abort, { once: true });
|
|
45
|
+
if (this.signal.aborted)
|
|
46
|
+
abort();
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { X509Certificate, createPrivateKey, createPublicKey, randomBytes, webcrypto } from 'node:crypto';
|
|
2
|
+
import { readFile, writeFile, rename, chmod, mkdir, unlink } from 'node:fs/promises';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
function inspect(value, now) {
|
|
5
|
+
const cert = new X509Certificate(value.cert);
|
|
6
|
+
const key = createPrivateKey(value.key);
|
|
7
|
+
if (key.asymmetricKeyType !== 'ec' || key.asymmetricKeyDetails?.namedCurve !== 'prime256v1'
|
|
8
|
+
|| !createPublicKey(key).export({ type: 'spki', format: 'der' }).equals(cert.publicKey.export({ type: 'spki', format: 'der' })))
|
|
9
|
+
throw new Error('Invalid QUIC certificate key');
|
|
10
|
+
const expiresAt = Date.parse(cert.validTo), startsAt = Date.parse(cert.validFrom);
|
|
11
|
+
if (!Number.isFinite(expiresAt) || startsAt > now || expiresAt - startsAt > 14 * 86400_000 || expiresAt < now + 2 * 86400_000)
|
|
12
|
+
throw new Error('QUIC certificate needs renewal');
|
|
13
|
+
return { ...value, hash: cert.fingerprint256.replaceAll(':', '').toLowerCase(), expiresAt };
|
|
14
|
+
}
|
|
15
|
+
/** Browsers require short-lived ECDSA certificates for hash-pinned QUIC.
|
|
16
|
+
* Their public hash is delivered through the already authenticated Noise link;
|
|
17
|
+
* the normal HTTPS certificate/CA is unchanged. */
|
|
18
|
+
export async function transportCertificate(directory, now = Date.now()) {
|
|
19
|
+
await mkdir(directory, { recursive: true, mode: 0o700 });
|
|
20
|
+
const file = join(directory, 'quic-certificate.json');
|
|
21
|
+
try {
|
|
22
|
+
const stored = JSON.parse(await readFile(file, 'utf8'));
|
|
23
|
+
const result = inspect(stored, now);
|
|
24
|
+
await chmod(file, 0o600);
|
|
25
|
+
return result;
|
|
26
|
+
}
|
|
27
|
+
catch { /* Missing, invalid or expiring certificates are replaced atomically. */ }
|
|
28
|
+
await import('reflect-metadata');
|
|
29
|
+
const x509 = await import('@peculiar/x509');
|
|
30
|
+
const keys = await webcrypto.subtle.generateKey({ name: 'ECDSA', namedCurve: 'P-256' }, true, ['sign', 'verify']);
|
|
31
|
+
const cert = await x509.X509CertificateGenerator.createSelfSigned({
|
|
32
|
+
serialNumber: randomBytes(16).toString('hex'), name: 'CN=Termdock QUIC',
|
|
33
|
+
notBefore: new Date(now - 60_000), notAfter: new Date(now + 13 * 86400_000),
|
|
34
|
+
signingAlgorithm: { name: 'ECDSA', hash: 'SHA-256' }, keys: keys,
|
|
35
|
+
extensions: [new x509.BasicConstraintsExtension(false), new x509.SubjectAlternativeNameExtension([
|
|
36
|
+
{ type: 'dns', value: 'localhost' }, { type: 'ip', value: '127.0.0.1' }, { type: 'ip', value: '::1' },
|
|
37
|
+
])],
|
|
38
|
+
}, webcrypto);
|
|
39
|
+
const exported = Buffer.from(await webcrypto.subtle.exportKey('pkcs8', keys.privateKey));
|
|
40
|
+
const key = `-----BEGIN PRIVATE KEY-----\n${exported.toString('base64').match(/.{1,64}/g).join('\n')}\n-----END PRIVATE KEY-----\n`;
|
|
41
|
+
const value = { cert: cert.toString('pem'), key };
|
|
42
|
+
const temp = `${file}.${randomBytes(8).toString('hex')}.tmp`;
|
|
43
|
+
try {
|
|
44
|
+
await writeFile(temp, JSON.stringify(value), { mode: 0o600, flag: 'wx' });
|
|
45
|
+
await rename(temp, file);
|
|
46
|
+
}
|
|
47
|
+
catch (error) {
|
|
48
|
+
await unlink(temp).catch(() => { });
|
|
49
|
+
throw error;
|
|
50
|
+
}
|
|
51
|
+
return inspect(value, now);
|
|
52
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export const WEBTRANSPORT_PATH = '/api/federation/transport';
|
|
2
|
+
export const WEBTRANSPORT_CONNECT_TIMEOUT_MS = 4000;
|
|
3
|
+
export const WEBTRANSPORT_STREAM_TIMEOUT_MS = 4000;
|
|
4
|
+
export const WEBTRANSPORT_MAX_STREAMS = 128;
|
|
5
|
+
export function readWebTransportDescriptor(value, now = Date.now()) {
|
|
6
|
+
if (!value || typeof value !== 'object')
|
|
7
|
+
return;
|
|
8
|
+
const d = value;
|
|
9
|
+
if (d.version !== 1 || d.path !== WEBTRANSPORT_PATH || !Number.isSafeInteger(d.port) || d.port < 1 || d.port > 65535
|
|
10
|
+
|| typeof d.certificateHash !== 'string' || !/^[a-f0-9]{64}$/.test(d.certificateHash)
|
|
11
|
+
|| !Number.isSafeInteger(d.expiresAt) || d.expiresAt <= now || d.expiresAt > now + 14 * 86400_000)
|
|
12
|
+
return;
|
|
13
|
+
return { version: 1, path: WEBTRANSPORT_PATH, port: d.port, certificateHash: d.certificateHash, expiresAt: d.expiresAt };
|
|
14
|
+
}
|
|
15
|
+
/** Cancel the operation, including late arrivals, rather than leaving a timed
|
|
16
|
+
* out stream/handshake attached to a live session. */
|
|
17
|
+
export async function abortable(promise, signal, cancel) {
|
|
18
|
+
return new Promise((resolve, reject) => {
|
|
19
|
+
const abort = () => { cancel(); reject(signal.reason ?? new Error('Transport aborted')); };
|
|
20
|
+
signal.addEventListener('abort', abort, { once: true });
|
|
21
|
+
void promise.then(value => { signal.removeEventListener('abort', abort); resolve(value); }, error => { signal.removeEventListener('abort', abort); reject(error); });
|
|
22
|
+
if (signal.aborted)
|
|
23
|
+
abort();
|
|
24
|
+
});
|
|
25
|
+
}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { randomBytes } from 'node:crypto';
|
|
2
|
+
import { streamDuplex } from './streamDuplex.js';
|
|
3
|
+
import { transportCertificate } from './webTransportCertificate.js';
|
|
4
|
+
import { WEBTRANSPORT_PATH, WEBTRANSPORT_MAX_STREAMS } from './webTransportProtocol.js';
|
|
5
|
+
export async function startWebTransportServer(options) {
|
|
6
|
+
// Optional native support must not become a static build/runtime dependency
|
|
7
|
+
// on platforms without a QUICHE binary. The upstream exports map also lacks
|
|
8
|
+
// a top-level TypeScript condition; keep our small adapter contract explicit.
|
|
9
|
+
const moduleName = '@fails-components/webtransport';
|
|
10
|
+
const implementation = await import(moduleName);
|
|
11
|
+
await implementation.quicheLoaded;
|
|
12
|
+
let certificate = await transportCertificate(options.directory);
|
|
13
|
+
const raw = new implementation.Http3Server({ host: options.host, port: options.port,
|
|
14
|
+
cert: certificate.cert, privKey: certificate.key, secret: randomBytes(32).toString('hex'),
|
|
15
|
+
initialStreamFlowControlWindow: 256 * 1024, initialSessionFlowControlWindow: 4 * 1024 * 1024,
|
|
16
|
+
streamShouldAutoTuneReceiveWindow: true, streamFlowControlWindowSizeLimit: 2 * 1024 * 1024,
|
|
17
|
+
sessionShouldAutoTuneReceiveWindow: true, sessionFlowControlWindowSizeLimit: 8 * 1024 * 1024,
|
|
18
|
+
initialBidirectionalReceiveStreams: WEBTRANSPORT_MAX_STREAMS,
|
|
19
|
+
});
|
|
20
|
+
const sessions = new Set();
|
|
21
|
+
const streams = new Set();
|
|
22
|
+
let stopped = false;
|
|
23
|
+
let nativeStopped = false;
|
|
24
|
+
let rotation;
|
|
25
|
+
const stopNative = () => {
|
|
26
|
+
if (nativeStopped)
|
|
27
|
+
return;
|
|
28
|
+
try {
|
|
29
|
+
raw.stopServer();
|
|
30
|
+
nativeStopped = true;
|
|
31
|
+
}
|
|
32
|
+
catch { /* Still initializing. */ }
|
|
33
|
+
};
|
|
34
|
+
const close = () => {
|
|
35
|
+
if (stopped)
|
|
36
|
+
return;
|
|
37
|
+
stopped = true;
|
|
38
|
+
clearInterval(rotation);
|
|
39
|
+
for (const stream of streams)
|
|
40
|
+
stream.close?.(new Error('QUIC server stopped'));
|
|
41
|
+
for (const session of sessions)
|
|
42
|
+
session.close({ closeCode: 0, reason: 'Service restarting' });
|
|
43
|
+
// Let RESET_STREAM / CONNECTION_CLOSE reach UDP before destroying the
|
|
44
|
+
// native socket. Closing it in the same turn strands peers until idle timeout.
|
|
45
|
+
const drain = () => { setTimeout(stopNative, 100).unref(); };
|
|
46
|
+
drain();
|
|
47
|
+
void raw.ready.then(drain, () => { });
|
|
48
|
+
};
|
|
49
|
+
raw.setRequestCallback(async ({ header }) => ({
|
|
50
|
+
path: WEBTRANSPORT_PATH,
|
|
51
|
+
status: !stopped && sessions.size < 64 && header[':path'] === WEBTRANSPORT_PATH
|
|
52
|
+
&& options.hostAllowed(header[':authority']) && options.originAllowed(header.origin, header[':authority']) ? 200 : 403,
|
|
53
|
+
}));
|
|
54
|
+
const incoming = raw.sessionStream(WEBTRANSPORT_PATH).getReader();
|
|
55
|
+
async function serve(session) {
|
|
56
|
+
if (stopped || sessions.size >= 64) {
|
|
57
|
+
session.close({ closeCode: 1, reason: 'Connection limit' });
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
sessions.add(session);
|
|
61
|
+
const own = new Set();
|
|
62
|
+
const cleanup = () => {
|
|
63
|
+
sessions.delete(session);
|
|
64
|
+
for (const duplex of own)
|
|
65
|
+
duplex.close?.(new Error('QUIC session closed'));
|
|
66
|
+
};
|
|
67
|
+
void session.closed.then(cleanup, cleanup);
|
|
68
|
+
await session.ready;
|
|
69
|
+
const reader = session.incomingBidirectionalStreams.getReader();
|
|
70
|
+
try {
|
|
71
|
+
while (!stopped) {
|
|
72
|
+
const { done, value } = await reader.read();
|
|
73
|
+
if (done)
|
|
74
|
+
return;
|
|
75
|
+
const duplex = streamDuplex(value);
|
|
76
|
+
if (own.size >= WEBTRANSPORT_MAX_STREAMS || streams.size >= 256) {
|
|
77
|
+
duplex.close?.(new Error('Stream limit'));
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
own.add(duplex);
|
|
81
|
+
streams.add(duplex);
|
|
82
|
+
const context = { allowOpenAccess: options.openAccessAllowed(session.header?.origin, session.header?.[':authority']), singleOperation: true };
|
|
83
|
+
void options.accept(duplex, context).catch(() => duplex.close?.(new Error('Secure stream failed')))
|
|
84
|
+
.finally(() => { own.delete(duplex); streams.delete(duplex); });
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
finally {
|
|
88
|
+
reader.releaseLock();
|
|
89
|
+
cleanup();
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
void (async () => {
|
|
93
|
+
try {
|
|
94
|
+
while (!stopped) {
|
|
95
|
+
const { done, value } = await incoming.read();
|
|
96
|
+
if (done)
|
|
97
|
+
return;
|
|
98
|
+
void serve(value).catch(() => value.close({ closeCode: 1, reason: 'Invalid stream' }));
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
catch { /* Native shutdown ends this reader. */ }
|
|
102
|
+
finally {
|
|
103
|
+
incoming.releaseLock();
|
|
104
|
+
}
|
|
105
|
+
})();
|
|
106
|
+
void raw.closed.then(close, close);
|
|
107
|
+
raw.startServer();
|
|
108
|
+
let timer;
|
|
109
|
+
try {
|
|
110
|
+
await Promise.race([raw.ready, new Promise((_resolve, reject) => { timer = setTimeout(() => reject(new Error('QUIC listener startup timed out')), 5000); })]);
|
|
111
|
+
const port = raw.address()?.port;
|
|
112
|
+
if (!port)
|
|
113
|
+
throw new Error('QUIC listener has no port');
|
|
114
|
+
rotation = setInterval(() => {
|
|
115
|
+
if (certificate.expiresAt > Date.now() + 3 * 86400_000)
|
|
116
|
+
return;
|
|
117
|
+
void transportCertificate(options.directory).then(next => {
|
|
118
|
+
if (stopped || next.hash === certificate.hash)
|
|
119
|
+
return;
|
|
120
|
+
raw.updateCert(next.cert, next.key, false);
|
|
121
|
+
certificate = next;
|
|
122
|
+
}).catch(() => { });
|
|
123
|
+
}, 60 * 60_000);
|
|
124
|
+
rotation.unref();
|
|
125
|
+
return {
|
|
126
|
+
close,
|
|
127
|
+
descriptor() {
|
|
128
|
+
return stopped || certificate.expiresAt <= Date.now() ? undefined : {
|
|
129
|
+
version: 1, port, path: WEBTRANSPORT_PATH, certificateHash: certificate.hash, expiresAt: certificate.expiresAt,
|
|
130
|
+
};
|
|
131
|
+
},
|
|
132
|
+
stats: () => ({ sessions: sessions.size, streams: streams.size }),
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
catch (error) {
|
|
136
|
+
close();
|
|
137
|
+
throw error;
|
|
138
|
+
}
|
|
139
|
+
finally {
|
|
140
|
+
clearTimeout(timer);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { TerminalInputQueue } from '../utils/terminalInputQueue.js';
|
|
1
2
|
import { copyTmuxSelection } from '../utils/tmuxCopySelection.js';
|
|
2
3
|
import { isConfirmedEmptyTmuxServer } from '../utils/tmuxEmptyServerProbe.js';
|
|
3
4
|
import { collaborationSessionDisplayName } from '../utils/sessionDisplayName.js';
|
|
@@ -9191,6 +9192,7 @@ export function handleTerminalWebSocket(ws, sessionId, clientId, options = {}, i
|
|
|
9191
9192
|
type: 'connected',
|
|
9192
9193
|
streamEpoch: TERMINAL_STREAM_EPOCH,
|
|
9193
9194
|
outputProtocol: options.flowControl ? 2 : undefined,
|
|
9195
|
+
copyModeInput: ownTmux,
|
|
9194
9196
|
cols: session.cols,
|
|
9195
9197
|
rows: session.rows,
|
|
9196
9198
|
runtime,
|
|
@@ -9265,6 +9267,20 @@ export function handleTerminalWebSocket(ws, sessionId, clientId, options = {}, i
|
|
|
9265
9267
|
ws.close(1008, 'Incomplete terminal paste');
|
|
9266
9268
|
}
|
|
9267
9269
|
});
|
|
9270
|
+
const inputQueue = new TerminalInputQueue(data => {
|
|
9271
|
+
session.lastActivity = Date.now();
|
|
9272
|
+
if (attachment)
|
|
9273
|
+
attachment.write(data);
|
|
9274
|
+
else if (session.mode === 'tmux')
|
|
9275
|
+
return enqueueTmuxIo(session, async () => { session.ptyProcess.write(data); });
|
|
9276
|
+
else
|
|
9277
|
+
session.ptyProcess.write(data);
|
|
9278
|
+
}, error => {
|
|
9279
|
+
if (ws.readyState !== ws.OPEN)
|
|
9280
|
+
return;
|
|
9281
|
+
ws.send(JSON.stringify({ type: 'error', error: error.message }));
|
|
9282
|
+
ws.close(1011, 'Terminal input preparation failed');
|
|
9283
|
+
});
|
|
9268
9284
|
// Handle client → server messages
|
|
9269
9285
|
ws.on('message', async (raw) => {
|
|
9270
9286
|
const messageReceivedAt = performance.now();
|
|
@@ -9288,22 +9304,17 @@ export function handleTerminalWebSocket(ws, sessionId, clientId, options = {}, i
|
|
|
9288
9304
|
ws.close(1008, 'Invalid terminal paste');
|
|
9289
9305
|
return;
|
|
9290
9306
|
}
|
|
9291
|
-
|
|
9292
|
-
|
|
9293
|
-
|
|
9294
|
-
|
|
9295
|
-
|
|
9296
|
-
|
|
9297
|
-
|
|
9298
|
-
|
|
9299
|
-
|
|
9300
|
-
|
|
9301
|
-
|
|
9302
|
-
else {
|
|
9303
|
-
session.lastActivity = Date.now();
|
|
9304
|
-
session.ptyProcess.write(data);
|
|
9305
|
-
}
|
|
9306
|
-
}
|
|
9307
|
+
const exitCopyMode = msg.exitCopyMode === true && session.mode === 'tmux' && !!session.tmuxSessionName;
|
|
9308
|
+
inputQueue.push(exitCopyMode && msg.data === '\x1b' ? [] : parts, exitCopyMode ? async () => {
|
|
9309
|
+
await enqueueTmuxIo(session, () => executeTmuxAction(session.tmuxSessionName, 'copy-mode', { enabled: false }, session.tmuxControl));
|
|
9310
|
+
// Preserve the confirmed copy-mode state for all observers without
|
|
9311
|
+
// holding the first key behind a layout query or a browser ACK.
|
|
9312
|
+
const target = session.tmuxSessionName;
|
|
9313
|
+
void getTmuxLayout(target).then(layout => {
|
|
9314
|
+
if (ws.readyState === ws.OPEN && session.tmuxSessionName === target)
|
|
9315
|
+
broadcastJsonWs(sessionId, { type: 'tmux-layout', layout });
|
|
9316
|
+
}).catch(() => { });
|
|
9317
|
+
} : undefined);
|
|
9307
9318
|
}
|
|
9308
9319
|
break;
|
|
9309
9320
|
}
|
|
@@ -9489,6 +9500,7 @@ export function handleTerminalWebSocket(ws, sessionId, clientId, options = {}, i
|
|
|
9489
9500
|
});
|
|
9490
9501
|
// Cleanup on close
|
|
9491
9502
|
ws.on('close', () => {
|
|
9503
|
+
inputQueue.close();
|
|
9492
9504
|
pasteInput.clear();
|
|
9493
9505
|
initialScreen?.cancel();
|
|
9494
9506
|
initialScreen = null;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/** Serializes a terminal's input with its optional server-side preparation.
|
|
2
|
+
* A slow preparation never permits later keys or paste segments to overtake it. */
|
|
3
|
+
export class TerminalInputQueue {
|
|
4
|
+
write;
|
|
5
|
+
failed;
|
|
6
|
+
items = [];
|
|
7
|
+
bytes = 0;
|
|
8
|
+
running = false;
|
|
9
|
+
stopped = false;
|
|
10
|
+
constructor(write, failed) {
|
|
11
|
+
this.write = write;
|
|
12
|
+
this.failed = failed;
|
|
13
|
+
}
|
|
14
|
+
push(data, before) {
|
|
15
|
+
if (this.stopped)
|
|
16
|
+
return;
|
|
17
|
+
const bytes = data.reduce((total, part) => total + Buffer.byteLength(part), 0);
|
|
18
|
+
if (this.items.length >= 256 || this.bytes + bytes > 1024 * 1024) {
|
|
19
|
+
this.fail(new Error('Terminal input queue exceeded its budget'));
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
this.items.push({ data, before, bytes });
|
|
23
|
+
this.bytes += bytes;
|
|
24
|
+
if (!this.running)
|
|
25
|
+
void this.drain();
|
|
26
|
+
}
|
|
27
|
+
close() { this.stopped = true; this.items = []; this.bytes = 0; }
|
|
28
|
+
fail(error) { this.close(); this.failed(error); }
|
|
29
|
+
async drain() {
|
|
30
|
+
this.running = true;
|
|
31
|
+
try {
|
|
32
|
+
while (!this.stopped && this.items.length) {
|
|
33
|
+
const item = this.items[0];
|
|
34
|
+
if (item.before)
|
|
35
|
+
await item.before();
|
|
36
|
+
for (const part of item.data) {
|
|
37
|
+
if (this.stopped)
|
|
38
|
+
return;
|
|
39
|
+
const result = this.write(part);
|
|
40
|
+
if (result)
|
|
41
|
+
await result;
|
|
42
|
+
}
|
|
43
|
+
if (this.stopped)
|
|
44
|
+
return;
|
|
45
|
+
this.items.shift();
|
|
46
|
+
this.bytes -= item.bytes;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
catch (error) {
|
|
50
|
+
if (!this.stopped)
|
|
51
|
+
this.fail(error instanceof Error ? error : new Error(String(error)));
|
|
52
|
+
}
|
|
53
|
+
finally {
|
|
54
|
+
this.running = false;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "termdock",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.343",
|
|
4
4
|
"description": "A complete web-based terminal application with modern UI",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": ".desktop-dist/main.js",
|
|
@@ -65,6 +65,7 @@
|
|
|
65
65
|
"@libp2p/utils": "7.0.7",
|
|
66
66
|
"@noble/hashes": "2.4.0",
|
|
67
67
|
"@novnc/novnc": "^1.7.0",
|
|
68
|
+
"@peculiar/x509": "2.2.0",
|
|
68
69
|
"@serenity-kit/opaque": "1.1.0",
|
|
69
70
|
"@types/cookie-parser": "^1.4.10",
|
|
70
71
|
"@types/csurf": "^1.11.5",
|
|
@@ -100,6 +101,7 @@
|
|
|
100
101
|
"react": "^18.2.0",
|
|
101
102
|
"react-diff-view": "^3.3.3",
|
|
102
103
|
"react-dom": "^18.2.0",
|
|
104
|
+
"reflect-metadata": "0.2.2",
|
|
103
105
|
"refractor": "^2.10.1",
|
|
104
106
|
"swiper": "^12.1.3",
|
|
105
107
|
"tailwind-merge": "^2.2.0",
|
|
@@ -167,5 +169,9 @@
|
|
|
167
169
|
},
|
|
168
170
|
"overrides": {
|
|
169
171
|
"prismjs": "^1.30.0"
|
|
172
|
+
},
|
|
173
|
+
"optionalDependencies": {
|
|
174
|
+
"@fails-components/webtransport": "1.6.11",
|
|
175
|
+
"@fails-components/webtransport-transport-http3-quiche": "1.6.11"
|
|
170
176
|
}
|
|
171
177
|
}
|
package/runtime-manifest.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
3
|
"packageName": "termdock",
|
|
4
|
-
"version": "1.4.
|
|
4
|
+
"version": "1.4.343",
|
|
5
5
|
"runtimeProtocolVersion": 1,
|
|
6
6
|
"minimumDesktopVersion": "1.4.46",
|
|
7
7
|
"nodeMajor": 22,
|
|
8
|
-
"dependencyHash": "sha256-
|
|
9
|
-
"serverBundleHash": "sha256-
|
|
10
|
-
"clientBundleHash": "sha256-
|
|
8
|
+
"dependencyHash": "sha256-4fjVNH4wSrTRkRTd373WiwHrjn1w8wGVCOPGWBDE+p4=",
|
|
9
|
+
"serverBundleHash": "sha256-Ln+odmvyZxmEopnizE6Y2RlGc4cLxM5xteZJrN6nbRY=",
|
|
10
|
+
"clientBundleHash": "sha256-jDj06V5zZYLzbDsoFe1zaxYtOwjgrDsPZwtsYZDlu4s=",
|
|
11
11
|
"entrypoint": "dist/server/cli.js",
|
|
12
12
|
"clientEntrypoint": "dist/client/index.html"
|
|
13
13
|
}
|