<Self, S extends Spec>(
tag: HyperlinkTag<Self, S>,
options?: LookupClientOptions
): Layer.Layer<
Self,
LookupClientError,
LookupIdentity | LookupDirectory | LookupAdvice
>Lookup-resolved nodeless client (D7/D4) — you do not pass a Node; Lookup
chooses the dial target. Contrast client(Tag, node), where you name the Node.
Resolution order: Lookup.Identityresolve(tag.key), else
Lookup.DirectorynodesServing(tag.key).
Fail-closed by default: missing or more than one directory row →
LookupClientError. When N>1, a live Lookup.Advice prefer that
matches a directory row wins before D4 { pick }. Opt into soft pick with
{ pick: "first" } or a sync (rows) => DirectoryEntry. Identity resolve
ignores advice / pick (unique by key).
Bake name sketch was unsafeLookupClient (“trust Lookup or die”); bare
lookupClient(Tag) keeps that fail-closed contract when advice is absent/stale.
// Sole endpoint (identity winner or one directory row):
Hyperlink.lookupClient(Mail).pipe(Layer.provide(Lookup.layer))
// Coordinator published advice — bare client honors prefer:
yield* Lookup.advise({ serviceKey: Mail.key, prefer: "fleet/Mail#w2" })
Hyperlink.lookupClient(Mail)
// N>1 replicas — opt-in pick when no advice (still fail on 0):
Hyperlink.lookupClient(Mail, { pick: "first" })
// You already know an addressed Node — client auto-connects:
Hyperlink.client(Mail, East)export const const lookupClient: <
Self,
S extends Spec
>(
tag: HyperlinkTag<Self, S>,
options?: LookupClientOptions
) => Layer.Layer<
Self,
LookupClientError,
LookupIdentity | LookupDirectory | LookupAdvice
>
Lookup-resolved nodeless client (D7/D4) — you do not pass a
Node
; Lookup
chooses the dial target. Contrast
client
(Tag, node), where you name the Node.
Resolution order:
Lookup.Identity
resolve(tag.key), else
Lookup.Directory
nodesServing(tag.key).
Fail-closed by default: missing or more than one directory row →
LookupClientError
. When N>1, a live
Lookup.Advice
prefer that
matches a directory row wins before D4 { pick }. Opt into soft pick with
{ pick: "first" } or a sync (rows) => DirectoryEntry. Identity resolve
ignores advice / pick (unique by key).
Bake name sketch was unsafeLookupClient (“trust Lookup or die”); bare
lookupClient(Tag) keeps that fail-closed contract when advice is absent/stale.
// Sole endpoint (identity winner or one directory row):
Hyperlink.lookupClient(Mail).pipe(Layer.provide(Lookup.layer))
// Coordinator published advice — bare client honors prefer:
yield* Lookup.advise({ serviceKey: Mail.key, prefer: "fleet/Mail#w2" })
Hyperlink.lookupClient(Mail)
// N>1 replicas — opt-in pick when no advice (still fail on 0):
Hyperlink.lookupClient(Mail, { pick: "first" })
// You already know an addressed Node — client auto-connects:
Hyperlink.client(Mail, East)
lookupClient = <function (type parameter) Self in <Self, S extends Spec>(tag: HyperlinkTag<Self, S>, options?: LookupClientOptions): Layer.Layer<Self, LookupClientError, LookupIdentity | LookupDirectory | LookupAdvice>Self, function (type parameter) S in <Self, S extends Spec>(tag: HyperlinkTag<Self, S>, options?: LookupClientOptions): Layer.Layer<Self, LookupClientError, LookupIdentity | LookupDirectory | LookupAdvice>S extends Spec>(
tag: HyperlinkTag<Self, S>(parameter) tag: {
description: string | undefined;
key: Identifier;
of: (this: void, self: Simplify<{ readonly [K in keyof S]: S[K] extends FromLocalMethod<infer M> ? InjectLocal<M, Self> : S[K] extends LocalMethod<infer T> ? LocalEffect<T, never, Self> : S[K] extends DefaultMethod<infer F> ? F : S[K] extends …;
context: (self: Simplify<{ readonly [K in keyof S]: S[K] extends FromLocalMethod<infer M> ? InjectLocal<M, Self> : S[K] extends LocalMethod<infer T> ? LocalEffect<T, never, Self> : S[K] extends DefaultMethod<infer F> ? F : S[K] extends { readonly _…;
use: (f: (service: Simplify<{ readonly [K in keyof S]: S[K] extends FromLocalMethod<infer M> ? InjectLocal<M, Self> : S[K] extends LocalMethod<infer T> ? LocalEffect<T, never, Self> : S[K] extends DefaultMethod<infer F> ? F : S[K] extends { rea…;
useSync: (f: (service: Simplify<{ readonly [K in keyof S]: S[K] extends FromLocalMethod<infer M> ? InjectLocal<M, Self> : S[K] extends LocalMethod<infer T> ? LocalEffect<T, never, Self> : S[K] extends DefaultMethod<infer F> ? F : S[K] extends { rea…;
Identifier: Identifier;
Service: Shape;
stack: string | undefined;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
toString: () => string;
toJSON: () => unknown;
}
tag: interface HyperlinkTag<Self, S extends Spec, Svc = Simplify<{ readonly [K in keyof S]: S[K] extends FromLocalMethod<infer M> ? InjectLocal<M, Self> : S[K] extends LocalMethod<infer T> ? LocalEffect<...> : S[K] extends DefaultMethod<...> ? F : S[K] extends { ...; } ? SuccessOf<...> : S[K] extends { ...; } ? Subscribable<...> : S[K] extends { ...; } ? ClientMethod<...> : S[K] extends Spec ? Simplify<...> : never; }>>The type of a HyperService tag carrying spec S — what
Hyperlink.Tag
produces
(and what you extend). Lets a consumer write
<S extends Spec>(tag: HyperlinkTag<Self, S>) and read the spec through named types
(
specOf
/
groupOf
) instead of a Parameters<typeof specOf> workaround.
HyperlinkTag<function (type parameter) Self in <Self, S extends Spec>(tag: HyperlinkTag<Self, S>, options?: LookupClientOptions): Layer.Layer<Self, LookupClientError, LookupIdentity | LookupDirectory | LookupAdvice>Self, function (type parameter) S in <Self, S extends Spec>(tag: HyperlinkTag<Self, S>, options?: LookupClientOptions): Layer.Layer<Self, LookupClientError, LookupIdentity | LookupDirectory | LookupAdvice>S>,
options: LookupClientOptionsoptions?: type LookupClientOptions = {
readonly pick?: LookupClientPick
}
Options for
lookupClient
— opt-in soft pick when the directory is ambiguous
and placement advice is absent or stale.
LookupClientOptions,
): import LayerLayer.interface Layer<in ROut, out E = never, out RIn = never>A Layer describes how to build one or more services for dependency injection.
When to use
Use to model construction of application services for dependency injection,
especially when services have dependencies, can fail during construction, or
need scoped setup and release.
Details
A Layer<ROut, E, RIn> represents ROut as the services this layer
provides, E as the possible errors during layer construction, and RIn as
the services this layer requires as dependencies.
Layer<
function (type parameter) Self in <Self, S extends Spec>(tag: HyperlinkTag<Self, S>, options?: LookupClientOptions): Layer.Layer<Self, LookupClientError, LookupIdentity | LookupDirectory | LookupAdvice>Self,
class LookupClientErrorclass LookupClientError {
name: string;
message: string;
stack: string;
cause: unknown;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
toString: () => string;
toJSON: () => unknown;
_tag: Tag;
tag: string;
reason: 'missing' | 'ambiguous';
count: number;
}
lookupClient
could not resolve exactly one dial target for the Tag
(missing = none; ambiguous = more than one directory row and no
LookupClientOptions.pick
).
LookupClientError,
class LookupIdentityclass LookupIdentity {
key: Identifier;
Service: {
claim: (payload: { kind: 'Http' | 'WebSocket' | 'IpcSocket'; key: string; nodeKey: string; url?: string | undefined; path?: string | undefined }) => Effect.Effect<Endpoint, DuplicateIdentity, never>;
resolve: (payload: { key: string }) => Effect.Effect<Option.Option<Endpoint>, never, never>;
};
}
Lookup identity service — claim HyperService keys (first wins; dead winners replaceable).
LookupIdentity | class LookupDirectoryclass LookupDirectory {
key: Identifier;
Service: {
advertise: (payload: { kind: 'Http' | 'WebSocket' | 'IpcSocket'; nodeKey: string; serves: ReadonlyArray<string>; url?: string | undefined; path?: string | undefined; onConflict?: 'livenessReplace' | 'askIncumbent' | 'reject' | 'inherit' | undefined }…;
unregister: (payload: { nodeKey: string; kind?: 'Http' | 'WebSocket' | 'IpcSocket' | undefined; url?: string | undefined; path?: string | undefined }) => Effect.Effect<boolean, never, never>;
nodesServing: (payload: { serviceKey: string }) => Effect.Effect<ReadonlyArray<LookupDirectoryEntry>, never, never>;
};
}
Lookup node directory — advertise / unregister / list by served HyperService key.
LookupDirectory | class LookupAdviceclass LookupAdvice {
key: Identifier;
Service: {
advise: (payload: { serviceKey: string; prefer: string }) => Effect.Effect<string, never, never>;
clear: (payload: { serviceKey: string }) => Effect.Effect<boolean, never, never>;
preferred: (payload: { serviceKey: string }) => Effect.Effect<Option.Option<string>, never, never>;
};
}
Lookup placement board — coordinator advice for nodeless /
Hyperlink.lookupClient
dial.
v1: last-write-wins, in-memory, no advisor ACL. Algorithms stay app-owned (who calls
advise
); Lookup only stores and surfaces the preference.
LookupAdvice
> =>
import LayerLayer.const unwrap: <A, E1, R1, E, R>(
self: Effect<Layer<A, E1, R1>, E, R>
) => Layer<
A,
E | E1,
R1 | Exclude<R, Scope.Scope>
>
Unwraps a Layer from an Effect, flattening the nested structure.
When to use
Use when you have an Effect that produces a Layer and you want to
use that layer directly.
Details
The resulting Layer will have the combined error and dependency types from
both the outer Effect and the inner Layer.
Example (Unwrapping an effectful layer)
import { Context, Effect, Layer } from "effect"
class Database extends Context.Service<Database, {
readonly query: (sql: string) => Effect.Effect<string>
}>()("Database") {}
const layerEffect = Effect.succeed(
Layer.succeed(Database, { query: Effect.fn("Database.query")((sql: string) => Effect.succeed("result")) })
)
const unwrappedLayer = Layer.unwrap(layerEffect)
unwrap(
import EffectEffect.const gen: {
<Eff extends Effect<any, any, any>, AEff>(
f: () => Generator<Eff, AEff, never>
): Effect<
AEff,
[Eff] extends [never]
? never
: [Eff] extends [
Effect<infer _A, infer E, infer _R>
]
? E
: never,
[Eff] extends [never]
? never
: [Eff] extends [
Effect<infer _A, infer _E, infer R>
]
? R
: never
>
<Self, Eff extends Effect<any, any, any>, AEff>(
options: { readonly self: Self },
f: (this: Self) => Generator<Eff, AEff, never>
): Effect<
AEff,
[Eff] extends [never]
? never
: [Eff] extends [
Effect<infer _A, infer E, infer _R>
]
? E
: never,
[Eff] extends [never]
? never
: [Eff] extends [
Effect<infer _A, infer _E, infer R>
]
? R
: never
>
}
Provides a way to write effectful code using generator functions, simplifying
control flow and error handling.
When to use
Use when you want to write effectful code that looks and behaves like
synchronous code, while still handling asynchronous tasks, errors, and complex
control flow such as loops and conditions.
Generator functions work similarly to async/await but keep errors,
requirements, and interruption in the Effect type. You can yield* values
from effects and return the final result at the end.
Example (Sequencing effects with generators)
import { Data, Effect } from "effect"
class DiscountRateError extends Data.TaggedError("DiscountRateError")<{}> {}
const addServiceCharge = (amount: number) => amount + 1
const applyDiscount = (
total: number,
discountRate: number
): Effect.Effect<number, DiscountRateError> =>
discountRate === 0
? Effect.fail(new DiscountRateError())
: Effect.succeed(total - (total * discountRate) / 100)
const fetchTransactionAmount = Effect.promise(() => Promise.resolve(100))
const fetchDiscountRate = Effect.promise(() => Promise.resolve(5))
export const program = Effect.gen(function*() {
const transactionAmount = yield* fetchTransactionAmount
const discountRate = yield* fetchDiscountRate
const discountedAmount = yield* applyDiscount(
transactionAmount,
discountRate
)
const finalAmount = addServiceCharge(discountedAmount)
return `Final amount to charge: ${finalAmount}`
})
gen(function* () {
const const Lookup: typeof import("/Users/nikolasstow/Coding/Hyperlink/worktrees/epsilon/src/Lookup")const Lookup: {
resolveOnConflict: (...prefs: ReadonlyArray<OnConflict | undefined>) => OnConflictResolved;
Endpoint: typeof Endpoint;
ClaimRequest: typeof ClaimRequest;
ResolveRequest: typeof ResolveRequest;
DuplicateIdentity: typeof DuplicateIdentity;
DirectoryEntry: typeof LookupDirectoryEntry;
AdvertiseRequest: typeof AdvertiseRequest;
UnregisterRequest: typeof UnregisterRequest;
NodesServingRequest: typeof NodesServingRequest;
IncumbentAlive: typeof IncumbentAlive;
AdviseRequest: typeof AdviseRequest;
ClearAdviceRequest: typeof ClearAdviceRequest;
PreferredRequest: typeof PreferredRequest;
LookupUnaddressed: typeof LookupUnaddressed;
kind: 'hyperlink-ts/Lookup';
Identity: typeof LookupIdentity;
Directory: typeof LookupDirectory;
Advice: typeof LookupAdvice;
nodesServing: (service: string | { readonly key: string }) => Effect.Effect<ReadonlyArray<DirectoryEntry>, never, Directory>;
advise: (input: { readonly serviceKey: string; readonly prefer: string }) => Effect.Effect<string, never, Advice>;
prefer: (service: string | { readonly key: string }, nodeKey: string) => Effect.Effect<string, never, Advice>;
preferEntry: (service: string | { readonly key: string }, entry: { readonly nodeKey: string }) => Effect.Effect<string, never, Advice>;
clearAdvice: (service: string | { readonly key: string }) => Effect.Effect<boolean, never, Advice>;
preferred: (service: string | { readonly key: string }) => Effect.Effect<Option.Option<string>, never, Advice>;
defaultIpcPath: '/tmp/hyperlink-ts-lookup.sock';
layerIpc: (path: string, options?: { readonly unlink?: boolean; readonly onConflict?: OnConflictResolved }) => Layer.Layer<Identity | Directory | Advice | Hyperlink.Local<Identity> | Handler<'claim'> | Handler<'resolve'> | Hyperlink.Local<Directory>…;
layerNode: (node: AnyNode & { readonly key: string }, options?: { readonly unlink?: boolean }) => Layer.Layer<never, LookupUnaddressed>;
directoryAdvertiseLayer: (node: AnyNode & { readonly key: string }, serves: ReadonlyArray<string>, options?: { readonly onConflict?: OnConflict }) => Layer.Layer<never, IncumbentAlive>;
client: (node: AnyNode & { readonly path?: string }) => Layer.Layer<Services, LookupUnaddressed>;
clientOptions: (options?: { readonly path?: string }) => Layer.Layer<Services, LookupUnaddressed>;
layerOptions: (options?: { readonly path?: string; readonly unlink?: boolean }) => Layer.Layer<Services>;
layer: Layer.Layer<Services>;
}
Lookup = yield* import EffectEffect.const promise: <A>(
evaluate: (
signal: AbortSignal
) => PromiseLike<A>
) => Effect<A>
Creates an Effect that represents an asynchronous computation guaranteed to
succeed.
When to use
Use to convert a Promise into an Effect when the async operation is
guaranteed to succeed and will not reject.
Details
An optional AbortSignal can be provided to allow for interruption of the
wrapped Promise API.
Gotchas
The Promise must not reject. If it rejects, the rejection is treated as a
defect, not as a typed failure. Use tryPromise when rejection is expected.
Interruption aborts the provided AbortSignal, but the underlying
asynchronous operation only stops if it observes that signal.
Example (Wrapping a non-rejecting Promise)
import { Effect } from "effect"
const delay = (message: string) =>
Effect.promise<string>(
() =>
new Promise((resolve) => {
setTimeout(() => {
resolve(message)
}, 2000)
})
)
// ┌─── Effect<string, never, never>
// ▼
const program = delay("Async operation completed successfully!")
promise(() => import("./Lookup"));
const const identity: {
readonly claim: (payload: {
kind: "Http" | "WebSocket" | "IpcSocket"
key: string
nodeKey: string
url?: string | undefined
path?: string | undefined
}) => Effect.Effect<
Endpoint,
DuplicateIdentity,
never
>
readonly resolve: (payload: {
key: string
}) => Effect.Effect<
Option.Option<Endpoint>,
never,
never
>
}
identity = yield* const Lookup: typeof import("/Users/nikolasstow/Coding/Hyperlink/worktrees/epsilon/src/Lookup")const Lookup: {
resolveOnConflict: (...prefs: ReadonlyArray<OnConflict | undefined>) => OnConflictResolved;
Endpoint: typeof Endpoint;
ClaimRequest: typeof ClaimRequest;
ResolveRequest: typeof ResolveRequest;
DuplicateIdentity: typeof DuplicateIdentity;
DirectoryEntry: typeof LookupDirectoryEntry;
AdvertiseRequest: typeof AdvertiseRequest;
UnregisterRequest: typeof UnregisterRequest;
NodesServingRequest: typeof NodesServingRequest;
IncumbentAlive: typeof IncumbentAlive;
AdviseRequest: typeof AdviseRequest;
ClearAdviceRequest: typeof ClearAdviceRequest;
PreferredRequest: typeof PreferredRequest;
LookupUnaddressed: typeof LookupUnaddressed;
kind: 'hyperlink-ts/Lookup';
Identity: typeof LookupIdentity;
Directory: typeof LookupDirectory;
Advice: typeof LookupAdvice;
nodesServing: (service: string | { readonly key: string }) => Effect.Effect<ReadonlyArray<DirectoryEntry>, never, Directory>;
advise: (input: { readonly serviceKey: string; readonly prefer: string }) => Effect.Effect<string, never, Advice>;
prefer: (service: string | { readonly key: string }, nodeKey: string) => Effect.Effect<string, never, Advice>;
preferEntry: (service: string | { readonly key: string }, entry: { readonly nodeKey: string }) => Effect.Effect<string, never, Advice>;
clearAdvice: (service: string | { readonly key: string }) => Effect.Effect<boolean, never, Advice>;
preferred: (service: string | { readonly key: string }) => Effect.Effect<Option.Option<string>, never, Advice>;
defaultIpcPath: '/tmp/hyperlink-ts-lookup.sock';
layerIpc: (path: string, options?: { readonly unlink?: boolean; readonly onConflict?: OnConflictResolved }) => Layer.Layer<Identity | Directory | Advice | Hyperlink.Local<Identity> | Handler<'claim'> | Handler<'resolve'> | Hyperlink.Local<Directory>…;
layerNode: (node: AnyNode & { readonly key: string }, options?: { readonly unlink?: boolean }) => Layer.Layer<never, LookupUnaddressed>;
directoryAdvertiseLayer: (node: AnyNode & { readonly key: string }, serves: ReadonlyArray<string>, options?: { readonly onConflict?: OnConflict }) => Layer.Layer<never, IncumbentAlive>;
client: (node: AnyNode & { readonly path?: string }) => Layer.Layer<Services, LookupUnaddressed>;
clientOptions: (options?: { readonly path?: string }) => Layer.Layer<Services, LookupUnaddressed>;
layerOptions: (options?: { readonly path?: string; readonly unlink?: boolean }) => Layer.Layer<Services>;
layer: Layer.Layer<Services>;
}
Lookup.class Identityclass Identity {
key: Identifier;
Service: {
claim: (payload: { kind: 'Http' | 'WebSocket' | 'IpcSocket'; key: string; nodeKey: string; url?: string | undefined; path?: string | undefined }) => Effect.Effect<Endpoint, DuplicateIdentity, never>;
resolve: (payload: { key: string }) => Effect.Effect<Option.Option<Endpoint>, never, never>;
};
description: string | undefined;
of: (this: void, self: { readonly claim: (payload: { kind: 'Http' | 'WebSocket' | 'IpcSocket'; key: string; nodeKey: string; url?: string | undefined; path?: string | undefined }) => Effect.Effect<Endpoint, DuplicateIdentity, never>; readonly …;
context: (self: { readonly claim: (payload: { kind: 'Http' | 'WebSocket' | 'IpcSocket'; key: string; nodeKey: string; url?: string | undefined; path?: string | undefined }) => Effect.Effect<Endpoint, DuplicateIdentity, never>; readonly resolve: (pa…;
use: (f: (service: { readonly claim: (payload: { kind: 'Http' | 'WebSocket' | 'IpcSocket'; key: string; nodeKey: string; url?: string | undefined; path?: string | undefined }) => Effect.Effect<Endpoint, DuplicateIdentity, never>; readonly resol…;
useSync: (f: (service: { readonly claim: (payload: { kind: 'Http' | 'WebSocket' | 'IpcSocket'; key: string; nodeKey: string; url?: string | undefined; path?: string | undefined }) => Effect.Effect<Endpoint, DuplicateIdentity, never>; readonly resol…;
Identifier: Identifier;
stack: string | undefined;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
toString: () => string;
toJSON: () => unknown;
}
Lookup identity service — claim HyperService keys (first wins; dead winners replaceable).
Identity;
const const resolved: Option.Option<Endpoint>resolved = yield* const identity: {
readonly claim: (payload: {
kind: "Http" | "WebSocket" | "IpcSocket"
key: string
nodeKey: string
url?: string | undefined
path?: string | undefined
}) => Effect.Effect<
Endpoint,
DuplicateIdentity,
never
>
readonly resolve: (payload: {
key: string
}) => Effect.Effect<
Option.Option<Endpoint>,
never,
never
>
}
identity.resolve: (payload: {
key: string
}) => Effect.Effect<
Option.Option<Endpoint>,
never,
never
>
resolve(
new const Lookup: typeof import("/Users/nikolasstow/Coding/Hyperlink/worktrees/epsilon/src/Lookup")const Lookup: {
resolveOnConflict: (...prefs: ReadonlyArray<OnConflict | undefined>) => OnConflictResolved;
Endpoint: typeof Endpoint;
ClaimRequest: typeof ClaimRequest;
ResolveRequest: typeof ResolveRequest;
DuplicateIdentity: typeof DuplicateIdentity;
DirectoryEntry: typeof LookupDirectoryEntry;
AdvertiseRequest: typeof AdvertiseRequest;
UnregisterRequest: typeof UnregisterRequest;
NodesServingRequest: typeof NodesServingRequest;
IncumbentAlive: typeof IncumbentAlive;
AdviseRequest: typeof AdviseRequest;
ClearAdviceRequest: typeof ClearAdviceRequest;
PreferredRequest: typeof PreferredRequest;
LookupUnaddressed: typeof LookupUnaddressed;
kind: 'hyperlink-ts/Lookup';
Identity: typeof LookupIdentity;
Directory: typeof LookupDirectory;
Advice: typeof LookupAdvice;
nodesServing: (service: string | { readonly key: string }) => Effect.Effect<ReadonlyArray<DirectoryEntry>, never, Directory>;
advise: (input: { readonly serviceKey: string; readonly prefer: string }) => Effect.Effect<string, never, Advice>;
prefer: (service: string | { readonly key: string }, nodeKey: string) => Effect.Effect<string, never, Advice>;
preferEntry: (service: string | { readonly key: string }, entry: { readonly nodeKey: string }) => Effect.Effect<string, never, Advice>;
clearAdvice: (service: string | { readonly key: string }) => Effect.Effect<boolean, never, Advice>;
preferred: (service: string | { readonly key: string }) => Effect.Effect<Option.Option<string>, never, Advice>;
defaultIpcPath: '/tmp/hyperlink-ts-lookup.sock';
layerIpc: (path: string, options?: { readonly unlink?: boolean; readonly onConflict?: OnConflictResolved }) => Layer.Layer<Identity | Directory | Advice | Hyperlink.Local<Identity> | Handler<'claim'> | Handler<'resolve'> | Hyperlink.Local<Directory>…;
layerNode: (node: AnyNode & { readonly key: string }, options?: { readonly unlink?: boolean }) => Layer.Layer<never, LookupUnaddressed>;
directoryAdvertiseLayer: (node: AnyNode & { readonly key: string }, serves: ReadonlyArray<string>, options?: { readonly onConflict?: OnConflict }) => Layer.Layer<never, IncumbentAlive>;
client: (node: AnyNode & { readonly path?: string }) => Layer.Layer<Services, LookupUnaddressed>;
clientOptions: (options?: { readonly path?: string }) => Layer.Layer<Services, LookupUnaddressed>;
layerOptions: (options?: { readonly path?: string; readonly unlink?: boolean }) => Layer.Layer<Services>;
layer: Layer.Layer<Services>;
}
Lookup.constructor ResolveRequest(props: Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlyMakeIn<{
readonly key: Schema.String;
}>, options?: Schema.MakeOptions | undefined): ResolveRequest
constructor ResolveRequest(props: Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlyMakeIn<{
readonly key: Schema.String;
}>, options?: Schema.MakeOptions | undefined): {
Type: Self;
Encoded: S["Encoded"];
DecodingServices: S["DecodingServices"];
EncodingServices: S["EncodingServices"];
Iso: S["Iso"];
identifier: string;
fields: S["fields"];
mapFields: (f: (fields: { readonly key: Schema.String }) => To, options?: { readonly unsafePreserveChecks?: boolean | undefined } | undefined) => Schema.Struct<{ [K in keyof Readonly<To>]: Readonly<To>[K]; }>;
extend: (identifier: string) => { (fields: NewFields, annotations?: Schema.Annotations.Declaration<Extended, readonly [Schema.Struct<{ [K in keyof { [K in keyof ('key' & keyof NewFields extends never ? { readonly key: Schema.String; } & NewFields …;
Rebuild: Rebuild;
ast: Ast;
annotate: (annotations: Schema.Annotations.Bottom<ResolveRequest, readonly [Schema.Struct<{ readonly key: Schema.String }>]>) => Schema.decodeTo<Schema.declareConstructor<ResolveRequest, Schema.Struct.ReadonlySide<{ readonly key: Schema.String }, 'E…;
annotateKey: (annotations: Schema.Annotations.Key<ResolveRequest>) => Schema.decodeTo<Schema.declareConstructor<ResolveRequest, Schema.Struct.ReadonlySide<{ readonly key: Schema.String }, 'Encoded'>, readonly [Schema.Struct<{ readonly key: Schema.Strin…;
check: (checks_0: Check<ResolveRequest>, ...checks: Array<Check<ResolveRequest>>) => Schema.decodeTo<Schema.declareConstructor<ResolveRequest, Schema.Struct.ReadonlySide<{ readonly key: Schema.String }, 'Encoded'>, readonly [Schema.Struct<{ reado…;
rebuild: (ast: Declaration) => Schema.decodeTo<Schema.declareConstructor<ResolveRequest, Schema.Struct.ReadonlySide<{ readonly key: Schema.String }, 'Encoded'>, readonly [Schema.Struct<{ readonly key: Schema.String }>], Schema.Struct.ReadonlySide<{…;
make: (input: Struct.ReadonlyMakeIn<{ readonly key: String }>, options?: MakeOptions) => ResolveRequest;
makeOption: (input: Struct.ReadonlyMakeIn<{ readonly key: String }>, options?: MakeOptions) => Option_.Option<ResolveRequest>;
makeEffect: (input: Struct.ReadonlyMakeIn<{ readonly key: String }>, options?: MakeOptions) => Effect.Effect<ResolveRequest, SchemaError, never>;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
}
Resolve payload — look up a winning claim by HyperService key (nodeless clients).
ResolveRequest({ key: stringkey: tag: HyperlinkTag<Self, S>(parameter) tag: {
description: string | undefined;
key: Identifier;
of: (this: void, self: Simplify<{ readonly [K in keyof S]: S[K] extends FromLocalMethod<infer M> ? InjectLocal<M, Self> : S[K] extends LocalMethod<infer T> ? LocalEffect<T, never, Self> : S[K] extends DefaultMethod<infer F> ? F : S[K] extends …;
context: (self: Simplify<{ readonly [K in keyof S]: S[K] extends FromLocalMethod<infer M> ? InjectLocal<M, Self> : S[K] extends LocalMethod<infer T> ? LocalEffect<T, never, Self> : S[K] extends DefaultMethod<infer F> ? F : S[K] extends { readonly _…;
use: (f: (service: Simplify<{ readonly [K in keyof S]: S[K] extends FromLocalMethod<infer M> ? InjectLocal<M, Self> : S[K] extends LocalMethod<infer T> ? LocalEffect<T, never, Self> : S[K] extends DefaultMethod<infer F> ? F : S[K] extends { rea…;
useSync: (f: (service: Simplify<{ readonly [K in keyof S]: S[K] extends FromLocalMethod<infer M> ? InjectLocal<M, Self> : S[K] extends LocalMethod<infer T> ? LocalEffect<T, never, Self> : S[K] extends DefaultMethod<infer F> ? F : S[K] extends { rea…;
Identifier: Identifier;
Service: Shape;
stack: string | undefined;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
toString: () => string;
toJSON: () => unknown;
}
tag.ServiceClass<Self, string, Simplify<{ readonly [K in keyof S]: S[K] extends FromLocalMethod<infer M> ? InjectLocal<M, Self> : S[K] extends LocalMethod<...> ? LocalEffect<...> : S[K] extends DefaultMethod<...> ? F : S[K] extends { ...; } ? SuccessOf<...> : S[K] extends { ...; } ? Subscribable<...> : S[K] extends { ...; } ? ClientMethod<...> : S[K] extends Spec ? Simplify<...> : never; }>>.key: stringkey }),
);
if (import OptionOption.const isSome: <A>(
self: Option<A>
) => self is Some<A>
Checks whether an Option contains a value (Some).
When to use
Use when you need to branch on a present Option before accessing .value.
Details
- Acts as a type guard, narrowing to
Some<A>
Example (Checking for Some)
import { Option } from "effect"
console.log(Option.isSome(Option.some(1)))
// Output: true
console.log(Option.isSome(Option.none()))
// Output: false
isSome(const resolved: Option.Option<Endpoint>resolved)) {
return const clientLayerForEndpoint: <
Self,
S extends Spec
>(
tag: HyperlinkTag<Self, S>,
endpoint: {
readonly nodeKey: string
readonly kind: ProtocolKind
readonly url?: string
readonly path?: string
}
) => Layer.Layer<Self>
Client layer dialing a Lookup winner's
Endpoint
— used when identity claim loses.
clientLayerForEndpoint(tag: HyperlinkTag<Self, S>(parameter) tag: {
description: string | undefined;
key: Identifier;
of: (this: void, self: Simplify<{ readonly [K in keyof S]: S[K] extends FromLocalMethod<infer M> ? InjectLocal<M, Self> : S[K] extends LocalMethod<infer T> ? LocalEffect<T, never, Self> : S[K] extends DefaultMethod<infer F> ? F : S[K] extends …;
context: (self: Simplify<{ readonly [K in keyof S]: S[K] extends FromLocalMethod<infer M> ? InjectLocal<M, Self> : S[K] extends LocalMethod<infer T> ? LocalEffect<T, never, Self> : S[K] extends DefaultMethod<infer F> ? F : S[K] extends { readonly _…;
use: (f: (service: Simplify<{ readonly [K in keyof S]: S[K] extends FromLocalMethod<infer M> ? InjectLocal<M, Self> : S[K] extends LocalMethod<infer T> ? LocalEffect<T, never, Self> : S[K] extends DefaultMethod<infer F> ? F : S[K] extends { rea…;
useSync: (f: (service: Simplify<{ readonly [K in keyof S]: S[K] extends FromLocalMethod<infer M> ? InjectLocal<M, Self> : S[K] extends LocalMethod<infer T> ? LocalEffect<T, never, Self> : S[K] extends DefaultMethod<infer F> ? F : S[K] extends { rea…;
Identifier: Identifier;
Service: Shape;
stack: string | undefined;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
toString: () => string;
toJSON: () => unknown;
}
tag, const resolved: Option.Some<Endpoint>const resolved: {
_tag: "Some";
_op: "Some";
value: A;
valueOrUndefined: A;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
toString: () => string;
toJSON: () => unknown;
}
resolved.Some<Endpoint>.value: Endpoint(property) Some<Endpoint>.value: {
kind: 'Http' | 'WebSocket' | 'IpcSocket';
nodeKey: string;
url: string | undefined;
path: string | undefined;
}
value);
}
const const entries: ReadonlyArray<LookupDirectoryEntry>entries = yield* const Lookup: typeof import("/Users/nikolasstow/Coding/Hyperlink/worktrees/epsilon/src/Lookup")const Lookup: {
resolveOnConflict: (...prefs: ReadonlyArray<OnConflict | undefined>) => OnConflictResolved;
Endpoint: typeof Endpoint;
ClaimRequest: typeof ClaimRequest;
ResolveRequest: typeof ResolveRequest;
DuplicateIdentity: typeof DuplicateIdentity;
DirectoryEntry: typeof LookupDirectoryEntry;
AdvertiseRequest: typeof AdvertiseRequest;
UnregisterRequest: typeof UnregisterRequest;
NodesServingRequest: typeof NodesServingRequest;
IncumbentAlive: typeof IncumbentAlive;
AdviseRequest: typeof AdviseRequest;
ClearAdviceRequest: typeof ClearAdviceRequest;
PreferredRequest: typeof PreferredRequest;
LookupUnaddressed: typeof LookupUnaddressed;
kind: 'hyperlink-ts/Lookup';
Identity: typeof LookupIdentity;
Directory: typeof LookupDirectory;
Advice: typeof LookupAdvice;
nodesServing: (service: string | { readonly key: string }) => Effect.Effect<ReadonlyArray<DirectoryEntry>, never, Directory>;
advise: (input: { readonly serviceKey: string; readonly prefer: string }) => Effect.Effect<string, never, Advice>;
prefer: (service: string | { readonly key: string }, nodeKey: string) => Effect.Effect<string, never, Advice>;
preferEntry: (service: string | { readonly key: string }, entry: { readonly nodeKey: string }) => Effect.Effect<string, never, Advice>;
clearAdvice: (service: string | { readonly key: string }) => Effect.Effect<boolean, never, Advice>;
preferred: (service: string | { readonly key: string }) => Effect.Effect<Option.Option<string>, never, Advice>;
defaultIpcPath: '/tmp/hyperlink-ts-lookup.sock';
layerIpc: (path: string, options?: { readonly unlink?: boolean; readonly onConflict?: OnConflictResolved }) => Layer.Layer<Identity | Directory | Advice | Hyperlink.Local<Identity> | Handler<'claim'> | Handler<'resolve'> | Hyperlink.Local<Directory>…;
layerNode: (node: AnyNode & { readonly key: string }, options?: { readonly unlink?: boolean }) => Layer.Layer<never, LookupUnaddressed>;
directoryAdvertiseLayer: (node: AnyNode & { readonly key: string }, serves: ReadonlyArray<string>, options?: { readonly onConflict?: OnConflict }) => Layer.Layer<never, IncumbentAlive>;
client: (node: AnyNode & { readonly path?: string }) => Layer.Layer<Services, LookupUnaddressed>;
clientOptions: (options?: { readonly path?: string }) => Layer.Layer<Services, LookupUnaddressed>;
layerOptions: (options?: { readonly path?: string; readonly unlink?: boolean }) => Layer.Layer<Services>;
layer: Layer.Layer<Services>;
}
Lookup.const nodesServing: (
service: string | { readonly key: string }
) => Effect.Effect<
ReadonlyArray<DirectoryEntry>,
never,
Directory
>
List directory rows that advertise a HyperService (Tag or wire key).
Sugar over
Directory
.nodesServing — wire stays
NodesServingRequest
.
const rows = yield* Lookup.nodesServing(Jobs)
// or Lookup.nodesServing("fleet/Jobs")
nodesServing(tag: HyperlinkTag<Self, S>(parameter) tag: {
description: string | undefined;
key: Identifier;
of: (this: void, self: Simplify<{ readonly [K in keyof S]: S[K] extends FromLocalMethod<infer M> ? InjectLocal<M, Self> : S[K] extends LocalMethod<infer T> ? LocalEffect<T, never, Self> : S[K] extends DefaultMethod<infer F> ? F : S[K] extends …;
context: (self: Simplify<{ readonly [K in keyof S]: S[K] extends FromLocalMethod<infer M> ? InjectLocal<M, Self> : S[K] extends LocalMethod<infer T> ? LocalEffect<T, never, Self> : S[K] extends DefaultMethod<infer F> ? F : S[K] extends { readonly _…;
use: (f: (service: Simplify<{ readonly [K in keyof S]: S[K] extends FromLocalMethod<infer M> ? InjectLocal<M, Self> : S[K] extends LocalMethod<infer T> ? LocalEffect<T, never, Self> : S[K] extends DefaultMethod<infer F> ? F : S[K] extends { rea…;
useSync: (f: (service: Simplify<{ readonly [K in keyof S]: S[K] extends FromLocalMethod<infer M> ? InjectLocal<M, Self> : S[K] extends LocalMethod<infer T> ? LocalEffect<T, never, Self> : S[K] extends DefaultMethod<infer F> ? F : S[K] extends { rea…;
Identifier: Identifier;
Service: Shape;
stack: string | undefined;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
toString: () => string;
toJSON: () => unknown;
}
tag);
if (const entries: ReadonlyArray<LookupDirectoryEntry>entries.ReadonlyArray<T>.length: numberGets the length of the array. This is a number one higher than the highest element defined in an array.
length === 0) {
return yield* new constructor LookupClientError<{
readonly tag: string;
readonly reason: "missing" | "ambiguous";
readonly count: number;
}>(args: {
readonly tag: string;
readonly reason: "missing" | "ambiguous";
readonly count: number;
}): LookupClientError
lookupClient
could not resolve exactly one dial target for the Tag
(missing = none; ambiguous = more than one directory row and no
LookupClientOptions.pick
).
LookupClientError({
tag: stringtag: tag: HyperlinkTag<Self, S>(parameter) tag: {
description: string | undefined;
key: Identifier;
of: (this: void, self: Simplify<{ readonly [K in keyof S]: S[K] extends FromLocalMethod<infer M> ? InjectLocal<M, Self> : S[K] extends LocalMethod<infer T> ? LocalEffect<T, never, Self> : S[K] extends DefaultMethod<infer F> ? F : S[K] extends …;
context: (self: Simplify<{ readonly [K in keyof S]: S[K] extends FromLocalMethod<infer M> ? InjectLocal<M, Self> : S[K] extends LocalMethod<infer T> ? LocalEffect<T, never, Self> : S[K] extends DefaultMethod<infer F> ? F : S[K] extends { readonly _…;
use: (f: (service: Simplify<{ readonly [K in keyof S]: S[K] extends FromLocalMethod<infer M> ? InjectLocal<M, Self> : S[K] extends LocalMethod<infer T> ? LocalEffect<T, never, Self> : S[K] extends DefaultMethod<infer F> ? F : S[K] extends { rea…;
useSync: (f: (service: Simplify<{ readonly [K in keyof S]: S[K] extends FromLocalMethod<infer M> ? InjectLocal<M, Self> : S[K] extends LocalMethod<infer T> ? LocalEffect<T, never, Self> : S[K] extends DefaultMethod<infer F> ? F : S[K] extends { rea…;
Identifier: Identifier;
Service: Shape;
stack: string | undefined;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
toString: () => string;
toJSON: () => unknown;
}
tag.ServiceClass<Self, string, Simplify<{ readonly [K in keyof S]: S[K] extends FromLocalMethod<infer M> ? InjectLocal<M, Self> : S[K] extends LocalMethod<...> ? LocalEffect<...> : S[K] extends DefaultMethod<...> ? F : S[K] extends { ...; } ? SuccessOf<...> : S[K] extends { ...; } ? Subscribable<...> : S[K] extends { ...; } ? ClientMethod<...> : S[K] extends Spec ? Simplify<...> : never; }>>.key: stringkey,
reason: "missing" | "ambiguous"reason: "missing",
count: numbercount: 0,
});
}
if (const entries: ReadonlyArray<LookupDirectoryEntry>entries.ReadonlyArray<T>.length: numberGets the length of the array. This is a number one higher than the highest element defined in an array.
length === 1) {
return const clientLayerForEndpoint: <
Self,
S extends Spec
>(
tag: HyperlinkTag<Self, S>,
endpoint: {
readonly nodeKey: string
readonly kind: ProtocolKind
readonly url?: string
readonly path?: string
}
) => Layer.Layer<Self>
Client layer dialing a Lookup winner's
Endpoint
— used when identity claim loses.
clientLayerForEndpoint(tag: HyperlinkTag<Self, S>(parameter) tag: {
description: string | undefined;
key: Identifier;
of: (this: void, self: Simplify<{ readonly [K in keyof S]: S[K] extends FromLocalMethod<infer M> ? InjectLocal<M, Self> : S[K] extends LocalMethod<infer T> ? LocalEffect<T, never, Self> : S[K] extends DefaultMethod<infer F> ? F : S[K] extends …;
context: (self: Simplify<{ readonly [K in keyof S]: S[K] extends FromLocalMethod<infer M> ? InjectLocal<M, Self> : S[K] extends LocalMethod<infer T> ? LocalEffect<T, never, Self> : S[K] extends DefaultMethod<infer F> ? F : S[K] extends { readonly _…;
use: (f: (service: Simplify<{ readonly [K in keyof S]: S[K] extends FromLocalMethod<infer M> ? InjectLocal<M, Self> : S[K] extends LocalMethod<infer T> ? LocalEffect<T, never, Self> : S[K] extends DefaultMethod<infer F> ? F : S[K] extends { rea…;
useSync: (f: (service: Simplify<{ readonly [K in keyof S]: S[K] extends FromLocalMethod<infer M> ? InjectLocal<M, Self> : S[K] extends LocalMethod<infer T> ? LocalEffect<T, never, Self> : S[K] extends DefaultMethod<infer F> ? F : S[K] extends { rea…;
Identifier: Identifier;
Service: Shape;
stack: string | undefined;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
toString: () => string;
toJSON: () => unknown;
}
tag, const entries: ReadonlyArray<LookupDirectoryEntry>entries[0]!);
}
// M5 — honor placement advice when the preferred node is still advertised.
const const prefer: Option.Option<string>prefer = yield* const Lookup: typeof import("/Users/nikolasstow/Coding/Hyperlink/worktrees/epsilon/src/Lookup")const Lookup: {
resolveOnConflict: (...prefs: ReadonlyArray<OnConflict | undefined>) => OnConflictResolved;
Endpoint: typeof Endpoint;
ClaimRequest: typeof ClaimRequest;
ResolveRequest: typeof ResolveRequest;
DuplicateIdentity: typeof DuplicateIdentity;
DirectoryEntry: typeof LookupDirectoryEntry;
AdvertiseRequest: typeof AdvertiseRequest;
UnregisterRequest: typeof UnregisterRequest;
NodesServingRequest: typeof NodesServingRequest;
IncumbentAlive: typeof IncumbentAlive;
AdviseRequest: typeof AdviseRequest;
ClearAdviceRequest: typeof ClearAdviceRequest;
PreferredRequest: typeof PreferredRequest;
LookupUnaddressed: typeof LookupUnaddressed;
kind: 'hyperlink-ts/Lookup';
Identity: typeof LookupIdentity;
Directory: typeof LookupDirectory;
Advice: typeof LookupAdvice;
nodesServing: (service: string | { readonly key: string }) => Effect.Effect<ReadonlyArray<DirectoryEntry>, never, Directory>;
advise: (input: { readonly serviceKey: string; readonly prefer: string }) => Effect.Effect<string, never, Advice>;
prefer: (service: string | { readonly key: string }, nodeKey: string) => Effect.Effect<string, never, Advice>;
preferEntry: (service: string | { readonly key: string }, entry: { readonly nodeKey: string }) => Effect.Effect<string, never, Advice>;
clearAdvice: (service: string | { readonly key: string }) => Effect.Effect<boolean, never, Advice>;
preferred: (service: string | { readonly key: string }) => Effect.Effect<Option.Option<string>, never, Advice>;
defaultIpcPath: '/tmp/hyperlink-ts-lookup.sock';
layerIpc: (path: string, options?: { readonly unlink?: boolean; readonly onConflict?: OnConflictResolved }) => Layer.Layer<Identity | Directory | Advice | Hyperlink.Local<Identity> | Handler<'claim'> | Handler<'resolve'> | Hyperlink.Local<Directory>…;
layerNode: (node: AnyNode & { readonly key: string }, options?: { readonly unlink?: boolean }) => Layer.Layer<never, LookupUnaddressed>;
directoryAdvertiseLayer: (node: AnyNode & { readonly key: string }, serves: ReadonlyArray<string>, options?: { readonly onConflict?: OnConflict }) => Layer.Layer<never, IncumbentAlive>;
client: (node: AnyNode & { readonly path?: string }) => Layer.Layer<Services, LookupUnaddressed>;
clientOptions: (options?: { readonly path?: string }) => Layer.Layer<Services, LookupUnaddressed>;
layerOptions: (options?: { readonly path?: string; readonly unlink?: boolean }) => Layer.Layer<Services>;
layer: Layer.Layer<Services>;
}
Lookup.const preferred: (
service: string | { readonly key: string }
) => Effect.Effect<
Option.Option<string>,
never,
Advice
>
Read preferred directory nodeKey for a HyperService (Tag or wire key).
preferred(tag: HyperlinkTag<Self, S>(parameter) tag: {
description: string | undefined;
key: Identifier;
of: (this: void, self: Simplify<{ readonly [K in keyof S]: S[K] extends FromLocalMethod<infer M> ? InjectLocal<M, Self> : S[K] extends LocalMethod<infer T> ? LocalEffect<T, never, Self> : S[K] extends DefaultMethod<infer F> ? F : S[K] extends …;
context: (self: Simplify<{ readonly [K in keyof S]: S[K] extends FromLocalMethod<infer M> ? InjectLocal<M, Self> : S[K] extends LocalMethod<infer T> ? LocalEffect<T, never, Self> : S[K] extends DefaultMethod<infer F> ? F : S[K] extends { readonly _…;
use: (f: (service: Simplify<{ readonly [K in keyof S]: S[K] extends FromLocalMethod<infer M> ? InjectLocal<M, Self> : S[K] extends LocalMethod<infer T> ? LocalEffect<T, never, Self> : S[K] extends DefaultMethod<infer F> ? F : S[K] extends { rea…;
useSync: (f: (service: Simplify<{ readonly [K in keyof S]: S[K] extends FromLocalMethod<infer M> ? InjectLocal<M, Self> : S[K] extends LocalMethod<infer T> ? LocalEffect<T, never, Self> : S[K] extends DefaultMethod<infer F> ? F : S[K] extends { rea…;
Identifier: Identifier;
Service: Shape;
stack: string | undefined;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
toString: () => string;
toJSON: () => unknown;
}
tag.ServiceClass<Self, string, Simplify<{ readonly [K in keyof S]: S[K] extends FromLocalMethod<infer M> ? InjectLocal<M, Self> : S[K] extends LocalMethod<...> ? LocalEffect<...> : S[K] extends DefaultMethod<...> ? F : S[K] extends { ...; } ? SuccessOf<...> : S[K] extends { ...; } ? Subscribable<...> : S[K] extends { ...; } ? ClientMethod<...> : S[K] extends Spec ? Simplify<...> : never; }>>.key: stringkey);
if (import OptionOption.const isSome: <A>(
self: Option<A>
) => self is Some<A>
Checks whether an Option contains a value (Some).
When to use
Use when you need to branch on a present Option before accessing .value.
Details
- Acts as a type guard, narrowing to
Some<A>
Example (Checking for Some)
import { Option } from "effect"
console.log(Option.isSome(Option.some(1)))
// Output: true
console.log(Option.isSome(Option.none()))
// Output: false
isSome(const prefer: Option.Option<string>prefer)) {
const const advised:
| LookupDirectoryEntry
| undefined
advised = const entries: ReadonlyArray<LookupDirectoryEntry>entries.ReadonlyArray<DirectoryEntry>.find(predicate: (value: LookupDirectoryEntry, index: number, obj: readonly LookupDirectoryEntry[]) => unknown, thisArg?: any): LookupDirectoryEntry | undefined (+1 overload)Returns the value of the first element in the array where predicate is true, and undefined
otherwise.
find((row: LookupDirectoryEntry(parameter) row: {
kind: 'Http' | 'WebSocket' | 'IpcSocket';
nodeKey: string;
serves: ReadonlyArray<string>;
url: string | undefined;
path: string | undefined;
}
row) => row: LookupDirectoryEntry(parameter) row: {
kind: 'Http' | 'WebSocket' | 'IpcSocket';
nodeKey: string;
serves: ReadonlyArray<string>;
url: string | undefined;
path: string | undefined;
}
row.nodeKey: stringnodeKey === const prefer: Option.Some<string>const prefer: {
_tag: "Some";
_op: "Some";
value: A;
valueOrUndefined: A;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
toString: () => string;
toJSON: () => unknown;
}
prefer.Some<string>.value: stringvalue);
if (const advised:
| LookupDirectoryEntry
| undefined
advised !== var undefinedundefined) {
return const clientLayerForEndpoint: <
Self,
S extends Spec
>(
tag: HyperlinkTag<Self, S>,
endpoint: {
readonly nodeKey: string
readonly kind: ProtocolKind
readonly url?: string
readonly path?: string
}
) => Layer.Layer<Self>
Client layer dialing a Lookup winner's
Endpoint
— used when identity claim loses.
clientLayerForEndpoint(tag: HyperlinkTag<Self, S>(parameter) tag: {
description: string | undefined;
key: Identifier;
of: (this: void, self: Simplify<{ readonly [K in keyof S]: S[K] extends FromLocalMethod<infer M> ? InjectLocal<M, Self> : S[K] extends LocalMethod<infer T> ? LocalEffect<T, never, Self> : S[K] extends DefaultMethod<infer F> ? F : S[K] extends …;
context: (self: Simplify<{ readonly [K in keyof S]: S[K] extends FromLocalMethod<infer M> ? InjectLocal<M, Self> : S[K] extends LocalMethod<infer T> ? LocalEffect<T, never, Self> : S[K] extends DefaultMethod<infer F> ? F : S[K] extends { readonly _…;
use: (f: (service: Simplify<{ readonly [K in keyof S]: S[K] extends FromLocalMethod<infer M> ? InjectLocal<M, Self> : S[K] extends LocalMethod<infer T> ? LocalEffect<T, never, Self> : S[K] extends DefaultMethod<infer F> ? F : S[K] extends { rea…;
useSync: (f: (service: Simplify<{ readonly [K in keyof S]: S[K] extends FromLocalMethod<infer M> ? InjectLocal<M, Self> : S[K] extends LocalMethod<infer T> ? LocalEffect<T, never, Self> : S[K] extends DefaultMethod<infer F> ? F : S[K] extends { rea…;
Identifier: Identifier;
Service: Shape;
stack: string | undefined;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
toString: () => string;
toJSON: () => unknown;
}
tag, const advised: LookupDirectoryEntryconst advised: {
kind: 'Http' | 'WebSocket' | 'IpcSocket';
nodeKey: string;
serves: ReadonlyArray<string>;
url: string | undefined;
path: string | undefined;
}
advised);
}
}
const const pick: LookupClientPick | undefinedpick = options: LookupClientOptionsoptions?.pick?: LookupClientPickpick;
if (const pick: LookupClientPick | undefinedpick === var undefinedundefined) {
return yield* new constructor LookupClientError<{
readonly tag: string;
readonly reason: "missing" | "ambiguous";
readonly count: number;
}>(args: {
readonly tag: string;
readonly reason: "missing" | "ambiguous";
readonly count: number;
}): LookupClientError
lookupClient
could not resolve exactly one dial target for the Tag
(missing = none; ambiguous = more than one directory row and no
LookupClientOptions.pick
).
LookupClientError({
tag: stringtag: tag: HyperlinkTag<Self, S>(parameter) tag: {
description: string | undefined;
key: Identifier;
of: (this: void, self: Simplify<{ readonly [K in keyof S]: S[K] extends FromLocalMethod<infer M> ? InjectLocal<M, Self> : S[K] extends LocalMethod<infer T> ? LocalEffect<T, never, Self> : S[K] extends DefaultMethod<infer F> ? F : S[K] extends …;
context: (self: Simplify<{ readonly [K in keyof S]: S[K] extends FromLocalMethod<infer M> ? InjectLocal<M, Self> : S[K] extends LocalMethod<infer T> ? LocalEffect<T, never, Self> : S[K] extends DefaultMethod<infer F> ? F : S[K] extends { readonly _…;
use: (f: (service: Simplify<{ readonly [K in keyof S]: S[K] extends FromLocalMethod<infer M> ? InjectLocal<M, Self> : S[K] extends LocalMethod<infer T> ? LocalEffect<T, never, Self> : S[K] extends DefaultMethod<infer F> ? F : S[K] extends { rea…;
useSync: (f: (service: Simplify<{ readonly [K in keyof S]: S[K] extends FromLocalMethod<infer M> ? InjectLocal<M, Self> : S[K] extends LocalMethod<infer T> ? LocalEffect<T, never, Self> : S[K] extends DefaultMethod<infer F> ? F : S[K] extends { rea…;
Identifier: Identifier;
Service: Shape;
stack: string | undefined;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
toString: () => string;
toJSON: () => unknown;
}
tag.ServiceClass<Self, string, Simplify<{ readonly [K in keyof S]: S[K] extends FromLocalMethod<infer M> ? InjectLocal<M, Self> : S[K] extends LocalMethod<...> ? LocalEffect<...> : S[K] extends DefaultMethod<...> ? F : S[K] extends { ...; } ? SuccessOf<...> : S[K] extends { ...; } ? Subscribable<...> : S[K] extends { ...; } ? ClientMethod<...> : S[K] extends Spec ? Simplify<...> : never; }>>.key: stringkey,
reason: "missing" | "ambiguous"reason: "ambiguous",
count: numbercount: const entries: ReadonlyArray<LookupDirectoryEntry>entries.ReadonlyArray<T>.length: numberGets the length of the array. This is a number one higher than the highest element defined in an array.
length,
});
}
const const chosen: LookupDirectoryEntryconst chosen: {
kind: 'Http' | 'WebSocket' | 'IpcSocket';
nodeKey: string;
serves: ReadonlyArray<string>;
url: string | undefined;
path: string | undefined;
}
chosen = const pick: LookupClientPickpick === "first" ? const entries: ReadonlyArray<LookupDirectoryEntry>entries[0]! : const pick: (
rows: ReadonlyArray<LookupDirectoryEntry>
) => LookupDirectoryEntry
pick(const entries: ReadonlyArray<LookupDirectoryEntry>entries);
return const clientLayerForEndpoint: <
Self,
S extends Spec
>(
tag: HyperlinkTag<Self, S>,
endpoint: {
readonly nodeKey: string
readonly kind: ProtocolKind
readonly url?: string
readonly path?: string
}
) => Layer.Layer<Self>
Client layer dialing a Lookup winner's
Endpoint
— used when identity claim loses.
clientLayerForEndpoint(tag: HyperlinkTag<Self, S>(parameter) tag: {
description: string | undefined;
key: Identifier;
of: (this: void, self: Simplify<{ readonly [K in keyof S]: S[K] extends FromLocalMethod<infer M> ? InjectLocal<M, Self> : S[K] extends LocalMethod<infer T> ? LocalEffect<T, never, Self> : S[K] extends DefaultMethod<infer F> ? F : S[K] extends …;
context: (self: Simplify<{ readonly [K in keyof S]: S[K] extends FromLocalMethod<infer M> ? InjectLocal<M, Self> : S[K] extends LocalMethod<infer T> ? LocalEffect<T, never, Self> : S[K] extends DefaultMethod<infer F> ? F : S[K] extends { readonly _…;
use: (f: (service: Simplify<{ readonly [K in keyof S]: S[K] extends FromLocalMethod<infer M> ? InjectLocal<M, Self> : S[K] extends LocalMethod<infer T> ? LocalEffect<T, never, Self> : S[K] extends DefaultMethod<infer F> ? F : S[K] extends { rea…;
useSync: (f: (service: Simplify<{ readonly [K in keyof S]: S[K] extends FromLocalMethod<infer M> ? InjectLocal<M, Self> : S[K] extends LocalMethod<infer T> ? LocalEffect<T, never, Self> : S[K] extends DefaultMethod<infer F> ? F : S[K] extends { rea…;
Identifier: Identifier;
Service: Shape;
stack: string | undefined;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
toString: () => string;
toJSON: () => unknown;
}
tag, const chosen: LookupDirectoryEntryconst chosen: {
kind: 'Http' | 'WebSocket' | 'IpcSocket';
nodeKey: string;
serves: ReadonlyArray<string>;
url: string | undefined;
path: string | undefined;
}
chosen);
}),
) as import LayerLayer.interface Layer<in ROut, out E = never, out RIn = never>A Layer describes how to build one or more services for dependency injection.
When to use
Use to model construction of application services for dependency injection,
especially when services have dependencies, can fail during construction, or
need scoped setup and release.
Details
A Layer<ROut, E, RIn> represents ROut as the services this layer
provides, E as the possible errors during layer construction, and RIn as
the services this layer requires as dependencies.
Layer<
function (type parameter) Self in <Self, S extends Spec>(tag: HyperlinkTag<Self, S>, options?: LookupClientOptions): Layer.Layer<Self, LookupClientError, LookupIdentity | LookupDirectory | LookupAdvice>Self,
class LookupClientErrorclass LookupClientError {
name: string;
message: string;
stack: string;
cause: unknown;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
toString: () => string;
toJSON: () => unknown;
_tag: Tag;
tag: string;
reason: 'missing' | 'ambiguous';
count: number;
}
lookupClient
could not resolve exactly one dial target for the Tag
(missing = none; ambiguous = more than one directory row and no
LookupClientOptions.pick
).
LookupClientError,
class LookupIdentityclass LookupIdentity {
key: Identifier;
Service: {
claim: (payload: { kind: 'Http' | 'WebSocket' | 'IpcSocket'; key: string; nodeKey: string; url?: string | undefined; path?: string | undefined }) => Effect.Effect<Endpoint, DuplicateIdentity, never>;
resolve: (payload: { key: string }) => Effect.Effect<Option.Option<Endpoint>, never, never>;
};
}
Lookup identity service — claim HyperService keys (first wins; dead winners replaceable).
LookupIdentity | class LookupDirectoryclass LookupDirectory {
key: Identifier;
Service: {
advertise: (payload: { kind: 'Http' | 'WebSocket' | 'IpcSocket'; nodeKey: string; serves: ReadonlyArray<string>; url?: string | undefined; path?: string | undefined; onConflict?: 'livenessReplace' | 'askIncumbent' | 'reject' | 'inherit' | undefined }…;
unregister: (payload: { nodeKey: string; kind?: 'Http' | 'WebSocket' | 'IpcSocket' | undefined; url?: string | undefined; path?: string | undefined }) => Effect.Effect<boolean, never, never>;
nodesServing: (payload: { serviceKey: string }) => Effect.Effect<ReadonlyArray<LookupDirectoryEntry>, never, never>;
};
}
Lookup node directory — advertise / unregister / list by served HyperService key.
LookupDirectory | class LookupAdviceclass LookupAdvice {
key: Identifier;
Service: {
advise: (payload: { serviceKey: string; prefer: string }) => Effect.Effect<string, never, never>;
clear: (payload: { serviceKey: string }) => Effect.Effect<boolean, never, never>;
preferred: (payload: { serviceKey: string }) => Effect.Effect<Option.Option<string>, never, never>;
};
}
Lookup placement board — coordinator advice for nodeless /
Hyperlink.lookupClient
dial.
v1: last-write-wins, in-memory, no advisor ACL. Algorithms stay app-owned (who calls
advise
); Lookup only stores and surfaces the preference.
LookupAdvice
>;