dsh-zen-remote 2.3.11 → 2.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (249) hide show
  1. package/CHANGELOG.md +45 -78
  2. package/README.md +94 -84
  3. package/README.zh-CN.md +90 -81
  4. package/bin/zen-remote.mjs +5 -0
  5. package/docs/interface.md +6 -6
  6. package/docs/remote-access.en.md +6 -4
  7. package/docs/remote-access.md +6 -4
  8. package/dsh-push.mjs +96 -10
  9. package/lib/adapters/dsh-better-sidebar/index.js +7 -3
  10. package/lib/adapters/dsh-better-sidebar/index.js.map +1 -1
  11. package/lib/admin-routes.js +10 -2
  12. package/lib/admin-routes.js.map +1 -1
  13. package/lib/cli/args.js +251 -0
  14. package/lib/cli/args.js.map +1 -0
  15. package/lib/cli/bootstrap.js +449 -0
  16. package/lib/cli/bootstrap.js.map +1 -0
  17. package/lib/cli/command-setup.js +484 -0
  18. package/lib/cli/command-setup.js.map +1 -0
  19. package/lib/cli/commands-client.js +359 -0
  20. package/lib/cli/commands-client.js.map +1 -0
  21. package/lib/cli/commands-host.js +1108 -0
  22. package/lib/cli/commands-host.js.map +1 -0
  23. package/lib/cli/commands-status.js +279 -0
  24. package/lib/cli/commands-status.js.map +1 -0
  25. package/lib/cli/config-writer.js +334 -0
  26. package/lib/cli/config-writer.js.map +1 -0
  27. package/lib/cli/context.js +10 -0
  28. package/lib/cli/context.js.map +1 -0
  29. package/lib/cli/i18n.js +620 -0
  30. package/lib/cli/i18n.js.map +1 -0
  31. package/lib/cli/ipc-client.js +160 -0
  32. package/lib/cli/ipc-client.js.map +1 -0
  33. package/lib/cli/ipc-server.js +464 -0
  34. package/lib/cli/ipc-server.js.map +1 -0
  35. package/lib/cli/main.js +245 -0
  36. package/lib/cli/main.js.map +1 -0
  37. package/lib/cli/qr-terminal.js +48 -0
  38. package/lib/cli/qr-terminal.js.map +1 -0
  39. package/lib/client-data/qr.js +286 -0
  40. package/lib/client-data/qr.js.map +1 -0
  41. package/lib/client-routes.js +308 -25
  42. package/lib/client-routes.js.map +1 -1
  43. package/lib/client.js +1013 -229
  44. package/lib/config.js +50 -12
  45. package/lib/config.js.map +1 -1
  46. package/lib/debug-report.js +28 -1
  47. package/lib/debug-report.js.map +1 -1
  48. package/lib/fetch-route-intercept.js +334 -26
  49. package/lib/fetch-route-intercept.js.map +1 -1
  50. package/lib/index.js +608 -375
  51. package/lib/index.js.map +1 -1
  52. package/lib/intercept.js +1833 -280
  53. package/lib/intercept.js.map +1 -1
  54. package/lib/lan-gate-server.cjs +36 -10
  55. package/lib/merge-streams.js +103 -11
  56. package/lib/merge-streams.js.map +1 -1
  57. package/lib/plugin-route-intercept.js +93 -63
  58. package/lib/plugin-route-intercept.js.map +1 -1
  59. package/lib/relay-access.js +8 -1
  60. package/lib/relay-access.js.map +1 -1
  61. package/lib/relay-client.js +133 -4
  62. package/lib/relay-client.js.map +1 -1
  63. package/lib/relay-pool.js +275 -0
  64. package/lib/relay-pool.js.map +1 -0
  65. package/lib/relay-server.js +269 -17
  66. package/lib/relay-server.js.map +1 -1
  67. package/lib/restart-fields.js +6 -4
  68. package/lib/restart-fields.js.map +1 -1
  69. package/lib/share-ops.js +68 -0
  70. package/lib/share-ops.js.map +1 -1
  71. package/lib/share-store.js +65 -27
  72. package/lib/share-store.js.map +1 -1
  73. package/lib/state-store.js +400 -0
  74. package/lib/state-store.js.map +1 -0
  75. package/lib/types/adapters/dsh-better-sidebar/index.d.ts +3 -2
  76. package/lib/types/adapters/dsh-better-sidebar/index.d.ts.map +1 -1
  77. package/lib/types/admin-routes.d.ts.map +1 -1
  78. package/lib/types/cli/args.d.ts +78 -0
  79. package/lib/types/cli/args.d.ts.map +1 -0
  80. package/lib/types/cli/bootstrap.d.ts +170 -0
  81. package/lib/types/cli/bootstrap.d.ts.map +1 -0
  82. package/lib/types/cli/command-setup.d.ts +72 -0
  83. package/lib/types/cli/command-setup.d.ts.map +1 -0
  84. package/lib/types/cli/commands-client.d.ts +36 -0
  85. package/lib/types/cli/commands-client.d.ts.map +1 -0
  86. package/lib/types/cli/commands-host.d.ts +82 -0
  87. package/lib/types/cli/commands-host.d.ts.map +1 -0
  88. package/lib/types/cli/commands-status.d.ts +46 -0
  89. package/lib/types/cli/commands-status.d.ts.map +1 -0
  90. package/lib/types/cli/config-writer.d.ts +92 -0
  91. package/lib/types/cli/config-writer.d.ts.map +1 -0
  92. package/lib/types/cli/context.d.ts +39 -0
  93. package/lib/types/cli/context.d.ts.map +1 -0
  94. package/lib/types/cli/i18n.d.ts +32 -0
  95. package/lib/types/cli/i18n.d.ts.map +1 -0
  96. package/lib/types/cli/ipc-client.d.ts +83 -0
  97. package/lib/types/cli/ipc-client.d.ts.map +1 -0
  98. package/lib/types/cli/ipc-server.d.ts +113 -0
  99. package/lib/types/cli/ipc-server.d.ts.map +1 -0
  100. package/lib/types/cli/main.d.ts +57 -0
  101. package/lib/types/cli/main.d.ts.map +1 -0
  102. package/lib/types/cli/qr-terminal.d.ts +17 -0
  103. package/lib/types/cli/qr-terminal.d.ts.map +1 -0
  104. package/lib/types/client/RemoteStatusIcon.d.ts.map +1 -1
  105. package/lib/types/client/current-session-report.d.ts +4 -0
  106. package/lib/types/client/current-session-report.d.ts.map +1 -1
  107. package/lib/types/client/effects/model-group-side.d.ts.map +1 -1
  108. package/lib/types/client/effects/remote-session.d.ts.map +1 -1
  109. package/lib/types/client/locales.d.ts +47 -3
  110. package/lib/types/client/locales.d.ts.map +1 -1
  111. package/lib/types/client/settings/SettingsSection.d.ts.map +1 -1
  112. package/lib/types/client/settings/settings-css.d.ts +1 -1
  113. package/lib/types/client/settings/settings-css.d.ts.map +1 -1
  114. package/lib/types/client/styles/remote-session.css.d.ts +1 -1
  115. package/lib/types/client/styles/remote-session.css.d.ts.map +1 -1
  116. package/lib/types/client/wizard/GatewayWizard.d.ts.map +1 -1
  117. package/lib/types/client/wizard/cards/ProxyCard.d.ts.map +1 -1
  118. package/lib/types/client/wizard/wizard-css.d.ts +1 -1
  119. package/lib/types/client/wizard/wizard-css.d.ts.map +1 -1
  120. package/lib/types/client-data/model-group-side.d.ts +23 -2
  121. package/lib/types/client-data/model-group-side.d.ts.map +1 -1
  122. package/lib/types/client-data/remote-status.d.ts +47 -1
  123. package/lib/types/client-data/remote-status.d.ts.map +1 -1
  124. package/lib/types/client-data/settings-form.d.ts +85 -1
  125. package/lib/types/client-data/settings-form.d.ts.map +1 -1
  126. package/lib/types/client-data/wizard.d.ts +56 -1
  127. package/lib/types/client-data/wizard.d.ts.map +1 -1
  128. package/lib/types/client-routes.d.ts +25 -1
  129. package/lib/types/client-routes.d.ts.map +1 -1
  130. package/lib/types/config.d.ts +40 -14
  131. package/lib/types/config.d.ts.map +1 -1
  132. package/lib/types/debug-report.d.ts.map +1 -1
  133. package/lib/types/fetch-route-intercept.d.ts +66 -8
  134. package/lib/types/fetch-route-intercept.d.ts.map +1 -1
  135. package/lib/types/index.d.ts +9 -2
  136. package/lib/types/index.d.ts.map +1 -1
  137. package/lib/types/intercept.d.ts +72 -10
  138. package/lib/types/intercept.d.ts.map +1 -1
  139. package/lib/types/merge-streams.d.ts +79 -1
  140. package/lib/types/merge-streams.d.ts.map +1 -1
  141. package/lib/types/plugin-route-intercept.d.ts +25 -9
  142. package/lib/types/plugin-route-intercept.d.ts.map +1 -1
  143. package/lib/types/relay-access.d.ts +3 -1
  144. package/lib/types/relay-access.d.ts.map +1 -1
  145. package/lib/types/relay-client.d.ts +23 -2
  146. package/lib/types/relay-client.d.ts.map +1 -1
  147. package/lib/types/relay-pool.d.ts +148 -0
  148. package/lib/types/relay-pool.d.ts.map +1 -0
  149. package/lib/types/relay-server.d.ts +30 -3
  150. package/lib/types/relay-server.d.ts.map +1 -1
  151. package/lib/types/restart-fields.d.ts +5 -5
  152. package/lib/types/restart-fields.d.ts.map +1 -1
  153. package/lib/types/share-ops.d.ts +47 -1
  154. package/lib/types/share-ops.d.ts.map +1 -1
  155. package/lib/types/share-store.d.ts.map +1 -1
  156. package/lib/types/state-store.d.ts +179 -0
  157. package/lib/types/state-store.d.ts.map +1 -0
  158. package/lib/types/upload-limits.d.ts +15 -0
  159. package/lib/types/upload-limits.d.ts.map +1 -1
  160. package/lib/types/virtual-id.d.ts +21 -0
  161. package/lib/types/virtual-id.d.ts.map +1 -1
  162. package/lib/types/wizard/probe.d.ts.map +1 -1
  163. package/lib/types/wizard/proxy-snippets.d.ts +3 -0
  164. package/lib/types/wizard/proxy-snippets.d.ts.map +1 -1
  165. package/lib/types/wizard/routes.d.ts +1 -0
  166. package/lib/types/wizard/routes.d.ts.map +1 -1
  167. package/lib/types/wizard/status.d.ts +9 -0
  168. package/lib/types/wizard/status.d.ts.map +1 -1
  169. package/lib/types/wizard/verify.d.ts +3 -0
  170. package/lib/types/wizard/verify.d.ts.map +1 -1
  171. package/lib/upload-limits.js +15 -0
  172. package/lib/upload-limits.js.map +1 -1
  173. package/lib/virtual-id.js +60 -0
  174. package/lib/virtual-id.js.map +1 -1
  175. package/lib/wizard/probe.js +46 -1
  176. package/lib/wizard/probe.js.map +1 -1
  177. package/lib/wizard/proxy-snippets.js +14 -1
  178. package/lib/wizard/proxy-snippets.js.map +1 -1
  179. package/lib/wizard/routes.js +23 -4
  180. package/lib/wizard/routes.js.map +1 -1
  181. package/lib/wizard/status.js +21 -0
  182. package/lib/wizard/status.js.map +1 -1
  183. package/lib/wizard/verify.js +31 -8
  184. package/lib/wizard/verify.js.map +1 -1
  185. package/package.json +8 -4
  186. package/pwa/icons/badge-96.png +0 -0
  187. package/pwa/icons/badge.svg +1 -0
  188. package/pwa/manifest.json +2 -1
  189. package/pwa/sw.js +3 -1
  190. package/scripts/check-debug-report.mjs +41 -1
  191. package/scripts/check-settings-form.mjs +14 -3
  192. package/scripts/check-settings-view.mjs +247 -0
  193. package/scripts/check-wizard-ui.mjs +37 -0
  194. package/src/adapters/dsh-better-sidebar/index.ts +7 -3
  195. package/src/admin-routes.ts +10 -2
  196. package/src/cli/args.ts +289 -0
  197. package/src/cli/bootstrap.ts +569 -0
  198. package/src/cli/command-setup.ts +540 -0
  199. package/src/cli/commands-client.ts +369 -0
  200. package/src/cli/commands-host.ts +1127 -0
  201. package/src/cli/commands-status.ts +296 -0
  202. package/src/cli/config-writer.ts +354 -0
  203. package/src/cli/context.ts +38 -0
  204. package/src/cli/i18n.ts +645 -0
  205. package/src/cli/ipc-client.ts +216 -0
  206. package/src/cli/ipc-server.ts +531 -0
  207. package/src/cli/main.ts +285 -0
  208. package/src/cli/qr-terminal.ts +49 -0
  209. package/src/client/RemoteStatusIcon.tsx +4 -1
  210. package/src/client/current-session-report.ts +28 -4
  211. package/src/client/effects/model-group-side.ts +19 -5
  212. package/src/client/effects/remote-session.ts +26 -6
  213. package/src/client/locales.ts +96 -6
  214. package/src/client/settings/SettingsSection.tsx +287 -92
  215. package/src/client/settings/settings-css.ts +18 -0
  216. package/src/client/styles/remote-session.css.ts +15 -1
  217. package/src/client/wizard/GatewayWizard.tsx +470 -109
  218. package/src/client/wizard/cards/ProxyCard.tsx +2 -1
  219. package/src/client/wizard/wizard-css.ts +23 -0
  220. package/src/client-data/model-group-side.ts +37 -10
  221. package/src/client-data/remote-status.ts +112 -17
  222. package/src/client-data/settings-form.ts +164 -8
  223. package/src/client-data/wizard.ts +112 -2
  224. package/src/client-routes.ts +334 -26
  225. package/src/config.ts +62 -16
  226. package/src/debug-report.ts +27 -1
  227. package/src/fetch-route-intercept.ts +381 -32
  228. package/src/index.ts +608 -380
  229. package/src/intercept.ts +1866 -286
  230. package/src/merge-streams.ts +155 -10
  231. package/src/plugin-route-intercept.ts +120 -71
  232. package/src/relay-access.ts +14 -3
  233. package/src/relay-client.ts +163 -5
  234. package/src/relay-pool.ts +387 -0
  235. package/src/relay-server.ts +312 -16
  236. package/src/restart-fields.ts +6 -4
  237. package/src/share-ops.ts +82 -1
  238. package/src/share-store.ts +59 -26
  239. package/src/state-store.ts +428 -0
  240. package/src/upload-limits.ts +16 -0
  241. package/src/virtual-id.ts +57 -0
  242. package/src/wizard/probe.ts +54 -2
  243. package/src/wizard/proxy-snippets.ts +17 -2
  244. package/src/wizard/routes.ts +24 -5
  245. package/src/wizard/status.ts +28 -0
  246. package/src/wizard/verify.ts +33 -11
  247. package/AGENTS.md +0 -185
  248. package/docs/adr/0001-plugin-bridge-forwards-plugin-routes.md +0 -15
  249. package/docs/adr/0002-relay-emulates-websocket.md +0 -8
@@ -0,0 +1 @@
1
+ {"version":3,"file":"i18n.js","sourceRoot":"","sources":["../../src/cli/i18n.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AASH,MAAM,EAAE,GAAqC;IAC3C,8EAA8E;IAC9E,YAAY,EAAE,4CAA4C;IAC1D,YAAY,EAAE,6BAA6B;IAC3C,kBAAkB,EAAE,8BAA8B;IAClD,eAAe,EAAE,KAAK;IACtB,oBAAoB,EAAE,4BAA4B;IAClD,qBAAqB,EAAE,wBAAwB;IAC/C,yBAAyB,EAAE,qDAAqD;IAChF,0BAA0B,EAAE,qDAAqD;IACjF,yBAAyB,EAAE,2CAA2C;IACtE,2BAA2B,EAAE,+DAA+D;IAC5F,yBAAyB,EAAE,iCAAiC;IAC5D,cAAc,EAAE,KAAK;IACrB,kBAAkB,EAAE,kCAAkC;IACtD,kBAAkB,EAAE,sBAAsB;IAC1C,oBAAoB,EAAE,2CAA2C;IACjE,kBAAkB,EAAE,4CAA4C;IAChE,iBAAiB,EAAE,kCAAkC;IACrD,oBAAoB,EAAE,iCAAiC;IACvD,mBAAmB,EAAE,yCAAyC;IAC9D,kBAAkB,EAAE,uCAAuC;IAC3D,qBAAqB,EAAE,wCAAwC;IAC/D,qBAAqB,EAAE,0DAA0D;IACjF,oBAAoB,EAAE,qBAAqB;IAC3C,qBAAqB,EAAE,uCAAuC;IAC9D,mBAAmB,EAAE,6BAA6B;IAClD,uBAAuB,EAAE,0CAA0C;IACnE,uBAAuB,EAAE,4CAA4C;IACrE,sBAAsB,EAAE,8CAA8C;IACtE,mBAAmB,EAAE,6CAA6C;IAClE,wBAAwB,EAAE,4CAA4C;IACtE,qBAAqB,EAAE,8BAA8B;IACrD,kBAAkB,EAAE,mBAAmB;IACvC,kBAAkB,EAAE,sBAAsB;IAC1C,iBAAiB,EAAE,4BAA4B;IAC/C,aAAa,EAAE,2CAA2C;IAE1D,gFAAgF;IAChF,YAAY,EAAE,GAAG;IACjB,WAAW,EAAE,GAAG;IAChB,aAAa,EAAE,IAAI;IACnB,eAAe,EAAE,IAAI;IACrB,cAAc,EAAE,IAAI;IACpB,aAAa,EAAE,IAAI;IAEnB,kFAAkF;IAClF,oBAAoB,EAAE,iDAAiD;IACvE,yBAAyB,EAAE,iDAAiD;IAC5E,kBAAkB,EAAE,2CAA2C;IAC/D,2BAA2B,EAAE,4CAA4C;IACzE,6BAA6B,EAAE,8CAA8C;IAC7E,6BAA6B,EAAE,wEAAwE;IACvG,iBAAiB,EAAE,kDAAkD;IACrE,qBAAqB,EAAE,gFAAgF;IACvG,mBAAmB,EAAE,iDAAiD;IACtE,oBAAoB,EAAE,qEAAqE;IAC3F,qBAAqB,EAAE,+EAA+E;IACtG,gBAAgB,EAAE,kEAAkE;IAEpF,mFAAmF;IACnF,kBAAkB,EAAE,yCAAyC;IAC7D,mBAAmB,EAAE,2BAA2B;IAChD,uBAAuB,EAAE,kCAAkC;IAC3D,wBAAwB,EAAE,gCAAgC;IAC1D,qBAAqB,EAAE,mBAAmB;IAC1C,iBAAiB,EAAE,0DAA0D;IAC7E,gBAAgB,EAAE,8CAA8C;IAChE,cAAc,EAAE,iBAAiB;IAEjC,oFAAoF;IACpF,cAAc,EAAE,sCAAsC;IACtD,gBAAgB,EAAE,6BAA6B;IAC/C,sBAAsB,EAAE,+BAA+B;IACvD,wBAAwB,EAAE,gCAAgC;IAC1D,qBAAqB,EAAE,kDAAkD;IACzE,iBAAiB,EAAE,4BAA4B;IAC/C,gBAAgB,EAAE,4BAA4B;IAC9C,gBAAgB,EAAE,2CAA2C;IAC7D,eAAe,EAAE,uTAAuT;IAExU,wEAAwE;IACxE,qBAAqB,EAAE,IAAI;IAC3B,kBAAkB,EAAE,iCAAiC;IACrD,wBAAwB,EAAE,uBAAuB;IACjD,yBAAyB,EAAE,mCAAmC;IAC9D,wBAAwB,EAAE,cAAc;IACxC,mBAAmB,EAAE,mBAAmB;IACxC,gBAAgB,EAAE,cAAc;IAChC,sBAAsB,EAAE,YAAY;IACpC,iBAAiB,EAAE,OAAO;IAC1B,iBAAiB,EAAE,OAAO;IAE1B,qFAAqF;IACrF,kBAAkB,EAAE,0BAA0B;IAC9C,oBAAoB,EAAE,mBAAmB;IACzC,kBAAkB,EAAE,gBAAgB;IACpC,kBAAkB,EAAE,aAAa;IACjC,oBAAoB,EAAE,aAAa;IACnC,sBAAsB,EAAE,gBAAgB;IACxC,mBAAmB,EAAE,UAAU;IAC/B,uBAAuB,EAAE,kBAAkB;IAC3C,6BAA6B,EAAE,OAAO;IACtC,yBAAyB,EAAE,QAAQ;IACnC,qBAAqB,EAAE,aAAa;IACpC,uBAAuB,EAAE,kBAAkB;IAC3C,0BAA0B,EAAE,kBAAkB;IAC9C,2BAA2B,EAAE,8BAA8B;IAC3D,wBAAwB,EAAE,KAAK;IAC/B,wBAAwB,EAAE,KAAK;IAC/B,qBAAqB,EAAE,iBAAiB;IACxC,wBAAwB,EAAE,0BAA0B;IACpD,4BAA4B,EAAE,sBAAsB;IACpD,qBAAqB,EAAE,YAAY;IACnC,2BAA2B,EAAE,6BAA6B;IAC1D,sBAAsB,EAAE,KAAK;IAC7B,2BAA2B,EAAE,OAAO;IACpC,wBAAwB,EAAE,QAAQ;IAClC,0BAA0B,EAAE,kBAAkB;IAC9C,iCAAiC,EAAE,SAAS;IAC5C,2BAA2B,EAAE,iBAAiB;IAC9C,yBAAyB,EAAE,cAAc;IACzC,oBAAoB,EAAE,kBAAkB;IACxC,yBAAyB,EAAE,mBAAmB;IAC9C,mBAAmB,EAAE,kBAAkB;IACvC,eAAe,EAAE,eAAe;IAChC,iBAAiB,EAAE,KAAK;IACxB,eAAe,EAAE,IAAI;IACrB,gBAAgB,EAAE,IAAI;IACtB,mBAAmB,EAAE,KAAK;IAC1B,gBAAgB,EAAE,mBAAmB;IACrC,qBAAqB,EAAE,gBAAgB;IAEvC,uFAAuF;IACvF,oBAAoB,EAAE,WAAW;IACjC,gBAAgB,EAAE,gCAAgC;IAClD,kBAAkB,EAAE,8BAA8B;IAClD,yBAAyB,EAAE,iDAAiD;IAC5E,uBAAuB,EAAE,wBAAwB;IACjD,uBAAuB,EAAE,WAAW;IACpC,mBAAmB,EAAE,wBAAwB;IAC7C,oBAAoB,EAAE,wBAAwB;IAC9C,0BAA0B,EAAE,uCAAuC;IACnE,uBAAuB,EAAE,2CAA2C;IACpE,kBAAkB,EAAE,2BAA2B;IAC/C,sBAAsB,EAAE,KAAK;IAC7B,uBAAuB,EAAE,oBAAoB;IAC7C,qBAAqB,EAAE,cAAc;IACrC,yBAAyB,EAAE,sBAAsB;IACjD,yBAAyB,EAAE,sBAAsB;IACjD,sBAAsB,EAAE,8BAA8B;IACtD,mBAAmB,EAAE,OAAO;IAC5B,oBAAoB,EAAE,yBAAyB;IAC/C,oBAAoB,EAAE,yBAAyB;IAC/C,oBAAoB,EAAE,yBAAyB;IAC/C,2BAA2B,EAAE,wDAAwD;IACrF,iBAAiB,EAAE,uBAAuB;IAC1C,mBAAmB,EAAE,8BAA8B;IACnD,0BAA0B,EAAE,sCAAsC;IAClE,yBAAyB,EAAE,4DAA4D;IACvF,mBAAmB,EAAE,qDAAqD;IAC1E,mBAAmB,EAAE,YAAY;IACjC,sBAAsB,EAAE,4CAA4C;IACpE,yBAAyB,EAAE,0CAA0C;IACrE,wBAAwB,EAAE,mBAAmB;IAC7C,0BAA0B,EAAE,wBAAwB;IACpD,0BAA0B,EAAE,qBAAqB;IACjD,wBAAwB,EAAE,eAAe;IACzC,mBAAmB,EAAE,MAAM;IAC3B,sBAAsB,EAAE,iDAAiD;IACzE,2BAA2B,EAAE,uCAAuC;IACpE,4BAA4B,EAAE,gBAAgB;IAC9C,qBAAqB,EAAE,YAAY;IACnC,oBAAoB,EAAE,WAAW;IACjC,uBAAuB,EAAE,2BAA2B;IACpD,sBAAsB,EAAE,6BAA6B;IACrD,oBAAoB,EAAE,oEAAoE;IAC1F,cAAc,EAAE,gBAAgB;IAEhC,yFAAyF;IACzF,uBAAuB,EAAE,+DAA+D;IACxF,oBAAoB,EAAE,WAAW;IACjC,oBAAoB,EAAE,sBAAsB;IAC5C,yBAAyB,EAAE,mEAAmE;IAC9F,2BAA2B,EAAE,4DAA4D;IACzF,yBAAyB,EAAE,gBAAgB;IAC3C,8BAA8B,EAAE,YAAY;IAC5C,sBAAsB,EAAE,YAAY;IACpC,2BAA2B,EAAE,wBAAwB;IACrD,qBAAqB,EAAE,oCAAoC;IAC3D,0BAA0B,EAAE,yBAAyB;IACrD,yBAAyB,EAAE,eAAe;IAC1C,mBAAmB,EAAE,gBAAgB;IACrC,mBAAmB,EAAE,4BAA4B;IACjD,kBAAkB,EAAE,eAAe;IACnC,wBAAwB,EAAE,kBAAkB;IAC5C,yBAAyB,EAAE,4BAA4B;IACvD,yBAAyB,EAAE,2BAA2B;IACtD,sBAAsB,EAAE,aAAa;IACrC,uBAAuB,EAAE,4BAA4B;IACrD,4BAA4B,EAAE,uCAAuC;IACrE,6BAA6B,EAAE,cAAc;IAC7C,qBAAqB,EAAE,SAAS;IAChC,kBAAkB,EAAE,YAAY;IAChC,gBAAgB,EAAE,aAAa;IAC/B,mBAAmB,EAAE,aAAa;IAClC,mBAAmB,EAAE,YAAY;IACjC,iBAAiB,EAAE,MAAM;IACzB,qBAAqB,EAAE,4BAA4B;IACnD,iBAAiB,EAAE,cAAc;IACjC,oBAAoB,EAAE,iCAAiC;IACvD,gBAAgB,EAAE,uBAAuB;IACzC,yBAAyB,EAAE,qBAAqB;IAChD,wBAAwB,EAAE,sBAAsB;IAChD,kBAAkB,EAAE,sBAAsB;IAC1C,mBAAmB,EAAE,iBAAiB;IAEtC,yFAAyF;IACzF,uBAAuB,EAAE,WAAW;IACpC,yBAAyB,EAAE,aAAa;IACxC,sBAAsB,EAAE,yBAAyB;IACjD,0BAA0B,EAAE,iCAAiC;IAC7D,2BAA2B,EAAE,0CAA0C;IACvE,qBAAqB,EAAE,aAAa;IACpC,wBAAwB,EAAE,UAAU;IACpC,yBAAyB,EAAE,6BAA6B;IACxD,uBAAuB,EAAE,uCAAuC;IAChE,4BAA4B,EAAE,2BAA2B;IACzD,2BAA2B,EAAE,wBAAwB;IACrD,uBAAuB,EAAE,QAAQ;IACjC,uBAAuB,EAAE,YAAY;IACrC,wBAAwB,EAAE,kBAAkB;IAC5C,wBAAwB,EAAE,wCAAwC;IAClE,0BAA0B,EAAE,qCAAqC;IACjE,4BAA4B,EAAE,WAAW;IACzC,8BAA8B,EAAE,cAAc;IAC9C,iCAAiC,EAAE,6BAA6B;IAChE,qBAAqB,EAAE,kBAAkB;IACzC,wBAAwB,EAAE,aAAa;IACvC,0BAA0B,EAAE,SAAS;IACrC,sBAAsB,EAAE,kBAAkB;IAC1C,sBAAsB,EAAE,UAAU;IAClC,0BAA0B,EAAE,8CAA8C;IAC1E,yBAAyB,EAAE,SAAS;IACpC,4BAA4B,EAAE,sDAAsD;IACpF,6BAA6B,EAAE,yCAAyC;IACxE,8BAA8B,EAAE,mCAAmC;IACnE,8BAA8B,EAAE,iBAAiB;IACjD,2BAA2B,EAAE,gCAAgC;IAC7D,gCAAgC,EAAE,SAAS;IAC3C,4BAA4B,EAAE,wBAAwB;IACtD,0BAA0B,EAAE,sBAAsB;IAClD,wBAAwB,EAAE,KAAK;IAC/B,4BAA4B,EAAE,wBAAwB;IACtD,mCAAmC,EAAE,0EAA0E;IAC/G,4BAA4B,EAAE,8CAA8C;IAC5E,0BAA0B,EAAE,yCAAyC;IACrE,uCAAuC,EAAE,UAAU;IACnD,wCAAwC,EAAE,WAAW;IACrD,2CAA2C,EAAE,YAAY;IACzD,8CAA8C,EAAE,UAAU;IAC1D,uCAAuC,EAAE,oDAAoD;IAC7F,uCAAuC,EAAE,oBAAoB;IAC7D,mCAAmC,EAAE,iBAAiB;IACtD,wCAAwC,EAAE,oBAAoB;IAC9D,sCAAsC,EAAE,mDAAmD;IAC3F,mCAAmC,EAAE,yBAAyB;IAC9D,wCAAwC,EAAE,0CAA0C;IACpF,wCAAwC,EAAE,uBAAuB;IACjE,qCAAqC,EAAE,uBAAuB;IAC9D,iCAAiC,EAAE,8BAA8B;IACjE,gCAAgC,EAAE,mBAAmB;IACrD,gCAAgC,EAAE,mBAAmB;IACrD,2CAA2C,EAAE,+DAA+D;IAC5G,iCAAiC,EAAE,+BAA+B;IAClE,6BAA6B,EAAE,4BAA4B;IAC3D,6BAA6B,EAAE,iBAAiB;IAChD,+BAA+B,EAAE,WAAW;IAC5C,yBAAyB,EAAE,qCAAqC;IAChE,yBAAyB,EAAE,wCAAwC;IACnE,eAAe,EAAE,8DAA8D;IAC/E,kBAAkB,EAAE,mCAAmC;IACvD,sBAAsB,EAAE,uBAAuB;IAC/C,wBAAwB,EAAE,uBAAuB;IACjD,sBAAsB,EAAE,qBAAqB;IAC7C,0BAA0B,EAAE,+FAA+F;IAC3H,0BAA0B,EAAE,gEAAgE;IAC5F,2BAA2B,EAAE,6OAA6O;IAC1Q,8BAA8B,EAAE,qCAAqC;IACrE,4BAA4B,EAAE,0BAA0B;IACxD,iCAAiC,EAAE,uDAAuD;CAC3F,CAAA;AAED,MAAM,EAAE,GAAqC;IAC3C,8EAA8E;IAC9E,YAAY,EAAE,8DAA8D;IAC5E,YAAY,EAAE,2CAA2C;IACzD,kBAAkB,EAAE,0FAA0F;IAC9G,eAAe,EAAE,WAAW;IAC5B,oBAAoB,EAAE,0DAA0D;IAChF,qBAAqB,EAAE,8DAA8D;IACrF,yBAAyB,EAAE,yEAAyE;IACpG,0BAA0B,EAAE,qEAAqE;IACjG,yBAAyB,EAAE,wDAAwD;IACnF,2BAA2B,EAAE,yEAAyE;IACtG,yBAAyB,EAAE,wCAAwC;IACnE,cAAc,EAAE,UAAU;IAC1B,kBAAkB,EAAE,+CAA+C;IACnE,kBAAkB,EAAE,sCAAsC;IAC1D,oBAAoB,EAAE,oEAAoE;IAC1F,kBAAkB,EAAE,0EAA0E;IAC9F,iBAAiB,EAAE,sEAAsE;IACzF,oBAAoB,EAAE,qEAAqE;IAC3F,mBAAmB,EAAE,gEAAgE;IACrF,kBAAkB,EAAE,oEAAoE;IACxF,qBAAqB,EAAE,0DAA0D;IACjF,qBAAqB,EAAE,uEAAuE;IAC9F,oBAAoB,EAAE,8BAA8B;IACpD,qBAAqB,EAAE,0CAA0C;IACjE,mBAAmB,EAAE,4DAA4D;IACjF,uBAAuB,EAAE,sDAAsD;IAC/E,uBAAuB,EAAE,6DAA6D;IACtF,sBAAsB,EAAE,0DAA0D;IAClF,mBAAmB,EAAE,sEAAsE;IAC3F,wBAAwB,EAAE,8DAA8D;IACxF,qBAAqB,EAAE,uCAAuC;IAC9D,kBAAkB,EAAE,iCAAiC;IACrD,kBAAkB,EAAE,6CAA6C;IACjE,iBAAiB,EAAE,yDAAyD;IAC5E,aAAa,EAAE,6EAA6E;IAE5F,gFAAgF;IAChF,YAAY,EAAE,KAAK;IACnB,WAAW,EAAE,IAAI;IACjB,aAAa,EAAE,MAAM;IACrB,eAAe,EAAE,QAAQ;IACzB,cAAc,EAAE,OAAO;IACvB,aAAa,EAAE,MAAM;IAErB,kFAAkF;IAClF,oBAAoB,EAAE,6EAA6E;IACnG,yBAAyB,EAAE,yFAAyF;IACpH,kBAAkB,EAAE,kEAAkE;IACtF,2BAA2B,EAAE,iGAAiG;IAC9H,6BAA6B,EAAE,mGAAmG;IAClI,6BAA6B,EAAE,yHAAyH;IACxJ,iBAAiB,EAAE,uHAAuH;IAC1I,qBAAqB,EAAE,sKAAsK;IAC7L,mBAAmB,EAAE,uIAAuI;IAC5J,oBAAoB,EAAE,iHAAiH;IACvI,qBAAqB,EAAE,gIAAgI;IACvJ,gBAAgB,EAAE,8GAA8G;IAEhI,mFAAmF;IACnF,kBAAkB,EAAE,yDAAyD;IAC7E,mBAAmB,EAAE,gDAAgD;IACrE,uBAAuB,EAAE,qDAAqD;IAC9E,wBAAwB,EAAE,oDAAoD;IAC9E,qBAAqB,EAAE,oCAAoC;IAC3D,iBAAiB,EAAE,iEAAiE;IACpF,gBAAgB,EAAE,iFAAiF;IACnG,cAAc,EAAE,4BAA4B;IAE5C,oFAAoF;IACpF,cAAc,EAAE,kDAAkD;IAClE,gBAAgB,EAAE,0DAA0D;IAC5E,sBAAsB,EAAE,oDAAoD;IAC5E,wBAAwB,EAAE,4DAA4D;IACtF,qBAAqB,EAAE,mEAAmE;IAC1F,iBAAiB,EAAE,sCAAsC;IACzD,gBAAgB,EAAE,iDAAiD;IACnE,gBAAgB,EAAE,4EAA4E;IAC9F,eAAe,EAAE,8YAA8Y;IAE/Z,iFAAiF;IACjF,qBAAqB,EAAE,SAAS;IAChC,kBAAkB,EAAE,oCAAoC;IACxD,wBAAwB,EAAE,mEAAmE;IAC7F,yBAAyB,EAAE,oFAAoF;IAC/G,wBAAwB,EAAE,cAAc;IACxC,mBAAmB,EAAE,kCAAkC;IACvD,gBAAgB,EAAE,wBAAwB;IAC1C,sBAAsB,EAAE,2CAA2C;IACnE,iBAAiB,EAAE,OAAO;IAC1B,iBAAiB,EAAE,OAAO;IAE1B,qFAAqF;IACrF,kBAAkB,EAAE,6DAA6D;IACjF,oBAAoB,EAAE,wCAAwC;IAC9D,kBAAkB,EAAE,mCAAmC;IACvD,kBAAkB,EAAE,sBAAsB;IAC1C,oBAAoB,EAAE,sBAAsB;IAC5C,sBAAsB,EAAE,2BAA2B;IACnD,mBAAmB,EAAE,cAAc;IACnC,uBAAuB,EAAE,iCAAiC;IAC1D,6BAA6B,EAAE,mBAAmB;IAClD,yBAAyB,EAAE,uBAAuB;IAClD,qBAAqB,EAAE,sBAAsB;IAC7C,uBAAuB,EAAE,6BAA6B;IACtD,0BAA0B,EAAE,wBAAwB;IACpD,2BAA2B,EAAE,oCAAoC;IACjE,wBAAwB,EAAE,SAAS;IACnC,wBAAwB,EAAE,aAAa;IACvC,qBAAqB,EAAE,yBAAyB;IAChD,wBAAwB,EAAE,2BAA2B;IACrD,4BAA4B,EAAE,0BAA0B;IACxD,qBAAqB,EAAE,gBAAgB;IACvC,2BAA2B,EAAE,+BAA+B;IAC5D,sBAAsB,EAAE,SAAS;IACjC,2BAA2B,EAAE,cAAc;IAC3C,wBAAwB,EAAE,kCAAkC;IAC5D,0BAA0B,EAAE,6CAA6C;IACzE,iCAAiC,EAAE,oCAAoC;IACvE,2BAA2B,EAAE,2BAA2B;IACxD,yBAAyB,EAAE,qBAAqB;IAChD,oBAAoB,EAAE,2CAA2C;IACjE,yBAAyB,EAAE,0CAA0C;IACrE,mBAAmB,EAAE,8BAA8B;IACnD,eAAe,EAAE,gBAAgB;IACjC,iBAAiB,EAAE,UAAU;IAC7B,eAAe,EAAE,QAAQ;IACzB,gBAAgB,EAAE,SAAS;IAC3B,mBAAmB,EAAE,YAAY;IACjC,gBAAgB,EAAE,oBAAoB;IACtC,qBAAqB,EAAE,8BAA8B;IAErD,uFAAuF;IACvF,oBAAoB,EAAE,8BAA8B;IACpD,gBAAgB,EAAE,6DAA6D;IAC/E,kBAAkB,EAAE,uCAAuC;IAC3D,yBAAyB,EAAE,sGAAsG;IACjI,uBAAuB,EAAE,qEAAqE;IAC9F,uBAAuB,EAAE,iCAAiC;IAC1D,mBAAmB,EAAE,qEAAqE;IAC1F,oBAAoB,EAAE,mDAAmD;IACzE,0BAA0B,EAAE,iCAAiC;IAC7D,uBAAuB,EAAE,8DAA8D;IACvF,kBAAkB,EAAE,8BAA8B;IAClD,sBAAsB,EAAE,eAAe;IACvC,uBAAuB,EAAE,wBAAwB;IACjD,qBAAqB,EAAE,6CAA6C;IACpE,yBAAyB,EAAE,mCAAmC;IAC9D,yBAAyB,EAAE,wCAAwC;IACnE,sBAAsB,EAAE,oEAAoE;IAC5F,mBAAmB,EAAE,oBAAoB;IACzC,oBAAoB,EAAE,wCAAwC;IAC9D,oBAAoB,EAAE,6CAA6C;IACnE,oBAAoB,EAAE,6CAA6C;IACnE,2BAA2B,EAAE,+GAA+G;IAC5I,iBAAiB,EAAE,uDAAuD;IAC1E,mBAAmB,EAAE,gDAAgD;IACrE,0BAA0B,EAAE,yEAAyE;IACrG,yBAAyB,EAAE,+EAA+E;IAC1G,mBAAmB,EAAE,uFAAuF;IAC5G,mBAAmB,EAAE,mCAAmC;IACxD,sBAAsB,EAAE,mGAAmG;IAC3H,yBAAyB,EAAE,0GAA0G;IACrI,wBAAwB,EAAE,yDAAyD;IACnF,0BAA0B,EAAE,qDAAqD;IACjF,0BAA0B,EAAE,qCAAqC;IACjE,wBAAwB,EAAE,uCAAuC;IACjE,mBAAmB,EAAE,wBAAwB;IAC7C,sBAAsB,EAAE,oFAAoF;IAC5G,2BAA2B,EAAE,+DAA+D;IAC5F,4BAA4B,EAAE,2BAA2B;IACzD,qBAAqB,EAAE,gCAAgC;IACvD,oBAAoB,EAAE,cAAc;IACpC,uBAAuB,EAAE,+BAA+B;IACxD,sBAAsB,EAAE,+BAA+B;IACvD,oBAAoB,EAAE,uFAAuF;IAC7G,cAAc,EAAE,6BAA6B;IAE7C,yFAAyF;IACzF,uBAAuB,EAAE,8EAA8E;IACvG,oBAAoB,EAAE,oCAAoC;IAC1D,oBAAoB,EAAE,oDAAoD;IAC1E,yBAAyB,EAAE,wGAAwG;IACnI,2BAA2B,EAAE,qGAAqG;IAClI,yBAAyB,EAAE,uCAAuC;IAClE,8BAA8B,EAAE,8CAA8C;IAC9E,sBAAsB,EAAE,uCAAuC;IAC/D,2BAA2B,EAAE,iEAAiE;IAC9F,qBAAqB,EAAE,4EAA4E;IACnG,0BAA0B,EAAE,mEAAmE;IAC/F,yBAAyB,EAAE,kDAAkD;IAC7E,mBAAmB,EAAE,wBAAwB;IAC7C,mBAAmB,EAAE,gCAAgC;IACrD,kBAAkB,EAAE,wBAAwB;IAC5C,wBAAwB,EAAE,+CAA+C;IACzE,yBAAyB,EAAE,oCAAoC;IAC/D,yBAAyB,EAAE,qCAAqC;IAChE,sBAAsB,EAAE,iBAAiB;IACzC,uBAAuB,EAAE,kCAAkC;IAC3D,4BAA4B,EAAE,wFAAwF;IACtH,6BAA6B,EAAE,0BAA0B;IACzD,qBAAqB,EAAE,6BAA6B;IACpD,kBAAkB,EAAE,eAAe;IACnC,gBAAgB,EAAE,iBAAiB;IACnC,mBAAmB,EAAE,0BAA0B;IAC/C,mBAAmB,EAAE,sBAAsB;IAC3C,iBAAiB,EAAE,aAAa;IAChC,qBAAqB,EAAE,qFAAqF;IAC5G,iBAAiB,EAAE,gDAAgD;IACnE,oBAAoB,EAAE,2EAA2E;IACjG,gBAAgB,EAAE,6DAA6D;IAC/E,yBAAyB,EAAE,sCAAsC;IACjE,wBAAwB,EAAE,6BAA6B;IACvD,kBAAkB,EAAE,sCAAsC;IAC1D,mBAAmB,EAAE,mBAAmB;IAExC,yFAAyF;IACzF,uBAAuB,EAAE,qBAAqB;IAC9C,yBAAyB,EAAE,oCAAoC;IAC/D,sBAAsB,EAAE,iCAAiC;IACzD,0BAA0B,EAAE,6CAA6C;IACzE,2BAA2B,EAAE,sEAAsE;IACnG,qBAAqB,EAAE,0BAA0B;IACjD,wBAAwB,EAAE,kCAAkC;IAC5D,yBAAyB,EAAE,oDAAoD;IAC/E,uBAAuB,EAAE,iHAAiH;IAC1I,4BAA4B,EAAE,0DAA0D;IACxF,2BAA2B,EAAE,2EAA2E;IACxG,uBAAuB,EAAE,iBAAiB;IAC1C,uBAAuB,EAAE,0BAA0B;IACnD,wBAAwB,EAAE,6DAA6D;IACvF,wBAAwB,EAAE,yCAAyC;IACnE,0BAA0B,EAAE,+CAA+C;IAC3E,4BAA4B,EAAE,4BAA4B;IAC1D,8BAA8B,EAAE,4BAA4B;IAC5D,iCAAiC,EAAE,mEAAmE;IACtG,qBAAqB,EAAE,4BAA4B;IACnD,wBAAwB,EAAE,sBAAsB;IAChD,0BAA0B,EAAE,gCAAgC;IAC5D,sBAAsB,EAAE,kCAAkC;IAC1D,sBAAsB,EAAE,yBAAyB;IACjD,0BAA0B,EAAE,wEAAwE;IACpG,yBAAyB,EAAE,0BAA0B;IACrD,4BAA4B,EAAE,qFAAqF;IACnH,6BAA6B,EAAE,uEAAuE;IACtG,8BAA8B,EAAE,2EAA2E;IAC3G,8BAA8B,EAAE,0CAA0C;IAC1E,2BAA2B,EAAE,sDAAsD;IACnF,gCAAgC,EAAE,4BAA4B;IAC9D,4BAA4B,EAAE,yCAAyC;IACvE,0BAA0B,EAAE,4CAA4C;IACxE,wBAAwB,EAAE,QAAQ;IAClC,4BAA4B,EAAE,qEAAqE;IACnG,mCAAmC,EAAE,6IAA6I;IAClL,4BAA4B,EAAE,0FAA0F;IACxH,0BAA0B,EAAE,iFAAiF;IAC7G,uCAAuC,EAAE,iCAAiC;IAC1E,wCAAwC,EAAE,oCAAoC;IAC9E,2CAA2C,EAAE,2CAA2C;IACxF,8CAA8C,EAAE,mCAAmC;IACnF,uCAAuC,EAAE,+HAA+H;IACxK,uCAAuC,EAAE,kDAAkD;IAC3F,mCAAmC,EAAE,iCAAiC;IACtE,wCAAwC,EAAE,2BAA2B;IACrE,sCAAsC,EAAE,gGAAgG;IACxI,mCAAmC,EAAE,2CAA2C;IAChF,wCAAwC,EAAE,mEAAmE;IAC7G,wCAAwC,EAAE,2CAA2C;IACrF,qCAAqC,EAAE,6CAA6C;IACpF,iCAAiC,EAAE,2CAA2C;IAC9E,gCAAgC,EAAE,qCAAqC;IACvE,gCAAgC,EAAE,0CAA0C;IAC5E,2CAA2C,EAAE,+GAA+G;IAC5J,iCAAiC,EAAE,8EAA8E;IACjH,6BAA6B,EAAE,8FAA8F;IAC7H,6BAA6B,EAAE,+BAA+B;IAC9D,+BAA+B,EAAE,iCAAiC;IAClE,yBAAyB,EAAE,sEAAsE;IACjG,yBAAyB,EAAE,+FAA+F;IAC1H,eAAe,EAAE,8DAA8D;IAC/E,kBAAkB,EAAE,wDAAwD;IAC5E,sBAAsB,EAAE,mCAAmC;IAC3D,wBAAwB,EAAE,oCAAoC;IAC9D,sBAAsB,EAAE,uDAAuD;IAC/E,0BAA0B,EAAE,gIAAgI;IAC5J,0BAA0B,EAAE,0FAA0F;IACtH,2BAA2B,EAAE,kPAAkP;IAC/Q,8BAA8B,EAAE,wEAAwE;IACxG,4BAA4B,EAAE,gDAAgD;IAC9E,iCAAiC,EAAE,0JAA0J;CAC9L,CAAA;AAED,MAAM,YAAY,GAAgE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAA;AAEpG;;;;;;GAMG;AACH,MAAM,UAAU,cAAc,CAAC,QAA4B,EAAE,GAAuB;IAClF,MAAM,IAAI,GAAG,QAAQ,EAAE,IAAI,EAAE,CAAC,WAAW,EAAE,CAAA;IAC3C,IAAI,IAAI,KAAK,IAAI;QAAE,OAAO,IAAI,CAAA;IAC9B,IAAI,IAAI,KAAK,IAAI;QAAE,OAAO,IAAI,CAAA;IAC9B,MAAM,IAAI,GAAG,GAAG,IAAI,OAAO,CAAC,GAAG,CAAA;IAC/B,MAAM,GAAG,GAAG,IAAI,CAAC,eAAe,EAAE,IAAI,EAAE,CAAC,WAAW,EAAE,CAAA;IACtD,IAAI,GAAG,KAAK,IAAI;QAAE,OAAO,IAAI,CAAA;IAC7B,IAAI,GAAG,KAAK,IAAI;QAAE,OAAO,IAAI,CAAA;IAC7B,MAAM,MAAM,GAAG,CAAC,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAA;IAC1E,OAAO,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAA;AAC1C,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAAC,IAAa;IAC5C,MAAM,KAAK,GAAG,YAAY,CAAC,IAAI,CAAC,CAAA;IAChC,MAAM,SAAS,GAAG,CAAC,GAAW,EAAE,MAAwC,EAAU,EAAE;QAClF,IAAI,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC,IAAI,YAAY,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,GAAG,CAAA;QACpD,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACzB,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;gBACnD,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,IAAI,GAAG,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAA;YACpD,CAAC;QACH,CAAC;QACD,OAAO,IAAI,CAAA;IACb,CAAC,CAAA;IACD,OAAO,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAA;AAClD,CAAC"}
@@ -0,0 +1,160 @@
1
+ /**
2
+ * CLI-2 IPC client: the CLI half of the local control channel that
3
+ * `src/cli/ipc-server.ts` serves inside the DSH plugin process. Discovery
4
+ * walks the same candidate socket paths the server binds (or a single
5
+ * explicit `--socket` path), pings each existing one with a short 200ms
6
+ * budget, and sorts the answers into three buckets the command layer can
7
+ * speak about: LIVE instances whose `cliProtocolVersion` matches, sockets
8
+ * speaking a DIFFERENT protocol version (the upgrade-prompt case), and paths
9
+ * that refused us with EACCES / EPERM (the "DSH runs as another user, try
10
+ * `sudo -E`" case).
11
+ *
12
+ * The request helper is a thin http-over-Unix-socket (Windows: named pipe)
13
+ * round trip. Transport errors REJECT — a dead socket is a real failure the
14
+ * caller must see — while HTTP error statuses resolve normally: the IPC
15
+ * protocol answers every failure as JSON (`{ ok: false, error: … }`), so a
16
+ * 409 wrong-role or 409 env-shadowed is data, not an exception.
17
+ */
18
+ import { request as httpRequest } from 'node:http';
19
+ import { statSync } from 'node:fs';
20
+ import { CLI_CONFIG_ROUTE, CLI_PING_ROUTE, CLI_PROTOCOL_VERSION, candidateSocketPaths } from './ipc-server.js';
21
+ import { CLIENT_DEBUG_REPORT_ROUTE, CLIENT_STATUS_ROUTE } from '../client-routes.js';
22
+ /** Discovery ping budget: finding out whether anything answers must stay
23
+ * fast — up to 8 candidates × 200ms is the worst case, and every absent
24
+ * path skips the probe entirely. */
25
+ const PING_TIMEOUT_MS = 200;
26
+ const DEFAULT_REQUEST_TIMEOUT_MS = 15_000;
27
+ const DEBUG_REPORT_TIMEOUT_MS = 30_000;
28
+ function errnoCode(error) {
29
+ if (!(error instanceof Error))
30
+ return undefined;
31
+ const code = error.code;
32
+ return typeof code === 'string' ? code : undefined;
33
+ }
34
+ function isDenied(error) {
35
+ const code = errnoCode(error);
36
+ return code === 'EACCES' || code === 'EPERM';
37
+ }
38
+ /** One http round trip over the socket. Rejects on transport errors; HTTP
39
+ * error statuses are answers, not failures. */
40
+ function ipcRequest(socketPath, method, route, body, timeoutMs) {
41
+ return new Promise((resolve, reject) => {
42
+ const payload = body === undefined ? undefined : JSON.stringify(body);
43
+ const headers = {};
44
+ if (payload !== undefined) {
45
+ headers['content-type'] = 'application/json';
46
+ headers['content-length'] = String(Buffer.byteLength(payload));
47
+ }
48
+ const req = httpRequest({ socketPath, method, path: route, headers, agent: false, timeout: timeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS }, (res) => {
49
+ const chunks = [];
50
+ res.on('data', (chunk) => chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk)));
51
+ res.on('end', () => resolve({ status: res.statusCode ?? 0, headers: res.headers, text: Buffer.concat(chunks).toString('utf8') }));
52
+ res.on('error', reject);
53
+ });
54
+ req.on('timeout', () => {
55
+ req.destroy();
56
+ reject(new Error(`IPC request timed out after ${timeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS}ms: ${method} ${route}`));
57
+ });
58
+ req.on('error', reject);
59
+ if (payload !== undefined)
60
+ req.write(payload);
61
+ req.end();
62
+ });
63
+ }
64
+ async function probeCandidate(socketPath, probeEvenIfAbsent) {
65
+ let statDenied = false;
66
+ try {
67
+ statSync(socketPath);
68
+ }
69
+ catch (error) {
70
+ if (isDenied(error))
71
+ statDenied = true;
72
+ else if (!probeEvenIfAbsent)
73
+ return { kind: 'absent' };
74
+ // A missing explicit path is still probed below — the connect error tells
75
+ // the same story, and ENOENT is not a permission problem.
76
+ }
77
+ if (statDenied)
78
+ return { kind: 'denied' };
79
+ let answer;
80
+ try {
81
+ answer = await ipcRequest(socketPath, 'GET', CLI_PING_ROUTE, undefined, PING_TIMEOUT_MS);
82
+ }
83
+ catch (error) {
84
+ return isDenied(error) ? { kind: 'denied' } : { kind: 'dead' };
85
+ }
86
+ if (answer.status !== 200)
87
+ return { kind: 'dead' };
88
+ let parsed;
89
+ try {
90
+ parsed = JSON.parse(answer.text);
91
+ }
92
+ catch {
93
+ return { kind: 'dead' };
94
+ }
95
+ if (parsed === null || typeof parsed !== 'object' || Array.isArray(parsed))
96
+ return { kind: 'dead' };
97
+ const body = parsed;
98
+ if (body.ok !== true)
99
+ return { kind: 'dead' };
100
+ const reported = typeof body.cliProtocolVersion === 'number' ? body.cliProtocolVersion : undefined;
101
+ if (reported !== CLI_PROTOCOL_VERSION)
102
+ return { kind: 'mismatch', reportedVersion: reported };
103
+ return { kind: 'live', ping: parsed };
104
+ }
105
+ /**
106
+ * Walk the CLI socket candidates under `dshHome` (or only `explicitSocket`)
107
+ * and classify every answering socket. Absent candidates are skipped without
108
+ * a probe; a dead file that merely squats a candidate name simply answers
109
+ * nothing and lands nowhere.
110
+ */
111
+ export async function discoverCliSockets(options) {
112
+ const paths = options.explicitSocket !== undefined
113
+ ? [options.explicitSocket]
114
+ : candidateSocketPaths(options.dshHome, options.platform ?? process.platform);
115
+ const found = { live: [], versionMismatch: [], permissionDenied: [] };
116
+ for (const socketPath of paths) {
117
+ const verdict = await probeCandidate(socketPath, options.explicitSocket !== undefined);
118
+ if (verdict.kind === 'live')
119
+ found.live.push({ ...verdict.ping, socketPath });
120
+ else if (verdict.kind === 'mismatch')
121
+ found.versionMismatch.push({ socketPath, cliProtocolVersion: verdict.reportedVersion });
122
+ else if (verdict.kind === 'denied')
123
+ found.permissionDenied.push(socketPath);
124
+ }
125
+ return found;
126
+ }
127
+ function parseBody(text) {
128
+ try {
129
+ return JSON.parse(text);
130
+ }
131
+ catch {
132
+ return text;
133
+ }
134
+ }
135
+ /**
136
+ * A client bound to one socket path. `request` is the generic escape hatch
137
+ * for routes added in later CLI phases; the named methods cover the routes
138
+ * this phase already drives.
139
+ */
140
+ export function createCliIpcClient(socketPath) {
141
+ const request = async (method, path, body, timeoutMs) => {
142
+ const answer = await ipcRequest(socketPath, method, path, body, timeoutMs);
143
+ return { status: answer.status, body: parseBody(answer.text), headers: answer.headers };
144
+ };
145
+ return {
146
+ socketPath,
147
+ ping: async () => {
148
+ const result = await request('GET', CLI_PING_ROUTE, undefined, PING_TIMEOUT_MS);
149
+ return result.body;
150
+ },
151
+ getStatus: async () => (await request('GET', CLIENT_STATUS_ROUTE)).body,
152
+ getDebugReport: async () => (await request('GET', CLIENT_DEBUG_REPORT_ROUTE, undefined, DEBUG_REPORT_TIMEOUT_MS)).body,
153
+ writeConfig: async (input) => await request('POST', CLI_CONFIG_ROUTE, {
154
+ ...(input.set === undefined ? {} : { set: input.set }),
155
+ ...(input.unset === undefined ? {} : { unset: input.unset }),
156
+ }),
157
+ request,
158
+ };
159
+ }
160
+ //# sourceMappingURL=ipc-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ipc-client.js","sourceRoot":"","sources":["../../src/cli/ipc-client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,464 @@
1
+ /**
2
+ * The CLI's local IPC control server (CLI-1): a small HTTP server over a
3
+ * 0600 Unix domain socket (`<dshHome>/zen-remote-cli.sock`, Windows: a named
4
+ * pipe), owned by the DSH plugin process. Every DSH `webServer` route sits
5
+ * behind signed-cookie auth, and the pieces the CLI must drive (the relay
6
+ * pool, the managed Caddy / cloudflared children, the wizard state) follow
7
+ * the plugin's single-in-process-owner discipline — so the CLI talks to THIS
8
+ * process over THIS socket instead of a second entry point. Same user, same
9
+ * machine: the 0600 socket IS the authentication.
10
+ *
11
+ * Lifecycle: the server is module-level (one per process, per dshHome). A
12
+ * plugin row reload — including the role flips `restart-watcher` triggers —
13
+ * re-acquires it and swaps the request DELEGATE in place; the underlying
14
+ * socket never unbinds, so a CLI session survives every reload. When the
15
+ * last owning row released it and a short grace period passes without a new
16
+ * acquire, the server closes and the socket file is removed (the grace
17
+ * covers the cordis dispose order, where the OLD row's disposer runs after
18
+ * the NEW row's apply — a plain refcount would tear down between them).
19
+ *
20
+ * The wiring side (src/index.ts) folds the acquire/release into the existing
21
+ * `'dsh-zen-remote: restart watcher'` effect on purpose: test/
22
+ * role-wiring.test.cjs pins the exact number of top-level `ctx.effect`
23
+ * registrations per role, so the IPC lifecycle may not add one.
24
+ */
25
+ import { createServer, get } from 'node:http';
26
+ import { chmodSync, existsSync, unlinkSync } from 'node:fs';
27
+ import { join } from 'node:path';
28
+ import { connectsRole, servesRole } from '../config.js';
29
+ import { responseJson } from '../http.js';
30
+ import { ADMIN_ROUTE_PREFIX } from '../admin-routes.js';
31
+ import { CLIENT_ROUTE_PREFIX } from '../client-routes.js';
32
+ import { WIZARD_ROUTE_PREFIX } from '../wizard/routes.js';
33
+ /** The CLI protocol's major version. A client asking for a different one is
34
+ * talking to a build it cannot drive (SPEC: refuse and tell the user to
35
+ * upgrade the plugin). */
36
+ export const CLI_PROTOCOL_VERSION = 1;
37
+ /** The protocol handshake route. */
38
+ export const CLI_PING_ROUTE = '/_dsh/zen-remote/cli/ping';
39
+ /** The config-write route (POST `{set, unset}` → the anti-shadowing writer). */
40
+ export const CLI_CONFIG_ROUTE = '/_dsh/zen-remote/cli/config';
41
+ /** Socket file / pipe basename: `zen-remote-cli.sock`, `-2.sock`, … */
42
+ export const CLI_SOCKET_BASENAME = 'zen-remote-cli';
43
+ /** How long a fully-released IPC server waits for a re-acquire (the hot
44
+ * reload window: cordis runs the OLD row's disposer AFTER the new apply, so
45
+ * refcount 0 is momentary during every reload). Exported for tests. */
46
+ export const CLI_CLOSE_GRACE_MS = 250;
47
+ /** Inbound config body cap — the CLI writes a few fields at a time. */
48
+ const MAX_BODY_BYTES = 16 * 1024;
49
+ /** Socket paths the process still holds, for the exit-time cleanup. */
50
+ const boundSocketFiles = new Set();
51
+ let exitHookInstalled = false;
52
+ function ensureExitHook() {
53
+ if (exitHookInstalled)
54
+ return;
55
+ exitHookInstalled = true;
56
+ process.on('exit', () => {
57
+ for (const path of boundSocketFiles) {
58
+ try {
59
+ unlinkSync(path);
60
+ }
61
+ catch { /* already gone */ }
62
+ }
63
+ });
64
+ }
65
+ /**
66
+ * The bind candidates, in backoff order: `<dshHome>/zen-remote-cli.sock`,
67
+ * then `-2.sock` … `-8.sock` (two DSH instances on one machine — a web
68
+ * profile and a headless one — each get their own channel). Windows has no
69
+ * filesystem sockets: named pipes under the package's pipe name
70
+ * `dsh-zen-remote-cli` with the same numbering.
71
+ */
72
+ export function candidateSocketPaths(dshHome, platform = process.platform) {
73
+ const out = [];
74
+ for (let n = 1; n <= 8; n += 1) {
75
+ if (platform === 'win32') {
76
+ out.push(n === 1 ? `\\\\.\\pipe\\dsh-${CLI_SOCKET_BASENAME}` : `\\\\.\\pipe\\dsh-${CLI_SOCKET_BASENAME}-${n}`);
77
+ }
78
+ else {
79
+ out.push(join(dshHome, n === 1 ? `${CLI_SOCKET_BASENAME}.sock` : `${CLI_SOCKET_BASENAME}-${n}.sock`));
80
+ }
81
+ }
82
+ return out;
83
+ }
84
+ /** Is something ANSWERING on this socket path? A stale file (a dead
85
+ * instance's leftover, or a plain file that merely squats the name) answers
86
+ * nothing and may be cleaned; a live DSH instance answers its ping and must
87
+ * be left alone. */
88
+ function probeAlive(socketPath) {
89
+ return new Promise((resolve) => {
90
+ let settled = false;
91
+ const done = (value) => {
92
+ if (settled)
93
+ return;
94
+ settled = true;
95
+ resolve(value);
96
+ };
97
+ const req = get({ socketPath, path: CLI_PING_ROUTE, timeout: 150 }, (res) => {
98
+ res.resume();
99
+ done(true);
100
+ });
101
+ req.on('timeout', () => {
102
+ req.destroy();
103
+ done(false);
104
+ });
105
+ req.on('error', () => done(false));
106
+ });
107
+ }
108
+ /** Read the whole body under the cap and demand one JSON object. Same
109
+ * contract as every route module's reader: empty body → `{}`, malformed or
110
+ * oversized → null. */
111
+ async function readJsonObject(req) {
112
+ const declared = req.headers['content-length'];
113
+ const expected = declared === undefined ? undefined : Number(declared);
114
+ if (expected !== undefined && Number.isSafeInteger(expected) && expected > MAX_BODY_BYTES)
115
+ return null;
116
+ const chunks = [];
117
+ let size = 0;
118
+ for await (const chunk of req) {
119
+ const bytes = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
120
+ size += bytes.length;
121
+ if (size > MAX_BODY_BYTES)
122
+ return null;
123
+ chunks.push(bytes);
124
+ }
125
+ const text = Buffer.concat(chunks).toString('utf8');
126
+ if (text.trim() === '')
127
+ return {};
128
+ try {
129
+ const parsed = JSON.parse(text);
130
+ if (parsed === null || typeof parsed !== 'object' || Array.isArray(parsed))
131
+ return null;
132
+ return parsed;
133
+ }
134
+ catch {
135
+ return null;
136
+ }
137
+ }
138
+ function plainObject(value) {
139
+ return value !== null && typeof value === 'object' && !Array.isArray(value)
140
+ ? value
141
+ : undefined;
142
+ }
143
+ function isErrnoCode(error, code) {
144
+ return error instanceof Error && 'code' in error && error.code === code;
145
+ }
146
+ /**
147
+ * Bind one CLI IPC server: walk the candidate paths, probing occupied files
148
+ * for a live owner (skip those), cleaning stale ones, and answering with the
149
+ * bound handle. Throws when every candidate is taken by a live instance.
150
+ */
151
+ export async function createCliIpcServer(options) {
152
+ const platform = options.platform ?? process.platform;
153
+ const isWin = platform === 'win32';
154
+ let delegate = options.delegate;
155
+ let current;
156
+ let socketPath = '';
157
+ const routeListener = (req, res) => {
158
+ void handleCliRequest(req, res, () => delegate);
159
+ };
160
+ for (const candidate of candidateSocketPaths(options.dshHome, platform)) {
161
+ if (!isWin && existsSync(candidate)) {
162
+ if (await probeAlive(candidate))
163
+ continue;
164
+ try {
165
+ unlinkSync(candidate);
166
+ }
167
+ catch {
168
+ continue; // unwritable squatter — try the next name
169
+ }
170
+ }
171
+ const server = createServer(routeListener);
172
+ try {
173
+ await new Promise((resolve, reject) => {
174
+ server.once('error', reject);
175
+ server.listen(candidate, () => resolve());
176
+ });
177
+ current = server;
178
+ socketPath = candidate;
179
+ break;
180
+ }
181
+ catch (error) {
182
+ // EADDRINUSE (another process won the race) or any other bind failure
183
+ // — the remaining candidates are the fallback, never a crash.
184
+ server.close();
185
+ if (!isErrnoCode(error, 'EADDRINUSE'))
186
+ void error;
187
+ continue;
188
+ }
189
+ }
190
+ if (current === undefined) {
191
+ throw new Error(`every ${CLI_SOCKET_BASENAME} candidate is occupied by a live instance (${options.dshHome})`);
192
+ }
193
+ if (!isWin) {
194
+ try {
195
+ chmodSync(socketPath, 0o600);
196
+ }
197
+ catch { /* exotic filesystems — the 0700 home is the outer wall */ }
198
+ }
199
+ else {
200
+ // Named pipes carry no unlinkable file; nothing to register for exit.
201
+ }
202
+ if (!isWin) {
203
+ boundSocketFiles.add(socketPath);
204
+ ensureExitHook();
205
+ }
206
+ // The listen-phase `once('error')` is spent; later server-level errors
207
+ // (accept failures on a dying socket) must not crash the host process.
208
+ current.on('error', () => { });
209
+ // The listening handle must not hold the event loop open (the same
210
+ // discipline as the restart watcher's poll and the fetch-route fallback
211
+ // timer): the DSH host process stays alive on its own services anyway,
212
+ // and a composition whose everything-else has shut down should still be
213
+ // able to exit. The exit hook above still cleans the socket file.
214
+ if (typeof current.unref === 'function')
215
+ current.unref();
216
+ let closed = false;
217
+ return {
218
+ socketPath,
219
+ swapDelegate(next) {
220
+ delegate = next;
221
+ },
222
+ close() {
223
+ if (closed)
224
+ return Promise.resolve();
225
+ closed = true;
226
+ boundSocketFiles.delete(socketPath);
227
+ return new Promise((resolve) => {
228
+ const finish = () => {
229
+ if (!isWin) {
230
+ try {
231
+ unlinkSync(socketPath);
232
+ }
233
+ catch { /* the server's own close unlink usually got here first */ }
234
+ }
235
+ resolve();
236
+ };
237
+ current.close(() => finish());
238
+ if (typeof current.closeAllConnections === 'function')
239
+ current.closeAllConnections();
240
+ });
241
+ },
242
+ };
243
+ }
244
+ /** The per-request dispatch: version headers on EVERY answer first, then the
245
+ * two CLI routes, then the role-gated forwards into the row's handlers. */
246
+ async function handleCliRequest(req, res, getDelegate) {
247
+ try {
248
+ const delegate = getDelegate();
249
+ res.setHeader('x-zr-cli-version', String(CLI_PROTOCOL_VERSION));
250
+ res.setHeader('x-zr-plugin-version', delegate.pluginVersion());
251
+ const url = new URL(req.url ?? '/', 'http://dsh.internal');
252
+ const route = url.pathname;
253
+ const method = req.method ?? 'GET';
254
+ if (route === CLI_PING_ROUTE) {
255
+ if (method !== 'GET') {
256
+ res.setHeader('Allow', 'GET');
257
+ responseJson(res, 405, { ok: false, error: { code: 'method-not-allowed', message: 'Use GET' } });
258
+ return;
259
+ }
260
+ const role = delegate.role();
261
+ const profileName = delegate.profileName();
262
+ responseJson(res, 200, {
263
+ ok: true,
264
+ cliProtocolVersion: CLI_PROTOCOL_VERSION,
265
+ pluginVersion: delegate.pluginVersion(),
266
+ pid: process.pid,
267
+ role,
268
+ serves: servesRole(role),
269
+ connects: connectsRole(role),
270
+ serverName: delegate.serverName(),
271
+ ...(profileName === undefined ? {} : { profileName }),
272
+ });
273
+ return;
274
+ }
275
+ if (route === CLI_CONFIG_ROUTE) {
276
+ if (method !== 'POST') {
277
+ res.setHeader('Allow', 'POST');
278
+ responseJson(res, 405, { ok: false, error: { code: 'method-not-allowed', message: 'Use POST' } });
279
+ return;
280
+ }
281
+ const body = await readJsonObject(req);
282
+ if (body === null) {
283
+ responseJson(res, 400, { ok: false, error: { code: 'bad-request', message: 'The request body must be one JSON object' } });
284
+ return;
285
+ }
286
+ const set = body.set === undefined ? undefined : plainObject(body.set);
287
+ const rawUnset = body.unset === undefined ? undefined : body.unset;
288
+ const unset = Array.isArray(rawUnset) && rawUnset.every((item) => typeof item === 'string')
289
+ ? rawUnset
290
+ : undefined;
291
+ if ((body.set !== undefined && set === undefined) || (body.unset !== undefined && unset === undefined)) {
292
+ responseJson(res, 400, { ok: false, error: { code: 'bad-request', message: '`set` must be an object and `unset` a string array' } });
293
+ return;
294
+ }
295
+ let result;
296
+ try {
297
+ result = delegate.writeConfig({
298
+ ...(set === undefined ? {} : { set }),
299
+ ...(unset === undefined ? {} : { unset }),
300
+ });
301
+ }
302
+ catch (error) {
303
+ responseJson(res, 500, { ok: false, error: { code: 'internal', message: error instanceof Error ? error.message : String(error) } });
304
+ return;
305
+ }
306
+ if (!result.ok) {
307
+ responseJson(res, 409, { ok: false, error: { code: result.code, field: result.field, envVar: result.envVar } });
308
+ return;
309
+ }
310
+ responseJson(res, 200, { ok: true, values: result.values });
311
+ return;
312
+ }
313
+ if (route === WIZARD_ROUTE_PREFIX || route.startsWith(`${WIZARD_ROUTE_PREFIX}/`)) {
314
+ await forwardIfRole(req, res, delegate, delegate.wizardHandler);
315
+ return;
316
+ }
317
+ if (route === ADMIN_ROUTE_PREFIX || route.startsWith(`${ADMIN_ROUTE_PREFIX}/`)) {
318
+ await forwardIfRole(req, res, delegate, delegate.adminHandler);
319
+ return;
320
+ }
321
+ if (route === CLIENT_ROUTE_PREFIX || route.startsWith(`${CLIENT_ROUTE_PREFIX}/`)) {
322
+ // The pairing surfaces belong to a dialing role; remote-status and the
323
+ // debug report are every role's own (the host answers its empty
324
+ // conclusion). SPEC pins exactly this split.
325
+ const sub = route.slice(CLIENT_ROUTE_PREFIX.length) || '/';
326
+ const pairingOnly = new Set(['/status', '/claim', '/unpair', '/reconnect']);
327
+ const required = pairingOnly.has(sub) ? 'client' : undefined;
328
+ if (required !== undefined && !connectsRole(delegate.role())) {
329
+ wrongRole(res, delegate.role(), required);
330
+ return;
331
+ }
332
+ if (delegate.clientHandler === undefined) {
333
+ responseJson(res, 503, { ok: false, error: { code: 'unavailable', message: 'no client handler in this row generation' } });
334
+ return;
335
+ }
336
+ await delegate.clientHandler(req, res);
337
+ return;
338
+ }
339
+ responseJson(res, 404, { ok: false, error: { code: 'not-found', message: 'Unknown CLI route' } });
340
+ }
341
+ catch (error) {
342
+ // A malformed req.url (`new URL` throwing) or a broken delegate must
343
+ // never escape as an unhandled rejection — the handler owns the whole
344
+ // response lifecycle.
345
+ if (!res.headersSent) {
346
+ responseJson(res, 500, { ok: false, error: { code: 'internal', message: error instanceof Error ? error.message : String(error) } });
347
+ }
348
+ else {
349
+ res.destroy();
350
+ }
351
+ }
352
+ }
353
+ /** The host-side role gate: answer 409 wrong-role (or 503 when the row never
354
+ * built the handler) and stop there, or forward into the row's handler. */
355
+ async function forwardIfRole(req, res, delegate, handler) {
356
+ if (!servesRole(delegate.role())) {
357
+ wrongRole(res, delegate.role(), 'host');
358
+ return;
359
+ }
360
+ if (handler === undefined) {
361
+ responseJson(res, 503, { ok: false, error: { code: 'unavailable', message: 'no host handler in this row generation' } });
362
+ return;
363
+ }
364
+ await handler(req, res);
365
+ }
366
+ function wrongRole(res, role, required) {
367
+ responseJson(res, 409, { ok: false, error: { code: 'wrong-role', role, required } });
368
+ }
369
+ const acquisitions = new Map();
370
+ /**
371
+ * A stand-in delegate for the bind window: between `listen` succeeding and
372
+ * the acquiring row's swap landing (one microtask later), a request would
373
+ * otherwise meet no delegate at all. It answers EVERYTHING through the
374
+ * entry's pending delegate — which `acquireCliIpcServer` sets synchronously
375
+ * — so the stub is only visible when literally no row ever acquired, and
376
+ * its write refuses rather than pretending.
377
+ */
378
+ function bootstrapDelegateFor(getEntry) {
379
+ return {
380
+ role: () => getEntry()?.pendingDelegate?.role() ?? 'host',
381
+ serverName: () => getEntry()?.pendingDelegate?.serverName() ?? '',
382
+ profileName: () => getEntry()?.pendingDelegate?.profileName(),
383
+ pluginVersion: () => getEntry()?.pendingDelegate?.pluginVersion() ?? 'unknown',
384
+ writeConfig: (input) => {
385
+ const current = getEntry()?.pendingDelegate;
386
+ if (current === undefined)
387
+ throw new Error('no plugin row has acquired the CLI IPC server yet');
388
+ return current.writeConfig(input);
389
+ },
390
+ wizardHandler: undefined,
391
+ adminHandler: undefined,
392
+ clientHandler: undefined,
393
+ };
394
+ }
395
+ /**
396
+ * Acquire (or hot-swap into) this process's IPC server for `dshHome`.
397
+ * Synchronous on purpose: apply() runs inside cordis and cannot await. The
398
+ * returned handle's `release()` is the row disposer; a release that hits
399
+ * refcount 0 closes the server after {@link CLI_CLOSE_GRACE_MS} unless a new
400
+ * row acquires first.
401
+ */
402
+ export function acquireCliIpcServer(dshHome, delegate) {
403
+ let entry = acquisitions.get(dshHome);
404
+ if (entry === undefined) {
405
+ // The entry the bind closure reads through `getEntry` — assigned right
406
+ // after the (synchronous) object literal completes, long before any
407
+ // request callback can run.
408
+ let creating;
409
+ const created = {
410
+ starting: createCliIpcServer({ dshHome, delegate: bootstrapDelegateFor(() => creating) }),
411
+ server: undefined,
412
+ pendingDelegate: undefined,
413
+ refCount: 0,
414
+ closed: false,
415
+ graceTimer: undefined,
416
+ };
417
+ creating = created;
418
+ entry = created;
419
+ acquisitions.set(dshHome, created);
420
+ void created.starting
421
+ .then((server) => {
422
+ created.server = server;
423
+ if (created.closed) {
424
+ void server.close();
425
+ return;
426
+ }
427
+ if (created.pendingDelegate !== undefined)
428
+ server.swapDelegate(created.pendingDelegate);
429
+ })
430
+ .catch(() => {
431
+ // Every candidate was taken by live instances — drop the slot so a
432
+ // later acquire can retry from scratch.
433
+ if (acquisitions.get(dshHome) === created)
434
+ acquisitions.delete(dshHome);
435
+ });
436
+ }
437
+ if (entry.graceTimer !== undefined) {
438
+ clearTimeout(entry.graceTimer);
439
+ entry.graceTimer = undefined;
440
+ }
441
+ entry.refCount += 1;
442
+ entry.pendingDelegate = delegate;
443
+ if (entry.server !== undefined && !entry.closed)
444
+ entry.server.swapDelegate(delegate);
445
+ return {
446
+ release() {
447
+ if (entry.refCount > 0)
448
+ entry.refCount -= 1;
449
+ if (entry.refCount > 0 || entry.closed || entry.graceTimer !== undefined)
450
+ return;
451
+ entry.graceTimer = setTimeout(() => {
452
+ entry.graceTimer = undefined;
453
+ if (entry.refCount > 0 || entry.closed)
454
+ return;
455
+ acquisitions.delete(dshHome);
456
+ entry.closed = true;
457
+ void entry.starting.then((server) => server.close()).catch(() => { });
458
+ }, CLI_CLOSE_GRACE_MS);
459
+ if (typeof entry.graceTimer.unref === 'function')
460
+ entry.graceTimer.unref();
461
+ },
462
+ };
463
+ }
464
+ //# sourceMappingURL=ipc-server.js.map