@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
@@ -5,6 +5,7 @@ import { Effect, Logger, Option } from "effect"
5
5
  import { RpcServer } from "effect/rpc"
6
6
  import { fromModule, type RunnerContract } from "../Contract"
7
7
  import * as Port from "./port"
8
+ import { prepare, type RunnerContract as PreparedContract } from "./contract"
8
9
  import * as Services from "./services"
9
10
  import * as Child from "./child"
10
11
  import * as Multiplex from "./runner/Multiplex"
@@ -15,97 +16,99 @@ import { closedNormally } from "./runner/connectionEnded"
15
16
  import { endpoint } from "./control"
16
17
 
17
18
  /** Import a contract in the runner installation; importing this module performs no I/O. */
18
- export const load = (specifier: string) =>
19
- Effect.gen(function* () {
20
- const module = yield* loadModule(specifier)
21
- const contract = fromModule(module)
22
- if (Option.isNone(contract))
23
- return yield* ContractNotFound.make({ module: specifier })
24
- return contract.value
25
- })
19
+ export const load = Effect.fnUntraced(function* (specifier: string) {
20
+ const module = yield* loadModule(specifier)
21
+ const contract = fromModule(module)
22
+ if (Option.isNone(contract))
23
+ return yield* ContractNotFound.make({ module: specifier })
24
+ return contract.value
25
+ })
26
26
 
27
- const connect = (
28
- contract: RunnerContract,
27
+ const connect = Effect.fnUntraced(function* (
28
+ contract: PreparedContract,
29
29
  channel: Port.Channel,
30
30
  session: string,
31
31
  bootstrap: Bootstrap | undefined,
32
- ) =>
33
- Effect.gen(function* () {
34
- const mux =
35
- bootstrap === undefined ? undefined : yield* Multiplex.make(channel)
36
- return yield* Port.make(
37
- mux === undefined ? channel : Wire.channel(mux, 1),
38
- {
39
- session,
40
- serve: {
41
- ...Services.endpoints(contract.provides),
42
- [endpoint]: contract.control,
43
- },
44
- call: Services.endpoints(contract.inject),
45
- ...(bootstrap === undefined ? {} : { limits: bootstrap.limits }),
46
- },
47
- )
32
+ ) {
33
+ const mux =
34
+ bootstrap === undefined ? undefined : yield* Multiplex.make(channel)
35
+ return yield* Port.make(mux === undefined ? channel : Wire.channel(mux, 1), {
36
+ session,
37
+ serve: {
38
+ ...Services.endpoints(contract.provides),
39
+ [endpoint]: contract.control,
40
+ },
41
+ call: Services.endpoints(contract.inject),
42
+ ...(bootstrap === undefined ? {} : { limits: bootstrap.limits }),
48
43
  })
44
+ })
49
45
 
50
46
  /** One execution unit; the executable supplies the platform and Graft services. */
51
- export const run = (
52
- contract: RunnerContract,
47
+ export const run: (
48
+ descriptor: RunnerContract,
53
49
  channel: Port.Channel,
54
- session = "local",
50
+ session?: string,
55
51
  bootstrap?: Bootstrap,
56
- stop: Effect.Effect<unknown, ExecutionError> = Effect.never,
57
- ): Effect.Effect<void, ExecutionError, Graft.Graft> =>
58
- Effect.scoped(
59
- Effect.gen(function* () {
60
- const telemetry = yield* Child.telemetry(contract)
61
- const loggers = yield* Logger.CurrentLoggers
62
- yield* Effect.gen(function* () {
63
- const peer = yield* connect(contract, channel, session, bootstrap)
64
- const instance = yield* Child.lifecycle(
65
- contract,
66
- peer,
67
- bootstrap?.identity ?? { id: session, generation: 1 },
68
- telemetry,
69
- )
70
- const handlers = yield* contract.control.toHandlers({
71
- Load: ({ input }) => instance.load(input),
72
- Dispose: () => instance.dispose,
73
- Events: () => telemetry.eventStream,
74
- Logs: () => telemetry.logStream,
75
- })
76
- yield* RpcServer.make(contract.control, {
77
- disableFatalDefects: true,
78
- }).pipe(
79
- Effect.provideContext(handlers),
80
- Effect.provideService(
81
- RpcServer.Protocol,
82
- peer.serverProtocol(endpoint),
83
- ),
84
- Effect.forkScoped,
85
- )
86
- yield* Effect.raceFirst(
87
- peer.await.pipe(
88
- Effect.catchIf(
89
- (error) => closedNormally(error.cause),
90
- () => Effect.void,
91
- ),
92
- Effect.mapError((error) =>
93
- ExecutionError.make({
94
- detail: "Child transport failed",
95
- cause: error.cause,
96
- }),
97
- ),
98
- ),
99
- stop,
100
- ).pipe(
101
- // Release exports before closing the instance scope, including on interruption.
102
- Effect.ensuring(instance.release),
103
- )
52
+ stop?: Effect.Effect<unknown, ExecutionError>,
53
+ ) => Effect.Effect<void, ExecutionError, Graft.Graft> = Effect.fnUntraced(
54
+ function* (
55
+ descriptor: RunnerContract,
56
+ channel: Port.Channel,
57
+ session: string = "local",
58
+ bootstrap?: Bootstrap,
59
+ stop: Effect.Effect<unknown, ExecutionError> = Effect.never,
60
+ ) {
61
+ const contract = prepare(descriptor)
62
+ const telemetry = yield* Child.telemetry(contract)
63
+ const loggers = yield* Logger.CurrentLoggers
64
+ yield* Effect.gen(function* () {
65
+ const peer = yield* connect(contract, channel, session, bootstrap)
66
+ const instance = yield* Child.lifecycle(
67
+ contract,
68
+ peer,
69
+ bootstrap?.identity ?? { id: session, generation: 1 },
70
+ telemetry,
71
+ )
72
+ const handlers = yield* contract.control.toHandlers({
73
+ Load: ({ input }) => instance.load(input),
74
+ Dispose: () => instance.dispose,
75
+ Events: () => telemetry.eventStream,
76
+ Logs: () => telemetry.logStream,
77
+ })
78
+ yield* RpcServer.make(contract.control, {
79
+ disableFatalDefects: true,
104
80
  }).pipe(
81
+ Effect.provideContext(handlers),
105
82
  Effect.provideService(
106
- Logger.CurrentLoggers,
107
- new Set([...loggers, telemetry.logger]),
83
+ RpcServer.Protocol,
84
+ peer.serverProtocol(endpoint),
108
85
  ),
86
+ Effect.forkScoped,
109
87
  )
110
- }),
111
- )
88
+ yield* Effect.raceFirst(
89
+ peer.await.pipe(
90
+ Effect.catchIf(
91
+ (error) => closedNormally(error.cause),
92
+ () => Effect.void,
93
+ ),
94
+ Effect.mapError((error) =>
95
+ ExecutionError.make({
96
+ detail: "Child transport failed",
97
+ cause: error.cause,
98
+ }),
99
+ ),
100
+ ),
101
+ stop,
102
+ ).pipe(
103
+ // Release exports before closing the instance scope, including on interruption.
104
+ Effect.ensuring(instance.release),
105
+ )
106
+ }).pipe(
107
+ Effect.provideService(
108
+ Logger.CurrentLoggers,
109
+ new Set([...loggers, telemetry.logger]),
110
+ ),
111
+ )
112
+ },
113
+ Effect.scoped,
114
+ )
@@ -0,0 +1,47 @@
1
+ import { Cause, Schema } from "effect"
2
+ import * as Contract from "../Contract"
3
+ import { ChildFailure } from "./childErrors"
4
+ import * as Control from "./control"
5
+
6
+ /** Control RPCs and child failures belong to the execution protocol, not the public descriptor. */
7
+ export const prepare = <
8
+ S extends Schema.Top & {
9
+ readonly Encoded: Schema.Json
10
+ readonly DecodingServices: never
11
+ readonly EncodingServices: never
12
+ },
13
+ E extends Schema.Top & {
14
+ readonly DecodingServices: never
15
+ readonly EncodingServices: never
16
+ },
17
+ >(
18
+ contract: Contract.Contract<S, E>,
19
+ ) => {
20
+ const failure = Schema.Union([
21
+ contract.error,
22
+ Contract.UndeclaredFailure,
23
+ ChildFailure,
24
+ ])
25
+ const codec = Schema.toCodecJson(
26
+ Schema.Cause(failure, Schema.Defect({ includeStack: true })),
27
+ )
28
+ const declared = Schema.is(failure)
29
+ const normalizeCause = (cause: Cause.Cause<unknown>) =>
30
+ Cause.map(cause, (error) =>
31
+ declared(error)
32
+ ? error
33
+ : Contract.UndeclaredFailure.make({ original: error }),
34
+ )
35
+ return {
36
+ ...contract,
37
+ control: Control.make(codec),
38
+ normalizeCause,
39
+ encodeCause: (cause: Cause.Cause<unknown>) =>
40
+ normalizeCause(cause).pipe(Schema.encodeEffect(codec)),
41
+ decodeCause: Schema.decodeUnknownEffect(codec),
42
+ }
43
+ }
44
+
45
+ export type RunnerContract = ReturnType<
46
+ typeof prepare<Schema.Codec<unknown, Schema.Json>, Schema.Codec<unknown>>
47
+ >
@@ -15,9 +15,11 @@ export type Source<A, D extends ReadonlyArray<Plugin.Dependency>, E = unknown> =
15
15
  NoInfer<Plugin.Required<D>> | Scope.Scope
16
16
  >
17
17
  }
18
- type Token<D extends ReadonlyArray<Plugin.Dependency>> =
18
+ /** A token value, a file, or a credential effect with declared dependencies. */
19
+ export type Token<D extends ReadonlyArray<Plugin.Dependency>> =
19
20
  string | { readonly file: string } | Source<Redacted.Redacted<string>, D>
20
- type Authentication<D extends ReadonlyArray<Plugin.Dependency>> =
21
+ /** Authentication configuration shared by TypeScript connection descriptions. */
22
+ export type Authentication<D extends ReadonlyArray<Plugin.Dependency>> =
21
23
  | { readonly name: string; readonly config?: unknown }
22
24
  | { readonly none: { readonly identity?: string } }
23
25
  | {
@@ -27,14 +29,15 @@ type Authentication<D extends ReadonlyArray<Plugin.Dependency>> =
27
29
  }
28
30
  | { readonly bearer: { readonly token: Token<D> } }
29
31
  | { readonly jwt: { readonly token: Token<D> } }
30
- type WithCredentials<C, D extends ReadonlyArray<Plugin.Dependency>> = C extends
31
- | { readonly local: object }
32
- | { readonly worker: object }
33
- | { readonly command: ReadonlyArray<string> }
34
- ? C
35
- : Omit<C, "auth"> & { readonly auth?: Authentication<D> }
36
32
  export type Connect<D extends ReadonlyArray<Plugin.Dependency> = readonly []> =
37
- WithCredentials<typeof Configuration.Connect.Encoded, D>
33
+ typeof Configuration.Connect.Encoded extends infer C
34
+ ? C extends
35
+ | { readonly local: object }
36
+ | { readonly worker: object }
37
+ | { readonly command: ReadonlyArray<string> }
38
+ ? C
39
+ : Omit<C, "auth"> & { readonly auth?: Authentication<D> }
40
+ : never
38
41
 
39
42
  const provider = <A, E, D extends ReadonlyArray<Plugin.Dependency>>(
40
43
  source: Source<A, D, E>,
@@ -12,7 +12,7 @@ import {
12
12
  } from "effect"
13
13
  import { ChildProcessSpawner } from "effect/process"
14
14
  import * as Contract from "../Contract"
15
- import { MissingInstance } from "../Errors"
15
+ import { MissingInstance, RemoteEntryError as EntryError } from "../Errors"
16
16
  import { LocalTransport, WorkerTransport } from "./directTransport"
17
17
  import * as Configuration from "./entryConfig"
18
18
  import * as Assembly from "./assembly"
@@ -25,19 +25,6 @@ import type { ExecutionOptions } from "./execution"
25
25
  import * as Importer from "./importer"
26
26
  import { SecureRandom } from "effect/crypto"
27
27
 
28
- export class EntryError extends Schema.TaggedError<
29
- EntryError,
30
- { readonly brand: unique symbol }
31
- >()("RemoteEntryError", {
32
- entry: Schema.Option(Schema.String),
33
- directory: Schema.Option(Schema.String),
34
- field: Schema.String,
35
- cause: Schema.Cause(Schema.Unknown, Schema.Unknown),
36
- }) {
37
- override get message() {
38
- return `Remote entry ${Option.getOrElse(this.entry, () => "<programmatic>")} failed at ${this.field}`
39
- }
40
- }
41
28
  export const boundary = Effect.fnUntraced(function* (field: string) {
42
29
  const entry = yield* Entry.CurrentId
43
30
  const directory = yield* ConfigDirectory
@@ -54,17 +41,16 @@ export const resolve = Effect.fnUntraced(function* (
54
41
  const directory = path.resolve(Option.getOrElse(source, () => "."))
55
42
  const resolver = yield* Option.match(existing, {
56
43
  onSome: Effect.succeed,
57
- onNone: () =>
58
- Effect.gen(function* () {
59
- const importer = yield* Importer.make(directory)
60
- return yield* ModuleResolver.make({
61
- base: directory,
62
- importer: (specifier) =>
63
- String.startsWith("@graftland/plugin-remote/")(specifier)
64
- ? import(specifier)
65
- : importer(specifier),
66
- })
67
- }),
44
+ onNone: Effect.fnUntraced(function* () {
45
+ const importer = yield* Importer.make(directory)
46
+ return yield* ModuleResolver.make({
47
+ base: directory,
48
+ importer: (specifier) =>
49
+ String.startsWith("@graftland/plugin-remote/")(specifier)
50
+ ? import(specifier)
51
+ : importer(specifier),
52
+ })
53
+ }),
68
54
  })
69
55
  const fail = yield* boundary(field)
70
56
  const plugin = yield* resolver
@@ -1,6 +1,15 @@
1
1
  import { Plugin } from "@graftland/graft"
2
- import { Array, Cause, Effect, Fiber, Schema, Scope } from "effect"
2
+ import {
3
+ Array,
4
+ Cause,
5
+ Effect,
6
+ Fiber,
7
+ PlatformError,
8
+ Schema,
9
+ Scope,
10
+ } from "effect"
3
11
  import { SecureRandom } from "effect/crypto"
12
+ import { RpcClientError } from "effect/rpc"
4
13
  import type {
5
14
  LocalTarget as Local,
6
15
  WorkerTarget as Worker,
@@ -12,9 +21,15 @@ import type { Duration } from "effect"
12
21
  import * as Connection from "./runner/Connection"
13
22
  import * as Services from "./services"
14
23
  import * as Host from "./host"
24
+ import * as Errors from "../Errors"
15
25
  import { RemoteWithdrawn, RemoteError, MissingInstance } from "../Errors"
26
+ import * as ChildErrors from "./childErrors"
27
+ import * as Assembly from "./assembly"
28
+ import * as Model from "./runner/model"
29
+ import { ReleaseInterrupted } from "./release"
16
30
  import * as Contract from "../Contract"
17
31
  import * as Control from "./control"
32
+ import { prepare } from "./contract"
18
33
 
19
34
  export interface ExecutionOptions {
20
35
  readonly contractModule: string
@@ -63,8 +78,9 @@ export const executionPlugin = <
63
78
  ...Array.map(contract.inject, (service) => service.key),
64
79
  ],
65
80
  config: Schema.toEncoded(contract.config),
66
- apply: (input) =>
67
- Effect.gen(function* () {
81
+ apply: Effect.fnUntraced(
82
+ function* (input: Schema.Json) {
83
+ const prepared = prepare(contract)
68
84
  const random = yield* SecureRandom.SecureRandom
69
85
  const session = yield* random.uuidV4()
70
86
  const active = yield* Connection.acquire(
@@ -75,10 +91,10 @@ export const executionPlugin = <
75
91
  serve: Services.endpoints(contract.inject),
76
92
  call: {
77
93
  ...Services.endpoints(contract.provides),
78
- [Control.endpoint]: contract.control,
94
+ [Control.endpoint]: prepared.control,
79
95
  },
80
96
  },
81
- Host.initialize(contract),
97
+ Host.initialize(prepared),
82
98
  Host.dispose,
83
99
  options.shutdownTimeout ?? "5 seconds",
84
100
  )
@@ -96,12 +112,57 @@ export const executionPlugin = <
96
112
  ),
97
113
  )
98
114
  return () => Effect.succeed(false)
99
- }).pipe(
100
- Effect.annotateLogs(annotations),
101
- Effect.mapError((error) => publicError(contract.error, error)),
102
- ),
115
+ },
116
+ Effect.annotateLogs(annotations),
117
+ Effect.mapError((error) => publicError(contract.error, error)),
118
+ ),
103
119
  })
104
120
 
121
+ /** Failures raised by the host machinery; a permissive declared schema must not claim them. */
122
+ const internalErrors: ReadonlyArray<abstract new (...args: never) => unknown> =
123
+ [
124
+ Errors.ProcessExited,
125
+ Errors.TransportError,
126
+ Errors.LocalTerminationTimeout,
127
+ Errors.CredentialsError,
128
+ Errors.AuthenticationFailed,
129
+ Errors.RemoteEntryError,
130
+ ChildErrors.AlreadyLoaded,
131
+ ChildErrors.ContractNotFound,
132
+ ChildErrors.ModuleImportFailed,
133
+ ChildErrors.ActivationFailed,
134
+ Model.PackageError,
135
+ Model.SessionAccessDenied,
136
+ Model.StaleSession,
137
+ Model.LeaseExpired,
138
+ Model.SessionStopped,
139
+ Model.SessionConflict,
140
+ Model.StateStorageError,
141
+ Model.ExecutionError,
142
+ Model.TerminationUnconfirmed,
143
+ Model.RunnerClosing,
144
+ Model.StateDirectoryLocked,
145
+ Model.RemoteTerminationUnconfirmed,
146
+ ReleaseInterrupted,
147
+ RpcClientError.RpcClientError,
148
+ ...Assembly.errors,
149
+ ]
150
+ const isInternal = (error: unknown) =>
151
+ Schema.isSchemaError(error) ||
152
+ PlatformError.isPlatformError(error) ||
153
+ Array.some(internalErrors, (Class) => error instanceof Class)
154
+ const isPublic = (
155
+ error: unknown,
156
+ ): error is
157
+ | Contract.UndeclaredFailure
158
+ | RemoteWithdrawn
159
+ | RemoteError
160
+ | MissingInstance =>
161
+ Schema.is(Contract.UndeclaredFailure)(error) ||
162
+ Schema.is(RemoteWithdrawn)(error) ||
163
+ Schema.is(RemoteError)(error) ||
164
+ Schema.is(MissingInstance)(error)
165
+
105
166
  export const publicError = <E extends Schema.Top>(
106
167
  declared: E,
107
168
  error: unknown,
@@ -111,11 +172,9 @@ export const publicError = <E extends Schema.Top>(
111
172
  | RemoteWithdrawn
112
173
  | RemoteError
113
174
  | MissingInstance =>
114
- Schema.is(declared)(error)
175
+ isPublic(error)
115
176
  ? error
116
- : Schema.is(Contract.UndeclaredFailure)(error) ||
117
- Schema.is(RemoteWithdrawn)(error) ||
118
- Schema.is(RemoteError)(error) ||
119
- Schema.is(MissingInstance)(error)
177
+ : // Classify host failures before the declared schema, which may be structural.
178
+ !isInternal(error) && Schema.is(declared)(error)
120
179
  ? error
121
180
  : RemoteError.make({ cause: Cause.fail(error) })