@graftland/plugin-remote 0.3.1 → 0.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Auth.d.ts +2 -2
- package/dist/Auth.d.ts.map +1 -1
- package/dist/Auth.js.map +1 -1
- package/dist/{Bootstrap-Dr6sX7el.js → Bootstrap-H9gDsgsC.js} +2 -2
- package/dist/{Contract-DL2mHvaT.js → Contract-DsJtisvL.js} +2 -2
- package/dist/Contract.js +1 -1
- package/dist/{Errors-BMKmu5Y7.js → Errors-DYhsGZcZ.js} +3 -1
- package/dist/Errors.d.ts +7 -0
- package/dist/Errors.d.ts.map +1 -1
- package/dist/Errors.js +3 -1
- package/dist/Errors.js.map +1 -1
- package/dist/{FailureGroup-BcH0XOBi.js → FailureGroup-BgT73AaR.js} +14 -4
- package/dist/{Framing-zaYdOJnT.js → Framing-G9eSaeLb.js} +1 -1
- package/dist/{Graft-CVyueNOf.js → Graft-B71CPA2Y.js} +20 -16
- package/dist/{Packages-JNL34JpS.js → Packages-AgoCGotL.js} +23 -26
- package/dist/{Peer-BT7eAGmh.js → Peer-DXeVrGBh.js} +5 -5
- package/dist/{ProcessObservation-DEGrEMfP.js → ProcessObservation-gLgGirYv.js} +1 -1
- package/dist/{ServeLifecycle-CJM0gG5B.js → ServeLifecycle-Bd1FPJ6e.js} +1 -1
- package/dist/Transport.d.ts +2 -2
- package/dist/Transport.d.ts.map +1 -1
- package/dist/Transport.js.map +1 -1
- package/dist/bin.js +48 -47
- package/dist/bin.js.map +1 -1
- package/dist/{childRuntime-An0HsIzl.js → childRuntime-Bm3iSg_N.js} +29 -26
- package/dist/{connectionEnded-DCpFCjMX.js → connectionEnded-BwcxQ7W8.js} +4 -4
- package/dist/{entry-B89sepMU.js → entry-psOpX3Bj.js} +72 -35
- package/dist/host/auth/bearer.js +1 -1
- package/dist/host/auth/jwt.js +1 -1
- package/dist/host/auth/mtls.js +2 -2
- package/dist/host/auth/none.js +1 -1
- package/dist/host/command.js +4 -4
- package/dist/host/local.js +3 -3
- package/dist/host/unix.js +3 -3
- package/dist/host/websocket.js +3 -3
- package/dist/host/worker.js +4 -5
- package/dist/{importer-Bk6U_sn4.js → importer-Cvf88eAY.js} +5 -8
- package/dist/index.js +9 -9
- package/dist/index.js.map +1 -1
- package/dist/internal/Certificates.js +4 -4
- package/dist/internal/Certificates.js.map +1 -1
- package/dist/internal/FailureGroup.js +3 -2
- package/dist/internal/FailureGroup.js.map +1 -1
- package/dist/internal/assembly.js +9 -2
- package/dist/internal/assembly.js.map +1 -1
- package/dist/internal/auth/mtls.js +1 -1
- package/dist/internal/auth/mtls.js.map +1 -1
- package/dist/internal/child.js +20 -17
- package/dist/internal/child.js.map +1 -1
- package/dist/internal/childRuntime.js +4 -4
- package/dist/internal/childRuntime.js.map +1 -1
- package/dist/internal/directTransport.d.ts +1 -1
- package/dist/internal/entry.d.ts.map +1 -1
- package/dist/internal/entry.js +1 -1
- package/dist/internal/entry.js.map +1 -1
- package/dist/internal/execution.js +40 -5
- package/dist/internal/execution.js.map +1 -1
- package/dist/internal/host/runner.js +7 -6
- package/dist/internal/host/runner.js.map +1 -1
- package/dist/internal/host.js +5 -5
- package/dist/internal/host.js.map +1 -1
- package/dist/internal/port.js +5 -5
- package/dist/internal/port.js.map +1 -1
- package/dist/internal/release.js +1 -1
- package/dist/internal/release.js.map +1 -1
- package/dist/internal/runner/Connection.d.ts +1 -1
- package/dist/internal/runner/Connection.js +4 -4
- package/dist/internal/runner/Connection.js.map +1 -1
- package/dist/internal/runner/Execution.js +3 -3
- package/dist/internal/runner/Execution.js.map +1 -1
- package/dist/internal/runner/Framing.js +1 -1
- package/dist/internal/runner/Framing.js.map +1 -1
- package/dist/internal/runner/Local.js +1 -1
- package/dist/internal/runner/Local.js.map +1 -1
- package/dist/internal/runner/Lock.js +1 -1
- package/dist/internal/runner/Lock.js.map +1 -1
- package/dist/internal/runner/Packages.d.ts +1 -1
- package/dist/internal/runner/Packages.js +22 -25
- package/dist/internal/runner/Packages.js.map +1 -1
- package/dist/internal/runner/Processes.js +7 -9
- package/dist/internal/runner/Processes.js.map +1 -1
- package/dist/internal/runner/Store.js +3 -3
- package/dist/internal/runner/Store.js.map +1 -1
- package/dist/internal/runner/Supervisor.js +46 -47
- package/dist/internal/runner/Supervisor.js.map +1 -1
- package/dist/internal/runner/accept.js +3 -3
- package/dist/internal/runner/accept.js.map +1 -1
- package/dist/internal/runner/model.js +1 -1
- package/dist/internal/runner/model.js.map +1 -1
- package/dist/internal/serve.js +1 -1
- package/dist/internal/serve.js.map +1 -1
- package/dist/internal/supervisorPlugin.js +1 -1
- package/dist/internal/watchdogMain.js +5 -5
- package/dist/internal/watchdogMain.js.map +1 -1
- package/dist/internal/websocketServer.js +3 -1
- package/dist/internal/websocketServer.js.map +1 -1
- package/dist/internal/workerMain.js +3 -3
- package/dist/{port-DSVUY8Bq.js → port--3x2zJ4D.js} +8 -8
- package/dist/{release-BY4Mlluy.js → release-DfZPuIcK.js} +1 -1
- package/dist/runner/auth/bearer.js +2 -2
- package/dist/runner/auth/jwt.js +4 -4
- package/dist/runner/auth/jwt.js.map +1 -1
- package/dist/runner/auth/mtls.js +3 -3
- package/dist/runner/auth/none.js +1 -1
- package/dist/runner/index.js +5 -5
- package/dist/runner/stdio.js +3 -3
- package/dist/runner/unix.js +3 -3
- package/dist/runner/websocket.js +4 -4
- package/dist/{socketChannel-C_ppdSzz.js → socketChannel-CJvL2DiB.js} +2 -2
- package/dist/{supervisorPlugin-CivhM7x5.js → supervisorPlugin-t6Z6PrhD.js} +72 -76
- package/dist/{token-Cc_1CTbE.js → token-CYBNNlhS.js} +1 -1
- package/dist/{tokenCredentials-CI6mMRRd.js → tokenCredentials-CbCuk-Rt.js} +3 -3
- package/dist/{websocketServer-D2Hk7wsA.js → websocketServer-NQhODlEt.js} +5 -3
- package/dist/{workerChannel-cmLc13vm.js → workerChannel-C8hhBJzA.js} +1 -1
- package/package.json +3 -3
- package/src/Auth.ts +9 -2
- package/src/Errors.ts +8 -0
- package/src/Transport.ts +6 -2
- package/src/bin.ts +28 -30
- package/src/index.ts +5 -3
- package/src/internal/Certificates.ts +10 -13
- package/src/internal/FailureGroup.ts +128 -121
- package/src/internal/assembly.ts +19 -10
- package/src/internal/auth/mtls.ts +19 -20
- package/src/internal/child.ts +248 -239
- package/src/internal/childRuntime.ts +81 -80
- package/src/internal/entry.ts +10 -11
- package/src/internal/execution.ts +69 -12
- package/src/internal/host/runner.ts +153 -153
- package/src/internal/host.ts +116 -120
- package/src/internal/port.ts +100 -103
- package/src/internal/release.ts +3 -2
- package/src/internal/runner/Connection.ts +52 -60
- package/src/internal/runner/Execution.ts +163 -164
- package/src/internal/runner/Framing.ts +9 -10
- package/src/internal/runner/Local.ts +26 -27
- package/src/internal/runner/Lock.ts +23 -25
- package/src/internal/runner/Packages.ts +67 -70
- package/src/internal/runner/Processes.ts +89 -92
- package/src/internal/runner/Store.ts +110 -114
- package/src/internal/runner/Supervisor.ts +392 -405
- package/src/internal/runner/accept.ts +76 -84
- package/src/internal/runner/model.ts +20 -21
- package/src/internal/serve.ts +15 -13
- package/src/internal/watchdogMain.ts +16 -11
- package/src/internal/websocketServer.ts +18 -3
- package/src/runner/auth/jwt.ts +10 -6
- package/dist/cleanup-CXLa1Wd9.js +0 -13
|
@@ -1,23 +1,22 @@
|
|
|
1
|
-
import { c as isPlugin, i as plugin, l as make, o as fork, t as forks, u as optional } from "./Graft-
|
|
1
|
+
import { c as isPlugin, i as plugin, l as make, o as fork, t as forks, u as optional } from "./Graft-B71CPA2Y.js";
|
|
2
2
|
import { t as ConfigDirectory } from "./ConfigDirectory-BCC6q2R4.js";
|
|
3
|
-
import { i as make$2, m as isSubtreeActive, n as ModuleInvalid, o as CurrentId, p as findSubtree, r as ModuleResolver, t as make$1 } from "./importer-
|
|
4
|
-
import { c as endpoint, n as UndeclaredFailure, o as endpoints, r as fromModule } from "./Contract-
|
|
5
|
-
import { a as
|
|
3
|
+
import { i as make$2, m as isSubtreeActive, n as ModuleInvalid, o as CurrentId, p as findSubtree, r as ModuleResolver, t as make$1 } from "./importer-Cvf88eAY.js";
|
|
4
|
+
import { c as endpoint, n as UndeclaredFailure, o as endpoints, r as fromModule } from "./Contract-DsJtisvL.js";
|
|
5
|
+
import { a as MissingInstance, c as RemoteError, i as LocalTerminationTimeout, l as RemoteWithdrawn, o as ProcessExited, r as CredentialsError, s as RemoteEntryError, t as AuthenticationFailed, u as TransportError } from "./Errors-DYhsGZcZ.js";
|
|
6
6
|
import { n as WorkerTransport, t as LocalTransport } from "./directTransport-DrexuPSm.js";
|
|
7
|
-
import { a as PositiveDuration, i as Supervisor, n as resolveEntry, r as verify } from "./Packages-
|
|
8
|
-
import { E as make$3, b as awaitTermination, n as Session, r as channel, t as Peer, x as childOf } from "./Peer-
|
|
7
|
+
import { a as PositiveDuration, i as Supervisor, n as resolveEntry, r as verify } from "./Packages-AgoCGotL.js";
|
|
8
|
+
import { E as make$3, _ as StateStorageError, a as ExecutionError, b as awaitTermination, c as PackageError, d as SessionAccessDenied, f as SessionConflict, g as StateDirectoryLocked, h as StaleSession, l as RemoteTerminationUnconfirmed, m as SessionStopped, n as Session, r as channel, s as LeaseExpired, t as Peer, u as RunnerClosing, x as childOf, y as TerminationUnconfirmed } from "./Peer-DXeVrGBh.js";
|
|
9
9
|
import { n as Credentials, t as Authenticator } from "./Auth-BElTC9_X.js";
|
|
10
10
|
import { n as Listener, t as Connector } from "./Transport-DULzpsgR.js";
|
|
11
|
-
import { n as connectionEnded, r as prepare, t as closedNormally } from "./connectionEnded-
|
|
12
|
-
import { t as ServeLifecycle } from "./ServeLifecycle-
|
|
13
|
-
import { t as make$4 } from "./FailureGroup-
|
|
14
|
-
import { n as
|
|
15
|
-
import { n as
|
|
16
|
-
import { n as
|
|
17
|
-
import {
|
|
18
|
-
import { Array, Cause, Context, Deferred, Duration, Effect, Exit, Fiber, Option, Path, Ref, References, Schema, Scope, Stream, String } from "effect";
|
|
11
|
+
import { a as AlreadyLoaded, i as ActivationFailed, n as connectionEnded, o as ContractNotFound, r as prepare, s as ModuleImportFailed, t as closedNormally } from "./connectionEnded-BwcxQ7W8.js";
|
|
12
|
+
import { t as ServeLifecycle } from "./ServeLifecycle-Bd1FPJ6e.js";
|
|
13
|
+
import { n as children, r as cleanupCause, t as make$4 } from "./FailureGroup-BgT73AaR.js";
|
|
14
|
+
import { n as make$5, o as defaults } from "./port--3x2zJ4D.js";
|
|
15
|
+
import { n as close, t as ReleaseInterrupted } from "./release-DfZPuIcK.js";
|
|
16
|
+
import { n as stdinExitTimeout } from "./ProcessObservation-gLgGirYv.js";
|
|
17
|
+
import { Array, Cause, Context, Deferred, Duration, Effect, Exit, Fiber, Option, Path, PlatformError, Ref, References, Schema, Scope, Stream, String } from "effect";
|
|
19
18
|
import { SecureRandom } from "effect/crypto";
|
|
20
|
-
import { RpcClient } from "effect/rpc";
|
|
19
|
+
import { RpcClient, RpcClientError } from "effect/rpc";
|
|
21
20
|
import { ChildProcessSpawner } from "effect/process";
|
|
22
21
|
// packages/remote/src/internal/entryConfig.ts
|
|
23
22
|
const Reference = Schema.Struct({
|
|
@@ -216,6 +215,13 @@ var CapabilityCombinationError = class extends Schema.TaggedError()("CapabilityC
|
|
|
216
215
|
}
|
|
217
216
|
};
|
|
218
217
|
var CapabilityFailed = class extends Schema.TaggedError()("CapabilityFailed", { cause: Schema.Cause(Schema.Unknown, Schema.Unknown) }) {};
|
|
218
|
+
/** Every failure class assembly raises; host error classification reads this list. */
|
|
219
|
+
const errors = [
|
|
220
|
+
ListenerConfigError,
|
|
221
|
+
CapabilityContractError,
|
|
222
|
+
CapabilityCombinationError,
|
|
223
|
+
CapabilityFailed
|
|
224
|
+
];
|
|
219
225
|
const definition = Schema.declare(isPlugin);
|
|
220
226
|
/** Entries resolve capability modules before assembling their private providers. */
|
|
221
227
|
const Invocation = Schema.Struct({
|
|
@@ -281,7 +287,7 @@ const compatible = (properties, kind) => {
|
|
|
281
287
|
const kind = (auth) => auth._tag === "Mtls" ? "Certificate" : auth._tag === "Header" ? "Authorization" : "None";
|
|
282
288
|
const warn = (properties, credentials, side) => Effect.all([properties.network && !properties.encrypted ? Effect.logWarning(credentials === "Authorization" ? `${properties.protocol}:// ${side === "host" ? "connection" : "listener"} is unencrypted; credentials are transmitted in plaintext` : `${properties.protocol}:// ${side === "host" ? "connection" : "listener"} is unencrypted`) : Effect.void, side === "runner" && properties.network && credentials === "None" ? Effect.logWarning("WebSocket listener has no authentication") : Effect.void], { discard: true });
|
|
283
289
|
const directAuth = (properties, explicit) => explicit && (properties.protocol === "stdio" || properties.protocol === "command") ? Effect.fail(CapabilityCombinationError.make({ detail: `${properties.protocol} transports do not accept auth` })) : Effect.void;
|
|
284
|
-
const connectWith =
|
|
290
|
+
const connectWith = Effect.fnUntraced(function* (explicitAuth = false) {
|
|
285
291
|
const connector = yield* Connector;
|
|
286
292
|
const credentials = yield* Credentials;
|
|
287
293
|
yield* directAuth(connector.properties, explicitAuth);
|
|
@@ -321,7 +327,7 @@ const makeListenerConsumer = (prepare = () => Effect.void, ready = Effect.void)
|
|
|
321
327
|
const listenerConsumer = makeListenerConsumer();
|
|
322
328
|
connectWith();
|
|
323
329
|
// packages/remote/src/internal/host/runner.ts
|
|
324
|
-
const connect$1 = (target, contractModule, options, resources, processScope)
|
|
330
|
+
const connect$1 = Effect.fnUntraced(function* (target, contractModule, options, resources, processScope) {
|
|
325
331
|
const instance = target.instance;
|
|
326
332
|
const margin = Duration.toMillis(target.margin ?? "5 seconds");
|
|
327
333
|
const channel$1 = yield* connectWith(target.explicitAuth).pipe(Scope.provide(processScope));
|
|
@@ -344,7 +350,7 @@ const connect$1 = (target, contractModule, options, resources, processScope) =>
|
|
|
344
350
|
const finishStarted = yield* Ref.make(false);
|
|
345
351
|
const terminate = yield* Effect.cached(Effect.gen(function* () {
|
|
346
352
|
yield* Ref.set(finishStarted, true);
|
|
347
|
-
yield* failures.close;
|
|
353
|
+
const closed = yield* Effect.exit(failures.close);
|
|
348
354
|
const result = yield* awaitTermination(record.handle, session.Dispose(record.handle), record.leaseMillis, margin);
|
|
349
355
|
const { code, signal, stderr, cause } = result.exit;
|
|
350
356
|
yield* Effect.logInfo("Remote execution terminated", {
|
|
@@ -357,7 +363,8 @@ const connect$1 = (target, contractModule, options, resources, processScope) =>
|
|
|
357
363
|
"remote.generation": record.handle.generation,
|
|
358
364
|
"remote.termination": result.kind
|
|
359
365
|
}));
|
|
360
|
-
|
|
366
|
+
const failure = Exit.isFailure(closed) ? Cause.combine(closed.cause, result.cause) : result.cause;
|
|
367
|
+
if (failure.reasons.length > 0) return yield* Effect.failCause(cleanupCause(failure));
|
|
361
368
|
}));
|
|
362
369
|
yield* Scope.addFinalizer(processScope, Effect.gen(function* () {
|
|
363
370
|
if (!(yield* Ref.get(finishStarted))) yield* terminate.pipe(Effect.catchCause((cause) => Effect.failCause(cleanupCause(cause))));
|
|
@@ -377,7 +384,7 @@ const connect$1 = (target, contractModule, options, resources, processScope) =>
|
|
|
377
384
|
}).pipe(Scope.provide(resources));
|
|
378
385
|
const report = (cause) => Cause.hasInterruptsOnly(cause) ? Effect.void : failures.failCause(Cause.map(cause, (error) => TransportError.make({ cause: Cause.fail(error) })));
|
|
379
386
|
yield* failures.await.pipe(Effect.catchCause((cause) => Cause.hasInterruptsOnly(cause) ? Effect.void : peer.fail(TransportError.make({ cause }))), Effect.forkIn(resources));
|
|
380
|
-
yield* failures.run(Fiber.join(renewed).pipe(Effect.catchCause(
|
|
387
|
+
yield* failures.run(Fiber.join(renewed).pipe(Effect.catchCause(Effect.fnUntraced(function* (cause) {
|
|
381
388
|
if (Cause.hasInterruptsOnly(cause)) return;
|
|
382
389
|
const status = yield* Effect.exit(session.Status(record.handle).pipe(Effect.timeout("5 seconds")));
|
|
383
390
|
if (Exit.isSuccess(status) && status.value.phase === "Stopped") {
|
|
@@ -394,7 +401,7 @@ const connect$1 = (target, contractModule, options, resources, processScope) =>
|
|
|
394
401
|
resources,
|
|
395
402
|
pid: Option.map(childOf(loaded), (child) => child.pid),
|
|
396
403
|
diagnostics: failures.cause,
|
|
397
|
-
terminate:
|
|
404
|
+
terminate: Effect.fnUntraced(function* () {
|
|
398
405
|
yield* Fiber.interrupt(renewed);
|
|
399
406
|
yield* terminate;
|
|
400
407
|
}),
|
|
@@ -426,7 +433,7 @@ const connect = Effect.fnUntraced(function* (execution, options) {
|
|
|
426
433
|
report
|
|
427
434
|
},
|
|
428
435
|
diagnostics: Fiber.await(exited).pipe(Effect.andThen(failures.cause)),
|
|
429
|
-
terminate:
|
|
436
|
+
terminate: Effect.fnUntraced(function* (graceful) {
|
|
430
437
|
yield* failures.close;
|
|
431
438
|
if (!graceful) return;
|
|
432
439
|
const status = yield* peer.end.pipe(Effect.catchCauseIf(Cause.hasInterruptsOnly, () => Effect.void), Effect.andThen(Fiber.join(exited)), Effect.interruptible, Effect.timeoutOrElse({
|
|
@@ -463,17 +470,17 @@ const finish = (causes) => {
|
|
|
463
470
|
const scopes = Effect.acquireRelease(Effect.all({
|
|
464
471
|
resources: Scope.make(),
|
|
465
472
|
process: Scope.make()
|
|
466
|
-
}),
|
|
473
|
+
}), Effect.fnUntraced(function* (scopes, exit) {
|
|
467
474
|
const process = yield* Effect.exit(close(scopes.process, exit));
|
|
468
475
|
const resources = yield* Effect.exit(close(scopes.resources, exit));
|
|
469
476
|
yield* finish([reason(process), reason(resources)]);
|
|
470
477
|
}));
|
|
471
478
|
/** Setup supplies a concrete control lifecycle; release never reads a later-installed effect. */
|
|
472
|
-
const acquire = (target, contractModule, options, setup, dispose, timeout)
|
|
479
|
+
const acquire = Effect.fnUntraced(function* (target, contractModule, options, setup, dispose, timeout) {
|
|
473
480
|
const owned = yield* scopes;
|
|
474
481
|
const connection = yield* Effect.acquireRelease(Effect.gen(function* () {
|
|
475
482
|
return target._tag === "Local" || target._tag === "Worker" ? yield* Local(target, contractModule, options, owned.resources, owned.process).pipe(Effect.map(connected)) : yield* connect$1(target, contractModule, options, owned.resources, owned.process);
|
|
476
|
-
}).pipe(Effect.interruptible),
|
|
483
|
+
}).pipe(Effect.interruptible), Effect.fnUntraced(function* (connection, exit) {
|
|
477
484
|
const process = yield* Effect.exit(close(owned.process, exit));
|
|
478
485
|
yield* connection.diagnostics;
|
|
479
486
|
const resources = yield* Effect.exit(close(owned.resources, exit));
|
|
@@ -484,7 +491,7 @@ const acquire = (target, contractModule, options, setup, dispose, timeout) => Ef
|
|
|
484
491
|
diagnostics
|
|
485
492
|
]);
|
|
486
493
|
}));
|
|
487
|
-
return yield* Effect.acquireRelease(setup.pipe(Effect.provideService(Connection, connection)),
|
|
494
|
+
return yield* Effect.acquireRelease(setup.pipe(Effect.provideService(Connection, connection)), Effect.fnUntraced(function* (value) {
|
|
488
495
|
const graceful = yield* dispose(value).pipe(Effect.interruptible, Effect.timeout(timeout), Effect.exit);
|
|
489
496
|
const terminated = yield* Effect.exit(connection.terminate(Exit.isSuccess(graceful)));
|
|
490
497
|
yield* finish([Exit.isSuccess(graceful) ? graceful.value : graceful.cause, reason(terminated)]);
|
|
@@ -492,7 +499,7 @@ const acquire = (target, contractModule, options, setup, dispose, timeout) => Ef
|
|
|
492
499
|
});
|
|
493
500
|
// packages/remote/src/internal/host.ts
|
|
494
501
|
const race = (connection, effect) => Effect.raceFirst(effect, connection.transport.failure);
|
|
495
|
-
const forwardEvents = (contract, client, connection)
|
|
502
|
+
const forwardEvents = Effect.fnUntraced(function* (contract, client, connection) {
|
|
496
503
|
const stopped = yield* Deferred.make();
|
|
497
504
|
const remoteFailure = yield* make$4();
|
|
498
505
|
return {
|
|
@@ -507,10 +514,10 @@ const forwardEvents = (contract, client, connection) => Effect.gen(function* ()
|
|
|
507
514
|
}))).pipe(Effect.tapCause(connection.transport.report), Effect.forkIn(connection.resources))
|
|
508
515
|
};
|
|
509
516
|
});
|
|
510
|
-
const forwardLogs = (contract, client, connection)
|
|
517
|
+
const forwardLogs = Effect.fnUntraced(function* (contract, client, connection) {
|
|
511
518
|
const logsEnded = yield* Deferred.make();
|
|
512
519
|
const reportedDrops = yield* Ref.make(0);
|
|
513
|
-
yield* race(connection, client.Logs().pipe(Stream.runForEach(
|
|
520
|
+
yield* race(connection, client.Logs().pipe(Stream.runForEach(Effect.fnUntraced(function* (event) {
|
|
514
521
|
const previous = yield* Ref.getAndSet(reportedDrops, event.dropped);
|
|
515
522
|
if (event.dropped > previous) yield* Effect.logWarning("Remote logs were dropped").pipe(Effect.annotateLogs({
|
|
516
523
|
...Option.isSome(connection.pid) ? { "remote.pid": connection.pid.value } : {},
|
|
@@ -531,7 +538,7 @@ const forwardLogs = (contract, client, connection) => Effect.gen(function* () {
|
|
|
531
538
|
})))).pipe(Effect.tapCause(connection.transport.report), Effect.forkIn(connection.resources));
|
|
532
539
|
return logsEnded;
|
|
533
540
|
});
|
|
534
|
-
const initialize =
|
|
541
|
+
const initialize = Effect.fnUntraced(function* (contract) {
|
|
535
542
|
const connection = yield* Connection;
|
|
536
543
|
const client = yield* RpcClient.make(contract.control).pipe(Effect.provideService(RpcClient.Protocol, connection.transport.clientProtocol(endpoint)), Scope.provide(connection.resources));
|
|
537
544
|
for (const service of contract.inject) yield* service.serve(connection.transport).pipe(Effect.tapCause(connection.transport.report), Effect.forkIn(connection.resources));
|
|
@@ -545,7 +552,7 @@ const initialize = (contract) => Effect.gen(function* () {
|
|
|
545
552
|
};
|
|
546
553
|
});
|
|
547
554
|
const load$1 = (active, input) => race(active.connection, Effect.raceFirst(active.client.Load({ input }).pipe(Effect.catchIf((cause) => Cause.isCause(cause), Effect.failCause)), active.remoteFailure.await));
|
|
548
|
-
const dispose =
|
|
555
|
+
const dispose = Effect.fnUntraced(function* (active) {
|
|
549
556
|
const result = yield* race(active.connection, active.client.Dispose().pipe(Effect.catchIf(Cause.isCause, Effect.succeed)));
|
|
550
557
|
const cause = Cause.isCause(result) ? result : Cause.empty;
|
|
551
558
|
yield* race(active.connection, Deferred.await(active.stopped).pipe(Effect.andThen(Deferred.await(active.logsEnded)))).pipe(Effect.onError(() => Effect.failCause(cleanupCause(cause))));
|
|
@@ -562,7 +569,7 @@ const executionPlugin = (contract, options, configured, annotations = {}) => mak
|
|
|
562
569
|
...Array.map(contract.inject, (service) => service.key)
|
|
563
570
|
],
|
|
564
571
|
config: Schema.toEncoded(contract.config),
|
|
565
|
-
apply:
|
|
572
|
+
apply: Effect.fnUntraced(function* (input) {
|
|
566
573
|
const prepared = prepare(contract);
|
|
567
574
|
const session = yield* (yield* SecureRandom.SecureRandom).uuidV4();
|
|
568
575
|
const active = yield* acquire(configured, options.contractModule, {
|
|
@@ -577,9 +584,39 @@ const executionPlugin = (contract, options, configured, annotations = {}) => mak
|
|
|
577
584
|
for (const service of contract.provides) yield* service.publish(active.connection.transport).pipe(Scope.provide(active.connection.resources));
|
|
578
585
|
yield* fork(Effect.raceFirst(Fiber.join(active.events), active.remoteFailure.await).pipe(Effect.mapError((error) => publicError(contract.error, error))));
|
|
579
586
|
return () => Effect.succeed(false);
|
|
580
|
-
}
|
|
587
|
+
}, Effect.annotateLogs(annotations), Effect.mapError((error) => publicError(contract.error, error)))
|
|
581
588
|
});
|
|
582
|
-
|
|
589
|
+
/** Failures raised by the host machinery; a permissive declared schema must not claim them. */
|
|
590
|
+
const internalErrors = [
|
|
591
|
+
ProcessExited,
|
|
592
|
+
TransportError,
|
|
593
|
+
LocalTerminationTimeout,
|
|
594
|
+
CredentialsError,
|
|
595
|
+
AuthenticationFailed,
|
|
596
|
+
RemoteEntryError,
|
|
597
|
+
AlreadyLoaded,
|
|
598
|
+
ContractNotFound,
|
|
599
|
+
ModuleImportFailed,
|
|
600
|
+
ActivationFailed,
|
|
601
|
+
PackageError,
|
|
602
|
+
SessionAccessDenied,
|
|
603
|
+
StaleSession,
|
|
604
|
+
LeaseExpired,
|
|
605
|
+
SessionStopped,
|
|
606
|
+
SessionConflict,
|
|
607
|
+
StateStorageError,
|
|
608
|
+
ExecutionError,
|
|
609
|
+
TerminationUnconfirmed,
|
|
610
|
+
RunnerClosing,
|
|
611
|
+
StateDirectoryLocked,
|
|
612
|
+
RemoteTerminationUnconfirmed,
|
|
613
|
+
ReleaseInterrupted,
|
|
614
|
+
RpcClientError.RpcClientError,
|
|
615
|
+
...errors
|
|
616
|
+
];
|
|
617
|
+
const isInternal = (error) => Schema.isSchemaError(error) || PlatformError.isPlatformError(error) || Array.some(internalErrors, (Class) => error instanceof Class);
|
|
618
|
+
const isPublic = (error) => Schema.is(UndeclaredFailure)(error) || Schema.is(RemoteWithdrawn)(error) || Schema.is(RemoteError)(error) || Schema.is(MissingInstance)(error);
|
|
619
|
+
const publicError = (declared, error) => isPublic(error) ? error : !isInternal(error) && Schema.is(declared)(error) ? error : RemoteError.make({ cause: Cause.fail(error) });
|
|
583
620
|
// packages/remote/src/internal/entry.ts
|
|
584
621
|
const boundary = Effect.fnUntraced(function* (field) {
|
|
585
622
|
const entry = yield* CurrentId;
|
|
@@ -598,7 +635,7 @@ const resolve = Effect.fnUntraced(function* (reference, field) {
|
|
|
598
635
|
const directory = path.resolve(Option.getOrElse(source, () => "."));
|
|
599
636
|
const resolver = yield* Option.match(existing, {
|
|
600
637
|
onSome: Effect.succeed,
|
|
601
|
-
onNone:
|
|
638
|
+
onNone: Effect.fnUntraced(function* () {
|
|
602
639
|
const importer = yield* make$1(directory);
|
|
603
640
|
return yield* make$2({
|
|
604
641
|
base: directory,
|
package/dist/host/auth/bearer.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as plugin, t as Config } from "../../tokenCredentials-
|
|
1
|
+
import { n as plugin, t as Config } from "../../tokenCredentials-CbCuk-Rt.js";
|
|
2
2
|
// packages/remote/src/host/auth/bearer.ts
|
|
3
3
|
const capability = plugin("remote-bearer-credentials");
|
|
4
4
|
export { Config, capability as default };
|
package/dist/host/auth/jwt.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as plugin, t as Config } from "../../tokenCredentials-
|
|
1
|
+
import { n as plugin, t as Config } from "../../tokenCredentials-CbCuk-Rt.js";
|
|
2
2
|
// packages/remote/src/host/auth/jwt.ts
|
|
3
3
|
const capability = plugin("remote-jwt-credentials");
|
|
4
4
|
export { Config, capability as default };
|
package/dist/host/auth/mtls.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { a as provide, l as make } from "../../Graft-
|
|
2
|
-
import {
|
|
1
|
+
import { a as provide, l as make } from "../../Graft-B71CPA2Y.js";
|
|
2
|
+
import { r as CredentialsError } from "../../Errors-DYhsGZcZ.js";
|
|
3
3
|
import { t as ConfigDirectory } from "../../ConfigDirectory-BCC6q2R4.js";
|
|
4
4
|
import { n as Credentials } from "../../Auth-BElTC9_X.js";
|
|
5
5
|
import { Cause, Effect, FileSystem, Option, Path, Redacted, Schema } from "effect";
|
package/dist/host/auth/none.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as provide, l as make } from "../../Graft-
|
|
1
|
+
import { a as provide, l as make } from "../../Graft-B71CPA2Y.js";
|
|
2
2
|
import { n as Credentials } from "../../Auth-BElTC9_X.js";
|
|
3
3
|
import { Effect, Schema } from "effect";
|
|
4
4
|
// packages/remote/src/host/auth/none.ts
|
package/dist/host/command.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { a as provide, l as make$1 } from "../Graft-
|
|
1
|
+
import { a as provide, l as make$1 } from "../Graft-B71CPA2Y.js";
|
|
2
2
|
import { t as Connector } from "../Transport-DULzpsgR.js";
|
|
3
3
|
import { t as ConfigDirectory } from "../ConfigDirectory-BCC6q2R4.js";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import { n as stdinExitTimeout, t as observe } from "../ProcessObservation-
|
|
4
|
+
import { u as TransportError } from "../Errors-DYhsGZcZ.js";
|
|
5
|
+
import { r as cleanupCause } from "../FailureGroup-BgT73AaR.js";
|
|
6
|
+
import { n as stdinExitTimeout, t as observe } from "../ProcessObservation-gLgGirYv.js";
|
|
7
7
|
import { Array, Cause, Effect, Option, Path, Schema, Scope, Sink, Stream } from "effect";
|
|
8
8
|
import { ChildProcess, ChildProcessSpawner } from "effect/process";
|
|
9
9
|
// packages/remote/src/host/command.ts
|
package/dist/host/local.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { d as service } from "../Graft-
|
|
1
|
+
import { d as service } from "../Graft-B71CPA2Y.js";
|
|
2
2
|
import { t as LocalTransport } from "../directTransport-DrexuPSm.js";
|
|
3
3
|
import { t as command } from "../command-9zrHdbwT.js";
|
|
4
|
-
import {
|
|
5
|
-
import { t as observe$1 } from "../ProcessObservation-
|
|
4
|
+
import { o as ProcessExited, u as TransportError } from "../Errors-DYhsGZcZ.js";
|
|
5
|
+
import { t as observe$1 } from "../ProcessObservation-gLgGirYv.js";
|
|
6
6
|
import { Array, Cause, Effect, Fiber, Option, Scope, Sink, Stream } from "effect";
|
|
7
7
|
import { ChildProcess, ChildProcessSpawner } from "effect/process";
|
|
8
8
|
// packages/remote/src/internal/host/local.ts
|
package/dist/host/unix.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { a as provide, l as make$1 } from "../Graft-
|
|
1
|
+
import { a as provide, l as make$1 } from "../Graft-B71CPA2Y.js";
|
|
2
2
|
import { t as ConfigDirectory } from "../ConfigDirectory-BCC6q2R4.js";
|
|
3
|
-
import { a as payloadLimit, c as wrapper_default, i as path, s as protocol, t as fromSocket } from "../socketChannel-
|
|
3
|
+
import { a as payloadLimit, c as wrapper_default, i as path, s as protocol, t as fromSocket } from "../socketChannel-CJvL2DiB.js";
|
|
4
4
|
import { t as Connector } from "../Transport-DULzpsgR.js";
|
|
5
|
-
import {
|
|
5
|
+
import { u as TransportError } from "../Errors-DYhsGZcZ.js";
|
|
6
6
|
import { Cause, Effect, Layer, Option, Path, Redacted, Schema } from "effect";
|
|
7
7
|
import { Socket } from "effect/socket";
|
|
8
8
|
// packages/remote/src/host/unix.ts
|
package/dist/host/websocket.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { a as provide, l as make$1 } from "../Graft-
|
|
1
|
+
import { a as provide, l as make$1 } from "../Graft-B71CPA2Y.js";
|
|
2
2
|
import { t as Connector } from "../Transport-DULzpsgR.js";
|
|
3
|
-
import {
|
|
3
|
+
import { u as TransportError } from "../Errors-DYhsGZcZ.js";
|
|
4
4
|
import { t as ConfigDirectory } from "../ConfigDirectory-BCC6q2R4.js";
|
|
5
|
-
import { n as Url, o as properties, r as open, t as fromSocket } from "../socketChannel-
|
|
5
|
+
import { n as Url, o as properties, r as open, t as fromSocket } from "../socketChannel-CJvL2DiB.js";
|
|
6
6
|
import { Cause, Effect, FileSystem, Option, Path, Schema } from "effect";
|
|
7
7
|
// packages/remote/src/host/websocket.ts
|
|
8
8
|
/** Configured Connector; certificate paths belong to the enclosing configuration. */
|
package/dist/host/worker.js
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import { d as service } from "../Graft-
|
|
1
|
+
import { d as service } from "../Graft-B71CPA2Y.js";
|
|
2
2
|
import { n as WorkerTransport } from "../directTransport-DrexuPSm.js";
|
|
3
|
-
import {
|
|
4
|
-
import { n as Bootstrap, t as make } from "../workerChannel-
|
|
5
|
-
import { t as make$1 } from "../FailureGroup-
|
|
6
|
-
import { n as cleanupCause } from "../cleanup-CXLa1Wd9.js";
|
|
3
|
+
import { o as ProcessExited, u as TransportError } from "../Errors-DYhsGZcZ.js";
|
|
4
|
+
import { n as Bootstrap, t as make } from "../workerChannel-C8hhBJzA.js";
|
|
5
|
+
import { r as cleanupCause, t as make$1 } from "../FailureGroup-BgT73AaR.js";
|
|
7
6
|
import { Cause, Deferred, Effect, FiberSet, Option, Schema } from "effect";
|
|
8
7
|
import { Worker } from "node:worker_threads";
|
|
9
8
|
// packages/remote/src/host/worker.ts
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { s as fromModule } from "./Graft-
|
|
1
|
+
import { s as fromModule } from "./Graft-B71CPA2Y.js";
|
|
2
2
|
import { t as ConfigDirectory } from "./ConfigDirectory-BCC6q2R4.js";
|
|
3
3
|
import { registerHooks } from "node:module";
|
|
4
4
|
import { Array, Cause, Config, Context, Data, Effect, Exit, HashMap, MutableList, Option, Path, Predicate, Record, Ref, Result, Schema, Scope, String } from "effect";
|
|
@@ -202,7 +202,7 @@ const inCandidateScope = (effect) => Effect.uninterruptibleMask((restore) => Eff
|
|
|
202
202
|
* Importers may attach observation-only leases to the separate observationScope.
|
|
203
203
|
* The caller keeps that scope through failure and closes it on retry or disposal.
|
|
204
204
|
*/
|
|
205
|
-
const make$1 =
|
|
205
|
+
const make$1 = Effect.fnUntraced(function* (options) {
|
|
206
206
|
const path = yield* Path.Path;
|
|
207
207
|
/** Keep the import target and Node's possible missing names in one normalization step. */
|
|
208
208
|
const normalize = Effect.fnUntraced(function* (specifier) {
|
|
@@ -253,14 +253,11 @@ const make$1 = (options) => Effect.gen(function* () {
|
|
|
253
253
|
});
|
|
254
254
|
const environment = options.resolution;
|
|
255
255
|
const revision = environment === void 0 ? 0 : yield* environment.revision;
|
|
256
|
-
const
|
|
257
|
-
if (cached.revision === revision) {
|
|
258
|
-
const found = HashMap.get(cached.entries, key);
|
|
259
|
-
if (Option.isSome(found)) return found.value;
|
|
260
|
-
} else yield* Ref.set(plans, {
|
|
256
|
+
const found = yield* Ref.modify(plans, (current) => current.revision === revision ? [HashMap.get(current.entries, key), current] : revision > current.revision ? [Option.none(), {
|
|
261
257
|
revision,
|
|
262
258
|
entries: HashMap.empty()
|
|
263
|
-
});
|
|
259
|
+
}] : [Option.none(), current]);
|
|
260
|
+
if (Option.isSome(found)) return found.value;
|
|
264
261
|
const normalized = yield* Effect.forEach(candidates(name), (specifier) => Effect.map(normalize(specifier), (candidate) => ({
|
|
265
262
|
...candidate,
|
|
266
263
|
specifier
|
package/dist/index.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { a as provide, l as make, u as optional } from "./Graft-
|
|
2
|
-
import { r as ModuleResolver } from "./importer-
|
|
3
|
-
import { a as publicError, d as follow, f as Host, n as host, r as launch, s as CapabilityFailed } from "./entry-
|
|
1
|
+
import { a as provide, l as make, u as optional } from "./Graft-B71CPA2Y.js";
|
|
2
|
+
import { r as ModuleResolver } from "./importer-Cvf88eAY.js";
|
|
3
|
+
import { a as publicError, d as follow, f as Host, n as host, r as launch, s as CapabilityFailed } from "./entry-psOpX3Bj.js";
|
|
4
4
|
import { n as Credentials } from "./Auth-BElTC9_X.js";
|
|
5
|
-
import {
|
|
6
|
-
import { n as prepare } from "./token-
|
|
7
|
-
import { n as UndeclaredFailure, t as Contract_exports } from "./Contract-
|
|
8
|
-
import { O as Instance, l as RemoteTerminationUnconfirmed } from "./Peer-
|
|
5
|
+
import { a as MissingInstance, c as RemoteError, l as RemoteWithdrawn, r as CredentialsError } from "./Errors-DYhsGZcZ.js";
|
|
6
|
+
import { n as prepare } from "./token-CYBNNlhS.js";
|
|
7
|
+
import { n as UndeclaredFailure, t as Contract_exports } from "./Contract-DsJtisvL.js";
|
|
8
|
+
import { O as Instance, l as RemoteTerminationUnconfirmed } from "./Peer-DXeVrGBh.js";
|
|
9
9
|
import { Array, Cause, Context, Effect, Path, Schema, Scope } from "effect";
|
|
10
10
|
import { SecureRandom } from "effect/crypto";
|
|
11
11
|
import { ChildProcessSpawner } from "effect/process";
|
|
@@ -69,7 +69,7 @@ const plugin = (contract, options) => make({
|
|
|
69
69
|
ChildProcessSpawner.ChildProcessSpawner
|
|
70
70
|
],
|
|
71
71
|
retry: options.retry,
|
|
72
|
-
apply:
|
|
72
|
+
apply: Effect.fnUntraced(function* () {
|
|
73
73
|
const input = yield* Schema.decodeUnknownEffect(Host)({
|
|
74
74
|
contract: options.contractModule,
|
|
75
75
|
connect: options.connect,
|
|
@@ -81,6 +81,6 @@ const plugin = (contract, options) => make({
|
|
|
81
81
|
shutdownTimeout: options.shutdownTimeout
|
|
82
82
|
}, invocation(options.connect));
|
|
83
83
|
yield* follow(child, (cause) => Effect.failCause(publicCause(contract.error, cause)));
|
|
84
|
-
}
|
|
84
|
+
}, Effect.mapError((error) => publicError(contract.error, error)))
|
|
85
85
|
});
|
|
86
86
|
export { Contract_exports as Contract, Instance, MissingInstance, RemoteError, RemoteTerminationUnconfirmed, RemoteWithdrawn, UndeclaredFailure, host as default, plugin };
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["Configuration.Host","Credential.invocation"],"sources":["../src/index.ts"],"sourcesContent":["import { Plugin } from \"@graftland/graft\"\nimport { ModuleResolver } from \"@graftland/loader\"\nimport { Array, Cause, Effect, Path, Schema } from \"effect\"\nimport type { Duration, Schedule } from \"effect\"\nimport { SecureRandom } from \"effect/crypto\"\nimport { ChildProcessSpawner } from \"effect/process\"\nimport { launch } from \"./internal/entry\"\nimport { follow } from \"./internal/follow\"\nimport { CapabilityFailed } from \"./internal/assembly\"\nimport { publicError } from \"./internal/execution\"\nimport * as Configuration from \"./internal/entryConfig\"\nimport * as Credential from \"./internal/credentials\"\nimport { RemoteWithdrawn, RemoteError, MissingInstance } from \"./Errors\"\nimport * as Contract from \"./Contract\"\nexport { Contract }\nexport { Instance } from \"./Instance\"\nexport { RemoteTerminationUnconfirmed } from \"./internal/runner/model\"\nexport { RemoteError, RemoteWithdrawn, MissingInstance } from \"./Errors\"\nexport { UndeclaredFailure } from \"./Contract\"\nexport type {\n\tConnect,\n\tAuthentication,\n\tToken as CredentialToken,\n\tSource as CredentialSource,\n} from \"./internal/credentials\"\n\nexport interface Options<\n\tD extends ReadonlyArray<Plugin.Dependency> = readonly [],\n> {\n\treadonly connect: Credential.Connect<D>\n\t/** Contract module resolved independently in each execution environment. */\n\treadonly contractModule: string\n\treadonly config?: Schema.Json\n\treadonly retry?: Schedule.Schedule<unknown, unknown> | undefined\n\treadonly shutdownTimeout?: Duration.Input | undefined\n}\nconst publicCause = <E extends Schema.Top>(\n\tdeclared: E,\n\tcause: Cause.Cause<unknown>,\n): Cause.Cause<\n\t| E[\"Type\"]\n\t| Contract.UndeclaredFailure\n\t| RemoteWithdrawn\n\t| RemoteError\n\t| MissingInstance\n> =>\n\tCause.fromReasons(\n\t\tArray.flatMap(cause.reasons, (reason) => {\n\t\t\tif (reason._tag !== \"Fail\") return [reason]\n\t\t\treturn Schema.is(CapabilityFailed)(reason.error)\n\t\t\t\t? Array.map(\n\t\t\t\t\t\tpublicCause(declared, reason.error.cause).reasons,\n\t\t\t\t\t\t(inner) => inner.annotate(Cause.reasonAnnotations(reason)),\n\t\t\t\t\t)\n\t\t\t\t: [\n\t\t\t\t\t\tCause.makeFailReason(publicError(declared, reason.error)).annotate(\n\t\t\t\t\t\t\tCause.reasonAnnotations(reason),\n\t\t\t\t\t\t),\n\t\t\t\t\t]\n\t\t}),\n\t)\n\nexport const plugin = <\n\tS extends Schema.Top & {\n\t\treadonly Encoded: Schema.Json\n\t\treadonly DecodingServices: never\n\t\treadonly EncodingServices: never\n\t},\n\tE extends Schema.Top & {\n\t\treadonly DecodingServices: never\n\t\treadonly EncodingServices: never\n\t},\n\tconst D extends ReadonlyArray<Plugin.Dependency> = readonly [],\n>(\n\tcontract: Contract.Contract<S, E>,\n\toptions: Options<D> & { readonly config?: S[\"Encoded\"] },\n): Plugin.Plugin<\n\tvoid,\n\tvoid,\n\t| E[\"Type\"]\n\t| Contract.UndeclaredFailure\n\t| RemoteError\n\t| RemoteWithdrawn\n\t| MissingInstance\n> =>\n\tPlugin.make({\n\t\tname: contract.name,\n\t\tinject: [\n\t\t\tPlugin.optional(ModuleResolver.ModuleResolver),\n\t\t\tPath.Path,\n\t\t\tSecureRandom.SecureRandom,\n\t\t\tChildProcessSpawner.ChildProcessSpawner,\n\t\t],\n\t\tretry: options.retry,\n\t\tapply: (
|
|
1
|
+
{"version":3,"file":"index.js","names":["Configuration.Host","Credential.invocation"],"sources":["../src/index.ts"],"sourcesContent":["import { Plugin } from \"@graftland/graft\"\nimport { ModuleResolver } from \"@graftland/loader\"\nimport { Array, Cause, Effect, Path, Schema } from \"effect\"\nimport type { Duration, Schedule } from \"effect\"\nimport { SecureRandom } from \"effect/crypto\"\nimport { ChildProcessSpawner } from \"effect/process\"\nimport { launch } from \"./internal/entry\"\nimport { follow } from \"./internal/follow\"\nimport { CapabilityFailed } from \"./internal/assembly\"\nimport { publicError } from \"./internal/execution\"\nimport * as Configuration from \"./internal/entryConfig\"\nimport * as Credential from \"./internal/credentials\"\nimport { RemoteWithdrawn, RemoteError, MissingInstance } from \"./Errors\"\nimport * as Contract from \"./Contract\"\nexport { Contract }\nexport { Instance } from \"./Instance\"\nexport { RemoteTerminationUnconfirmed } from \"./internal/runner/model\"\nexport { RemoteError, RemoteWithdrawn, MissingInstance } from \"./Errors\"\nexport { UndeclaredFailure } from \"./Contract\"\nexport type {\n\tConnect,\n\tAuthentication,\n\tToken as CredentialToken,\n\tSource as CredentialSource,\n} from \"./internal/credentials\"\n\nexport interface Options<\n\tD extends ReadonlyArray<Plugin.Dependency> = readonly [],\n> {\n\treadonly connect: Credential.Connect<D>\n\t/** Contract module resolved independently in each execution environment. */\n\treadonly contractModule: string\n\treadonly config?: Schema.Json\n\treadonly retry?: Schedule.Schedule<unknown, unknown> | undefined\n\treadonly shutdownTimeout?: Duration.Input | undefined\n}\nconst publicCause = <E extends Schema.Top>(\n\tdeclared: E,\n\tcause: Cause.Cause<unknown>,\n): Cause.Cause<\n\t| E[\"Type\"]\n\t| Contract.UndeclaredFailure\n\t| RemoteWithdrawn\n\t| RemoteError\n\t| MissingInstance\n> =>\n\tCause.fromReasons(\n\t\tArray.flatMap(cause.reasons, (reason) => {\n\t\t\tif (reason._tag !== \"Fail\") return [reason]\n\t\t\treturn Schema.is(CapabilityFailed)(reason.error)\n\t\t\t\t? Array.map(\n\t\t\t\t\t\tpublicCause(declared, reason.error.cause).reasons,\n\t\t\t\t\t\t(inner) => inner.annotate(Cause.reasonAnnotations(reason)),\n\t\t\t\t\t)\n\t\t\t\t: [\n\t\t\t\t\t\tCause.makeFailReason(publicError(declared, reason.error)).annotate(\n\t\t\t\t\t\t\tCause.reasonAnnotations(reason),\n\t\t\t\t\t\t),\n\t\t\t\t\t]\n\t\t}),\n\t)\n\nexport const plugin = <\n\tS extends Schema.Top & {\n\t\treadonly Encoded: Schema.Json\n\t\treadonly DecodingServices: never\n\t\treadonly EncodingServices: never\n\t},\n\tE extends Schema.Top & {\n\t\treadonly DecodingServices: never\n\t\treadonly EncodingServices: never\n\t},\n\tconst D extends ReadonlyArray<Plugin.Dependency> = readonly [],\n>(\n\tcontract: Contract.Contract<S, E>,\n\toptions: Options<D> & { readonly config?: S[\"Encoded\"] },\n): Plugin.Plugin<\n\tvoid,\n\tvoid,\n\t| E[\"Type\"]\n\t| Contract.UndeclaredFailure\n\t| RemoteError\n\t| RemoteWithdrawn\n\t| MissingInstance\n> =>\n\tPlugin.make({\n\t\tname: contract.name,\n\t\tinject: [\n\t\t\tPlugin.optional(ModuleResolver.ModuleResolver),\n\t\t\tPath.Path,\n\t\t\tSecureRandom.SecureRandom,\n\t\t\tChildProcessSpawner.ChildProcessSpawner,\n\t\t],\n\t\tretry: options.retry,\n\t\tapply: Effect.fnUntraced(\n\t\t\tfunction* () {\n\t\t\t\tconst input = yield* Schema.decodeUnknownEffect(Configuration.Host)({\n\t\t\t\t\tcontract: options.contractModule,\n\t\t\t\t\tconnect: options.connect,\n\t\t\t\t\tconfig: options.config === undefined ? {} : options.config,\n\t\t\t\t})\n\t\t\t\tyield* Schema.decodeEffect(contract.config)(input.config)\n\t\t\t\tconst child = yield* launch(\n\t\t\t\t\tcontract,\n\t\t\t\t\tinput,\n\t\t\t\t\t{\n\t\t\t\t\t\tcontractModule: options.contractModule,\n\t\t\t\t\t\tshutdownTimeout: options.shutdownTimeout,\n\t\t\t\t\t},\n\t\t\t\t\tCredential.invocation(options.connect),\n\t\t\t\t)\n\t\t\t\tyield* follow(child, (cause) =>\n\t\t\t\t\tEffect.failCause(publicCause(contract.error, cause)),\n\t\t\t\t)\n\t\t\t},\n\t\t\tEffect.mapError((error) => publicError(contract.error, error)),\n\t\t),\n\t})\nexport { host as default } from \"./internal/entry\"\n"],"mappings":";;;;;;;;;;;;;;;;AAoCA,MAAM,eACL,UACA,UAQA,MAAM,YACL,MAAM,QAAQ,MAAM,UAAU,WAAW;CACxC,IAAI,OAAO,SAAS,QAAQ,OAAO,CAAC,MAAM;CAC1C,OAAO,OAAO,GAAG,gBAAgB,CAAC,CAAC,OAAO,KAAK,IAC5C,MAAM,IACN,YAAY,UAAU,OAAO,MAAM,KAAK,CAAC,CAAC,UACzC,UAAU,MAAM,SAAS,MAAM,kBAAkB,MAAM,CAAC,CAC1D,IACC,CACA,MAAM,eAAe,YAAY,UAAU,OAAO,KAAK,CAAC,CAAC,CAAC,SACzD,MAAM,kBAAkB,MAAM,CAC/B,CACD;AACH,CAAC,CACF;AAED,MAAa,UAYZ,UACA,YAUA,OAAO,KAAK;CACX,MAAM,SAAS;CACf,QAAQ;EACP,OAAO,SAAS,eAAe,cAAc;EAC7C,KAAK;EACL,aAAa;EACb,oBAAoB;CACrB;CACA,OAAO,QAAQ;CACf,OAAO,OAAO,WACb,aAAa;EACZ,MAAM,QAAQ,OAAO,OAAO,oBAAoBA,IAAkB,CAAC,CAAC;GACnE,UAAU,QAAQ;GAClB,SAAS,QAAQ;GACjB,QAAQ,QAAQ,WAAW,KAAA,IAAY,CAAC,IAAI,QAAQ;EACrD,CAAC;EACD,OAAO,OAAO,aAAa,SAAS,MAAM,CAAC,CAAC,MAAM,MAAM;EACxD,MAAM,QAAQ,OAAO,OACpB,UACA,OACA;GACC,gBAAgB,QAAQ;GACxB,iBAAiB,QAAQ;EAC1B,GACAC,WAAsB,QAAQ,OAAO,CACtC;EACA,OAAO,OAAO,QAAQ,UACrB,OAAO,UAAU,YAAY,SAAS,OAAO,KAAK,CAAC,CACpD;CACD,GACA,OAAO,UAAU,UAAU,YAAY,SAAS,OAAO,KAAK,CAAC,CAC9D;AACD,CAAC"}
|
|
@@ -137,10 +137,10 @@ const write = Effect.fn("Certificates.write")(function* (base, pair, force = fal
|
|
|
137
137
|
yield* fs.writeFileString(base + ".key", Redacted.value(pair.privateKey), {
|
|
138
138
|
flag: force ? "w" : "wx",
|
|
139
139
|
mode: 384
|
|
140
|
-
})
|
|
141
|
-
yield* fs.chmod(base + ".key", 384)
|
|
142
|
-
yield* fs.writeFileString(base + ".crt", pair.certificate, { flag: force ? "w" : "wx" })
|
|
143
|
-
});
|
|
140
|
+
});
|
|
141
|
+
yield* fs.chmod(base + ".key", 384);
|
|
142
|
+
yield* fs.writeFileString(base + ".crt", pair.certificate, { flag: force ? "w" : "wx" });
|
|
143
|
+
}, Effect.uninterruptible);
|
|
144
144
|
/** URI-encode names so each identity has a distinct filename, including names with slashes. */
|
|
145
145
|
const clientName = (identity) => `client-${encodeURIComponent(identity)}`;
|
|
146
146
|
const generate = Effect.fn("Certificates.generate")(function* (options) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Certificates.js","names":[],"sources":["../../src/internal/Certificates.ts"],"sourcesContent":["import {\n\tArray,\n\tDateTime,\n\tEffect,\n\tFileSystem,\n\tPath,\n\tRedacted,\n\tResult,\n\tSchema,\n\tString,\n} from \"effect\"\nimport { SecureRandom, WebCrypto } from \"effect/crypto\"\nimport { Base64 } from \"effect/encoding\"\nimport { NetAddress } from \"effect/net\"\nimport * as asn1js from \"asn1js\"\nimport * as pki from \"pkijs\"\n\nexport class CertificateError extends Schema.TaggedError<\n\tCertificateError,\n\t{ readonly brand: unique symbol }\n>()(\"CertificateError\", {\n\tdetail: Schema.String,\n\tcause: Schema.optional(Schema.Defect()),\n}) {\n\toverride get message() {\n\t\treturn this.detail\n\t}\n}\n\n/** A requested output already exists and replacing it was not asked for. */\nexport class CertificateExists extends Schema.TaggedError<\n\tCertificateExists,\n\t{ readonly brand: unique symbol }\n>()(\"CertificateExists\", { file: Schema.String }) {\n\toverride get message() {\n\t\treturn `${this.file} already exists; use --force to replace the requested certificates`\n\t}\n}\n\n/** Only PEM leaves this boundary; PKI.js objects stay local to each operation. */\nexport interface Pem {\n\treadonly certificate: string\n\treadonly privateKey: Redacted.Redacted<string>\n}\nexport interface IssueOptions {\n\treadonly name: string\n\treadonly days: number\n\treadonly usage: \"ca\" | \"server\" | \"client\"\n\treadonly hosts?: ReadonlyArray<string>\n\treadonly identities?: ReadonlyArray<string>\n\treadonly issuer?: Pem\n}\nconst pem = (label: string, bytes: ArrayBuffer) =>\n\t`-----BEGIN ${label}-----\\n${String.replace(/.{64}(?=.)/g, \"$&\\n\")(Base64.encode(new Uint8Array(bytes)))}\\n-----END ${label}-----\\n`\n// WebCrypto and PKI.js take ArrayBuffer-backed bytes, so the decoded view is copied into one.\nconst der = (value: string) =>\n\tEffect.fromResult(\n\t\tBase64.decode(String.replace(/-----[^-]+-----|\\s/g, \"\")(value)),\n\t).pipe(Effect.map((bytes) => new Uint8Array(bytes)))\nconst subject = (name: string) =>\n\tnew pki.RelativeDistinguishedNames({\n\t\ttypesAndValues: [\n\t\t\tnew pki.AttributeTypeAndValue({\n\t\t\t\ttype: \"2.5.4.3\",\n\t\t\t\tvalue: new asn1js.Utf8String({ value: name }),\n\t\t\t}),\n\t\t],\n\t})\nconst hostName = (host: string) =>\n\tResult.match(NetAddress.ipFromString(host), {\n\t\tonFailure: () => new pki.GeneralName({ type: 2, value: host }),\n\t\tonSuccess: (ip) =>\n\t\t\tnew pki.GeneralName({\n\t\t\t\ttype: 7,\n\t\t\t\tvalue: new asn1js.OctetString({\n\t\t\t\t\tvalueHex: new Uint8Array(\n\t\t\t\t\t\tip._tag === \"Ipv4Address\"\n\t\t\t\t\t\t\t? NetAddress.ipv4ToOctets(ip)\n\t\t\t\t\t\t\t: NetAddress.ipv6ToOctets(ip),\n\t\t\t\t\t),\n\t\t\t\t}),\n\t\t\t}),\n\t})\n\nexport const issue = Effect.fn(\"Certificates.issue\")(function* (\n\toptions: IssueOptions,\n) {\n\tconst random = yield* SecureRandom.SecureRandom\n\tconst serial = yield* random.randomBytes(19)\n\tconst now = yield* DateTime.now\n\tconst webcrypto = yield* WebCrypto.WebCrypto\n\tconst engine = new pki.CryptoEngine({\n\t\tname: \"Node WebCrypto\",\n\t\tcrypto: webcrypto,\n\t})\n\tconst failure = (cause: unknown) =>\n\t\tCertificateError.make({\n\t\t\tdetail: `Could not issue the certificate for ${options.name}`,\n\t\t\tcause,\n\t\t})\n\tconst keys = yield* Effect.tryPromise({\n\t\ttry: () =>\n\t\t\twebcrypto.subtle.generateKey(\n\t\t\t\t{ name: \"ECDSA\", namedCurve: \"P-256\" },\n\t\t\t\ttrue,\n\t\t\t\t[\"sign\", \"verify\"],\n\t\t\t),\n\t\tcatch: failure,\n\t})\n\t// Reused CA keys have the same P-256 / PKCS#8 format as the ones this command creates.\n\tconst authority =\n\t\toptions.issuer === undefined\n\t\t\t? undefined\n\t\t\t: {\n\t\t\t\t\tcertificate: yield* Effect.mapError(\n\t\t\t\t\t\tder(options.issuer.certificate),\n\t\t\t\t\t\tfailure,\n\t\t\t\t\t),\n\t\t\t\t\tprivateKey: yield* Effect.mapError(\n\t\t\t\t\t\tder(Redacted.value(options.issuer.privateKey)),\n\t\t\t\t\t\tfailure,\n\t\t\t\t\t),\n\t\t\t\t}\n\tconst signingKey =\n\t\tauthority === undefined\n\t\t\t? keys.privateKey\n\t\t\t: yield* Effect.tryPromise({\n\t\t\t\t\ttry: () =>\n\t\t\t\t\t\twebcrypto.subtle.importKey(\n\t\t\t\t\t\t\t\"pkcs8\",\n\t\t\t\t\t\t\tauthority.privateKey,\n\t\t\t\t\t\t\t{ name: \"ECDSA\", namedCurve: \"P-256\" },\n\t\t\t\t\t\t\tfalse,\n\t\t\t\t\t\t\t[\"sign\"],\n\t\t\t\t\t\t),\n\t\t\t\t\tcatch: failure,\n\t\t\t\t})\n\tconst certificate = yield* Effect.try({\n\t\ttry: () => {\n\t\t\tconst issuer =\n\t\t\t\tauthority === undefined\n\t\t\t\t\t? undefined\n\t\t\t\t\t: pki.Certificate.fromBER(authority.certificate)\n\t\t\tconst names = [\n\t\t\t\t...Array.map(options.hosts ?? [], hostName),\n\t\t\t\t...Array.map(\n\t\t\t\t\toptions.identities ?? [],\n\t\t\t\t\t(identity) =>\n\t\t\t\t\t\tnew pki.GeneralName({ type: 6, value: `graft://${identity}` }),\n\t\t\t\t),\n\t\t\t]\n\t\t\treturn new pki.Certificate({\n\t\t\t\tversion: 2,\n\t\t\t\t// A leading nonzero byte keeps the serial positive without losing random bits.\n\t\t\t\tserialNumber: new asn1js.Integer({\n\t\t\t\t\tvalueHex: new Uint8Array([1, ...serial]),\n\t\t\t\t}),\n\t\t\t\tsubject: subject(options.name),\n\t\t\t\tissuer: issuer?.subject ?? subject(options.name),\n\t\t\t\tnotBefore: new pki.Time({ value: DateTime.toDateUtc(now) }),\n\t\t\t\tnotAfter: new pki.Time({\n\t\t\t\t\tvalue: DateTime.toDateUtc(DateTime.add(now, { days: options.days })),\n\t\t\t\t}),\n\t\t\t\textensions: [\n\t\t\t\t\tnew pki.Extension({\n\t\t\t\t\t\textnID: \"2.5.29.19\",\n\t\t\t\t\t\tcritical: true,\n\t\t\t\t\t\textnValue: new pki.BasicConstraints({ cA: options.usage === \"ca\" })\n\t\t\t\t\t\t\t.toSchema()\n\t\t\t\t\t\t\t.toBER(),\n\t\t\t\t\t}),\n\t\t\t\t\tnew pki.Extension({\n\t\t\t\t\t\textnID: \"2.5.29.15\",\n\t\t\t\t\t\tcritical: true,\n\t\t\t\t\t\textnValue: new asn1js.BitString({\n\t\t\t\t\t\t\tvalueHex: new Uint8Array([options.usage === \"ca\" ? 0x06 : 0x80]),\n\t\t\t\t\t\t}).toBER(),\n\t\t\t\t\t}),\n\t\t\t\t\t...(options.usage === \"ca\"\n\t\t\t\t\t\t? []\n\t\t\t\t\t\t: [\n\t\t\t\t\t\t\t\tnew pki.Extension({\n\t\t\t\t\t\t\t\t\textnID: \"2.5.29.37\",\n\t\t\t\t\t\t\t\t\textnValue: new pki.ExtKeyUsage({\n\t\t\t\t\t\t\t\t\t\tkeyPurposes: [\n\t\t\t\t\t\t\t\t\t\t\toptions.usage === \"server\"\n\t\t\t\t\t\t\t\t\t\t\t\t? \"1.3.6.1.5.5.7.3.1\"\n\t\t\t\t\t\t\t\t\t\t\t\t: \"1.3.6.1.5.5.7.3.2\",\n\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t\t\t.toSchema()\n\t\t\t\t\t\t\t\t\t\t.toBER(),\n\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t]),\n\t\t\t\t\t...(names.length === 0\n\t\t\t\t\t\t? []\n\t\t\t\t\t\t: [\n\t\t\t\t\t\t\t\tnew pki.Extension({\n\t\t\t\t\t\t\t\t\textnID: \"2.5.29.17\",\n\t\t\t\t\t\t\t\t\textnValue: new pki.AltName({ altNames: names })\n\t\t\t\t\t\t\t\t\t\t.toSchema()\n\t\t\t\t\t\t\t\t\t\t.toBER(),\n\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t]),\n\t\t\t\t],\n\t\t\t})\n\t\t},\n\t\tcatch: failure,\n\t})\n\tyield* Effect.tryPromise({\n\t\ttry: () =>\n\t\t\tcertificate.subjectPublicKeyInfo.importKey(keys.publicKey, engine),\n\t\tcatch: failure,\n\t})\n\tyield* Effect.tryPromise({\n\t\ttry: () => certificate.sign(signingKey, \"SHA-256\", engine),\n\t\tcatch: failure,\n\t})\n\tconst privateKey = yield* Effect.tryPromise({\n\t\ttry: () => webcrypto.subtle.exportKey(\"pkcs8\", keys.privateKey),\n\t\tcatch: failure,\n\t})\n\treturn yield* Effect.try({\n\t\ttry: () => ({\n\t\t\tcertificate: pem(\"CERTIFICATE\", certificate.toSchema().toBER()),\n\t\t\tprivateKey: Redacted.make(pem(\"PRIVATE KEY\", privateKey)),\n\t\t}),\n\t\tcatch: failure,\n\t})\n})\n\nexport const read = Effect.fn(\"Certificates.read\")(function* (base: string) {\n\tconst fs = yield* FileSystem.FileSystem\n\tconst certificate = yield* fs.readFileString(base + \".crt\")\n\tconst privateKey = yield* fs.readFileString(base + \".key\")\n\treturn { certificate, privateKey: Redacted.make(privateKey) }\n})\nexport const write = Effect.fn(\"Certificates.write\")(function* (\n\tbase: string,\n\tpair: Pem,\n\tforce: boolean = false,\n) {\n\tconst fs = yield* FileSystem.FileSystem\n\tyield* fs\n\t\t.writeFileString(base + \".key\", Redacted.value(pair.privateKey), {\n\t\t\tflag: force ? \"w\" : \"wx\",\n\t\t\tmode: 0o600,\n\t\t})\n\t\t.pipe(Effect.uninterruptible)\n\t// Opening an existing file does not change its permissions when renewing it.\n\tyield* fs.chmod(base + \".key\", 0o600).pipe(Effect.uninterruptible)\n\tyield* fs\n\t\t.writeFileString(base + \".crt\", pair.certificate, {\n\t\t\tflag: force ? \"w\" : \"wx\",\n\t\t})\n\t\t.pipe(Effect.uninterruptible)\n})\n\nexport interface Options {\n\treadonly out: string\n\treadonly server: ReadonlyArray<string>\n\treadonly identity: ReadonlyArray<string>\n\treadonly days: number\n\treadonly force: boolean\n}\n/** URI-encode names so each identity has a distinct filename, including names with slashes. */\nexport const clientName = (identity: string) =>\n\t`client-${encodeURIComponent(identity)}`\nexport const generate = Effect.fn(\"Certificates.generate\")(function* (\n\toptions: Options,\n) {\n\tconst fs = yield* FileSystem.FileSystem\n\tconst path = yield* Path.Path\n\tconst outputs = [\n\t\t...(options.server.length === 0 ? [] : [\"server\"]),\n\t\t...Array.map(Array.dedupe(options.identity), clientName),\n\t]\n\tif (!options.force) {\n\t\tconst files = Array.flatMap(outputs, (name) =>\n\t\t\tArray.map([\".crt\", \".key\"], (extension) =>\n\t\t\t\tpath.join(options.out, name + extension),\n\t\t\t),\n\t\t)\n\t\tconst taken = yield* Effect.filter(files, fs.exists)\n\t\tif (Array.isReadonlyArrayNonEmpty(taken))\n\t\t\treturn yield* CertificateExists.make({ file: taken[0] })\n\t}\n\tyield* fs\n\t\t.makeDirectory(options.out, { recursive: true })\n\t\t.pipe(Effect.uninterruptible)\n\tconst ca = path.join(options.out, \"ca\")\n\tconst existing =\n\t\t(yield* fs.exists(ca + \".crt\")) || (yield* fs.exists(ca + \".key\"))\n\t// An incomplete CA pair fails on read. Even --force never replaces the signing authority.\n\tconst issuer = existing\n\t\t? yield* read(ca)\n\t\t: yield* issue({ name: \"Graft CA\", usage: \"ca\", days: options.days }).pipe(\n\t\t\t\tEffect.tap((pair) => write(ca, pair)),\n\t\t\t)\n\tif (options.server.length > 0) {\n\t\tconst pair = yield* issue({\n\t\t\tname: \"Graft runner\",\n\t\t\tusage: \"server\",\n\t\t\thosts: options.server,\n\t\t\tdays: options.days,\n\t\t\tissuer,\n\t\t})\n\t\tyield* write(path.join(options.out, \"server\"), pair, options.force)\n\t}\n\tyield* Effect.forEach(\n\t\tArray.dedupe(options.identity),\n\t\t(identity) =>\n\t\t\tissue({\n\t\t\t\tname: identity,\n\t\t\t\tusage: \"client\",\n\t\t\t\tidentities: [identity],\n\t\t\t\tdays: options.days,\n\t\t\t\tissuer,\n\t\t\t}).pipe(\n\t\t\t\tEffect.flatMap((pair) =>\n\t\t\t\t\twrite(\n\t\t\t\t\t\tpath.join(options.out, clientName(identity)),\n\t\t\t\t\t\tpair,\n\t\t\t\t\t\toptions.force,\n\t\t\t\t\t),\n\t\t\t\t),\n\t\t\t),\n\t\t{ discard: true },\n\t)\n})\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Certificates.js","names":[],"sources":["../../src/internal/Certificates.ts"],"sourcesContent":["import {\n\tArray,\n\tDateTime,\n\tEffect,\n\tFileSystem,\n\tPath,\n\tRedacted,\n\tResult,\n\tSchema,\n\tString,\n} from \"effect\"\nimport { SecureRandom, WebCrypto } from \"effect/crypto\"\nimport { Base64 } from \"effect/encoding\"\nimport { NetAddress } from \"effect/net\"\nimport * as asn1js from \"asn1js\"\nimport * as pki from \"pkijs\"\n\nexport class CertificateError extends Schema.TaggedError<\n\tCertificateError,\n\t{ readonly brand: unique symbol }\n>()(\"CertificateError\", {\n\tdetail: Schema.String,\n\tcause: Schema.optional(Schema.Defect()),\n}) {\n\toverride get message() {\n\t\treturn this.detail\n\t}\n}\n\n/** A requested output already exists and replacing it was not asked for. */\nexport class CertificateExists extends Schema.TaggedError<\n\tCertificateExists,\n\t{ readonly brand: unique symbol }\n>()(\"CertificateExists\", { file: Schema.String }) {\n\toverride get message() {\n\t\treturn `${this.file} already exists; use --force to replace the requested certificates`\n\t}\n}\n\n/** Only PEM leaves this boundary; PKI.js objects stay local to each operation. */\nexport interface Pem {\n\treadonly certificate: string\n\treadonly privateKey: Redacted.Redacted<string>\n}\nexport interface IssueOptions {\n\treadonly name: string\n\treadonly days: number\n\treadonly usage: \"ca\" | \"server\" | \"client\"\n\treadonly hosts?: ReadonlyArray<string>\n\treadonly identities?: ReadonlyArray<string>\n\treadonly issuer?: Pem\n}\nconst pem = (label: string, bytes: ArrayBuffer) =>\n\t`-----BEGIN ${label}-----\\n${String.replace(/.{64}(?=.)/g, \"$&\\n\")(Base64.encode(new Uint8Array(bytes)))}\\n-----END ${label}-----\\n`\n// WebCrypto and PKI.js take ArrayBuffer-backed bytes, so the decoded view is copied into one.\nconst der = (value: string) =>\n\tEffect.fromResult(\n\t\tBase64.decode(String.replace(/-----[^-]+-----|\\s/g, \"\")(value)),\n\t).pipe(Effect.map((bytes) => new Uint8Array(bytes)))\nconst subject = (name: string) =>\n\tnew pki.RelativeDistinguishedNames({\n\t\ttypesAndValues: [\n\t\t\tnew pki.AttributeTypeAndValue({\n\t\t\t\ttype: \"2.5.4.3\",\n\t\t\t\tvalue: new asn1js.Utf8String({ value: name }),\n\t\t\t}),\n\t\t],\n\t})\nconst hostName = (host: string) =>\n\tResult.match(NetAddress.ipFromString(host), {\n\t\tonFailure: () => new pki.GeneralName({ type: 2, value: host }),\n\t\tonSuccess: (ip) =>\n\t\t\tnew pki.GeneralName({\n\t\t\t\ttype: 7,\n\t\t\t\tvalue: new asn1js.OctetString({\n\t\t\t\t\tvalueHex: new Uint8Array(\n\t\t\t\t\t\tip._tag === \"Ipv4Address\"\n\t\t\t\t\t\t\t? NetAddress.ipv4ToOctets(ip)\n\t\t\t\t\t\t\t: NetAddress.ipv6ToOctets(ip),\n\t\t\t\t\t),\n\t\t\t\t}),\n\t\t\t}),\n\t})\n\nexport const issue = Effect.fn(\"Certificates.issue\")(function* (\n\toptions: IssueOptions,\n) {\n\tconst random = yield* SecureRandom.SecureRandom\n\tconst serial = yield* random.randomBytes(19)\n\tconst now = yield* DateTime.now\n\tconst webcrypto = yield* WebCrypto.WebCrypto\n\tconst engine = new pki.CryptoEngine({\n\t\tname: \"Node WebCrypto\",\n\t\tcrypto: webcrypto,\n\t})\n\tconst failure = (cause: unknown) =>\n\t\tCertificateError.make({\n\t\t\tdetail: `Could not issue the certificate for ${options.name}`,\n\t\t\tcause,\n\t\t})\n\tconst keys = yield* Effect.tryPromise({\n\t\ttry: () =>\n\t\t\twebcrypto.subtle.generateKey(\n\t\t\t\t{ name: \"ECDSA\", namedCurve: \"P-256\" },\n\t\t\t\ttrue,\n\t\t\t\t[\"sign\", \"verify\"],\n\t\t\t),\n\t\tcatch: failure,\n\t})\n\t// Reused CA keys have the same P-256 / PKCS#8 format as the ones this command creates.\n\tconst authority =\n\t\toptions.issuer === undefined\n\t\t\t? undefined\n\t\t\t: {\n\t\t\t\t\tcertificate: yield* Effect.mapError(\n\t\t\t\t\t\tder(options.issuer.certificate),\n\t\t\t\t\t\tfailure,\n\t\t\t\t\t),\n\t\t\t\t\tprivateKey: yield* Effect.mapError(\n\t\t\t\t\t\tder(Redacted.value(options.issuer.privateKey)),\n\t\t\t\t\t\tfailure,\n\t\t\t\t\t),\n\t\t\t\t}\n\tconst signingKey =\n\t\tauthority === undefined\n\t\t\t? keys.privateKey\n\t\t\t: yield* Effect.tryPromise({\n\t\t\t\t\ttry: () =>\n\t\t\t\t\t\twebcrypto.subtle.importKey(\n\t\t\t\t\t\t\t\"pkcs8\",\n\t\t\t\t\t\t\tauthority.privateKey,\n\t\t\t\t\t\t\t{ name: \"ECDSA\", namedCurve: \"P-256\" },\n\t\t\t\t\t\t\tfalse,\n\t\t\t\t\t\t\t[\"sign\"],\n\t\t\t\t\t\t),\n\t\t\t\t\tcatch: failure,\n\t\t\t\t})\n\tconst certificate = yield* Effect.try({\n\t\ttry: () => {\n\t\t\tconst issuer =\n\t\t\t\tauthority === undefined\n\t\t\t\t\t? undefined\n\t\t\t\t\t: pki.Certificate.fromBER(authority.certificate)\n\t\t\tconst names = [\n\t\t\t\t...Array.map(options.hosts ?? [], hostName),\n\t\t\t\t...Array.map(\n\t\t\t\t\toptions.identities ?? [],\n\t\t\t\t\t(identity) =>\n\t\t\t\t\t\tnew pki.GeneralName({ type: 6, value: `graft://${identity}` }),\n\t\t\t\t),\n\t\t\t]\n\t\t\treturn new pki.Certificate({\n\t\t\t\tversion: 2,\n\t\t\t\t// A leading nonzero byte keeps the serial positive without losing random bits.\n\t\t\t\tserialNumber: new asn1js.Integer({\n\t\t\t\t\tvalueHex: new Uint8Array([1, ...serial]),\n\t\t\t\t}),\n\t\t\t\tsubject: subject(options.name),\n\t\t\t\tissuer: issuer?.subject ?? subject(options.name),\n\t\t\t\tnotBefore: new pki.Time({ value: DateTime.toDateUtc(now) }),\n\t\t\t\tnotAfter: new pki.Time({\n\t\t\t\t\tvalue: DateTime.toDateUtc(DateTime.add(now, { days: options.days })),\n\t\t\t\t}),\n\t\t\t\textensions: [\n\t\t\t\t\tnew pki.Extension({\n\t\t\t\t\t\textnID: \"2.5.29.19\",\n\t\t\t\t\t\tcritical: true,\n\t\t\t\t\t\textnValue: new pki.BasicConstraints({ cA: options.usage === \"ca\" })\n\t\t\t\t\t\t\t.toSchema()\n\t\t\t\t\t\t\t.toBER(),\n\t\t\t\t\t}),\n\t\t\t\t\tnew pki.Extension({\n\t\t\t\t\t\textnID: \"2.5.29.15\",\n\t\t\t\t\t\tcritical: true,\n\t\t\t\t\t\textnValue: new asn1js.BitString({\n\t\t\t\t\t\t\tvalueHex: new Uint8Array([options.usage === \"ca\" ? 0x06 : 0x80]),\n\t\t\t\t\t\t}).toBER(),\n\t\t\t\t\t}),\n\t\t\t\t\t...(options.usage === \"ca\"\n\t\t\t\t\t\t? []\n\t\t\t\t\t\t: [\n\t\t\t\t\t\t\t\tnew pki.Extension({\n\t\t\t\t\t\t\t\t\textnID: \"2.5.29.37\",\n\t\t\t\t\t\t\t\t\textnValue: new pki.ExtKeyUsage({\n\t\t\t\t\t\t\t\t\t\tkeyPurposes: [\n\t\t\t\t\t\t\t\t\t\t\toptions.usage === \"server\"\n\t\t\t\t\t\t\t\t\t\t\t\t? \"1.3.6.1.5.5.7.3.1\"\n\t\t\t\t\t\t\t\t\t\t\t\t: \"1.3.6.1.5.5.7.3.2\",\n\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t\t\t.toSchema()\n\t\t\t\t\t\t\t\t\t\t.toBER(),\n\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t]),\n\t\t\t\t\t...(names.length === 0\n\t\t\t\t\t\t? []\n\t\t\t\t\t\t: [\n\t\t\t\t\t\t\t\tnew pki.Extension({\n\t\t\t\t\t\t\t\t\textnID: \"2.5.29.17\",\n\t\t\t\t\t\t\t\t\textnValue: new pki.AltName({ altNames: names })\n\t\t\t\t\t\t\t\t\t\t.toSchema()\n\t\t\t\t\t\t\t\t\t\t.toBER(),\n\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t]),\n\t\t\t\t],\n\t\t\t})\n\t\t},\n\t\tcatch: failure,\n\t})\n\tyield* Effect.tryPromise({\n\t\ttry: () =>\n\t\t\tcertificate.subjectPublicKeyInfo.importKey(keys.publicKey, engine),\n\t\tcatch: failure,\n\t})\n\tyield* Effect.tryPromise({\n\t\ttry: () => certificate.sign(signingKey, \"SHA-256\", engine),\n\t\tcatch: failure,\n\t})\n\tconst privateKey = yield* Effect.tryPromise({\n\t\ttry: () => webcrypto.subtle.exportKey(\"pkcs8\", keys.privateKey),\n\t\tcatch: failure,\n\t})\n\treturn yield* Effect.try({\n\t\ttry: () => ({\n\t\t\tcertificate: pem(\"CERTIFICATE\", certificate.toSchema().toBER()),\n\t\t\tprivateKey: Redacted.make(pem(\"PRIVATE KEY\", privateKey)),\n\t\t}),\n\t\tcatch: failure,\n\t})\n})\n\nexport const read = Effect.fn(\"Certificates.read\")(function* (base: string) {\n\tconst fs = yield* FileSystem.FileSystem\n\tconst certificate = yield* fs.readFileString(base + \".crt\")\n\tconst privateKey = yield* fs.readFileString(base + \".key\")\n\treturn { certificate, privateKey: Redacted.make(privateKey) }\n})\nexport const write = Effect.fn(\"Certificates.write\")(function* (\n\tbase: string,\n\tpair: Pem,\n\tforce: boolean = false,\n) {\n\tconst fs = yield* FileSystem.FileSystem\n\tyield* fs.writeFileString(base + \".key\", Redacted.value(pair.privateKey), {\n\t\tflag: force ? \"w\" : \"wx\",\n\t\tmode: 0o600,\n\t})\n\t// Opening an existing file does not change its permissions when renewing it.\n\tyield* fs.chmod(base + \".key\", 0o600)\n\tyield* fs.writeFileString(base + \".crt\", pair.certificate, {\n\t\tflag: force ? \"w\" : \"wx\",\n\t})\n\t// One region for the pair: an interruption between the files would leave a key without its certificate.\n}, Effect.uninterruptible)\n\nexport interface Options {\n\treadonly out: string\n\treadonly server: ReadonlyArray<string>\n\treadonly identity: ReadonlyArray<string>\n\treadonly days: number\n\treadonly force: boolean\n}\n/** URI-encode names so each identity has a distinct filename, including names with slashes. */\nexport const clientName = (identity: string) =>\n\t`client-${encodeURIComponent(identity)}`\nexport const generate = Effect.fn(\"Certificates.generate\")(function* (\n\toptions: Options,\n) {\n\tconst fs = yield* FileSystem.FileSystem\n\tconst path = yield* Path.Path\n\tconst outputs = [\n\t\t...(options.server.length === 0 ? [] : [\"server\"]),\n\t\t...Array.map(Array.dedupe(options.identity), clientName),\n\t]\n\tif (!options.force) {\n\t\tconst files = Array.flatMap(outputs, (name) =>\n\t\t\tArray.map([\".crt\", \".key\"], (extension) =>\n\t\t\t\tpath.join(options.out, name + extension),\n\t\t\t),\n\t\t)\n\t\tconst taken = yield* Effect.filter(files, fs.exists)\n\t\tif (Array.isReadonlyArrayNonEmpty(taken))\n\t\t\treturn yield* CertificateExists.make({ file: taken[0] })\n\t}\n\tyield* fs\n\t\t.makeDirectory(options.out, { recursive: true })\n\t\t.pipe(Effect.uninterruptible)\n\tconst ca = path.join(options.out, \"ca\")\n\tconst existing =\n\t\t(yield* fs.exists(ca + \".crt\")) || (yield* fs.exists(ca + \".key\"))\n\t// An incomplete CA pair fails on read. Even --force never replaces the signing authority.\n\tconst issuer = existing\n\t\t? yield* read(ca)\n\t\t: yield* issue({ name: \"Graft CA\", usage: \"ca\", days: options.days }).pipe(\n\t\t\t\tEffect.tap((pair) => write(ca, pair)),\n\t\t\t)\n\tif (options.server.length > 0) {\n\t\tconst pair = yield* issue({\n\t\t\tname: \"Graft runner\",\n\t\t\tusage: \"server\",\n\t\t\thosts: options.server,\n\t\t\tdays: options.days,\n\t\t\tissuer,\n\t\t})\n\t\tyield* write(path.join(options.out, \"server\"), pair, options.force)\n\t}\n\tyield* Effect.forEach(\n\t\tArray.dedupe(options.identity),\n\t\t(identity) =>\n\t\t\tissue({\n\t\t\t\tname: identity,\n\t\t\t\tusage: \"client\",\n\t\t\t\tidentities: [identity],\n\t\t\t\tdays: options.days,\n\t\t\t\tissuer,\n\t\t\t}).pipe(\n\t\t\t\tEffect.flatMap((pair) =>\n\t\t\t\t\twrite(\n\t\t\t\t\t\tpath.join(options.out, clientName(identity)),\n\t\t\t\t\t\tpair,\n\t\t\t\t\t\toptions.force,\n\t\t\t\t\t),\n\t\t\t\t),\n\t\t\t),\n\t\t{ discard: true },\n\t)\n})\n"],"mappings":"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"}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { ReleaseInterrupted, close } from "./release.js";
|
|
2
|
+
import { cleanupCause } from "./cleanup.js";
|
|
2
3
|
import { Array, Cause, Data, Deferred, Effect, Exit, Fiber, FiberSet, Ref, Schema, Scope, TxRef } from "effect";
|
|
3
4
|
// src/internal/FailureGroup.ts
|
|
4
5
|
const State = Data.taggedEnum();
|
|
5
6
|
/** One owner for first failure, transaction wakeups, and interruption of sibling work. */
|
|
6
|
-
const make =
|
|
7
|
+
const make = Effect.fnUntraced(function* () {
|
|
7
8
|
const fibers = yield* FiberSet.make();
|
|
8
9
|
const state = yield* TxRef.make(State.Open());
|
|
9
10
|
const failures = yield* Ref.make(Cause.empty);
|
|
@@ -37,7 +38,7 @@ const make = () => Effect.gen(function* () {
|
|
|
37
38
|
const failure = Effect.tx(check.pipe(Effect.andThen(Effect.txRetry)));
|
|
38
39
|
const failCause = (cause) => FiberSet.run(fibers, observe(Effect.failCause(cause))).pipe(Effect.asVoid);
|
|
39
40
|
const close$1 = TxRef.update(state, (s) => s._tag === "Open" ? State.Closed() : s).pipe(Effect.andThen(FiberSet.clear(fibers)), Effect.andThen(Ref.get(cleanup)), Effect.flatMap((cause) => cause.reasons.length > 0 ? Effect.failCause(cause) : Effect.void), Effect.uninterruptible);
|
|
40
|
-
yield* Effect.addFinalizer(() => close$1.pipe(Effect.
|
|
41
|
+
yield* Effect.addFinalizer(() => close$1.pipe(Effect.catchCause((cause) => Effect.failCause(cleanupCause(cause)))));
|
|
41
42
|
return {
|
|
42
43
|
await: failure,
|
|
43
44
|
check,
|