@graftland/plugin-remote 0.0.0-stage → 0.2.0-beta.2

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,323 @@
1
+ import { loadModule } from "./loadModule"
2
+ import { AlreadyLoaded, ActivationFailed } from "./childErrors"
3
+ import { Graft, Plugin, type Fork } from "@graftland/graft"
4
+ import {
5
+ Array,
6
+ Cause,
7
+ Data,
8
+ Deferred,
9
+ Effect,
10
+ Exit,
11
+ Fiber,
12
+ Logger,
13
+ MutableRef,
14
+ Option,
15
+ Queue,
16
+ Ref,
17
+ References,
18
+ Scope,
19
+ Stream,
20
+ SynchronizedRef,
21
+ } from "effect"
22
+ import type { Schema } from "effect"
23
+ import { type RunnerContract } from "../Contract"
24
+ import { Instance, type Identity } from "../Instance"
25
+ import type * as Port from "./port"
26
+ import type { Event, Log, LogEvent } from "./control"
27
+
28
+ type Peer = Port.Port
29
+ type ChildEvent = Data.TaggedEnum<{
30
+ Failed: { readonly cause: Cause.Cause<unknown> }
31
+ Withdrawing: {}
32
+ Stopped: {}
33
+ }>
34
+ const ChildEvent = Data.taggedEnum<ChildEvent>()
35
+ type LogEntry = Omit<typeof Log.Type, "cause"> & {
36
+ readonly cause: Cause.Cause<unknown>
37
+ }
38
+
39
+ /** Queue data; serialization belongs to the RPC consumer, outside synchronous logger callbacks. */
40
+ export const telemetry = (contract: RunnerContract) =>
41
+ Effect.gen(function* () {
42
+ const events = yield* Queue.bounded<ChildEvent>(2)
43
+ const logs = yield* Queue.dropping<LogEntry, Cause.Done>(128)
44
+ const dropped = MutableRef.make(0)
45
+ const encode = (cause: Cause.Cause<unknown>) =>
46
+ contract.encodeCause(cause).pipe(Effect.orDie)
47
+ const logger = Logger.make((entry) => {
48
+ // Logger callbacks are synchronous; a dropping offer and loss counter cannot suspend.
49
+ const accepted = Queue.offerUnsafe(logs, {
50
+ level: entry.logLevel,
51
+ message: entry.message,
52
+ cause: entry.cause,
53
+ annotations: entry.fiber.getRef(References.CurrentLogAnnotations),
54
+ })
55
+ if (!accepted) MutableRef.increment(dropped)
56
+ })
57
+ return {
58
+ events,
59
+ logs,
60
+ logger,
61
+ eventStream: Stream.fromQueue(events).pipe(
62
+ Stream.mapEffect((event): Effect.Effect<typeof Event.Type> =>
63
+ event._tag === "Failed"
64
+ ? encode(event.cause).pipe(
65
+ Effect.map(
66
+ (cause) =>
67
+ ({
68
+ _tag: "Failed",
69
+ cause,
70
+ }) satisfies typeof Event.Type,
71
+ ),
72
+ )
73
+ : Effect.succeed(event),
74
+ ),
75
+ ),
76
+ logStream: Stream.fromQueue(logs).pipe(
77
+ Stream.mapEffect((entry) =>
78
+ encode(entry.cause).pipe(
79
+ Effect.map((cause): typeof LogEvent.Type => ({
80
+ _tag: "Log",
81
+ entry: { ...entry, cause },
82
+ dropped: MutableRef.get(dropped),
83
+ })),
84
+ ),
85
+ ),
86
+ Stream.concat(
87
+ Stream.sync((): typeof LogEvent.Type => ({
88
+ _tag: "LogsEnded",
89
+ dropped: MutableRef.get(dropped),
90
+ })),
91
+ ),
92
+ ),
93
+ }
94
+ })
95
+ type Telemetry = Effect.Success<ReturnType<typeof telemetry>>
96
+ interface Running {
97
+ readonly fork: Pick<Fork.Fork<never, unknown>, "dispose" | "state">
98
+ readonly bridge: Pick<Fork.Fork<never, never>, "dispose" | "state">
99
+ readonly observation: Fiber.Fiber<void>
100
+ readonly observedFailure: Ref.Ref<Cause.Cause<unknown>>
101
+ }
102
+ type Lifecycle = Data.TaggedEnum<{
103
+ Idle: {}
104
+ Loading: {}
105
+ Running: { readonly running: Running }
106
+ Withdrawing: { readonly running: Option.Option<Running> }
107
+ Disposing: { readonly running: Option.Option<Running> }
108
+ }>
109
+ const Lifecycle = Data.taggedEnum<Lifecycle>()
110
+ const runningOf = (state: Lifecycle): Option.Option<Running> =>
111
+ state._tag === "Running"
112
+ ? Option.some(state.running)
113
+ : state._tag === "Withdrawing" || state._tag === "Disposing"
114
+ ? state.running
115
+ : Option.none()
116
+
117
+ const cleanup = (running: Running, retired: boolean) =>
118
+ Effect.gen(function* () {
119
+ const pluginExit = yield* Effect.exit(running.fork.dispose)
120
+ const bridgeExit = yield* Effect.exit(running.bridge.dispose)
121
+ yield* Fiber.join(running.observation)
122
+ const failed = yield* Ref.get(running.observedFailure)
123
+ return Array.reduce(
124
+ [bridgeExit, pluginExit],
125
+ retired ? failed : Cause.empty,
126
+ (cause, exit) =>
127
+ Exit.isFailure(exit)
128
+ ? Cause.combine(
129
+ cause,
130
+ Cause.fromReasons(
131
+ Array.flatMap(exit.cause.reasons, (reason) =>
132
+ reason._tag === "Fail"
133
+ ? reason.error.cause.reasons
134
+ : [reason],
135
+ ),
136
+ ),
137
+ )
138
+ : cause,
139
+ )
140
+ })
141
+
142
+ export const lifecycle = (
143
+ contract: RunnerContract,
144
+ peer: Peer,
145
+ identity: typeof Identity.Type,
146
+ telemetry: Telemetry,
147
+ ) =>
148
+ Effect.gen(function* () {
149
+ const scope = yield* Effect.scope
150
+ const instanceScope = yield* Scope.fork(scope)
151
+ const releaseExports = yield* Deferred.make<void>()
152
+ const state = yield* SynchronizedRef.make<Lifecycle>(Lifecycle.Idle())
153
+ // This gate represents host consumers draining, not a second lifecycle state.
154
+ const release = SynchronizedRef.update(state, (current) =>
155
+ Lifecycle.Disposing({ running: runningOf(current) }),
156
+ ).pipe(Effect.andThen(Deferred.succeed(releaseExports, undefined)))
157
+
158
+ const exportBridge = Graft.plugin(
159
+ Plugin.make({
160
+ name: `${contract.name}/exports`,
161
+ inject: Array.map(contract.provides, (service) => service.key),
162
+ apply: () =>
163
+ Effect.gen(function* () {
164
+ for (const service of contract.provides)
165
+ yield* service.serve(peer).pipe(
166
+ Effect.tapCause((cause) =>
167
+ Cause.hasInterruptsOnly(cause)
168
+ ? Effect.void
169
+ : Queue.offer(
170
+ telemetry.events,
171
+ ChildEvent.Failed({ cause }),
172
+ ),
173
+ ),
174
+ Effect.forkScoped,
175
+ )
176
+ yield* Effect.addFinalizer(() =>
177
+ Effect.gen(function* () {
178
+ const withdrawing = yield* SynchronizedRef.modify(
179
+ state,
180
+ (current) =>
181
+ current._tag === "Disposing"
182
+ ? [false, current]
183
+ : [
184
+ true,
185
+ Lifecycle.Withdrawing({
186
+ running: runningOf(current),
187
+ }),
188
+ ],
189
+ )
190
+ if (withdrawing)
191
+ yield* Queue.offer(telemetry.events, ChildEvent.Withdrawing())
192
+ yield* Deferred.await(releaseExports)
193
+ }),
194
+ )
195
+ }),
196
+ }),
197
+ ).pipe(Scope.provide(instanceScope))
198
+
199
+ const start = (input: Schema.Json) =>
200
+ Effect.gen(function* () {
201
+ // Imported clients outlive Load and remain available during plugin cleanup.
202
+ for (const service of contract.inject)
203
+ yield* service.publish(peer).pipe(
204
+ Scope.provide(scope),
205
+ Effect.mapError((error) =>
206
+ ActivationFailed.make({
207
+ detail: "Publishing imported services failed",
208
+ cause: Cause.fail(error),
209
+ }),
210
+ ),
211
+ )
212
+ const module = yield* loadModule(contract.module)
213
+ const plugin = Plugin.fromModule(module)
214
+ if (Option.isNone(plugin))
215
+ return yield* ActivationFailed.make({
216
+ detail: "The implementation module exports no plugin",
217
+ })
218
+ const fork = yield* Graft.plugin(
219
+ { ...plugin.value, retry: undefined },
220
+ input,
221
+ ).pipe(
222
+ Effect.provideService(Instance, identity),
223
+ Scope.provide(instanceScope),
224
+ )
225
+ const observedFailure = yield* Ref.make<Cause.Cause<unknown>>(
226
+ Cause.empty,
227
+ )
228
+ const observation = yield* fork.state.pipe(
229
+ Stream.runForEach((state) =>
230
+ state._tag === "Failed"
231
+ ? Ref.set(observedFailure, state.cause)
232
+ : Effect.void,
233
+ ),
234
+ Effect.forkIn(instanceScope),
235
+ )
236
+ const bridge = yield* exportBridge
237
+ return { fork, bridge, observedFailure, observation } satisfies Running
238
+ })
239
+ const awaitActive = (running: Running) =>
240
+ Effect.gen(function* () {
241
+ const first = yield* running.fork.state.pipe(
242
+ Stream.filter((state) => state._tag !== "Loading"),
243
+ Stream.runHead,
244
+ )
245
+ if (Option.isNone(first))
246
+ return yield* ActivationFailed.make({
247
+ detail: "The remote fork disappeared during startup",
248
+ })
249
+ if (first.value._tag === "Failed")
250
+ return yield* Effect.fail(contract.normalizeCause(first.value.cause))
251
+ if (first.value._tag !== "Active")
252
+ return yield* ActivationFailed.make({
253
+ detail:
254
+ "The remote plugin did not become active; check its declared dependencies",
255
+ })
256
+ yield* running.fork.state.pipe(
257
+ Stream.runForEach((state) =>
258
+ state._tag === "Failed"
259
+ ? Queue.offer(
260
+ telemetry.events,
261
+ ChildEvent.Failed({ cause: state.cause }),
262
+ )
263
+ : Effect.void,
264
+ ),
265
+ Effect.forkIn(instanceScope),
266
+ )
267
+ const exported = yield* running.bridge.state.pipe(
268
+ Stream.filter(
269
+ (state) =>
270
+ state._tag === "Active" ||
271
+ state._tag === "Failed" ||
272
+ state._tag === "Disposed",
273
+ ),
274
+ Stream.runHead,
275
+ )
276
+ if (Option.isSome(exported) && exported.value._tag === "Failed")
277
+ return yield* ActivationFailed.make({
278
+ detail: "The remote export bridge failed during startup",
279
+ cause: exported.value.cause,
280
+ })
281
+ if (Option.isNone(exported) || exported.value._tag !== "Active")
282
+ return yield* ActivationFailed.make({
283
+ detail: "The remote export bridge stopped during startup",
284
+ })
285
+ })
286
+ const load = (input: Schema.Json) =>
287
+ Effect.gen(function* () {
288
+ yield* SynchronizedRef.updateEffect(state, (current) =>
289
+ current._tag === "Idle"
290
+ ? Effect.succeed(Lifecycle.Loading())
291
+ : Effect.fail(AlreadyLoaded.make({})),
292
+ )
293
+ const running = yield* start(input)
294
+ yield* SynchronizedRef.update(state, (current) =>
295
+ current._tag === "Withdrawing"
296
+ ? Lifecycle.Withdrawing({ running: Option.some(running) })
297
+ : current._tag === "Disposing"
298
+ ? Lifecycle.Disposing({ running: Option.some(running) })
299
+ : Lifecycle.Running({ running }),
300
+ )
301
+ yield* awaitActive(running)
302
+ }).pipe(
303
+ Effect.mapError((error) =>
304
+ Cause.isCause(error)
305
+ ? error
306
+ : contract.normalizeCause(Cause.fail(error)),
307
+ ),
308
+ )
309
+ const dispose = Effect.gen(function* () {
310
+ const previous = yield* SynchronizedRef.get(state)
311
+ yield* release
312
+ const current = runningOf(previous)
313
+ const retired = previous._tag === "Withdrawing"
314
+ const cause = Option.isSome(current)
315
+ ? yield* cleanup(current.value, retired)
316
+ : Cause.empty
317
+ yield* Queue.offer(telemetry.events, ChildEvent.Stopped())
318
+ yield* Queue.end(telemetry.logs)
319
+ if (cause.reasons.length > 0)
320
+ return yield* Effect.fail(contract.normalizeCause(cause))
321
+ })
322
+ return { load, dispose, release }
323
+ })
@@ -0,0 +1,44 @@
1
+ import { Schema } from "effect"
2
+
3
+ export class AlreadyLoaded extends Schema.TaggedError<
4
+ AlreadyLoaded,
5
+ { readonly brand: unique symbol }
6
+ >()("AlreadyLoaded", {}) {}
7
+ export class ContractNotFound extends Schema.TaggedError<
8
+ ContractNotFound,
9
+ { readonly brand: unique symbol }
10
+ >()("ContractNotFound", { module: Schema.String }) {
11
+ override get message() {
12
+ return `No remote contract exported by ${this.module}`
13
+ }
14
+ }
15
+ export class ModuleImportFailed extends Schema.TaggedError<
16
+ ModuleImportFailed,
17
+ { readonly brand: unique symbol }
18
+ >()("ModuleImportFailed", {
19
+ module: Schema.String,
20
+ cause: Schema.Defect({ includeStack: true }),
21
+ }) {}
22
+ export class ActivationFailed extends Schema.TaggedError<
23
+ ActivationFailed,
24
+ { readonly brand: unique symbol }
25
+ >()("ActivationFailed", {
26
+ detail: Schema.String,
27
+ cause: Schema.optionalKey(
28
+ Schema.Cause(
29
+ Schema.Defect({ includeStack: true }),
30
+ Schema.Defect({ includeStack: true }),
31
+ ),
32
+ ),
33
+ }) {
34
+ override get message() {
35
+ return this.detail
36
+ }
37
+ }
38
+ export const ChildFailure = Schema.Union([
39
+ AlreadyLoaded,
40
+ ContractNotFound,
41
+ ModuleImportFailed,
42
+ ActivationFailed,
43
+ ])
44
+ export type ChildFailure = typeof ChildFailure.Type
@@ -0,0 +1,111 @@
1
+ import { loadModule } from "./loadModule"
2
+ import { ContractNotFound } from "./childErrors"
3
+ import type { Graft } from "@graftland/graft"
4
+ import { Effect, Logger, Option } from "effect"
5
+ import { RpcServer } from "effect/rpc"
6
+ import { fromModule, type RunnerContract } from "../Contract"
7
+ import * as Port from "./port"
8
+ import * as Services from "./services"
9
+ import * as Child from "./child"
10
+ import * as Multiplex from "./runner/Multiplex"
11
+ import * as Wire from "./runner/Wire"
12
+ import type { Bootstrap } from "./runner/Bootstrap"
13
+ import { ExecutionError } from "./runner/model"
14
+ import { closedNormally } from "./runner/connectionEnded"
15
+ import { endpoint } from "./control"
16
+
17
+ /** Import a contract in the runner installation; importing this module performs no I/O. */
18
+ export const load = (specifier: string) =>
19
+ Effect.gen(function* () {
20
+ const module = yield* loadModule(specifier)
21
+ const contract = fromModule(module)
22
+ if (Option.isNone(contract))
23
+ return yield* ContractNotFound.make({ module: specifier })
24
+ return contract.value
25
+ })
26
+
27
+ const connect = (
28
+ contract: RunnerContract,
29
+ channel: Port.Channel,
30
+ session: string,
31
+ bootstrap: Bootstrap | undefined,
32
+ ) =>
33
+ Effect.gen(function* () {
34
+ const mux =
35
+ bootstrap === undefined ? undefined : yield* Multiplex.make(channel)
36
+ return yield* Port.make(
37
+ mux === undefined ? channel : Wire.channel(mux, 1),
38
+ {
39
+ session,
40
+ serve: {
41
+ ...Services.endpoints(contract.provides),
42
+ [endpoint]: contract.control,
43
+ },
44
+ call: Services.endpoints(contract.inject),
45
+ ...(bootstrap === undefined ? {} : { limits: bootstrap.limits }),
46
+ },
47
+ )
48
+ })
49
+
50
+ /** One execution unit; the executable supplies the platform and Graft services. */
51
+ export const run = (
52
+ contract: RunnerContract,
53
+ channel: Port.Channel,
54
+ session = "local",
55
+ bootstrap?: Bootstrap,
56
+ stop: Effect.Effect<unknown, ExecutionError> = Effect.never,
57
+ ): Effect.Effect<void, ExecutionError, Graft.Graft> =>
58
+ Effect.scoped(
59
+ Effect.gen(function* () {
60
+ const telemetry = yield* Child.telemetry(contract)
61
+ const loggers = yield* Logger.CurrentLoggers
62
+ yield* Effect.gen(function* () {
63
+ const peer = yield* connect(contract, channel, session, bootstrap)
64
+ const instance = yield* Child.lifecycle(
65
+ contract,
66
+ peer,
67
+ bootstrap?.identity ?? { id: session, generation: 1 },
68
+ telemetry,
69
+ )
70
+ const handlers = yield* contract.control.toHandlers({
71
+ Load: ({ input }) => instance.load(input),
72
+ Dispose: () => instance.dispose,
73
+ Events: () => telemetry.eventStream,
74
+ Logs: () => telemetry.logStream,
75
+ })
76
+ yield* RpcServer.make(contract.control, {
77
+ disableFatalDefects: true,
78
+ }).pipe(
79
+ Effect.provideContext(handlers),
80
+ Effect.provideService(
81
+ RpcServer.Protocol,
82
+ peer.serverProtocol(endpoint),
83
+ ),
84
+ Effect.forkScoped,
85
+ )
86
+ yield* Effect.raceFirst(
87
+ peer.await.pipe(
88
+ Effect.catchIf(
89
+ (error) => closedNormally(error.cause),
90
+ () => Effect.void,
91
+ ),
92
+ Effect.mapError((error) =>
93
+ ExecutionError.make({
94
+ detail: "Child transport failed",
95
+ cause: error.cause,
96
+ }),
97
+ ),
98
+ ),
99
+ stop,
100
+ ).pipe(
101
+ // Release exports before closing the instance scope, including on interruption.
102
+ Effect.ensuring(instance.release),
103
+ )
104
+ }).pipe(
105
+ Effect.provideService(
106
+ Logger.CurrentLoggers,
107
+ new Set([...loggers, telemetry.logger]),
108
+ ),
109
+ )
110
+ }),
111
+ )
@@ -0,0 +1,34 @@
1
+ import { Fork } from "@graftland/graft"
2
+ import { Array, Cause, Effect, Schema, Scope } from "effect"
3
+ import * as Release from "./release"
4
+
5
+ /** Finalizers have no typed failure channel. Keep reasons and their annotations flat. */
6
+ export const cleanupCause = (cause: Cause.Cause<unknown>): Cause.Cause<never> =>
7
+ Cause.fromReasons(
8
+ Array.flatMap(cause.reasons, (reason) => {
9
+ const error =
10
+ reason._tag === "Fail"
11
+ ? reason.error
12
+ : reason._tag === "Die"
13
+ ? reason.defect
14
+ : undefined
15
+ if (Schema.is(Fork.CleanupError)(error))
16
+ return Array.map(cleanupCause(error.cause).reasons, (inner) =>
17
+ inner.annotate(Cause.reasonAnnotations(reason)),
18
+ )
19
+ return [
20
+ reason._tag === "Fail"
21
+ ? Cause.makeDieReason(reason.error).annotate(
22
+ Cause.reasonAnnotations(reason),
23
+ )
24
+ : reason,
25
+ ]
26
+ }),
27
+ )
28
+
29
+ /** Assembly children close before the entry reports their cleanup as its own result. */
30
+ export const children = Effect.acquireRelease(Scope.make(), (scope, exit) =>
31
+ Release.close(scope, exit).pipe(
32
+ Effect.catchCause((cause) => Effect.failCause(cleanupCause(cause))),
33
+ ),
34
+ )
@@ -0,0 +1,8 @@
1
+ import { Duration, Schema } from "effect"
2
+
3
+ export const PositiveDuration = Schema.DurationFromString.check(
4
+ Schema.makeFilter(
5
+ (value) => Duration.isFinite(value) && Duration.toMillis(value) > 0,
6
+ { expected: "a finite, positive duration" },
7
+ ),
8
+ )
@@ -0,0 +1,49 @@
1
+ import { Schema } from "effect"
2
+ import { Rpc, RpcGroup } from "effect/rpc"
3
+
4
+ import { Priority } from "./port"
5
+
6
+ export const Log = Schema.Struct({
7
+ level: Schema.Literals([
8
+ "Fatal",
9
+ "Error",
10
+ "Warn",
11
+ "Info",
12
+ "Debug",
13
+ "Trace",
14
+ "All",
15
+ "None",
16
+ ]),
17
+ message: Schema.Defect({ includeStack: true }),
18
+ cause: Schema.Json,
19
+ annotations: Schema.Record(
20
+ Schema.String,
21
+ Schema.Defect({ includeStack: true }),
22
+ ),
23
+ })
24
+ export const Event = Schema.Union([
25
+ Schema.TaggedStruct("Failed", { cause: Schema.Json }),
26
+ Schema.TaggedStruct("Stopped", {}),
27
+ Schema.TaggedStruct("Withdrawing", {}),
28
+ ])
29
+ export const LogEvent = Schema.Union([
30
+ Schema.TaggedStruct("Log", { entry: Log, dropped: Schema.Int }),
31
+ Schema.TaggedStruct("LogsEnded", { dropped: Schema.Int }),
32
+ ])
33
+ export const endpoint = "@graftland/plugin-remote/control"
34
+ export const make = <C extends Schema.Top>(cause: C) =>
35
+ RpcGroup.make(
36
+ Rpc.make("Load", {
37
+ payload: { input: Schema.Json },
38
+ error: cause,
39
+ }),
40
+ Rpc.make("Events", { success: Event, stream: true }),
41
+ Rpc.make("Dispose", { error: cause }),
42
+ )
43
+ .annotateRpcs(Priority, "control")
44
+ .add(
45
+ Rpc.make("Logs", { success: LogEvent, stream: true }).annotate(
46
+ Priority,
47
+ "log",
48
+ ),
49
+ )
@@ -0,0 +1,112 @@
1
+ import { Graft, Plugin } from "@graftland/graft"
2
+ import { Cause, Context, Effect, Redacted, Scope } from "effect"
3
+ import { Credentials, type ClientCertificate, type Prepared } from "../Auth"
4
+ import { CredentialsError } from "../Errors"
5
+ import { prepare } from "./auth/token"
6
+ import type * as Configuration from "./entryConfig"
7
+
8
+ export type Source<A, D extends ReadonlyArray<Plugin.Dependency>, E = unknown> =
9
+ | Effect.Effect<A, E, Scope.Scope>
10
+ | {
11
+ readonly inject: D
12
+ readonly read: Effect.Effect<
13
+ A,
14
+ unknown,
15
+ NoInfer<Plugin.Required<D>> | Scope.Scope
16
+ >
17
+ }
18
+ type Token<D extends ReadonlyArray<Plugin.Dependency>> =
19
+ string | { readonly file: string } | Source<Redacted.Redacted<string>, D>
20
+ type Authentication<D extends ReadonlyArray<Plugin.Dependency>> =
21
+ | { readonly name: string; readonly config?: unknown }
22
+ | { readonly none: { readonly identity?: string } }
23
+ | {
24
+ readonly mtls:
25
+ | { readonly cert: string; readonly key: string }
26
+ | Source<ClientCertificate, D>
27
+ }
28
+ | { readonly bearer: { readonly token: Token<D> } }
29
+ | { readonly jwt: { readonly token: Token<D> } }
30
+ type WithCredentials<C, D extends ReadonlyArray<Plugin.Dependency>> = C extends
31
+ | { readonly local: object }
32
+ | { readonly worker: object }
33
+ | { readonly command: ReadonlyArray<string> }
34
+ ? C
35
+ : Omit<C, "auth"> & { readonly auth?: Authentication<D> }
36
+ export type Connect<D extends ReadonlyArray<Plugin.Dependency> = readonly []> =
37
+ WithCredentials<typeof Configuration.Connect.Encoded, D>
38
+
39
+ const provider = <A, E, D extends ReadonlyArray<Plugin.Dependency>>(
40
+ source: Source<A, D, E>,
41
+ encode: (
42
+ read: Effect.Effect<A, CredentialsError, Scope.Scope>,
43
+ ) => typeof Credentials.Service,
44
+ ) => {
45
+ const input = Effect.isEffect(source) ? { inject: [], read: source } : source
46
+ return Plugin.make({
47
+ name: "remote-effect-credentials",
48
+ inject: input.inject,
49
+ apply: Effect.fnUntraced(function* () {
50
+ // Restore the provider's context without replacing each read's owning scope.
51
+ const context = yield* Effect.context<
52
+ Plugin.Required<D> | Scope.Scope
53
+ >().pipe(Effect.map(Context.omit(Scope.Scope)))
54
+ const read = input.read.pipe(
55
+ Effect.provideContext(context),
56
+ Effect.mapError((error) =>
57
+ CredentialsError.make({ cause: Cause.fail(error) }),
58
+ ),
59
+ )
60
+ yield* Graft.provide(Credentials, encode(read))
61
+ }),
62
+ })
63
+ }
64
+ export const invocation = <D extends ReadonlyArray<Plugin.Dependency>>(
65
+ connect: Connect<D>,
66
+ ) => {
67
+ const auth = connect.auth
68
+ if (auth === undefined) return undefined
69
+ if ("mtls" in auth) {
70
+ const source = auth.mtls
71
+ if (Effect.isEffect(source) || "read" in source)
72
+ return {
73
+ plugin: provider(source, (read) => ({
74
+ kind: "Certificate",
75
+ read: read.pipe(
76
+ Effect.map(
77
+ (value): Extract<Prepared, { readonly _tag: "Certificate" }> => ({
78
+ _tag: "Certificate",
79
+ value,
80
+ }),
81
+ ),
82
+ ),
83
+ })),
84
+ config: undefined,
85
+ }
86
+ }
87
+ if ("bearer" in auth || "jwt" in auth) {
88
+ const source = "bearer" in auth ? auth.bearer.token : auth.jwt.token
89
+ if (
90
+ typeof source !== "string" &&
91
+ (Effect.isEffect(source) || "read" in source)
92
+ )
93
+ return {
94
+ plugin: provider(source, (read) => ({
95
+ kind: "Authorization",
96
+ read: read.pipe(
97
+ Effect.flatMap(prepare),
98
+ Effect.map(
99
+ (
100
+ value,
101
+ ): Extract<Prepared, { readonly _tag: "Authorization" }> => ({
102
+ _tag: "Authorization",
103
+ value,
104
+ }),
105
+ ),
106
+ ),
107
+ })),
108
+ config: undefined,
109
+ }
110
+ }
111
+ return undefined
112
+ }