Hyperlinkv0.8.0-beta.28

Hyperlink

Hyperlink.withReadinessconstsrc/Hyperlink.ts:2618
<T extends PipeableTag>(
  readiness: ReadinessOf<
    T extends HyperlinkTag<any, infer S extends Spec>
      ? ServiceOf<S, any>
      : never
  >
): (tag: T) => T
<Self, S extends Spec, HSelf>(
  tag: NodeBoundTag<Self, S, HSelf>,
  readiness: ReadinessOf<ServiceOf<S, Self>>
): NodeBoundTag<Self, S, HSelf>
<Self, S extends Spec>(
  tag: HyperlinkTag<Self, S>,
  readiness: ReadinessOf<ServiceOf<S, Self>>
): HyperlinkTag<Self, S>

Attach a Readiness derivation to a tag — the seam the node's /health and NodeStatus aggregate over. Each contract applies it from its own status (so readiness can't drift from status); a bare Hyperlink.Tag can opt in the same way. Dual (data-first or .pipe):

class EdgeCache extends Hyperlink.Tag<EdgeCache>()("edge/Cache", {
  warm: Hyperlink.effect(Schema.Boolean),
}).pipe(
  Hyperlink.withReadiness((svc) =>
    Effect.map(svc.warm, (warm) => ({ ready: warm, ...(warm ? {} : { detail: "cold" }) })),
  ),
) {}
spec fieldsReadinessHyperlink.Tag
Source src/Hyperlink.ts:261836 lines
export const withReadiness: {
  // Data-last: `T extends PipeableTag` (shallow) — do not constrain against HyperlinkTag|NodeBoundTag
  // or stock tsc TS2589s on node-bound `class extends Tag()(…).pipe(withReadiness(…))` (expands Svc).
  // Readiness `svc` is still `ServiceOf<S, any>` from the inferred tag; Self is widened so class
  // `extends` does not recurse on the declaring type — see test/resource-withreadiness-pipe.test-d.ts.
  //
  // data-last (pipe): `tag.pipe(Hyperlink.withReadiness(fn))` — service type derived from the piped tag.
  <T extends PipeableTag>(
    readiness: ReadinessOf<
      T extends HyperlinkTag<any, infer S extends Spec> ? ServiceOf<S, any> : never
    >,
  ): (tag: T) => T;
  // data-first: `Hyperlink.withReadiness(tag, fn)` — full `ServiceOf<S, Self>` (contracts use this).
  // Two **inferred** overloads (not a fixed `<any,any>` union) so a fully-defined *class* — a
  // `typeof X` constructor — is accepted, the way `client`/`layer` accept one; node-bound first so a
  // node-bound tag keeps its node in the return.
  <Self, S extends Spec, HSelf>(
    tag: NodeBoundTag<Self, S, HSelf>,
    readiness: ReadinessOf<ServiceOf<S, Self>>,
  ): NodeBoundTag<Self, S, HSelf>;
  <Self, S extends Spec>(
    tag: HyperlinkTag<Self, S>,
    readiness: ReadinessOf<ServiceOf<S, Self>>,
  ): HyperlinkTag<Self, S>;
} = Fn.dual(
  2,
  <T extends HyperlinkTag<any, any, any>>(tag: T, readiness: ReadinessOf<unknown>): T => {
    // Stack onto any readiness already on the tag (e.g. a contract factory's own check): the new
    // derivation receives the prior one (applied to the same service) as `base`, so it can extend
    // it (`yield* base`) or replace it (ignore `base`). `base` flows down the chain from the root.
    const prior = tag[readinessSym];
    const composed = (service: unknown, base: Effect.Effect<Readiness, never, never>) =>
      readiness(service, prior === undefined ? base : (prior as any)(service, base)) as any;
    return Object.assign(tag, { [readinessSym]: composed }) as T;
  },
);
Referenced by 1 symbols