parasor 0.1.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 (633) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +208 -0
  3. package/THIRD-PARTY-NOTICES.md +138 -0
  4. package/bin/parasor.mjs +3 -0
  5. package/node_modules/@parasor/shared/dist/client.d.ts +8 -0
  6. package/node_modules/@parasor/shared/dist/client.d.ts.map +1 -0
  7. package/node_modules/@parasor/shared/dist/client.js +2 -0
  8. package/node_modules/@parasor/shared/dist/client.js.map +1 -0
  9. package/node_modules/@parasor/shared/dist/drops.d.ts +24 -0
  10. package/node_modules/@parasor/shared/dist/drops.d.ts.map +1 -0
  11. package/node_modules/@parasor/shared/dist/drops.js +2 -0
  12. package/node_modules/@parasor/shared/dist/drops.js.map +1 -0
  13. package/node_modules/@parasor/shared/dist/file-uploads.d.ts +56 -0
  14. package/node_modules/@parasor/shared/dist/file-uploads.d.ts.map +1 -0
  15. package/node_modules/@parasor/shared/dist/file-uploads.js +13 -0
  16. package/node_modules/@parasor/shared/dist/file-uploads.js.map +1 -0
  17. package/node_modules/@parasor/shared/dist/ide-commands.d.ts +8 -0
  18. package/node_modules/@parasor/shared/dist/ide-commands.d.ts.map +1 -0
  19. package/node_modules/@parasor/shared/dist/ide-commands.js +59 -0
  20. package/node_modules/@parasor/shared/dist/ide-commands.js.map +1 -0
  21. package/node_modules/@parasor/shared/dist/pane-commands.d.ts +7 -0
  22. package/node_modules/@parasor/shared/dist/pane-commands.d.ts.map +1 -0
  23. package/node_modules/@parasor/shared/dist/pane-commands.js +47 -0
  24. package/node_modules/@parasor/shared/dist/pane-commands.js.map +1 -0
  25. package/node_modules/@parasor/shared/dist/pane-model.d.ts +63 -0
  26. package/node_modules/@parasor/shared/dist/pane-model.d.ts.map +1 -0
  27. package/node_modules/@parasor/shared/dist/pane-model.js +89 -0
  28. package/node_modules/@parasor/shared/dist/pane-model.js.map +1 -0
  29. package/node_modules/@parasor/shared/dist/panes.d.ts +33 -0
  30. package/node_modules/@parasor/shared/dist/panes.d.ts.map +1 -0
  31. package/node_modules/@parasor/shared/dist/panes.js +2 -0
  32. package/node_modules/@parasor/shared/dist/panes.js.map +1 -0
  33. package/node_modules/@parasor/shared/dist/runtime.d.ts +180 -0
  34. package/node_modules/@parasor/shared/dist/runtime.d.ts.map +1 -0
  35. package/node_modules/@parasor/shared/dist/runtime.js +2 -0
  36. package/node_modules/@parasor/shared/dist/runtime.js.map +1 -0
  37. package/node_modules/@parasor/shared/dist/state.d.ts +192 -0
  38. package/node_modules/@parasor/shared/dist/state.d.ts.map +1 -0
  39. package/node_modules/@parasor/shared/dist/state.js +10 -0
  40. package/node_modules/@parasor/shared/dist/state.js.map +1 -0
  41. package/node_modules/@parasor/shared/dist/terminal.d.ts +191 -0
  42. package/node_modules/@parasor/shared/dist/terminal.d.ts.map +1 -0
  43. package/node_modules/@parasor/shared/dist/terminal.js +174 -0
  44. package/node_modules/@parasor/shared/dist/terminal.js.map +1 -0
  45. package/node_modules/@parasor/shared/dist/types.d.ts +13 -0
  46. package/node_modules/@parasor/shared/dist/types.d.ts.map +1 -0
  47. package/node_modules/@parasor/shared/dist/types.js +13 -0
  48. package/node_modules/@parasor/shared/dist/types.js.map +1 -0
  49. package/node_modules/@parasor/shared/dist/worktree-local-files.d.ts +14 -0
  50. package/node_modules/@parasor/shared/dist/worktree-local-files.d.ts.map +1 -0
  51. package/node_modules/@parasor/shared/dist/worktree-local-files.js +41 -0
  52. package/node_modules/@parasor/shared/dist/worktree-local-files.js.map +1 -0
  53. package/node_modules/@parasor/shared/dist/ws-events.d.ts +152 -0
  54. package/node_modules/@parasor/shared/dist/ws-events.d.ts.map +1 -0
  55. package/node_modules/@parasor/shared/dist/ws-events.js +2 -0
  56. package/node_modules/@parasor/shared/dist/ws-events.js.map +1 -0
  57. package/node_modules/@parasor/shared/package.json +13 -0
  58. package/package.json +61 -0
  59. package/server/agent-detector/agent-state-store.d.ts +23 -0
  60. package/server/agent-detector/agent-state-store.d.ts.map +1 -0
  61. package/server/agent-detector/agent-state-store.js +110 -0
  62. package/server/agent-detector/agent-state-store.js.map +1 -0
  63. package/server/agent-detector/detector.d.ts +80 -0
  64. package/server/agent-detector/detector.d.ts.map +1 -0
  65. package/server/agent-detector/detector.js +219 -0
  66. package/server/agent-detector/detector.js.map +1 -0
  67. package/server/agent-detector/event-map.d.ts +25 -0
  68. package/server/agent-detector/event-map.d.ts.map +1 -0
  69. package/server/agent-detector/event-map.js +136 -0
  70. package/server/agent-detector/event-map.js.map +1 -0
  71. package/server/agent-detector/manual-agent-tracker.d.ts +19 -0
  72. package/server/agent-detector/manual-agent-tracker.d.ts.map +1 -0
  73. package/server/agent-detector/manual-agent-tracker.js +123 -0
  74. package/server/agent-detector/manual-agent-tracker.js.map +1 -0
  75. package/server/agent-detector/output-eligibility.d.ts +3 -0
  76. package/server/agent-detector/output-eligibility.d.ts.map +1 -0
  77. package/server/agent-detector/output-eligibility.js +39 -0
  78. package/server/agent-detector/output-eligibility.js.map +1 -0
  79. package/server/application/files/errors.d.ts +28 -0
  80. package/server/application/files/errors.d.ts.map +1 -0
  81. package/server/application/files/errors.js +55 -0
  82. package/server/application/files/errors.js.map +1 -0
  83. package/server/application/files/local-filesystem.d.ts +36 -0
  84. package/server/application/files/local-filesystem.d.ts.map +1 -0
  85. package/server/application/files/local-filesystem.js +171 -0
  86. package/server/application/files/local-filesystem.js.map +1 -0
  87. package/server/application/files/project-file-queries.d.ts +16 -0
  88. package/server/application/files/project-file-queries.d.ts.map +1 -0
  89. package/server/application/files/project-file-queries.js +126 -0
  90. package/server/application/files/project-file-queries.js.map +1 -0
  91. package/server/application/integrations/errors.d.ts +16 -0
  92. package/server/application/integrations/errors.d.ts.map +1 -0
  93. package/server/application/integrations/errors.js +31 -0
  94. package/server/application/integrations/errors.js.map +1 -0
  95. package/server/application/integrations/hook-notify.d.ts +32 -0
  96. package/server/application/integrations/hook-notify.d.ts.map +1 -0
  97. package/server/application/integrations/hook-notify.js +118 -0
  98. package/server/application/integrations/hook-notify.js.map +1 -0
  99. package/server/application/integrations/open-url.d.ts +11 -0
  100. package/server/application/integrations/open-url.d.ts.map +1 -0
  101. package/server/application/integrations/open-url.js +23 -0
  102. package/server/application/integrations/open-url.js.map +1 -0
  103. package/server/application/ports.d.ts +11 -0
  104. package/server/application/ports.d.ts.map +1 -0
  105. package/server/application/ports.js +2 -0
  106. package/server/application/ports.js.map +1 -0
  107. package/server/application/workspace/errors.d.ts +21 -0
  108. package/server/application/workspace/errors.d.ts.map +1 -0
  109. package/server/application/workspace/errors.js +21 -0
  110. package/server/application/workspace/errors.js.map +1 -0
  111. package/server/application/workspace/pane-commands.d.ts +47 -0
  112. package/server/application/workspace/pane-commands.d.ts.map +1 -0
  113. package/server/application/workspace/pane-commands.js +193 -0
  114. package/server/application/workspace/pane-commands.js.map +1 -0
  115. package/server/application/workspace/project-commands.d.ts +34 -0
  116. package/server/application/workspace/project-commands.d.ts.map +1 -0
  117. package/server/application/workspace/project-commands.js +81 -0
  118. package/server/application/workspace/project-commands.js.map +1 -0
  119. package/server/application/workspace/project-queries.d.ts +21 -0
  120. package/server/application/workspace/project-queries.d.ts.map +1 -0
  121. package/server/application/workspace/project-queries.js +216 -0
  122. package/server/application/workspace/project-queries.js.map +1 -0
  123. package/server/application/workspace/session-commands.d.ts +24 -0
  124. package/server/application/workspace/session-commands.d.ts.map +1 -0
  125. package/server/application/workspace/session-commands.js +123 -0
  126. package/server/application/workspace/session-commands.js.map +1 -0
  127. package/server/application/workspace/session-queries.d.ts +14 -0
  128. package/server/application/workspace/session-queries.d.ts.map +1 -0
  129. package/server/application/workspace/session-queries.js +47 -0
  130. package/server/application/workspace/session-queries.js.map +1 -0
  131. package/server/application/workspace/worktree-commands.d.ts +98 -0
  132. package/server/application/workspace/worktree-commands.d.ts.map +1 -0
  133. package/server/application/workspace/worktree-commands.js +323 -0
  134. package/server/application/workspace/worktree-commands.js.map +1 -0
  135. package/server/application/workspace/worktree-local-files.d.ts +11 -0
  136. package/server/application/workspace/worktree-local-files.d.ts.map +1 -0
  137. package/server/application/workspace/worktree-local-files.js +223 -0
  138. package/server/application/workspace/worktree-local-files.js.map +1 -0
  139. package/server/application/workspace/worktree-reconcile.d.ts +21 -0
  140. package/server/application/workspace/worktree-reconcile.d.ts.map +1 -0
  141. package/server/application/workspace/worktree-reconcile.js +49 -0
  142. package/server/application/workspace/worktree-reconcile.js.map +1 -0
  143. package/server/auth/origin.d.ts +17 -0
  144. package/server/auth/origin.d.ts.map +1 -0
  145. package/server/auth/origin.js +93 -0
  146. package/server/auth/origin.js.map +1 -0
  147. package/server/auth/pairing-token.d.ts +28 -0
  148. package/server/auth/pairing-token.d.ts.map +1 -0
  149. package/server/auth/pairing-token.js +46 -0
  150. package/server/auth/pairing-token.js.map +1 -0
  151. package/server/auth/token-exchange.d.ts +11 -0
  152. package/server/auth/token-exchange.d.ts.map +1 -0
  153. package/server/auth/token-exchange.js +27 -0
  154. package/server/auth/token-exchange.js.map +1 -0
  155. package/server/auth/token.d.ts +18 -0
  156. package/server/auth/token.d.ts.map +1 -0
  157. package/server/auth/token.js +115 -0
  158. package/server/auth/token.js.map +1 -0
  159. package/server/bootstrap/create-app-server.d.ts +49 -0
  160. package/server/bootstrap/create-app-server.d.ts.map +1 -0
  161. package/server/bootstrap/create-app-server.js +154 -0
  162. package/server/bootstrap/create-app-server.js.map +1 -0
  163. package/server/bootstrap/project-runtime.d.ts +29 -0
  164. package/server/bootstrap/project-runtime.d.ts.map +1 -0
  165. package/server/bootstrap/project-runtime.js +253 -0
  166. package/server/bootstrap/project-runtime.js.map +1 -0
  167. package/server/bootstrap/pty-env.d.ts +3 -0
  168. package/server/bootstrap/pty-env.d.ts.map +1 -0
  169. package/server/bootstrap/pty-env.js +15 -0
  170. package/server/bootstrap/pty-env.js.map +1 -0
  171. package/server/bootstrap/reconcile-state.d.ts +16 -0
  172. package/server/bootstrap/reconcile-state.d.ts.map +1 -0
  173. package/server/bootstrap/reconcile-state.js +73 -0
  174. package/server/bootstrap/reconcile-state.js.map +1 -0
  175. package/server/bootstrap/runtime-loops.d.ts +51 -0
  176. package/server/bootstrap/runtime-loops.d.ts.map +1 -0
  177. package/server/bootstrap/runtime-loops.js +189 -0
  178. package/server/bootstrap/runtime-loops.js.map +1 -0
  179. package/server/bootstrap/runtime-port.d.ts +4 -0
  180. package/server/bootstrap/runtime-port.d.ts.map +1 -0
  181. package/server/bootstrap/runtime-port.js +52 -0
  182. package/server/bootstrap/runtime-port.js.map +1 -0
  183. package/server/bootstrap/safety-gate.d.ts +22 -0
  184. package/server/bootstrap/safety-gate.d.ts.map +1 -0
  185. package/server/bootstrap/safety-gate.js +43 -0
  186. package/server/bootstrap/safety-gate.js.map +1 -0
  187. package/server/bootstrap/shutdown-marker.d.ts +35 -0
  188. package/server/bootstrap/shutdown-marker.d.ts.map +1 -0
  189. package/server/bootstrap/shutdown-marker.js +100 -0
  190. package/server/bootstrap/shutdown-marker.js.map +1 -0
  191. package/server/bootstrap/shutdown-runtime.d.ts +62 -0
  192. package/server/bootstrap/shutdown-runtime.d.ts.map +1 -0
  193. package/server/bootstrap/shutdown-runtime.js +66 -0
  194. package/server/bootstrap/shutdown-runtime.js.map +1 -0
  195. package/server/bootstrap/startup-banner.d.ts +34 -0
  196. package/server/bootstrap/startup-banner.d.ts.map +1 -0
  197. package/server/bootstrap/startup-banner.js +114 -0
  198. package/server/bootstrap/startup-banner.js.map +1 -0
  199. package/server/bootstrap/wire-runtime.d.ts +42 -0
  200. package/server/bootstrap/wire-runtime.d.ts.map +1 -0
  201. package/server/bootstrap/wire-runtime.js +205 -0
  202. package/server/bootstrap/wire-runtime.js.map +1 -0
  203. package/server/cli/help.d.ts +3 -0
  204. package/server/cli/help.d.ts.map +1 -0
  205. package/server/cli/help.js +39 -0
  206. package/server/cli/help.js.map +1 -0
  207. package/server/cli/hook-client.d.ts +12 -0
  208. package/server/cli/hook-client.d.ts.map +1 -0
  209. package/server/cli/hook-client.js +81 -0
  210. package/server/cli/hook-client.js.map +1 -0
  211. package/server/cli/hook.d.ts +3 -0
  212. package/server/cli/hook.d.ts.map +1 -0
  213. package/server/cli/hook.js +152 -0
  214. package/server/cli/hook.js.map +1 -0
  215. package/server/cli/main.d.ts +2 -0
  216. package/server/cli/main.d.ts.map +1 -0
  217. package/server/cli/main.js +133 -0
  218. package/server/cli/main.js.map +1 -0
  219. package/server/cli/notify.d.ts +19 -0
  220. package/server/cli/notify.d.ts.map +1 -0
  221. package/server/cli/notify.js +77 -0
  222. package/server/cli/notify.js.map +1 -0
  223. package/server/cli/open.d.ts +2 -0
  224. package/server/cli/open.d.ts.map +1 -0
  225. package/server/cli/open.js +47 -0
  226. package/server/cli/open.js.map +1 -0
  227. package/server/cli/probe-daemon-version.d.ts +46 -0
  228. package/server/cli/probe-daemon-version.d.ts.map +1 -0
  229. package/server/cli/probe-daemon-version.js +167 -0
  230. package/server/cli/probe-daemon-version.js.map +1 -0
  231. package/server/cli/pty-host.d.ts +36 -0
  232. package/server/cli/pty-host.d.ts.map +1 -0
  233. package/server/cli/pty-host.js +390 -0
  234. package/server/cli/pty-host.js.map +1 -0
  235. package/server/cli/qr.d.ts +2 -0
  236. package/server/cli/qr.d.ts.map +1 -0
  237. package/server/cli/qr.js +70 -0
  238. package/server/cli/qr.js.map +1 -0
  239. package/server/cli/restart-confirm.d.ts +33 -0
  240. package/server/cli/restart-confirm.d.ts.map +1 -0
  241. package/server/cli/restart-confirm.js +107 -0
  242. package/server/cli/restart-confirm.js.map +1 -0
  243. package/server/cli/restart.d.ts +17 -0
  244. package/server/cli/restart.d.ts.map +1 -0
  245. package/server/cli/restart.js +145 -0
  246. package/server/cli/restart.js.map +1 -0
  247. package/server/cli/service-darwin.d.ts +70 -0
  248. package/server/cli/service-darwin.d.ts.map +1 -0
  249. package/server/cli/service-darwin.js +562 -0
  250. package/server/cli/service-darwin.js.map +1 -0
  251. package/server/cli/service-linux.d.ts +81 -0
  252. package/server/cli/service-linux.d.ts.map +1 -0
  253. package/server/cli/service-linux.js +412 -0
  254. package/server/cli/service-linux.js.map +1 -0
  255. package/server/cli/service.d.ts +33 -0
  256. package/server/cli/service.d.ts.map +1 -0
  257. package/server/cli/service.js +133 -0
  258. package/server/cli/service.js.map +1 -0
  259. package/server/cli/shim-installer.d.ts +35 -0
  260. package/server/cli/shim-installer.d.ts.map +1 -0
  261. package/server/cli/shim-installer.js +662 -0
  262. package/server/cli/shim-installer.js.map +1 -0
  263. package/server/cli/shim-open.d.ts +2 -0
  264. package/server/cli/shim-open.d.ts.map +1 -0
  265. package/server/cli/shim-open.js +128 -0
  266. package/server/cli/shim-open.js.map +1 -0
  267. package/server/cli/shutdown-deps.d.ts +41 -0
  268. package/server/cli/shutdown-deps.d.ts.map +1 -0
  269. package/server/cli/shutdown-deps.js +158 -0
  270. package/server/cli/shutdown-deps.js.map +1 -0
  271. package/server/cli/stop.d.ts +11 -0
  272. package/server/cli/stop.d.ts.map +1 -0
  273. package/server/cli/stop.js +123 -0
  274. package/server/cli/stop.js.map +1 -0
  275. package/server/cli/unknown-command.d.ts +8 -0
  276. package/server/cli/unknown-command.d.ts.map +1 -0
  277. package/server/cli/unknown-command.js +14 -0
  278. package/server/cli/unknown-command.js.map +1 -0
  279. package/server/debug/agent-status-recorder.d.ts +57 -0
  280. package/server/debug/agent-status-recorder.d.ts.map +1 -0
  281. package/server/debug/agent-status-recorder.js +209 -0
  282. package/server/debug/agent-status-recorder.js.map +1 -0
  283. package/server/debug/terminal-trace-recorder.d.ts +41 -0
  284. package/server/debug/terminal-trace-recorder.d.ts.map +1 -0
  285. package/server/debug/terminal-trace-recorder.js +112 -0
  286. package/server/debug/terminal-trace-recorder.js.map +1 -0
  287. package/server/fonts/catalog.d.ts +35 -0
  288. package/server/fonts/catalog.d.ts.map +1 -0
  289. package/server/fonts/catalog.js +76 -0
  290. package/server/fonts/catalog.js.map +1 -0
  291. package/server/fonts/installer.d.ts +45 -0
  292. package/server/fonts/installer.d.ts.map +1 -0
  293. package/server/fonts/installer.js +201 -0
  294. package/server/fonts/installer.js.map +1 -0
  295. package/server/fonts/routes.d.ts +4 -0
  296. package/server/fonts/routes.d.ts.map +1 -0
  297. package/server/fonts/routes.js +91 -0
  298. package/server/fonts/routes.js.map +1 -0
  299. package/server/fs/drops.d.ts +50 -0
  300. package/server/fs/drops.d.ts.map +1 -0
  301. package/server/fs/drops.js +137 -0
  302. package/server/fs/drops.js.map +1 -0
  303. package/server/fs/file-uploads.d.ts +57 -0
  304. package/server/fs/file-uploads.d.ts.map +1 -0
  305. package/server/fs/file-uploads.js +214 -0
  306. package/server/fs/file-uploads.js.map +1 -0
  307. package/server/fs/file-watcher.d.ts +22 -0
  308. package/server/fs/file-watcher.d.ts.map +1 -0
  309. package/server/fs/file-watcher.js +105 -0
  310. package/server/fs/file-watcher.js.map +1 -0
  311. package/server/fs/git-watcher.d.ts +76 -0
  312. package/server/fs/git-watcher.d.ts.map +1 -0
  313. package/server/fs/git-watcher.js +356 -0
  314. package/server/fs/git-watcher.js.map +1 -0
  315. package/server/fs/media.d.ts +35 -0
  316. package/server/fs/media.d.ts.map +1 -0
  317. package/server/fs/media.js +271 -0
  318. package/server/fs/media.js.map +1 -0
  319. package/server/fs/service.d.ts +97 -0
  320. package/server/fs/service.d.ts.map +1 -0
  321. package/server/fs/service.js +306 -0
  322. package/server/fs/service.js.map +1 -0
  323. package/server/fs/upload-staging.d.ts +76 -0
  324. package/server/fs/upload-staging.d.ts.map +1 -0
  325. package/server/fs/upload-staging.js +283 -0
  326. package/server/fs/upload-staging.js.map +1 -0
  327. package/server/fs/watcher-lifecycle.d.ts +24 -0
  328. package/server/fs/watcher-lifecycle.d.ts.map +1 -0
  329. package/server/fs/watcher-lifecycle.js +105 -0
  330. package/server/fs/watcher-lifecycle.js.map +1 -0
  331. package/server/index.d.ts +17 -0
  332. package/server/index.d.ts.map +1 -0
  333. package/server/index.js +510 -0
  334. package/server/index.js.map +1 -0
  335. package/server/ipc/socket-server.d.ts +28 -0
  336. package/server/ipc/socket-server.d.ts.map +1 -0
  337. package/server/ipc/socket-server.js +206 -0
  338. package/server/ipc/socket-server.js.map +1 -0
  339. package/server/lib/git-exec.d.ts +38 -0
  340. package/server/lib/git-exec.d.ts.map +1 -0
  341. package/server/lib/git-exec.js +96 -0
  342. package/server/lib/git-exec.js.map +1 -0
  343. package/server/lib/open-in-ide.d.ts +22 -0
  344. package/server/lib/open-in-ide.d.ts.map +1 -0
  345. package/server/lib/open-in-ide.js +90 -0
  346. package/server/lib/open-in-ide.js.map +1 -0
  347. package/server/lib/open-in-os.d.ts +20 -0
  348. package/server/lib/open-in-os.d.ts.map +1 -0
  349. package/server/lib/open-in-os.js +51 -0
  350. package/server/lib/open-in-os.js.map +1 -0
  351. package/server/lib/path.d.ts +2 -0
  352. package/server/lib/path.d.ts.map +1 -0
  353. package/server/lib/path.js +10 -0
  354. package/server/lib/path.js.map +1 -0
  355. package/server/lib/promise-mutex.d.ts +7 -0
  356. package/server/lib/promise-mutex.d.ts.map +1 -0
  357. package/server/lib/promise-mutex.js +26 -0
  358. package/server/lib/promise-mutex.js.map +1 -0
  359. package/server/lib/sd-notify.d.ts +8 -0
  360. package/server/lib/sd-notify.d.ts.map +1 -0
  361. package/server/lib/sd-notify.js +27 -0
  362. package/server/lib/sd-notify.js.map +1 -0
  363. package/server/net/local-machine.d.ts +7 -0
  364. package/server/net/local-machine.d.ts.map +1 -0
  365. package/server/net/local-machine.js +79 -0
  366. package/server/net/local-machine.js.map +1 -0
  367. package/server/net/reachable-host.d.ts +12 -0
  368. package/server/net/reachable-host.d.ts.map +1 -0
  369. package/server/net/reachable-host.js +25 -0
  370. package/server/net/reachable-host.js.map +1 -0
  371. package/server/network/endpoints.d.ts +14 -0
  372. package/server/network/endpoints.d.ts.map +1 -0
  373. package/server/network/endpoints.js +104 -0
  374. package/server/network/endpoints.js.map +1 -0
  375. package/server/network/qr.d.ts +16 -0
  376. package/server/network/qr.d.ts.map +1 -0
  377. package/server/network/qr.js +89 -0
  378. package/server/network/qr.js.map +1 -0
  379. package/server/port-forwarder/forwarder.d.ts +47 -0
  380. package/server/port-forwarder/forwarder.d.ts.map +1 -0
  381. package/server/port-forwarder/forwarder.js +159 -0
  382. package/server/port-forwarder/forwarder.js.map +1 -0
  383. package/server/port-scanner/scanner.d.ts +24 -0
  384. package/server/port-scanner/scanner.d.ts.map +1 -0
  385. package/server/port-scanner/scanner.js +193 -0
  386. package/server/port-scanner/scanner.js.map +1 -0
  387. package/server/pty/connection-lifecycle.d.ts +50 -0
  388. package/server/pty/connection-lifecycle.d.ts.map +1 -0
  389. package/server/pty/connection-lifecycle.js +113 -0
  390. package/server/pty/connection-lifecycle.js.map +1 -0
  391. package/server/pty/daemon-connect.d.ts +52 -0
  392. package/server/pty/daemon-connect.d.ts.map +1 -0
  393. package/server/pty/daemon-connect.js +62 -0
  394. package/server/pty/daemon-connect.js.map +1 -0
  395. package/server/pty/handshake-timeout-race.d.ts +22 -0
  396. package/server/pty/handshake-timeout-race.d.ts.map +1 -0
  397. package/server/pty/handshake-timeout-race.js +23 -0
  398. package/server/pty/handshake-timeout-race.js.map +1 -0
  399. package/server/pty/headless-replay-snapshot.d.ts +28 -0
  400. package/server/pty/headless-replay-snapshot.d.ts.map +1 -0
  401. package/server/pty/headless-replay-snapshot.js +285 -0
  402. package/server/pty/headless-replay-snapshot.js.map +1 -0
  403. package/server/pty/headless-terminal-state-cache.d.ts +31 -0
  404. package/server/pty/headless-terminal-state-cache.d.ts.map +1 -0
  405. package/server/pty/headless-terminal-state-cache.js +119 -0
  406. package/server/pty/headless-terminal-state-cache.js.map +1 -0
  407. package/server/pty/hello-ack-validator.d.ts +15 -0
  408. package/server/pty/hello-ack-validator.d.ts.map +1 -0
  409. package/server/pty/hello-ack-validator.js +30 -0
  410. package/server/pty/hello-ack-validator.js.map +1 -0
  411. package/server/pty/host-daemon/bootstrap.d.ts +100 -0
  412. package/server/pty/host-daemon/bootstrap.d.ts.map +1 -0
  413. package/server/pty/host-daemon/bootstrap.js +611 -0
  414. package/server/pty/host-daemon/bootstrap.js.map +1 -0
  415. package/server/pty/host-daemon/daemon.d.ts +111 -0
  416. package/server/pty/host-daemon/daemon.d.ts.map +1 -0
  417. package/server/pty/host-daemon/daemon.js +648 -0
  418. package/server/pty/host-daemon/daemon.js.map +1 -0
  419. package/server/pty/host-daemon/entry.d.ts +3 -0
  420. package/server/pty/host-daemon/entry.d.ts.map +1 -0
  421. package/server/pty/host-daemon/entry.js +72 -0
  422. package/server/pty/host-daemon/entry.js.map +1 -0
  423. package/server/pty/host-daemon/lockfile.d.ts +12 -0
  424. package/server/pty/host-daemon/lockfile.d.ts.map +1 -0
  425. package/server/pty/host-daemon/lockfile.js +120 -0
  426. package/server/pty/host-daemon/lockfile.js.map +1 -0
  427. package/server/pty/host-daemon/mode-marker.d.ts +77 -0
  428. package/server/pty/host-daemon/mode-marker.d.ts.map +1 -0
  429. package/server/pty/host-daemon/mode-marker.js +228 -0
  430. package/server/pty/host-daemon/mode-marker.js.map +1 -0
  431. package/server/pty/host-daemon/orphan-cleanup.d.ts +42 -0
  432. package/server/pty/host-daemon/orphan-cleanup.d.ts.map +1 -0
  433. package/server/pty/host-daemon/orphan-cleanup.js +84 -0
  434. package/server/pty/host-daemon/orphan-cleanup.js.map +1 -0
  435. package/server/pty/host-daemon/paths.d.ts +10 -0
  436. package/server/pty/host-daemon/paths.d.ts.map +1 -0
  437. package/server/pty/host-daemon/paths.js +56 -0
  438. package/server/pty/host-daemon/paths.js.map +1 -0
  439. package/server/pty/host-daemon/server-connection.d.ts +44 -0
  440. package/server/pty/host-daemon/server-connection.d.ts.map +1 -0
  441. package/server/pty/host-daemon/server-connection.js +100 -0
  442. package/server/pty/host-daemon/server-connection.js.map +1 -0
  443. package/server/pty/host-daemon/service-detection.d.ts +24 -0
  444. package/server/pty/host-daemon/service-detection.d.ts.map +1 -0
  445. package/server/pty/host-daemon/service-detection.js +16 -0
  446. package/server/pty/host-daemon/service-detection.js.map +1 -0
  447. package/server/pty/host-daemon/socket-ready.d.ts +22 -0
  448. package/server/pty/host-daemon/socket-ready.d.ts.map +1 -0
  449. package/server/pty/host-daemon/socket-ready.js +33 -0
  450. package/server/pty/host-daemon/socket-ready.js.map +1 -0
  451. package/server/pty/host-daemon/spawn-daemon.d.ts +45 -0
  452. package/server/pty/host-daemon/spawn-daemon.d.ts.map +1 -0
  453. package/server/pty/host-daemon/spawn-daemon.js +155 -0
  454. package/server/pty/host-daemon/spawn-daemon.js.map +1 -0
  455. package/server/pty/host-daemon/terminate-daemon.d.ts +16 -0
  456. package/server/pty/host-daemon/terminate-daemon.d.ts.map +1 -0
  457. package/server/pty/host-daemon/terminate-daemon.js +128 -0
  458. package/server/pty/host-daemon/terminate-daemon.js.map +1 -0
  459. package/server/pty/host-protocol/frames.d.ts +110 -0
  460. package/server/pty/host-protocol/frames.d.ts.map +1 -0
  461. package/server/pty/host-protocol/frames.js +255 -0
  462. package/server/pty/host-protocol/frames.js.map +1 -0
  463. package/server/pty/host-protocol/messages.d.ts +140 -0
  464. package/server/pty/host-protocol/messages.d.ts.map +1 -0
  465. package/server/pty/host-protocol/messages.js +117 -0
  466. package/server/pty/host-protocol/messages.js.map +1 -0
  467. package/server/pty/host.d.ts +273 -0
  468. package/server/pty/host.d.ts.map +1 -0
  469. package/server/pty/host.js +184 -0
  470. package/server/pty/host.js.map +1 -0
  471. package/server/pty/in-process-host.d.ts +224 -0
  472. package/server/pty/in-process-host.d.ts.map +1 -0
  473. package/server/pty/in-process-host.js +1183 -0
  474. package/server/pty/in-process-host.js.map +1 -0
  475. package/server/pty/osc7-lifecycle.d.ts +8 -0
  476. package/server/pty/osc7-lifecycle.d.ts.map +1 -0
  477. package/server/pty/osc7-lifecycle.js +22 -0
  478. package/server/pty/osc7-lifecycle.js.map +1 -0
  479. package/server/pty/osc7-parser.d.ts +23 -0
  480. package/server/pty/osc7-parser.d.ts.map +1 -0
  481. package/server/pty/osc7-parser.js +91 -0
  482. package/server/pty/osc7-parser.js.map +1 -0
  483. package/server/pty/remote-host.d.ts +188 -0
  484. package/server/pty/remote-host.d.ts.map +1 -0
  485. package/server/pty/remote-host.js +810 -0
  486. package/server/pty/remote-host.js.map +1 -0
  487. package/server/pty/request-correlator.d.ts +59 -0
  488. package/server/pty/request-correlator.d.ts.map +1 -0
  489. package/server/pty/request-correlator.js +75 -0
  490. package/server/pty/request-correlator.js.map +1 -0
  491. package/server/pty/scrollback-log.d.ts +130 -0
  492. package/server/pty/scrollback-log.d.ts.map +1 -0
  493. package/server/pty/scrollback-log.js +344 -0
  494. package/server/pty/scrollback-log.js.map +1 -0
  495. package/server/pty/scrollback-sanitize.d.ts +2 -0
  496. package/server/pty/scrollback-sanitize.d.ts.map +1 -0
  497. package/server/pty/scrollback-sanitize.js +54 -0
  498. package/server/pty/scrollback-sanitize.js.map +1 -0
  499. package/server/pty/session-mirror.d.ts +67 -0
  500. package/server/pty/session-mirror.d.ts.map +1 -0
  501. package/server/pty/session-mirror.js +112 -0
  502. package/server/pty/session-mirror.js.map +1 -0
  503. package/server/pty/session-policy.d.ts +85 -0
  504. package/server/pty/session-policy.d.ts.map +1 -0
  505. package/server/pty/session-policy.js +186 -0
  506. package/server/pty/session-policy.js.map +1 -0
  507. package/server/pty/version-mismatch-recovery.d.ts +71 -0
  508. package/server/pty/version-mismatch-recovery.d.ts.map +1 -0
  509. package/server/pty/version-mismatch-recovery.js +63 -0
  510. package/server/pty/version-mismatch-recovery.js.map +1 -0
  511. package/server/routes/debug-agent-status.d.ts +5 -0
  512. package/server/routes/debug-agent-status.d.ts.map +1 -0
  513. package/server/routes/debug-agent-status.js +22 -0
  514. package/server/routes/debug-agent-status.js.map +1 -0
  515. package/server/routes/debug-diagnostics.d.ts +8 -0
  516. package/server/routes/debug-diagnostics.d.ts.map +1 -0
  517. package/server/routes/debug-diagnostics.js +34 -0
  518. package/server/routes/debug-diagnostics.js.map +1 -0
  519. package/server/routes/debug-terminal-trace.d.ts +16 -0
  520. package/server/routes/debug-terminal-trace.d.ts.map +1 -0
  521. package/server/routes/debug-terminal-trace.js +545 -0
  522. package/server/routes/debug-terminal-trace.js.map +1 -0
  523. package/server/routes/drops.d.ts +13 -0
  524. package/server/routes/drops.d.ts.map +1 -0
  525. package/server/routes/drops.js +126 -0
  526. package/server/routes/drops.js.map +1 -0
  527. package/server/routes/file-uploads.d.ts +9 -0
  528. package/server/routes/file-uploads.d.ts.map +1 -0
  529. package/server/routes/file-uploads.js +119 -0
  530. package/server/routes/file-uploads.js.map +1 -0
  531. package/server/routes/files.d.ts +9 -0
  532. package/server/routes/files.d.ts.map +1 -0
  533. package/server/routes/files.js +441 -0
  534. package/server/routes/files.js.map +1 -0
  535. package/server/routes/filesystem.d.ts +6 -0
  536. package/server/routes/filesystem.d.ts.map +1 -0
  537. package/server/routes/filesystem.js +76 -0
  538. package/server/routes/filesystem.js.map +1 -0
  539. package/server/routes/git.d.ts +38 -0
  540. package/server/routes/git.d.ts.map +1 -0
  541. package/server/routes/git.js +585 -0
  542. package/server/routes/git.js.map +1 -0
  543. package/server/routes/healthz.d.ts +8 -0
  544. package/server/routes/healthz.d.ts.map +1 -0
  545. package/server/routes/healthz.js +24 -0
  546. package/server/routes/healthz.js.map +1 -0
  547. package/server/routes/hook.d.ts +14 -0
  548. package/server/routes/hook.d.ts.map +1 -0
  549. package/server/routes/hook.js +86 -0
  550. package/server/routes/hook.js.map +1 -0
  551. package/server/routes/ide-commands.d.ts +9 -0
  552. package/server/routes/ide-commands.d.ts.map +1 -0
  553. package/server/routes/ide-commands.js +23 -0
  554. package/server/routes/ide-commands.js.map +1 -0
  555. package/server/routes/lib/resolve-worktree.d.ts +30 -0
  556. package/server/routes/lib/resolve-worktree.d.ts.map +1 -0
  557. package/server/routes/lib/resolve-worktree.js +35 -0
  558. package/server/routes/lib/resolve-worktree.js.map +1 -0
  559. package/server/routes/open.d.ts +4 -0
  560. package/server/routes/open.d.ts.map +1 -0
  561. package/server/routes/open.js +21 -0
  562. package/server/routes/open.js.map +1 -0
  563. package/server/routes/pane-commands.d.ts +9 -0
  564. package/server/routes/pane-commands.d.ts.map +1 -0
  565. package/server/routes/pane-commands.js +23 -0
  566. package/server/routes/pane-commands.js.map +1 -0
  567. package/server/routes/projects.d.ts +15 -0
  568. package/server/routes/projects.d.ts.map +1 -0
  569. package/server/routes/projects.js +363 -0
  570. package/server/routes/projects.js.map +1 -0
  571. package/server/routes/server-notices.d.ts +4 -0
  572. package/server/routes/server-notices.d.ts.map +1 -0
  573. package/server/routes/server-notices.js +29 -0
  574. package/server/routes/server-notices.js.map +1 -0
  575. package/server/routes/service-config.d.ts +11 -0
  576. package/server/routes/service-config.d.ts.map +1 -0
  577. package/server/routes/service-config.js +64 -0
  578. package/server/routes/service-config.js.map +1 -0
  579. package/server/routes/sessions.d.ts +7 -0
  580. package/server/routes/sessions.d.ts.map +1 -0
  581. package/server/routes/sessions.js +218 -0
  582. package/server/routes/sessions.js.map +1 -0
  583. package/server/service/caffeinate.d.ts +33 -0
  584. package/server/service/caffeinate.d.ts.map +1 -0
  585. package/server/service/caffeinate.js +72 -0
  586. package/server/service/caffeinate.js.map +1 -0
  587. package/server/state/app-state.d.ts +167 -0
  588. package/server/state/app-state.d.ts.map +1 -0
  589. package/server/state/app-state.js +335 -0
  590. package/server/state/app-state.js.map +1 -0
  591. package/server/state/project-manager.d.ts +30 -0
  592. package/server/state/project-manager.d.ts.map +1 -0
  593. package/server/state/project-manager.js +128 -0
  594. package/server/state/project-manager.js.map +1 -0
  595. package/server/state/server-notices.d.ts +12 -0
  596. package/server/state/server-notices.d.ts.map +1 -0
  597. package/server/state/server-notices.js +32 -0
  598. package/server/state/server-notices.js.map +1 -0
  599. package/server/state/worktree-cache.d.ts +25 -0
  600. package/server/state/worktree-cache.d.ts.map +1 -0
  601. package/server/state/worktree-cache.js +53 -0
  602. package/server/state/worktree-cache.js.map +1 -0
  603. package/server/ws/events.d.ts +45 -0
  604. package/server/ws/events.d.ts.map +1 -0
  605. package/server/ws/events.js +134 -0
  606. package/server/ws/events.js.map +1 -0
  607. package/server/ws/keepalive.d.ts +27 -0
  608. package/server/ws/keepalive.d.ts.map +1 -0
  609. package/server/ws/keepalive.js +63 -0
  610. package/server/ws/keepalive.js.map +1 -0
  611. package/server/ws/terminal-attach.d.ts +13 -0
  612. package/server/ws/terminal-attach.d.ts.map +1 -0
  613. package/server/ws/terminal-attach.js +233 -0
  614. package/server/ws/terminal-attach.js.map +1 -0
  615. package/server/ws/terminal-flow.d.ts +17 -0
  616. package/server/ws/terminal-flow.d.ts.map +1 -0
  617. package/server/ws/terminal-flow.js +64 -0
  618. package/server/ws/terminal-flow.js.map +1 -0
  619. package/server/ws/terminal.d.ts +69 -0
  620. package/server/ws/terminal.d.ts.map +1 -0
  621. package/server/ws/terminal.js +311 -0
  622. package/server/ws/terminal.js.map +1 -0
  623. package/web/assets/EditorPane-CzzT3iYY.js +123 -0
  624. package/web/assets/SymbolsNerdFontMono-Regular-CwEZqMeU.woff2 +0 -0
  625. package/web/assets/TerminalPane-CjbYzePr.js +68 -0
  626. package/web/assets/TerminalPane-DkTCHfhq.css +1 -0
  627. package/web/assets/file-icons-JBi09j0r.js +6 -0
  628. package/web/assets/index-CTTkRpnn.css +2 -0
  629. package/web/assets/index-CmhewzMp.js +34 -0
  630. package/web/assets/session-resume-7f-tB-ZU.js +2 -0
  631. package/web/assets/terminal-trace-PuuFRybC.js +2803 -0
  632. package/web/assets/useVirtualKeyboard-DgJb9u9d.js +1 -0
  633. package/web/index.html +52 -0
@@ -0,0 +1,201 @@
1
+ import { createWriteStream } from "node:fs";
2
+ import { mkdir, rename, rm, stat } from "node:fs/promises";
3
+ import { homedir } from "node:os";
4
+ import { dirname, join } from "node:path";
5
+ import { Readable } from "node:stream";
6
+ import { pipeline } from "node:stream/promises";
7
+ import yauzl from "yauzl";
8
+ export class FontInstallError extends Error {
9
+ kind;
10
+ constructor(message, kind) {
11
+ super(message);
12
+ this.kind = kind;
13
+ }
14
+ }
15
+ export function defaultCacheDir() {
16
+ const base = process.env.XDG_CACHE_HOME ?? join(homedir(), ".cache");
17
+ return join(base, "parasor", "fonts");
18
+ }
19
+ export class FontInstaller {
20
+ cacheDir;
21
+ fetchImpl;
22
+ inflight = new Map();
23
+ constructor(opts = {}) {
24
+ this.cacheDir = opts.cacheDir ?? defaultCacheDir();
25
+ this.fetchImpl = opts.fetchImpl ?? fetch;
26
+ }
27
+ getCacheDir() {
28
+ return this.cacheDir;
29
+ }
30
+ /**
31
+ * Path of the cached TTF if already installed, otherwise null. Used by the
32
+ * static serving route to short-circuit without touching the installer.
33
+ */
34
+ async resolveInstalled(id) {
35
+ const dir = join(this.cacheDir, id);
36
+ const ttfPath = join(dir, "font.ttf");
37
+ try {
38
+ const st = await stat(ttfPath);
39
+ if (!st.isFile() || st.size === 0)
40
+ return null;
41
+ }
42
+ catch {
43
+ return null;
44
+ }
45
+ try {
46
+ const familyFile = join(dir, "family.txt");
47
+ const { readFile } = await import("node:fs/promises");
48
+ const family = (await readFile(familyFile, "utf-8")).trim();
49
+ if (!family)
50
+ return null;
51
+ return { filePath: ttfPath, family };
52
+ }
53
+ catch {
54
+ return null;
55
+ }
56
+ }
57
+ async listInstalled() {
58
+ const { readdir } = await import("node:fs/promises");
59
+ try {
60
+ const entries = await readdir(this.cacheDir, { withFileTypes: true });
61
+ const installed = [];
62
+ for (const entry of entries) {
63
+ if (!entry.isDirectory())
64
+ continue;
65
+ const resolved = await this.resolveInstalled(entry.name);
66
+ if (resolved)
67
+ installed.push(entry.name);
68
+ }
69
+ return installed;
70
+ }
71
+ catch {
72
+ return [];
73
+ }
74
+ }
75
+ /**
76
+ * Install a preset. Concurrent calls for the same id share a single
77
+ * download -- the second caller awaits the first rather than kicking off a
78
+ * duplicate 700MB fetch.
79
+ */
80
+ async install(preset) {
81
+ const existing = this.inflight.get(preset.id);
82
+ if (existing)
83
+ return existing;
84
+ const promise = this.doInstall(preset).finally(() => {
85
+ this.inflight.delete(preset.id);
86
+ });
87
+ this.inflight.set(preset.id, promise);
88
+ return promise;
89
+ }
90
+ async doInstall(preset) {
91
+ const resolved = await this.resolveInstalled(preset.id);
92
+ if (resolved) {
93
+ return {
94
+ id: preset.id,
95
+ family: resolved.family,
96
+ filename: "font.ttf",
97
+ filePath: resolved.filePath,
98
+ };
99
+ }
100
+ const targetDir = join(this.cacheDir, preset.id);
101
+ await mkdir(targetDir, { recursive: true });
102
+ const zipPath = join(targetDir, "download.zip.tmp");
103
+ const ttfTmpPath = join(targetDir, "font.ttf.tmp");
104
+ const ttfPath = join(targetDir, "font.ttf");
105
+ const familyPath = join(targetDir, "family.txt");
106
+ try {
107
+ await this.downloadTo(preset.zipUrl, zipPath);
108
+ await this.extractRegularTtf(zipPath, preset.regularMatch, ttfTmpPath);
109
+ await rename(ttfTmpPath, ttfPath);
110
+ const { writeFile } = await import("node:fs/promises");
111
+ await writeFile(familyPath, preset.family, "utf-8");
112
+ return {
113
+ id: preset.id,
114
+ family: preset.family,
115
+ filename: "font.ttf",
116
+ filePath: ttfPath,
117
+ };
118
+ }
119
+ finally {
120
+ // Best-effort cleanup of temp artifacts.
121
+ await rm(zipPath, { force: true });
122
+ await rm(ttfTmpPath, { force: true });
123
+ }
124
+ }
125
+ async downloadTo(url, destPath) {
126
+ await mkdir(dirname(destPath), { recursive: true });
127
+ let response;
128
+ try {
129
+ response = await this.fetchImpl(url, { redirect: "follow" });
130
+ }
131
+ catch (error) {
132
+ throw new FontInstallError(`download failed: ${error.message}`, "download_failed");
133
+ }
134
+ if (!response.ok || !response.body) {
135
+ throw new FontInstallError(`download returned ${response.status}`, "download_failed");
136
+ }
137
+ try {
138
+ // response.body is a web-stream ReadableStream; Readable.fromWeb bridges
139
+ // it into a Node stream that pipeline() can consume.
140
+ const nodeStream = Readable.fromWeb(response.body);
141
+ await pipeline(nodeStream, createWriteStream(destPath));
142
+ }
143
+ catch (error) {
144
+ throw new FontInstallError(`write failed: ${error.message}`, "io_failed");
145
+ }
146
+ }
147
+ extractRegularTtf(zipPath, matchSubstring, destPath) {
148
+ const matchLower = matchSubstring.toLowerCase();
149
+ return new Promise((resolve, reject) => {
150
+ yauzl.open(zipPath, { lazyEntries: true }, (err, zipfile) => {
151
+ if (err || !zipfile) {
152
+ reject(new FontInstallError(`zip open failed: ${err?.message ?? "no zipfile"}`, "extract_failed"));
153
+ return;
154
+ }
155
+ let extracted = false;
156
+ zipfile.readEntry();
157
+ zipfile.on("entry", (entry) => {
158
+ if (extracted) {
159
+ zipfile.close();
160
+ return;
161
+ }
162
+ const name = entry.fileName;
163
+ const isDir = /\/$/.test(name);
164
+ const lower = name.toLowerCase();
165
+ const isMatch = !isDir && lower.endsWith(".ttf") && lower.includes(matchLower);
166
+ if (!isMatch) {
167
+ zipfile.readEntry();
168
+ return;
169
+ }
170
+ zipfile.openReadStream(entry, (streamErr, readStream) => {
171
+ if (streamErr || !readStream) {
172
+ zipfile.close();
173
+ reject(new FontInstallError(`read stream failed: ${streamErr?.message ?? "no stream"}`, "extract_failed"));
174
+ return;
175
+ }
176
+ const writeStream = createWriteStream(destPath);
177
+ pipeline(readStream, writeStream)
178
+ .then(() => {
179
+ extracted = true;
180
+ zipfile.close();
181
+ resolve();
182
+ })
183
+ .catch((pipeErr) => {
184
+ zipfile.close();
185
+ reject(new FontInstallError(`extract write failed: ${pipeErr.message}`, "extract_failed"));
186
+ });
187
+ });
188
+ });
189
+ zipfile.on("end", () => {
190
+ if (!extracted) {
191
+ reject(new FontInstallError(`no Regular TTF matching "${matchSubstring}" in zip`, "asset_not_found"));
192
+ }
193
+ });
194
+ zipfile.on("error", (zipErr) => {
195
+ reject(new FontInstallError(`zip error: ${zipErr.message}`, "extract_failed"));
196
+ });
197
+ });
198
+ });
199
+ }
200
+ }
201
+ //# sourceMappingURL=installer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"installer.js","sourceRoot":"","sources":["../../src/fonts/installer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import { Hono } from "hono";
2
+ import { type FontInstaller } from "./installer.js";
3
+ export declare function createFontRoutes(installer: FontInstaller): Hono;
4
+ //# sourceMappingURL=routes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../../src/fonts/routes.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAQ5B,OAAO,EAAoB,KAAK,aAAa,EAAE,MAAM,gBAAgB,CAAC;AActE,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,aAAa,GAAG,IAAI,CA6E/D"}
@@ -0,0 +1,91 @@
1
+ import { createReadStream } from "node:fs";
2
+ import { stat } from "node:fs/promises";
3
+ import { Readable } from "node:stream";
4
+ import { Hono } from "hono";
5
+ import { stream } from "hono/streaming";
6
+ import { FONT_PRESETS, findPreset, isValidPresetId, toPublicPreset, } from "./catalog.js";
7
+ import { FontInstallError } from "./installer.js";
8
+ /*
9
+ * Font download / serving routes.
10
+ *
11
+ * GET /api/fonts/catalog list presets + which ones are already cached
12
+ * POST /api/fonts/install body { id } -> cache miss triggers zip DL
13
+ * GET /api/fonts/file/:id stream the cached TTF, 404 if not installed
14
+ *
15
+ * Everything lives under /api so the session-auth middleware (cookie or
16
+ * token) protects each endpoint. The TTF download is large but infrequent,
17
+ * so there is no separate unauthenticated static mount -- any client that
18
+ * can reach /api has the cookie a @font-face GET needs.
19
+ */
20
+ export function createFontRoutes(installer) {
21
+ const app = new Hono();
22
+ app.get("/catalog", async (c) => {
23
+ const installedIds = new Set(await installer.listInstalled());
24
+ const presets = FONT_PRESETS.map((preset) => ({
25
+ ...toPublicPreset(preset),
26
+ installed: installedIds.has(preset.id),
27
+ }));
28
+ return c.json({ presets });
29
+ });
30
+ app.post("/install", async (c) => {
31
+ const body = (await c.req.json().catch(() => null));
32
+ const id = body?.id;
33
+ if (!isValidPresetId(id)) {
34
+ return c.json({ error: "unknown preset id" }, 400);
35
+ }
36
+ const preset = findPreset(id);
37
+ if (!preset) {
38
+ return c.json({ error: "unknown preset id" }, 400);
39
+ }
40
+ try {
41
+ const result = await installer.install(preset);
42
+ return c.json({
43
+ id: result.id,
44
+ family: result.family,
45
+ url: `/api/fonts/file/${result.id}`,
46
+ installed: true,
47
+ });
48
+ }
49
+ catch (error) {
50
+ if (error instanceof FontInstallError) {
51
+ const status = error.kind === "download_failed"
52
+ ? 502
53
+ : error.kind === "asset_not_found"
54
+ ? 404
55
+ : 500;
56
+ return c.json({ error: error.message, kind: error.kind }, status);
57
+ }
58
+ throw error;
59
+ }
60
+ });
61
+ app.get("/file/:id", async (c) => {
62
+ const id = c.req.param("id");
63
+ if (!isValidPresetId(id)) {
64
+ return c.json({ error: "unknown preset id" }, 400);
65
+ }
66
+ const resolved = await installer.resolveInstalled(id);
67
+ if (!resolved) {
68
+ return c.json({ error: "not installed" }, 404);
69
+ }
70
+ let size;
71
+ try {
72
+ size = (await stat(resolved.filePath)).size;
73
+ }
74
+ catch {
75
+ return c.json({ error: "not installed" }, 404);
76
+ }
77
+ c.header("Content-Type", "font/ttf");
78
+ c.header("Content-Length", String(size));
79
+ // TTFs are immutable per-install (same version always produces the same
80
+ // bytes) -- let the browser cache aggressively so picking an installed
81
+ // preset a second time doesn't re-fetch.
82
+ c.header("Cache-Control", "public, max-age=31536000, immutable");
83
+ return stream(c, async (s) => {
84
+ const nodeStream = createReadStream(resolved.filePath);
85
+ const webStream = Readable.toWeb(nodeStream);
86
+ await s.pipe(webStream);
87
+ });
88
+ });
89
+ return app;
90
+ }
91
+ //# sourceMappingURL=routes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routes.js","sourceRoot":"","sources":["../../src/fonts/routes.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,50 @@
1
+ import { open } from "node:fs/promises";
2
+ /**
3
+ * Drops handler shared by chat-input image paste / DnD. Files are persisted
4
+ * under a caller-supplied `targetDir`; in production that is an
5
+ * `UploadStaging`-managed temp directory outside the project tree (issue
6
+ * upload staging isolation). The function does not create the dir -- the caller is expected to
7
+ * have produced it via `UploadStaging.acquire(sessionId)` so that the 3-
8
+ * layer GC owns its lifetime.
9
+ */
10
+ export type DropRejectReason = "path-traversal" | "control-char" | "too-long" | "empty" | "reserved";
11
+ export declare class InvalidFilenameError extends Error {
12
+ readonly reason: DropRejectReason;
13
+ constructor(reason: DropRejectReason, message?: string);
14
+ }
15
+ /**
16
+ * Replace characters the OS filesystem or pty pipe cannot safely carry:
17
+ * path separators, NUL, C0 controls, ASCII and NBSP whitespace. Reject
18
+ * the request outright for the three strings that silently resolve to
19
+ * a parent directory (`""`, `"."`, `".."`) or that include a `..`
20
+ * segment. Caller further fences the result against the target dir
21
+ * before writing (defence in depth).
22
+ */
23
+ export declare function sanitizeFilename(input: string): string;
24
+ export interface SaveDropsDeps {
25
+ /** Returns the current wall-clock. Injected for deterministic tests. */
26
+ now?: () => Date;
27
+ /**
28
+ * Test-only override for the `O_EXCL` filename-claim step. Production
29
+ * code always uses `node:fs/promises.open`; tests inject a stub that
30
+ * fakes EEXIST to exercise the collision-retry loop without pre-
31
+ * populating 1000+ real files on disk.
32
+ */
33
+ openForTest?: typeof open;
34
+ }
35
+ export interface DropInput {
36
+ /** Original filename as provided by the client. Sanitized internally. */
37
+ filename: string;
38
+ /** Raw file bytes to persist. */
39
+ bytes: Uint8Array;
40
+ }
41
+ /**
42
+ * Persist drops under `targetDir` (already created by the caller --
43
+ * typically `UploadStaging.acquire(sessionId)`) and return the absolute
44
+ * written paths in the same order as the input. Collisions in the same
45
+ * second get a `-2`, `-3`, ... suffix inserted before the final
46
+ * extension. `writeFileAtomic` guarantees partial writes are
47
+ * impossible: the temp file is renamed into place only after flush.
48
+ */
49
+ export declare function saveDrops(targetDir: string, inputs: readonly DropInput[], deps?: SaveDropsDeps): Promise<string[]>;
50
+ //# sourceMappingURL=drops.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"drops.d.ts","sourceRoot":"","sources":["../../src/fs/drops.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAY,MAAM,kBAAkB,CAAC;AAIlD;;;;;;;GAOG;AAEH,MAAM,MAAM,gBAAgB,GACxB,gBAAgB,GAChB,cAAc,GACd,UAAU,GACV,OAAO,GACP,UAAU,CAAC;AAEf,qBAAa,oBAAqB,SAAQ,KAAK;IAC7C,QAAQ,CAAC,MAAM,EAAE,gBAAgB,CAAC;gBACtB,MAAM,EAAE,gBAAgB,EAAE,OAAO,CAAC,EAAE,MAAM;CAKvD;AAgBD;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAiBtD;AAeD,MAAM,WAAW,aAAa;IAC5B,wEAAwE;IACxE,GAAG,CAAC,EAAE,MAAM,IAAI,CAAC;IACjB;;;;;OAKG;IACH,WAAW,CAAC,EAAE,OAAO,IAAI,CAAC;CAC3B;AAED,MAAM,WAAW,SAAS;IACxB,yEAAyE;IACzE,QAAQ,EAAE,MAAM,CAAC;IACjB,iCAAiC;IACjC,KAAK,EAAE,UAAU,CAAC;CACnB;AAED;;;;;;;GAOG;AACH,wBAAsB,SAAS,CAC7B,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,SAAS,SAAS,EAAE,EAC5B,IAAI,GAAE,aAAkB,GACvB,OAAO,CAAC,MAAM,EAAE,CAAC,CAoEnB"}
@@ -0,0 +1,137 @@
1
+ import { open, realpath } from "node:fs/promises";
2
+ import { extname, resolve, sep } from "node:path";
3
+ import writeFileAtomic from "write-file-atomic";
4
+ export class InvalidFilenameError extends Error {
5
+ reason;
6
+ constructor(reason, message) {
7
+ super(message ?? `invalid filename: ${reason}`);
8
+ this.reason = reason;
9
+ this.name = "InvalidFilenameError";
10
+ }
11
+ }
12
+ /**
13
+ * Drop naming: `{YYYYMMDD-HHMMSS}_{sanitized}` in local time. Local time
14
+ * is an explicit product decision (by design) -- the CLI user wants to
15
+ * reference "the file I just dropped" by human-readable wall-clock,
16
+ * not UTC.
17
+ */
18
+ function formatTimestamp(date) {
19
+ const pad = (n) => n.toString().padStart(2, "0");
20
+ return (`${date.getFullYear()}${pad(date.getMonth() + 1)}${pad(date.getDate())}` +
21
+ `-${pad(date.getHours())}${pad(date.getMinutes())}${pad(date.getSeconds())}`);
22
+ }
23
+ /**
24
+ * Replace characters the OS filesystem or pty pipe cannot safely carry:
25
+ * path separators, NUL, C0 controls, ASCII and NBSP whitespace. Reject
26
+ * the request outright for the three strings that silently resolve to
27
+ * a parent directory (`""`, `"."`, `".."`) or that include a `..`
28
+ * segment. Caller further fences the result against the target dir
29
+ * before writing (defence in depth).
30
+ */
31
+ export function sanitizeFilename(input) {
32
+ const nfc = input.normalize("NFC");
33
+ if (nfc === "" || nfc === "." || nfc === "..") {
34
+ throw new InvalidFilenameError("path-traversal");
35
+ }
36
+ if (/(^|[\\/])\.\.([\\/]|$)/.test(nfc)) {
37
+ throw new InvalidFilenameError("path-traversal");
38
+ }
39
+ // biome-ignore lint/suspicious/noControlCharactersInRegex: upload filenames intentionally rewrite C0/DEL bytes.
40
+ const replaced = nfc.replace(/[\\/\x00-\x1f\x7f  ]/g, "_");
41
+ if (replaced === "." || replaced === "..") {
42
+ throw new InvalidFilenameError("path-traversal");
43
+ }
44
+ if (replaced.length <= 255)
45
+ return replaced;
46
+ const ext = extname(replaced);
47
+ const base = replaced.slice(0, 255 - ext.length);
48
+ return base + ext;
49
+ }
50
+ /**
51
+ * `extname("image.tar.gz") === ".gz"`, so suffix insertion happens before
52
+ * the final extension only; conflict-count inserts ahead of `.gz` rather
53
+ * than in front of `.tar`. Agreed tradeoff -- the alternative (strip every
54
+ * tail ext) mis-handles dotted filenames like `component.test.tsx`.
55
+ */
56
+ function splitBasenameExt(name) {
57
+ const ext = extname(name);
58
+ return { base: ext ? name.slice(0, -ext.length) : name, ext };
59
+ }
60
+ const MAX_SUFFIX_ATTEMPTS = 1000;
61
+ /**
62
+ * Persist drops under `targetDir` (already created by the caller --
63
+ * typically `UploadStaging.acquire(sessionId)`) and return the absolute
64
+ * written paths in the same order as the input. Collisions in the same
65
+ * second get a `-2`, `-3`, ... suffix inserted before the final
66
+ * extension. `writeFileAtomic` guarantees partial writes are
67
+ * impossible: the temp file is renamed into place only after flush.
68
+ */
69
+ export async function saveDrops(targetDir, inputs, deps = {}) {
70
+ if (inputs.length === 0)
71
+ return [];
72
+ const now = deps.now ?? (() => new Date());
73
+ const openFn = deps.openForTest ?? open;
74
+ /**
75
+ * Realpath the supplied dir as defence in depth: even though the
76
+ * caller is expected to have done this, a regression upstream (e.g.
77
+ * passing a pre-canonical path that contains a symlink) would otherwise
78
+ * let a planted symlink under `targetDir` redirect writes outside it.
79
+ * We compare canonical paths when fencing each claim.
80
+ */
81
+ const canonicalTarget = await realpath(targetDir);
82
+ const saved = [];
83
+ for (const input of inputs) {
84
+ const sanitized = sanitizeFilename(input.filename);
85
+ const timestamp = formatTimestamp(now());
86
+ const { base, ext } = splitBasenameExt(sanitized);
87
+ const prefix = `${timestamp}_${base}`;
88
+ let finalName = `${prefix}${ext}`;
89
+ let attempt = 2;
90
+ let target = resolve(canonicalTarget, finalName);
91
+ /**
92
+ * Claim the final filename with an exclusive create (`O_EXCL`). This
93
+ * closes the check-then-write TOCTOU window that a `statSync + write`
94
+ * probe would leave open: two parallel uploads of `notes.txt` in the
95
+ * same second would otherwise both pass the exists-check and race
96
+ * each other's `writeFileAtomic(rename)` to overwrite the winner.
97
+ * `wx` fails with EEXIST if the file exists, so losers fall through
98
+ * to the next suffix.
99
+ */
100
+ while (true) {
101
+ // Fence against sanitizer misses: the claimed path must live under
102
+ // the canonicalized target dir.
103
+ if (!target.startsWith(canonicalTarget + sep)) {
104
+ throw new InvalidFilenameError("path-traversal", `refusing to write outside ${canonicalTarget}`);
105
+ }
106
+ try {
107
+ const fh = await openFn(target, "wx");
108
+ await fh.close();
109
+ break;
110
+ }
111
+ catch (err) {
112
+ if (!isNodeErrorWithCode(err, "EEXIST"))
113
+ throw err;
114
+ if (attempt > MAX_SUFFIX_ATTEMPTS) {
115
+ throw new Error(`saveDrops: exhausted ${MAX_SUFFIX_ATTEMPTS} collision slots for ${sanitized}`);
116
+ }
117
+ finalName = `${prefix}-${attempt}${ext}`;
118
+ target = resolve(canonicalTarget, finalName);
119
+ attempt += 1;
120
+ }
121
+ }
122
+ // write-file-atomic expects `string | Buffer`. Wrap without copying:
123
+ // `Buffer.from(Uint8Array)` shares the backing ArrayBuffer.
124
+ // The `O_EXCL` claim above has already reserved the final filename,
125
+ // so the atomic rename inside writeFileAtomic now only overwrites
126
+ // our own empty claim file -- never another uploader's content.
127
+ await writeFileAtomic(target, Buffer.from(input.bytes));
128
+ saved.push(target);
129
+ }
130
+ return saved;
131
+ }
132
+ function isNodeErrorWithCode(err, code) {
133
+ return (err instanceof Error &&
134
+ "code" in err &&
135
+ err.code === code);
136
+ }
137
+ //# sourceMappingURL=drops.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"drops.js","sourceRoot":"","sources":["../../src/fs/drops.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,57 @@
1
+ import { open } from "node:fs/promises";
2
+ import type { FileUploadDisposition, FileUploadRejectReason, FileUploadResultEntry } from "@parasor/shared";
3
+ export type InvalidTargetReason = "path-traversal" | "not-a-dir" | "missing";
4
+ export declare class InvalidUploadFilenameError extends Error {
5
+ readonly reason: FileUploadRejectReason;
6
+ constructor(reason: FileUploadRejectReason, message?: string);
7
+ }
8
+ export declare class InvalidUploadTargetError extends Error {
9
+ readonly reason: InvalidTargetReason;
10
+ constructor(reason: InvalidTargetReason, message?: string);
11
+ }
12
+ export declare class UploadConflictError extends Error {
13
+ readonly conflicts: string[];
14
+ constructor(conflicts: string[]);
15
+ }
16
+ /**
17
+ * Same character/length policy as `fs/drops.ts#sanitizeFilename`. The
18
+ * difference: drops always live under `{root}/.parasor/drops/`, whereas
19
+ * uploads target an arbitrary subdir. Both protect against `..` segments
20
+ * and control characters at the filename layer; the realpath fence below
21
+ * protects the directory layer.
22
+ */
23
+ export declare function sanitizeUploadFilename(input: string): string;
24
+ /**
25
+ * Resolve `relative` against `projectRoot` and prove the result is an
26
+ * existing directory inside the project. Returns the canonicalized
27
+ * (realpath-ed) absolute path; the caller writes into it.
28
+ *
29
+ * `relative` is the value submitted by the client via the `path` query
30
+ * parameter. An empty string (or `.`) means "the project root itself".
31
+ */
32
+ export declare function resolveTargetDir(projectRoot: string, relative: string): Promise<string>;
33
+ export interface UploadInput {
34
+ filename: string;
35
+ bytes: Uint8Array;
36
+ }
37
+ export interface SaveUploadsDeps {
38
+ /** Test-only override for the `O_EXCL` filename-claim step. */
39
+ openForTest?: typeof open;
40
+ }
41
+ /**
42
+ * Persist `inputs` into `targetDir` (already validated by
43
+ * `resolveTargetDir`) and return a result entry per input describing
44
+ * what happened on disk.
45
+ *
46
+ * `disposition` decides conflict semantics:
47
+ * - `replace` -- overwrite existing files in place via atomic rename
48
+ * - `keep-both` -- write next to the existing file with `-2`, `-3`, ...
49
+ * - `skip` -- preflight all collisions; if any exist, throw
50
+ * `UploadConflictError` and write nothing
51
+ *
52
+ * `targetDir` must be the canonical (realpath-ed) directory; this
53
+ * function asserts every claim path lives under it as a defence-in-depth
54
+ * fence behind `resolveTargetDir`.
55
+ */
56
+ export declare function saveUploads(targetDir: string, inputs: readonly UploadInput[], disposition: FileUploadDisposition, deps?: SaveUploadsDeps): Promise<FileUploadResultEntry[]>;
57
+ //# sourceMappingURL=file-uploads.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-uploads.d.ts","sourceRoot":"","sources":["../../src/fs/file-uploads.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAkB,MAAM,kBAAkB,CAAC;AAExD,OAAO,KAAK,EACV,qBAAqB,EACrB,sBAAsB,EACtB,qBAAqB,EACtB,MAAM,iBAAiB,CAAC;AAGzB,MAAM,MAAM,mBAAmB,GAAG,gBAAgB,GAAG,WAAW,GAAG,SAAS,CAAC;AAE7E,qBAAa,0BAA2B,SAAQ,KAAK;IACnD,QAAQ,CAAC,MAAM,EAAE,sBAAsB,CAAC;gBAC5B,MAAM,EAAE,sBAAsB,EAAE,OAAO,CAAC,EAAE,MAAM;CAK7D;AAED,qBAAa,wBAAyB,SAAQ,KAAK;IACjD,QAAQ,CAAC,MAAM,EAAE,mBAAmB,CAAC;gBACzB,MAAM,EAAE,mBAAmB,EAAE,OAAO,CAAC,EAAE,MAAM;CAK1D;AAED,qBAAa,mBAAoB,SAAQ,KAAK;IAC5C,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,CAAC;gBACjB,SAAS,EAAE,MAAM,EAAE;CAKhC;AAED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAiB5D;AASD;;;;;;;GAOG;AACH,wBAAsB,gBAAgB,CACpC,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,MAAM,CAAC,CA8CjB;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,UAAU,CAAC;CACnB;AAED,MAAM,WAAW,eAAe;IAC9B,+DAA+D;IAC/D,WAAW,CAAC,EAAE,OAAO,IAAI,CAAC;CAC3B;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,WAAW,CAC/B,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,SAAS,WAAW,EAAE,EAC9B,WAAW,EAAE,qBAAqB,EAClC,IAAI,GAAE,eAAoB,GACzB,OAAO,CAAC,qBAAqB,EAAE,CAAC,CAsFlC"}