@graftland/plugin-remote 0.3.2 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +18 -54
- package/README.zh-CN.md +17 -51
- package/README.zh-TW.md +17 -51
- package/dist/Auth.d.ts.map +1 -1
- package/dist/Auth.js.map +1 -1
- package/dist/Config.d.ts +1151 -0
- package/dist/Config.d.ts.map +1 -0
- package/dist/Config.js +183 -0
- package/dist/Config.js.map +1 -0
- package/dist/Contract.d.ts +1 -1
- package/dist/Contract.d.ts.map +1 -1
- package/dist/Contract.js +32 -1
- package/dist/Contract.js.map +1 -1
- package/dist/Instance.d.ts.map +1 -1
- package/dist/Instance.js.map +1 -1
- package/dist/Testing.d.ts +1 -1
- package/dist/Testing.d.ts.map +1 -1
- package/dist/Testing.js.map +1 -1
- package/dist/Transport.d.ts +1 -1
- package/dist/Transport.d.ts.map +1 -1
- package/dist/Transport.js.map +1 -1
- package/dist/cli.d.ts +4 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +25 -0
- package/dist/cli.js.map +1 -0
- package/dist/host/auth/bearer.d.ts +9 -1
- package/dist/host/auth/bearer.d.ts.map +1 -1
- package/dist/host/auth/bearer.js +4 -2
- package/dist/host/auth/bearer.js.map +1 -1
- package/dist/host/auth/jwt.d.ts +9 -1
- package/dist/host/auth/jwt.d.ts.map +1 -1
- package/dist/host/auth/jwt.js +4 -2
- package/dist/host/auth/jwt.js.map +1 -1
- package/dist/host/auth/mtls.d.ts +10 -7
- package/dist/host/auth/mtls.d.ts.map +1 -1
- package/dist/host/auth/mtls.js +13 -14
- package/dist/host/auth/mtls.js.map +1 -1
- package/dist/host/auth/none.d.ts +3 -1
- package/dist/host/auth/none.js +7 -5
- package/dist/host/auth/none.js.map +1 -1
- package/dist/host/command.d.ts +14 -1
- package/dist/host/command.d.ts.map +1 -1
- package/dist/host/command.js +11 -9
- package/dist/host/command.js.map +1 -1
- package/dist/host/local.d.ts +2 -1
- package/dist/host/local.d.ts.map +1 -1
- package/dist/host/local.js +9 -30
- package/dist/host/local.js.map +1 -1
- package/dist/host/unix.d.ts +6 -1
- package/dist/host/unix.d.ts.map +1 -1
- package/dist/host/unix.js +13 -9
- package/dist/host/unix.js.map +1 -1
- package/dist/host/websocket.d.ts +10 -1
- package/dist/host/websocket.d.ts.map +1 -1
- package/dist/host/websocket.js +11 -8
- package/dist/host/websocket.js.map +1 -1
- package/dist/host/worker.d.ts +3 -1
- package/dist/host/worker.d.ts.map +1 -1
- package/dist/host/worker.js +13 -9
- package/dist/host/worker.js.map +1 -1
- package/dist/index.d.ts +6 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +30 -64
- package/dist/index.js.map +1 -1
- package/dist/internal/Certificates.js.map +1 -1
- package/dist/internal/FailureGroup.js +6 -6
- package/dist/internal/FailureGroup.js.map +1 -1
- package/dist/internal/Peer.js.map +1 -1
- package/dist/internal/{ServeLifecycle.js → RunnerLifecycle.js} +6 -6
- package/dist/internal/RunnerLifecycle.js.map +1 -0
- package/dist/internal/Supervisor.js.map +1 -1
- package/dist/internal/assembly.d.ts +3 -2
- package/dist/internal/assembly.js +8 -8
- package/dist/internal/assembly.js.map +1 -1
- package/dist/internal/auth/config.d.ts +27 -0
- package/dist/internal/auth/config.d.ts.map +1 -0
- package/dist/internal/auth/config.js +29 -0
- package/dist/internal/auth/config.js.map +1 -0
- package/dist/internal/auth/mtls.js.map +1 -1
- package/dist/internal/auth/token.js.map +1 -1
- package/dist/internal/auth/tokenCredentials.d.ts +2 -1
- package/dist/internal/auth/tokenCredentials.d.ts.map +1 -1
- package/dist/internal/auth/tokenCredentials.js +1 -1
- package/dist/internal/auth/tokenCredentials.js.map +1 -1
- package/dist/internal/child.js +3 -3
- package/dist/internal/child.js.map +1 -1
- package/dist/internal/childMain.js +47 -0
- package/dist/internal/childMain.js.map +1 -0
- package/dist/internal/childRuntime.js +8 -8
- package/dist/internal/childRuntime.js.map +1 -1
- package/dist/internal/cleanup.js +3 -3
- package/dist/internal/cleanup.js.map +1 -1
- package/dist/internal/contract.js.map +1 -1
- package/dist/internal/credentials.d.ts +3 -2
- package/dist/internal/credentials.d.ts.map +1 -1
- package/dist/internal/credentials.js +1 -1
- package/dist/internal/credentials.js.map +1 -1
- package/dist/internal/directTransport.js.map +1 -1
- package/dist/internal/entry.d.ts +493 -3
- package/dist/internal/entry.d.ts.map +1 -1
- package/dist/internal/entry.js +22 -9
- package/dist/internal/entry.js.map +1 -1
- package/dist/internal/entryConfig.d.ts +2 -202
- package/dist/internal/entryConfig.js +2 -136
- package/dist/internal/entryConfig.js.map +1 -1
- package/dist/internal/execution.d.ts +4 -4
- package/dist/internal/execution.js +11 -11
- package/dist/internal/execution.js.map +1 -1
- package/dist/internal/follow.js +1 -1
- package/dist/internal/follow.js.map +1 -1
- package/dist/internal/forkTree.js.map +1 -1
- package/dist/internal/host/local.js.map +1 -1
- package/dist/internal/host/runner.js +4 -4
- package/dist/internal/host/runner.js.map +1 -1
- package/dist/internal/host.js +2 -2
- package/dist/internal/host.js.map +1 -1
- package/dist/internal/importer.js +1 -1
- package/dist/internal/importer.js.map +1 -1
- package/dist/internal/listenerStartup.js +1 -1
- package/dist/internal/listenerStartup.js.map +1 -1
- package/dist/internal/loadModule.js.map +1 -1
- package/dist/internal/platform.js +1 -9
- package/dist/internal/port.d.ts +1 -1
- package/dist/internal/port.js +2 -2
- package/dist/internal/port.js.map +1 -1
- package/dist/internal/runner/Bootstrap.js.map +1 -1
- package/dist/internal/runner/Connection.d.ts +3 -2
- package/dist/internal/runner/Connection.js +6 -6
- package/dist/internal/runner/Connection.js.map +1 -1
- package/dist/internal/runner/Execution.js +6 -6
- package/dist/internal/runner/Execution.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.map +1 -1
- package/dist/internal/runner/Multiplex.js.map +1 -1
- package/dist/internal/runner/Packages.js.map +1 -1
- package/dist/internal/runner/ProcessObservation.js.map +1 -1
- package/dist/internal/runner/Processes.js.map +1 -1
- package/dist/internal/runner/Retention.js.map +1 -1
- package/dist/internal/runner/Store.js.map +1 -1
- package/dist/internal/runner/Supervisor.js +5 -5
- package/dist/internal/runner/Supervisor.js.map +1 -1
- package/dist/internal/runner/Watchdog.js.map +1 -1
- package/dist/internal/runner/Wire.d.ts +1 -1
- package/dist/internal/runner/Wire.js.map +1 -1
- package/dist/internal/runner/accept.js +2 -2
- package/dist/internal/runner/accept.js.map +1 -1
- package/dist/internal/runner/command.js +1 -1
- package/dist/internal/runner/command.js.map +1 -1
- package/dist/internal/runner/connectionEnded.js +1 -1
- package/dist/internal/runner/connectionEnded.js.map +1 -1
- package/dist/internal/runner/model.d.ts.map +1 -1
- package/dist/internal/runner/model.js.map +1 -1
- package/dist/internal/services.d.ts.map +1 -1
- package/dist/internal/services.js +1 -1
- package/dist/internal/services.js.map +1 -1
- package/dist/internal/socketChannel.js.map +1 -1
- package/dist/internal/stdioChannel.js.map +1 -1
- package/dist/internal/supervisorPlugin.js +48 -1
- package/dist/internal/supervisorPlugin.js.map +1 -1
- package/dist/internal/transportOptions.d.ts.map +1 -1
- package/dist/internal/watchdogMain.js +5 -3
- package/dist/internal/watchdogMain.js.map +1 -1
- package/dist/internal/websocket.js.map +1 -1
- package/dist/internal/websocketServer.js +1 -1
- package/dist/internal/websocketServer.js.map +1 -1
- package/dist/internal/workerChannel.js.map +1 -1
- package/dist/internal/workerMain.js +13 -6
- package/dist/internal/workerMain.js.map +1 -1
- package/dist/runner/auth/bearer.d.ts +8 -5
- package/dist/runner/auth/bearer.d.ts.map +1 -1
- package/dist/runner/auth/bearer.js +13 -11
- package/dist/runner/auth/bearer.js.map +1 -1
- package/dist/runner/auth/jwt.d.ts +30 -17
- package/dist/runner/auth/jwt.d.ts.map +1 -1
- package/dist/runner/auth/jwt.js +16 -28
- package/dist/runner/auth/jwt.js.map +1 -1
- package/dist/runner/auth/mtls.d.ts +8 -6
- package/dist/runner/auth/mtls.d.ts.map +1 -1
- package/dist/runner/auth/mtls.js +13 -29
- package/dist/runner/auth/mtls.js.map +1 -1
- package/dist/runner/auth/none.d.ts +7 -1
- package/dist/runner/auth/none.js +7 -5
- package/dist/runner/auth/none.js.map +1 -1
- package/dist/runner/index.d.ts +5 -1
- package/dist/runner/index.d.ts.map +1 -1
- package/dist/runner/index.js +62 -30
- package/dist/runner/index.js.map +1 -1
- package/dist/runner/stdio.d.ts +6 -1
- package/dist/runner/stdio.d.ts.map +1 -1
- package/dist/runner/stdio.js +11 -9
- package/dist/runner/stdio.js.map +1 -1
- package/dist/runner/unix.d.ts +6 -1
- package/dist/runner/unix.d.ts.map +1 -1
- package/dist/runner/unix.js +10 -8
- package/dist/runner/unix.js.map +1 -1
- package/dist/runner/websocket.d.ts +24 -1
- package/dist/runner/websocket.d.ts.map +1 -1
- package/dist/runner/websocket.js +12 -10
- package/dist/runner/websocket.js.map +1 -1
- package/package.json +14 -12
- package/schema.json +2269 -0
- package/src/Auth.ts +8 -2
- package/src/Config.ts +196 -0
- package/src/Contract.ts +12 -3
- package/src/Instance.ts +1 -0
- package/src/Testing.ts +6 -4
- package/src/Transport.ts +12 -3
- package/src/cli.ts +60 -0
- package/src/host/auth/bearer.ts +1 -0
- package/src/host/auth/jwt.ts +1 -0
- package/src/host/auth/mtls.ts +7 -12
- package/src/host/auth/none.ts +3 -1
- package/src/host/command.ts +8 -5
- package/src/host/local.ts +4 -2
- package/src/host/unix.ts +11 -7
- package/src/host/websocket.ts +10 -7
- package/src/host/worker.ts +8 -5
- package/src/index.ts +36 -23
- package/src/internal/Certificates.ts +1 -0
- package/src/internal/FailureGroup.ts +5 -3
- package/src/internal/Peer.ts +1 -0
- package/src/internal/{ServeLifecycle.ts → RunnerLifecycle.ts} +7 -5
- package/src/internal/Supervisor.ts +5 -4
- package/src/internal/assembly.ts +11 -9
- package/src/internal/auth/config.ts +44 -0
- package/src/internal/auth/mtls.ts +1 -0
- package/src/internal/auth/token.ts +1 -0
- package/src/internal/auth/tokenCredentials.ts +4 -2
- package/src/internal/child.ts +8 -6
- package/src/{bin.ts → internal/childMain.ts} +16 -61
- package/src/internal/childRuntime.ts +12 -10
- package/src/internal/cleanup.ts +3 -2
- package/src/internal/contract.ts +1 -0
- package/src/internal/credentials.ts +3 -1
- package/src/internal/directTransport.ts +9 -2
- package/src/internal/entry.ts +53 -16
- package/src/internal/entryConfig.ts +10 -132
- package/src/internal/execution.ts +17 -15
- package/src/internal/follow.ts +2 -1
- package/src/internal/forkTree.ts +2 -1
- package/src/internal/host/local.ts +1 -0
- package/src/internal/host/runner.ts +7 -5
- package/src/internal/host.ts +9 -8
- package/src/internal/importer.ts +3 -2
- package/src/internal/listenerStartup.ts +4 -2
- package/src/internal/loadModule.ts +1 -0
- package/src/internal/platform.ts +1 -12
- package/src/internal/port.ts +11 -6
- package/src/internal/runner/Bootstrap.ts +1 -0
- package/src/internal/runner/Connection.ts +13 -11
- package/src/internal/runner/Execution.ts +14 -13
- package/src/internal/runner/Local.ts +3 -2
- package/src/internal/runner/Lock.ts +1 -0
- package/src/internal/runner/Multiplex.ts +2 -1
- package/src/internal/runner/Packages.ts +7 -5
- package/src/internal/runner/ProcessObservation.ts +2 -1
- package/src/internal/runner/Processes.ts +3 -1
- package/src/internal/runner/Retention.ts +1 -0
- package/src/internal/runner/Store.ts +3 -2
- package/src/internal/runner/Supervisor.ts +22 -20
- package/src/internal/runner/Watchdog.ts +3 -1
- package/src/internal/runner/Wire.ts +13 -12
- package/src/internal/runner/accept.ts +6 -5
- package/src/internal/runner/command.ts +3 -2
- package/src/internal/runner/connectionEnded.ts +2 -1
- package/src/internal/runner/model.ts +5 -3
- package/src/internal/services.ts +9 -2
- package/src/internal/socketChannel.ts +2 -1
- package/src/internal/stdioChannel.ts +4 -2
- package/src/internal/supervisorPlugin.ts +10 -8
- package/src/internal/transportOptions.ts +1 -0
- package/src/internal/watchdogMain.ts +5 -3
- package/src/internal/websocket.ts +5 -2
- package/src/internal/websocketServer.ts +6 -4
- package/src/internal/workerChannel.ts +1 -0
- package/src/internal/workerMain.ts +21 -5
- package/src/runner/auth/bearer.ts +10 -6
- package/src/runner/auth/jwt.ts +10 -41
- package/src/runner/auth/mtls.ts +6 -3
- package/src/runner/auth/none.ts +3 -1
- package/src/runner/index.ts +102 -11
- package/src/runner/stdio.ts +15 -10
- package/src/runner/unix.ts +7 -4
- package/src/runner/websocket.ts +9 -7
- package/dist/Auth-BElTC9_X.js +0 -6
- package/dist/Bootstrap-H9gDsgsC.js +0 -9
- package/dist/ConfigDirectory-BCC6q2R4.js +0 -5
- package/dist/Contract-DsJtisvL.js +0 -83
- package/dist/Errors-DYhsGZcZ.js +0 -58
- package/dist/FailureGroup-BgT73AaR.js +0 -63
- package/dist/Framing-G9eSaeLb.js +0 -61
- package/dist/Graft-B71CPA2Y.js +0 -996
- package/dist/Packages-AgoCGotL.js +0 -108
- package/dist/Peer-DXeVrGBh.js +0 -342
- package/dist/ProcessObservation-gLgGirYv.js +0 -38
- package/dist/ServeLifecycle-Bd1FPJ6e.js +0 -24
- package/dist/Transport-DULzpsgR.js +0 -6
- package/dist/WatchdogProtocol-BZmVxrBP.js +0 -17
- package/dist/bin.js +0 -28276
- package/dist/bin.js.map +0 -1
- package/dist/childRuntime-Bm3iSg_N.js +0 -192
- package/dist/command-9zrHdbwT.js +0 -7
- package/dist/connectionEnded-BwcxQ7W8.js +0 -54
- package/dist/directTransport-DrexuPSm.js +0 -5
- package/dist/entry-psOpX3Bj.js +0 -736
- package/dist/importer-Cvf88eAY.js +0 -344
- package/dist/internal/ServeLifecycle.js.map +0 -1
- package/dist/internal/entryConfig.d.ts.map +0 -1
- package/dist/internal/platform.js.map +0 -1
- package/dist/internal/release.js +0 -25
- package/dist/internal/release.js.map +0 -1
- package/dist/internal/serve.js +0 -60
- package/dist/internal/serve.js.map +0 -1
- package/dist/port--3x2zJ4D.js +0 -285
- package/dist/release-DfZPuIcK.js +0 -23
- package/dist/rolldown-runtime-DYf_mQCB.js +0 -34
- package/dist/socketChannel-CJvL2DiB.js +0 -3658
- package/dist/supervisorPlugin-t6Z6PrhD.js +0 -733
- package/dist/token-CYBNNlhS.js +0 -17
- package/dist/tokenCredentials-CbCuk-Rt.js +0 -31
- package/dist/websocketServer-NQhODlEt.js +0 -60
- package/dist/workerChannel-C8hhBJzA.js +0 -27
- package/src/internal/release.ts +0 -72
- package/src/internal/serve.ts +0 -119
- /package/dist/{bin.d.ts → internal/childMain.d.ts} +0 -0
package/dist/index.js
CHANGED
|
@@ -1,86 +1,52 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
1
|
+
import { Contract_exports, UndeclaredFailure } from "./Contract.js";
|
|
2
|
+
import { AuthenticationFailed, AuthenticatorUnavailable, CredentialsError, LocalTerminationTimeout, MissingInstance, ProcessExited, RemoteEntryError, RemoteError, RemoteWithdrawn, TransportError } from "./Errors.js";
|
|
3
|
+
import { CapabilityFailed } from "./internal/assembly.js";
|
|
4
|
+
import { invocation } from "./internal/credentials.js";
|
|
5
|
+
import { host, launch } from "./internal/entry.js";
|
|
6
|
+
import { Host } from "./Config.js";
|
|
7
|
+
import { publicError } from "./internal/execution.js";
|
|
8
|
+
import { follow } from "./internal/follow.js";
|
|
9
|
+
import { Instance } from "./Instance.js";
|
|
10
|
+
import { RemoteTerminationUnconfirmed } from "./internal/runner/model.js";
|
|
11
|
+
import { Array, Cause, Effect, Path, Schema } from "effect";
|
|
10
12
|
import { SecureRandom } from "effect/crypto";
|
|
11
13
|
import { ChildProcessSpawner } from "effect/process";
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
inject: [],
|
|
16
|
-
read: source
|
|
17
|
-
} : source;
|
|
18
|
-
return make({
|
|
19
|
-
name: "remote-effect-credentials",
|
|
20
|
-
inject: input.inject,
|
|
21
|
-
apply: Effect.fnUntraced(function* () {
|
|
22
|
-
const context = yield* Effect.context().pipe(Effect.map(Context.omit(Scope.Scope)));
|
|
23
|
-
const read = input.read.pipe(Effect.provideContext(context), Effect.mapError((error) => CredentialsError.make({ cause: Cause.fail(error) })));
|
|
24
|
-
yield* provide(Credentials, encode(read));
|
|
25
|
-
})
|
|
26
|
-
});
|
|
27
|
-
};
|
|
28
|
-
const invocation = (connect) => {
|
|
29
|
-
const auth = connect.auth;
|
|
30
|
-
if (auth === void 0) return void 0;
|
|
31
|
-
if ("mtls" in auth) {
|
|
32
|
-
const source = auth.mtls;
|
|
33
|
-
if (Effect.isEffect(source) || "read" in source) return {
|
|
34
|
-
plugin: provider(source, (read) => ({
|
|
35
|
-
kind: "Certificate",
|
|
36
|
-
read: read.pipe(Effect.map((value) => ({
|
|
37
|
-
_tag: "Certificate",
|
|
38
|
-
value
|
|
39
|
-
})))
|
|
40
|
-
})),
|
|
41
|
-
config: void 0
|
|
42
|
-
};
|
|
43
|
-
}
|
|
44
|
-
if ("bearer" in auth || "jwt" in auth) {
|
|
45
|
-
const source = "bearer" in auth ? auth.bearer.token : auth.jwt.token;
|
|
46
|
-
if (typeof source !== "string" && (Effect.isEffect(source) || "read" in source)) return {
|
|
47
|
-
plugin: provider(source, (read) => ({
|
|
48
|
-
kind: "Authorization",
|
|
49
|
-
read: read.pipe(Effect.flatMap(prepare), Effect.map((value) => ({
|
|
50
|
-
_tag: "Authorization",
|
|
51
|
-
value
|
|
52
|
-
})))
|
|
53
|
-
})),
|
|
54
|
-
config: void 0
|
|
55
|
-
};
|
|
56
|
-
}
|
|
57
|
-
};
|
|
58
|
-
// packages/remote/src/index.ts
|
|
14
|
+
import { Plugin } from "@graftland/graft";
|
|
15
|
+
import { ModuleResolver } from "@graftland/loader";
|
|
16
|
+
// src/index.ts
|
|
59
17
|
const publicCause = (declared, cause) => Cause.fromReasons(Array.flatMap(cause.reasons, (reason) => {
|
|
60
18
|
if (reason._tag !== "Fail") return [reason];
|
|
61
19
|
return Schema.is(CapabilityFailed)(reason.error) ? Array.map(publicCause(declared, reason.error.cause).reasons, (inner) => inner.annotate(Cause.reasonAnnotations(reason))) : [Cause.makeFailReason(publicError(declared, reason.error)).annotate(Cause.reasonAnnotations(reason))];
|
|
62
20
|
}));
|
|
63
|
-
|
|
21
|
+
/** Fixes deployment options; business config is plugin input, and updates restart the execution unit. */
|
|
22
|
+
const plugin = (contract, options) => Plugin.make({
|
|
64
23
|
name: contract.name,
|
|
65
24
|
inject: [
|
|
66
|
-
optional(ModuleResolver),
|
|
25
|
+
Plugin.optional(ModuleResolver.ModuleResolver),
|
|
67
26
|
Path.Path,
|
|
68
27
|
SecureRandom.SecureRandom,
|
|
69
28
|
ChildProcessSpawner.ChildProcessSpawner
|
|
70
29
|
],
|
|
71
30
|
retry: options.retry,
|
|
72
|
-
|
|
31
|
+
config: Schema.toEncoded(contract.config),
|
|
32
|
+
apply: (config) => Effect.gen(function* () {
|
|
33
|
+
const auth = invocation(options.connect);
|
|
73
34
|
const input = yield* Schema.decodeUnknownEffect(Host)({
|
|
74
35
|
contract: options.contractModule,
|
|
75
|
-
connect: options.connect
|
|
76
|
-
|
|
36
|
+
connect: auth === void 0 ? options.connect : {
|
|
37
|
+
...options.connect,
|
|
38
|
+
auth: { name: "effect-credentials" }
|
|
39
|
+
},
|
|
40
|
+
config
|
|
77
41
|
});
|
|
78
42
|
yield* Schema.decodeEffect(contract.config)(input.config);
|
|
79
43
|
const child = yield* launch(contract, input, {
|
|
80
44
|
contractModule: options.contractModule,
|
|
81
45
|
shutdownTimeout: options.shutdownTimeout
|
|
82
|
-
},
|
|
46
|
+
}, auth);
|
|
83
47
|
yield* follow(child, (cause) => Effect.failCause(publicCause(contract.error, cause)));
|
|
84
|
-
}
|
|
48
|
+
}).pipe(Effect.mapError((error) => publicError(contract.error, error)))
|
|
85
49
|
});
|
|
86
|
-
export { Contract_exports as Contract, Instance, MissingInstance, RemoteError, RemoteTerminationUnconfirmed, RemoteWithdrawn, UndeclaredFailure, host as default, plugin };
|
|
50
|
+
export { AuthenticationFailed, AuthenticatorUnavailable, Contract_exports as Contract, CredentialsError, Instance, LocalTerminationTimeout, MissingInstance, ProcessExited, RemoteEntryError, RemoteError, RemoteTerminationUnconfirmed, RemoteWithdrawn, TransportError, UndeclaredFailure, host as default, plugin };
|
|
51
|
+
|
|
52
|
+
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["
|
|
1
|
+
{"version":3,"file":"index.js","names":["Credential.invocation","Configuration.Host"],"sources":["../src/index.ts"],"sourcesContent":["import {\n\tArray,\n\tCause,\n\tEffect,\n\tPath,\n\tSchema,\n\ttype Duration,\n\ttype Schedule,\n} from \"effect\"\nimport { SecureRandom } from \"effect/crypto\"\nimport { ChildProcessSpawner } from \"effect/process\"\n\nimport { Plugin } from \"@graftland/graft\"\nimport { ModuleResolver } from \"@graftland/loader\"\n\nimport * as Contract from \"./Contract\"\nimport { MissingInstance, RemoteError, RemoteWithdrawn } from \"./Errors\"\nimport { CapabilityFailed } from \"./internal/assembly\"\nimport * as Credential from \"./internal/credentials\"\nimport { launch } from \"./internal/entry\"\nimport * as Configuration from \"./internal/entryConfig\"\nimport { publicError } from \"./internal/execution\"\nimport { follow } from \"./internal/follow\"\n\nexport { Contract }\nexport { Instance } from \"./Instance\"\nexport { RemoteTerminationUnconfirmed } from \"./internal/runner/model\"\nexport * 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 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\n/** Fixes deployment options; business config is plugin input, and updates restart the execution unit. */\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>,\n): Plugin.Plugin<\n\tS[\"Encoded\"],\n\tS[\"Encoded\"],\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\tconfig: Schema.toEncoded(contract.config),\n\t\tapply: (config) =>\n\t\t\tEffect.gen(function* () {\n\t\t\t\tconst auth = Credential.invocation(options.connect)\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:\n\t\t\t\t\t\tauth === undefined\n\t\t\t\t\t\t\t? options.connect\n\t\t\t\t\t\t\t: { ...options.connect, auth: { name: \"effect-credentials\" } },\n\t\t\t\t\tconfig,\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\tauth,\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":";;;;;;;;;;;;;;;;AA6CA,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;;AAGD,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,QAAQ,OAAO,UAAU,SAAS,MAAM;CACxC,QAAQ,WACP,OAAO,IAAI,aAAa;EACvB,MAAM,OAAOA,WAAsB,QAAQ,OAAO;EAClD,MAAM,QAAQ,OAAO,OAAO,oBAAoBC,IAAkB,CAAC,CAAC;GACnE,UAAU,QAAQ;GAClB,SACC,SAAS,KAAA,IACN,QAAQ,UACR;IAAE,GAAG,QAAQ;IAAS,MAAM,EAAE,MAAM,qBAAqB;GAAE;GAC/D;EACD,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,GACA,IACD;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 +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.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
|
+
{"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\"\n\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":";;;;;;;AAkBA,IAAa,mBAAb,cAAsC,OAAO,YAG3C,CAAC,CAAC,oBAAoB;CACvB,QAAQ,OAAO;CACf,OAAO,OAAO,SAAS,OAAO,OAAO,CAAC;AACvC,CAAC,CAAC,CAAC;CACF,IAAa,UAAU;EACtB,OAAO,KAAK;CACb;AACD;;AAGA,IAAa,oBAAb,cAAuC,OAAO,YAG5C,CAAC,CAAC,qBAAqB,EAAE,MAAM,OAAO,OAAO,CAAC,CAAC,CAAC;CACjD,IAAa,UAAU;EACtB,OAAO,GAAG,KAAK,KAAK;CACrB;AACD;AAeA,MAAM,OAAO,OAAe,UAC3B,cAAc,MAAM,SAAS,OAAO,QAAQ,eAAe,MAAM,CAAC,CAAC,OAAO,OAAO,IAAI,WAAW,KAAK,CAAC,CAAC,EAAE,aAAa,MAAM;AAE7H,MAAM,OAAO,UACZ,OAAO,WACN,OAAO,OAAO,OAAO,QAAQ,uBAAuB,EAAE,CAAC,CAAC,KAAK,CAAC,CAC/D,CAAC,CAAC,KAAK,OAAO,KAAK,UAAU,IAAI,WAAW,KAAK,CAAC,CAAC;AACpD,MAAM,WAAW,SAChB,IAAI,IAAI,2BAA2B,EAClC,gBAAgB,CACf,IAAI,IAAI,sBAAsB;CAC7B,MAAM;CACN,OAAO,IAAI,OAAO,WAAW,EAAE,OAAO,KAAK,CAAC;AAC7C,CAAC,CACF,EACD,CAAC;AACF,MAAM,YAAY,SACjB,OAAO,MAAM,WAAW,aAAa,IAAI,GAAG;CAC3C,iBAAiB,IAAI,IAAI,YAAY;EAAE,MAAM;EAAG,OAAO;CAAK,CAAC;CAC7D,YAAY,OACX,IAAI,IAAI,YAAY;EACnB,MAAM;EACN,OAAO,IAAI,OAAO,YAAY,EAC7B,UAAU,IAAI,WACb,GAAG,SAAS,gBACT,WAAW,aAAa,EAAE,IAC1B,WAAW,aAAa,EAAE,CAC9B,EACD,CAAC;CACF,CAAC;AACH,CAAC;AAEF,MAAa,QAAQ,OAAO,GAAG,oBAAoB,CAAC,CAAC,WACpD,SACC;CAED,MAAM,SAAS,QAAO,OADA,aAAa,aAAA,CACN,YAAY,EAAE;CAC3C,MAAM,MAAM,OAAO,SAAS;CAC5B,MAAM,YAAY,OAAO,UAAU;CACnC,MAAM,SAAS,IAAI,IAAI,aAAa;EACnC,MAAM;EACN,QAAQ;CACT,CAAC;CACD,MAAM,WAAW,UAChB,iBAAiB,KAAK;EACrB,QAAQ,uCAAuC,QAAQ;EACvD;CACD,CAAC;CACF,MAAM,OAAO,OAAO,OAAO,WAAW;EACrC,WACC,UAAU,OAAO,YAChB;GAAE,MAAM;GAAS,YAAY;EAAQ,GACrC,MACA,CAAC,QAAQ,QAAQ,CAClB;EACD,OAAO;CACR,CAAC;CAED,MAAM,YACL,QAAQ,WAAW,KAAA,IAChB,KAAA,IACA;EACA,aAAa,OAAO,OAAO,SAC1B,IAAI,QAAQ,OAAO,WAAW,GAC9B,OACD;EACA,YAAY,OAAO,OAAO,SACzB,IAAI,SAAS,MAAM,QAAQ,OAAO,UAAU,CAAC,GAC7C,OACD;CACD;CACH,MAAM,aACL,cAAc,KAAA,IACX,KAAK,aACL,OAAO,OAAO,WAAW;EACzB,WACC,UAAU,OAAO,UAChB,SACA,UAAU,YACV;GAAE,MAAM;GAAS,YAAY;EAAQ,GACrC,OACA,CAAC,MAAM,CACR;EACD,OAAO;CACR,CAAC;CACJ,MAAM,cAAc,OAAO,OAAO,IAAI;EACrC,WAAW;GACV,MAAM,SACL,cAAc,KAAA,IACX,KAAA,IACA,IAAI,YAAY,QAAQ,UAAU,WAAW;GACjD,MAAM,QAAQ,CACb,GAAG,MAAM,IAAI,QAAQ,SAAS,CAAC,GAAG,QAAQ,GAC1C,GAAG,MAAM,IACR,QAAQ,cAAc,CAAC,IACtB,aACA,IAAI,IAAI,YAAY;IAAE,MAAM;IAAG,OAAO,WAAW;GAAW,CAAC,CAC/D,CACD;GACA,OAAO,IAAI,IAAI,YAAY;IAC1B,SAAS;IAET,cAAc,IAAI,OAAO,QAAQ,EAChC,UAAU,IAAI,WAAW,CAAC,GAAG,GAAG,MAAM,CAAC,EACxC,CAAC;IACD,SAAS,QAAQ,QAAQ,IAAI;IAC7B,QAAQ,QAAQ,WAAW,QAAQ,QAAQ,IAAI;IAC/C,WAAW,IAAI,IAAI,KAAK,EAAE,OAAO,SAAS,UAAU,GAAG,EAAE,CAAC;IAC1D,UAAU,IAAI,IAAI,KAAK,EACtB,OAAO,SAAS,UAAU,SAAS,IAAI,KAAK,EAAE,MAAM,QAAQ,KAAK,CAAC,CAAC,EACpE,CAAC;IACD,YAAY;KACX,IAAI,IAAI,UAAU;MACjB,QAAQ;MACR,UAAU;MACV,WAAW,IAAI,IAAI,iBAAiB,EAAE,IAAI,QAAQ,UAAU,KAAK,CAAC,CAAC,CACjE,SAAS,CAAC,CACV,MAAM;KACT,CAAC;KACD,IAAI,IAAI,UAAU;MACjB,QAAQ;MACR,UAAU;MACV,WAAW,IAAI,OAAO,UAAU,EAC/B,UAAU,IAAI,WAAW,CAAC,QAAQ,UAAU,OAAO,IAAO,GAAI,CAAC,EAChE,CAAC,CAAC,CAAC,MAAM;KACV,CAAC;KACD,GAAI,QAAQ,UAAU,OACnB,CAAC,IACD,CACA,IAAI,IAAI,UAAU;MACjB,QAAQ;MACR,WAAW,IAAI,IAAI,YAAY,EAC9B,aAAa,CACZ,QAAQ,UAAU,WACf,sBACA,mBACJ,EACD,CAAC,CAAC,CACA,SAAS,CAAC,CACV,MAAM;KACT,CAAC,CACF;KACF,GAAI,MAAM,WAAW,IAClB,CAAC,IACD,CACA,IAAI,IAAI,UAAU;MACjB,QAAQ;MACR,WAAW,IAAI,IAAI,QAAQ,EAAE,UAAU,MAAM,CAAC,CAAC,CAC7C,SAAS,CAAC,CACV,MAAM;KACT,CAAC,CACF;IACH;GACD,CAAC;EACF;EACA,OAAO;CACR,CAAC;CACD,OAAO,OAAO,WAAW;EACxB,WACC,YAAY,qBAAqB,UAAU,KAAK,WAAW,MAAM;EAClE,OAAO;CACR,CAAC;CACD,OAAO,OAAO,WAAW;EACxB,WAAW,YAAY,KAAK,YAAY,WAAW,MAAM;EACzD,OAAO;CACR,CAAC;CACD,MAAM,aAAa,OAAO,OAAO,WAAW;EAC3C,WAAW,UAAU,OAAO,UAAU,SAAS,KAAK,UAAU;EAC9D,OAAO;CACR,CAAC;CACD,OAAO,OAAO,OAAO,IAAI;EACxB,YAAY;GACX,aAAa,IAAI,eAAe,YAAY,SAAS,CAAC,CAAC,MAAM,CAAC;GAC9D,YAAY,SAAS,KAAK,IAAI,eAAe,UAAU,CAAC;EACzD;EACA,OAAO;CACR,CAAC;AACF,CAAC;AAED,MAAa,OAAO,OAAO,GAAG,mBAAmB,CAAC,CAAC,WAAW,MAAc;CAC3E,MAAM,KAAK,OAAO,WAAW;CAC7B,MAAM,cAAc,OAAO,GAAG,eAAe,OAAO,MAAM;CAC1D,MAAM,aAAa,OAAO,GAAG,eAAe,OAAO,MAAM;CACzD,OAAO;EAAE;EAAa,YAAY,SAAS,KAAK,UAAU;CAAE;AAC7D,CAAC;AACD,MAAa,QAAQ,OAAO,GAAG,oBAAoB,CAAC,CAAC,WACpD,MACA,MACA,QAAiB,OAChB;CACD,MAAM,KAAK,OAAO,WAAW;CAC7B,OAAO,GAAG,gBAAgB,OAAO,QAAQ,SAAS,MAAM,KAAK,UAAU,GAAG;EACzE,MAAM,QAAQ,MAAM;EACpB,MAAM;CACP,CAAC;CAED,OAAO,GAAG,MAAM,OAAO,QAAQ,GAAK;CACpC,OAAO,GAAG,gBAAgB,OAAO,QAAQ,KAAK,aAAa,EAC1D,MAAM,QAAQ,MAAM,KACrB,CAAC;AAEF,GAAG,OAAO,eAAe;;AAUzB,MAAa,cAAc,aAC1B,UAAU,mBAAmB,QAAQ;AACtC,MAAa,WAAW,OAAO,GAAG,uBAAuB,CAAC,CAAC,WAC1D,SACC;CACD,MAAM,KAAK,OAAO,WAAW;CAC7B,MAAM,OAAO,OAAO,KAAK;CACzB,MAAM,UAAU,CACf,GAAI,QAAQ,OAAO,WAAW,IAAI,CAAC,IAAI,CAAC,QAAQ,GAChD,GAAG,MAAM,IAAI,MAAM,OAAO,QAAQ,QAAQ,GAAG,UAAU,CACxD;CACA,IAAI,CAAC,QAAQ,OAAO;EACnB,MAAM,QAAQ,MAAM,QAAQ,UAAU,SACrC,MAAM,IAAI,CAAC,QAAQ,MAAM,IAAI,cAC5B,KAAK,KAAK,QAAQ,KAAK,OAAO,SAAS,CACxC,CACD;EACA,MAAM,QAAQ,OAAO,OAAO,OAAO,OAAO,GAAG,MAAM;EACnD,IAAI,MAAM,wBAAwB,KAAK,GACtC,OAAO,OAAO,kBAAkB,KAAK,EAAE,MAAM,MAAM,GAAG,CAAC;CACzD;CACA,OAAO,GACL,cAAc,QAAQ,KAAK,EAAE,WAAW,KAAK,CAAC,CAAC,CAC/C,KAAK,OAAO,eAAe;CAC7B,MAAM,KAAK,KAAK,KAAK,QAAQ,KAAK,IAAI;CAItC,MAAM,UAFJ,OAAO,GAAG,OAAO,KAAK,MAAM,OAAO,OAAO,GAAG,OAAO,KAAK,MAAM,KAG9D,OAAO,KAAK,EAAE,IACd,OAAO,MAAM;EAAE,MAAM;EAAY,OAAO;EAAM,MAAM,QAAQ;CAAK,CAAC,CAAC,CAAC,KACpE,OAAO,KAAK,SAAS,MAAM,IAAI,IAAI,CAAC,CACrC;CACF,IAAI,QAAQ,OAAO,SAAS,GAAG;EAC9B,MAAM,OAAO,OAAO,MAAM;GACzB,MAAM;GACN,OAAO;GACP,OAAO,QAAQ;GACf,MAAM,QAAQ;GACd;EACD,CAAC;EACD,OAAO,MAAM,KAAK,KAAK,QAAQ,KAAK,QAAQ,GAAG,MAAM,QAAQ,KAAK;CACnE;CACA,OAAO,OAAO,QACb,MAAM,OAAO,QAAQ,QAAQ,IAC5B,aACA,MAAM;EACL,MAAM;EACN,OAAO;EACP,YAAY,CAAC,QAAQ;EACrB,MAAM,QAAQ;EACd;CACD,CAAC,CAAC,CAAC,KACF,OAAO,SAAS,SACf,MACC,KAAK,KAAK,QAAQ,KAAK,WAAW,QAAQ,CAAC,GAC3C,MACA,QAAQ,KACT,CACD,CACD,GACD,EAAE,SAAS,KAAK,CACjB;AACD,CAAC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { ReleaseInterrupted, close } from "./release.js";
|
|
2
1
|
import { cleanupCause } from "./cleanup.js";
|
|
3
2
|
import { Array, Cause, Data, Deferred, Effect, Exit, Fiber, FiberSet, Ref, Schema, Scope, TxRef } from "effect";
|
|
3
|
+
import * as Release from "@graftland/graft/Release";
|
|
4
4
|
// src/internal/FailureGroup.ts
|
|
5
5
|
const State = Data.taggedEnum();
|
|
6
6
|
/** One owner for first failure, transaction wakeups, and interruption of sibling work. */
|
|
@@ -18,12 +18,12 @@ const make = Effect.fnUntraced(function* () {
|
|
|
18
18
|
const waiting = yield* Effect.exit(restore(Fiber.await(worker)));
|
|
19
19
|
if (Exit.isFailure(waiting)) yield* Fiber.interrupt(worker);
|
|
20
20
|
const body = yield* Fiber.await(worker);
|
|
21
|
-
const closed = yield* Effect.exit(close(scope, body));
|
|
21
|
+
const closed = yield* Effect.exit(Release.close(scope, body));
|
|
22
22
|
const expected = Exit.isFailure(waiting) && Exit.isFailure(body) && Array.every(body.cause.reasons, (reason) => reason._tag === "Interrupt" && reason.fiberId === ownerId);
|
|
23
23
|
const bodyCause = Exit.isFailure(body) && !expected ? body.cause : Cause.empty;
|
|
24
24
|
const releaseCause = Exit.isFailure(closed) && !Cause.hasInterruptsOnly(closed.cause) ? closed.cause : Cause.empty;
|
|
25
25
|
const failure = Cause.combine(bodyCause, releaseCause);
|
|
26
|
-
const closing = Cause.combine(Cause.hasInterrupts(bodyCause) || Array.some(bodyCause.reasons, (reason) => reason._tag === "Die" && Schema.is(ReleaseInterrupted)(reason.defect)) ? bodyCause : Cause.empty, releaseCause);
|
|
26
|
+
const closing = Cause.combine(Cause.hasInterrupts(bodyCause) || Array.some(bodyCause.reasons, (reason) => reason._tag === "Die" && Schema.is(Release.ReleaseInterrupted)(reason.defect)) ? bodyCause : Cause.empty, releaseCause);
|
|
27
27
|
yield* Ref.update(cleanup, (cause) => Cause.combine(cause, closing));
|
|
28
28
|
if (failure.reasons.length > 0) {
|
|
29
29
|
yield* Ref.update(failures, (cause) => Cause.combine(cause, failure));
|
|
@@ -37,8 +37,8 @@ const make = Effect.fnUntraced(function* () {
|
|
|
37
37
|
yield* FiberSet.join(fibers).pipe(Effect.catchCause((cause) => publish(cause).pipe(Effect.andThen(FiberSet.clear(fibers)), Effect.uninterruptible)), Effect.forkScoped);
|
|
38
38
|
const failure = Effect.tx(check.pipe(Effect.andThen(Effect.txRetry)));
|
|
39
39
|
const failCause = (cause) => FiberSet.run(fibers, observe(Effect.failCause(cause))).pipe(Effect.asVoid);
|
|
40
|
-
const close
|
|
41
|
-
yield* Effect.addFinalizer(() => close
|
|
40
|
+
const close = 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);
|
|
41
|
+
yield* Effect.addFinalizer(() => close.pipe(Effect.catchCause((cause) => Effect.failCause(cleanupCause(cause)))));
|
|
42
42
|
return {
|
|
43
43
|
await: failure,
|
|
44
44
|
check,
|
|
@@ -48,7 +48,7 @@ const make = Effect.fnUntraced(function* () {
|
|
|
48
48
|
fail: (error) => failCause(Cause.fail(error)),
|
|
49
49
|
failCause,
|
|
50
50
|
race: (effect) => check.pipe(Effect.andThen(Effect.raceFirst(effect, failure))),
|
|
51
|
-
close
|
|
51
|
+
close
|
|
52
52
|
};
|
|
53
53
|
});
|
|
54
54
|
export { make };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FailureGroup.js","names":[
|
|
1
|
+
{"version":3,"file":"FailureGroup.js","names":[],"sources":["../../src/internal/FailureGroup.ts"],"sourcesContent":["import {\n\tArray,\n\tCause,\n\tData,\n\tDeferred,\n\tEffect,\n\tExit,\n\tFiber,\n\tFiberSet,\n\tRef,\n\tSchema,\n\tScope,\n\tTxRef,\n} from \"effect\"\n\nimport * as Release from \"@graftland/graft/Release\"\n\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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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Peer.js","names":[],"sources":["../../src/internal/Peer.ts"],"sourcesContent":["import { Context } from \"effect\"\nexport class Peer extends Context.Service<Peer, string>()(\n\t\"@graftland/plugin-remote/internal/Peer\",\n) {}\n"],"mappings":";;
|
|
1
|
+
{"version":3,"file":"Peer.js","names":[],"sources":["../../src/internal/Peer.ts"],"sourcesContent":["import { Context } from \"effect\"\n\nexport class Peer extends Context.Service<Peer, string>()(\n\t\"@graftland/plugin-remote/internal/Peer\",\n) {}\n"],"mappings":";;AAEA,IAAa,OAAb,cAA0B,QAAQ,QAAsB,CAAC,CACxD,wCACD,CAAC,CAAC,CAAC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { close } from "./release.js";
|
|
2
1
|
import { Context, Deferred, Effect, Exit, Option, Schema, Scope } from "effect";
|
|
3
|
-
|
|
2
|
+
import * as Release from "@graftland/graft/Release";
|
|
3
|
+
// src/internal/RunnerLifecycle.ts
|
|
4
4
|
var StartupError = class extends Schema.TaggedError()("RunnerStartupError", {
|
|
5
5
|
detail: Schema.String,
|
|
6
6
|
cause: Schema.optionalKey(Schema.Cause(Schema.Unknown, Schema.Defect()))
|
|
@@ -9,18 +9,18 @@ var StartupError = class extends Schema.TaggedError()("RunnerStartupError", {
|
|
|
9
9
|
return this.detail;
|
|
10
10
|
}
|
|
11
11
|
};
|
|
12
|
-
var
|
|
12
|
+
var RunnerLifecycle = class extends Context.Service()("@graftland/plugin-remote/internal/RunnerLifecycle") {};
|
|
13
13
|
const make = Effect.all({
|
|
14
14
|
ended: Deferred.make(),
|
|
15
15
|
released: Deferred.make()
|
|
16
16
|
});
|
|
17
17
|
/** Observe shutdown independently of the loader, which logs child cleanup failures. */
|
|
18
18
|
const resources = Effect.fnUntraced(function* (lifecycle) {
|
|
19
|
-
return yield* Effect.acquireRelease(Scope.make(), (scope, exit) => close(scope, exit).pipe(Effect.onExit((released) => Option.isNone(lifecycle) ? Effect.void : Deferred.done(lifecycle.value.released, Exit.isSuccess(released) ? Exit.void : Exit.fail(StartupError.make({
|
|
19
|
+
return yield* Effect.acquireRelease(Scope.make(), (scope, exit) => Release.close(scope, exit).pipe(Effect.onExit((released) => Option.isNone(lifecycle) ? Effect.void : Deferred.done(lifecycle.value.released, Exit.isSuccess(released) ? Exit.void : Exit.fail(StartupError.make({
|
|
20
20
|
detail: "Supervisor shutdown failed",
|
|
21
21
|
cause: released.cause
|
|
22
22
|
}))).pipe(Effect.asVoid))));
|
|
23
23
|
});
|
|
24
|
-
export {
|
|
24
|
+
export { RunnerLifecycle, StartupError, make, resources };
|
|
25
25
|
|
|
26
|
-
//# sourceMappingURL=
|
|
26
|
+
//# sourceMappingURL=RunnerLifecycle.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RunnerLifecycle.js","names":[],"sources":["../../src/internal/RunnerLifecycle.ts"],"sourcesContent":["import { Context, Deferred, Effect, Exit, Option, Schema, Scope } from \"effect\"\n\nimport * as Release from \"@graftland/graft/Release\"\n\nimport type { TransportError } from \"../Errors\"\n\nexport class StartupError extends Schema.TaggedError<\n\tStartupError,\n\t{ readonly brand: unique symbol }\n>()(\"RunnerStartupError\", {\n\tdetail: Schema.String,\n\tcause: Schema.optionalKey(Schema.Cause(Schema.Unknown, Schema.Defect())),\n}) {\n\toverride get message() {\n\t\treturn this.detail\n\t}\n}\n\nexport class RunnerLifecycle extends Context.Service<\n\tRunnerLifecycle,\n\t{\n\t\treadonly ended: Deferred.Deferred<void, TransportError>\n\t\treadonly released: Deferred.Deferred<void, StartupError>\n\t}\n>()(\"@graftland/plugin-remote/internal/RunnerLifecycle\") {}\n\nexport const make = Effect.all({\n\tended: Deferred.make<void, TransportError>(),\n\treleased: Deferred.make<void, StartupError>(),\n})\n\n/** Observe shutdown independently of the loader, which logs child cleanup failures. */\nexport const resources = Effect.fnUntraced(function* (\n\tlifecycle: Option.Option<typeof RunnerLifecycle.Service>,\n) {\n\treturn yield* Effect.acquireRelease(Scope.make(), (scope, exit) =>\n\t\tRelease.close(scope, exit).pipe(\n\t\t\tEffect.onExit((released) =>\n\t\t\t\tOption.isNone(lifecycle)\n\t\t\t\t\t? Effect.void\n\t\t\t\t\t: Deferred.done(\n\t\t\t\t\t\t\tlifecycle.value.released,\n\t\t\t\t\t\t\tExit.isSuccess(released)\n\t\t\t\t\t\t\t\t? Exit.void\n\t\t\t\t\t\t\t\t: Exit.fail(\n\t\t\t\t\t\t\t\t\t\tStartupError.make({\n\t\t\t\t\t\t\t\t\t\t\tdetail: \"Supervisor shutdown failed\",\n\t\t\t\t\t\t\t\t\t\t\tcause: released.cause,\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).pipe(Effect.asVoid),\n\t\t\t),\n\t\t),\n\t)\n})\n"],"mappings":";;;AAMA,IAAa,eAAb,cAAkC,OAAO,YAGvC,CAAC,CAAC,sBAAsB;CACzB,QAAQ,OAAO;CACf,OAAO,OAAO,YAAY,OAAO,MAAM,OAAO,SAAS,OAAO,OAAO,CAAC,CAAC;AACxE,CAAC,CAAC,CAAC;CACF,IAAa,UAAU;EACtB,OAAO,KAAK;CACb;AACD;AAEA,IAAa,kBAAb,cAAqC,QAAQ,QAM3C,CAAC,CAAC,mDAAmD,CAAC,CAAC,CAAC;AAE1D,MAAa,OAAO,OAAO,IAAI;CAC9B,OAAO,SAAS,KAA2B;CAC3C,UAAU,SAAS,KAAyB;AAC7C,CAAC;;AAGD,MAAa,YAAY,OAAO,WAAW,WAC1C,WACC;CACD,OAAO,OAAO,OAAO,eAAe,MAAM,KAAK,IAAI,OAAO,SACzD,QAAQ,MAAM,OAAO,IAAI,CAAC,CAAC,KAC1B,OAAO,QAAQ,aACd,OAAO,OAAO,SAAS,IACpB,OAAO,OACP,SAAS,KACT,UAAU,MAAM,UAChB,KAAK,UAAU,QAAQ,IACpB,KAAK,OACL,KAAK,KACL,aAAa,KAAK;EACjB,QAAQ;EACR,OAAO,SAAS;CACjB,CAAC,CACF,CACH,CAAC,CAAC,KAAK,OAAO,MAAM,CACvB,CACD,CACD;AACD,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Supervisor.js","names":[],"sources":["../../src/internal/Supervisor.ts"],"sourcesContent":["/** A listener hands an authenticated byte channel to the supervisor. */\nimport { Context
|
|
1
|
+
{"version":3,"file":"Supervisor.js","names":[],"sources":["../../src/internal/Supervisor.ts"],"sourcesContent":["/** A listener hands an authenticated byte channel to the supervisor. */\nimport { Context, type Effect, type Scope } from \"effect\"\n\nimport type { TransportError } from \"../Errors\"\nimport type { Channel } from \"../Transport\"\nimport type { Peer } from \"./Peer\"\n\nexport class Supervisor extends Context.Service<\n\tSupervisor,\n\t{\n\t\treadonly accept: (\n\t\t\tchannel: Channel,\n\t\t) => Effect.Effect<void, TransportError, Peer | Scope.Scope>\n\t}\n>()(\"@graftland/plugin-remote/internal/Supervisor\") {}\n"],"mappings":";;;AAOA,IAAa,aAAb,cAAgC,QAAQ,QAOtC,CAAC,CAAC,8CAA8C,CAAC,CAAC,CAAC"}
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import { findSubtree, isSubtreeActive } from "./forkTree.js";
|
|
2
|
-
import { Peer } from "./Peer.js";
|
|
3
1
|
import { Authenticator, Credentials } from "../Auth.js";
|
|
4
|
-
import { Connector, Listener } from "../Transport.js";
|
|
5
2
|
import { AuthenticationFailed } from "../Errors.js";
|
|
6
|
-
import {
|
|
3
|
+
import { Connector, Listener } from "../Transport.js";
|
|
7
4
|
import { follow } from "./follow.js";
|
|
5
|
+
import { findSubtree, isSubtreeActive } from "./forkTree.js";
|
|
6
|
+
import { Peer } from "./Peer.js";
|
|
8
7
|
import { closedNormally, connectionEnded } from "./runner/connectionEnded.js";
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
8
|
+
import { RunnerLifecycle } from "./RunnerLifecycle.js";
|
|
9
|
+
import { Supervisor } from "./Supervisor.js";
|
|
11
10
|
import { Array, Deferred, Effect, Fiber, Option, Schema, Stream } from "effect";
|
|
11
|
+
import { Graft, Plugin } from "@graftland/graft";
|
|
12
12
|
// src/internal/assembly.ts
|
|
13
13
|
var ListenerConfigError = class extends Schema.TaggedError()("ListenerConfigError", { detail: Schema.String }) {
|
|
14
14
|
get message() {
|
|
@@ -122,13 +122,13 @@ const makeListenerConsumer = (prepare = () => Effect.void, ready = Effect.void)
|
|
|
122
122
|
Listener,
|
|
123
123
|
Authenticator,
|
|
124
124
|
Supervisor,
|
|
125
|
-
Plugin.optional(
|
|
125
|
+
Plugin.optional(RunnerLifecycle)
|
|
126
126
|
],
|
|
127
127
|
apply: Effect.fnUntraced(function* () {
|
|
128
128
|
const listener = yield* Listener;
|
|
129
129
|
const auth = yield* Authenticator;
|
|
130
130
|
const supervisor = yield* Supervisor;
|
|
131
|
-
const lifecycle = yield* Effect.serviceOption(
|
|
131
|
+
const lifecycle = yield* Effect.serviceOption(RunnerLifecycle);
|
|
132
132
|
yield* prepare(listener.properties, auth);
|
|
133
133
|
yield* compatible(listener.properties, kind(auth)).pipe(Effect.mapError((error) => ListenerConfigError.make({ detail: error.detail })));
|
|
134
134
|
yield* warn(listener.properties, kind(auth), "runner");
|
|
@@ -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\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":"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"}
|
|
1
|
+
{"version":3,"file":"assembly.js","names":[],"sources":["../../src/internal/assembly.ts"],"sourcesContent":["import {\n\tArray,\n\tContext,\n\tDeferred,\n\tEffect,\n\tFiber,\n\tOption,\n\tSchema,\n\tStream,\n} from \"effect\"\n\nimport { Graft, Plugin, type Fork } from \"@graftland/graft\"\n\nimport {\n\tAuthenticator,\n\tCredentials,\n\ttype AuthenticatorApi,\n\ttype CredentialsApi,\n} from \"../Auth\"\nimport { AuthenticationFailed } from \"../Errors\"\nimport {\n\tConnector,\n\tListener,\n\ttype Accept,\n\ttype Properties,\n\ttype Session,\n} from \"../Transport\"\nimport { follow } from \"./follow\"\nimport { findSubtree, isSubtreeActive } from \"./forkTree\"\nimport { Peer } from \"./Peer\"\nimport { closedNormally, connectionEnded } from \"./runner/connectionEnded\"\nimport { RunnerLifecycle } from \"./RunnerLifecycle\"\nimport { Supervisor } from \"./Supervisor\"\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(RunnerLifecycle),\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(RunnerLifecycle)\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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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Schema } from "effect";
|
|
2
|
+
export declare const ClockTolerance: Schema.DurationFromString;
|
|
3
|
+
export declare const Jwt: Schema.Struct<{
|
|
4
|
+
readonly issuer: Schema.NonEmptyString;
|
|
5
|
+
readonly audience: Schema.NonEmptyArray<Schema.NonEmptyString>;
|
|
6
|
+
readonly algorithms: Schema.NonEmptyArray<Schema.Literals<readonly ["RS256", "RS384", "RS512", "PS256", "PS384", "PS512", "ES256", "ES384", "ES512", "EdDSA"]>>;
|
|
7
|
+
readonly identityClaim: Schema.withDecodingDefaultKey<Schema.NonEmptyString, never>;
|
|
8
|
+
readonly clockTolerance: Schema.withDecodingDefaultKey<Schema.DurationFromString, never>;
|
|
9
|
+
readonly keys: Schema.Union<readonly [Schema.Struct<{
|
|
10
|
+
readonly jwksUrl: Schema.String;
|
|
11
|
+
readonly publicKey: Schema.optionalKey<Schema.Never>;
|
|
12
|
+
}>, Schema.Struct<{
|
|
13
|
+
readonly publicKey: Schema.String;
|
|
14
|
+
readonly jwksUrl: Schema.optionalKey<Schema.Never>;
|
|
15
|
+
}>]>;
|
|
16
|
+
}>;
|
|
17
|
+
export declare const Certificate: Schema.Struct<{
|
|
18
|
+
readonly cert: Schema.String;
|
|
19
|
+
readonly key: Schema.String;
|
|
20
|
+
}>;
|
|
21
|
+
export declare const Mtls: Schema.Struct<{
|
|
22
|
+
readonly ca: Schema.String;
|
|
23
|
+
}>;
|
|
24
|
+
export declare const Bearer: Schema.Struct<{
|
|
25
|
+
readonly tokens: Schema.String;
|
|
26
|
+
}>;
|
|
27
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","names":[],"sources":["../../../src/internal/auth/config.ts"],"mappings":";qBAGa,gBAAc,OAAA;qBAOd,KAAG,OAAA;;;;;;;;;;;;;;qBAsBH,aAAW,OAAA;;;;qBAOX,MAAI,OAAA;;;qBACJ,QAAM,OAAA"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { Duration, Effect, Schema } from "effect";
|
|
2
|
+
import { Jwk } from "effect/jose";
|
|
3
|
+
// src/internal/auth/config.ts
|
|
4
|
+
const ClockTolerance = Schema.DurationFromString.check(Schema.makeFilter((duration) => Duration.isFinite(duration) && Duration.toMillis(duration) >= 0, { expected: "a finite, non-negative duration" }));
|
|
5
|
+
const Jwt$1 = Schema.Struct({
|
|
6
|
+
issuer: Schema.NonEmptyString,
|
|
7
|
+
audience: Schema.NonEmptyArray(Schema.NonEmptyString),
|
|
8
|
+
algorithms: Schema.NonEmptyArray(Jwk.AsymmetricAlgorithm),
|
|
9
|
+
identityClaim: Schema.NonEmptyString.pipe(Schema.withDecodingDefaultKey(Effect.succeed("sub"))),
|
|
10
|
+
clockTolerance: ClockTolerance.pipe(Schema.withDecodingDefaultKey(Effect.succeed("5 seconds"))),
|
|
11
|
+
keys: Schema.Union([Schema.Struct({
|
|
12
|
+
jwksUrl: Schema.String,
|
|
13
|
+
publicKey: Schema.optionalKey(Schema.Never)
|
|
14
|
+
}), Schema.Struct({
|
|
15
|
+
publicKey: Schema.String,
|
|
16
|
+
jwksUrl: Schema.optionalKey(Schema.Never)
|
|
17
|
+
})])
|
|
18
|
+
});
|
|
19
|
+
const Certificate = Schema.Struct({
|
|
20
|
+
cert: Schema.String,
|
|
21
|
+
key: Schema.String
|
|
22
|
+
});
|
|
23
|
+
const Token = Schema.Struct({ token: Schema.Union([Schema.String, Schema.Struct({ file: Schema.String })]) });
|
|
24
|
+
const Mtls = Schema.Struct({ ca: Schema.String });
|
|
25
|
+
const Bearer = Schema.Struct({ tokens: Schema.String });
|
|
26
|
+
const None = Schema.Struct({ identity: Schema.optionalKey(Schema.String) });
|
|
27
|
+
export { Bearer, Certificate, ClockTolerance, Jwt$1 as Jwt, Mtls, None, Token };
|
|
28
|
+
|
|
29
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","names":["Jwt"],"sources":["../../../src/internal/auth/config.ts"],"sourcesContent":["import { Duration, Effect, Schema } from \"effect\"\nimport { Jwk } from \"effect/jose\"\n\nexport const ClockTolerance = Schema.DurationFromString.check(\n\tSchema.makeFilter(\n\t\t(duration) =>\n\t\t\tDuration.isFinite(duration) && Duration.toMillis(duration) >= 0,\n\t\t{ expected: \"a finite, non-negative duration\" },\n\t),\n)\nexport const Jwt = Schema.Struct({\n\tissuer: Schema.NonEmptyString,\n\taudience: Schema.NonEmptyArray(Schema.NonEmptyString),\n\talgorithms: Schema.NonEmptyArray(Jwk.AsymmetricAlgorithm),\n\tidentityClaim: Schema.NonEmptyString.pipe(\n\t\tSchema.withDecodingDefaultKey(Effect.succeed(\"sub\")),\n\t),\n\tclockTolerance: ClockTolerance.pipe(\n\t\tSchema.withDecodingDefaultKey(Effect.succeed(\"5 seconds\")),\n\t),\n\tkeys: Schema.Union([\n\t\tSchema.Struct({\n\t\t\tjwksUrl: Schema.String,\n\t\t\tpublicKey: Schema.optionalKey(Schema.Never),\n\t\t}),\n\t\tSchema.Struct({\n\t\t\tpublicKey: Schema.String,\n\t\t\tjwksUrl: Schema.optionalKey(Schema.Never),\n\t\t}),\n\t]),\n})\n\nexport const Certificate = Schema.Struct({\n\tcert: Schema.String,\n\tkey: Schema.String,\n})\nexport const Token = Schema.Struct({\n\ttoken: Schema.Union([Schema.String, Schema.Struct({ file: Schema.String })]),\n})\nexport const Mtls = Schema.Struct({ ca: Schema.String })\nexport const Bearer = Schema.Struct({ tokens: Schema.String })\nexport const None = Schema.Struct({\n\tidentity: Schema.optionalKey(Schema.String),\n})\n"],"mappings":";;;AAGA,MAAa,iBAAiB,OAAO,mBAAmB,MACvD,OAAO,YACL,aACA,SAAS,SAAS,QAAQ,KAAK,SAAS,SAAS,QAAQ,KAAK,GAC/D,EAAE,UAAU,kCAAkC,CAC/C,CACD;AACA,MAAaA,QAAM,OAAO,OAAO;CAChC,QAAQ,OAAO;CACf,UAAU,OAAO,cAAc,OAAO,cAAc;CACpD,YAAY,OAAO,cAAc,IAAI,mBAAmB;CACxD,eAAe,OAAO,eAAe,KACpC,OAAO,uBAAuB,OAAO,QAAQ,KAAK,CAAC,CACpD;CACA,gBAAgB,eAAe,KAC9B,OAAO,uBAAuB,OAAO,QAAQ,WAAW,CAAC,CAC1D;CACA,MAAM,OAAO,MAAM,CAClB,OAAO,OAAO;EACb,SAAS,OAAO;EAChB,WAAW,OAAO,YAAY,OAAO,KAAK;CAC3C,CAAC,GACD,OAAO,OAAO;EACb,WAAW,OAAO;EAClB,SAAS,OAAO,YAAY,OAAO,KAAK;CACzC,CAAC,CACF,CAAC;AACF,CAAC;AAED,MAAa,cAAc,OAAO,OAAO;CACxC,MAAM,OAAO;CACb,KAAK,OAAO;AACb,CAAC;AACD,MAAa,QAAQ,OAAO,OAAO,EAClC,OAAO,OAAO,MAAM,CAAC,OAAO,QAAQ,OAAO,OAAO,EAAE,MAAM,OAAO,OAAO,CAAC,CAAC,CAAC,EAC5E,CAAC;AACD,MAAa,OAAO,OAAO,OAAO,EAAE,IAAI,OAAO,OAAO,CAAC;AACvD,MAAa,SAAS,OAAO,OAAO,EAAE,QAAQ,OAAO,OAAO,CAAC;AAC7D,MAAa,OAAO,OAAO,OAAO,EACjC,UAAU,OAAO,YAAY,OAAO,MAAM,EAC3C,CAAC"}
|
|
@@ -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 = 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":";;;
|
|
1
|
+
{"version":3,"file":"mtls.js","names":[],"sources":["../../../src/internal/auth/mtls.ts"],"sourcesContent":["import { Array, Cause, Effect, Schema, String } from \"effect\"\n\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":";;;AAKA,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"}
|