@graftland/plugin-remote 0.3.0 → 0.3.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 (209) hide show
  1. package/dist/Auth.d.ts +2 -2
  2. package/dist/Auth.d.ts.map +1 -1
  3. package/dist/Auth.js.map +1 -1
  4. package/dist/{Bootstrap-MCwivGN1.js → Bootstrap-H9gDsgsC.js} +2 -2
  5. package/dist/{Contract-CcpSIJm4.js → Contract-DsJtisvL.js} +8 -46
  6. package/dist/Contract.d.ts +50 -53
  7. package/dist/Contract.d.ts.map +1 -1
  8. package/dist/Contract.js +1 -1
  9. package/dist/Contract.js.map +1 -1
  10. package/dist/{Errors-oPsTLY7l.js → Errors-DYhsGZcZ.js} +14 -1
  11. package/dist/Errors.d.ts +19 -0
  12. package/dist/Errors.d.ts.map +1 -1
  13. package/dist/Errors.js +14 -1
  14. package/dist/Errors.js.map +1 -1
  15. package/dist/{FailureGroup-BcH0XOBi.js → FailureGroup-BgT73AaR.js} +14 -4
  16. package/dist/{Framing-zaYdOJnT.js → Framing-G9eSaeLb.js} +1 -1
  17. package/dist/{Graft-BsYq3F-J.js → Graft-B71CPA2Y.js} +46 -35
  18. package/dist/{Packages-B1TPk8pa.js → Packages-AgoCGotL.js} +23 -26
  19. package/dist/{Peer-IJgFK6mD.js → Peer-DXeVrGBh.js} +5 -5
  20. package/dist/{ProcessObservation-DEGrEMfP.js → ProcessObservation-gLgGirYv.js} +1 -1
  21. package/dist/{ServeLifecycle-CJM0gG5B.js → ServeLifecycle-Bd1FPJ6e.js} +1 -1
  22. package/dist/Testing.d.ts +4 -4
  23. package/dist/Testing.d.ts.map +1 -1
  24. package/dist/Testing.js +10 -4
  25. package/dist/Testing.js.map +1 -1
  26. package/dist/Transport.d.ts +2 -2
  27. package/dist/Transport.d.ts.map +1 -1
  28. package/dist/Transport.js.map +1 -1
  29. package/dist/bin.js +48 -47
  30. package/dist/bin.js.map +1 -1
  31. package/dist/{childRuntime-DSqtFN9o.js → childRuntime-Bm3iSg_N.js} +30 -26
  32. package/dist/connectionEnded-BwcxQ7W8.js +54 -0
  33. package/dist/{entry-SYsx9VNb.js → entry-psOpX3Bj.js} +76 -48
  34. package/dist/host/auth/bearer.d.ts +1 -2
  35. package/dist/host/auth/bearer.d.ts.map +1 -1
  36. package/dist/host/auth/bearer.js +1 -1
  37. package/dist/host/auth/bearer.js.map +1 -1
  38. package/dist/host/auth/jwt.d.ts +1 -2
  39. package/dist/host/auth/jwt.d.ts.map +1 -1
  40. package/dist/host/auth/jwt.js +1 -1
  41. package/dist/host/auth/jwt.js.map +1 -1
  42. package/dist/host/auth/mtls.js +2 -2
  43. package/dist/host/auth/none.js +1 -1
  44. package/dist/host/command.d.ts +1 -1
  45. package/dist/host/command.d.ts.map +1 -1
  46. package/dist/host/command.js +4 -4
  47. package/dist/host/command.js.map +1 -1
  48. package/dist/host/local.d.ts +1 -2
  49. package/dist/host/local.d.ts.map +1 -1
  50. package/dist/host/local.js +3 -3
  51. package/dist/host/local.js.map +1 -1
  52. package/dist/host/unix.d.ts +1 -1
  53. package/dist/host/unix.d.ts.map +1 -1
  54. package/dist/host/unix.js +3 -3
  55. package/dist/host/unix.js.map +1 -1
  56. package/dist/host/websocket.d.ts +1 -1
  57. package/dist/host/websocket.d.ts.map +1 -1
  58. package/dist/host/websocket.js +3 -3
  59. package/dist/host/websocket.js.map +1 -1
  60. package/dist/host/worker.d.ts +1 -2
  61. package/dist/host/worker.d.ts.map +1 -1
  62. package/dist/host/worker.js +4 -5
  63. package/dist/host/worker.js.map +1 -1
  64. package/dist/{importer-D7zSgqxq.js → importer-Cvf88eAY.js} +5 -8
  65. package/dist/index.d.ts +2 -3
  66. package/dist/index.d.ts.map +1 -1
  67. package/dist/index.js +10 -10
  68. package/dist/index.js.map +1 -1
  69. package/dist/internal/Certificates.js +4 -4
  70. package/dist/internal/Certificates.js.map +1 -1
  71. package/dist/internal/FailureGroup.js +3 -2
  72. package/dist/internal/FailureGroup.js.map +1 -1
  73. package/dist/internal/assembly.js +9 -2
  74. package/dist/internal/assembly.js.map +1 -1
  75. package/dist/internal/auth/mtls.js +1 -1
  76. package/dist/internal/auth/mtls.js.map +1 -1
  77. package/dist/internal/auth/tokenCredentials.d.ts +0 -1
  78. package/dist/internal/auth/tokenCredentials.d.ts.map +1 -1
  79. package/dist/internal/auth/tokenCredentials.js.map +1 -1
  80. package/dist/internal/child.js +20 -17
  81. package/dist/internal/child.js.map +1 -1
  82. package/dist/internal/childRuntime.js +6 -4
  83. package/dist/internal/childRuntime.js.map +1 -1
  84. package/dist/internal/contract.js +26 -0
  85. package/dist/internal/contract.js.map +1 -0
  86. package/dist/internal/credentials.d.ts +6 -6
  87. package/dist/internal/credentials.d.ts.map +1 -1
  88. package/dist/internal/credentials.js.map +1 -1
  89. package/dist/internal/directTransport.d.ts +1 -1
  90. package/dist/internal/entry.d.ts +1 -2
  91. package/dist/internal/entry.d.ts.map +1 -1
  92. package/dist/internal/entry.js +4 -14
  93. package/dist/internal/entry.js.map +1 -1
  94. package/dist/internal/execution.js +44 -7
  95. package/dist/internal/execution.js.map +1 -1
  96. package/dist/internal/host/runner.js +7 -6
  97. package/dist/internal/host/runner.js.map +1 -1
  98. package/dist/internal/host.js +5 -5
  99. package/dist/internal/host.js.map +1 -1
  100. package/dist/internal/port.d.ts +2 -10
  101. package/dist/internal/port.js +5 -5
  102. package/dist/internal/port.js.map +1 -1
  103. package/dist/internal/release.js +1 -1
  104. package/dist/internal/release.js.map +1 -1
  105. package/dist/internal/runner/Connection.d.ts +1 -1
  106. package/dist/internal/runner/Connection.js +4 -4
  107. package/dist/internal/runner/Connection.js.map +1 -1
  108. package/dist/internal/runner/Execution.js +3 -3
  109. package/dist/internal/runner/Execution.js.map +1 -1
  110. package/dist/internal/runner/Framing.d.ts +1 -11
  111. package/dist/internal/runner/Framing.js +1 -1
  112. package/dist/internal/runner/Framing.js.map +1 -1
  113. package/dist/internal/runner/Local.js +1 -1
  114. package/dist/internal/runner/Local.js.map +1 -1
  115. package/dist/internal/runner/Lock.js +1 -1
  116. package/dist/internal/runner/Lock.js.map +1 -1
  117. package/dist/internal/runner/Packages.d.ts +1 -1
  118. package/dist/internal/runner/Packages.js +22 -25
  119. package/dist/internal/runner/Packages.js.map +1 -1
  120. package/dist/internal/runner/Processes.js +7 -9
  121. package/dist/internal/runner/Processes.js.map +1 -1
  122. package/dist/internal/runner/Store.js +3 -3
  123. package/dist/internal/runner/Store.js.map +1 -1
  124. package/dist/internal/runner/Supervisor.js +46 -47
  125. package/dist/internal/runner/Supervisor.js.map +1 -1
  126. package/dist/internal/runner/accept.js +3 -3
  127. package/dist/internal/runner/accept.js.map +1 -1
  128. package/dist/internal/runner/model.js +1 -1
  129. package/dist/internal/runner/model.js.map +1 -1
  130. package/dist/internal/serve.js +1 -1
  131. package/dist/internal/serve.js.map +1 -1
  132. package/dist/internal/services.d.ts +2 -12
  133. package/dist/internal/services.d.ts.map +1 -1
  134. package/dist/internal/services.js.map +1 -1
  135. package/dist/internal/supervisorPlugin.js +1 -1
  136. package/dist/internal/watchdogMain.js +5 -5
  137. package/dist/internal/watchdogMain.js.map +1 -1
  138. package/dist/internal/websocketServer.js +3 -1
  139. package/dist/internal/websocketServer.js.map +1 -1
  140. package/dist/internal/workerMain.js +3 -3
  141. package/dist/{port-Blbh8tms.js → port--3x2zJ4D.js} +8 -8
  142. package/dist/{release-BY4Mlluy.js → release-DfZPuIcK.js} +1 -1
  143. package/dist/runner/auth/bearer.js +2 -2
  144. package/dist/runner/auth/jwt.js +4 -4
  145. package/dist/runner/auth/jwt.js.map +1 -1
  146. package/dist/runner/auth/mtls.js +3 -3
  147. package/dist/runner/auth/none.js +1 -1
  148. package/dist/runner/index.js +5 -5
  149. package/dist/runner/stdio.js +3 -3
  150. package/dist/runner/unix.js +3 -3
  151. package/dist/runner/websocket.js +4 -4
  152. package/dist/{socketChannel-KmtzF-9G.js → socketChannel-CJvL2DiB.js} +2 -2
  153. package/dist/{supervisorPlugin-Inb1S5IV.js → supervisorPlugin-t6Z6PrhD.js} +72 -76
  154. package/dist/{token-v5ne2I0-.js → token-CYBNNlhS.js} +1 -1
  155. package/dist/{tokenCredentials-WUJm2AKm.js → tokenCredentials-CbCuk-Rt.js} +3 -3
  156. package/dist/{websocketServer-MXcCJx0v.js → websocketServer-NQhODlEt.js} +5 -3
  157. package/dist/{workerChannel-P82YdNjh.js → workerChannel-C8hhBJzA.js} +1 -1
  158. package/package.json +3 -3
  159. package/src/Auth.ts +9 -2
  160. package/src/Contract.ts +67 -51
  161. package/src/Errors.ts +23 -0
  162. package/src/Testing.ts +16 -2
  163. package/src/Transport.ts +6 -2
  164. package/src/bin.ts +28 -30
  165. package/src/host/auth/bearer.ts +1 -6
  166. package/src/host/auth/jwt.ts +1 -6
  167. package/src/host/command.ts +2 -0
  168. package/src/host/local.ts +5 -9
  169. package/src/host/unix.ts +2 -0
  170. package/src/host/websocket.ts +2 -0
  171. package/src/host/worker.ts +4 -6
  172. package/src/index.ts +8 -4
  173. package/src/internal/Certificates.ts +10 -13
  174. package/src/internal/FailureGroup.ts +128 -121
  175. package/src/internal/assembly.ts +19 -10
  176. package/src/internal/auth/mtls.ts +19 -20
  177. package/src/internal/auth/tokenCredentials.ts +1 -7
  178. package/src/internal/child.ts +249 -240
  179. package/src/internal/childRuntime.ts +84 -81
  180. package/src/internal/contract.ts +47 -0
  181. package/src/internal/credentials.ts +12 -9
  182. package/src/internal/entry.ts +11 -25
  183. package/src/internal/execution.ts +73 -14
  184. package/src/internal/host/runner.ts +153 -153
  185. package/src/internal/host.ts +123 -130
  186. package/src/internal/port.ts +100 -103
  187. package/src/internal/release.ts +3 -2
  188. package/src/internal/runner/Connection.ts +52 -60
  189. package/src/internal/runner/Execution.ts +163 -164
  190. package/src/internal/runner/Framing.ts +9 -10
  191. package/src/internal/runner/Local.ts +26 -27
  192. package/src/internal/runner/Lock.ts +23 -25
  193. package/src/internal/runner/Packages.ts +67 -70
  194. package/src/internal/runner/Processes.ts +89 -92
  195. package/src/internal/runner/Store.ts +110 -114
  196. package/src/internal/runner/Supervisor.ts +392 -405
  197. package/src/internal/runner/accept.ts +76 -84
  198. package/src/internal/runner/model.ts +20 -21
  199. package/src/internal/serve.ts +15 -13
  200. package/src/internal/services.ts +1 -19
  201. package/src/internal/watchdogMain.ts +16 -11
  202. package/src/internal/websocketServer.ts +18 -3
  203. package/src/runner/auth/jwt.ts +10 -6
  204. package/dist/cleanup-BPWr-5U9.js +0 -13
  205. package/dist/connectionEnded-DUgcobEd.js +0 -9
  206. package/dist/internal/childErrors.d.ts +0 -33
  207. package/dist/internal/childErrors.d.ts.map +0 -1
  208. package/dist/internal/port.d.ts.map +0 -1
  209. package/dist/internal/runner/Framing.d.ts.map +0 -1
@@ -1,4 +1,4 @@
1
- import { s as fromModule } from "./Graft-BsYq3F-J.js";
1
+ import { s as fromModule } from "./Graft-B71CPA2Y.js";
2
2
  import { t as ConfigDirectory } from "./ConfigDirectory-BCC6q2R4.js";
3
3
  import { registerHooks } from "node:module";
4
4
  import { Array, Cause, Config, Context, Data, Effect, Exit, HashMap, MutableList, Option, Path, Predicate, Record, Ref, Result, Schema, Scope, String } from "effect";
@@ -202,7 +202,7 @@ const inCandidateScope = (effect) => Effect.uninterruptibleMask((restore) => Eff
202
202
  * Importers may attach observation-only leases to the separate observationScope.
203
203
  * The caller keeps that scope through failure and closes it on retry or disposal.
204
204
  */
205
- const make$1 = (options) => Effect.gen(function* () {
205
+ const make$1 = Effect.fnUntraced(function* (options) {
206
206
  const path = yield* Path.Path;
207
207
  /** Keep the import target and Node's possible missing names in one normalization step. */
208
208
  const normalize = Effect.fnUntraced(function* (specifier) {
@@ -253,14 +253,11 @@ const make$1 = (options) => Effect.gen(function* () {
253
253
  });
254
254
  const environment = options.resolution;
255
255
  const revision = environment === void 0 ? 0 : yield* environment.revision;
256
- const cached = yield* Ref.get(plans);
257
- if (cached.revision === revision) {
258
- const found = HashMap.get(cached.entries, key);
259
- if (Option.isSome(found)) return found.value;
260
- } else yield* Ref.set(plans, {
256
+ const found = yield* Ref.modify(plans, (current) => current.revision === revision ? [HashMap.get(current.entries, key), current] : revision > current.revision ? [Option.none(), {
261
257
  revision,
262
258
  entries: HashMap.empty()
263
- });
259
+ }] : [Option.none(), current]);
260
+ if (Option.isSome(found)) return found.value;
264
261
  const normalized = yield* Effect.forEach(candidates(name), (specifier) => Effect.map(normalize(specifier), (candidate) => ({
265
262
  ...candidate,
266
263
  specifier
package/dist/index.d.ts CHANGED
@@ -1,5 +1,4 @@
1
- import { Connect, Source } from "./internal/credentials.js";
2
- import { ChildFailure } from "./internal/childErrors.js";
1
+ import { Authentication, Connect, Source, Token } from "./internal/credentials.js";
3
2
  import { MissingInstance, RemoteError, RemoteWithdrawn } from "./Errors.js";
4
3
  import { Contract, Contract_d_exports, UndeclaredFailure } from "./Contract.js";
5
4
  import { Instance } from "./Instance.js";
@@ -25,5 +24,5 @@ export declare const plugin: <S extends Schema.Top & {
25
24
  }, const D extends ReadonlyArray<Plugin.Dependency> = readonly []>(contract: Contract<S, E>, options: Options<D> & {
26
25
  readonly config?: S["Encoded"];
27
26
  }) => Plugin.Plugin<void, void, E["Type"] | UndeclaredFailure | RemoteError | RemoteWithdrawn | MissingInstance>;
28
- export { ChildFailure, type Connect, Contract_d_exports as Contract, type Source as CredentialSource, Instance, MissingInstance, RemoteError, RemoteTerminationUnconfirmed, RemoteWithdrawn, UndeclaredFailure, host as default };
27
+ export { type Authentication, type Connect, Contract_d_exports as Contract, type Source as CredentialSource, type Token as CredentialToken, Instance, MissingInstance, RemoteError, RemoteTerminationUnconfirmed, RemoteWithdrawn, UndeclaredFailure, host as default };
29
28
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":["Credential.Connect","Contract.Contract","Contract.UndeclaredFailure"],"sources":["../src/index.ts"],"mappings":";;;;;;;;;iBAwBiB,QAChB,UAAU,cAAc,OAAO;WAEtB,SAASA,QAAmB;;WAE5B;WACA,SAAS,OAAO;WAChB,QAAQ,SAAS;WACjB,kBAAkB,SAAS;;qBA4BxB,SACZ,UAAU,OAAO;WACP,SAAS,OAAO;WAChB;WACA;GAEV,UAAU,OAAO;WACP;WACA;SAEJ,UAAU,cAAc,OAAO,2BAAyB,UAEpDC,SAAkB,GAAG,IAAE,SACxB,QAAQ;WAAgB,SAAS;MACxC,OAAO,mBAGP,YACAC,oBACA,cACA,kBACA"}
1
+ {"version":3,"file":"index.d.ts","names":["Credential.Connect","Contract.Contract","Contract.UndeclaredFailure"],"sources":["../src/index.ts"],"mappings":";;;;;;;;iBA0BiB,QAChB,UAAU,cAAc,OAAO;WAEtB,SAASA,QAAmB;;WAE5B;WACA,SAAS,OAAO;WAChB,QAAQ,SAAS;WACjB,kBAAkB,SAAS;;qBA4BxB,SACZ,UAAU,OAAO;WACP,SAAS,OAAO;WAChB;WACA;GAEV,UAAU,OAAO;WACP;WACA;SAEJ,UAAU,cAAc,OAAO,2BAAyB,UAEpDC,SAAkB,GAAG,IAAE,SACxB,QAAQ;WAAgB,SAAS;MACxC,OAAO,mBAGP,YACAC,oBACA,cACA,kBACA"}
package/dist/index.js CHANGED
@@ -1,11 +1,11 @@
1
- import { a as provide, l as make, u as optional } from "./Graft-BsYq3F-J.js";
2
- import { r as ModuleResolver } from "./importer-D7zSgqxq.js";
3
- import { a as publicError, d as follow, f as Host, n as host, r as launch, s as CapabilityFailed } from "./entry-SYsx9VNb.js";
1
+ import { a as provide, l as make, u as optional } from "./Graft-B71CPA2Y.js";
2
+ import { r as ModuleResolver } from "./importer-Cvf88eAY.js";
3
+ import { a as publicError, d as follow, f as Host, n as host, r as launch, s as CapabilityFailed } from "./entry-psOpX3Bj.js";
4
4
  import { n as Credentials } from "./Auth-BElTC9_X.js";
5
- import { i as MissingInstance, n as CredentialsError, o as RemoteError, s as RemoteWithdrawn } from "./Errors-oPsTLY7l.js";
6
- import { n as prepare } from "./token-v5ne2I0-.js";
7
- import { d as ChildFailure, n as UndeclaredFailure, t as Contract_exports } from "./Contract-CcpSIJm4.js";
8
- import { O as Instance, l as RemoteTerminationUnconfirmed } from "./Peer-IJgFK6mD.js";
5
+ import { a as MissingInstance, c as RemoteError, l as RemoteWithdrawn, r as CredentialsError } from "./Errors-DYhsGZcZ.js";
6
+ import { n as prepare } from "./token-CYBNNlhS.js";
7
+ import { n as UndeclaredFailure, t as Contract_exports } from "./Contract-DsJtisvL.js";
8
+ import { O as Instance, l as RemoteTerminationUnconfirmed } from "./Peer-DXeVrGBh.js";
9
9
  import { Array, Cause, Context, Effect, Path, Schema, Scope } from "effect";
10
10
  import { SecureRandom } from "effect/crypto";
11
11
  import { ChildProcessSpawner } from "effect/process";
@@ -69,7 +69,7 @@ const plugin = (contract, options) => make({
69
69
  ChildProcessSpawner.ChildProcessSpawner
70
70
  ],
71
71
  retry: options.retry,
72
- apply: () => Effect.gen(function* () {
72
+ apply: Effect.fnUntraced(function* () {
73
73
  const input = yield* Schema.decodeUnknownEffect(Host)({
74
74
  contract: options.contractModule,
75
75
  connect: options.connect,
@@ -81,6 +81,6 @@ const plugin = (contract, options) => make({
81
81
  shutdownTimeout: options.shutdownTimeout
82
82
  }, invocation(options.connect));
83
83
  yield* follow(child, (cause) => Effect.failCause(publicCause(contract.error, cause)));
84
- }).pipe(Effect.mapError((error) => publicError(contract.error, error)))
84
+ }, Effect.mapError((error) => publicError(contract.error, error)))
85
85
  });
86
- export { ChildFailure, Contract_exports as Contract, Instance, MissingInstance, RemoteError, RemoteTerminationUnconfirmed, RemoteWithdrawn, UndeclaredFailure, host as default, plugin };
86
+ export { Contract_exports as Contract, Instance, MissingInstance, RemoteError, RemoteTerminationUnconfirmed, RemoteWithdrawn, UndeclaredFailure, host as default, plugin };
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["Configuration.Host","Credential.invocation"],"sources":["../src/index.ts"],"sourcesContent":["import { Plugin } from \"@graftland/graft\"\nimport { ModuleResolver } from \"@graftland/loader\"\nimport { Array, Cause, Effect, Path, Schema } from \"effect\"\nimport type { Duration, Schedule } from \"effect\"\nimport { SecureRandom } from \"effect/crypto\"\nimport { ChildProcessSpawner } from \"effect/process\"\nimport { launch } from \"./internal/entry\"\nimport { follow } from \"./internal/follow\"\nimport { CapabilityFailed } from \"./internal/assembly\"\nimport { publicError } from \"./internal/execution\"\nimport * as Configuration from \"./internal/entryConfig\"\nimport * as Credential from \"./internal/credentials\"\nimport { RemoteWithdrawn, RemoteError, MissingInstance } from \"./Errors\"\nimport * as Contract from \"./Contract\"\nexport { Contract }\nexport { Instance } from \"./Instance\"\nexport { RemoteTerminationUnconfirmed } from \"./internal/runner/model\"\nexport { RemoteError, RemoteWithdrawn, MissingInstance } from \"./Errors\"\nexport { UndeclaredFailure, ChildFailure } from \"./Contract\"\nexport type {\n\tConnect,\n\tSource as CredentialSource,\n} from \"./internal/credentials\"\n\nexport interface Options<\n\tD extends ReadonlyArray<Plugin.Dependency> = readonly [],\n> {\n\treadonly connect: Credential.Connect<D>\n\t/** Contract module resolved independently in each execution environment. */\n\treadonly contractModule: string\n\treadonly config?: Schema.Json\n\treadonly retry?: Schedule.Schedule<unknown, unknown> | undefined\n\treadonly shutdownTimeout?: Duration.Input | undefined\n}\nconst publicCause = <E extends Schema.Top>(\n\tdeclared: E,\n\tcause: Cause.Cause<unknown>,\n): Cause.Cause<\n\t| E[\"Type\"]\n\t| Contract.UndeclaredFailure\n\t| RemoteWithdrawn\n\t| RemoteError\n\t| MissingInstance\n> =>\n\tCause.fromReasons(\n\t\tArray.flatMap(cause.reasons, (reason) => {\n\t\t\tif (reason._tag !== \"Fail\") return [reason]\n\t\t\treturn Schema.is(CapabilityFailed)(reason.error)\n\t\t\t\t? Array.map(\n\t\t\t\t\t\tpublicCause(declared, reason.error.cause).reasons,\n\t\t\t\t\t\t(inner) => inner.annotate(Cause.reasonAnnotations(reason)),\n\t\t\t\t\t)\n\t\t\t\t: [\n\t\t\t\t\t\tCause.makeFailReason(publicError(declared, reason.error)).annotate(\n\t\t\t\t\t\t\tCause.reasonAnnotations(reason),\n\t\t\t\t\t\t),\n\t\t\t\t\t]\n\t\t}),\n\t)\n\nexport const plugin = <\n\tS extends Schema.Top & {\n\t\treadonly Encoded: Schema.Json\n\t\treadonly DecodingServices: never\n\t\treadonly EncodingServices: never\n\t},\n\tE extends Schema.Top & {\n\t\treadonly DecodingServices: never\n\t\treadonly EncodingServices: never\n\t},\n\tconst D extends ReadonlyArray<Plugin.Dependency> = readonly [],\n>(\n\tcontract: Contract.Contract<S, E>,\n\toptions: Options<D> & { readonly config?: S[\"Encoded\"] },\n): Plugin.Plugin<\n\tvoid,\n\tvoid,\n\t| E[\"Type\"]\n\t| Contract.UndeclaredFailure\n\t| RemoteError\n\t| RemoteWithdrawn\n\t| MissingInstance\n> =>\n\tPlugin.make({\n\t\tname: contract.name,\n\t\tinject: [\n\t\t\tPlugin.optional(ModuleResolver.ModuleResolver),\n\t\t\tPath.Path,\n\t\t\tSecureRandom.SecureRandom,\n\t\t\tChildProcessSpawner.ChildProcessSpawner,\n\t\t],\n\t\tretry: options.retry,\n\t\tapply: () =>\n\t\t\tEffect.gen(function* () {\n\t\t\t\tconst input = yield* Schema.decodeUnknownEffect(Configuration.Host)({\n\t\t\t\t\tcontract: options.contractModule,\n\t\t\t\t\tconnect: options.connect,\n\t\t\t\t\tconfig: options.config === undefined ? {} : options.config,\n\t\t\t\t})\n\t\t\t\tyield* Schema.decodeEffect(contract.config)(input.config)\n\t\t\t\tconst child = yield* launch(\n\t\t\t\t\tcontract,\n\t\t\t\t\tinput,\n\t\t\t\t\t{\n\t\t\t\t\t\tcontractModule: options.contractModule,\n\t\t\t\t\t\tshutdownTimeout: options.shutdownTimeout,\n\t\t\t\t\t},\n\t\t\t\t\tCredential.invocation(options.connect),\n\t\t\t\t)\n\t\t\t\tyield* follow(child, (cause) =>\n\t\t\t\t\tEffect.failCause(publicCause(contract.error, cause)),\n\t\t\t\t)\n\t\t\t}).pipe(Effect.mapError((error) => publicError(contract.error, error))),\n\t})\nexport { host as default } from \"./internal/entry\"\n"],"mappings":";;;;;;;;;;;;;;;;;AAkCA,MAAM,eACL,UACA,UAQA,MAAM,YACL,MAAM,QAAQ,MAAM,UAAU,WAAW;CACxC,IAAI,OAAO,SAAS,QAAQ,OAAO,CAAC,MAAM;CAC1C,OAAO,OAAO,GAAG,gBAAgB,CAAC,CAAC,OAAO,KAAK,IAC5C,MAAM,IACN,YAAY,UAAU,OAAO,MAAM,KAAK,CAAC,CAAC,UACzC,UAAU,MAAM,SAAS,MAAM,kBAAkB,MAAM,CAAC,CAC1D,IACC,CACA,MAAM,eAAe,YAAY,UAAU,OAAO,KAAK,CAAC,CAAC,CAAC,SACzD,MAAM,kBAAkB,MAAM,CAC/B,CACD;AACH,CAAC,CACF;AAED,MAAa,UAYZ,UACA,YAUA,OAAO,KAAK;CACX,MAAM,SAAS;CACf,QAAQ;EACP,OAAO,SAAS,eAAe,cAAc;EAC7C,KAAK;EACL,aAAa;EACb,oBAAoB;CACrB;CACA,OAAO,QAAQ;CACf,aACC,OAAO,IAAI,aAAa;EACvB,MAAM,QAAQ,OAAO,OAAO,oBAAoBA,IAAkB,CAAC,CAAC;GACnE,UAAU,QAAQ;GAClB,SAAS,QAAQ;GACjB,QAAQ,QAAQ,WAAW,KAAA,IAAY,CAAC,IAAI,QAAQ;EACrD,CAAC;EACD,OAAO,OAAO,aAAa,SAAS,MAAM,CAAC,CAAC,MAAM,MAAM;EACxD,MAAM,QAAQ,OAAO,OACpB,UACA,OACA;GACC,gBAAgB,QAAQ;GACxB,iBAAiB,QAAQ;EAC1B,GACAC,WAAsB,QAAQ,OAAO,CACtC;EACA,OAAO,OAAO,QAAQ,UACrB,OAAO,UAAU,YAAY,SAAS,OAAO,KAAK,CAAC,CACpD;CACD,CAAC,CAAC,CAAC,KAAK,OAAO,UAAU,UAAU,YAAY,SAAS,OAAO,KAAK,CAAC,CAAC;AACxE,CAAC"}
1
+ {"version":3,"file":"index.js","names":["Configuration.Host","Credential.invocation"],"sources":["../src/index.ts"],"sourcesContent":["import { Plugin } from \"@graftland/graft\"\nimport { ModuleResolver } from \"@graftland/loader\"\nimport { Array, Cause, Effect, Path, Schema } from \"effect\"\nimport type { Duration, Schedule } from \"effect\"\nimport { SecureRandom } from \"effect/crypto\"\nimport { ChildProcessSpawner } from \"effect/process\"\nimport { launch } from \"./internal/entry\"\nimport { follow } from \"./internal/follow\"\nimport { CapabilityFailed } from \"./internal/assembly\"\nimport { publicError } from \"./internal/execution\"\nimport * as Configuration from \"./internal/entryConfig\"\nimport * as Credential from \"./internal/credentials\"\nimport { RemoteWithdrawn, RemoteError, MissingInstance } from \"./Errors\"\nimport * as Contract from \"./Contract\"\nexport { Contract }\nexport { Instance } from \"./Instance\"\nexport { RemoteTerminationUnconfirmed } from \"./internal/runner/model\"\nexport { RemoteError, RemoteWithdrawn, MissingInstance } from \"./Errors\"\nexport { UndeclaredFailure } from \"./Contract\"\nexport type {\n\tConnect,\n\tAuthentication,\n\tToken as CredentialToken,\n\tSource as CredentialSource,\n} from \"./internal/credentials\"\n\nexport interface Options<\n\tD extends ReadonlyArray<Plugin.Dependency> = readonly [],\n> {\n\treadonly connect: Credential.Connect<D>\n\t/** Contract module resolved independently in each execution environment. */\n\treadonly contractModule: string\n\treadonly config?: Schema.Json\n\treadonly retry?: Schedule.Schedule<unknown, unknown> | undefined\n\treadonly shutdownTimeout?: Duration.Input | undefined\n}\nconst publicCause = <E extends Schema.Top>(\n\tdeclared: E,\n\tcause: Cause.Cause<unknown>,\n): Cause.Cause<\n\t| E[\"Type\"]\n\t| Contract.UndeclaredFailure\n\t| RemoteWithdrawn\n\t| RemoteError\n\t| MissingInstance\n> =>\n\tCause.fromReasons(\n\t\tArray.flatMap(cause.reasons, (reason) => {\n\t\t\tif (reason._tag !== \"Fail\") return [reason]\n\t\t\treturn Schema.is(CapabilityFailed)(reason.error)\n\t\t\t\t? Array.map(\n\t\t\t\t\t\tpublicCause(declared, reason.error.cause).reasons,\n\t\t\t\t\t\t(inner) => inner.annotate(Cause.reasonAnnotations(reason)),\n\t\t\t\t\t)\n\t\t\t\t: [\n\t\t\t\t\t\tCause.makeFailReason(publicError(declared, reason.error)).annotate(\n\t\t\t\t\t\t\tCause.reasonAnnotations(reason),\n\t\t\t\t\t\t),\n\t\t\t\t\t]\n\t\t}),\n\t)\n\nexport const plugin = <\n\tS extends Schema.Top & {\n\t\treadonly Encoded: Schema.Json\n\t\treadonly DecodingServices: never\n\t\treadonly EncodingServices: never\n\t},\n\tE extends Schema.Top & {\n\t\treadonly DecodingServices: never\n\t\treadonly EncodingServices: never\n\t},\n\tconst D extends ReadonlyArray<Plugin.Dependency> = readonly [],\n>(\n\tcontract: Contract.Contract<S, E>,\n\toptions: Options<D> & { readonly config?: S[\"Encoded\"] },\n): Plugin.Plugin<\n\tvoid,\n\tvoid,\n\t| E[\"Type\"]\n\t| Contract.UndeclaredFailure\n\t| RemoteError\n\t| RemoteWithdrawn\n\t| MissingInstance\n> =>\n\tPlugin.make({\n\t\tname: contract.name,\n\t\tinject: [\n\t\t\tPlugin.optional(ModuleResolver.ModuleResolver),\n\t\t\tPath.Path,\n\t\t\tSecureRandom.SecureRandom,\n\t\t\tChildProcessSpawner.ChildProcessSpawner,\n\t\t],\n\t\tretry: options.retry,\n\t\tapply: Effect.fnUntraced(\n\t\t\tfunction* () {\n\t\t\t\tconst input = yield* Schema.decodeUnknownEffect(Configuration.Host)({\n\t\t\t\t\tcontract: options.contractModule,\n\t\t\t\t\tconnect: options.connect,\n\t\t\t\t\tconfig: options.config === undefined ? {} : options.config,\n\t\t\t\t})\n\t\t\t\tyield* Schema.decodeEffect(contract.config)(input.config)\n\t\t\t\tconst child = yield* launch(\n\t\t\t\t\tcontract,\n\t\t\t\t\tinput,\n\t\t\t\t\t{\n\t\t\t\t\t\tcontractModule: options.contractModule,\n\t\t\t\t\t\tshutdownTimeout: options.shutdownTimeout,\n\t\t\t\t\t},\n\t\t\t\t\tCredential.invocation(options.connect),\n\t\t\t\t)\n\t\t\t\tyield* follow(child, (cause) =>\n\t\t\t\t\tEffect.failCause(publicCause(contract.error, cause)),\n\t\t\t\t)\n\t\t\t},\n\t\t\tEffect.mapError((error) => publicError(contract.error, error)),\n\t\t),\n\t})\nexport { host as default } from \"./internal/entry\"\n"],"mappings":";;;;;;;;;;;;;;;;AAoCA,MAAM,eACL,UACA,UAQA,MAAM,YACL,MAAM,QAAQ,MAAM,UAAU,WAAW;CACxC,IAAI,OAAO,SAAS,QAAQ,OAAO,CAAC,MAAM;CAC1C,OAAO,OAAO,GAAG,gBAAgB,CAAC,CAAC,OAAO,KAAK,IAC5C,MAAM,IACN,YAAY,UAAU,OAAO,MAAM,KAAK,CAAC,CAAC,UACzC,UAAU,MAAM,SAAS,MAAM,kBAAkB,MAAM,CAAC,CAC1D,IACC,CACA,MAAM,eAAe,YAAY,UAAU,OAAO,KAAK,CAAC,CAAC,CAAC,SACzD,MAAM,kBAAkB,MAAM,CAC/B,CACD;AACH,CAAC,CACF;AAED,MAAa,UAYZ,UACA,YAUA,OAAO,KAAK;CACX,MAAM,SAAS;CACf,QAAQ;EACP,OAAO,SAAS,eAAe,cAAc;EAC7C,KAAK;EACL,aAAa;EACb,oBAAoB;CACrB;CACA,OAAO,QAAQ;CACf,OAAO,OAAO,WACb,aAAa;EACZ,MAAM,QAAQ,OAAO,OAAO,oBAAoBA,IAAkB,CAAC,CAAC;GACnE,UAAU,QAAQ;GAClB,SAAS,QAAQ;GACjB,QAAQ,QAAQ,WAAW,KAAA,IAAY,CAAC,IAAI,QAAQ;EACrD,CAAC;EACD,OAAO,OAAO,aAAa,SAAS,MAAM,CAAC,CAAC,MAAM,MAAM;EACxD,MAAM,QAAQ,OAAO,OACpB,UACA,OACA;GACC,gBAAgB,QAAQ;GACxB,iBAAiB,QAAQ;EAC1B,GACAC,WAAsB,QAAQ,OAAO,CACtC;EACA,OAAO,OAAO,QAAQ,UACrB,OAAO,UAAU,YAAY,SAAS,OAAO,KAAK,CAAC,CACpD;CACD,GACA,OAAO,UAAU,UAAU,YAAY,SAAS,OAAO,KAAK,CAAC,CAC9D;AACD,CAAC"}
@@ -137,10 +137,10 @@ const write = Effect.fn("Certificates.write")(function* (base, pair, force = fal
137
137
  yield* fs.writeFileString(base + ".key", Redacted.value(pair.privateKey), {
138
138
  flag: force ? "w" : "wx",
139
139
  mode: 384
140
- }).pipe(Effect.uninterruptible);
141
- yield* fs.chmod(base + ".key", 384).pipe(Effect.uninterruptible);
142
- yield* fs.writeFileString(base + ".crt", pair.certificate, { flag: force ? "w" : "wx" }).pipe(Effect.uninterruptible);
143
- });
140
+ });
141
+ yield* fs.chmod(base + ".key", 384);
142
+ yield* fs.writeFileString(base + ".crt", pair.certificate, { flag: force ? "w" : "wx" });
143
+ }, Effect.uninterruptible);
144
144
  /** URI-encode names so each identity has a distinct filename, including names with slashes. */
145
145
  const clientName = (identity) => `client-${encodeURIComponent(identity)}`;
146
146
  const generate = Effect.fn("Certificates.generate")(function* (options) {
@@ -1 +1 @@
1
- {"version":3,"file":"Certificates.js","names":[],"sources":["../../src/internal/Certificates.ts"],"sourcesContent":["import {\n\tArray,\n\tDateTime,\n\tEffect,\n\tFileSystem,\n\tPath,\n\tRedacted,\n\tResult,\n\tSchema,\n\tString,\n} from \"effect\"\nimport { SecureRandom, WebCrypto } from \"effect/crypto\"\nimport { Base64 } from \"effect/encoding\"\nimport { NetAddress } from \"effect/net\"\nimport * as asn1js from \"asn1js\"\nimport * as pki from \"pkijs\"\n\nexport class CertificateError extends Schema.TaggedError<\n\tCertificateError,\n\t{ readonly brand: unique symbol }\n>()(\"CertificateError\", {\n\tdetail: Schema.String,\n\tcause: Schema.optional(Schema.Defect()),\n}) {\n\toverride get message() {\n\t\treturn this.detail\n\t}\n}\n\n/** A requested output already exists and replacing it was not asked for. */\nexport class CertificateExists extends Schema.TaggedError<\n\tCertificateExists,\n\t{ readonly brand: unique symbol }\n>()(\"CertificateExists\", { file: Schema.String }) {\n\toverride get message() {\n\t\treturn `${this.file} already exists; use --force to replace the requested certificates`\n\t}\n}\n\n/** Only PEM leaves this boundary; PKI.js objects stay local to each operation. */\nexport interface Pem {\n\treadonly certificate: string\n\treadonly privateKey: Redacted.Redacted<string>\n}\nexport interface IssueOptions {\n\treadonly name: string\n\treadonly days: number\n\treadonly usage: \"ca\" | \"server\" | \"client\"\n\treadonly hosts?: ReadonlyArray<string>\n\treadonly identities?: ReadonlyArray<string>\n\treadonly issuer?: Pem\n}\nconst pem = (label: string, bytes: ArrayBuffer) =>\n\t`-----BEGIN ${label}-----\\n${String.replace(/.{64}(?=.)/g, \"$&\\n\")(Base64.encode(new Uint8Array(bytes)))}\\n-----END ${label}-----\\n`\n// WebCrypto and PKI.js take ArrayBuffer-backed bytes, so the decoded view is copied into one.\nconst der = (value: string) =>\n\tEffect.fromResult(\n\t\tBase64.decode(String.replace(/-----[^-]+-----|\\s/g, \"\")(value)),\n\t).pipe(Effect.map((bytes) => new Uint8Array(bytes)))\nconst subject = (name: string) =>\n\tnew pki.RelativeDistinguishedNames({\n\t\ttypesAndValues: [\n\t\t\tnew pki.AttributeTypeAndValue({\n\t\t\t\ttype: \"2.5.4.3\",\n\t\t\t\tvalue: new asn1js.Utf8String({ value: name }),\n\t\t\t}),\n\t\t],\n\t})\nconst hostName = (host: string) =>\n\tResult.match(NetAddress.ipFromString(host), {\n\t\tonFailure: () => new pki.GeneralName({ type: 2, value: host }),\n\t\tonSuccess: (ip) =>\n\t\t\tnew pki.GeneralName({\n\t\t\t\ttype: 7,\n\t\t\t\tvalue: new asn1js.OctetString({\n\t\t\t\t\tvalueHex: new Uint8Array(\n\t\t\t\t\t\tip._tag === \"Ipv4Address\"\n\t\t\t\t\t\t\t? NetAddress.ipv4ToOctets(ip)\n\t\t\t\t\t\t\t: NetAddress.ipv6ToOctets(ip),\n\t\t\t\t\t),\n\t\t\t\t}),\n\t\t\t}),\n\t})\n\nexport const issue = Effect.fn(\"Certificates.issue\")(function* (\n\toptions: IssueOptions,\n) {\n\tconst random = yield* SecureRandom.SecureRandom\n\tconst serial = yield* random.randomBytes(19)\n\tconst now = yield* DateTime.now\n\tconst webcrypto = yield* WebCrypto.WebCrypto\n\tconst engine = new pki.CryptoEngine({\n\t\tname: \"Node WebCrypto\",\n\t\tcrypto: webcrypto,\n\t})\n\tconst failure = (cause: unknown) =>\n\t\tCertificateError.make({\n\t\t\tdetail: `Could not issue the certificate for ${options.name}`,\n\t\t\tcause,\n\t\t})\n\tconst keys = yield* Effect.tryPromise({\n\t\ttry: () =>\n\t\t\twebcrypto.subtle.generateKey(\n\t\t\t\t{ name: \"ECDSA\", namedCurve: \"P-256\" },\n\t\t\t\ttrue,\n\t\t\t\t[\"sign\", \"verify\"],\n\t\t\t),\n\t\tcatch: failure,\n\t})\n\t// Reused CA keys have the same P-256 / PKCS#8 format as the ones this command creates.\n\tconst authority =\n\t\toptions.issuer === undefined\n\t\t\t? undefined\n\t\t\t: {\n\t\t\t\t\tcertificate: yield* Effect.mapError(\n\t\t\t\t\t\tder(options.issuer.certificate),\n\t\t\t\t\t\tfailure,\n\t\t\t\t\t),\n\t\t\t\t\tprivateKey: yield* Effect.mapError(\n\t\t\t\t\t\tder(Redacted.value(options.issuer.privateKey)),\n\t\t\t\t\t\tfailure,\n\t\t\t\t\t),\n\t\t\t\t}\n\tconst signingKey =\n\t\tauthority === undefined\n\t\t\t? keys.privateKey\n\t\t\t: yield* Effect.tryPromise({\n\t\t\t\t\ttry: () =>\n\t\t\t\t\t\twebcrypto.subtle.importKey(\n\t\t\t\t\t\t\t\"pkcs8\",\n\t\t\t\t\t\t\tauthority.privateKey,\n\t\t\t\t\t\t\t{ name: \"ECDSA\", namedCurve: \"P-256\" },\n\t\t\t\t\t\t\tfalse,\n\t\t\t\t\t\t\t[\"sign\"],\n\t\t\t\t\t\t),\n\t\t\t\t\tcatch: failure,\n\t\t\t\t})\n\tconst certificate = yield* Effect.try({\n\t\ttry: () => {\n\t\t\tconst issuer =\n\t\t\t\tauthority === undefined\n\t\t\t\t\t? undefined\n\t\t\t\t\t: pki.Certificate.fromBER(authority.certificate)\n\t\t\tconst names = [\n\t\t\t\t...Array.map(options.hosts ?? [], hostName),\n\t\t\t\t...Array.map(\n\t\t\t\t\toptions.identities ?? [],\n\t\t\t\t\t(identity) =>\n\t\t\t\t\t\tnew pki.GeneralName({ type: 6, value: `graft://${identity}` }),\n\t\t\t\t),\n\t\t\t]\n\t\t\treturn new pki.Certificate({\n\t\t\t\tversion: 2,\n\t\t\t\t// A leading nonzero byte keeps the serial positive without losing random bits.\n\t\t\t\tserialNumber: new asn1js.Integer({\n\t\t\t\t\tvalueHex: new Uint8Array([1, ...serial]),\n\t\t\t\t}),\n\t\t\t\tsubject: subject(options.name),\n\t\t\t\tissuer: issuer?.subject ?? subject(options.name),\n\t\t\t\tnotBefore: new pki.Time({ value: DateTime.toDateUtc(now) }),\n\t\t\t\tnotAfter: new pki.Time({\n\t\t\t\t\tvalue: DateTime.toDateUtc(DateTime.add(now, { days: options.days })),\n\t\t\t\t}),\n\t\t\t\textensions: [\n\t\t\t\t\tnew pki.Extension({\n\t\t\t\t\t\textnID: \"2.5.29.19\",\n\t\t\t\t\t\tcritical: true,\n\t\t\t\t\t\textnValue: new pki.BasicConstraints({ cA: options.usage === \"ca\" })\n\t\t\t\t\t\t\t.toSchema()\n\t\t\t\t\t\t\t.toBER(),\n\t\t\t\t\t}),\n\t\t\t\t\tnew pki.Extension({\n\t\t\t\t\t\textnID: \"2.5.29.15\",\n\t\t\t\t\t\tcritical: true,\n\t\t\t\t\t\textnValue: new asn1js.BitString({\n\t\t\t\t\t\t\tvalueHex: new Uint8Array([options.usage === \"ca\" ? 0x06 : 0x80]),\n\t\t\t\t\t\t}).toBER(),\n\t\t\t\t\t}),\n\t\t\t\t\t...(options.usage === \"ca\"\n\t\t\t\t\t\t? []\n\t\t\t\t\t\t: [\n\t\t\t\t\t\t\t\tnew pki.Extension({\n\t\t\t\t\t\t\t\t\textnID: \"2.5.29.37\",\n\t\t\t\t\t\t\t\t\textnValue: new pki.ExtKeyUsage({\n\t\t\t\t\t\t\t\t\t\tkeyPurposes: [\n\t\t\t\t\t\t\t\t\t\t\toptions.usage === \"server\"\n\t\t\t\t\t\t\t\t\t\t\t\t? \"1.3.6.1.5.5.7.3.1\"\n\t\t\t\t\t\t\t\t\t\t\t\t: \"1.3.6.1.5.5.7.3.2\",\n\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t\t\t.toSchema()\n\t\t\t\t\t\t\t\t\t\t.toBER(),\n\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t]),\n\t\t\t\t\t...(names.length === 0\n\t\t\t\t\t\t? []\n\t\t\t\t\t\t: [\n\t\t\t\t\t\t\t\tnew pki.Extension({\n\t\t\t\t\t\t\t\t\textnID: \"2.5.29.17\",\n\t\t\t\t\t\t\t\t\textnValue: new pki.AltName({ altNames: names })\n\t\t\t\t\t\t\t\t\t\t.toSchema()\n\t\t\t\t\t\t\t\t\t\t.toBER(),\n\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t]),\n\t\t\t\t],\n\t\t\t})\n\t\t},\n\t\tcatch: failure,\n\t})\n\tyield* Effect.tryPromise({\n\t\ttry: () =>\n\t\t\tcertificate.subjectPublicKeyInfo.importKey(keys.publicKey, engine),\n\t\tcatch: failure,\n\t})\n\tyield* Effect.tryPromise({\n\t\ttry: () => certificate.sign(signingKey, \"SHA-256\", engine),\n\t\tcatch: failure,\n\t})\n\tconst privateKey = yield* Effect.tryPromise({\n\t\ttry: () => webcrypto.subtle.exportKey(\"pkcs8\", keys.privateKey),\n\t\tcatch: failure,\n\t})\n\treturn yield* Effect.try({\n\t\ttry: () => ({\n\t\t\tcertificate: pem(\"CERTIFICATE\", certificate.toSchema().toBER()),\n\t\t\tprivateKey: Redacted.make(pem(\"PRIVATE KEY\", privateKey)),\n\t\t}),\n\t\tcatch: failure,\n\t})\n})\n\nexport const read = Effect.fn(\"Certificates.read\")(function* (base: string) {\n\tconst fs = yield* FileSystem.FileSystem\n\tconst certificate = yield* fs.readFileString(base + \".crt\")\n\tconst privateKey = yield* fs.readFileString(base + \".key\")\n\treturn { certificate, privateKey: Redacted.make(privateKey) }\n})\nexport const write = Effect.fn(\"Certificates.write\")(function* (\n\tbase: string,\n\tpair: Pem,\n\tforce: boolean = false,\n) {\n\tconst fs = yield* FileSystem.FileSystem\n\tyield* fs\n\t\t.writeFileString(base + \".key\", Redacted.value(pair.privateKey), {\n\t\t\tflag: force ? \"w\" : \"wx\",\n\t\t\tmode: 0o600,\n\t\t})\n\t\t.pipe(Effect.uninterruptible)\n\t// Opening an existing file does not change its permissions when renewing it.\n\tyield* fs.chmod(base + \".key\", 0o600).pipe(Effect.uninterruptible)\n\tyield* fs\n\t\t.writeFileString(base + \".crt\", pair.certificate, {\n\t\t\tflag: force ? \"w\" : \"wx\",\n\t\t})\n\t\t.pipe(Effect.uninterruptible)\n})\n\nexport interface Options {\n\treadonly out: string\n\treadonly server: ReadonlyArray<string>\n\treadonly identity: ReadonlyArray<string>\n\treadonly days: number\n\treadonly force: boolean\n}\n/** URI-encode names so each identity has a distinct filename, including names with slashes. */\nexport const clientName = (identity: string) =>\n\t`client-${encodeURIComponent(identity)}`\nexport const generate = Effect.fn(\"Certificates.generate\")(function* (\n\toptions: Options,\n) {\n\tconst fs = yield* FileSystem.FileSystem\n\tconst path = yield* Path.Path\n\tconst outputs = [\n\t\t...(options.server.length === 0 ? [] : [\"server\"]),\n\t\t...Array.map(Array.dedupe(options.identity), clientName),\n\t]\n\tif (!options.force) {\n\t\tconst files = Array.flatMap(outputs, (name) =>\n\t\t\tArray.map([\".crt\", \".key\"], (extension) =>\n\t\t\t\tpath.join(options.out, name + extension),\n\t\t\t),\n\t\t)\n\t\tconst taken = yield* Effect.filter(files, fs.exists)\n\t\tif (Array.isReadonlyArrayNonEmpty(taken))\n\t\t\treturn yield* CertificateExists.make({ file: taken[0] })\n\t}\n\tyield* fs\n\t\t.makeDirectory(options.out, { recursive: true })\n\t\t.pipe(Effect.uninterruptible)\n\tconst ca = path.join(options.out, \"ca\")\n\tconst existing =\n\t\t(yield* fs.exists(ca + \".crt\")) || (yield* fs.exists(ca + \".key\"))\n\t// An incomplete CA pair fails on read. Even --force never replaces the signing authority.\n\tconst issuer = existing\n\t\t? yield* read(ca)\n\t\t: yield* issue({ name: \"Graft CA\", usage: \"ca\", days: options.days }).pipe(\n\t\t\t\tEffect.tap((pair) => write(ca, pair)),\n\t\t\t)\n\tif (options.server.length > 0) {\n\t\tconst pair = yield* issue({\n\t\t\tname: \"Graft runner\",\n\t\t\tusage: \"server\",\n\t\t\thosts: options.server,\n\t\t\tdays: options.days,\n\t\t\tissuer,\n\t\t})\n\t\tyield* write(path.join(options.out, \"server\"), pair, options.force)\n\t}\n\tyield* Effect.forEach(\n\t\tArray.dedupe(options.identity),\n\t\t(identity) =>\n\t\t\tissue({\n\t\t\t\tname: identity,\n\t\t\t\tusage: \"client\",\n\t\t\t\tidentities: [identity],\n\t\t\t\tdays: options.days,\n\t\t\t\tissuer,\n\t\t\t}).pipe(\n\t\t\t\tEffect.flatMap((pair) =>\n\t\t\t\t\twrite(\n\t\t\t\t\t\tpath.join(options.out, clientName(identity)),\n\t\t\t\t\t\tpair,\n\t\t\t\t\t\toptions.force,\n\t\t\t\t\t),\n\t\t\t\t),\n\t\t\t),\n\t\t{ discard: true },\n\t)\n})\n"],"mappings":"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"}
1
+ {"version":3,"file":"Certificates.js","names":[],"sources":["../../src/internal/Certificates.ts"],"sourcesContent":["import {\n\tArray,\n\tDateTime,\n\tEffect,\n\tFileSystem,\n\tPath,\n\tRedacted,\n\tResult,\n\tSchema,\n\tString,\n} from \"effect\"\nimport { SecureRandom, WebCrypto } from \"effect/crypto\"\nimport { Base64 } from \"effect/encoding\"\nimport { NetAddress } from \"effect/net\"\nimport * as asn1js from \"asn1js\"\nimport * as pki from \"pkijs\"\n\nexport class CertificateError extends Schema.TaggedError<\n\tCertificateError,\n\t{ readonly brand: unique symbol }\n>()(\"CertificateError\", {\n\tdetail: Schema.String,\n\tcause: Schema.optional(Schema.Defect()),\n}) {\n\toverride get message() {\n\t\treturn this.detail\n\t}\n}\n\n/** A requested output already exists and replacing it was not asked for. */\nexport class CertificateExists extends Schema.TaggedError<\n\tCertificateExists,\n\t{ readonly brand: unique symbol }\n>()(\"CertificateExists\", { file: Schema.String }) {\n\toverride get message() {\n\t\treturn `${this.file} already exists; use --force to replace the requested certificates`\n\t}\n}\n\n/** Only PEM leaves this boundary; PKI.js objects stay local to each operation. */\nexport interface Pem {\n\treadonly certificate: string\n\treadonly privateKey: Redacted.Redacted<string>\n}\nexport interface IssueOptions {\n\treadonly name: string\n\treadonly days: number\n\treadonly usage: \"ca\" | \"server\" | \"client\"\n\treadonly hosts?: ReadonlyArray<string>\n\treadonly identities?: ReadonlyArray<string>\n\treadonly issuer?: Pem\n}\nconst pem = (label: string, bytes: ArrayBuffer) =>\n\t`-----BEGIN ${label}-----\\n${String.replace(/.{64}(?=.)/g, \"$&\\n\")(Base64.encode(new Uint8Array(bytes)))}\\n-----END ${label}-----\\n`\n// WebCrypto and PKI.js take ArrayBuffer-backed bytes, so the decoded view is copied into one.\nconst der = (value: string) =>\n\tEffect.fromResult(\n\t\tBase64.decode(String.replace(/-----[^-]+-----|\\s/g, \"\")(value)),\n\t).pipe(Effect.map((bytes) => new Uint8Array(bytes)))\nconst subject = (name: string) =>\n\tnew pki.RelativeDistinguishedNames({\n\t\ttypesAndValues: [\n\t\t\tnew pki.AttributeTypeAndValue({\n\t\t\t\ttype: \"2.5.4.3\",\n\t\t\t\tvalue: new asn1js.Utf8String({ value: name }),\n\t\t\t}),\n\t\t],\n\t})\nconst hostName = (host: string) =>\n\tResult.match(NetAddress.ipFromString(host), {\n\t\tonFailure: () => new pki.GeneralName({ type: 2, value: host }),\n\t\tonSuccess: (ip) =>\n\t\t\tnew pki.GeneralName({\n\t\t\t\ttype: 7,\n\t\t\t\tvalue: new asn1js.OctetString({\n\t\t\t\t\tvalueHex: new Uint8Array(\n\t\t\t\t\t\tip._tag === \"Ipv4Address\"\n\t\t\t\t\t\t\t? NetAddress.ipv4ToOctets(ip)\n\t\t\t\t\t\t\t: NetAddress.ipv6ToOctets(ip),\n\t\t\t\t\t),\n\t\t\t\t}),\n\t\t\t}),\n\t})\n\nexport const issue = Effect.fn(\"Certificates.issue\")(function* (\n\toptions: IssueOptions,\n) {\n\tconst random = yield* SecureRandom.SecureRandom\n\tconst serial = yield* random.randomBytes(19)\n\tconst now = yield* DateTime.now\n\tconst webcrypto = yield* WebCrypto.WebCrypto\n\tconst engine = new pki.CryptoEngine({\n\t\tname: \"Node WebCrypto\",\n\t\tcrypto: webcrypto,\n\t})\n\tconst failure = (cause: unknown) =>\n\t\tCertificateError.make({\n\t\t\tdetail: `Could not issue the certificate for ${options.name}`,\n\t\t\tcause,\n\t\t})\n\tconst keys = yield* Effect.tryPromise({\n\t\ttry: () =>\n\t\t\twebcrypto.subtle.generateKey(\n\t\t\t\t{ name: \"ECDSA\", namedCurve: \"P-256\" },\n\t\t\t\ttrue,\n\t\t\t\t[\"sign\", \"verify\"],\n\t\t\t),\n\t\tcatch: failure,\n\t})\n\t// Reused CA keys have the same P-256 / PKCS#8 format as the ones this command creates.\n\tconst authority =\n\t\toptions.issuer === undefined\n\t\t\t? undefined\n\t\t\t: {\n\t\t\t\t\tcertificate: yield* Effect.mapError(\n\t\t\t\t\t\tder(options.issuer.certificate),\n\t\t\t\t\t\tfailure,\n\t\t\t\t\t),\n\t\t\t\t\tprivateKey: yield* Effect.mapError(\n\t\t\t\t\t\tder(Redacted.value(options.issuer.privateKey)),\n\t\t\t\t\t\tfailure,\n\t\t\t\t\t),\n\t\t\t\t}\n\tconst signingKey =\n\t\tauthority === undefined\n\t\t\t? keys.privateKey\n\t\t\t: yield* Effect.tryPromise({\n\t\t\t\t\ttry: () =>\n\t\t\t\t\t\twebcrypto.subtle.importKey(\n\t\t\t\t\t\t\t\"pkcs8\",\n\t\t\t\t\t\t\tauthority.privateKey,\n\t\t\t\t\t\t\t{ name: \"ECDSA\", namedCurve: \"P-256\" },\n\t\t\t\t\t\t\tfalse,\n\t\t\t\t\t\t\t[\"sign\"],\n\t\t\t\t\t\t),\n\t\t\t\t\tcatch: failure,\n\t\t\t\t})\n\tconst certificate = yield* Effect.try({\n\t\ttry: () => {\n\t\t\tconst issuer =\n\t\t\t\tauthority === undefined\n\t\t\t\t\t? undefined\n\t\t\t\t\t: pki.Certificate.fromBER(authority.certificate)\n\t\t\tconst names = [\n\t\t\t\t...Array.map(options.hosts ?? [], hostName),\n\t\t\t\t...Array.map(\n\t\t\t\t\toptions.identities ?? [],\n\t\t\t\t\t(identity) =>\n\t\t\t\t\t\tnew pki.GeneralName({ type: 6, value: `graft://${identity}` }),\n\t\t\t\t),\n\t\t\t]\n\t\t\treturn new pki.Certificate({\n\t\t\t\tversion: 2,\n\t\t\t\t// A leading nonzero byte keeps the serial positive without losing random bits.\n\t\t\t\tserialNumber: new asn1js.Integer({\n\t\t\t\t\tvalueHex: new Uint8Array([1, ...serial]),\n\t\t\t\t}),\n\t\t\t\tsubject: subject(options.name),\n\t\t\t\tissuer: issuer?.subject ?? subject(options.name),\n\t\t\t\tnotBefore: new pki.Time({ value: DateTime.toDateUtc(now) }),\n\t\t\t\tnotAfter: new pki.Time({\n\t\t\t\t\tvalue: DateTime.toDateUtc(DateTime.add(now, { days: options.days })),\n\t\t\t\t}),\n\t\t\t\textensions: [\n\t\t\t\t\tnew pki.Extension({\n\t\t\t\t\t\textnID: \"2.5.29.19\",\n\t\t\t\t\t\tcritical: true,\n\t\t\t\t\t\textnValue: new pki.BasicConstraints({ cA: options.usage === \"ca\" })\n\t\t\t\t\t\t\t.toSchema()\n\t\t\t\t\t\t\t.toBER(),\n\t\t\t\t\t}),\n\t\t\t\t\tnew pki.Extension({\n\t\t\t\t\t\textnID: \"2.5.29.15\",\n\t\t\t\t\t\tcritical: true,\n\t\t\t\t\t\textnValue: new asn1js.BitString({\n\t\t\t\t\t\t\tvalueHex: new Uint8Array([options.usage === \"ca\" ? 0x06 : 0x80]),\n\t\t\t\t\t\t}).toBER(),\n\t\t\t\t\t}),\n\t\t\t\t\t...(options.usage === \"ca\"\n\t\t\t\t\t\t? []\n\t\t\t\t\t\t: [\n\t\t\t\t\t\t\t\tnew pki.Extension({\n\t\t\t\t\t\t\t\t\textnID: \"2.5.29.37\",\n\t\t\t\t\t\t\t\t\textnValue: new pki.ExtKeyUsage({\n\t\t\t\t\t\t\t\t\t\tkeyPurposes: [\n\t\t\t\t\t\t\t\t\t\t\toptions.usage === \"server\"\n\t\t\t\t\t\t\t\t\t\t\t\t? \"1.3.6.1.5.5.7.3.1\"\n\t\t\t\t\t\t\t\t\t\t\t\t: \"1.3.6.1.5.5.7.3.2\",\n\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t\t\t.toSchema()\n\t\t\t\t\t\t\t\t\t\t.toBER(),\n\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t]),\n\t\t\t\t\t...(names.length === 0\n\t\t\t\t\t\t? []\n\t\t\t\t\t\t: [\n\t\t\t\t\t\t\t\tnew pki.Extension({\n\t\t\t\t\t\t\t\t\textnID: \"2.5.29.17\",\n\t\t\t\t\t\t\t\t\textnValue: new pki.AltName({ altNames: names })\n\t\t\t\t\t\t\t\t\t\t.toSchema()\n\t\t\t\t\t\t\t\t\t\t.toBER(),\n\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t]),\n\t\t\t\t],\n\t\t\t})\n\t\t},\n\t\tcatch: failure,\n\t})\n\tyield* Effect.tryPromise({\n\t\ttry: () =>\n\t\t\tcertificate.subjectPublicKeyInfo.importKey(keys.publicKey, engine),\n\t\tcatch: failure,\n\t})\n\tyield* Effect.tryPromise({\n\t\ttry: () => certificate.sign(signingKey, \"SHA-256\", engine),\n\t\tcatch: failure,\n\t})\n\tconst privateKey = yield* Effect.tryPromise({\n\t\ttry: () => webcrypto.subtle.exportKey(\"pkcs8\", keys.privateKey),\n\t\tcatch: failure,\n\t})\n\treturn yield* Effect.try({\n\t\ttry: () => ({\n\t\t\tcertificate: pem(\"CERTIFICATE\", certificate.toSchema().toBER()),\n\t\t\tprivateKey: Redacted.make(pem(\"PRIVATE KEY\", privateKey)),\n\t\t}),\n\t\tcatch: failure,\n\t})\n})\n\nexport const read = Effect.fn(\"Certificates.read\")(function* (base: string) {\n\tconst fs = yield* FileSystem.FileSystem\n\tconst certificate = yield* fs.readFileString(base + \".crt\")\n\tconst privateKey = yield* fs.readFileString(base + \".key\")\n\treturn { certificate, privateKey: Redacted.make(privateKey) }\n})\nexport const write = Effect.fn(\"Certificates.write\")(function* (\n\tbase: string,\n\tpair: Pem,\n\tforce: boolean = false,\n) {\n\tconst fs = yield* FileSystem.FileSystem\n\tyield* fs.writeFileString(base + \".key\", Redacted.value(pair.privateKey), {\n\t\tflag: force ? \"w\" : \"wx\",\n\t\tmode: 0o600,\n\t})\n\t// Opening an existing file does not change its permissions when renewing it.\n\tyield* fs.chmod(base + \".key\", 0o600)\n\tyield* fs.writeFileString(base + \".crt\", pair.certificate, {\n\t\tflag: force ? \"w\" : \"wx\",\n\t})\n\t// One region for the pair: an interruption between the files would leave a key without its certificate.\n}, Effect.uninterruptible)\n\nexport interface Options {\n\treadonly out: string\n\treadonly server: ReadonlyArray<string>\n\treadonly identity: ReadonlyArray<string>\n\treadonly days: number\n\treadonly force: boolean\n}\n/** URI-encode names so each identity has a distinct filename, including names with slashes. */\nexport const clientName = (identity: string) =>\n\t`client-${encodeURIComponent(identity)}`\nexport const generate = Effect.fn(\"Certificates.generate\")(function* (\n\toptions: Options,\n) {\n\tconst fs = yield* FileSystem.FileSystem\n\tconst path = yield* Path.Path\n\tconst outputs = [\n\t\t...(options.server.length === 0 ? [] : [\"server\"]),\n\t\t...Array.map(Array.dedupe(options.identity), clientName),\n\t]\n\tif (!options.force) {\n\t\tconst files = Array.flatMap(outputs, (name) =>\n\t\t\tArray.map([\".crt\", \".key\"], (extension) =>\n\t\t\t\tpath.join(options.out, name + extension),\n\t\t\t),\n\t\t)\n\t\tconst taken = yield* Effect.filter(files, fs.exists)\n\t\tif (Array.isReadonlyArrayNonEmpty(taken))\n\t\t\treturn yield* CertificateExists.make({ file: taken[0] })\n\t}\n\tyield* fs\n\t\t.makeDirectory(options.out, { recursive: true })\n\t\t.pipe(Effect.uninterruptible)\n\tconst ca = path.join(options.out, \"ca\")\n\tconst existing =\n\t\t(yield* fs.exists(ca + \".crt\")) || (yield* fs.exists(ca + \".key\"))\n\t// An incomplete CA pair fails on read. Even --force never replaces the signing authority.\n\tconst issuer = existing\n\t\t? yield* read(ca)\n\t\t: yield* issue({ name: \"Graft CA\", usage: \"ca\", days: options.days }).pipe(\n\t\t\t\tEffect.tap((pair) => write(ca, pair)),\n\t\t\t)\n\tif (options.server.length > 0) {\n\t\tconst pair = yield* issue({\n\t\t\tname: \"Graft runner\",\n\t\t\tusage: \"server\",\n\t\t\thosts: options.server,\n\t\t\tdays: options.days,\n\t\t\tissuer,\n\t\t})\n\t\tyield* write(path.join(options.out, \"server\"), pair, options.force)\n\t}\n\tyield* Effect.forEach(\n\t\tArray.dedupe(options.identity),\n\t\t(identity) =>\n\t\t\tissue({\n\t\t\t\tname: identity,\n\t\t\t\tusage: \"client\",\n\t\t\t\tidentities: [identity],\n\t\t\t\tdays: options.days,\n\t\t\t\tissuer,\n\t\t\t}).pipe(\n\t\t\t\tEffect.flatMap((pair) =>\n\t\t\t\t\twrite(\n\t\t\t\t\t\tpath.join(options.out, clientName(identity)),\n\t\t\t\t\t\tpair,\n\t\t\t\t\t\toptions.force,\n\t\t\t\t\t),\n\t\t\t\t),\n\t\t\t),\n\t\t{ discard: true },\n\t)\n})\n"],"mappings":"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"}
@@ -1,9 +1,10 @@
1
1
  import { ReleaseInterrupted, close } from "./release.js";
2
+ import { cleanupCause } from "./cleanup.js";
2
3
  import { Array, Cause, Data, Deferred, Effect, Exit, Fiber, FiberSet, Ref, Schema, Scope, TxRef } from "effect";
3
4
  // src/internal/FailureGroup.ts
4
5
  const State = Data.taggedEnum();
5
6
  /** One owner for first failure, transaction wakeups, and interruption of sibling work. */
6
- const make = () => Effect.gen(function* () {
7
+ const make = Effect.fnUntraced(function* () {
7
8
  const fibers = yield* FiberSet.make();
8
9
  const state = yield* TxRef.make(State.Open());
9
10
  const failures = yield* Ref.make(Cause.empty);
@@ -37,7 +38,7 @@ const make = () => Effect.gen(function* () {
37
38
  const failure = Effect.tx(check.pipe(Effect.andThen(Effect.txRetry)));
38
39
  const failCause = (cause) => FiberSet.run(fibers, observe(Effect.failCause(cause))).pipe(Effect.asVoid);
39
40
  const close$1 = TxRef.update(state, (s) => s._tag === "Open" ? State.Closed() : s).pipe(Effect.andThen(FiberSet.clear(fibers)), Effect.andThen(Ref.get(cleanup)), Effect.flatMap((cause) => cause.reasons.length > 0 ? Effect.failCause(cause) : Effect.void), Effect.uninterruptible);
40
- yield* Effect.addFinalizer(() => close$1.pipe(Effect.orDie));
41
+ yield* Effect.addFinalizer(() => close$1.pipe(Effect.catchCause((cause) => Effect.failCause(cleanupCause(cause)))));
41
42
  return {
42
43
  await: failure,
43
44
  check,
@@ -1 +1 @@
1
- {"version":3,"file":"FailureGroup.js","names":["Release.close","Release.ReleaseInterrupted","close"],"sources":["../../src/internal/FailureGroup.ts"],"sourcesContent":["import {\n\tArray,\n\tCause,\n\tFiber,\n\tData,\n\tDeferred,\n\tEffect,\n\tExit,\n\tFiberSet,\n\tRef,\n\tScope,\n\tSchema,\n\tTxRef,\n} from \"effect\"\nimport * as Release from \"./release\"\n\ntype State<E> = Data.TaggedEnum<{\n\tOpen: {}\n\tFailed: { readonly cause: Cause.Cause<E> }\n\tClosed: {}\n}>\ninterface StateDefinition extends Data.TaggedEnum.WithGenerics<1> {\n\treadonly taggedEnum: State<this[\"A\"]>\n}\nconst State = Data.taggedEnum<StateDefinition>()\nexport interface FailureGroup<E> {\n\treadonly await: Effect.Effect<never, E>\n\treadonly check: Effect.Effect<void, E>\n\treadonly cause: Effect.Effect<Cause.Cause<E>>\n\treadonly run: <A, R>(\n\t\teffect: Effect.Effect<A, E, R>,\n\t) => Effect.Effect<Fiber.Fiber<A, E>, never, R>\n\treadonly fail: (error: E) => Effect.Effect<void>\n\treadonly failCause: (cause: Cause.Cause<E>) => Effect.Effect<void>\n\treadonly race: <A, E2, R>(\n\t\teffect: Effect.Effect<A, E2, R>,\n\t) => Effect.Effect<A, E | E2, R>\n\treadonly runtime: <R>() => Effect.Effect<\n\t\t(effect: Effect.Effect<unknown, E, R>) => Fiber.Fiber<unknown, E>,\n\t\tnever,\n\t\tR\n\t>\n\treadonly close: Effect.Effect<void, E>\n}\n\n/** One owner for first failure, transaction wakeups, and interruption of sibling work. */\nexport const make = <E>(): Effect.Effect<FailureGroup<E>, never, Scope.Scope> =>\n\tEffect.gen(function* () {\n\t\tconst fibers = yield* FiberSet.make<unknown, E>()\n\t\tconst state = yield* TxRef.make<State<E>>(State.Open())\n\t\tconst failures = yield* Ref.make<Cause.Cause<E>>(Cause.empty)\n\t\tconst cleanup = yield* Ref.make<Cause.Cause<E>>(Cause.empty)\n\t\tconst check = TxRef.get(state).pipe(\n\t\t\tEffect.flatMap((s) =>\n\t\t\t\ts._tag === \"Failed\"\n\t\t\t\t\t? Effect.failCause(s.cause)\n\t\t\t\t\t: s._tag === \"Closed\"\n\t\t\t\t\t\t? Effect.interrupt\n\t\t\t\t\t\t: Effect.void,\n\t\t\t),\n\t\t)\n\t\tconst publish = (cause: Cause.Cause<E>) =>\n\t\t\tTxRef.update(state, (s): State<E> =>\n\t\t\t\ts._tag === \"Open\" ? State.Failed({ cause }) : s,\n\t\t\t)\n\n\t\tconst observe = <A, R>(effect: Effect.Effect<A, E, R>) =>\n\t\t\tEffect.uninterruptibleMask((restore) =>\n\t\t\t\tEffect.gen(function* () {\n\t\t\t\t\tconst scope = yield* Scope.make()\n\t\t\t\t\t// The owned child makes cancellation explicit, even when a stream closes an internal scope.\n\t\t\t\t\tconst ownerId = yield* Effect.withFiber((self) =>\n\t\t\t\t\t\tEffect.succeed(self.id),\n\t\t\t\t\t)\n\t\t\t\t\tconst worker = yield* Effect.forkIn(\n\t\t\t\t\t\trestore(Scope.provide(scope)(effect)),\n\t\t\t\t\t\tscope,\n\t\t\t\t\t)\n\t\t\t\t\tconst waiting = yield* Effect.exit(restore(Fiber.await(worker)))\n\t\t\t\t\tif (Exit.isFailure(waiting)) yield* Fiber.interrupt(worker)\n\t\t\t\t\tconst body = yield* Fiber.await(worker)\n\t\t\t\t\tconst closed = yield* Effect.exit(Release.close(scope, body))\n\t\t\t\t\t// Forwarding this exact cancellation from a finalizer is indistinguishable from acknowledging it.\n\t\t\t\t\tconst expected =\n\t\t\t\t\t\tExit.isFailure(waiting) &&\n\t\t\t\t\t\tExit.isFailure(body) &&\n\t\t\t\t\t\tArray.every(\n\t\t\t\t\t\t\tbody.cause.reasons,\n\t\t\t\t\t\t\t(reason) =>\n\t\t\t\t\t\t\t\treason._tag === \"Interrupt\" && reason.fiberId === ownerId,\n\t\t\t\t\t\t)\n\t\t\t\t\tconst bodyCause =\n\t\t\t\t\t\tExit.isFailure(body) && !expected ? body.cause : Cause.empty\n\t\t\t\t\t// Release.close marks independent interruptions; an unmarked one is pending cancellation.\n\t\t\t\t\tconst releaseCause =\n\t\t\t\t\t\tExit.isFailure(closed) && !Cause.hasInterruptsOnly(closed.cause)\n\t\t\t\t\t\t\t? closed.cause\n\t\t\t\t\t\t\t: Cause.empty\n\t\t\t\t\tconst failure = Cause.combine(bodyCause, releaseCause)\n\t\t\t\t\t// Body cleanup may carry either an interruption or a release defect from an inner group.\n\t\t\t\t\tconst closing = Cause.combine(\n\t\t\t\t\t\tCause.hasInterrupts(bodyCause) ||\n\t\t\t\t\t\t\tArray.some(\n\t\t\t\t\t\t\t\tbodyCause.reasons,\n\t\t\t\t\t\t\t\t(reason) =>\n\t\t\t\t\t\t\t\t\treason._tag === \"Die\" &&\n\t\t\t\t\t\t\t\t\tSchema.is(Release.ReleaseInterrupted)(reason.defect),\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t? bodyCause\n\t\t\t\t\t\t\t: Cause.empty,\n\t\t\t\t\t\treleaseCause,\n\t\t\t\t\t)\n\t\t\t\t\tyield* Ref.update(cleanup, (cause) => Cause.combine(cause, closing))\n\t\t\t\t\tif (failure.reasons.length > 0) {\n\t\t\t\t\t\tyield* Ref.update(failures, (cause) =>\n\t\t\t\t\t\t\tCause.combine(cause, failure),\n\t\t\t\t\t\t)\n\t\t\t\t\t\tyield* publish(failure)\n\t\t\t\t\t\tyield* Deferred.failCause(fibers.deferred, failure)\n\t\t\t\t\t}\n\t\t\t\t\tif (Exit.isFailure(closed))\n\t\t\t\t\t\treturn yield* Effect.failCause(\n\t\t\t\t\t\t\tExit.isFailure(body)\n\t\t\t\t\t\t\t\t? Cause.combine(body.cause, closed.cause)\n\t\t\t\t\t\t\t\t: closed.cause,\n\t\t\t\t\t\t)\n\t\t\t\t\tif (Exit.isFailure(waiting) && Exit.isSuccess(body))\n\t\t\t\t\t\treturn yield* Effect.failCause(waiting.cause)\n\t\t\t\t\treturn yield* body\n\t\t\t\t}),\n\t\t\t)\n\t\tyield* FiberSet.join(fibers).pipe(\n\t\t\tEffect.catchCause((cause) =>\n\t\t\t\tpublish(cause).pipe(\n\t\t\t\t\tEffect.andThen(FiberSet.clear(fibers)),\n\t\t\t\t\tEffect.uninterruptible,\n\t\t\t\t),\n\t\t\t),\n\t\t\tEffect.forkScoped,\n\t\t)\n\t\tconst failure = Effect.tx(check.pipe(Effect.andThen(Effect.txRetry)))\n\t\tconst failCause = (cause: Cause.Cause<E>) =>\n\t\t\t// This is an explicit failure report, not cancellation of an owned worker.\n\t\t\tFiberSet.run(fibers, observe(Effect.failCause(cause))).pipe(Effect.asVoid)\n\t\tconst close = TxRef.update(state, (s) =>\n\t\t\ts._tag === \"Open\" ? State.Closed() : s,\n\t\t).pipe(\n\t\t\tEffect.andThen(FiberSet.clear(fibers)),\n\t\t\tEffect.andThen(Ref.get(cleanup)),\n\t\t\tEffect.flatMap((cause) =>\n\t\t\t\tcause.reasons.length > 0 ? Effect.failCause(cause) : Effect.void,\n\t\t\t),\n\t\t\tEffect.uninterruptible,\n\t\t)\n\t\t// Operational failure is delivered by await; release must also deliver sibling cleanup failures.\n\t\tyield* Effect.addFinalizer(() => close.pipe(Effect.orDie))\n\t\treturn {\n\t\t\tawait: failure,\n\t\t\tcheck,\n\t\t\tcause: Ref.get(failures),\n\t\t\truntime: <R>() =>\n\t\t\t\tFiberSet.runtime(fibers)<R>().pipe(\n\t\t\t\t\tEffect.map(\n\t\t\t\t\t\t(run) => (effect: Effect.Effect<unknown, E, R>) =>\n\t\t\t\t\t\t\trun(check.pipe(Effect.andThen(observe(effect)))),\n\t\t\t\t\t),\n\t\t\t\t),\n\t\t\trun: (effect) =>\n\t\t\t\tFiberSet.run(fibers, check.pipe(Effect.andThen(observe(effect)))),\n\t\t\tfail: (error) => failCause(Cause.fail(error)),\n\t\t\tfailCause,\n\t\t\trace: (effect) =>\n\t\t\t\tcheck.pipe(Effect.andThen(Effect.raceFirst(effect, failure))),\n\t\t\tclose,\n\t\t}\n\t})\n"],"mappings":"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"}
1
+ {"version":3,"file":"FailureGroup.js","names":["Release.close","Release.ReleaseInterrupted","close"],"sources":["../../src/internal/FailureGroup.ts"],"sourcesContent":["import {\n\tArray,\n\tCause,\n\tFiber,\n\tData,\n\tDeferred,\n\tEffect,\n\tExit,\n\tFiberSet,\n\tRef,\n\tScope,\n\tSchema,\n\tTxRef,\n} from \"effect\"\nimport * as Release from \"./release\"\nimport { cleanupCause } from \"./cleanup\"\n\ntype State<E> = Data.TaggedEnum<{\n\tOpen: {}\n\tFailed: { readonly cause: Cause.Cause<E> }\n\tClosed: {}\n}>\ninterface StateDefinition extends Data.TaggedEnum.WithGenerics<1> {\n\treadonly taggedEnum: State<this[\"A\"]>\n}\nconst State = Data.taggedEnum<StateDefinition>()\nexport interface FailureGroup<E> {\n\treadonly await: Effect.Effect<never, E>\n\treadonly check: Effect.Effect<void, E>\n\treadonly cause: Effect.Effect<Cause.Cause<E>>\n\treadonly run: <A, R>(\n\t\teffect: Effect.Effect<A, E, R>,\n\t) => Effect.Effect<Fiber.Fiber<A, E>, never, R>\n\treadonly fail: (error: E) => Effect.Effect<void>\n\treadonly failCause: (cause: Cause.Cause<E>) => Effect.Effect<void>\n\treadonly race: <A, E2, R>(\n\t\teffect: Effect.Effect<A, E2, R>,\n\t) => Effect.Effect<A, E | E2, R>\n\treadonly runtime: <R>() => Effect.Effect<\n\t\t(effect: Effect.Effect<unknown, E, R>) => Fiber.Fiber<unknown, E>,\n\t\tnever,\n\t\tR\n\t>\n\treadonly close: Effect.Effect<void, E>\n}\n\n/** One owner for first failure, transaction wakeups, and interruption of sibling work. */\nexport const make = Effect.fnUntraced(function* <E>(): Effect.fn.Return<\n\tFailureGroup<E>,\n\tnever,\n\tScope.Scope\n> {\n\tconst fibers = yield* FiberSet.make<unknown, E>()\n\tconst state = yield* TxRef.make<State<E>>(State.Open())\n\tconst failures = yield* Ref.make<Cause.Cause<E>>(Cause.empty)\n\tconst cleanup = yield* Ref.make<Cause.Cause<E>>(Cause.empty)\n\tconst check = TxRef.get(state).pipe(\n\t\tEffect.flatMap((s) =>\n\t\t\ts._tag === \"Failed\"\n\t\t\t\t? Effect.failCause(s.cause)\n\t\t\t\t: s._tag === \"Closed\"\n\t\t\t\t\t? Effect.interrupt\n\t\t\t\t\t: Effect.void,\n\t\t),\n\t)\n\tconst publish = (cause: Cause.Cause<E>) =>\n\t\tTxRef.update(state, (s): State<E> =>\n\t\t\ts._tag === \"Open\" ? State.Failed({ cause }) : s,\n\t\t)\n\n\tconst observe = <A, R>(effect: Effect.Effect<A, E, R>) =>\n\t\tEffect.uninterruptibleMask((restore) =>\n\t\t\tEffect.gen(function* () {\n\t\t\t\tconst scope = yield* Scope.make()\n\t\t\t\t// The owned child makes cancellation explicit, even when a stream closes an internal scope.\n\t\t\t\tconst ownerId = yield* Effect.withFiber((self) =>\n\t\t\t\t\tEffect.succeed(self.id),\n\t\t\t\t)\n\t\t\t\tconst worker = yield* Effect.forkIn(\n\t\t\t\t\trestore(Scope.provide(scope)(effect)),\n\t\t\t\t\tscope,\n\t\t\t\t)\n\t\t\t\tconst waiting = yield* Effect.exit(restore(Fiber.await(worker)))\n\t\t\t\tif (Exit.isFailure(waiting)) yield* Fiber.interrupt(worker)\n\t\t\t\tconst body = yield* Fiber.await(worker)\n\t\t\t\tconst closed = yield* Effect.exit(Release.close(scope, body))\n\t\t\t\t// Forwarding this exact cancellation from a finalizer is indistinguishable from acknowledging it.\n\t\t\t\tconst expected =\n\t\t\t\t\tExit.isFailure(waiting) &&\n\t\t\t\t\tExit.isFailure(body) &&\n\t\t\t\t\tArray.every(\n\t\t\t\t\t\tbody.cause.reasons,\n\t\t\t\t\t\t(reason) =>\n\t\t\t\t\t\t\treason._tag === \"Interrupt\" && reason.fiberId === ownerId,\n\t\t\t\t\t)\n\t\t\t\tconst bodyCause =\n\t\t\t\t\tExit.isFailure(body) && !expected ? body.cause : Cause.empty\n\t\t\t\t// Release.close marks independent interruptions; an unmarked one is pending cancellation.\n\t\t\t\tconst releaseCause =\n\t\t\t\t\tExit.isFailure(closed) && !Cause.hasInterruptsOnly(closed.cause)\n\t\t\t\t\t\t? closed.cause\n\t\t\t\t\t\t: Cause.empty\n\t\t\t\tconst failure = Cause.combine(bodyCause, releaseCause)\n\t\t\t\t// Body cleanup may carry either an interruption or a release defect from an inner group.\n\t\t\t\tconst closing = Cause.combine(\n\t\t\t\t\tCause.hasInterrupts(bodyCause) ||\n\t\t\t\t\t\tArray.some(\n\t\t\t\t\t\t\tbodyCause.reasons,\n\t\t\t\t\t\t\t(reason) =>\n\t\t\t\t\t\t\t\treason._tag === \"Die\" &&\n\t\t\t\t\t\t\t\tSchema.is(Release.ReleaseInterrupted)(reason.defect),\n\t\t\t\t\t\t)\n\t\t\t\t\t\t? bodyCause\n\t\t\t\t\t\t: Cause.empty,\n\t\t\t\t\treleaseCause,\n\t\t\t\t)\n\t\t\t\tyield* Ref.update(cleanup, (cause) => Cause.combine(cause, closing))\n\t\t\t\tif (failure.reasons.length > 0) {\n\t\t\t\t\tyield* Ref.update(failures, (cause) => Cause.combine(cause, failure))\n\t\t\t\t\tyield* publish(failure)\n\t\t\t\t\tyield* Deferred.failCause(fibers.deferred, failure)\n\t\t\t\t}\n\t\t\t\tif (Exit.isFailure(closed))\n\t\t\t\t\treturn yield* Effect.failCause(\n\t\t\t\t\t\tExit.isFailure(body)\n\t\t\t\t\t\t\t? Cause.combine(body.cause, closed.cause)\n\t\t\t\t\t\t\t: closed.cause,\n\t\t\t\t\t)\n\t\t\t\tif (Exit.isFailure(waiting) && Exit.isSuccess(body))\n\t\t\t\t\treturn yield* Effect.failCause(waiting.cause)\n\t\t\t\treturn yield* body\n\t\t\t}),\n\t\t)\n\tyield* FiberSet.join(fibers).pipe(\n\t\tEffect.catchCause((cause) =>\n\t\t\tpublish(cause).pipe(\n\t\t\t\tEffect.andThen(FiberSet.clear(fibers)),\n\t\t\t\tEffect.uninterruptible,\n\t\t\t),\n\t\t),\n\t\tEffect.forkScoped,\n\t)\n\tconst failure = Effect.tx(check.pipe(Effect.andThen(Effect.txRetry)))\n\tconst failCause = (cause: Cause.Cause<E>) =>\n\t\t// This is an explicit failure report, not cancellation of an owned worker.\n\t\tFiberSet.run(fibers, observe(Effect.failCause(cause))).pipe(Effect.asVoid)\n\tconst close = TxRef.update(state, (s) =>\n\t\ts._tag === \"Open\" ? State.Closed() : s,\n\t).pipe(\n\t\tEffect.andThen(FiberSet.clear(fibers)),\n\t\tEffect.andThen(Ref.get(cleanup)),\n\t\tEffect.flatMap((cause) =>\n\t\t\tcause.reasons.length > 0 ? Effect.failCause(cause) : Effect.void,\n\t\t),\n\t\tEffect.uninterruptible,\n\t)\n\t// Operational failure is delivered by await; release must also deliver sibling cleanup failures.\n\t// Every sibling failure and interruption survives as a defect; orDie would keep only the first failure.\n\tyield* Effect.addFinalizer(() =>\n\t\tclose.pipe(\n\t\t\tEffect.catchCause((cause) => Effect.failCause(cleanupCause(cause))),\n\t\t),\n\t)\n\treturn {\n\t\tawait: failure,\n\t\tcheck,\n\t\tcause: Ref.get(failures),\n\t\truntime: <R>() =>\n\t\t\tFiberSet.runtime(fibers)<R>().pipe(\n\t\t\t\tEffect.map(\n\t\t\t\t\t(run) => (effect: Effect.Effect<unknown, E, R>) =>\n\t\t\t\t\t\trun(check.pipe(Effect.andThen(observe(effect)))),\n\t\t\t\t),\n\t\t\t),\n\t\trun: (effect) =>\n\t\t\tFiberSet.run(fibers, check.pipe(Effect.andThen(observe(effect)))),\n\t\tfail: (error) => failCause(Cause.fail(error)),\n\t\tfailCause,\n\t\trace: (effect) =>\n\t\t\tcheck.pipe(Effect.andThen(Effect.raceFirst(effect, failure))),\n\t\tclose,\n\t}\n})\n"],"mappings":"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"}
@@ -29,6 +29,13 @@ var CapabilityCombinationError = class extends Schema.TaggedError()("CapabilityC
29
29
  }
30
30
  };
31
31
  var CapabilityFailed = class extends Schema.TaggedError()("CapabilityFailed", { cause: Schema.Cause(Schema.Unknown, Schema.Unknown) }) {};
32
+ /** Every failure class assembly raises; host error classification reads this list. */
33
+ const errors = [
34
+ ListenerConfigError,
35
+ CapabilityContractError,
36
+ CapabilityCombinationError,
37
+ CapabilityFailed
38
+ ];
32
39
  const definition = Schema.declare(Plugin.isPlugin);
33
40
  /** Entries resolve capability modules before assembling their private providers. */
34
41
  const Invocation = Schema.Struct({
@@ -94,7 +101,7 @@ const compatible = (properties, kind) => {
94
101
  const kind = (auth) => auth._tag === "Mtls" ? "Certificate" : auth._tag === "Header" ? "Authorization" : "None";
95
102
  const warn = (properties, credentials, side) => Effect.all([properties.network && !properties.encrypted ? Effect.logWarning(credentials === "Authorization" ? `${properties.protocol}:// ${side === "host" ? "connection" : "listener"} is unencrypted; credentials are transmitted in plaintext` : `${properties.protocol}:// ${side === "host" ? "connection" : "listener"} is unencrypted`) : Effect.void, side === "runner" && properties.network && credentials === "None" ? Effect.logWarning("WebSocket listener has no authentication") : Effect.void], { discard: true });
96
103
  const directAuth = (properties, explicit) => explicit && (properties.protocol === "stdio" || properties.protocol === "command") ? Effect.fail(CapabilityCombinationError.make({ detail: `${properties.protocol} transports do not accept auth` })) : Effect.void;
97
- const connectWith = (explicitAuth = false) => Effect.gen(function* () {
104
+ const connectWith = Effect.fnUntraced(function* (explicitAuth = false) {
98
105
  const connector = yield* Connector;
99
106
  const credentials = yield* Credentials;
100
107
  yield* directAuth(connector.properties, explicitAuth);
@@ -133,6 +140,6 @@ const makeListenerConsumer = (prepare = () => Effect.void, ready = Effect.void)
133
140
  });
134
141
  const listenerConsumer = makeListenerConsumer();
135
142
  connectWith();
136
- export { CapabilityCombinationError, CapabilityContractError, CapabilityFailed, Invocation, ListenerConfigError, accept, compatible, connectWith, directAuth, host, listenerConsumer, makeListenerConsumer, runner };
143
+ export { CapabilityCombinationError, CapabilityContractError, CapabilityFailed, Invocation, ListenerConfigError, accept, compatible, connectWith, directAuth, errors, host, listenerConsumer, makeListenerConsumer, runner };
137
144
 
138
145
  //# sourceMappingURL=assembly.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"assembly.js","names":[],"sources":["../../src/internal/assembly.ts"],"sourcesContent":["import { findSubtree, isSubtreeActive } from \"./forkTree\"\nimport { Peer } from \"./Peer\"\nimport { Graft, Plugin, type Fork } from \"@graftland/graft\"\nimport {\n\tArray,\n\tContext,\n\tDeferred,\n\tEffect,\n\tFiber,\n\tOption,\n\tSchema,\n\tStream,\n} from \"effect\"\nimport {\n\tAuthenticator,\n\tCredentials,\n\ttype AuthenticatorApi,\n\ttype CredentialsApi,\n} from \"../Auth\"\nimport {\n\tConnector,\n\tListener,\n\ttype Accept,\n\ttype Properties,\n\ttype Session,\n} from \"../Transport\"\nimport { AuthenticationFailed } from \"../Errors\"\nimport { Supervisor } from \"./Supervisor\"\nimport { follow } from \"./follow\"\nimport { connectionEnded, closedNormally } from \"./runner/connectionEnded\"\nimport { ServeLifecycle } from \"./ServeLifecycle\"\n\nexport class ListenerConfigError extends Schema.TaggedError<\n\tListenerConfigError,\n\t{ readonly brand: unique symbol }\n>()(\"ListenerConfigError\", { detail: Schema.String }) {\n\toverride get message() {\n\t\treturn this.detail\n\t}\n}\n\nexport class CapabilityContractError extends Schema.TaggedError<\n\tCapabilityContractError,\n\t{ readonly brand: unique symbol }\n>()(\"CapabilityContractError\", { plugin: Schema.String, key: Schema.String }) {\n\toverride get message() {\n\t\treturn `Capability ${this.plugin} became active without providing ${this.key}`\n\t}\n}\nexport class CapabilityCombinationError extends Schema.TaggedError<\n\tCapabilityCombinationError,\n\t{ readonly brand: unique symbol }\n>()(\"CapabilityCombinationError\", { detail: Schema.String }) {\n\toverride get message() {\n\t\treturn this.detail\n\t}\n}\n\nexport class CapabilityFailed extends Schema.TaggedError<\n\tCapabilityFailed,\n\t{ readonly brand: unique symbol }\n>()(\"CapabilityFailed\", {\n\tcause: Schema.Cause(Schema.Unknown, Schema.Unknown),\n}) {}\n\nconst definition = Schema.declare(Plugin.isPlugin)\n/** Entries resolve capability modules before assembling their private providers. */\nexport const Invocation = Schema.Struct({\n\tplugin: definition,\n\tconfig: Schema.Unknown,\n})\nconst Input = Schema.Struct({\n\ttransport: Invocation,\n\tauth: Invocation,\n\tconsumer: definition,\n\tinput: Schema.optionalKey(Schema.Unknown),\n})\nexport type Input = typeof Input.Type\n\nconst failure = (tree: Fork.ForkTree): Effect.Effect<void, CapabilityFailed> =>\n\ttree.state._tag === \"Failed\"\n\t\t? Effect.fail(CapabilityFailed.make({ cause: tree.state.cause }))\n\t\t: Effect.forEach(tree.children, failure, { discard: true })\n\nconst probe = (name: string, key: Context.Key<unknown, unknown>) =>\n\tPlugin.make({\n\t\tname: \"remote-capability-contract\",\n\t\tinject: [Plugin.optional(key)],\n\t\tapply: Effect.fnUntraced(function* () {\n\t\t\tconst value = yield* Effect.serviceOption(key)\n\t\t\tif (Option.isNone(value))\n\t\t\t\treturn yield* CapabilityContractError.make({\n\t\t\t\t\tplugin: name,\n\t\t\t\t\tkey: key.key,\n\t\t\t\t})\n\t\t}),\n\t})\n\n/** Resolve the key in a fresh consumer after the provider subtree settles.\n * An optional consumer started earlier could still hold a pre-publication snapshot.\n */\nconst watch = (provider: Fork.Fork, key: Context.Key<unknown, unknown>) =>\n\tPlugin.fork(\n\t\tGraft.forks.pipe(\n\t\t\tStream.map((trees) => findSubtree(trees, provider.id)),\n\t\t\tStream.filter(Option.isSome),\n\t\t\tStream.map((tree) => tree.value),\n\t\t\tStream.tap(failure),\n\t\t\tStream.map((tree) => ({\n\t\t\t\tname: tree.name,\n\t\t\t\tactive: isSubtreeActive(tree),\n\t\t\t})),\n\t\t\tStream.changesWith((left, right) => left.active === right.active),\n\t\t\tStream.filter((tree) => tree.active),\n\t\t\tStream.runForEach((tree) =>\n\t\t\t\tEffect.scoped(\n\t\t\t\t\tGraft.plugin(probe(tree.name, key)).pipe(\n\t\t\t\t\t\tEffect.flatMap((fork) => fork.await),\n\t\t\t\t\t),\n\t\t\t\t),\n\t\t\t),\n\t\t),\n\t)\n\nconst assembly = (\n\tkeys: readonly [Context.Key<unknown, unknown>, Context.Key<unknown, unknown>],\n) =>\n\tPlugin.make({\n\t\tname: \"remote-assembly\",\n\t\tconfig: Input,\n\t\tapply: Effect.fnUntraced(function* (input) {\n\t\t\tyield* Effect.forEach(\n\t\t\t\t[\n\t\t\t\t\t{ invocation: input.transport, key: keys[0] },\n\t\t\t\t\t{ invocation: input.auth, key: keys[1] },\n\t\t\t\t],\n\t\t\t\tEffect.fnUntraced(function* ({ invocation, key }) {\n\t\t\t\t\tconst provider = yield* Graft.plugin(\n\t\t\t\t\t\tinvocation.plugin,\n\t\t\t\t\t\tinvocation.config,\n\t\t\t\t\t)\n\t\t\t\t\tyield* watch(provider, key)\n\t\t\t\t}),\n\t\t\t)\n\t\t\tconst consumer = yield* Graft.plugin(input.consumer, input.input)\n\t\t\t// Capability publication can leave a transient Pending snapshot; business dependencies may remain Pending.\n\t\t\tyield* consumer.state.pipe(\n\t\t\t\tStream.filter(\n\t\t\t\t\t(state) =>\n\t\t\t\t\t\tstate._tag !== \"Loading\" &&\n\t\t\t\t\t\t(state._tag !== \"Pending\" ||\n\t\t\t\t\t\t\t!Array.some(keys, (key) =>\n\t\t\t\t\t\t\t\tArray.contains(state.missing, key.key),\n\t\t\t\t\t\t\t)),\n\t\t\t\t),\n\t\t\t\tStream.runHead,\n\t\t\t)\n\t\t\tyield* follow(consumer, (cause) =>\n\t\t\t\tEffect.fail(CapabilityFailed.make({ cause })),\n\t\t\t)\n\t\t}),\n\t})\nconst hostAssembly = assembly([Connector, Credentials])\nconst runnerAssembly = assembly([Listener, Authenticator])\n\nexport const host = (input: Input) =>\n\tGraft.plugin(hostAssembly, input, { isolate: [Connector, Credentials] })\nexport const runner = (\n\tinput: Omit<Input, \"consumer\">,\n\tconsumer = listenerConsumer,\n) =>\n\tGraft.plugin(\n\t\trunnerAssembly,\n\t\t{ ...input, consumer },\n\t\t{ isolate: [Listener, Authenticator] },\n\t)\n\nexport const compatible = (\n\tproperties: Properties,\n\tkind: CredentialsApi[\"kind\"],\n): Effect.Effect<void, CapabilityCombinationError> => {\n\tif (\n\t\tkind === \"Certificate\" &&\n\t\t(properties.protocol !== \"wss\" ||\n\t\t\t!properties.encrypted ||\n\t\t\t!Array.contains(properties.carries, \"certificate\"))\n\t)\n\t\treturn Effect.fail(\n\t\t\tCapabilityCombinationError.make({\n\t\t\t\tdetail: \"Mutual TLS requires encrypted wss with certificate evidence\",\n\t\t\t}),\n\t\t)\n\tif (kind === \"Authorization\" && !Array.contains(properties.carries, \"header\"))\n\t\treturn Effect.fail(\n\t\t\tCapabilityCombinationError.make({\n\t\t\t\tdetail: \"This transport cannot carry Authorization headers\",\n\t\t\t}),\n\t\t)\n\treturn Effect.void\n}\nconst kind = (auth: AuthenticatorApi): CredentialsApi[\"kind\"] =>\n\tauth._tag === \"Mtls\"\n\t\t? \"Certificate\"\n\t\t: auth._tag === \"Header\"\n\t\t\t? \"Authorization\"\n\t\t\t: \"None\"\nconst warn = (\n\tproperties: Properties,\n\tcredentials: CredentialsApi[\"kind\"],\n\tside: \"host\" | \"runner\",\n) =>\n\tEffect.all(\n\t\t[\n\t\t\tproperties.network && !properties.encrypted\n\t\t\t\t? Effect.logWarning(\n\t\t\t\t\t\tcredentials === \"Authorization\"\n\t\t\t\t\t\t\t? `${properties.protocol}:// ${side === \"host\" ? \"connection\" : \"listener\"} is unencrypted; credentials are transmitted in plaintext`\n\t\t\t\t\t\t\t: `${properties.protocol}:// ${side === \"host\" ? \"connection\" : \"listener\"} is unencrypted`,\n\t\t\t\t\t)\n\t\t\t\t: Effect.void,\n\t\t\tside === \"runner\" && properties.network && credentials === \"None\"\n\t\t\t\t? Effect.logWarning(\"WebSocket listener has no authentication\")\n\t\t\t\t: Effect.void,\n\t\t],\n\t\t{ discard: true },\n\t)\n\nexport const directAuth = (properties: Properties, explicit: boolean) =>\n\texplicit &&\n\t(properties.protocol === \"stdio\" || properties.protocol === \"command\")\n\t\t? Effect.fail(\n\t\t\t\tCapabilityCombinationError.make({\n\t\t\t\t\tdetail: `${properties.protocol} transports do not accept auth`,\n\t\t\t\t}),\n\t\t\t)\n\t\t: Effect.void\n\nexport const connectWith = (explicitAuth = false) =>\n\tEffect.gen(function* () {\n\t\tconst connector = yield* Connector\n\t\tconst credentials = yield* Credentials\n\t\tyield* directAuth(connector.properties, explicitAuth)\n\t\tyield* compatible(connector.properties, credentials.kind)\n\t\tyield* warn(connector.properties, credentials.kind, \"host\")\n\t\tconst prepared = yield* credentials.read\n\t\treturn yield* connector.connect(prepared)\n\t})\n\nexport const accept =\n\t(\n\t\tauth: AuthenticatorApi,\n\t\tproperties: Properties,\n\t\tsession: (identity: string) => Session,\n\t): Accept =>\n\t(handshake) => {\n\t\tconst identity =\n\t\t\tauth._tag === \"Header\"\n\t\t\t\t? auth.authenticate(handshake.authorization)\n\t\t\t\t: auth._tag === \"Mtls\"\n\t\t\t\t\t? Option.match(handshake.certificate, {\n\t\t\t\t\t\t\tonNone: () =>\n\t\t\t\t\t\t\t\tEffect.fail(AuthenticationFailed.make({ reason: \"missing\" })),\n\t\t\t\t\t\t\tonSome: auth.authenticate,\n\t\t\t\t\t\t})\n\t\t\t\t\t: (properties.network\n\t\t\t\t\t\t\t? Effect.logWarning(\"WebSocket connection has no authentication\")\n\t\t\t\t\t\t\t: Effect.void\n\t\t\t\t\t\t).pipe(Effect.as(auth.identity))\n\t\treturn identity.pipe(Effect.map(session))\n\t}\n\nexport const makeListenerConsumer = (\n\tprepare: (\n\t\tproperties: Properties,\n\t\tauth: AuthenticatorApi,\n\t) => Effect.Effect<void, CapabilityCombinationError> = () => Effect.void,\n\tready: Effect.Effect<void> = Effect.void,\n) =>\n\tPlugin.make({\n\t\tname: \"remote-listener-consumer\",\n\t\tinject: [\n\t\t\tListener,\n\t\t\tAuthenticator,\n\t\t\tSupervisor,\n\t\t\tPlugin.optional(ServeLifecycle),\n\t\t],\n\t\tapply: Effect.fnUntraced(function* () {\n\t\t\tconst listener = yield* Listener\n\t\t\tconst auth = yield* Authenticator\n\t\t\tconst supervisor = yield* Supervisor\n\t\t\tconst lifecycle = yield* Effect.serviceOption(ServeLifecycle)\n\t\t\tyield* prepare(listener.properties, auth)\n\t\t\tyield* compatible(listener.properties, kind(auth)).pipe(\n\t\t\t\tEffect.mapError((error) =>\n\t\t\t\t\tListenerConfigError.make({ detail: error.detail }),\n\t\t\t\t),\n\t\t\t)\n\t\t\tyield* warn(listener.properties, kind(auth), \"runner\")\n\t\t\tconst serving = yield* listener.bind(\n\t\t\t\tauth._tag === \"Mtls\" ? Option.some(auth.tls) : Option.none(),\n\t\t\t)\n\t\t\tconst running = yield* Plugin.fork(\n\t\t\t\tserving\n\t\t\t\t\t.serve(\n\t\t\t\t\t\taccept(\n\t\t\t\t\t\t\tauth,\n\t\t\t\t\t\t\tlistener.properties,\n\t\t\t\t\t\t\t(identity) => (channel) =>\n\t\t\t\t\t\t\t\tsupervisor.accept(channel).pipe(\n\t\t\t\t\t\t\t\t\tEffect.catchCause((cause) =>\n\t\t\t\t\t\t\t\t\t\tlistener.properties.protocol === \"stdio\"\n\t\t\t\t\t\t\t\t\t\t\t? closedNormally(cause)\n\t\t\t\t\t\t\t\t\t\t\t\t? Effect.void\n\t\t\t\t\t\t\t\t\t\t\t\t: Effect.failCause(cause)\n\t\t\t\t\t\t\t\t\t\t\t: connectionEnded(cause),\n\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\tEffect.provideService(Peer, identity),\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t),\n\t\t\t\t\t)\n\t\t\t\t\t.pipe(\n\t\t\t\t\t\tEffect.onExit((exit) =>\n\t\t\t\t\t\t\tlistener.properties.protocol === \"stdio\" &&\n\t\t\t\t\t\t\tOption.isSome(lifecycle)\n\t\t\t\t\t\t\t\t? Deferred.done(lifecycle.value.ended, exit)\n\t\t\t\t\t\t\t\t: Effect.void,\n\t\t\t\t\t\t),\n\t\t\t\t\t),\n\t\t\t)\n\t\t\tyield* serving.ready.pipe(Effect.raceFirst(Fiber.join(running)))\n\t\t\tyield* ready\n\t\t}),\n\t})\n\nexport const listenerConsumer = makeListenerConsumer()\n\nexport const connect = connectWith()\n"],"mappings":"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"}
1
+ {"version":3,"file":"assembly.js","names":[],"sources":["../../src/internal/assembly.ts"],"sourcesContent":["import { findSubtree, isSubtreeActive } from \"./forkTree\"\nimport { Peer } from \"./Peer\"\nimport { Graft, Plugin, type Fork } from \"@graftland/graft\"\nimport {\n\tArray,\n\tContext,\n\tDeferred,\n\tEffect,\n\tFiber,\n\tOption,\n\tSchema,\n\tStream,\n} from \"effect\"\nimport {\n\tAuthenticator,\n\tCredentials,\n\ttype AuthenticatorApi,\n\ttype CredentialsApi,\n} from \"../Auth\"\nimport {\n\tConnector,\n\tListener,\n\ttype Accept,\n\ttype Properties,\n\ttype Session,\n} from \"../Transport\"\nimport { AuthenticationFailed } from \"../Errors\"\nimport { Supervisor } from \"./Supervisor\"\nimport { follow } from \"./follow\"\nimport { connectionEnded, closedNormally } from \"./runner/connectionEnded\"\nimport { ServeLifecycle } from \"./ServeLifecycle\"\n\nexport class ListenerConfigError extends Schema.TaggedError<\n\tListenerConfigError,\n\t{ readonly brand: unique symbol }\n>()(\"ListenerConfigError\", { detail: Schema.String }) {\n\toverride get message() {\n\t\treturn this.detail\n\t}\n}\n\nexport class CapabilityContractError extends Schema.TaggedError<\n\tCapabilityContractError,\n\t{ readonly brand: unique symbol }\n>()(\"CapabilityContractError\", { plugin: Schema.String, key: Schema.String }) {\n\toverride get message() {\n\t\treturn `Capability ${this.plugin} became active without providing ${this.key}`\n\t}\n}\nexport class CapabilityCombinationError extends Schema.TaggedError<\n\tCapabilityCombinationError,\n\t{ readonly brand: unique symbol }\n>()(\"CapabilityCombinationError\", { detail: Schema.String }) {\n\toverride get message() {\n\t\treturn this.detail\n\t}\n}\n\nexport class CapabilityFailed extends Schema.TaggedError<\n\tCapabilityFailed,\n\t{ readonly brand: unique symbol }\n>()(\"CapabilityFailed\", {\n\tcause: Schema.Cause(Schema.Unknown, Schema.Unknown),\n}) {}\n\n/** Every failure class assembly raises; host error classification reads this list. */\nexport const errors = [\n\tListenerConfigError,\n\tCapabilityContractError,\n\tCapabilityCombinationError,\n\tCapabilityFailed,\n] as const\n\nconst definition = Schema.declare(Plugin.isPlugin)\n/** Entries resolve capability modules before assembling their private providers. */\nexport const Invocation = Schema.Struct({\n\tplugin: definition,\n\tconfig: Schema.Unknown,\n})\nconst Input = Schema.Struct({\n\ttransport: Invocation,\n\tauth: Invocation,\n\tconsumer: definition,\n\tinput: Schema.optionalKey(Schema.Unknown),\n})\nexport type Input = typeof Input.Type\n\nconst failure = (tree: Fork.ForkTree): Effect.Effect<void, CapabilityFailed> =>\n\ttree.state._tag === \"Failed\"\n\t\t? Effect.fail(CapabilityFailed.make({ cause: tree.state.cause }))\n\t\t: Effect.forEach(tree.children, failure, { discard: true })\n\nconst probe = (name: string, key: Context.Key<unknown, unknown>) =>\n\tPlugin.make({\n\t\tname: \"remote-capability-contract\",\n\t\tinject: [Plugin.optional(key)],\n\t\tapply: Effect.fnUntraced(function* () {\n\t\t\tconst value = yield* Effect.serviceOption(key)\n\t\t\tif (Option.isNone(value))\n\t\t\t\treturn yield* CapabilityContractError.make({\n\t\t\t\t\tplugin: name,\n\t\t\t\t\tkey: key.key,\n\t\t\t\t})\n\t\t}),\n\t})\n\n/** Resolve the key in a fresh consumer after the provider subtree settles.\n * An optional consumer started earlier could still hold a pre-publication snapshot.\n */\nconst watch = (provider: Fork.Fork, key: Context.Key<unknown, unknown>) =>\n\tPlugin.fork(\n\t\tGraft.forks.pipe(\n\t\t\tStream.map((trees) => findSubtree(trees, provider.id)),\n\t\t\tStream.filter(Option.isSome),\n\t\t\tStream.map((tree) => tree.value),\n\t\t\tStream.tap(failure),\n\t\t\tStream.map((tree) => ({\n\t\t\t\tname: tree.name,\n\t\t\t\tactive: isSubtreeActive(tree),\n\t\t\t})),\n\t\t\tStream.changesWith((left, right) => left.active === right.active),\n\t\t\tStream.filter((tree) => tree.active),\n\t\t\tStream.runForEach((tree) =>\n\t\t\t\tEffect.scoped(\n\t\t\t\t\tGraft.plugin(probe(tree.name, key)).pipe(\n\t\t\t\t\t\tEffect.flatMap((fork) => fork.await),\n\t\t\t\t\t),\n\t\t\t\t),\n\t\t\t),\n\t\t),\n\t)\n\nconst assembly = (\n\tkeys: readonly [Context.Key<unknown, unknown>, Context.Key<unknown, unknown>],\n) =>\n\tPlugin.make({\n\t\tname: \"remote-assembly\",\n\t\tconfig: Input,\n\t\tapply: Effect.fnUntraced(function* (input) {\n\t\t\tyield* Effect.forEach(\n\t\t\t\t[\n\t\t\t\t\t{ invocation: input.transport, key: keys[0] },\n\t\t\t\t\t{ invocation: input.auth, key: keys[1] },\n\t\t\t\t],\n\t\t\t\tEffect.fnUntraced(function* ({ invocation, key }) {\n\t\t\t\t\tconst provider = yield* Graft.plugin(\n\t\t\t\t\t\tinvocation.plugin,\n\t\t\t\t\t\tinvocation.config,\n\t\t\t\t\t)\n\t\t\t\t\tyield* watch(provider, key)\n\t\t\t\t}),\n\t\t\t)\n\t\t\tconst consumer = yield* Graft.plugin(input.consumer, input.input)\n\t\t\t// Capability publication can leave a transient Pending snapshot; business dependencies may remain Pending.\n\t\t\tyield* consumer.state.pipe(\n\t\t\t\tStream.filter(\n\t\t\t\t\t(state) =>\n\t\t\t\t\t\tstate._tag !== \"Loading\" &&\n\t\t\t\t\t\t(state._tag !== \"Pending\" ||\n\t\t\t\t\t\t\t!Array.some(keys, (key) =>\n\t\t\t\t\t\t\t\tArray.contains(state.missing, key.key),\n\t\t\t\t\t\t\t)),\n\t\t\t\t),\n\t\t\t\tStream.runHead,\n\t\t\t)\n\t\t\tyield* follow(consumer, (cause) =>\n\t\t\t\tEffect.fail(CapabilityFailed.make({ cause })),\n\t\t\t)\n\t\t}),\n\t})\nconst hostAssembly = assembly([Connector, Credentials])\nconst runnerAssembly = assembly([Listener, Authenticator])\n\nexport const host = (input: Input) =>\n\tGraft.plugin(hostAssembly, input, { isolate: [Connector, Credentials] })\nexport const runner = (\n\tinput: Omit<Input, \"consumer\">,\n\tconsumer = listenerConsumer,\n) =>\n\tGraft.plugin(\n\t\trunnerAssembly,\n\t\t{ ...input, consumer },\n\t\t{ isolate: [Listener, Authenticator] },\n\t)\n\nexport const compatible = (\n\tproperties: Properties,\n\tkind: CredentialsApi[\"kind\"],\n): Effect.Effect<void, CapabilityCombinationError> => {\n\tif (\n\t\tkind === \"Certificate\" &&\n\t\t(properties.protocol !== \"wss\" ||\n\t\t\t!properties.encrypted ||\n\t\t\t!Array.contains(properties.carries, \"certificate\"))\n\t)\n\t\treturn Effect.fail(\n\t\t\tCapabilityCombinationError.make({\n\t\t\t\tdetail: \"Mutual TLS requires encrypted wss with certificate evidence\",\n\t\t\t}),\n\t\t)\n\tif (kind === \"Authorization\" && !Array.contains(properties.carries, \"header\"))\n\t\treturn Effect.fail(\n\t\t\tCapabilityCombinationError.make({\n\t\t\t\tdetail: \"This transport cannot carry Authorization headers\",\n\t\t\t}),\n\t\t)\n\treturn Effect.void\n}\nconst kind = (auth: AuthenticatorApi): CredentialsApi[\"kind\"] =>\n\tauth._tag === \"Mtls\"\n\t\t? \"Certificate\"\n\t\t: auth._tag === \"Header\"\n\t\t\t? \"Authorization\"\n\t\t\t: \"None\"\nconst warn = (\n\tproperties: Properties,\n\tcredentials: CredentialsApi[\"kind\"],\n\tside: \"host\" | \"runner\",\n) =>\n\tEffect.all(\n\t\t[\n\t\t\tproperties.network && !properties.encrypted\n\t\t\t\t? Effect.logWarning(\n\t\t\t\t\t\tcredentials === \"Authorization\"\n\t\t\t\t\t\t\t? `${properties.protocol}:// ${side === \"host\" ? \"connection\" : \"listener\"} is unencrypted; credentials are transmitted in plaintext`\n\t\t\t\t\t\t\t: `${properties.protocol}:// ${side === \"host\" ? \"connection\" : \"listener\"} is unencrypted`,\n\t\t\t\t\t)\n\t\t\t\t: Effect.void,\n\t\t\tside === \"runner\" && properties.network && credentials === \"None\"\n\t\t\t\t? Effect.logWarning(\"WebSocket listener has no authentication\")\n\t\t\t\t: Effect.void,\n\t\t],\n\t\t{ discard: true },\n\t)\n\nexport const directAuth = (properties: Properties, explicit: boolean) =>\n\texplicit &&\n\t(properties.protocol === \"stdio\" || properties.protocol === \"command\")\n\t\t? Effect.fail(\n\t\t\t\tCapabilityCombinationError.make({\n\t\t\t\t\tdetail: `${properties.protocol} transports do not accept auth`,\n\t\t\t\t}),\n\t\t\t)\n\t\t: Effect.void\n\nexport const connectWith = Effect.fnUntraced(function* (\n\texplicitAuth: boolean = false,\n) {\n\tconst connector = yield* Connector\n\tconst credentials = yield* Credentials\n\tyield* directAuth(connector.properties, explicitAuth)\n\tyield* compatible(connector.properties, credentials.kind)\n\tyield* warn(connector.properties, credentials.kind, \"host\")\n\tconst prepared = yield* credentials.read\n\treturn yield* connector.connect(prepared)\n})\n\nexport const accept =\n\t(\n\t\tauth: AuthenticatorApi,\n\t\tproperties: Properties,\n\t\tsession: (identity: string) => Session,\n\t): Accept =>\n\t(handshake) => {\n\t\tconst identity =\n\t\t\tauth._tag === \"Header\"\n\t\t\t\t? auth.authenticate(handshake.authorization)\n\t\t\t\t: auth._tag === \"Mtls\"\n\t\t\t\t\t? Option.match(handshake.certificate, {\n\t\t\t\t\t\t\tonNone: () =>\n\t\t\t\t\t\t\t\tEffect.fail(AuthenticationFailed.make({ reason: \"missing\" })),\n\t\t\t\t\t\t\tonSome: auth.authenticate,\n\t\t\t\t\t\t})\n\t\t\t\t\t: (properties.network\n\t\t\t\t\t\t\t? Effect.logWarning(\"WebSocket connection has no authentication\")\n\t\t\t\t\t\t\t: Effect.void\n\t\t\t\t\t\t).pipe(Effect.as(auth.identity))\n\t\treturn identity.pipe(Effect.map(session))\n\t}\n\nexport const makeListenerConsumer = (\n\tprepare: (\n\t\tproperties: Properties,\n\t\tauth: AuthenticatorApi,\n\t) => Effect.Effect<void, CapabilityCombinationError> = () => Effect.void,\n\tready: Effect.Effect<void> = Effect.void,\n) =>\n\tPlugin.make({\n\t\tname: \"remote-listener-consumer\",\n\t\tinject: [\n\t\t\tListener,\n\t\t\tAuthenticator,\n\t\t\tSupervisor,\n\t\t\tPlugin.optional(ServeLifecycle),\n\t\t],\n\t\tapply: Effect.fnUntraced(function* () {\n\t\t\tconst listener = yield* Listener\n\t\t\tconst auth = yield* Authenticator\n\t\t\tconst supervisor = yield* Supervisor\n\t\t\tconst lifecycle = yield* Effect.serviceOption(ServeLifecycle)\n\t\t\tyield* prepare(listener.properties, auth)\n\t\t\tyield* compatible(listener.properties, kind(auth)).pipe(\n\t\t\t\tEffect.mapError((error) =>\n\t\t\t\t\tListenerConfigError.make({ detail: error.detail }),\n\t\t\t\t),\n\t\t\t)\n\t\t\tyield* warn(listener.properties, kind(auth), \"runner\")\n\t\t\tconst serving = yield* listener.bind(\n\t\t\t\tauth._tag === \"Mtls\" ? Option.some(auth.tls) : Option.none(),\n\t\t\t)\n\t\t\tconst running = yield* Plugin.fork(\n\t\t\t\tserving\n\t\t\t\t\t.serve(\n\t\t\t\t\t\taccept(\n\t\t\t\t\t\t\tauth,\n\t\t\t\t\t\t\tlistener.properties,\n\t\t\t\t\t\t\t(identity) => (channel) =>\n\t\t\t\t\t\t\t\tsupervisor.accept(channel).pipe(\n\t\t\t\t\t\t\t\t\tEffect.catchCause((cause) =>\n\t\t\t\t\t\t\t\t\t\tlistener.properties.protocol === \"stdio\"\n\t\t\t\t\t\t\t\t\t\t\t? closedNormally(cause)\n\t\t\t\t\t\t\t\t\t\t\t\t? Effect.void\n\t\t\t\t\t\t\t\t\t\t\t\t: Effect.failCause(cause)\n\t\t\t\t\t\t\t\t\t\t\t: connectionEnded(cause),\n\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\tEffect.provideService(Peer, identity),\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t),\n\t\t\t\t\t)\n\t\t\t\t\t.pipe(\n\t\t\t\t\t\tEffect.onExit((exit) =>\n\t\t\t\t\t\t\tlistener.properties.protocol === \"stdio\" &&\n\t\t\t\t\t\t\tOption.isSome(lifecycle)\n\t\t\t\t\t\t\t\t? Deferred.done(lifecycle.value.ended, exit)\n\t\t\t\t\t\t\t\t: Effect.void,\n\t\t\t\t\t\t),\n\t\t\t\t\t),\n\t\t\t)\n\t\t\tyield* serving.ready.pipe(Effect.raceFirst(Fiber.join(running)))\n\t\t\tyield* ready\n\t\t}),\n\t})\n\nexport const listenerConsumer = makeListenerConsumer()\n\nexport const connect = connectWith()\n"],"mappings":";;;;;;;;;;;;AAgCA,IAAa,sBAAb,cAAyC,OAAO,YAG9C,CAAC,CAAC,uBAAuB,EAAE,QAAQ,OAAO,OAAO,CAAC,CAAC,CAAC;CACrD,IAAa,UAAU;EACtB,OAAO,KAAK;CACb;AACD;AAEA,IAAa,0BAAb,cAA6C,OAAO,YAGlD,CAAC,CAAC,2BAA2B;CAAE,QAAQ,OAAO;CAAQ,KAAK,OAAO;AAAO,CAAC,CAAC,CAAC;CAC7E,IAAa,UAAU;EACtB,OAAO,cAAc,KAAK,OAAO,mCAAmC,KAAK;CAC1E;AACD;AACA,IAAa,6BAAb,cAAgD,OAAO,YAGrD,CAAC,CAAC,8BAA8B,EAAE,QAAQ,OAAO,OAAO,CAAC,CAAC,CAAC;CAC5D,IAAa,UAAU;EACtB,OAAO,KAAK;CACb;AACD;AAEA,IAAa,mBAAb,cAAsC,OAAO,YAG3C,CAAC,CAAC,oBAAoB,EACvB,OAAO,OAAO,MAAM,OAAO,SAAS,OAAO,OAAO,EACnD,CAAC,CAAC,CAAC,CAAC;;AAGJ,MAAa,SAAS;CACrB;CACA;CACA;CACA;AACD;AAEA,MAAM,aAAa,OAAO,QAAQ,OAAO,QAAQ;;AAEjD,MAAa,aAAa,OAAO,OAAO;CACvC,QAAQ;CACR,QAAQ,OAAO;AAChB,CAAC;AACD,MAAM,QAAQ,OAAO,OAAO;CAC3B,WAAW;CACX,MAAM;CACN,UAAU;CACV,OAAO,OAAO,YAAY,OAAO,OAAO;AACzC,CAAC;AAGD,MAAM,WAAW,SAChB,KAAK,MAAM,SAAS,WACjB,OAAO,KAAK,iBAAiB,KAAK,EAAE,OAAO,KAAK,MAAM,MAAM,CAAC,CAAC,IAC9D,OAAO,QAAQ,KAAK,UAAU,SAAS,EAAE,SAAS,KAAK,CAAC;AAE5D,MAAM,SAAS,MAAc,QAC5B,OAAO,KAAK;CACX,MAAM;CACN,QAAQ,CAAC,OAAO,SAAS,GAAG,CAAC;CAC7B,OAAO,OAAO,WAAW,aAAa;EACrC,MAAM,QAAQ,OAAO,OAAO,cAAc,GAAG;EAC7C,IAAI,OAAO,OAAO,KAAK,GACtB,OAAO,OAAO,wBAAwB,KAAK;GAC1C,QAAQ;GACR,KAAK,IAAI;EACV,CAAC;CACH,CAAC;AACF,CAAC;;;;AAKF,MAAM,SAAS,UAAqB,QACnC,OAAO,KACN,MAAM,MAAM,KACX,OAAO,KAAK,UAAU,YAAY,OAAO,SAAS,EAAE,CAAC,GACrD,OAAO,OAAO,OAAO,MAAM,GAC3B,OAAO,KAAK,SAAS,KAAK,KAAK,GAC/B,OAAO,IAAI,OAAO,GAClB,OAAO,KAAK,UAAU;CACrB,MAAM,KAAK;CACX,QAAQ,gBAAgB,IAAI;AAC7B,EAAE,GACF,OAAO,aAAa,MAAM,UAAU,KAAK,WAAW,MAAM,MAAM,GAChE,OAAO,QAAQ,SAAS,KAAK,MAAM,GACnC,OAAO,YAAY,SAClB,OAAO,OACN,MAAM,OAAO,MAAM,KAAK,MAAM,GAAG,CAAC,CAAC,CAAC,KACnC,OAAO,SAAS,SAAS,KAAK,KAAK,CACpC,CACD,CACD,CACD,CACD;AAED,MAAM,YACL,SAEA,OAAO,KAAK;CACX,MAAM;CACN,QAAQ;CACR,OAAO,OAAO,WAAW,WAAW,OAAO;EAC1C,OAAO,OAAO,QACb,CACC;GAAE,YAAY,MAAM;GAAW,KAAK,KAAK;EAAG,GAC5C;GAAE,YAAY,MAAM;GAAM,KAAK,KAAK;EAAG,CACxC,GACA,OAAO,WAAW,WAAW,EAAE,YAAY,OAAO;GACjD,MAAM,WAAW,OAAO,MAAM,OAC7B,WAAW,QACX,WAAW,MACZ;GACA,OAAO,MAAM,UAAU,GAAG;EAC3B,CAAC,CACF;EACA,MAAM,WAAW,OAAO,MAAM,OAAO,MAAM,UAAU,MAAM,KAAK;EAEhE,OAAO,SAAS,MAAM,KACrB,OAAO,QACL,UACA,MAAM,SAAS,cACd,MAAM,SAAS,aACf,CAAC,MAAM,KAAK,OAAO,QAClB,MAAM,SAAS,MAAM,SAAS,IAAI,GAAG,CACtC,EACH,GACA,OAAO,OACR;EACA,OAAO,OAAO,WAAW,UACxB,OAAO,KAAK,iBAAiB,KAAK,EAAE,MAAM,CAAC,CAAC,CAC7C;CACD,CAAC;AACF,CAAC;AACF,MAAM,eAAe,SAAS,CAAC,WAAW,WAAW,CAAC;AACtD,MAAM,iBAAiB,SAAS,CAAC,UAAU,aAAa,CAAC;AAEzD,MAAa,QAAQ,UACpB,MAAM,OAAO,cAAc,OAAO,EAAE,SAAS,CAAC,WAAW,WAAW,EAAE,CAAC;AACxE,MAAa,UACZ,OACA,WAAW,qBAEX,MAAM,OACL,gBACA;CAAE,GAAG;CAAO;AAAS,GACrB,EAAE,SAAS,CAAC,UAAU,aAAa,EAAE,CACtC;AAED,MAAa,cACZ,YACA,SACqD;CACrD,IACC,SAAS,kBACR,WAAW,aAAa,SACxB,CAAC,WAAW,aACZ,CAAC,MAAM,SAAS,WAAW,SAAS,aAAa,IAElD,OAAO,OAAO,KACb,2BAA2B,KAAK,EAC/B,QAAQ,8DACT,CAAC,CACF;CACD,IAAI,SAAS,mBAAmB,CAAC,MAAM,SAAS,WAAW,SAAS,QAAQ,GAC3E,OAAO,OAAO,KACb,2BAA2B,KAAK,EAC/B,QAAQ,oDACT,CAAC,CACF;CACD,OAAO,OAAO;AACf;AACA,MAAM,QAAQ,SACb,KAAK,SAAS,SACX,gBACA,KAAK,SAAS,WACb,kBACA;AACL,MAAM,QACL,YACA,aACA,SAEA,OAAO,IACN,CACC,WAAW,WAAW,CAAC,WAAW,YAC/B,OAAO,WACP,gBAAgB,kBACb,GAAG,WAAW,SAAS,MAAM,SAAS,SAAS,eAAe,WAAW,6DACzE,GAAG,WAAW,SAAS,MAAM,SAAS,SAAS,eAAe,WAAW,gBAC7E,IACC,OAAO,MACV,SAAS,YAAY,WAAW,WAAW,gBAAgB,SACxD,OAAO,WAAW,0CAA0C,IAC5D,OAAO,IACX,GACA,EAAE,SAAS,KAAK,CACjB;AAED,MAAa,cAAc,YAAwB,aAClD,aACC,WAAW,aAAa,WAAW,WAAW,aAAa,aACzD,OAAO,KACP,2BAA2B,KAAK,EAC/B,QAAQ,GAAG,WAAW,SAAS,gCAChC,CAAC,CACF,IACC,OAAO;AAEX,MAAa,cAAc,OAAO,WAAW,WAC5C,eAAwB,OACvB;CACD,MAAM,YAAY,OAAO;CACzB,MAAM,cAAc,OAAO;CAC3B,OAAO,WAAW,UAAU,YAAY,YAAY;CACpD,OAAO,WAAW,UAAU,YAAY,YAAY,IAAI;CACxD,OAAO,KAAK,UAAU,YAAY,YAAY,MAAM,MAAM;CAC1D,MAAM,WAAW,OAAO,YAAY;CACpC,OAAO,OAAO,UAAU,QAAQ,QAAQ;AACzC,CAAC;AAED,MAAa,UAEX,MACA,YACA,aAEA,cAAc;CAcd,QAZC,KAAK,SAAS,WACX,KAAK,aAAa,UAAU,aAAa,IACzC,KAAK,SAAS,SACb,OAAO,MAAM,UAAU,aAAa;EACpC,cACC,OAAO,KAAK,qBAAqB,KAAK,EAAE,QAAQ,UAAU,CAAC,CAAC;EAC7D,QAAQ,KAAK;CACd,CAAC,KACC,WAAW,UACV,OAAO,WAAW,4CAA4C,IAC9D,OAAO,KAAA,CACR,KAAK,OAAO,GAAG,KAAK,QAAQ,CAAC,EAAA,CACnB,KAAK,OAAO,IAAI,OAAO,CAAC;AACzC;AAED,MAAa,wBACZ,gBAG6D,OAAO,MACpE,QAA6B,OAAO,SAEpC,OAAO,KAAK;CACX,MAAM;CACN,QAAQ;EACP;EACA;EACA;EACA,OAAO,SAAS,cAAc;CAC/B;CACA,OAAO,OAAO,WAAW,aAAa;EACrC,MAAM,WAAW,OAAO;EACxB,MAAM,OAAO,OAAO;EACpB,MAAM,aAAa,OAAO;EAC1B,MAAM,YAAY,OAAO,OAAO,cAAc,cAAc;EAC5D,OAAO,QAAQ,SAAS,YAAY,IAAI;EACxC,OAAO,WAAW,SAAS,YAAY,KAAK,IAAI,CAAC,CAAC,CAAC,KAClD,OAAO,UAAU,UAChB,oBAAoB,KAAK,EAAE,QAAQ,MAAM,OAAO,CAAC,CAClD,CACD;EACA,OAAO,KAAK,SAAS,YAAY,KAAK,IAAI,GAAG,QAAQ;EACrD,MAAM,UAAU,OAAO,SAAS,KAC/B,KAAK,SAAS,SAAS,OAAO,KAAK,KAAK,GAAG,IAAI,OAAO,KAAK,CAC5D;EACA,MAAM,UAAU,OAAO,OAAO,KAC7B,QACE,MACA,OACC,MACA,SAAS,aACR,cAAc,YACd,WAAW,OAAO,OAAO,CAAC,CAAC,KAC1B,OAAO,YAAY,UAClB,SAAS,WAAW,aAAa,UAC9B,eAAe,KAAK,IACnB,OAAO,OACP,OAAO,UAAU,KAAK,IACvB,gBAAgB,KAAK,CACzB,GACA,OAAO,eAAe,MAAM,QAAQ,CACrC,CACF,CACD,CAAC,CACA,KACA,OAAO,QAAQ,SACd,SAAS,WAAW,aAAa,WACjC,OAAO,OAAO,SAAS,IACpB,SAAS,KAAK,UAAU,MAAM,OAAO,IAAI,IACzC,OAAO,IACX,CACD,CACF;EACA,OAAO,QAAQ,MAAM,KAAK,OAAO,UAAU,MAAM,KAAK,OAAO,CAAC,CAAC;EAC/D,OAAO;CACR,CAAC;AACF,CAAC;AAEF,MAAa,mBAAmB,qBAAqB;AAE9B,YAAY"}
@@ -9,7 +9,7 @@ const uriValue = (field) => {
9
9
  }))) : Effect.succeed(value);
10
10
  };
11
11
  /** Read exactly one graft URI from Node's plain or JSON-quoted SAN representation. */
12
- const identityFromSubjectAltName = (san) => Effect.gen(function* () {
12
+ const identityFromSubjectAltName = Effect.fnUntraced(function* (san) {
13
13
  const values = yield* Effect.forEach(Array.filter(String.split(san ?? "", ", "), String.startsWith("URI:")), uriValue);
14
14
  const uris = Array.filter(values, String.startsWith("graft://"));
15
15
  const [uri] = uris;
@@ -1 +1 @@
1
- {"version":3,"file":"mtls.js","names":[],"sources":["../../../src/internal/auth/mtls.ts"],"sourcesContent":["import { Array, Cause, Effect, Schema, String } from \"effect\"\nimport { AuthenticationFailed } from \"../../Errors\"\n\n// Node JSON-quotes SAN values containing separators, escaping commas inside the value.\nconst uriValue = (field: string) => {\n\tconst value = String.slice(4)(field)\n\treturn String.startsWith('\"')(value)\n\t\t? Schema.decodeEffect(Schema.fromJsonString(Schema.String))(value).pipe(\n\t\t\t\tEffect.mapError((error) =>\n\t\t\t\t\tAuthenticationFailed.make({\n\t\t\t\t\t\treason: \"invalid\",\n\t\t\t\t\t\tcause: Cause.fail(error),\n\t\t\t\t\t}),\n\t\t\t\t),\n\t\t\t)\n\t\t: Effect.succeed(value)\n}\n\n/** Read exactly one graft URI from Node's plain or JSON-quoted SAN representation. */\nexport const identityFromSubjectAltName = (\n\tsan: string | undefined,\n): Effect.Effect<string, AuthenticationFailed> =>\n\tEffect.gen(function* () {\n\t\tconst values = yield* Effect.forEach(\n\t\t\tArray.filter(String.split(san ?? \"\", \", \"), String.startsWith(\"URI:\")),\n\t\t\turiValue,\n\t\t)\n\t\tconst uris = Array.filter(values, String.startsWith(\"graft://\"))\n\t\tconst [uri] = uris\n\t\treturn yield* uris.length === 1 && uri !== undefined\n\t\t\t? Effect.succeed(uri)\n\t\t\t: Effect.fail(\n\t\t\t\t\tAuthenticationFailed.make({\n\t\t\t\t\t\treason: \"invalid\",\n\t\t\t\t\t\tcause: Cause.fail(\n\t\t\t\t\t\t\t\"The peer certificate must contain exactly one graft SAN URI\",\n\t\t\t\t\t\t),\n\t\t\t\t\t}),\n\t\t\t\t)\n\t})\n"],"mappings":";;;AAIA,MAAM,YAAY,UAAkB;CACnC,MAAM,QAAQ,OAAO,MAAM,CAAC,CAAC,CAAC,KAAK;CACnC,OAAO,OAAO,WAAW,IAAG,CAAC,CAAC,KAAK,IAChC,OAAO,aAAa,OAAO,eAAe,OAAO,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,KACjE,OAAO,UAAU,UAChB,qBAAqB,KAAK;EACzB,QAAQ;EACR,OAAO,MAAM,KAAK,KAAK;CACxB,CAAC,CACF,CACD,IACC,OAAO,QAAQ,KAAK;AACxB;;AAGA,MAAa,8BACZ,QAEA,OAAO,IAAI,aAAa;CACvB,MAAM,SAAS,OAAO,OAAO,QAC5B,MAAM,OAAO,OAAO,MAAM,OAAO,IAAI,IAAI,GAAG,OAAO,WAAW,MAAM,CAAC,GACrE,QACD;CACA,MAAM,OAAO,MAAM,OAAO,QAAQ,OAAO,WAAW,UAAU,CAAC;CAC/D,MAAM,CAAC,OAAO;CACd,OAAO,OAAO,KAAK,WAAW,KAAK,QAAQ,KAAA,IACxC,OAAO,QAAQ,GAAG,IAClB,OAAO,KACP,qBAAqB,KAAK;EACzB,QAAQ;EACR,OAAO,MAAM,KACZ,6DACD;CACD,CAAC,CACF;AACH,CAAC"}
1
+ {"version":3,"file":"mtls.js","names":[],"sources":["../../../src/internal/auth/mtls.ts"],"sourcesContent":["import { Array, Cause, Effect, Schema, String } from \"effect\"\nimport { AuthenticationFailed } from \"../../Errors\"\n\n// Node JSON-quotes SAN values containing separators, escaping commas inside the value.\nconst uriValue = (field: string) => {\n\tconst value = String.slice(4)(field)\n\treturn String.startsWith('\"')(value)\n\t\t? Schema.decodeEffect(Schema.fromJsonString(Schema.String))(value).pipe(\n\t\t\t\tEffect.mapError((error) =>\n\t\t\t\t\tAuthenticationFailed.make({\n\t\t\t\t\t\treason: \"invalid\",\n\t\t\t\t\t\tcause: Cause.fail(error),\n\t\t\t\t\t}),\n\t\t\t\t),\n\t\t\t)\n\t\t: Effect.succeed(value)\n}\n\n/** Read exactly one graft URI from Node's plain or JSON-quoted SAN representation. */\nexport const identityFromSubjectAltName = Effect.fnUntraced(function* (\n\tsan: string | undefined,\n): Effect.fn.Return<string, AuthenticationFailed> {\n\tconst values = yield* Effect.forEach(\n\t\tArray.filter(String.split(san ?? \"\", \", \"), String.startsWith(\"URI:\")),\n\t\turiValue,\n\t)\n\tconst uris = Array.filter(values, String.startsWith(\"graft://\"))\n\tconst [uri] = uris\n\treturn yield* uris.length === 1 && uri !== undefined\n\t\t? Effect.succeed(uri)\n\t\t: Effect.fail(\n\t\t\t\tAuthenticationFailed.make({\n\t\t\t\t\treason: \"invalid\",\n\t\t\t\t\tcause: Cause.fail(\n\t\t\t\t\t\t\"The peer certificate must contain exactly one graft SAN URI\",\n\t\t\t\t\t),\n\t\t\t\t}),\n\t\t\t)\n})\n"],"mappings":";;;AAIA,MAAM,YAAY,UAAkB;CACnC,MAAM,QAAQ,OAAO,MAAM,CAAC,CAAC,CAAC,KAAK;CACnC,OAAO,OAAO,WAAW,IAAG,CAAC,CAAC,KAAK,IAChC,OAAO,aAAa,OAAO,eAAe,OAAO,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,KACjE,OAAO,UAAU,UAChB,qBAAqB,KAAK;EACzB,QAAQ;EACR,OAAO,MAAM,KAAK,KAAK;CACxB,CAAC,CACF,CACD,IACC,OAAO,QAAQ,KAAK;AACxB;;AAGA,MAAa,6BAA6B,OAAO,WAAW,WAC3D,KACiD;CACjD,MAAM,SAAS,OAAO,OAAO,QAC5B,MAAM,OAAO,OAAO,MAAM,OAAO,IAAI,IAAI,GAAG,OAAO,WAAW,MAAM,CAAC,GACrE,QACD;CACA,MAAM,OAAO,MAAM,OAAO,QAAQ,OAAO,WAAW,UAAU,CAAC;CAC/D,MAAM,CAAC,OAAO;CACd,OAAO,OAAO,KAAK,WAAW,KAAK,QAAQ,KAAA,IACxC,OAAO,QAAQ,GAAG,IAClB,OAAO,KACP,qBAAqB,KAAK;EACzB,QAAQ;EACR,OAAO,MAAM,KACZ,6DACD;CACD,CAAC,CACF;AACH,CAAC"}
@@ -1,4 +1,3 @@
1
- import { Graft, Plugin } from "@graftland/graft";
2
1
  import { Schema } from "effect";
3
2
  export declare const Config: Schema.Struct<{
4
3
  readonly token: Schema.Union<readonly [Schema.RedactedFromValue<Schema.String>, Schema.Struct<{
@@ -1 +1 @@
1
- {"version":3,"file":"tokenCredentials.d.ts","names":[],"sources":["../../../src/internal/auth/tokenCredentials.ts"],"mappings":";;qBAea,QAAM,OAAA"}
1
+ {"version":3,"file":"tokenCredentials.d.ts","names":[],"sources":["../../../src/internal/auth/tokenCredentials.ts"],"mappings":";qBAea,QAAM,OAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"tokenCredentials.js","names":[],"sources":["../../../src/internal/auth/tokenCredentials.ts"],"sourcesContent":["import { Graft, Plugin } from \"@graftland/graft\"\nimport { ConfigDirectory } from \"@graftland/loader\"\nimport {\n\tCause,\n\tEffect,\n\tFileSystem,\n\tOption,\n\tPath,\n\tRedacted,\n\tSchema,\n} from \"effect\"\nimport { Credentials, type Prepared } from \"../../Auth\"\nimport { CredentialsError } from \"../../Errors\"\nimport { prepare } from \"./token\"\n\nexport const Config = Schema.Struct({\n\ttoken: Schema.Union([\n\t\tSchema.RedactedFromValue(Schema.String),\n\t\tSchema.Struct({ file: Schema.String }),\n\t]),\n})\nexport const plugin = (\n\tname: string,\n): Plugin.Plugin<\n\ttypeof Config.Type,\n\ttypeof Config.Encoded,\n\tGraft.ServiceConflict\n> =>\n\tPlugin.make({\n\t\tname,\n\t\tconfig: Config,\n\t\tinject: [FileSystem.FileSystem, Path.Path],\n\t\tapply: Effect.fnUntraced(function* (config) {\n\t\t\tconst fs = yield* FileSystem.FileSystem\n\t\t\tconst path = yield* Path.Path\n\t\t\tconst directory = yield* ConfigDirectory\n\t\t\tconst token = config.token\n\t\t\tconst read = Redacted.isRedacted(token)\n\t\t\t\t? Effect.succeed(token)\n\t\t\t\t: fs\n\t\t\t\t\t\t.readFileString(\n\t\t\t\t\t\t\tpath.resolve(\n\t\t\t\t\t\t\t\tOption.getOrElse(directory, () => \".\"),\n\t\t\t\t\t\t\t\ttoken.file,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t)\n\t\t\t\t\t\t.pipe(Effect.map(Redacted.make))\n\t\t\tyield* Graft.provide(Credentials, {\n\t\t\t\tkind: \"Authorization\",\n\t\t\t\tread: read.pipe(\n\t\t\t\t\tEffect.flatMap(prepare),\n\t\t\t\t\tEffect.mapBoth({\n\t\t\t\t\t\tonSuccess: (\n\t\t\t\t\t\t\tvalue,\n\t\t\t\t\t\t): Extract<Prepared, { readonly _tag: \"Authorization\" }> => ({\n\t\t\t\t\t\t\t_tag: \"Authorization\",\n\t\t\t\t\t\t\tvalue,\n\t\t\t\t\t\t}),\n\t\t\t\t\t\tonFailure: (error) =>\n\t\t\t\t\t\t\tCredentialsError.make({ cause: Cause.fail(error) }),\n\t\t\t\t\t}),\n\t\t\t\t),\n\t\t\t})\n\t\t}),\n\t})\n"],"mappings":";;;;;;;AAeA,MAAa,SAAS,OAAO,OAAO,EACnC,OAAO,OAAO,MAAM,CACnB,OAAO,kBAAkB,OAAO,MAAM,GACtC,OAAO,OAAO,EAAE,MAAM,OAAO,OAAO,CAAC,CACtC,CAAC,EACF,CAAC;AACD,MAAa,UACZ,SAMA,OAAO,KAAK;CACX;CACA,QAAQ;CACR,QAAQ,CAAC,WAAW,YAAY,KAAK,IAAI;CACzC,OAAO,OAAO,WAAW,WAAW,QAAQ;EAC3C,MAAM,KAAK,OAAO,WAAW;EAC7B,MAAM,OAAO,OAAO,KAAK;EACzB,MAAM,YAAY,OAAO;EACzB,MAAM,QAAQ,OAAO;EACrB,MAAM,OAAO,SAAS,WAAW,KAAK,IACnC,OAAO,QAAQ,KAAK,IACpB,GACC,eACA,KAAK,QACJ,OAAO,UAAU,iBAAiB,GAAG,GACrC,MAAM,IACP,CACD,CAAC,CACA,KAAK,OAAO,IAAI,SAAS,IAAI,CAAC;EAClC,OAAO,MAAM,QAAQ,aAAa;GACjC,MAAM;GACN,MAAM,KAAK,KACV,OAAO,QAAQ,OAAO,GACtB,OAAO,QAAQ;IACd,YACC,WAC4D;KAC5D,MAAM;KACN;IACD;IACA,YAAY,UACX,iBAAiB,KAAK,EAAE,OAAO,MAAM,KAAK,KAAK,EAAE,CAAC;GACpD,CAAC,CACF;EACD,CAAC;CACF,CAAC;AACF,CAAC"}
1
+ {"version":3,"file":"tokenCredentials.js","names":[],"sources":["../../../src/internal/auth/tokenCredentials.ts"],"sourcesContent":["import { Graft, Plugin } from \"@graftland/graft\"\nimport { ConfigDirectory } from \"@graftland/loader\"\nimport {\n\tCause,\n\tEffect,\n\tFileSystem,\n\tOption,\n\tPath,\n\tRedacted,\n\tSchema,\n} from \"effect\"\nimport { Credentials, type Prepared } from \"../../Auth\"\nimport { CredentialsError } from \"../../Errors\"\nimport { prepare } from \"./token\"\n\nexport const Config = Schema.Struct({\n\ttoken: Schema.Union([\n\t\tSchema.RedactedFromValue(Schema.String),\n\t\tSchema.Struct({ file: Schema.String }),\n\t]),\n})\nexport const plugin = (name: string) =>\n\tPlugin.make({\n\t\tname,\n\t\tconfig: Config,\n\t\tinject: [FileSystem.FileSystem, Path.Path],\n\t\tapply: Effect.fnUntraced(function* (config) {\n\t\t\tconst fs = yield* FileSystem.FileSystem\n\t\t\tconst path = yield* Path.Path\n\t\t\tconst directory = yield* ConfigDirectory\n\t\t\tconst token = config.token\n\t\t\tconst read = Redacted.isRedacted(token)\n\t\t\t\t? Effect.succeed(token)\n\t\t\t\t: fs\n\t\t\t\t\t\t.readFileString(\n\t\t\t\t\t\t\tpath.resolve(\n\t\t\t\t\t\t\t\tOption.getOrElse(directory, () => \".\"),\n\t\t\t\t\t\t\t\ttoken.file,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t)\n\t\t\t\t\t\t.pipe(Effect.map(Redacted.make))\n\t\t\tyield* Graft.provide(Credentials, {\n\t\t\t\tkind: \"Authorization\",\n\t\t\t\tread: read.pipe(\n\t\t\t\t\tEffect.flatMap(prepare),\n\t\t\t\t\tEffect.mapBoth({\n\t\t\t\t\t\tonSuccess: (\n\t\t\t\t\t\t\tvalue,\n\t\t\t\t\t\t): Extract<Prepared, { readonly _tag: \"Authorization\" }> => ({\n\t\t\t\t\t\t\t_tag: \"Authorization\",\n\t\t\t\t\t\t\tvalue,\n\t\t\t\t\t\t}),\n\t\t\t\t\t\tonFailure: (error) =>\n\t\t\t\t\t\t\tCredentialsError.make({ cause: Cause.fail(error) }),\n\t\t\t\t\t}),\n\t\t\t\t),\n\t\t\t})\n\t\t}),\n\t})\n"],"mappings":";;;;;;;AAeA,MAAa,SAAS,OAAO,OAAO,EACnC,OAAO,OAAO,MAAM,CACnB,OAAO,kBAAkB,OAAO,MAAM,GACtC,OAAO,OAAO,EAAE,MAAM,OAAO,OAAO,CAAC,CACtC,CAAC,EACF,CAAC;AACD,MAAa,UAAU,SACtB,OAAO,KAAK;CACX;CACA,QAAQ;CACR,QAAQ,CAAC,WAAW,YAAY,KAAK,IAAI;CACzC,OAAO,OAAO,WAAW,WAAW,QAAQ;EAC3C,MAAM,KAAK,OAAO,WAAW;EAC7B,MAAM,OAAO,OAAO,KAAK;EACzB,MAAM,YAAY,OAAO;EACzB,MAAM,QAAQ,OAAO;EACrB,MAAM,OAAO,SAAS,WAAW,KAAK,IACnC,OAAO,QAAQ,KAAK,IACpB,GACC,eACA,KAAK,QACJ,OAAO,UAAU,iBAAiB,GAAG,GACrC,MAAM,IACP,CACD,CAAC,CACA,KAAK,OAAO,IAAI,SAAS,IAAI,CAAC;EAClC,OAAO,MAAM,QAAQ,aAAa;GACjC,MAAM;GACN,MAAM,KAAK,KACV,OAAO,QAAQ,OAAO,GACtB,OAAO,QAAQ;IACd,YACC,WAC4D;KAC5D,MAAM;KACN;IACD;IACA,YAAY,UACX,iBAAiB,KAAK,EAAE,OAAO,MAAM,KAAK,KAAK,EAAE,CAAC;GACpD,CAAC,CACF;EACD,CAAC;CACF,CAAC;AACF,CAAC"}
@@ -6,7 +6,7 @@ import { Array, Cause, Data, Deferred, Effect, Exit, Fiber, Logger, MutableRef,
6
6
  // src/internal/child.ts
7
7
  const ChildEvent = Data.taggedEnum();
8
8
  /** Queue data; serialization belongs to the RPC consumer, outside synchronous logger callbacks. */
9
- const telemetry = (contract) => Effect.gen(function* () {
9
+ const telemetry = Effect.fnUntraced(function* (contract) {
10
10
  const events = yield* Queue.bounded(2);
11
11
  const logs = yield* Queue.dropping(128);
12
12
  const dropped = MutableRef.make(0);
@@ -41,31 +41,32 @@ const telemetry = (contract) => Effect.gen(function* () {
41
41
  });
42
42
  const Lifecycle = Data.taggedEnum();
43
43
  const runningOf = (state) => state._tag === "Running" ? Option.some(state.running) : state._tag === "Withdrawing" || state._tag === "Disposing" ? state.running : Option.none();
44
- const cleanup = (running, retired) => Effect.gen(function* () {
44
+ const cleanup = Effect.fnUntraced(function* (running, retired) {
45
45
  const pluginExit = yield* Effect.exit(running.fork.dispose);
46
46
  const bridgeExit = yield* Effect.exit(running.bridge.dispose);
47
47
  yield* Fiber.join(running.observation);
48
48
  const failed = yield* Ref.get(running.observedFailure);
49
49
  return Array.reduce([bridgeExit, pluginExit], retired ? failed : Cause.empty, (cause, exit) => Exit.isFailure(exit) ? Cause.combine(cause, Cause.fromReasons(Array.flatMap(exit.cause.reasons, (reason) => reason._tag === "Fail" ? reason.error.cause.reasons : [reason]))) : cause);
50
50
  });
51
- const lifecycle = (contract, peer, identity, telemetry) => Effect.gen(function* () {
51
+ const lifecycle = Effect.fnUntraced(function* (contract, peer, identity, telemetry) {
52
52
  const scope = yield* Effect.scope;
53
53
  const instanceScope = yield* Scope.fork(scope);
54
54
  const releaseExports = yield* Deferred.make();
55
55
  const state = yield* SynchronizedRef.make(Lifecycle.Idle());
56
- const release = SynchronizedRef.update(state, (current) => Lifecycle.Disposing({ running: runningOf(current) })).pipe(Effect.andThen(Deferred.succeed(releaseExports, void 0)));
56
+ const disposing = (current) => Lifecycle.Disposing({ running: runningOf(current) });
57
+ const release = SynchronizedRef.update(state, disposing).pipe(Effect.andThen(Deferred.succeed(releaseExports, void 0)));
57
58
  const exportBridge = Graft.plugin(Plugin.make({
58
59
  name: `${contract.name}/exports`,
59
60
  inject: Array.map(contract.provides, (service) => service.key),
60
- apply: () => Effect.gen(function* () {
61
+ apply: Effect.fnUntraced(function* () {
61
62
  for (const service of contract.provides) yield* service.serve(peer).pipe(Effect.tapCause((cause) => Cause.hasInterruptsOnly(cause) ? Effect.void : Queue.offer(telemetry.events, ChildEvent.Failed({ cause }))), Effect.forkScoped);
62
- yield* Effect.addFinalizer(() => Effect.gen(function* () {
63
+ yield* Effect.addFinalizer(Effect.fnUntraced(function* () {
63
64
  if (yield* SynchronizedRef.modify(state, (current) => current._tag === "Disposing" ? [false, current] : [true, Lifecycle.Withdrawing({ running: runningOf(current) })])) yield* Queue.offer(telemetry.events, ChildEvent.Withdrawing());
64
65
  yield* Deferred.await(releaseExports);
65
66
  }));
66
67
  })
67
68
  })).pipe(Scope.provide(instanceScope));
68
- const start = (input) => Effect.gen(function* () {
69
+ const start = Effect.fnUntraced(function* (input) {
69
70
  for (const service of contract.inject) yield* service.publish(peer).pipe(Scope.provide(scope), Effect.mapError((error) => ActivationFailed.make({
70
71
  detail: "Publishing imported services failed",
71
72
  cause: Cause.fail(error)
@@ -86,7 +87,7 @@ const lifecycle = (contract, peer, identity, telemetry) => Effect.gen(function*
86
87
  observation
87
88
  };
88
89
  });
89
- const awaitActive = (running) => Effect.gen(function* () {
90
+ const awaitActive = Effect.fnUntraced(function* (running) {
90
91
  const first = yield* running.fork.state.pipe(Stream.filter((state) => state._tag !== "Loading"), Stream.runHead);
91
92
  if (Option.isNone(first)) return yield* ActivationFailed.make({ detail: "The remote fork disappeared during startup" });
92
93
  if (first.value._tag === "Failed") return yield* Effect.fail(contract.normalizeCause(first.value.cause));
@@ -99,17 +100,19 @@ const lifecycle = (contract, peer, identity, telemetry) => Effect.gen(function*
99
100
  });
100
101
  if (Option.isNone(exported) || exported.value._tag !== "Active") return yield* ActivationFailed.make({ detail: "The remote export bridge stopped during startup" });
101
102
  });
102
- const load = (input) => Effect.gen(function* () {
103
- yield* SynchronizedRef.updateEffect(state, (current) => current._tag === "Idle" ? Effect.succeed(Lifecycle.Loading()) : Effect.fail(AlreadyLoaded.make({})));
104
- const running = yield* start(input);
105
- yield* SynchronizedRef.update(state, (current) => current._tag === "Withdrawing" ? Lifecycle.Withdrawing({ running: Option.some(running) }) : current._tag === "Disposing" ? Lifecycle.Disposing({ running: Option.some(running) }) : Lifecycle.Running({ running }));
106
- yield* awaitActive(running);
107
- }).pipe(Effect.mapError((error) => Cause.isCause(error) ? error : contract.normalizeCause(Cause.fail(error))));
108
103
  return {
109
- load,
104
+ load: Effect.fnUntraced(function* (input) {
105
+ yield* SynchronizedRef.updateEffect(state, (current) => current._tag === "Idle" ? Effect.succeed(Lifecycle.Loading()) : Effect.fail(AlreadyLoaded.make({})));
106
+ const running = yield* start(input);
107
+ if (yield* SynchronizedRef.modify(state, (current) => current._tag === "Withdrawing" ? [false, Lifecycle.Withdrawing({ running: Option.some(running) })] : current._tag === "Disposing" ? [true, Lifecycle.Disposing({ running: Option.some(running) })] : [false, Lifecycle.Running({ running })])) {
108
+ const cause = yield* cleanup(running, false);
109
+ return yield* Effect.fail(Cause.combine(Cause.fail(ActivationFailed.make({ detail: "The execution was disposed during load" })), cause));
110
+ }
111
+ yield* awaitActive(running);
112
+ }, Effect.mapError((error) => contract.normalizeCause(Cause.isCause(error) ? error : Cause.fail(error)))),
110
113
  dispose: Effect.gen(function* () {
111
- const previous = yield* SynchronizedRef.get(state);
112
- yield* release;
114
+ const previous = yield* SynchronizedRef.getAndUpdate(state, disposing);
115
+ yield* Deferred.succeed(releaseExports, void 0);
113
116
  const current = runningOf(previous);
114
117
  const retired = previous._tag === "Withdrawing";
115
118
  const cause = Option.isSome(current) ? yield* cleanup(current.value, retired) : Cause.empty;