1import * as NodeOS from "node:os";
2
3import * as HostProcess from "@t3tools/shared/HostProcess";
4import * as Context from "effect/Context";
5import * as Effect from "effect/Effect";
6import * as Layer from "effect/Layer";
7import * as Schema from "effect/Schema";
8
9export interface DesktopNetworkInterfaceInfo {
10 readonly address: string;
11 readonly family: string | number;
12 readonly internal: boolean;
13 readonly netmask?: string;
14 readonly mac?: string;
15 readonly cidr?: string | null;
16 readonly scopeid?: number;
17}
18
19export type NetworkInterfaces = Readonly<
20 Record<string, readonly DesktopNetworkInterfaceInfo[] | undefined>
21>;
22
23export class DesktopNetworkInterfacesReadError extends Schema.TaggedError<DesktopNetworkInterfacesReadError>()(
24 "DesktopNetworkInterfacesReadError",
25 {
26 platform: Schema.String,
27 cause: Schema.Defect(),
28 },
29) {
30 override get message(): string {
31 return `Failed to read desktop network interfaces on ${this.platform}.`;
32 }
33}
34
35export class DesktopNetworkInterfaces extends Context.Service<
36 DesktopNetworkInterfaces,
37 {
38 readonly read: Effect.Effect<NetworkInterfaces>;
39 }
40>()("@t3tools/desktop/backend/DesktopNetworkInterfaces") {}
41
42/** @public Service construction is part of the canonical Effect module API. */
43export const make = Effect.gen(function* () {
44 const platform = yield* HostProcess.Platform;
45 return DesktopNetworkInterfaces.of({
46 read: Effect.try({
47 try: () => NodeOS.networkInterfaces(),
48 catch: (cause) => new DesktopNetworkInterfacesReadError({ platform, cause }),
49 }).pipe(Effect.orDie),
50 });
51});
52
53export const layer = Layer.effect(DesktopNetworkInterfaces, make);