Hyperlinkv0.8.0-beta.28

Hyperlink

Hyperlink.clientInstancesconstsrc/Hyperlink.ts:5704
<S extends Spec, const Tags extends ReadonlyArray<WireInstanceTag<S>>>(
  factory: {
    readonly groupId: string
    readonly [specSym]: FlatSpec
    readonly [specTypeSym]?: S
    readonly [groupSym]: RpcGroupOf<S>
  },
  ...tags: Tags
): Layer.Layer<InstanceIdentifiers<Tags, S>, never, RpcClient.Protocol>

The client layer for many instances of one factory, sharing a single RPC client — the client mirror of Hyperlink.serveInstances. Builds one RpcClient for the family's group and provides every instance's handle from it, each pinned to its own instance-key header. So 100 instances of one control shape cost one client (and one shared connection), not one client each — the contract/group/schemas are already shared.

Wire-only: instances declaring Hyperlink.local members aren't accepted (their service type is wider than the wire) — use Hyperlink.client per instance for those.

clientsHyperlink.serveInstancesHyperlink.localHyperlink.client
Source src/Hyperlink.ts:570441 lines
const clientInstances = <
  S extends Spec,
  const Tags extends ReadonlyArray<WireInstanceTag<S>>,
>(
  factory: {
    readonly groupId: string;
    readonly [specSym]: FlatSpec;
    readonly [specTypeSym]?: S;
    readonly [groupSym]: RpcGroupOf<S>;
  },
  ...tags: Tags
): Layer.Layer<InstanceIdentifiers<Tags, S>, never, RpcClient.Protocol> =>
  Layer.effectContext(
    Effect.gen(function* () {
      const protocol = yield* Effect.serviceOption(RpcClient.Protocol);
      if (Option.isNone(protocol)) {
        return yield* new MissingClientProtocol({
          resource: factory.groupId,
        });
      }
      const rpc = yield* Effect.provideService(
        RpcClient.make(factory[groupSym]),
        RpcClient.Protocol,
        protocol.value,
      );
      let context = Context.empty();
      for (const tag of tags) {
        const service = nestService(
          forwardClient(rpc, factory[specSym], factory.groupId, tag.key),
        ) as WireServiceOf<S>;
        context = Context.add(context, tag, service);
      }
      // The only cast here: TS can't track the identifier union accumulated by the
      // per-instance `Context.add` loop. Runtime-safe — built key-for-key from `tags`.
      return context as Context.Context<InstanceIdentifiers<Tags, S>>;
    }),
  ) as unknown as Layer.Layer<
    InstanceIdentifiers<Tags, S>,
    never,
    RpcClient.Protocol
  >;