diffing 0.11.0 → 0.12.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.
Files changed (173) hide show
  1. package/README.md +2 -12
  2. package/dist/{cli-agent-DkwGxuy2.mjs → cli-agent-CWsOHN-j.mjs} +165 -53
  3. package/dist/{cli-gh-D0NfKpOp.mjs → cli-gh-DI69gJGo.mjs} +24 -14
  4. package/dist/cli.mjs +53 -22
  5. package/dist/client/assets/{angular-html-Dl53kkiy.js → angular-html-PLPuQo0k.js} +1 -1
  6. package/dist/client/assets/{angular-ts-wNJFFkey.js → angular-ts-CE02Ij4b.js} +1 -1
  7. package/dist/client/assets/{apl-BxtQST-h.js → apl-CsuUKZoi.js} +1 -1
  8. package/dist/client/assets/{arc-CBmZuzPB.js → arc-CgL5kFe-.js} +1 -1
  9. package/dist/client/assets/{architectureDiagram-3BPJPVTR-CEci_K9f.js → architectureDiagram-3BPJPVTR-DxZQWGnx.js} +1 -1
  10. package/dist/client/assets/{astro-BpADD5rh.js → astro-DkFc7sbz.js} +1 -1
  11. package/dist/client/assets/{blade-B4I5SQmP.js → blade-BkY07kcC.js} +1 -1
  12. package/dist/client/assets/{blockDiagram-GPEHLZMM-DcKhDtnE.js → blockDiagram-GPEHLZMM-D5a2KZV2.js} +1 -1
  13. package/dist/client/assets/{c-C3VtOgg8.js → c-T1BrPfJ6.js} +1 -1
  14. package/dist/client/assets/{c4Diagram-AAUBKEIU-CaHozoxF.js → c4Diagram-AAUBKEIU-mpMH4kFC.js} +1 -1
  15. package/dist/client/assets/channel-D3niKhl0.js +1 -0
  16. package/dist/client/assets/{chunk-2J33WTMH-tvuzKhdK.js → chunk-2J33WTMH-vMtgRLFH.js} +1 -1
  17. package/dist/client/assets/{chunk-3OPIFGDE-D_nBoD9w.js → chunk-3OPIFGDE-Dx-FqyO2.js} +1 -1
  18. package/dist/client/assets/{chunk-4BX2VUAB-yHPdy1G8.js → chunk-4BX2VUAB-CUrPd8Kv.js} +1 -1
  19. package/dist/client/assets/{chunk-55IACEB6-yXpL8wjV.js → chunk-55IACEB6-DHg3Nr8A.js} +1 -1
  20. package/dist/client/assets/{chunk-5ZQYHXKU-DZ5cvCDV.js → chunk-5ZQYHXKU-CpDPvbGs.js} +1 -1
  21. package/dist/client/assets/{chunk-727SXJPM-CJjgOWmY.js → chunk-727SXJPM-3VOGMxwk.js} +1 -1
  22. package/dist/client/assets/{chunk-AQP2D5EJ-CQYQKXSE.js → chunk-AQP2D5EJ-4dbfbIS6.js} +1 -1
  23. package/dist/client/assets/{chunk-BSJP7CBP-CP_f908b.js → chunk-BSJP7CBP-Dfyn0Uwp.js} +1 -1
  24. package/dist/client/assets/{chunk-CSCIHK7Q-tcgA8jR0.js → chunk-CSCIHK7Q-VTpSKo0F.js} +1 -1
  25. package/dist/client/assets/{chunk-FMBD7UC4-DlpmhBYg.js → chunk-FMBD7UC4-kXD1MyOL.js} +1 -1
  26. package/dist/client/assets/{chunk-KSCS5N6A-BkfieXpV.js → chunk-KSCS5N6A-BrVoWOAb.js} +1 -1
  27. package/dist/client/assets/{chunk-L5ZTLDWV-BjVXSZnt.js → chunk-L5ZTLDWV-wZEQDPsa.js} +1 -1
  28. package/dist/client/assets/{chunk-LZXEDZCA-CaAWmy4Q.js → chunk-LZXEDZCA-D3i0B0eg.js} +2 -2
  29. package/dist/client/assets/{chunk-ND2GUHAM-kWh41zUn.js → chunk-ND2GUHAM-hDVHT0bN.js} +1 -1
  30. package/dist/client/assets/{chunk-NZK2D7GU-CDrIi44_.js → chunk-NZK2D7GU-jQUfhp9h.js} +1 -1
  31. package/dist/client/assets/{chunk-O5CBEL6O-CbNGK3Te.js → chunk-O5CBEL6O-CX_vPWhk.js} +1 -1
  32. package/dist/client/assets/chunk-QZHKN3VN-CZLFuGpt.js +1 -0
  33. package/dist/client/assets/chunk-WU5MYG2G-BhcpjkaB.js +1 -0
  34. package/dist/client/assets/{chunk-XPW4576I-Cca0fTtG.js → chunk-XPW4576I-Co_-vDB4.js} +1 -1
  35. package/dist/client/assets/classDiagram-4FO5ZUOK-DK5KJNIt.js +1 -0
  36. package/dist/client/assets/classDiagram-v2-Q7XG4LA2-y5K9t6Se.js +1 -0
  37. package/dist/client/assets/{cobol-j-6eG2UQ.js → cobol-8-qBLs-a.js} +1 -1
  38. package/dist/client/assets/{coffee-CZLH0dtt.js → coffee-Bjz5lkyW.js} +1 -1
  39. package/dist/client/assets/{cose-bilkent-S5V4N54A-DlxESVex.js → cose-bilkent-S5V4N54A-BljJ0FSA.js} +1 -1
  40. package/dist/client/assets/{cpp-j6Bp24RI.js → cpp-5BVQCBXT.js} +1 -1
  41. package/dist/client/assets/{crystal-DW7wcFUs.js → crystal-CCkY93GS.js} +1 -1
  42. package/dist/client/assets/{css-C43BDU2i.js → css-BTM7Tp2a.js} +1 -1
  43. package/dist/client/assets/{dagre-BM42HDAG-BaemEJFh.js → dagre-BM42HDAG-BSynd_2D.js} +1 -1
  44. package/dist/client/assets/{diagram-2AECGRRQ-BaM-bkJ3.js → diagram-2AECGRRQ-K3E2CVdy.js} +1 -1
  45. package/dist/client/assets/{diagram-5GNKFQAL-BOH04DJO.js → diagram-5GNKFQAL-BQHIrfKc.js} +1 -1
  46. package/dist/client/assets/{diagram-KO2AKTUF-BP5MyqDZ.js → diagram-KO2AKTUF-Bqs8sNN4.js} +1 -1
  47. package/dist/client/assets/{diagram-LMA3HP47-Dt4gKMYF.js → diagram-LMA3HP47-C9K4bpQe.js} +1 -1
  48. package/dist/client/assets/{diagram-OG6HWLK6-DoT1VshN.js → diagram-OG6HWLK6-DK6wIXY2.js} +1 -1
  49. package/dist/client/assets/{dist-DEAxvC4F.js → dist-1nkZYMRy.js} +1 -1
  50. package/dist/client/assets/{edge-D9ySFlnD.js → edge-DqN2FJce.js} +1 -1
  51. package/dist/client/assets/{elixir-CoJz_LQ5.js → elixir-BiAgRUFF.js} +1 -1
  52. package/dist/client/assets/{elm-CvedWh_e.js → elm-N1IbY8sz.js} +1 -1
  53. package/dist/client/assets/{erDiagram-TEJ5UH35-CMP78FsQ.js → erDiagram-TEJ5UH35-jsHCiP02.js} +1 -1
  54. package/dist/client/assets/{erb-lD_yYZsm.js → erb-B-yYlWAZ.js} +1 -1
  55. package/dist/client/assets/{flowDiagram-I6XJVG4X-Dp0s5BFj.js → flowDiagram-I6XJVG4X-DOB1dAWG.js} +1 -1
  56. package/dist/client/assets/{ganttDiagram-6RSMTGT7-GmSG31U-.js → ganttDiagram-6RSMTGT7-BYIewcY5.js} +1 -1
  57. package/dist/client/assets/{git-rebase-DwZABzof.js → git-rebase-CVkPxOAF.js} +1 -1
  58. package/dist/client/assets/{gitGraphDiagram-PVQCEYII-C1SXShag.js → gitGraphDiagram-PVQCEYII-VNQzbpv2.js} +1 -1
  59. package/dist/client/assets/{glimmer-js-CWcs3w1Z.js → glimmer-js-BmG1xm72.js} +1 -1
  60. package/dist/client/assets/{glimmer-ts-CrzGN4lJ.js → glimmer-ts-CvTgwZsg.js} +1 -1
  61. package/dist/client/assets/{glsl-DRCtwX7h.js → glsl-DwjNNCbW.js} +1 -1
  62. package/dist/client/assets/{graphql-rpmrismS.js → graphql-BvgkyF8E.js} +1 -1
  63. package/dist/client/assets/{hack-Ba02RnuQ.js → hack-DH3188x2.js} +1 -1
  64. package/dist/client/assets/{haml-BHBACStm.js → haml-B0GTfMhX.js} +1 -1
  65. package/dist/client/assets/{handlebars-BtlQ1SCa.js → handlebars-he7hLDd9.js} +1 -1
  66. package/dist/client/assets/{html-BkVU3Dge.js → html-DIYgdTBq.js} +1 -1
  67. package/dist/client/assets/{html-derivative-DoK92vwi.js → html-derivative-2s6MXlci.js} +1 -1
  68. package/dist/client/assets/{http-CJAwKSPH.js → http-COS23XJP.js} +1 -1
  69. package/dist/client/assets/{hurl-kaX5jwuN.js → hurl-BlZPjeJt.js} +1 -1
  70. package/dist/client/assets/{index-BHeNiC07.js → index-BrEVVQOB.js} +154 -154
  71. package/dist/client/assets/{index-D8hOoJCg.css → index-BsuX6HVI.css} +1 -1
  72. package/dist/client/assets/{infoDiagram-5YYISTIA-B0i3BlNR.js → infoDiagram-5YYISTIA-DQRqk24I.js} +1 -1
  73. package/dist/client/assets/{ishikawaDiagram-YF4QCWOH-BN8sEei4.js → ishikawaDiagram-YF4QCWOH-DU1rqrLx.js} +1 -1
  74. package/dist/client/assets/{java-BvrigIoq.js → java-BAa5w-Qd.js} +1 -1
  75. package/dist/client/assets/{javascript-DZkPTYAi.js → javascript-C9e02ssI.js} +1 -1
  76. package/dist/client/assets/{jinja-Ceg7ui1S.js → jinja-Bx37xXwq.js} +1 -1
  77. package/dist/client/assets/{jison-iE1GaOyN.js → jison-m_DEf8Jo.js} +1 -1
  78. package/dist/client/assets/{journeyDiagram-JHISSGLW-CE6O3NhU.js → journeyDiagram-JHISSGLW-CoHlfevf.js} +1 -1
  79. package/dist/client/assets/{json-C0j8rEcg.js → json-DtN5AWRW.js} +1 -1
  80. package/dist/client/assets/{jsx-B7eXljgz.js → jsx-BlPpu8bR.js} +1 -1
  81. package/dist/client/assets/{julia-DMDw0aMP.js → julia-BAOmCbHl.js} +1 -1
  82. package/dist/client/assets/{just-BryMKRJ_.js → just-C_bvVjwE.js} +1 -1
  83. package/dist/client/assets/{kanban-definition-UN3LZRKU-j-aU6Yzp.js → kanban-definition-UN3LZRKU-BiqYI7_m.js} +1 -1
  84. package/dist/client/assets/{latex-BNC9-sjr.js → latex-81pMfNMt.js} +1 -1
  85. package/dist/client/assets/{line-CyEqpEDp.js → line-DCovs9My.js} +1 -1
  86. package/dist/client/assets/{linear-CXeaA9km.js → linear-cJF5XHE7.js} +1 -1
  87. package/dist/client/assets/{liquid-D-fQw-oJ.js → liquid-sKRTk6dT.js} +1 -1
  88. package/dist/client/assets/{lua-CD2aJ_rS.js → lua-C1uZL4IF.js} +1 -1
  89. package/dist/client/assets/{marko-BQ37hu6z.js → marko-BKEzP1CL.js} +1 -1
  90. package/dist/client/assets/{mdc-B5NUi3zZ.js → mdc-CLkfm94H.js} +1 -1
  91. package/dist/client/assets/{mermaid-parser.core-BxHF_XbX.js → mermaid-parser.core-CTsTbvb2.js} +1 -1
  92. package/dist/client/assets/{mermaid.core-BUtaf4P1.js → mermaid.core-D86HJEwL.js} +3 -3
  93. package/dist/client/assets/{mindmap-definition-RKZ34NQL-D13tPu2o.js → mindmap-definition-RKZ34NQL-CL3heUmL.js} +1 -1
  94. package/dist/client/assets/{nginx-1W1E03Rg.js → nginx-eDGm66pc.js} +1 -1
  95. package/dist/client/assets/{nim-C5A88bFP.js → nim-CoWZPv8-.js} +1 -1
  96. package/dist/client/assets/{perl-BYoP0wNt.js → perl-MoMqtMVr.js} +1 -1
  97. package/dist/client/assets/{php-CFxna09e.js → php-DXXVMAtN.js} +1 -1
  98. package/dist/client/assets/{pieDiagram-4H26LBE5-CHL7Ml5w.js → pieDiagram-4H26LBE5-CWV3TMu4.js} +1 -1
  99. package/dist/client/assets/{pug-BR4JgWAk.js → pug-CPWaB94J.js} +1 -1
  100. package/dist/client/assets/{qml-D1U1EFEe.js → qml-lhvpx8vk.js} +1 -1
  101. package/dist/client/assets/{quadrantDiagram-W4KKPZXB-BnYtv-HY.js → quadrantDiagram-W4KKPZXB-QV25BYos.js} +1 -1
  102. package/dist/client/assets/{r-ChE6X060.js → r-DYbUnmmK.js} +1 -1
  103. package/dist/client/assets/{razor-B5iVfQMe.js → razor-DcyOLv96.js} +1 -1
  104. package/dist/client/assets/{regexp-Dz2drUIf.js → regexp-BdY10jm0.js} +1 -1
  105. package/dist/client/assets/{requirementDiagram-4Y6WPE33-D8QEGLKB.js → requirementDiagram-4Y6WPE33-BPMsmU6J.js} +1 -1
  106. package/dist/client/assets/{review-export-CvFFbCAB.js → review-export-CMwjJURs.js} +1 -1
  107. package/dist/client/assets/{rst-DZM3RGRs.js → rst-6ShFOzgH.js} +1 -1
  108. package/dist/client/assets/{ruby-DkXnm-J8.js → ruby-B04DeVbi.js} +1 -1
  109. package/dist/client/assets/{sankeyDiagram-5OEKKPKP-wVaks6lB.js → sankeyDiagram-5OEKKPKP-DQJeroPp.js} +1 -1
  110. package/dist/client/assets/{sas-DMbpc71c.js → sas-Dj26ftNa.js} +1 -1
  111. package/dist/client/assets/{scss-IwVMMp22.js → scss-BOHpBkgl.js} +1 -1
  112. package/dist/client/assets/{sequenceDiagram-3UESZ5HK-Cg31TB-R.js → sequenceDiagram-3UESZ5HK-DdV0Y6Sz.js} +1 -1
  113. package/dist/client/assets/{shellscript-CIStAKx3.js → shellscript-CpHwjRcU.js} +1 -1
  114. package/dist/client/assets/{shellsession-uLtzHhlo.js → shellsession-BJAvf4GN.js} +1 -1
  115. package/dist/client/assets/{soy-BkxBYigm.js → soy-B67bZJnL.js} +1 -1
  116. package/dist/client/assets/{sql-Ba9y9EvJ.js → sql-8MzOqSsK.js} +1 -1
  117. package/dist/client/assets/{src-9MKexpFu.js → src-AaoRSmFl.js} +1 -1
  118. package/dist/client/assets/{stata-CrPCbiIZ.js → stata-aCME945h.js} +1 -1
  119. package/dist/client/assets/{stateDiagram-AJRCARHV-BbvNjVF6.js → stateDiagram-AJRCARHV-CMD_Xj2M.js} +1 -1
  120. package/dist/client/assets/stateDiagram-v2-BHNVJYJU-vLl7D4ue.js +1 -0
  121. package/dist/client/assets/{surrealql-Dvip5u_o.js → surrealql-B_V_HxAi.js} +1 -1
  122. package/dist/client/assets/{svelte-xBLD60Zd.js → svelte-BcQvTlqz.js} +1 -1
  123. package/dist/client/assets/{templ-CWv68xbP.js → templ-DZCQ2blz.js} +1 -1
  124. package/dist/client/assets/{tex-CHqz-fYs.js → tex-BfeQ5Wuu.js} +1 -1
  125. package/dist/client/assets/{timeline-definition-PNZ67QCA-CWKkJ3QZ.js → timeline-definition-PNZ67QCA-CyIS7Zoe.js} +1 -1
  126. package/dist/client/assets/{ts-tags-DS82EDuE.js → ts-tags-DVWE0E87.js} +1 -1
  127. package/dist/client/assets/{tsx-B2GBjp2F.js → tsx-DdJ7Sfqf.js} +1 -1
  128. package/dist/client/assets/{twig-CC8x9pG0.js → twig-_gVgaha5.js} +1 -1
  129. package/dist/client/assets/{typescript-g7i13lnC.js → typescript-Bj0_LzZV.js} +1 -1
  130. package/dist/client/assets/{vennDiagram-CIIHVFJN-OLItKWeg.js → vennDiagram-CIIHVFJN-C-J2kWyk.js} +1 -1
  131. package/dist/client/assets/{vue-rFbe7luB.js → vue-Dnt_GBRb.js} +1 -1
  132. package/dist/client/assets/{vue-html-D9GQtYub.js → vue-html-ClVA5__5.js} +1 -1
  133. package/dist/client/assets/{vue-vine-mrNtQtY5.js → vue-vine-BCcz4SVP.js} +1 -1
  134. package/dist/client/assets/{wardleyDiagram-YWT4CUSO-Dy1yfeb4.js → wardleyDiagram-YWT4CUSO-Dzt4EPh8.js} +1 -1
  135. package/dist/client/assets/{xml-CHfMjyAM.js → xml-BYeUHEti.js} +1 -1
  136. package/dist/client/assets/{xsl-BFkNSogJ.js → xsl-Vsx0SZEV.js} +1 -1
  137. package/dist/client/assets/{xychartDiagram-2RQKCTM6-DfSnfjVL.js → xychartDiagram-2RQKCTM6-BAWZKvwP.js} +1 -1
  138. package/dist/client/assets/{yaml-BfSgHc04.js → yaml-C6L1khMK.js} +1 -1
  139. package/dist/client/index.html +2 -2
  140. package/dist/{completions-BO2DUM-8.mjs → completions-DvyV49HY.mjs} +1 -0
  141. package/dist/{doctor-D0Y3kOY7.mjs → doctor-Bz9VHuBI.mjs} +7 -7
  142. package/dist/{find-tui-binary-B71xiwWu.mjs → find-tui-binary-DVQADOSF.mjs} +56 -25
  143. package/dist/{git-Czo96ymM.mjs → git-BGj31GX-.mjs} +71 -7
  144. package/dist/git-CfDSkUcE.mjs +2 -0
  145. package/dist/{github-CErBub2y.mjs → github-DXiEeHzk.mjs} +1 -1
  146. package/dist/{github-DBsZ0h_l.mjs → github-DpzqNrUh.mjs} +3 -3
  147. package/dist/{github-attachments-plDeB0iE.mjs → github-attachments-DgOf7BhP.mjs} +2 -2
  148. package/dist/{mcp-DtVrMR2S.mjs → mcp-zDVzU1vl.mjs} +32 -29
  149. package/dist/native/tui-darwin-arm64/diffing-tui +0 -0
  150. package/dist/native/tui-darwin-x64/diffing-tui +0 -0
  151. package/dist/native/tui-linux-arm64-gnu/diffing-tui +0 -0
  152. package/dist/native/tui-linux-arm64-musl/diffing-tui +0 -0
  153. package/dist/native/tui-linux-x64-gnu/diffing-tui +0 -0
  154. package/dist/native/tui-linux-x64-musl/diffing-tui +0 -0
  155. package/dist/native/tui-win32-x64-msvc/diffing-tui.exe +0 -0
  156. package/dist/{search-BMPY_ZW8.mjs → search-3R2E5xxr.mjs} +16 -1
  157. package/dist/{search-BO9Im7eu.mjs → search-CQ4nsjBX.mjs} +1 -1
  158. package/dist/{server-j0PnTVX1.mjs → server-Dw3lkQ5q.mjs} +157 -42
  159. package/dist/{server-lock-CY0_1mcS.mjs → server-lock-BNI8FKV1.mjs} +175 -23
  160. package/dist/{session-conflict-C6V9ZKo7.mjs → session-conflict-Bqt1M4Mp.mjs} +7 -7
  161. package/dist/{session-manager-CYNchhVA.mjs → session-manager-BKSZQqDJ.mjs} +2 -2
  162. package/dist/session-url-sr7lXXVc.mjs +100 -0
  163. package/dist/{tui-search-bridge-Bfb2ktdA.mjs → tui-search-bridge-BGgLCwMF.mjs} +3 -3
  164. package/dist/{update-check-Copcz9eb.mjs → update-check-BUfh4Y6c.mjs} +16 -15
  165. package/package.json +4 -1
  166. package/dist/client/assets/channel-Ct4-oSQN.js +0 -1
  167. package/dist/client/assets/chunk-QZHKN3VN-BXhKFVX7.js +0 -1
  168. package/dist/client/assets/chunk-WU5MYG2G-_EwuC51_.js +0 -1
  169. package/dist/client/assets/classDiagram-4FO5ZUOK-C8bdx9R4.js +0 -1
  170. package/dist/client/assets/classDiagram-v2-Q7XG4LA2-B26wrQuH.js +0 -1
  171. package/dist/client/assets/stateDiagram-v2-BHNVJYJU-B5BbZkU5.js +0 -1
  172. package/dist/git-DaP_1rVy.mjs +0 -2
  173. package/dist/settings-yK0GYpbn.mjs +0 -60
@@ -1,7 +1,136 @@
1
- import { d as getProjectStorageDir, p as getRepoRoot } from "./git-Czo96ymM.mjs";
2
- import { randomUUID } from "node:crypto";
1
+ import { f as getProjectStorageDir, h as getRepoRoot } from "./git-BGj31GX-.mjs";
2
+ import { spawnSync } from "node:child_process";
3
+ import { randomBytes, randomUUID } from "node:crypto";
3
4
  import { join } from "node:path";
4
- import { existsSync, mkdirSync, readFileSync, readdirSync, renameSync, rmSync, rmdirSync, statSync, unlinkSync, writeFileSync } from "node:fs";
5
+ import { chmodSync, existsSync, mkdirSync, readFileSync, readdirSync, renameSync, rmSync, rmdirSync, statSync, unlinkSync, writeFileSync } from "node:fs";
6
+ import { getCookie } from "hono/cookie";
7
+ //#region src/lib/server-auth.ts
8
+ /** Header, HttpOnly cookie, or legacy query param carrying the per-session review API token. */
9
+ const SESSION_TOKEN_HEADER = "x-diffing-token";
10
+ const SESSION_TOKEN_QUERY = "token";
11
+ const SESSION_TOKEN_COOKIE = "diffing-token";
12
+ function generateSessionToken() {
13
+ return randomBytes(32).toString("hex");
14
+ }
15
+ function isLoopbackHost(host) {
16
+ const normalized = host.toLowerCase();
17
+ if (normalized === "localhost" || normalized === "::1" || normalized === "[::1]") return true;
18
+ const octets = normalized.split(".");
19
+ return octets.length === 4 && octets[0] === "127" && octets.every((part) => {
20
+ if (!/^\d{1,3}$/.test(part)) return false;
21
+ const value = Number(part);
22
+ return value >= 0 && value <= 255;
23
+ });
24
+ }
25
+ function isWildcardBindHost(host) {
26
+ const normalized = host.toLowerCase();
27
+ return normalized === "0.0.0.0" || normalized === "::";
28
+ }
29
+ function requestHostHeader(hostHeader) {
30
+ if (!hostHeader) return null;
31
+ const trimmed = hostHeader.trim();
32
+ if (!trimmed) return null;
33
+ if (trimmed.startsWith("[")) {
34
+ const end = trimmed.indexOf("]");
35
+ return end === -1 ? trimmed.toLowerCase() : trimmed.slice(1, end).toLowerCase();
36
+ }
37
+ return trimmed.split(":")[0].toLowerCase();
38
+ }
39
+ /** Reject non-loopback Host headers when the server binds loopback (DNS rebinding guard). */
40
+ function isAllowedRequestHost(hostHeader, bindHost) {
41
+ if (!isLoopbackHost(bindHost)) return true;
42
+ const host = requestHostHeader(hostHeader);
43
+ if (!host) return true;
44
+ return isLoopbackHost(host);
45
+ }
46
+ function readSessionToken(c) {
47
+ const header = c.req.header(SESSION_TOKEN_HEADER);
48
+ if (header) return header;
49
+ const cookie = getCookie(c, SESSION_TOKEN_COOKIE);
50
+ if (cookie) return cookie;
51
+ return c.req.query("token") || null;
52
+ }
53
+ /** `Set-Cookie` value for the review session token (loopback http — no Secure). */
54
+ function buildSessionTokenSetCookieValue(token) {
55
+ return `${SESSION_TOKEN_COOKIE}=${encodeURIComponent(token)}; Path=/; SameSite=Strict; HttpOnly`;
56
+ }
57
+ /** Escape a session token for embedding in a double-quoted JS string literal. */
58
+ function escapeTokenForJsString(token) {
59
+ return token.replace(/\\/g, "\\\\").replace(/"/g, "\\\"");
60
+ }
61
+ /** Inject `window.__DIFFING_SESSION_TOKEN__` into served HTML so deep links work without `?token=`. */
62
+ function injectSessionTokenIntoHtml(html, authToken) {
63
+ if (!authToken) return html;
64
+ const script = `<script>window.__DIFFING_SESSION_TOKEN__="${escapeTokenForJsString(authToken)}";<\/script>`;
65
+ if (html.includes("</head>")) return html.replace("</head>", `${script}</head>`);
66
+ return `${script}${html}`;
67
+ }
68
+ function createServerAuthMiddleware(config) {
69
+ return async (c, next) => {
70
+ if (!c.req.path.startsWith("/api/")) {
71
+ await next();
72
+ return;
73
+ }
74
+ if (!isAllowedRequestHost(c.req.header("host"), config.bindHost)) return c.json({ error: "request Host header is not allowed for this bind address" }, 403);
75
+ if (!config.insecureNoAuth && config.authToken) {
76
+ if (readSessionToken(c) !== config.authToken) return c.json({ error: "invalid or missing review session token" }, 401);
77
+ }
78
+ await next();
79
+ };
80
+ }
81
+ //#endregion
82
+ //#region src/lib/lock-probe.ts
83
+ /** Map wildcard bind hosts to loopback for local probes. */
84
+ function loopbackProbeHost(host) {
85
+ if (host === "0.0.0.0") return "127.0.0.1";
86
+ return host;
87
+ }
88
+ /**
89
+ * Synchronous loopback probe: GET `/api/review/status` and expect a JSON body
90
+ * with a numeric `round` field. Used to detect stale locks after PID reuse.
91
+ */
92
+ function probeLockServerSync(lock) {
93
+ if (lock.port <= 0) return true;
94
+ const host = loopbackProbeHost(lock.host);
95
+ const headers = {};
96
+ if (lock.capability) headers["X-Diffing-Capability"] = lock.capability;
97
+ if (lock.authToken) headers[SESSION_TOKEN_HEADER] = lock.authToken;
98
+ const script = `
99
+ import http from 'node:http';
100
+ const host = ${JSON.stringify(host)};
101
+ const port = ${lock.port};
102
+ const headers = ${JSON.stringify(headers)};
103
+ const req = http.request({
104
+ hostname: host,
105
+ port,
106
+ path: '/api/review/status',
107
+ method: 'GET',
108
+ headers,
109
+ }, (res) => {
110
+ let data = '';
111
+ res.on('data', (chunk) => { data += chunk; });
112
+ res.on('end', () => { process.stdout.write(data); });
113
+ });
114
+ req.on('error', () => process.exit(2));
115
+ req.setTimeout(400, () => { req.destroy(); process.exit(2); });
116
+ req.end();
117
+ `;
118
+ const result = spawnSync(process.execPath, [
119
+ "--input-type=module",
120
+ "-e",
121
+ script
122
+ ], {
123
+ timeout: 900,
124
+ encoding: "utf8"
125
+ });
126
+ if (result.status !== 0) return false;
127
+ try {
128
+ return typeof JSON.parse(result.stdout.trim()).round === "number";
129
+ } catch {
130
+ return false;
131
+ }
132
+ }
133
+ //#endregion
5
134
  //#region src/lib/server-lock.ts
6
135
  const STARTUP_LEASE_STALE_MS = 3e4;
7
136
  /**
@@ -10,7 +139,7 @@ const STARTUP_LEASE_STALE_MS = 3e4;
10
139
  * mismatches between a user-started session and an MCP request.
11
140
  */
12
141
  function diffScopeKey(options) {
13
- const { port: _port, host: _host, noOpen: _noOpen, reuseSession: _reuseSession, replaceSession: _replaceSession, help: _help, version: _version, outputMode: _outputMode, tui: _tui, gpu: _gpu, noExtDiff: _noExtDiff, ...scope } = options;
142
+ const { port: _port, host: _host, noOpen: _noOpen, insecureNoAuth: _insecureNoAuth, reuseSession: _reuseSession, replaceSession: _replaceSession, help: _help, version: _version, outputMode: _outputMode, tui: _tui, gpu: _gpu, noExtDiff: _noExtDiff, ...scope } = options;
14
143
  return JSON.stringify(scope);
15
144
  }
16
145
  function lockPath(repoRoot) {
@@ -31,10 +160,23 @@ function sessionPath(lock) {
31
160
  return join(sessionsPath(lock.repoRoot), `${encodeURIComponent(serverSessionId(lock))}.json`);
32
161
  }
33
162
  function writeJsonAtomically(path, value) {
34
- mkdirSync(join(path, ".."), { recursive: true });
163
+ const parent = join(path, "..");
164
+ mkdirSync(parent, {
165
+ recursive: true,
166
+ mode: 448
167
+ });
168
+ try {
169
+ chmodSync(parent, 448);
170
+ } catch {}
35
171
  const temporary = `${path}.${process.pid}.${randomUUID()}.tmp`;
36
- writeFileSync(temporary, JSON.stringify(value, null, 2), "utf-8");
172
+ writeFileSync(temporary, JSON.stringify(value, null, 2), {
173
+ encoding: "utf-8",
174
+ mode: 384
175
+ });
37
176
  renameSync(temporary, path);
177
+ try {
178
+ chmodSync(path, 384);
179
+ } catch {}
38
180
  }
39
181
  function normalizedLock(lock) {
40
182
  return lock.sessionId ? lock : {
@@ -139,21 +281,24 @@ function activateServerLock(lock) {
139
281
  writeJsonAtomically(lockPath(lock.repoRoot), normalized);
140
282
  return normalized;
141
283
  }
284
+ function isPidAlive(pid) {
285
+ try {
286
+ process.kill(pid, 0);
287
+ return true;
288
+ } catch (error) {
289
+ return (error && typeof error === "object" && "code" in error ? error.code : void 0) === "EPERM";
290
+ }
291
+ }
142
292
  /**
143
- * True if the process named by the lock is still alive and the lock belongs to
144
- * this repo. `process.kill(pid, 0)` sends no signal it just probes existence.
293
+ * True when the lock pid is alive, belongs to this repo, and the loopback port
294
+ * still serves a diffing review status endpoint (detects PID reuse).
145
295
  */
146
296
  function isLockAlive(lock, expectedRepoRoot) {
297
+ if (!isPidAlive(lock.pid)) return false;
147
298
  try {
148
- process.kill(lock.pid, 0);
149
- } catch {
150
- return false;
151
- }
152
- try {
153
- return lock.repoRoot === (expectedRepoRoot ?? getRepoRoot());
154
- } catch {
155
- return true;
156
- }
299
+ if (lock.repoRoot !== (expectedRepoRoot ?? getRepoRoot())) return false;
300
+ } catch {}
301
+ return probeLockServerSync(lock);
157
302
  }
158
303
  function removeServerLock(repoRoot) {
159
304
  try {
@@ -249,11 +394,18 @@ function acquireServerStartupLease(repoRoot, ownerId, now = Date.now()) {
249
394
  }
250
395
  if (reclaim && !acquiredAfterRace) {
251
396
  const stalePath = `${path}.stale-${process.pid}-${now}`;
252
- renameSync(path, stalePath);
253
- rmSync(stalePath, {
254
- recursive: true,
255
- force: true
256
- });
397
+ try {
398
+ renameSync(path, stalePath);
399
+ rmSync(stalePath, {
400
+ recursive: true,
401
+ force: true
402
+ });
403
+ } catch (error) {
404
+ if (error?.code === "ENOENT") {
405
+ if (!tryCreate()) return null;
406
+ acquiredAfterRace = true;
407
+ } else return null;
408
+ }
257
409
  }
258
410
  if (!acquiredAfterRace && !tryCreate()) return null;
259
411
  }
@@ -272,4 +424,4 @@ function acquireServerStartupLease(repoRoot, ownerId, now = Date.now()) {
272
424
  };
273
425
  }
274
426
  //#endregion
275
- export { listServerLocks as a, removeServerLockIfOwned as c, sameServerSession as d, serverSessionId as f, isLockAlive as i, removeServerSession as l, activateServerLock as n, readServerLock as o, writeServerLock as p, diffScopeKey as r, removeServerLock as s, acquireServerStartupLease as t, resolveActiveServerLock as u };
427
+ export { isWildcardBindHost as S, buildSessionTokenSetCookieValue as _, listServerLocks as a, injectSessionTokenIntoHtml as b, removeServerLockIfOwned as c, sameServerSession as d, serverSessionId as f, SESSION_TOKEN_QUERY as g, SESSION_TOKEN_HEADER as h, isLockAlive as i, removeServerSession as l, probeLockServerSync as m, activateServerLock as n, readServerLock as o, writeServerLock as p, diffScopeKey as r, removeServerLock as s, acquireServerStartupLease as t, resolveActiveServerLock as u, createServerAuthMiddleware as v, isLoopbackHost as x, generateSessionToken as y };
@@ -1,16 +1,12 @@
1
- import { t as loadSettings } from "./settings-yK0GYpbn.mjs";
2
- import { l as removeServerSession } from "./server-lock-CY0_1mcS.mjs";
1
+ import { a as loadSettings, i as reviewSessionUrl } from "./session-url-sr7lXXVc.mjs";
2
+ import { l as removeServerSession, m as probeLockServerSync } from "./server-lock-BNI8FKV1.mjs";
3
3
  //#region src/lib/session-conflict.ts
4
4
  function sleepMs(ms) {
5
5
  return new Promise((resolve) => setTimeout(resolve, ms));
6
6
  }
7
7
  /** Loopback-safe review URL for web / gh-pr locks; null for TUI or invalid ports. */
8
8
  function existingSessionUrl(lock) {
9
- const mode = lock.mode ?? "web";
10
- if (mode === "tui" || !(lock.port > 0)) return null;
11
- const host = lock.host === "0.0.0.0" ? "127.0.0.1" : lock.host;
12
- const path = mode === "gh-pr" ? "/gh/pr" : "";
13
- return `http://${host}:${lock.port}${path}`;
9
+ return reviewSessionUrl(lock);
14
10
  }
15
11
  function defaultClearLock(lock) {
16
12
  removeServerSession(lock);
@@ -36,6 +32,10 @@ async function stopLockOwner(lock, options = {}) {
36
32
  const now = options.now ?? Date.now;
37
33
  const isAlive = options.isAlive ?? ((candidate) => pidAlive(candidate.pid, kill));
38
34
  const clearLock = options.clearLock ?? defaultClearLock;
35
+ if (!await (options.lockMatches ?? ((candidate) => probeLockServerSync(candidate)))(lock)) {
36
+ clearLock(lock);
37
+ return;
38
+ }
39
39
  if (!isAlive(lock)) {
40
40
  clearLock(lock);
41
41
  return;
@@ -1,5 +1,5 @@
1
- import { a as listServerLocks, d as sameServerSession, f as serverSessionId, n as activateServerLock, u as resolveActiveServerLock } from "./server-lock-CY0_1mcS.mjs";
2
- import { n as openExistingSession, r as stopLockOwner, t as existingSessionUrl } from "./session-conflict-C6V9ZKo7.mjs";
1
+ import { a as listServerLocks, d as sameServerSession, f as serverSessionId, n as activateServerLock, u as resolveActiveServerLock } from "./server-lock-BNI8FKV1.mjs";
2
+ import { n as openExistingSession, r as stopLockOwner, t as existingSessionUrl } from "./session-conflict-Bqt1M4Mp.mjs";
3
3
  //#region src/lib/session-manager.ts
4
4
  const EXIT_OK = 0;
5
5
  const EXIT_NOT_FOUND = 4;
@@ -0,0 +1,100 @@
1
+ import { g as SESSION_TOKEN_QUERY, x as isLoopbackHost } from "./server-lock-BNI8FKV1.mjs";
2
+ import { randomUUID } from "node:crypto";
3
+ import { join } from "node:path";
4
+ import { mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
5
+ import { homedir } from "node:os";
6
+ //#region src/lib/json-atomic.ts
7
+ /** Write JSON via a temp file and rename so readers never see a partial file. */
8
+ function writeJsonAtomically(path, value) {
9
+ mkdirSync(join(path, ".."), { recursive: true });
10
+ const temporary = `${path}.${process.pid}.${randomUUID()}.tmp`;
11
+ writeFileSync(temporary, JSON.stringify(value, null, 2), "utf-8");
12
+ renameSync(temporary, path);
13
+ }
14
+ //#endregion
15
+ //#region src/lib/settings.ts
16
+ const SETTINGS_FILE = join(join(homedir(), ".config", "diffing"), "settings.json");
17
+ const DEFAULTS = {
18
+ defaultMode: "web",
19
+ staged: true,
20
+ untracked: true,
21
+ diffStyle: "split",
22
+ defaultTabSize: 4,
23
+ theme: "rose-pine",
24
+ editorIDE: "default",
25
+ lineDiffType: "word",
26
+ lineWrap: false,
27
+ diffIndicators: "classic",
28
+ showLineNumbers: true,
29
+ hunkSeparators: "line-info",
30
+ lineHoverHighlight: "both",
31
+ fontSize: 13,
32
+ expandContextByDefault: false,
33
+ collapsedContextThreshold: 10,
34
+ expansionLineCount: 20,
35
+ haptics: true,
36
+ sounds: true,
37
+ uiFont: null,
38
+ monoFont: null,
39
+ density: "comfortable",
40
+ autoCollapseLineThreshold: 400,
41
+ requireViewAllBeforeSend: false,
42
+ showStatusBar: true,
43
+ savedReplies: [],
44
+ ignoreSpaceChange: false,
45
+ ignoreAllSpace: false
46
+ };
47
+ function loadSettings() {
48
+ try {
49
+ const data = readFileSync(SETTINGS_FILE, "utf-8");
50
+ const settings = {
51
+ ...DEFAULTS,
52
+ ...JSON.parse(data)
53
+ };
54
+ if (settings.defaultMode !== "web" && settings.defaultMode !== "tui") settings.defaultMode = DEFAULTS.defaultMode;
55
+ return settings;
56
+ } catch {
57
+ return { ...DEFAULTS };
58
+ }
59
+ }
60
+ function saveSettings(settings) {
61
+ const merged = {
62
+ ...loadSettings(),
63
+ ...settings
64
+ };
65
+ writeJsonAtomically(SETTINGS_FILE, merged);
66
+ return merged;
67
+ }
68
+ //#endregion
69
+ //#region src/lib/session-url.ts
70
+ /** Loopback-safe review URL for web / gh-pr locks; null for TUI or invalid ports. */
71
+ function reviewSessionBaseUrl(lock) {
72
+ if ((lock.mode ?? "web") === "tui" || !(lock.port > 0)) return null;
73
+ if (!isLoopbackHost(lock.host) && lock.host !== "0.0.0.0" && lock.host !== "::") return null;
74
+ const host = lock.host === "0.0.0.0" || lock.host === "::" ? "127.0.0.1" : lock.host;
75
+ const path = lock.mode === "gh-pr" ? "/gh/pr" : "";
76
+ return `http://${host}:${lock.port}${path}`;
77
+ }
78
+ /** Browseable review URL without auth query params (auth uses cookie + header). */
79
+ function appendSessionToken(url, _token) {
80
+ try {
81
+ const parsed = new URL(url);
82
+ parsed.searchParams.delete(SESSION_TOKEN_QUERY);
83
+ const search = parsed.searchParams.toString();
84
+ return `${parsed.origin}${parsed.pathname}${search ? `?${search}` : ""}${parsed.hash}`;
85
+ } catch {
86
+ return url;
87
+ }
88
+ }
89
+ /** Public review URL for humans (no `?token=` — session cookie is set when HTML is served). */
90
+ function reviewSessionUrl(lock) {
91
+ const base = reviewSessionBaseUrl(lock);
92
+ if (!base) return null;
93
+ return base;
94
+ }
95
+ /** Join an API path to a session base URL (origin only; strips any legacy `?token=`). */
96
+ function joinSessionApiUrl(base, path) {
97
+ return `${new URL(base).origin}${path.startsWith("/") ? path : `/${path}`}`;
98
+ }
99
+ //#endregion
100
+ export { loadSettings as a, reviewSessionUrl as i, joinSessionApiUrl as n, saveSettings as o, reviewSessionBaseUrl as r, appendSessionToken as t };
@@ -1,4 +1,4 @@
1
- import { o as getFileContent } from "./git-Czo96ymM.mjs";
1
+ import { s as getFileContent } from "./git-BGj31GX-.mjs";
2
2
  import { randomUUID } from "node:crypto";
3
3
  import { createServer } from "node:http";
4
4
  //#region src/lib/tui-search-bridge.ts
@@ -26,7 +26,7 @@ async function readJson(request) {
26
26
  return JSON.parse(Buffer.concat(chunks).toString("utf8"));
27
27
  }
28
28
  async function runSearch(body) {
29
- const { searchAll, searchContent, searchFiles, searchSymbols } = await import("./search-BO9Im7eu.mjs");
29
+ const { searchAll, searchContent, searchFiles, searchSymbols } = await import("./search-CQ4nsjBX.mjs");
30
30
  const scope = body.scope ?? "all";
31
31
  const query = typeof body.query === "string" ? body.query : "";
32
32
  const limit = typeof body.limit === "number" ? body.limit : void 0;
@@ -100,7 +100,7 @@ async function startTuiSearchBridge() {
100
100
  if (request.method === "POST" && request.url === "/track") {
101
101
  const body = await readJson(request);
102
102
  if (typeof body.path === "string") {
103
- const { trackSelection } = await import("./search-BO9Im7eu.mjs");
103
+ const { trackSelection } = await import("./search-CQ4nsjBX.mjs");
104
104
  await trackSelection(typeof body.query === "string" ? body.query : "", body.path);
105
105
  }
106
106
  sendJson(response, 200, { ok: true });
@@ -32,15 +32,18 @@ async function checkForUpdates(currentVersion) {
32
32
  try {
33
33
  const controller = new AbortController();
34
34
  const id = setTimeout(() => controller.abort(), 1e3);
35
- const res = await fetch("https://registry.npmjs.org/diffing/latest", { signal: controller.signal });
36
- clearTimeout(id);
37
- if (!res.ok) return null;
38
- const data = await res.json();
39
- if (!data.version) return null;
40
- return {
41
- hasUpdate: isNewerVersion(currentVersion, data.version),
42
- latestVersion: data.version
43
- };
35
+ try {
36
+ const res = await fetch("https://registry.npmjs.org/diffing/latest", { signal: controller.signal });
37
+ if (!res.ok) return null;
38
+ const data = await res.json();
39
+ if (!data.version) return null;
40
+ return {
41
+ hasUpdate: isNewerVersion(currentVersion, data.version),
42
+ latestVersion: data.version
43
+ };
44
+ } finally {
45
+ clearTimeout(id);
46
+ }
44
47
  } catch {
45
48
  return null;
46
49
  }
@@ -106,10 +109,7 @@ async function runUpdateCommand() {
106
109
  } catch {}
107
110
  console.log(`Running: ${cmd} ${args.join(" ")}\n`);
108
111
  const exitCode = await new Promise((res) => {
109
- const child = spawn(cmd, args, {
110
- stdio: "inherit",
111
- shell: true
112
- });
112
+ const child = spawn(cmd, args, { stdio: "inherit" });
113
113
  child.on("close", (code) => {
114
114
  res(code ?? 0);
115
115
  });
@@ -120,8 +120,9 @@ async function runUpdateCommand() {
120
120
  });
121
121
  if (exitCode === 0) console.log(`\n\x1b[38;5;82mSuccessfully updated diffing to v${latest}!\x1b[0m\n`);
122
122
  else {
123
- console.error(`\n\x1b[38;5;196mFailed to update diffing. Please try running the command manually with sudo if required:\x1b[0m`);
124
- console.error(` sudo ${cmd} ${args.join(" ")}\n`);
123
+ console.error(`\n\x1b[38;5;196mFailed to update diffing. Install into your user prefix instead of using sudo:\x1b[0m`);
124
+ console.error(` npm config get prefix # e.g. ~/.npm-global or ~/.local`);
125
+ console.error(` ${cmd} ${args.join(" ")}\n`);
125
126
  }
126
127
  return exitCode;
127
128
  }
package/package.json CHANGED
@@ -1,9 +1,12 @@
1
1
  {
2
2
  "name": "diffing",
3
- "version": "0.11.0",
3
+ "version": "0.12.0",
4
4
  "description": "local-first CLI for reviewing, navigating, and discussing git diffs with AI",
5
5
  "type": "module",
6
6
  "license": "MIT",
7
+ "engines": {
8
+ "node": ">=20"
9
+ },
7
10
  "packageManager": "pnpm@11.6.0",
8
11
  "homepage": "https://github.com/ahmedragab20/diffing",
9
12
  "repository": {
@@ -1 +0,0 @@
1
- import{at as e,ot as t}from"./chunk-CSCIHK7Q-tcgA8jR0.js";var n=(n,r)=>t.lang.round(e.parse(n)[r]);export{n as t};
@@ -1 +0,0 @@
1
- import{h as e}from"./src-9MKexpFu.js";var t=class{constructor(e){this.init=e,this.records=this.init()}static{e(this,`ImperativeState`)}reset(){this.records=this.init()}};export{t};
@@ -1 +0,0 @@
1
- import{h as e,p as t}from"./src-9MKexpFu.js";import{x as n}from"./chunk-CSCIHK7Q-tcgA8jR0.js";var r=e(e=>{let{securityLevel:r}=n(),i=t(`body`);return r===`sandbox`&&(i=t((t(`#i${e}`).node()?.contentDocument??document).body)),i.select(`#${e}`)},`selectSvgElement`);export{r as t};
@@ -1 +0,0 @@
1
- import{h as e}from"./src-9MKexpFu.js";import"./chunk-CSCIHK7Q-tcgA8jR0.js";import"./chunk-5ZQYHXKU-DZ5cvCDV.js";import"./chunk-O5CBEL6O-CbNGK3Te.js";import"./chunk-FMBD7UC4-DlpmhBYg.js";import"./chunk-BSJP7CBP-CP_f908b.js";import"./chunk-L5ZTLDWV-BjVXSZnt.js";import"./chunk-ND2GUHAM-kWh41zUn.js";import"./chunk-55IACEB6-yXpL8wjV.js";import"./chunk-2J33WTMH-tvuzKhdK.js";import"./chunk-NZK2D7GU-CDrIi44_.js";import"./chunk-3OPIFGDE-D_nBoD9w.js";import"./chunk-KSCS5N6A-BkfieXpV.js";import"./chunk-LZXEDZCA-CaAWmy4Q.js";import{i as t,n,r,t as i}from"./chunk-727SXJPM-CJjgOWmY.js";var a={parser:n,get db(){return new i},renderer:r,styles:t,init:e(e=>{e.class||={},e.class.arrowMarkerAbsolute=e.arrowMarkerAbsolute},`init`)};export{a as diagram};
@@ -1 +0,0 @@
1
- import{h as e}from"./src-9MKexpFu.js";import"./chunk-CSCIHK7Q-tcgA8jR0.js";import"./chunk-5ZQYHXKU-DZ5cvCDV.js";import"./chunk-O5CBEL6O-CbNGK3Te.js";import"./chunk-FMBD7UC4-DlpmhBYg.js";import"./chunk-BSJP7CBP-CP_f908b.js";import"./chunk-L5ZTLDWV-BjVXSZnt.js";import"./chunk-ND2GUHAM-kWh41zUn.js";import"./chunk-55IACEB6-yXpL8wjV.js";import"./chunk-2J33WTMH-tvuzKhdK.js";import"./chunk-NZK2D7GU-CDrIi44_.js";import"./chunk-3OPIFGDE-D_nBoD9w.js";import"./chunk-KSCS5N6A-BkfieXpV.js";import"./chunk-LZXEDZCA-CaAWmy4Q.js";import{i as t,n,r,t as i}from"./chunk-727SXJPM-CJjgOWmY.js";var a={parser:n,get db(){return new i},renderer:r,styles:t,init:e(e=>{e.class||={},e.class.arrowMarkerAbsolute=e.arrowMarkerAbsolute},`init`)};export{a as diagram};
@@ -1 +0,0 @@
1
- import{h as e}from"./src-9MKexpFu.js";import"./chunk-CSCIHK7Q-tcgA8jR0.js";import"./chunk-5ZQYHXKU-DZ5cvCDV.js";import"./chunk-O5CBEL6O-CbNGK3Te.js";import"./chunk-BSJP7CBP-CP_f908b.js";import"./chunk-L5ZTLDWV-BjVXSZnt.js";import"./chunk-55IACEB6-yXpL8wjV.js";import"./chunk-2J33WTMH-tvuzKhdK.js";import"./chunk-NZK2D7GU-CDrIi44_.js";import"./chunk-3OPIFGDE-D_nBoD9w.js";import"./chunk-KSCS5N6A-BkfieXpV.js";import"./chunk-LZXEDZCA-CaAWmy4Q.js";import{i as t,n,r,t as i}from"./chunk-AQP2D5EJ-CQYQKXSE.js";var a={parser:n,get db(){return new i(2)},renderer:r,styles:t,init:e(e=>{e.state||={},e.state.arrowMarkerAbsolute=e.arrowMarkerAbsolute},`init`)};export{a as diagram};
@@ -1,2 +0,0 @@
1
- import { d as getProjectStorageDir } from "./git-Czo96ymM.mjs";
2
- export { getProjectStorageDir };
@@ -1,60 +0,0 @@
1
- import { join } from "node:path";
2
- import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
3
- import { homedir } from "node:os";
4
- //#region src/lib/settings.ts
5
- const CONFIG_DIR = join(homedir(), ".config", "diffing");
6
- const SETTINGS_FILE = join(CONFIG_DIR, "settings.json");
7
- const DEFAULTS = {
8
- defaultMode: "web",
9
- staged: true,
10
- untracked: true,
11
- diffStyle: "split",
12
- defaultTabSize: 4,
13
- theme: "rose-pine",
14
- editorIDE: "default",
15
- lineDiffType: "word",
16
- lineWrap: false,
17
- diffIndicators: "classic",
18
- showLineNumbers: true,
19
- hunkSeparators: "line-info",
20
- lineHoverHighlight: "both",
21
- fontSize: 13,
22
- expandContextByDefault: false,
23
- collapsedContextThreshold: 10,
24
- expansionLineCount: 20,
25
- haptics: true,
26
- sounds: true,
27
- uiFont: null,
28
- monoFont: null,
29
- density: "comfortable",
30
- autoCollapseLineThreshold: 400,
31
- requireViewAllBeforeSend: false,
32
- showStatusBar: true,
33
- savedReplies: [],
34
- ignoreSpaceChange: false,
35
- ignoreAllSpace: false
36
- };
37
- function loadSettings() {
38
- try {
39
- const data = readFileSync(SETTINGS_FILE, "utf-8");
40
- const settings = {
41
- ...DEFAULTS,
42
- ...JSON.parse(data)
43
- };
44
- if (settings.defaultMode !== "web" && settings.defaultMode !== "tui") settings.defaultMode = DEFAULTS.defaultMode;
45
- return settings;
46
- } catch {
47
- return { ...DEFAULTS };
48
- }
49
- }
50
- function saveSettings(settings) {
51
- const merged = {
52
- ...loadSettings(),
53
- ...settings
54
- };
55
- mkdirSync(CONFIG_DIR, { recursive: true });
56
- writeFileSync(SETTINGS_FILE, JSON.stringify(merged, null, 2));
57
- return merged;
58
- }
59
- //#endregion
60
- export { saveSettings as n, loadSettings as t };