ImplOf<S>The implementation a localLayer / serve expects: wire members are their
Effect/Stream/function, and each LocalMethod is its raw value T (the toolkit wraps
it to require the Local). When an impl needs a capability (e.g. peers) to
build, provide it via the Effect form of Hyperlink.layer / Hyperlink.serve
— resolve it once, and the members close over it.
A value field's impl is the Stream that feeds it (typically a SubscriptionRef's .changes),
and a constant's is the Effect<A> resolved once — both differ from how they surface in
ServiceOf (a plain A), so annotate an impl with ImplOf, not ServiceOf.
export type type ImplOf<S extends Spec> = {
readonly [K in keyof S]: S[K] extends FromLocalMethod<
infer M
>
? M
: S[K] extends LocalMethod<infer T>
? T
: S[K] extends {
readonly _tag: "ref"
}
? Subscribable<SuccessOf<AsMethod<S[K]>>>
: S[K] extends {
readonly kind: MethodKind
}
? ServiceMethod<AsMethod<S[K]>>
: S[K] extends Spec
? ImplOf<S[K]>
: never
}
The implementation a
localLayer
/
serve
expects: wire members are their
Effect/Stream/function, and each
LocalMethod
is its raw value T (the toolkit wraps
it to require the
Local
). When an impl needs a capability (e.g.
peers
) to
build, provide it via the Effect form of
Hyperlink.layer
/
Hyperlink.serve
— resolve it once, and the members close over it.
A value field's impl is the Stream that feeds it (typically a SubscriptionRef's .changes),
and a constant's is the Effect<A> resolved once — both differ from how they surface in
ServiceOf
(a plain A), so annotate an impl with ImplOf, not ServiceOf.
ImplOf<function (type parameter) S in type ImplOf<S extends Spec>S extends Spec> = {
readonly [function (type parameter) KK in keyof function (type parameter) S in type ImplOf<S extends Spec>S]: function (type parameter) S in type ImplOf<S extends Spec>S[function (type parameter) KK] extends interface FromLocalMethod<M>A
fromService
local member as it sits in the resolved spec: a
LocalMethod
that
additionally carries the service interface's member type M, so
ServiceOf
surfaces it via
InjectLocal
(its own Effect/function + Local) instead of the value-obtain
LocalEffect
a plain local<T>() gets. Type-only; at runtime it's an ordinary bare
local
.
FromLocalMethod<infer function (type parameter) MM>
? function (type parameter) MM // fromService local: the impl provides the interface member itself
: function (type parameter) S in type ImplOf<S extends Spec>S[function (type parameter) KK] extends interface LocalMethod<T>A local-only member of a resource contract — built by
Hyperlink.local
. It is
not part of the wire contract (no schema, no rpc): use it for things that can't cross
RPC simply (a returned function, a raw Fiber/Scope/Ref, a callback). Its declared
type T is given directly. In the service it surfaces as
Effect<T, never, Local<Self>> — you yield* it to obtain the value, which requires the
local layer (
Local
).
LocalMethod<infer function (type parameter) TT>
? function (type parameter) TT
: function (type parameter) S in type ImplOf<S extends Spec>S[function (type parameter) KK] extends { readonly _tag: "ref"_tag: "ref" }
? interface Subscribable<A>A read-only reactive value: its current value (
Subscribable.get
, an Effect) plus a stream
of every change (
Subscribable.changes
). This is what a
ref
field surfaces — uniform local
and remote — and it's exactly the read side of a SubscriptionRef (Effect ships no Subscribable type in
this beta, so we name it here).
Subscribable<type SuccessOf<M extends AnyMethod> =
M["success"]["Type"]
SuccessOf<type AsMethod<T> = T extends {
readonly kind: MethodKind
readonly payload: infer P extends
| Schema.Struct.Fields
| Schema.Top
| undefined
readonly success: infer Su extends Schema.Top
readonly error: infer E extends Schema.Top
readonly stream: infer Str extends boolean
readonly annotations: infer Ann extends MethodAnnotations
}
? Method<P, Su, E, Str, Ann, Derive>
: never
Reconstruct a proper
Method
from a leaf's parts via infer — prop-presence + infer …
extends … is F-independent (reduces under a generic item schema) and keeps the payload precise,
unlike Extract/&. Lets the recursive spec types feed the existing ServiceMethod/ServeMethod/
RpcOf under a nested, generic Spec.
AsMethod<function (type parameter) S in type ImplOf<S extends Spec>S[function (type parameter) KK]>>> // impl owns the SubscriptionRef, provided via subscribable()
: function (type parameter) S in type ImplOf<S extends Spec>S[function (type parameter) KK] extends { readonly kind: MethodKindkind: type MethodKind = "query" | "mutate"How a method behaves, for tools (CLI/TUI/dashboard) — explicit, never inferred;
encoded by the constructor used (
effect
vs
effectFn
):
query — an idempotent read (CLI prints it, dashboard reads it as an Atom);
mutate — a mutation (CLI confirms, dashboard calls it as runtime.fn).
MethodKind }
? type ServiceMethod<M extends AnyMethod> =
M["stream"] extends true
? [M["payload"]] extends [undefined]
? Stream.Stream<
SuccessOf<M>,
ErrorOf<M>,
never
>
: (
payload: PayloadOf<M>
) => Stream.Stream<
SuccessOf<M>,
ErrorOf<M>
>
: [M["payload"]] extends [undefined]
? Effect.Effect<
SuccessOf<M>,
ErrorOf<M>,
never
>
: MutateMethodFn<M>
ServiceMethod<type AsMethod<T> = T extends {
readonly kind: MethodKind
readonly payload: infer P extends
| Schema.Struct.Fields
| Schema.Top
| undefined
readonly success: infer Su extends Schema.Top
readonly error: infer E extends Schema.Top
readonly stream: infer Str extends boolean
readonly annotations: infer Ann extends MethodAnnotations
}
? Method<P, Su, E, Str, Ann, Derive>
: never
Reconstruct a proper
Method
from a leaf's parts via infer — prop-presence + infer …
extends … is F-independent (reduces under a generic item schema) and keeps the payload precise,
unlike Extract/&. Lets the recursive spec types feed the existing ServiceMethod/ServeMethod/
RpcOf under a nested, generic Spec.
AsMethod<function (type parameter) S in type ImplOf<S extends Spec>S[function (type parameter) KK]>>
: function (type parameter) S in type ImplOf<S extends Spec>S[function (type parameter) KK] extends Spec
? type ImplOf<S extends Spec> = {
readonly [K in keyof S]: S[K] extends FromLocalMethod<
infer M
>
? M
: S[K] extends LocalMethod<infer T>
? T
: S[K] extends {
readonly _tag: "ref"
}
? Subscribable<SuccessOf<AsMethod<S[K]>>>
: S[K] extends {
readonly kind: MethodKind
}
? ServiceMethod<AsMethod<S[K]>>
: S[K] extends Spec
? ImplOf<S[K]>
: never
}
The implementation a
localLayer
/
serve
expects: wire members are their
Effect/Stream/function, and each
LocalMethod
is its raw value T (the toolkit wraps
it to require the
Local
). When an impl needs a capability (e.g.
peers
) to
build, provide it via the Effect form of
Hyperlink.layer
/
Hyperlink.serve
— resolve it once, and the members close over it.
A value field's impl is the Stream that feeds it (typically a SubscriptionRef's .changes),
and a constant's is the Effect<A> resolved once — both differ from how they surface in
ServiceOf
(a plain A), so annotate an impl with ImplOf, not ServiceOf.
ImplOf<function (type parameter) S in type ImplOf<S extends Spec>S[function (type parameter) KK]> // nested group → nested impl
: never;
};