@graftland/plugin-remote 0.0.0-stage → 0.3.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 (380) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +76 -2
  3. package/README.zh-CN.md +71 -0
  4. package/README.zh-TW.md +71 -0
  5. package/dist/Auth-BElTC9_X.js +6 -0
  6. package/dist/Auth.d.ts +49 -0
  7. package/dist/Auth.d.ts.map +1 -0
  8. package/dist/Auth.js +8 -0
  9. package/dist/Auth.js.map +1 -0
  10. package/dist/Bootstrap-MCwivGN1.js +9 -0
  11. package/dist/ConfigDirectory-BCC6q2R4.js +5 -0
  12. package/dist/Contract-CcpSIJm4.js +121 -0
  13. package/dist/Contract.d.ts +71 -0
  14. package/dist/Contract.d.ts.map +1 -0
  15. package/dist/Contract.js +1 -0
  16. package/dist/Contract.js.map +1 -0
  17. package/dist/Errors-oPsTLY7l.js +45 -0
  18. package/dist/Errors.d.ts +67 -0
  19. package/dist/Errors.d.ts.map +1 -0
  20. package/dist/Errors.js +47 -0
  21. package/dist/Errors.js.map +1 -0
  22. package/dist/FailureGroup-BcH0XOBi.js +53 -0
  23. package/dist/Framing-zaYdOJnT.js +61 -0
  24. package/dist/Graft-BsYq3F-J.js +985 -0
  25. package/dist/Instance.d.ts +7 -0
  26. package/dist/Instance.d.ts.map +1 -0
  27. package/dist/Instance.js +14 -0
  28. package/dist/Instance.js.map +1 -0
  29. package/dist/Packages-B1TPk8pa.js +111 -0
  30. package/dist/Peer-IJgFK6mD.js +342 -0
  31. package/dist/ProcessObservation-DEGrEMfP.js +38 -0
  32. package/dist/ServeLifecycle-CJM0gG5B.js +24 -0
  33. package/dist/Testing.d.ts +26 -0
  34. package/dist/Testing.d.ts.map +1 -0
  35. package/dist/Testing.js +69 -0
  36. package/dist/Testing.js.map +1 -0
  37. package/dist/Transport-DULzpsgR.js +6 -0
  38. package/dist/Transport.d.ts +39 -0
  39. package/dist/Transport.d.ts.map +1 -0
  40. package/dist/Transport.js +8 -0
  41. package/dist/Transport.js.map +1 -0
  42. package/dist/WatchdogProtocol-BZmVxrBP.js +17 -0
  43. package/dist/_virtual/_rolldown/runtime.js +12 -0
  44. package/dist/bin.d.ts +1 -0
  45. package/dist/bin.js +28275 -0
  46. package/dist/bin.js.map +1 -0
  47. package/dist/childRuntime-DSqtFN9o.js +188 -0
  48. package/dist/cleanup-BPWr-5U9.js +13 -0
  49. package/dist/command-9zrHdbwT.js +7 -0
  50. package/dist/connectionEnded-DUgcobEd.js +9 -0
  51. package/dist/directTransport-DrexuPSm.js +5 -0
  52. package/dist/entry-SYsx9VNb.js +708 -0
  53. package/dist/host/auth/bearer.d.ts +5 -0
  54. package/dist/host/auth/bearer.d.ts.map +1 -0
  55. package/dist/host/auth/bearer.js +4 -0
  56. package/dist/host/auth/bearer.js.map +1 -0
  57. package/dist/host/auth/jwt.d.ts +5 -0
  58. package/dist/host/auth/jwt.d.ts.map +1 -0
  59. package/dist/host/auth/jwt.js +4 -0
  60. package/dist/host/auth/jwt.js.map +1 -0
  61. package/dist/host/auth/mtls.d.ts +8 -0
  62. package/dist/host/auth/mtls.d.ts.map +1 -0
  63. package/dist/host/auth/mtls.js +34 -0
  64. package/dist/host/auth/mtls.js.map +1 -0
  65. package/dist/host/auth/none.d.ts +3 -0
  66. package/dist/host/auth/none.d.ts.map +1 -0
  67. package/dist/host/auth/none.js +13 -0
  68. package/dist/host/auth/none.js.map +1 -0
  69. package/dist/host/command.d.ts +22 -0
  70. package/dist/host/command.d.ts.map +1 -0
  71. package/dist/host/command.js +61 -0
  72. package/dist/host/command.js.map +1 -0
  73. package/dist/host/local.d.ts +4 -0
  74. package/dist/host/local.d.ts.map +1 -0
  75. package/dist/host/local.js +52 -0
  76. package/dist/host/local.js.map +1 -0
  77. package/dist/host/unix.d.ts +11 -0
  78. package/dist/host/unix.d.ts.map +1 -0
  79. package/dist/host/unix.js +39 -0
  80. package/dist/host/unix.js.map +1 -0
  81. package/dist/host/websocket.d.ts +13 -0
  82. package/dist/host/websocket.d.ts.map +1 -0
  83. package/dist/host/websocket.js +36 -0
  84. package/dist/host/websocket.js.map +1 -0
  85. package/dist/host/worker.d.ts +4 -0
  86. package/dist/host/worker.d.ts.map +1 -0
  87. package/dist/host/worker.js +52 -0
  88. package/dist/host/worker.js.map +1 -0
  89. package/dist/importer-D7zSgqxq.js +347 -0
  90. package/dist/index.d.ts +29 -0
  91. package/dist/index.d.ts.map +1 -0
  92. package/dist/index.js +86 -0
  93. package/dist/index.js.map +1 -0
  94. package/dist/internal/Certificates.js +182 -0
  95. package/dist/internal/Certificates.js.map +1 -0
  96. package/dist/internal/FailureGroup.js +55 -0
  97. package/dist/internal/FailureGroup.js.map +1 -0
  98. package/dist/internal/Limits.d.ts +1 -0
  99. package/dist/internal/Limits.js +17 -0
  100. package/dist/internal/Limits.js.map +1 -0
  101. package/dist/internal/Peer.js +6 -0
  102. package/dist/internal/Peer.js.map +1 -0
  103. package/dist/internal/ServeLifecycle.js +26 -0
  104. package/dist/internal/ServeLifecycle.js.map +1 -0
  105. package/dist/internal/Supervisor.js +7 -0
  106. package/dist/internal/Supervisor.js.map +1 -0
  107. package/dist/internal/assembly.d.ts +5 -0
  108. package/dist/internal/assembly.js +138 -0
  109. package/dist/internal/assembly.js.map +1 -0
  110. package/dist/internal/auth/mtls.js +23 -0
  111. package/dist/internal/auth/mtls.js.map +1 -0
  112. package/dist/internal/auth/token.js +19 -0
  113. package/dist/internal/auth/token.js.map +1 -0
  114. package/dist/internal/auth/tokenCredentials.d.ts +8 -0
  115. package/dist/internal/auth/tokenCredentials.d.ts.map +1 -0
  116. package/dist/internal/auth/tokenCredentials.js +33 -0
  117. package/dist/internal/auth/tokenCredentials.js.map +1 -0
  118. package/dist/internal/child.js +125 -0
  119. package/dist/internal/child.js.map +1 -0
  120. package/dist/internal/childErrors.d.ts +33 -0
  121. package/dist/internal/childErrors.d.ts.map +1 -0
  122. package/dist/internal/childErrors.js +29 -0
  123. package/dist/internal/childErrors.js.map +1 -0
  124. package/dist/internal/childRuntime.js +59 -0
  125. package/dist/internal/childRuntime.js.map +1 -0
  126. package/dist/internal/cleanup.js +15 -0
  127. package/dist/internal/cleanup.js.map +1 -0
  128. package/dist/internal/config.js +6 -0
  129. package/dist/internal/config.js.map +1 -0
  130. package/dist/internal/control.js +42 -0
  131. package/dist/internal/control.js.map +1 -0
  132. package/dist/internal/credentials.d.ts +44 -0
  133. package/dist/internal/credentials.d.ts.map +1 -0
  134. package/dist/internal/credentials.js +54 -0
  135. package/dist/internal/credentials.js.map +1 -0
  136. package/dist/internal/directTransport.d.ts +3 -0
  137. package/dist/internal/directTransport.js +7 -0
  138. package/dist/internal/directTransport.js.map +1 -0
  139. package/dist/internal/entry.d.ts +9 -0
  140. package/dist/internal/entry.d.ts.map +1 -0
  141. package/dist/internal/entry.js +144 -0
  142. package/dist/internal/entry.js.map +1 -0
  143. package/dist/internal/entryConfig.d.ts +202 -0
  144. package/dist/internal/entryConfig.d.ts.map +1 -0
  145. package/dist/internal/entryConfig.js +176 -0
  146. package/dist/internal/entryConfig.js.map +1 -0
  147. package/dist/internal/execution.d.ts +5 -0
  148. package/dist/internal/execution.js +43 -0
  149. package/dist/internal/execution.js.map +1 -0
  150. package/dist/internal/follow.js +11 -0
  151. package/dist/internal/follow.js.map +1 -0
  152. package/dist/internal/forkTree.js +7 -0
  153. package/dist/internal/forkTree.js.map +1 -0
  154. package/dist/internal/host/local.js +28 -0
  155. package/dist/internal/host/local.js.map +1 -0
  156. package/dist/internal/host/runner.js +100 -0
  157. package/dist/internal/host/runner.js.map +1 -0
  158. package/dist/internal/host.js +71 -0
  159. package/dist/internal/host.js.map +1 -0
  160. package/dist/internal/importer.js +18 -0
  161. package/dist/internal/importer.js.map +1 -0
  162. package/dist/internal/listenerStartup.js +17 -0
  163. package/dist/internal/listenerStartup.js.map +1 -0
  164. package/dist/internal/loadModule.js +20 -0
  165. package/dist/internal/loadModule.js.map +1 -0
  166. package/dist/internal/platform.js +9 -0
  167. package/dist/internal/platform.js.map +1 -0
  168. package/dist/internal/port.d.ts +13 -0
  169. package/dist/internal/port.d.ts.map +1 -0
  170. package/dist/internal/port.js +275 -0
  171. package/dist/internal/port.js.map +1 -0
  172. package/dist/internal/release.js +25 -0
  173. package/dist/internal/release.js.map +1 -0
  174. package/dist/internal/runner/Bootstrap.js +11 -0
  175. package/dist/internal/runner/Bootstrap.js.map +1 -0
  176. package/dist/internal/runner/Connection.d.ts +11 -0
  177. package/dist/internal/runner/Connection.js +56 -0
  178. package/dist/internal/runner/Connection.js.map +1 -0
  179. package/dist/internal/runner/Execution.js +115 -0
  180. package/dist/internal/runner/Execution.js.map +1 -0
  181. package/dist/internal/runner/Framing.d.ts +11 -0
  182. package/dist/internal/runner/Framing.d.ts.map +1 -0
  183. package/dist/internal/runner/Framing.js +63 -0
  184. package/dist/internal/runner/Framing.js.map +1 -0
  185. package/dist/internal/runner/Local.js +46 -0
  186. package/dist/internal/runner/Local.js.map +1 -0
  187. package/dist/internal/runner/Lock.js +25 -0
  188. package/dist/internal/runner/Lock.js.map +1 -0
  189. package/dist/internal/runner/Multiplex.d.ts +5 -0
  190. package/dist/internal/runner/Multiplex.js +49 -0
  191. package/dist/internal/runner/Multiplex.js.map +1 -0
  192. package/dist/internal/runner/Packages.d.ts +3 -0
  193. package/dist/internal/runner/Packages.js +108 -0
  194. package/dist/internal/runner/Packages.js.map +1 -0
  195. package/dist/internal/runner/ProcessObservation.js +40 -0
  196. package/dist/internal/runner/ProcessObservation.js.map +1 -0
  197. package/dist/internal/runner/Processes.js +83 -0
  198. package/dist/internal/runner/Processes.js.map +1 -0
  199. package/dist/internal/runner/Retention.js +13 -0
  200. package/dist/internal/runner/Retention.js.map +1 -0
  201. package/dist/internal/runner/Store.js +78 -0
  202. package/dist/internal/runner/Store.js.map +1 -0
  203. package/dist/internal/runner/Supervisor.js +375 -0
  204. package/dist/internal/runner/Supervisor.js.map +1 -0
  205. package/dist/internal/runner/Watchdog.js +47 -0
  206. package/dist/internal/runner/Watchdog.js.map +1 -0
  207. package/dist/internal/runner/WatchdogProtocol.js +19 -0
  208. package/dist/internal/runner/WatchdogProtocol.js.map +1 -0
  209. package/dist/internal/runner/Wire.d.ts +5 -0
  210. package/dist/internal/runner/Wire.js +64 -0
  211. package/dist/internal/runner/Wire.js.map +1 -0
  212. package/dist/internal/runner/accept.js +57 -0
  213. package/dist/internal/runner/accept.js.map +1 -0
  214. package/dist/internal/runner/command.js +9 -0
  215. package/dist/internal/runner/command.js.map +1 -0
  216. package/dist/internal/runner/connectionEnded.js +11 -0
  217. package/dist/internal/runner/connectionEnded.js.map +1 -0
  218. package/dist/internal/runner/model.d.ts +17 -0
  219. package/dist/internal/runner/model.d.ts.map +1 -0
  220. package/dist/internal/runner/model.js +231 -0
  221. package/dist/internal/runner/model.js.map +1 -0
  222. package/dist/internal/serve.js +60 -0
  223. package/dist/internal/serve.js.map +1 -0
  224. package/dist/internal/services.d.ts +18 -0
  225. package/dist/internal/services.d.ts.map +1 -0
  226. package/dist/internal/services.js +22 -0
  227. package/dist/internal/services.js.map +1 -0
  228. package/dist/internal/socketChannel.js +24 -0
  229. package/dist/internal/socketChannel.js.map +1 -0
  230. package/dist/internal/stdioChannel.js +23 -0
  231. package/dist/internal/stdioChannel.js.map +1 -0
  232. package/dist/internal/supervisorPlugin.js +1 -0
  233. package/dist/internal/supervisorPlugin.js.map +1 -0
  234. package/dist/internal/transportOptions.d.ts +18 -0
  235. package/dist/internal/transportOptions.d.ts.map +1 -0
  236. package/dist/internal/watchdogMain.d.ts +1 -0
  237. package/dist/internal/watchdogMain.js +55 -0
  238. package/dist/internal/watchdogMain.js.map +1 -0
  239. package/dist/internal/websocket.js +46 -0
  240. package/dist/internal/websocket.js.map +1 -0
  241. package/dist/internal/websocketServer.js +61 -0
  242. package/dist/internal/websocketServer.js.map +1 -0
  243. package/dist/internal/workerBootstrap.js +9 -0
  244. package/dist/internal/workerBootstrap.js.map +1 -0
  245. package/dist/internal/workerChannel.js +24 -0
  246. package/dist/internal/workerChannel.js.map +1 -0
  247. package/dist/internal/workerMain.d.ts +1 -0
  248. package/dist/internal/workerMain.js +18 -0
  249. package/dist/internal/workerMain.js.map +1 -0
  250. package/dist/port-Blbh8tms.js +285 -0
  251. package/dist/release-BY4Mlluy.js +23 -0
  252. package/dist/rolldown-runtime-DYf_mQCB.js +34 -0
  253. package/dist/runner/auth/bearer.d.ts +7 -0
  254. package/dist/runner/auth/bearer.d.ts.map +1 -0
  255. package/dist/runner/auth/bearer.js +42 -0
  256. package/dist/runner/auth/bearer.js.map +1 -0
  257. package/dist/runner/auth/jwt.d.ts +19 -0
  258. package/dist/runner/auth/jwt.d.ts.map +1 -0
  259. package/dist/runner/auth/jwt.js +65 -0
  260. package/dist/runner/auth/jwt.js.map +1 -0
  261. package/dist/runner/auth/mtls.d.ts +11 -0
  262. package/dist/runner/auth/mtls.d.ts.map +1 -0
  263. package/dist/runner/auth/mtls.js +48 -0
  264. package/dist/runner/auth/mtls.js.map +1 -0
  265. package/dist/runner/auth/none.d.ts +3 -0
  266. package/dist/runner/auth/none.d.ts.map +1 -0
  267. package/dist/runner/auth/none.js +13 -0
  268. package/dist/runner/auth/none.js.map +1 -0
  269. package/dist/runner/index.d.ts +3 -0
  270. package/dist/runner/index.d.ts.map +1 -0
  271. package/dist/runner/index.js +71 -0
  272. package/dist/runner/index.js.map +1 -0
  273. package/dist/runner/stdio.d.ts +7 -0
  274. package/dist/runner/stdio.d.ts.map +1 -0
  275. package/dist/runner/stdio.js +39 -0
  276. package/dist/runner/stdio.js.map +1 -0
  277. package/dist/runner/unix.d.ts +7 -0
  278. package/dist/runner/unix.d.ts.map +1 -0
  279. package/dist/runner/unix.js +42 -0
  280. package/dist/runner/unix.js.map +1 -0
  281. package/dist/runner/websocket.d.ts +28 -0
  282. package/dist/runner/websocket.d.ts.map +1 -0
  283. package/dist/runner/websocket.js +77 -0
  284. package/dist/runner/websocket.js.map +1 -0
  285. package/dist/socketChannel-KmtzF-9G.js +3658 -0
  286. package/dist/supervisorPlugin-Inb1S5IV.js +737 -0
  287. package/dist/token-v5ne2I0-.js +17 -0
  288. package/dist/tokenCredentials-WUJm2AKm.js +31 -0
  289. package/dist/websocketServer-MXcCJx0v.js +58 -0
  290. package/dist/workerChannel-P82YdNjh.js +27 -0
  291. package/package.json +69 -3
  292. package/src/Auth.ts +62 -0
  293. package/src/Contract.ts +100 -0
  294. package/src/Errors.ts +82 -0
  295. package/src/Instance.ts +12 -0
  296. package/src/Testing.ts +135 -0
  297. package/src/Transport.ts +52 -0
  298. package/src/bin.ts +145 -0
  299. package/src/host/auth/bearer.ts +10 -0
  300. package/src/host/auth/jwt.ts +10 -0
  301. package/src/host/auth/mtls.ts +48 -0
  302. package/src/host/auth/none.ts +13 -0
  303. package/src/host/command.ts +131 -0
  304. package/src/host/local.ts +41 -0
  305. package/src/host/unix.ts +65 -0
  306. package/src/host/websocket.ts +66 -0
  307. package/src/host/worker.ts +90 -0
  308. package/src/index.ts +115 -0
  309. package/src/internal/Certificates.ts +330 -0
  310. package/src/internal/FailureGroup.ts +176 -0
  311. package/src/internal/Limits.ts +12 -0
  312. package/src/internal/Peer.ts +4 -0
  313. package/src/internal/ServeLifecycle.ts +53 -0
  314. package/src/internal/Supervisor.ts +14 -0
  315. package/src/internal/assembly.ts +337 -0
  316. package/src/internal/auth/mtls.ts +40 -0
  317. package/src/internal/auth/token.ts +26 -0
  318. package/src/internal/auth/tokenCredentials.ts +65 -0
  319. package/src/internal/child.ts +323 -0
  320. package/src/internal/childErrors.ts +44 -0
  321. package/src/internal/childRuntime.ts +111 -0
  322. package/src/internal/cleanup.ts +34 -0
  323. package/src/internal/config.ts +8 -0
  324. package/src/internal/control.ts +49 -0
  325. package/src/internal/credentials.ts +112 -0
  326. package/src/internal/directTransport.ts +38 -0
  327. package/src/internal/entry.ts +288 -0
  328. package/src/internal/entryConfig.ts +190 -0
  329. package/src/internal/execution.ts +121 -0
  330. package/src/internal/follow.ts +17 -0
  331. package/src/internal/forkTree.ts +13 -0
  332. package/src/internal/host/local.ts +53 -0
  333. package/src/internal/host/runner.ts +187 -0
  334. package/src/internal/host.ts +209 -0
  335. package/src/internal/importer.ts +27 -0
  336. package/src/internal/listenerStartup.ts +55 -0
  337. package/src/internal/loadModule.ts +23 -0
  338. package/src/internal/platform.ts +12 -0
  339. package/src/internal/port.ts +623 -0
  340. package/src/internal/release.ts +71 -0
  341. package/src/internal/runner/Bootstrap.ts +9 -0
  342. package/src/internal/runner/Connection.ts +184 -0
  343. package/src/internal/runner/Execution.ts +244 -0
  344. package/src/internal/runner/Framing.ts +122 -0
  345. package/src/internal/runner/Local.ts +73 -0
  346. package/src/internal/runner/Lock.ts +29 -0
  347. package/src/internal/runner/Multiplex.ts +120 -0
  348. package/src/internal/runner/Packages.ts +178 -0
  349. package/src/internal/runner/ProcessObservation.ts +63 -0
  350. package/src/internal/runner/Processes.ts +109 -0
  351. package/src/internal/runner/Retention.ts +49 -0
  352. package/src/internal/runner/Store.ts +160 -0
  353. package/src/internal/runner/Supervisor.ts +901 -0
  354. package/src/internal/runner/Watchdog.ts +83 -0
  355. package/src/internal/runner/WatchdogProtocol.ts +12 -0
  356. package/src/internal/runner/Wire.ts +99 -0
  357. package/src/internal/runner/accept.ts +103 -0
  358. package/src/internal/runner/command.ts +15 -0
  359. package/src/internal/runner/connectionEnded.ts +28 -0
  360. package/src/internal/runner/model.ts +364 -0
  361. package/src/internal/serve.ts +117 -0
  362. package/src/internal/services.ts +74 -0
  363. package/src/internal/socketChannel.ts +64 -0
  364. package/src/internal/stdioChannel.ts +25 -0
  365. package/src/internal/supervisorPlugin.ts +67 -0
  366. package/src/internal/transportOptions.ts +17 -0
  367. package/src/internal/watchdogMain.ts +72 -0
  368. package/src/internal/websocket.ts +81 -0
  369. package/src/internal/websocketServer.ts +152 -0
  370. package/src/internal/workerBootstrap.ts +6 -0
  371. package/src/internal/workerChannel.ts +54 -0
  372. package/src/internal/workerMain.ts +23 -0
  373. package/src/runner/auth/bearer.ts +66 -0
  374. package/src/runner/auth/jwt.ts +114 -0
  375. package/src/runner/auth/mtls.ts +37 -0
  376. package/src/runner/auth/none.ts +13 -0
  377. package/src/runner/index.ts +97 -0
  378. package/src/runner/stdio.ts +76 -0
  379. package/src/runner/unix.ts +53 -0
  380. package/src/runner/websocket.ts +143 -0
@@ -0,0 +1,623 @@
1
+ import { EndOfStream } from "./runner/Framing"
2
+ export type { Channel } from "../Transport"
3
+ import type { Channel } from "../Transport"
4
+ import {
5
+ Array,
6
+ Cause,
7
+ Context,
8
+ Data,
9
+ Deferred,
10
+ Effect,
11
+ Fiber,
12
+ HashMap,
13
+ Option,
14
+ Queue,
15
+ Record,
16
+ Result,
17
+ Schema,
18
+ type Scope,
19
+ Stream,
20
+ TxQueue,
21
+ TxRef,
22
+ } from "effect"
23
+ import {
24
+ RpcClient,
25
+ RpcClientError,
26
+ RpcSerialization,
27
+ RpcServer,
28
+ } from "effect/rpc"
29
+ import type { Rpc, RpcGroup, RpcMessage } from "effect/rpc"
30
+ import * as FailureGroup from "./FailureGroup"
31
+ import { TransportError } from "../Errors"
32
+ import { defaults, type Limits } from "./Limits"
33
+ export type Priority = keyof Limits
34
+
35
+ export const Priority = Context.Reference<Priority>(
36
+ "@graftland/plugin-remote/internal/port/Priority",
37
+ { defaultValue: () => "data" },
38
+ )
39
+ type Endpoint = Pick<RpcGroup.RpcGroup<Rpc.Any>, "requests">
40
+
41
+ export interface Options {
42
+ readonly session: string
43
+ readonly serve: Readonly<Record<string, Endpoint>>
44
+ readonly call: Readonly<Record<string, Endpoint>>
45
+ /** Limits are shared across endpoints, separately for each direction.
46
+ * Each peer's inbound limits must accommodate the other's outbound limits. */
47
+ readonly limits?: Partial<Record<Priority, number>>
48
+ }
49
+ export interface Port {
50
+ readonly clientProtocol: (endpoint: string) => RpcClient.Protocol["Service"]
51
+ readonly serverProtocol: (endpoint: string) => RpcServer.Protocol["Service"]
52
+ readonly await: Effect.Effect<never, TransportError>
53
+ readonly fail: (error: TransportError) => Effect.Effect<void>
54
+ readonly end: Effect.Effect<void, TransportError>
55
+ }
56
+ class RequestKey extends Data.Class<{
57
+ readonly endpoint: string
58
+ readonly id: string | number
59
+ }> {}
60
+ interface RequestState<A> {
61
+ readonly queue: Queue.Queue<A, Cause.Done>
62
+ readonly priority: Priority
63
+ readonly sent: boolean
64
+ }
65
+ const Frame = Schema.Struct({
66
+ session: Schema.String,
67
+ endpoint: Schema.String,
68
+ direction: Schema.Literals(["request", "response"]),
69
+ priority: Schema.Literals(["control", "data", "log"]),
70
+ message: Schema.Unknown,
71
+ })
72
+ type Frame = typeof Frame.Type
73
+ interface Pending {
74
+ readonly frame: Frame
75
+ readonly request: Option.Option<RequestKey>
76
+ }
77
+ const Id = Schema.Union([Schema.String, Schema.Finite])
78
+ // Only routing fields belong to this transport. The RPC serialization codec
79
+ // validates payloads, chunks and exits before handlers or callers see them. These
80
+ // protocol callbacks are an opaque handoff, not validation of a complete RpcMessage.
81
+ // EncodedSchema requires binary payloads
82
+ // in Effect 4.1.2 and cannot describe these JSON codec messages.
83
+ const isRequest = Schema.is(
84
+ Schema.Union([
85
+ Schema.TaggedStruct("Request", { id: Id, tag: Schema.String }),
86
+ Schema.TaggedStruct("Ack", { requestId: Id }),
87
+ Schema.TaggedStruct("Interrupt", { requestId: Id }),
88
+ Schema.TaggedStruct("Eof", {}),
89
+ ]),
90
+ )
91
+ const isResponse = Schema.is(
92
+ Schema.Union([
93
+ Schema.TaggedStruct("Exit", { requestId: Id }),
94
+ Schema.TaggedStruct("Chunk", { requestId: Id }),
95
+ Schema.TaggedStruct("Defect", { defect: Schema.Unknown }),
96
+ ]),
97
+ )
98
+ const Request = Schema.declare<
99
+ Exclude<RpcMessage.FromClientEncoded, RpcMessage.Ping>
100
+ >((input): input is Exclude<RpcMessage.FromClientEncoded, RpcMessage.Ping> =>
101
+ isRequest(input),
102
+ )
103
+ const Response = Schema.declare<
104
+ Exclude<
105
+ RpcMessage.FromServerEncoded,
106
+ RpcMessage.Pong | RpcMessage.ClientProtocolError | RpcMessage.RequestEncoded
107
+ >
108
+ >(
109
+ (
110
+ input,
111
+ ): input is Exclude<
112
+ RpcMessage.FromServerEncoded,
113
+ RpcMessage.Pong | RpcMessage.ClientProtocolError | RpcMessage.RequestEncoded
114
+ > => isResponse(input),
115
+ )
116
+ const error = (message: string) =>
117
+ TransportError.make({ cause: Cause.die(new Error(message)) })
118
+ const rpcError = (cause: Cause.Cause<TransportError>) =>
119
+ RpcClientError.RpcClientError.make({
120
+ reason: RpcClientError.RpcClientDefect.make({
121
+ message: "Remote connection failed",
122
+ cause,
123
+ }),
124
+ })
125
+ const priority = (group: Endpoint, tag: string): Priority => {
126
+ const rpc = group.requests.get(tag)
127
+ return rpc === undefined ? "data" : Context.get(rpc.annotations, Priority)
128
+ }
129
+ const mailbox = <A>(priority: Priority) =>
130
+ Queue.dropping<A, Cause.Done>(2).pipe(
131
+ Effect.map((queue): RequestState<A> => ({ queue, priority, sent: false })),
132
+ )
133
+ const deliver = Effect.fnUntraced(function* <A>(
134
+ requestState: RequestState<A>,
135
+ message: A,
136
+ ) {
137
+ // One unacknowledged chunk and its terminal Exit may coexist.
138
+ if (!(yield* Queue.offer(requestState.queue, message)))
139
+ return yield* error("RPC request mailbox overflow")
140
+ })
141
+
142
+ type ServerEndpoint = {
143
+ readonly group: Endpoint
144
+ readonly ready: Deferred.Deferred<
145
+ Parameters<RpcServer.Protocol["Service"]["run"]>[0]
146
+ >
147
+ readonly disconnects: Queue.Queue<number>
148
+ }
149
+ type ClientEndpoint = {
150
+ readonly group: Endpoint
151
+ readonly ready: Deferred.Deferred<
152
+ Parameters<RpcClient.Protocol["Service"]["run"]>[1]
153
+ >
154
+ }
155
+ interface State {
156
+ readonly bytes: Channel
157
+ readonly options: Options
158
+ readonly limits: Record<Priority, number>
159
+ readonly workers: FailureGroup.FailureGroup<TransportError>
160
+ readonly incoming: TxRef.TxRef<
161
+ HashMap.HashMap<RequestKey, RequestState<RpcMessage.FromClientEncoded>>
162
+ >
163
+ readonly outgoing: TxRef.TxRef<
164
+ HashMap.HashMap<RequestKey, RequestState<RpcMessage.FromServerEncoded>>
165
+ >
166
+ readonly queues: Record<Priority, TxQueue.TxQueue<Pending, Cause.Done>>
167
+ readonly servers: HashMap.HashMap<string, ServerEndpoint>
168
+ readonly clients: HashMap.HashMap<string, ClientEndpoint>
169
+ }
170
+ const initialize = (bytes: Channel, options: Options) =>
171
+ Effect.gen(function* (): Effect.gen.Return<State, never, Scope.Scope> {
172
+ const limits = { ...defaults, ...options.limits }
173
+ const workers = yield* FailureGroup.make<TransportError>()
174
+ const incoming = yield* TxRef.make(
175
+ HashMap.empty<RequestKey, RequestState<RpcMessage.FromClientEncoded>>(),
176
+ )
177
+ const outgoing = yield* TxRef.make(
178
+ HashMap.empty<RequestKey, RequestState<RpcMessage.FromServerEncoded>>(),
179
+ )
180
+ const queues = {
181
+ control: yield* TxQueue.unbounded<Pending, Cause.Done>(),
182
+ data: yield* TxQueue.unbounded<Pending, Cause.Done>(),
183
+ log: yield* TxQueue.unbounded<Pending, Cause.Done>(),
184
+ }
185
+ const servers = yield* Effect.forEach(
186
+ Record.toEntries(options.serve),
187
+ Effect.fnUntraced(function* ([name, group]) {
188
+ return [
189
+ name,
190
+ {
191
+ group,
192
+ ready:
193
+ yield* Deferred.make<
194
+ Parameters<RpcServer.Protocol["Service"]["run"]>[0]
195
+ >(),
196
+ disconnects: yield* Queue.dropping<number>(1),
197
+ },
198
+ ] satisfies readonly [string, unknown]
199
+ }),
200
+ ).pipe(Effect.map(HashMap.fromIterable))
201
+ const clients = yield* Effect.forEach(
202
+ Record.toEntries(options.call),
203
+ Effect.fnUntraced(function* ([name, group]) {
204
+ return [
205
+ name,
206
+ {
207
+ group,
208
+ ready:
209
+ yield* Deferred.make<
210
+ Parameters<RpcClient.Protocol["Service"]["run"]>[1]
211
+ >(),
212
+ },
213
+ ] satisfies readonly [string, unknown]
214
+ }),
215
+ ).pipe(Effect.map(HashMap.fromIterable))
216
+ return {
217
+ bytes,
218
+ options,
219
+ limits,
220
+ workers,
221
+ incoming,
222
+ outgoing,
223
+ queues,
224
+ servers,
225
+ clients,
226
+ }
227
+ })
228
+
229
+ const admit = Effect.fnUntraced(function* <A>(
230
+ state: State,
231
+ table: TxRef.TxRef<HashMap.HashMap<RequestKey, RequestState<A>>>,
232
+ key: RequestKey,
233
+ requestState: RequestState<A>,
234
+ direction: "incoming" | "outgoing",
235
+ ) {
236
+ yield* Effect.tx(
237
+ Effect.gen(function* () {
238
+ yield* state.workers.check
239
+ const current = yield* TxRef.get(table)
240
+ const count = Array.filter(
241
+ Array.fromIterable(HashMap.values(current)),
242
+ (entry) => entry.priority === requestState.priority,
243
+ ).length
244
+ if (count >= state.limits[requestState.priority]) {
245
+ if (direction === "outgoing") return yield* Effect.txRetry
246
+ return yield* error(
247
+ `RPC admission limit exceeded for ${requestState.priority}`,
248
+ )
249
+ }
250
+ yield* TxRef.set(table, HashMap.set(current, key, requestState))
251
+ }),
252
+ )
253
+ })
254
+ const remove = Effect.fnUntraced(function* <A>(
255
+ table: TxRef.TxRef<HashMap.HashMap<RequestKey, RequestState<A>>>,
256
+ key: RequestKey,
257
+ requestState: RequestState<A>,
258
+ ) {
259
+ yield* TxRef.update(table, HashMap.remove(key))
260
+ yield* Queue.end(requestState.queue)
261
+ })
262
+ const enqueue = (
263
+ state: State,
264
+ frame: Frame,
265
+ request: Option.Option<RequestKey> = Option.none(),
266
+ ) =>
267
+ Effect.tx(
268
+ state.workers.check.pipe(
269
+ Effect.andThen(
270
+ TxQueue.offer(state.queues[frame.priority], { frame, request }).pipe(
271
+ Effect.flatMap((accepted) =>
272
+ accepted ? Effect.void : error("Remote output has ended"),
273
+ ),
274
+ ),
275
+ ),
276
+ Effect.asVoid,
277
+ ),
278
+ )
279
+ const frame = (
280
+ state: State,
281
+ endpoint: string,
282
+ direction: Frame["direction"],
283
+ p: Priority,
284
+ message: unknown,
285
+ ): Frame => ({
286
+ session: state.options.session,
287
+ endpoint,
288
+ direction,
289
+ priority: p,
290
+ message,
291
+ })
292
+ // Protocol sends are owned too: interrupting a caller cancels admission or enqueue.
293
+ const send = Effect.fnUntraced(function* (
294
+ state: State,
295
+ effect: Effect.Effect<void, TransportError>,
296
+ ) {
297
+ const fiber = yield* state.workers.run(
298
+ state.workers.check.pipe(Effect.andThen(effect)),
299
+ )
300
+ const result = yield* Fiber.await(fiber).pipe(
301
+ Effect.onInterrupt(() => Fiber.interrupt(fiber)),
302
+ )
303
+ // Group teardown interrupts this worker; callers still receive the connection cause.
304
+ yield* state.workers.check
305
+ yield* result
306
+ })
307
+ const cancel = Effect.fnUntraced(function* (state: State, key: RequestKey) {
308
+ const canceled = yield* Effect.tx(
309
+ Effect.gen(function* () {
310
+ const table = yield* TxRef.get(state.outgoing)
311
+ const requestState = HashMap.get(table, key)
312
+ if (Option.isNone(requestState))
313
+ return Option.none<RequestState<RpcMessage.FromServerEncoded>>()
314
+ if (requestState.value.sent) {
315
+ yield* enqueue(
316
+ state,
317
+ frame(state, key.endpoint, "request", "control", {
318
+ _tag: "Interrupt",
319
+ requestId: key.id,
320
+ }),
321
+ )
322
+ return Option.none<RequestState<RpcMessage.FromServerEncoded>>()
323
+ }
324
+ yield* TxRef.set(state.outgoing, HashMap.remove(table, key))
325
+ return requestState
326
+ }),
327
+ )
328
+ if (Option.isSome(canceled)) yield* Queue.end(canceled.value.queue)
329
+ })
330
+ const clientProtocol = (
331
+ state: State,
332
+ endpoint: string,
333
+ ): RpcClient.Protocol["Service"] => {
334
+ // Accessors accept endpoints declared when the port was created.
335
+ const client = Option.getOrThrow(HashMap.get(state.clients, endpoint))
336
+ return RpcClient.Protocol.of({
337
+ codecFor: RpcSerialization.json.codecFor,
338
+ supportsAck: true,
339
+ supportsTransferables: false,
340
+ run: (_id, receive) =>
341
+ Deferred.succeed(client.ready, receive).pipe(
342
+ Effect.andThen(state.workers.await),
343
+ Effect.catchCause((cause) =>
344
+ receive({ _tag: "ClientProtocolError", error: rpcError(cause) }),
345
+ ),
346
+ Effect.andThen(Effect.never),
347
+ ),
348
+ send: (_id, message) =>
349
+ send(
350
+ state,
351
+ Effect.gen(function* () {
352
+ if (message._tag === "Request") {
353
+ if (message.discard === true || message.isNotification === true)
354
+ return yield* error(
355
+ "Discard and notification requests are not supported",
356
+ )
357
+ const key = new RequestKey({ endpoint, id: message.id })
358
+ const requestState = yield* mailbox<RpcMessage.FromServerEncoded>(
359
+ priority(client.group, message.tag),
360
+ )
361
+ yield* admit(state, state.outgoing, key, requestState, "outgoing")
362
+ yield* state.workers.run(
363
+ Stream.fromQueue(requestState.queue).pipe(
364
+ Stream.runForEach(
365
+ Effect.fnUntraced(function* (response) {
366
+ const receive = yield* Deferred.await(client.ready)
367
+ if (response._tag === "Exit")
368
+ yield* remove(state.outgoing, key, requestState)
369
+ yield* receive(response)
370
+ }),
371
+ ),
372
+ ),
373
+ )
374
+ yield* enqueue(
375
+ state,
376
+ frame(state, endpoint, "request", requestState.priority, message),
377
+ Option.some(key),
378
+ )
379
+ } else if (message._tag === "Interrupt") {
380
+ yield* cancel(
381
+ state,
382
+ new RequestKey({ endpoint, id: message.requestId }),
383
+ )
384
+ } else if (message._tag === "Ack") {
385
+ yield* enqueue(
386
+ state,
387
+ frame(state, endpoint, "request", "control", message),
388
+ )
389
+ }
390
+ }),
391
+ ).pipe(Effect.mapError((failure) => rpcError(Cause.fail(failure)))),
392
+ })
393
+ }
394
+ const serverProtocol = (
395
+ state: State,
396
+ endpoint: string,
397
+ ): RpcServer.Protocol["Service"] => {
398
+ // Accessors accept endpoints declared when the port was created.
399
+ const server = Option.getOrThrow(HashMap.get(state.servers, endpoint))
400
+ return RpcServer.Protocol.of({
401
+ codecFor: RpcSerialization.json.codecFor,
402
+ supportsAck: true,
403
+ supportsTransferables: false,
404
+ supportsSpanPropagation: false,
405
+ supportsNotifications: false,
406
+ clientIds: Effect.succeed(new Set([0])),
407
+ initialMessage: Effect.succeedNone,
408
+ disconnects: server.disconnects,
409
+ end: () => Effect.void,
410
+ run: (receive) =>
411
+ Deferred.succeed(server.ready, receive).pipe(
412
+ Effect.andThen(Effect.never),
413
+ ),
414
+ send: (_id, message) =>
415
+ send(
416
+ state,
417
+ Effect.gen(function* () {
418
+ if (message._tag === "Chunk" || message._tag === "Exit") {
419
+ const key = new RequestKey({ endpoint, id: message.requestId })
420
+ const requestState = yield* TxRef.get(state.incoming).pipe(
421
+ Effect.map(HashMap.get(key)),
422
+ )
423
+ if (Option.isNone(requestState)) return
424
+ yield* enqueue(
425
+ state,
426
+ frame(
427
+ state,
428
+ endpoint,
429
+ "response",
430
+ message._tag === "Exit"
431
+ ? "control"
432
+ : requestState.value.priority,
433
+ message,
434
+ ),
435
+ )
436
+ if (message._tag === "Exit")
437
+ yield* remove(state.incoming, key, requestState.value)
438
+ } else
439
+ yield* enqueue(
440
+ state,
441
+ frame(state, endpoint, "response", "control", message),
442
+ )
443
+ }),
444
+ ).pipe(
445
+ // Disconnect already carries this cause to the server; late sends need no second failure.
446
+ Effect.catchTag("TransportError", () => Effect.void),
447
+ ),
448
+ })
449
+ }
450
+ const next = (state: State) =>
451
+ Effect.tx(
452
+ Effect.gen(function* () {
453
+ yield* state.workers.check
454
+ for (const p of [
455
+ "control",
456
+ "data",
457
+ "log",
458
+ ] satisfies ReadonlyArray<Priority>) {
459
+ const pending = yield* TxQueue.poll(state.queues[p])
460
+ if (Option.isNone(pending)) continue
461
+ const { frame, request } = pending.value
462
+ if (Option.isSome(request)) {
463
+ const table = yield* TxRef.get(state.outgoing)
464
+ const requestState = HashMap.get(table, request.value)
465
+ if (Option.isNone(requestState)) return Option.none<Frame>()
466
+ yield* TxRef.set(
467
+ state.outgoing,
468
+ HashMap.set(table, request.value, {
469
+ ...requestState.value,
470
+ sent: true,
471
+ }),
472
+ )
473
+ }
474
+ return Option.some(frame)
475
+ }
476
+ if (
477
+ (yield* TxQueue.isDone(state.queues.control)) &&
478
+ (yield* TxQueue.isDone(state.queues.data)) &&
479
+ (yield* TxQueue.isDone(state.queues.log))
480
+ )
481
+ return yield* Cause.done()
482
+ return yield* Effect.txRetry
483
+ }),
484
+ )
485
+ const writer = (state: State) =>
486
+ Stream.fromEffectRepeat(next(state)).pipe(
487
+ Stream.filterMap(Result.fromOption(() => undefined)),
488
+ Stream.mapEffect((frame) =>
489
+ Schema.encodeEffect(Schema.fromJsonString(Frame))(frame).pipe(
490
+ Effect.mapError((cause) =>
491
+ TransportError.make({ cause: Cause.fail(cause) }),
492
+ ),
493
+ ),
494
+ ),
495
+ Stream.map((json) => new TextEncoder().encode(json + "\n")),
496
+ Stream.run(state.bytes.output),
497
+ )
498
+ const read = Effect.fnUntraced(function* (state: State, raw: unknown) {
499
+ const current = yield* Schema.decodeUnknownEffect(Frame)(raw).pipe(
500
+ Effect.mapError((cause) =>
501
+ TransportError.make({ cause: Cause.fail(cause) }),
502
+ ),
503
+ )
504
+ if (current.session !== state.options.session) return
505
+ if (current.direction === "request") {
506
+ const server = HashMap.get(state.servers, current.endpoint)
507
+ if (Option.isNone(server))
508
+ return yield* error(`Unknown RPC server endpoint: ${current.endpoint}`)
509
+ const message = yield* Schema.decodeUnknownEffect(Request)(
510
+ current.message,
511
+ ).pipe(
512
+ Effect.mapError((cause) =>
513
+ TransportError.make({ cause: Cause.fail(cause) }),
514
+ ),
515
+ )
516
+ if (message._tag === "Eof")
517
+ return yield* TransportError.make({
518
+ cause: Cause.fail(EndOfStream.make({})),
519
+ })
520
+ const key = new RequestKey({
521
+ endpoint: current.endpoint,
522
+ id: message._tag === "Request" ? message.id : message.requestId,
523
+ })
524
+ if (message._tag === "Request") {
525
+ const p = priority(server.value.group, message.tag)
526
+ const requestState = yield* mailbox<RpcMessage.FromClientEncoded>(p)
527
+ yield* admit(state, state.incoming, key, requestState, "incoming")
528
+ yield* state.workers.run(
529
+ Stream.fromQueue(requestState.queue).pipe(
530
+ Stream.runForEach(
531
+ Effect.fnUntraced(function* (request) {
532
+ const receive = yield* Deferred.await(server.value.ready)
533
+ yield* receive(0, request)
534
+ }),
535
+ ),
536
+ ),
537
+ )
538
+ yield* deliver(requestState, message)
539
+ } else {
540
+ const requestState = yield* TxRef.get(state.incoming).pipe(
541
+ Effect.map(HashMap.get(key)),
542
+ )
543
+ if (Option.isSome(requestState))
544
+ yield* deliver(requestState.value, message)
545
+ }
546
+ } else {
547
+ const message = yield* Schema.decodeUnknownEffect(Response)(
548
+ current.message,
549
+ ).pipe(
550
+ Effect.mapError((cause) =>
551
+ TransportError.make({ cause: Cause.fail(cause) }),
552
+ ),
553
+ )
554
+ if (message._tag === "Defect")
555
+ return yield* TransportError.make({ cause: Cause.die(message.defect) })
556
+ const key = new RequestKey({
557
+ endpoint: current.endpoint,
558
+ id: message.requestId,
559
+ })
560
+ const requestState = yield* TxRef.get(state.outgoing).pipe(
561
+ Effect.map(HashMap.get(key)),
562
+ )
563
+ if (Option.isSome(requestState)) yield* deliver(requestState.value, message)
564
+ }
565
+ })
566
+ const reader = (state: State) =>
567
+ state.bytes.input.pipe(
568
+ Stream.decodeText(),
569
+ Stream.splitLines,
570
+ Stream.filter((line) => line.length > 0),
571
+ Stream.mapEffect((line) =>
572
+ Schema.decodeEffect(Schema.fromJsonString(Schema.Unknown))(line).pipe(
573
+ Effect.mapError((cause) =>
574
+ TransportError.make({ cause: Cause.fail(cause) }),
575
+ ),
576
+ ),
577
+ ),
578
+ Stream.runForEach((raw) => read(state, raw)),
579
+ Effect.andThen(
580
+ Effect.fail(
581
+ TransportError.make({ cause: Cause.fail(EndOfStream.make({})) }),
582
+ ),
583
+ ),
584
+ )
585
+
586
+ /** One RPC client/server per declared endpoint; servers may start after the port. */
587
+ export const make = Effect.fnUntraced(function* (
588
+ bytes: Channel,
589
+ options: Options,
590
+ ): Effect.fn.Return<Port, never, import("effect").Scope.Scope> {
591
+ const state = yield* initialize(bytes, options)
592
+ // The same failure remains observable through Port.await and client requests.
593
+ // This observer only publishes disconnects, even while the owner closes its scope.
594
+ yield* state.workers.await.pipe(
595
+ Effect.catchCause(() =>
596
+ Effect.uninterruptible(
597
+ Effect.gen(function* () {
598
+ for (const server of HashMap.values(state.servers))
599
+ yield* Queue.offer(server.disconnects, 0)
600
+ yield* Effect.tx(
601
+ TxRef.set(state.incoming, HashMap.empty()).pipe(
602
+ Effect.andThen(TxRef.set(state.outgoing, HashMap.empty())),
603
+ ),
604
+ )
605
+ }),
606
+ ),
607
+ ),
608
+ Effect.forkScoped,
609
+ )
610
+ const writing = yield* state.workers.run(writer(state))
611
+ yield* state.workers.run(reader(state))
612
+ return {
613
+ clientProtocol: (endpoint) => clientProtocol(state, endpoint),
614
+ serverProtocol: (endpoint) => serverProtocol(state, endpoint),
615
+ await: state.workers.await,
616
+ fail: state.workers.fail,
617
+ end: Effect.tx(
618
+ Effect.forEach(Record.values(state.queues), TxQueue.end, {
619
+ discard: true,
620
+ }),
621
+ ).pipe(Effect.andThen(Fiber.join(writing))),
622
+ }
623
+ })
@@ -0,0 +1,71 @@
1
+ import { Array, Cause, Effect, Exit, Result, Schema, Scope } from "effect"
2
+
3
+ /** Resource release was interrupted, rather than successfully cancelled. */
4
+ export class ReleaseInterrupted extends Schema.TaggedError<
5
+ ReleaseInterrupted,
6
+ { readonly brand: unique symbol }
7
+ >()("ReleaseInterrupted", {
8
+ cause: Schema.Cause(Schema.Never, Schema.Unknown),
9
+ }) {
10
+ override get message() {
11
+ return "Resource release was interrupted"
12
+ }
13
+ }
14
+
15
+ /** Keep a known release failure distinguishable from cancellation through enclosing scopes. */
16
+ export const close = (
17
+ scope: Scope.Closeable,
18
+ exit: Exit.Exit<unknown, unknown>,
19
+ ) =>
20
+ Effect.uninterruptible(
21
+ Scope.close(scope, exit).pipe(
22
+ Effect.catchCauseIf(Cause.hasInterruptsOnly, (cause) =>
23
+ Effect.gen(function* () {
24
+ // Re-entering interruptibility observes pending external cancellation without producing a self-interrupt.
25
+ // Read it after release so cancellation arriving during a finalizer is included too.
26
+ const pending = yield* Effect.exit(Effect.interruptible(Effect.void))
27
+ const [cancelled, interrupted] = Array.partition(
28
+ cause.reasons,
29
+ (reason) =>
30
+ Exit.isFailure(pending) &&
31
+ Array.some(
32
+ pending.cause.reasons,
33
+ (external) =>
34
+ reason._tag === "Interrupt" &&
35
+ external._tag === "Interrupt" &&
36
+ reason.fiberId === external.fiberId,
37
+ )
38
+ ? Result.succeed(reason)
39
+ : Result.fail(reason),
40
+ )
41
+ if (interrupted.length === 0) return yield* Effect.failCause(cause)
42
+ return yield* Effect.failCause(
43
+ Cause.combine(
44
+ Cause.fromReasons(cancelled),
45
+ Cause.die(
46
+ ReleaseInterrupted.make({
47
+ cause: Cause.fromReasons(interrupted),
48
+ }),
49
+ ),
50
+ ),
51
+ )
52
+ }),
53
+ ),
54
+ ),
55
+ )
56
+
57
+ export const scoped = <A, E, R>(effect: Effect.Effect<A, E, R>) =>
58
+ Effect.uninterruptibleMask((restore) =>
59
+ Effect.gen(function* () {
60
+ const scope = yield* Scope.make()
61
+ const body = yield* Effect.exit(restore(Scope.provide(scope)(effect)))
62
+ const closed = yield* Effect.exit(close(scope, body))
63
+ if (Exit.isFailure(closed))
64
+ return yield* Effect.failCause(
65
+ Exit.isFailure(body)
66
+ ? Cause.combine(body.cause, closed.cause)
67
+ : closed.cause,
68
+ )
69
+ return yield* body
70
+ }),
71
+ )
@@ -0,0 +1,9 @@
1
+ import { Schema } from "effect"
2
+ import { Identity } from "../../Instance"
3
+ import { Limits } from "./model"
4
+
5
+ export const Bootstrap = Schema.Struct({
6
+ identity: Identity,
7
+ limits: Limits,
8
+ })
9
+ export type Bootstrap = typeof Bootstrap.Type