@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.
- package/dist/Auth.d.ts +2 -2
- package/dist/Auth.d.ts.map +1 -1
- package/dist/Auth.js.map +1 -1
- package/dist/{Bootstrap-MCwivGN1.js → Bootstrap-H9gDsgsC.js} +2 -2
- package/dist/{Contract-CcpSIJm4.js → Contract-DsJtisvL.js} +8 -46
- package/dist/Contract.d.ts +50 -53
- package/dist/Contract.d.ts.map +1 -1
- package/dist/Contract.js +1 -1
- package/dist/Contract.js.map +1 -1
- package/dist/{Errors-oPsTLY7l.js → Errors-DYhsGZcZ.js} +14 -1
- package/dist/Errors.d.ts +19 -0
- package/dist/Errors.d.ts.map +1 -1
- package/dist/Errors.js +14 -1
- package/dist/Errors.js.map +1 -1
- package/dist/{FailureGroup-BcH0XOBi.js → FailureGroup-BgT73AaR.js} +14 -4
- package/dist/{Framing-zaYdOJnT.js → Framing-G9eSaeLb.js} +1 -1
- package/dist/{Graft-BsYq3F-J.js → Graft-B71CPA2Y.js} +46 -35
- package/dist/{Packages-B1TPk8pa.js → Packages-AgoCGotL.js} +23 -26
- package/dist/{Peer-IJgFK6mD.js → Peer-DXeVrGBh.js} +5 -5
- package/dist/{ProcessObservation-DEGrEMfP.js → ProcessObservation-gLgGirYv.js} +1 -1
- package/dist/{ServeLifecycle-CJM0gG5B.js → ServeLifecycle-Bd1FPJ6e.js} +1 -1
- package/dist/Testing.d.ts +4 -4
- package/dist/Testing.d.ts.map +1 -1
- package/dist/Testing.js +10 -4
- package/dist/Testing.js.map +1 -1
- package/dist/Transport.d.ts +2 -2
- package/dist/Transport.d.ts.map +1 -1
- package/dist/Transport.js.map +1 -1
- package/dist/bin.js +48 -47
- package/dist/bin.js.map +1 -1
- package/dist/{childRuntime-DSqtFN9o.js → childRuntime-Bm3iSg_N.js} +30 -26
- package/dist/connectionEnded-BwcxQ7W8.js +54 -0
- package/dist/{entry-SYsx9VNb.js → entry-psOpX3Bj.js} +76 -48
- package/dist/host/auth/bearer.d.ts +1 -2
- package/dist/host/auth/bearer.d.ts.map +1 -1
- package/dist/host/auth/bearer.js +1 -1
- package/dist/host/auth/bearer.js.map +1 -1
- package/dist/host/auth/jwt.d.ts +1 -2
- package/dist/host/auth/jwt.d.ts.map +1 -1
- package/dist/host/auth/jwt.js +1 -1
- package/dist/host/auth/jwt.js.map +1 -1
- package/dist/host/auth/mtls.js +2 -2
- package/dist/host/auth/none.js +1 -1
- package/dist/host/command.d.ts +1 -1
- package/dist/host/command.d.ts.map +1 -1
- package/dist/host/command.js +4 -4
- package/dist/host/command.js.map +1 -1
- package/dist/host/local.d.ts +1 -2
- package/dist/host/local.d.ts.map +1 -1
- package/dist/host/local.js +3 -3
- package/dist/host/local.js.map +1 -1
- package/dist/host/unix.d.ts +1 -1
- package/dist/host/unix.d.ts.map +1 -1
- package/dist/host/unix.js +3 -3
- package/dist/host/unix.js.map +1 -1
- package/dist/host/websocket.d.ts +1 -1
- package/dist/host/websocket.d.ts.map +1 -1
- package/dist/host/websocket.js +3 -3
- package/dist/host/websocket.js.map +1 -1
- package/dist/host/worker.d.ts +1 -2
- package/dist/host/worker.d.ts.map +1 -1
- package/dist/host/worker.js +4 -5
- package/dist/host/worker.js.map +1 -1
- package/dist/{importer-D7zSgqxq.js → importer-Cvf88eAY.js} +5 -8
- package/dist/index.d.ts +2 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -10
- package/dist/index.js.map +1 -1
- package/dist/internal/Certificates.js +4 -4
- package/dist/internal/Certificates.js.map +1 -1
- package/dist/internal/FailureGroup.js +3 -2
- package/dist/internal/FailureGroup.js.map +1 -1
- package/dist/internal/assembly.js +9 -2
- package/dist/internal/assembly.js.map +1 -1
- package/dist/internal/auth/mtls.js +1 -1
- package/dist/internal/auth/mtls.js.map +1 -1
- package/dist/internal/auth/tokenCredentials.d.ts +0 -1
- package/dist/internal/auth/tokenCredentials.d.ts.map +1 -1
- package/dist/internal/auth/tokenCredentials.js.map +1 -1
- package/dist/internal/child.js +20 -17
- package/dist/internal/child.js.map +1 -1
- package/dist/internal/childRuntime.js +6 -4
- package/dist/internal/childRuntime.js.map +1 -1
- package/dist/internal/contract.js +26 -0
- package/dist/internal/contract.js.map +1 -0
- package/dist/internal/credentials.d.ts +6 -6
- package/dist/internal/credentials.d.ts.map +1 -1
- package/dist/internal/credentials.js.map +1 -1
- package/dist/internal/directTransport.d.ts +1 -1
- package/dist/internal/entry.d.ts +1 -2
- package/dist/internal/entry.d.ts.map +1 -1
- package/dist/internal/entry.js +4 -14
- package/dist/internal/entry.js.map +1 -1
- package/dist/internal/execution.js +44 -7
- package/dist/internal/execution.js.map +1 -1
- package/dist/internal/host/runner.js +7 -6
- package/dist/internal/host/runner.js.map +1 -1
- package/dist/internal/host.js +5 -5
- package/dist/internal/host.js.map +1 -1
- package/dist/internal/port.d.ts +2 -10
- package/dist/internal/port.js +5 -5
- package/dist/internal/port.js.map +1 -1
- package/dist/internal/release.js +1 -1
- package/dist/internal/release.js.map +1 -1
- package/dist/internal/runner/Connection.d.ts +1 -1
- package/dist/internal/runner/Connection.js +4 -4
- package/dist/internal/runner/Connection.js.map +1 -1
- package/dist/internal/runner/Execution.js +3 -3
- package/dist/internal/runner/Execution.js.map +1 -1
- package/dist/internal/runner/Framing.d.ts +1 -11
- package/dist/internal/runner/Framing.js +1 -1
- package/dist/internal/runner/Framing.js.map +1 -1
- package/dist/internal/runner/Local.js +1 -1
- package/dist/internal/runner/Local.js.map +1 -1
- package/dist/internal/runner/Lock.js +1 -1
- package/dist/internal/runner/Lock.js.map +1 -1
- package/dist/internal/runner/Packages.d.ts +1 -1
- package/dist/internal/runner/Packages.js +22 -25
- package/dist/internal/runner/Packages.js.map +1 -1
- package/dist/internal/runner/Processes.js +7 -9
- package/dist/internal/runner/Processes.js.map +1 -1
- package/dist/internal/runner/Store.js +3 -3
- package/dist/internal/runner/Store.js.map +1 -1
- package/dist/internal/runner/Supervisor.js +46 -47
- package/dist/internal/runner/Supervisor.js.map +1 -1
- package/dist/internal/runner/accept.js +3 -3
- package/dist/internal/runner/accept.js.map +1 -1
- package/dist/internal/runner/model.js +1 -1
- package/dist/internal/runner/model.js.map +1 -1
- package/dist/internal/serve.js +1 -1
- package/dist/internal/serve.js.map +1 -1
- package/dist/internal/services.d.ts +2 -12
- package/dist/internal/services.d.ts.map +1 -1
- package/dist/internal/services.js.map +1 -1
- package/dist/internal/supervisorPlugin.js +1 -1
- package/dist/internal/watchdogMain.js +5 -5
- package/dist/internal/watchdogMain.js.map +1 -1
- package/dist/internal/websocketServer.js +3 -1
- package/dist/internal/websocketServer.js.map +1 -1
- package/dist/internal/workerMain.js +3 -3
- package/dist/{port-Blbh8tms.js → port--3x2zJ4D.js} +8 -8
- package/dist/{release-BY4Mlluy.js → release-DfZPuIcK.js} +1 -1
- package/dist/runner/auth/bearer.js +2 -2
- package/dist/runner/auth/jwt.js +4 -4
- package/dist/runner/auth/jwt.js.map +1 -1
- package/dist/runner/auth/mtls.js +3 -3
- package/dist/runner/auth/none.js +1 -1
- package/dist/runner/index.js +5 -5
- package/dist/runner/stdio.js +3 -3
- package/dist/runner/unix.js +3 -3
- package/dist/runner/websocket.js +4 -4
- package/dist/{socketChannel-KmtzF-9G.js → socketChannel-CJvL2DiB.js} +2 -2
- package/dist/{supervisorPlugin-Inb1S5IV.js → supervisorPlugin-t6Z6PrhD.js} +72 -76
- package/dist/{token-v5ne2I0-.js → token-CYBNNlhS.js} +1 -1
- package/dist/{tokenCredentials-WUJm2AKm.js → tokenCredentials-CbCuk-Rt.js} +3 -3
- package/dist/{websocketServer-MXcCJx0v.js → websocketServer-NQhODlEt.js} +5 -3
- package/dist/{workerChannel-P82YdNjh.js → workerChannel-C8hhBJzA.js} +1 -1
- package/package.json +3 -3
- package/src/Auth.ts +9 -2
- package/src/Contract.ts +67 -51
- package/src/Errors.ts +23 -0
- package/src/Testing.ts +16 -2
- package/src/Transport.ts +6 -2
- package/src/bin.ts +28 -30
- package/src/host/auth/bearer.ts +1 -6
- package/src/host/auth/jwt.ts +1 -6
- package/src/host/command.ts +2 -0
- package/src/host/local.ts +5 -9
- package/src/host/unix.ts +2 -0
- package/src/host/websocket.ts +2 -0
- package/src/host/worker.ts +4 -6
- package/src/index.ts +8 -4
- package/src/internal/Certificates.ts +10 -13
- package/src/internal/FailureGroup.ts +128 -121
- package/src/internal/assembly.ts +19 -10
- package/src/internal/auth/mtls.ts +19 -20
- package/src/internal/auth/tokenCredentials.ts +1 -7
- package/src/internal/child.ts +249 -240
- package/src/internal/childRuntime.ts +84 -81
- package/src/internal/contract.ts +47 -0
- package/src/internal/credentials.ts +12 -9
- package/src/internal/entry.ts +11 -25
- package/src/internal/execution.ts +73 -14
- package/src/internal/host/runner.ts +153 -153
- package/src/internal/host.ts +123 -130
- package/src/internal/port.ts +100 -103
- package/src/internal/release.ts +3 -2
- package/src/internal/runner/Connection.ts +52 -60
- package/src/internal/runner/Execution.ts +163 -164
- package/src/internal/runner/Framing.ts +9 -10
- package/src/internal/runner/Local.ts +26 -27
- package/src/internal/runner/Lock.ts +23 -25
- package/src/internal/runner/Packages.ts +67 -70
- package/src/internal/runner/Processes.ts +89 -92
- package/src/internal/runner/Store.ts +110 -114
- package/src/internal/runner/Supervisor.ts +392 -405
- package/src/internal/runner/accept.ts +76 -84
- package/src/internal/runner/model.ts +20 -21
- package/src/internal/serve.ts +15 -13
- package/src/internal/services.ts +1 -19
- package/src/internal/watchdogMain.ts +16 -11
- package/src/internal/websocketServer.ts +18 -3
- package/src/runner/auth/jwt.ts +10 -6
- package/dist/cleanup-BPWr-5U9.js +0 -13
- package/dist/connectionEnded-DUgcobEd.js +0 -9
- package/dist/internal/childErrors.d.ts +0 -33
- package/dist/internal/childErrors.d.ts.map +0 -1
- package/dist/internal/port.d.ts.map +0 -1
- package/dist/internal/runner/Framing.d.ts.map +0 -1
|
@@ -10,94 +10,86 @@ import * as Multiplex from "./Multiplex"
|
|
|
10
10
|
import * as Wire from "./Wire"
|
|
11
11
|
import { SessionAccessDenied, SessionConflict, type Handle } from "./model"
|
|
12
12
|
|
|
13
|
-
export const accept = (
|
|
13
|
+
export const accept = Effect.fnUntraced(function* (
|
|
14
14
|
supervisor: typeof Supervisor.Service,
|
|
15
15
|
execution: typeof Channels.Service,
|
|
16
16
|
channel: Channel,
|
|
17
|
-
)
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
instance,
|
|
17
|
+
) {
|
|
18
|
+
const identity = yield* Peer
|
|
19
|
+
const scope = yield* Effect.scope
|
|
20
|
+
const mux = yield* Multiplex.make(channel)
|
|
21
|
+
const peer = yield* Port.make(Wire.channel(mux, 0), {
|
|
22
|
+
session: "session-v1",
|
|
23
|
+
serve: { session: Wire.Session },
|
|
24
|
+
call: {},
|
|
25
|
+
})
|
|
26
|
+
const attached = yield* Ref.make(Option.none<string>())
|
|
27
|
+
const loading = yield* Semaphore.make(1)
|
|
28
|
+
const authorize = (handle: Handle) =>
|
|
29
|
+
handle.key.identity === identity
|
|
30
|
+
? Effect.void
|
|
31
|
+
: Effect.fail(
|
|
32
|
+
SessionAccessDenied.make({
|
|
33
|
+
detail: "The session belongs to another authenticated identity",
|
|
34
|
+
}),
|
|
35
|
+
)
|
|
36
|
+
const handlers = yield* Wire.Session.toHandlers({
|
|
37
|
+
HighWater: ({ instance }) => supervisor.highWater({ identity, instance }),
|
|
38
|
+
Open: ({ instance, requestId, expectedGeneration, leaseMillis, limits }) =>
|
|
39
|
+
supervisor.open({
|
|
40
|
+
key: { identity, instance },
|
|
41
41
|
requestId,
|
|
42
42
|
expectedGeneration,
|
|
43
|
-
leaseMillis,
|
|
43
|
+
...(leaseMillis === undefined ? {} : { lease: leaseMillis }),
|
|
44
44
|
limits,
|
|
45
|
-
})
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
})
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
return code
|
|
88
|
-
}).pipe(loading.withPermit),
|
|
89
|
-
Renew: (handle) =>
|
|
90
|
-
authorize(handle).pipe(Effect.andThen(supervisor.renew(handle))),
|
|
91
|
-
Dispose: (handle) =>
|
|
92
|
-
authorize(handle).pipe(Effect.andThen(supervisor.dispose(handle))),
|
|
93
|
-
Status: (handle) =>
|
|
94
|
-
authorize(handle).pipe(Effect.andThen(supervisor.status(handle))),
|
|
95
|
-
})
|
|
96
|
-
return yield* RpcServer.make(Wire.Session, {
|
|
97
|
-
disableFatalDefects: true,
|
|
98
|
-
}).pipe(
|
|
99
|
-
Effect.provideContext(handlers),
|
|
100
|
-
Effect.provideService(RpcServer.Protocol, peer.serverProtocol("session")),
|
|
101
|
-
Effect.raceFirst(mux.await),
|
|
102
|
-
)
|
|
45
|
+
}),
|
|
46
|
+
Load: Effect.fnUntraced(function* ({ handle, ...request }) {
|
|
47
|
+
yield* authorize(handle)
|
|
48
|
+
const attachment = yield* Ref.get(attached)
|
|
49
|
+
if (Option.isSome(attachment) && attachment.value !== handle.token)
|
|
50
|
+
return yield* SessionConflict.make({
|
|
51
|
+
detail: "A connection can attach only one execution",
|
|
52
|
+
})
|
|
53
|
+
const code = yield* supervisor.load(handle, request)
|
|
54
|
+
if (Option.isNone(attachment)) {
|
|
55
|
+
const child = yield* execution
|
|
56
|
+
.peer(handle.token)
|
|
57
|
+
.pipe(Scope.provide(scope))
|
|
58
|
+
yield* Ref.set(attached, Option.some(handle.token))
|
|
59
|
+
// A child EOF must not destroy the session channel before Dispose can acknowledge exit.
|
|
60
|
+
yield* Effect.all(
|
|
61
|
+
[
|
|
62
|
+
Effect.forever(
|
|
63
|
+
Effect.flatMap(mux.take(1), (bytes) => child.send(1, bytes)),
|
|
64
|
+
),
|
|
65
|
+
Effect.forever(
|
|
66
|
+
Effect.flatMap(child.take(1), (bytes) => mux.send(1, bytes)),
|
|
67
|
+
),
|
|
68
|
+
],
|
|
69
|
+
{ concurrency: "unbounded" },
|
|
70
|
+
).pipe(
|
|
71
|
+
Effect.catchCause((cause) =>
|
|
72
|
+
Cause.hasInterruptsOnly(cause)
|
|
73
|
+
? Effect.void
|
|
74
|
+
: child.fail(TransportError.make({ cause })),
|
|
75
|
+
),
|
|
76
|
+
Effect.forkIn(scope),
|
|
77
|
+
)
|
|
78
|
+
}
|
|
79
|
+
return code
|
|
80
|
+
}, loading.withPermit),
|
|
81
|
+
Renew: (handle) =>
|
|
82
|
+
authorize(handle).pipe(Effect.andThen(supervisor.renew(handle))),
|
|
83
|
+
Dispose: (handle) =>
|
|
84
|
+
authorize(handle).pipe(Effect.andThen(supervisor.dispose(handle))),
|
|
85
|
+
Status: (handle) =>
|
|
86
|
+
authorize(handle).pipe(Effect.andThen(supervisor.status(handle))),
|
|
103
87
|
})
|
|
88
|
+
return yield* RpcServer.make(Wire.Session, {
|
|
89
|
+
disableFatalDefects: true,
|
|
90
|
+
}).pipe(
|
|
91
|
+
Effect.provideContext(handlers),
|
|
92
|
+
Effect.provideService(RpcServer.Protocol, peer.serverProtocol("session")),
|
|
93
|
+
Effect.raceFirst(mux.await),
|
|
94
|
+
)
|
|
95
|
+
})
|
|
@@ -337,28 +337,27 @@ export class RemoteTerminationUnconfirmed extends Schema.TaggedError<
|
|
|
337
337
|
{ readonly brand: unique symbol }
|
|
338
338
|
>()("RemoteTerminationUnconfirmed", { handle: Handle }) {}
|
|
339
339
|
/** Losing contact never becomes a successful stop merely because a lease duration passed. */
|
|
340
|
-
export const awaitTermination = <E, R>(
|
|
340
|
+
export const awaitTermination = Effect.fnUntraced(function* <E, R>(
|
|
341
341
|
handle: Handle,
|
|
342
342
|
confirmation: Effect.Effect<Termination, E, R>,
|
|
343
343
|
leaseMillis: number,
|
|
344
344
|
marginMillis: number,
|
|
345
|
-
)
|
|
346
|
-
Effect.
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
if (result.
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
})
|
|
345
|
+
) {
|
|
346
|
+
const [elapsed, result] = yield* Effect.exit(
|
|
347
|
+
Effect.timeoutOption(confirmation, leaseMillis + marginMillis),
|
|
348
|
+
).pipe(Effect.timed)
|
|
349
|
+
if (result._tag === "Success") {
|
|
350
|
+
if (Option.isSome(result.value)) return result.value.value
|
|
351
|
+
return yield* RemoteTerminationUnconfirmed.make({ handle })
|
|
352
|
+
}
|
|
353
|
+
// Confirmation and the disconnected wait share one deadline.
|
|
354
|
+
yield* Effect.sleep(
|
|
355
|
+
Math.max(0, leaseMillis + marginMillis - Duration.toMillis(elapsed)),
|
|
356
|
+
)
|
|
357
|
+
return yield* Effect.failCause(
|
|
358
|
+
Cause.combine(
|
|
359
|
+
result.cause,
|
|
360
|
+
Cause.fail(RemoteTerminationUnconfirmed.make({ handle })),
|
|
361
|
+
),
|
|
362
|
+
)
|
|
363
|
+
})
|
package/src/internal/serve.ts
CHANGED
|
@@ -69,19 +69,21 @@ const ready = Plugin.make({
|
|
|
69
69
|
})
|
|
70
70
|
|
|
71
71
|
/** Loader logs child cleanup errors; the supervisor's release signal also reaches the command exit. */
|
|
72
|
-
const close = (
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
)
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
72
|
+
const close = Effect.fnUntraced(function* (
|
|
73
|
+
entries: Fork.Fork,
|
|
74
|
+
lifecycle: typeof ServeLifecycle.Service,
|
|
75
|
+
) {
|
|
76
|
+
const disposed = yield* Effect.exit(entries.dispose)
|
|
77
|
+
const released = yield* Effect.exit(Deferred.await(lifecycle.released))
|
|
78
|
+
const cause = Array.reduce(
|
|
79
|
+
[disposed, released],
|
|
80
|
+
Cause.empty,
|
|
81
|
+
(cause: Cause.Cause<unknown>, exit: Exit.Exit<void, unknown>) =>
|
|
82
|
+
Exit.isFailure(exit) ? Cause.combine(cause, exit.cause) : cause,
|
|
83
|
+
)
|
|
84
|
+
if (cause.reasons.length > 0)
|
|
85
|
+
return yield* Effect.failCause(cleanupCause(cause))
|
|
86
|
+
})
|
|
85
87
|
|
|
86
88
|
const load = Effect.fnUntraced(function* (config: string, directory: string) {
|
|
87
89
|
const lifecycle = yield* make
|
package/src/internal/services.ts
CHANGED
|
@@ -1,27 +1,9 @@
|
|
|
1
1
|
import { Array, Context, Effect, Record } from "effect"
|
|
2
2
|
import { Graft } from "@graftland/graft"
|
|
3
3
|
import { RpcClient, RpcServer } from "effect/rpc"
|
|
4
|
-
import type { Scope } from "effect"
|
|
5
4
|
import type { Rpc, RpcClientError, RpcGroup } from "effect/rpc"
|
|
6
|
-
import type
|
|
5
|
+
import type { Service } from "../Contract"
|
|
7
6
|
|
|
8
|
-
type Peer = Port.Port
|
|
9
|
-
|
|
10
|
-
/** RPC types stay inside the descriptor; Graft supplies its dynamic activation context. */
|
|
11
|
-
export interface Service<R = never, ClientR = never> {
|
|
12
|
-
readonly key: Context.Key<unknown, unknown>
|
|
13
|
-
readonly group: Pick<RpcGroup.RpcGroup<Rpc.Any>, "requests">
|
|
14
|
-
readonly serve: (
|
|
15
|
-
port: Pick<Peer, "serverProtocol">,
|
|
16
|
-
) => Effect.Effect<never, never, R>
|
|
17
|
-
readonly publish: (
|
|
18
|
-
port: Pick<Peer, "clientProtocol">,
|
|
19
|
-
) => Effect.Effect<
|
|
20
|
-
void,
|
|
21
|
-
Graft.ServiceConflict,
|
|
22
|
-
Graft.Graft | Scope.Scope | ClientR
|
|
23
|
-
>
|
|
24
|
-
}
|
|
25
7
|
export const service = <
|
|
26
8
|
I,
|
|
27
9
|
S,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/** Executable worker: fd 4 and the lease timer remain independent of the plugin thread. */
|
|
2
2
|
import { NodeRuntime, NodeStream } from "@effect/platform-node"
|
|
3
|
-
import { Effect, FiberHandle, Ref, Schema, Stream } from "effect"
|
|
3
|
+
import { Clock, Effect, FiberHandle, Ref, Schema, Stream } from "effect"
|
|
4
4
|
import { Socket } from "node:net"
|
|
5
5
|
import { parentPort } from "node:worker_threads"
|
|
6
6
|
import process from "node:process"
|
|
@@ -17,14 +17,19 @@ const notify = (notice: typeof Notice.Type) =>
|
|
|
17
17
|
Effect.sync(() => parentPort?.postMessage(message)),
|
|
18
18
|
),
|
|
19
19
|
)
|
|
20
|
-
|
|
21
|
-
const
|
|
22
|
-
Effect.
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
20
|
+
// Milliseconds on the monotonic clock, which the lease sleep also uses.
|
|
21
|
+
const now = Clock.monotonicTimeNanos.pipe(
|
|
22
|
+
Effect.map((nanos) => Number(nanos) / 1_000_000),
|
|
23
|
+
)
|
|
24
|
+
const expire = Effect.fnUntraced(function* (
|
|
25
|
+
deadline: number,
|
|
26
|
+
): Effect.fn.Return<never> {
|
|
27
|
+
const remaining = deadline - (yield* now)
|
|
28
|
+
if (remaining <= 0) return yield* die
|
|
29
|
+
// The clock splits sleeps longer than the platform timer limit.
|
|
30
|
+
yield* Effect.sleep(remaining)
|
|
31
|
+
return yield* expire(deadline)
|
|
32
|
+
})
|
|
28
33
|
const main = Effect.scoped(
|
|
29
34
|
Effect.gen(function* () {
|
|
30
35
|
const lease = yield* Ref.make({
|
|
@@ -45,8 +50,8 @@ const main = Effect.scoped(
|
|
|
45
50
|
Stream.decodeText(),
|
|
46
51
|
Stream.splitLines,
|
|
47
52
|
Stream.mapEffect((line) => Schema.decodeEffect(CommandJson)(line)),
|
|
48
|
-
Stream.runForEach(
|
|
49
|
-
Effect.
|
|
53
|
+
Stream.runForEach(
|
|
54
|
+
Effect.fnUntraced(function* (command: typeof CommandJson.Type) {
|
|
50
55
|
if (command.kind === "start") return yield* notify("start")
|
|
51
56
|
if (command.kind === "stop") {
|
|
52
57
|
yield* Ref.update(lease, (state) => ({ ...state, stopped: true }))
|
|
@@ -12,12 +12,27 @@ import {
|
|
|
12
12
|
import { HttpServerRequest, HttpServerResponse } from "effect/http"
|
|
13
13
|
import type { Socket } from "effect/socket"
|
|
14
14
|
import { TLSSocket } from "node:tls"
|
|
15
|
-
import {
|
|
15
|
+
import {
|
|
16
|
+
type AuthenticationFailed,
|
|
17
|
+
type AuthenticatorUnavailable,
|
|
18
|
+
TransportError,
|
|
19
|
+
} from "../Errors"
|
|
16
20
|
import type { Accept, Handshake, Serving } from "../Transport"
|
|
17
21
|
import * as Channel from "./socketChannel"
|
|
18
22
|
import { path, protocol, payloadLimit } from "./websocket"
|
|
19
23
|
|
|
20
|
-
const rejection = (error: AuthenticationFailed) =>
|
|
24
|
+
const rejection = (error: AuthenticationFailed | AuthenticatorUnavailable) =>
|
|
25
|
+
error._tag === "AuthenticatorUnavailable"
|
|
26
|
+
? unavailable(error)
|
|
27
|
+
: unauthorized(error)
|
|
28
|
+
|
|
29
|
+
// The credential was not judged, so the client is told to retry rather than to replace it.
|
|
30
|
+
const unavailable = (error: AuthenticatorUnavailable) =>
|
|
31
|
+
Effect.logError("Remote host authenticator is unavailable", error.cause).pipe(
|
|
32
|
+
Effect.as(HttpServerResponse.empty({ status: 503 })),
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
const unauthorized = (error: AuthenticationFailed) =>
|
|
21
36
|
Effect.logWarning(
|
|
22
37
|
"Remote host authentication failed",
|
|
23
38
|
{
|
|
@@ -83,7 +98,7 @@ const open = Effect.fnUntraced(function* (
|
|
|
83
98
|
run: <A, E, R>(
|
|
84
99
|
accept: Effect.Effect<
|
|
85
100
|
(socket: Socket.Socket) => Effect.Effect<A, E, R>,
|
|
86
|
-
AuthenticationFailed,
|
|
101
|
+
AuthenticationFailed | AuthenticatorUnavailable,
|
|
87
102
|
HttpServerRequest.HttpServerRequest
|
|
88
103
|
>,
|
|
89
104
|
) =>
|
package/src/runner/auth/jwt.ts
CHANGED
|
@@ -14,7 +14,7 @@ import { Signature } from "effect/crypto"
|
|
|
14
14
|
import { HttpClient } from "effect/http"
|
|
15
15
|
import { Authenticator } from "../../Auth"
|
|
16
16
|
import { ConfigDirectory } from "@graftland/loader"
|
|
17
|
-
import { AuthenticationFailed } from "../../Errors"
|
|
17
|
+
import { AuthenticationFailed, AuthenticatorUnavailable } from "../../Errors"
|
|
18
18
|
import * as Token from "../../internal/auth/token"
|
|
19
19
|
|
|
20
20
|
export const ClockTolerance = Schema.DurationFromString.check(
|
|
@@ -97,12 +97,16 @@ export default Plugin.make({
|
|
|
97
97
|
verified.claims[config.identityClaim],
|
|
98
98
|
),
|
|
99
99
|
),
|
|
100
|
+
// An unreachable key set says nothing about the token; the client must not discard it.
|
|
100
101
|
Effect.mapError((error) =>
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
102
|
+
error._tag === "JoseError" &&
|
|
103
|
+
error.reason._tag === "KeySetUnavailable"
|
|
104
|
+
? AuthenticatorUnavailable.make({ cause: Cause.fail(error) })
|
|
105
|
+
: AuthenticationFailed.make({
|
|
106
|
+
reason: "invalid",
|
|
107
|
+
challenge: 'Bearer error="invalid_token"',
|
|
108
|
+
cause: Cause.fail(error),
|
|
109
|
+
}),
|
|
106
110
|
),
|
|
107
111
|
Effect.provideService(Signature.Signature, signature),
|
|
108
112
|
Effect.provideContext(services),
|
package/dist/cleanup-BPWr-5U9.js
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { f as CleanupError } from "./Graft-BsYq3F-J.js";
|
|
2
|
-
import { n as close } from "./release-BY4Mlluy.js";
|
|
3
|
-
import { Array, Cause, Effect, Schema, Scope } from "effect";
|
|
4
|
-
// packages/remote/src/internal/cleanup.ts
|
|
5
|
-
/** Finalizers have no typed failure channel. Keep reasons and their annotations flat. */
|
|
6
|
-
const cleanupCause = (cause) => Cause.fromReasons(Array.flatMap(cause.reasons, (reason) => {
|
|
7
|
-
const error = reason._tag === "Fail" ? reason.error : reason._tag === "Die" ? reason.defect : void 0;
|
|
8
|
-
if (Schema.is(CleanupError)(error)) return Array.map(cleanupCause(error.cause).reasons, (inner) => inner.annotate(Cause.reasonAnnotations(reason)));
|
|
9
|
-
return [reason._tag === "Fail" ? Cause.makeDieReason(reason.error).annotate(Cause.reasonAnnotations(reason)) : reason];
|
|
10
|
-
}));
|
|
11
|
-
/** Assembly children close before the entry reports their cleanup as its own result. */
|
|
12
|
-
const children = Effect.acquireRelease(Scope.make(), (scope, exit) => close(scope, exit).pipe(Effect.catchCause((cause) => Effect.failCause(cleanupCause(cause)))));
|
|
13
|
-
export { cleanupCause as n, children as t };
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { c as TransportError } from "./Errors-oPsTLY7l.js";
|
|
2
|
-
import { t as EndOfStream } from "./Framing-zaYdOJnT.js";
|
|
3
|
-
import { t as Peer } from "./Peer-IJgFK6mD.js";
|
|
4
|
-
import { Array, Cause, Effect, Schema } from "effect";
|
|
5
|
-
import { Socket } from "effect/socket";
|
|
6
|
-
// packages/remote/src/internal/runner/connectionEnded.ts
|
|
7
|
-
const closedNormally = (cause) => cause.reasons.length > 0 && Array.every(cause.reasons, (reason) => reason._tag === "Fail" && (Schema.is(TransportError)(reason.error) ? closedNormally(reason.error.cause) : Schema.is(EndOfStream)(reason.error) || Socket.isSocketError(reason.error) && reason.error.reason._tag === "SocketCloseError" && reason.error.reason.code === 1e3));
|
|
8
|
-
const connectionEnded = (cause) => Cause.hasInterruptsOnly(cause) || closedNormally(cause) ? Effect.void : Effect.flatMap(Peer, (identity) => Effect.logWarning("Remote host connection failed", cause).pipe(Effect.annotateLogs({ "remote.peer": identity })));
|
|
9
|
-
export { connectionEnded as n, closedNormally as t };
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import { Schema } from "effect";
|
|
2
|
-
declare const AlreadyLoaded_base: Schema.Class<AlreadyLoaded, Schema.TaggedStruct<"AlreadyLoaded", {}>, import("effect/Cause").YieldableError & {
|
|
3
|
-
readonly brand: unique symbol;
|
|
4
|
-
}>;
|
|
5
|
-
export declare class AlreadyLoaded extends AlreadyLoaded_base {}
|
|
6
|
-
declare const ContractNotFound_base: Schema.Class<ContractNotFound, Schema.TaggedStruct<"ContractNotFound", {
|
|
7
|
-
readonly module: Schema.String;
|
|
8
|
-
}>, import("effect/Cause").YieldableError & {
|
|
9
|
-
readonly brand: unique symbol;
|
|
10
|
-
}>;
|
|
11
|
-
export declare class ContractNotFound extends ContractNotFound_base {
|
|
12
|
-
get message(): string;
|
|
13
|
-
}
|
|
14
|
-
declare const ModuleImportFailed_base: Schema.Class<ModuleImportFailed, Schema.TaggedStruct<"ModuleImportFailed", {
|
|
15
|
-
readonly module: Schema.String;
|
|
16
|
-
readonly cause: Schema.Defect;
|
|
17
|
-
}>, import("effect/Cause").YieldableError & {
|
|
18
|
-
readonly brand: unique symbol;
|
|
19
|
-
}>;
|
|
20
|
-
export declare class ModuleImportFailed extends ModuleImportFailed_base {}
|
|
21
|
-
declare const ActivationFailed_base: Schema.Class<ActivationFailed, Schema.TaggedStruct<"ActivationFailed", {
|
|
22
|
-
readonly detail: Schema.String;
|
|
23
|
-
readonly cause: Schema.optionalKey<Schema.Cause<Schema.Defect, Schema.Defect>>;
|
|
24
|
-
}>, import("effect/Cause").YieldableError & {
|
|
25
|
-
readonly brand: unique symbol;
|
|
26
|
-
}>;
|
|
27
|
-
export declare class ActivationFailed extends ActivationFailed_base {
|
|
28
|
-
get message(): string;
|
|
29
|
-
}
|
|
30
|
-
export declare const ChildFailure: Schema.Union<readonly [typeof AlreadyLoaded, typeof ContractNotFound, typeof ModuleImportFailed, typeof ActivationFailed]>;
|
|
31
|
-
export type ChildFailure = typeof ChildFailure.Type;
|
|
32
|
-
export {};
|
|
33
|
-
//# sourceMappingURL=childErrors.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"childErrors.d.ts","names":[],"sources":["../../src/internal/childErrors.ts"],"mappings":";;WAImB;;qBAFN,sBAAsB;;;;WAMhB;;qBAFN,yBAAyB;MAIxB;;;;;;WAMK;;qBAFN,2BAA2B;;;;;WASrB;;qBAFN,yBAAyB;MAYxB;;qBAID,cAAY,OAAA,uBAAA,sBAAA,yBAAA,2BAAA;YAMb,sBAAsB,aAAa"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"port.d.ts","names":[],"sources":["../../src/internal/port.ts"],"mappings":";;;;;iBAgDiB;WACP,iBAAiB,qBAAqB,UAAU;WAChD,iBAAiB,qBAAqB,UAAU;WAChD,OAAO,OAAO,cAAc;WAC5B,OAAO,OAAO,mBAAmB,OAAO;WACxC,KAAK,OAAO,aAAa"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Framing.d.ts","names":[],"sources":["../../../src/internal/runner/Framing.ts"],"mappings":";;;;WAImB;;qBAFN,mBAAmB;MAIlB"}
|