the-wireguard-effect
Version:
Cross platform wireguard api client for nodejs built on wireguard-go with effect-ts
1,666 lines (1,533 loc) • 53.3 kB
text/typescript
/**
* Internet schemas for wireguard configuration.
*
* @since 1.0.0
*/
import * as Array from "effect/Array";
import * as Brand from "effect/Brand";
import * as Duration from "effect/Duration";
import * as Effect from "effect/Effect";
import * as Function from "effect/Function";
import * as ParseResult from "effect/ParseResult";
import * as Predicate from "effect/Predicate";
import * as Schema from "effect/Schema";
import * as Stream from "effect/Stream";
import * as String from "effect/String";
import * as Tuple from "effect/Tuple";
import * as net from "node:net";
import * as internal from "./internal/internetSchemas.js";
/**
* Transforms a `number` of seconds into a `Duration`.
*
* @since 1.0.0
* @category Schemas
* @example
* import * as Duration from "effect/Duration";
* import * as Schema from "effect/Schema";
* import { DurationFromSeconds } from "the-wireguard-effect/InternetSchemas";
*
* const decodeDuration = Schema.decodeSync(DurationFromSeconds);
* const duration = decodeDuration(11);
* assert.strictEqual(Duration.toSeconds(duration), 11);
*/
export class DurationFromSeconds extends Schema.transform(Schema.Int, Schema.DurationFromSelf, {
decode: Duration.seconds,
encode: Duration.toSeconds,
}).annotations({
identifier: "DurationFromSeconds",
description: "A duration from a number of seconds",
}) {}
/**
* Transforms a `string` of seconds into a `Duration`.
*
* @since 1.0.0
* @category Schemas
* @example
* import * as Duration from "effect/Duration";
* import * as Schema from "effect/Schema";
* import { DurationFromSecondsString } from "the-wireguard-effect/InternetSchemas";
*
* const decodeDurationString = Schema.decodeSync(
* DurationFromSecondsString
* );
* const duration = decodeDurationString("12");
* assert.strictEqual(Duration.toSeconds(duration), 12);
*/
export class DurationFromSecondsString extends Schema.compose(Schema.NumberFromString, DurationFromSeconds).annotations(
{
identifier: "DurationFromSecondsString",
description: "A duration from a string of seconds",
}
) {}
/**
* @since 1.0.0
* @category Branded types
*/
export type PortBrand = number & Brand.Brand<"Port">;
/**
* @since 1.0.0
* @category Branded constructors
*/
export const PortBrand = Brand.nominal<PortBrand>();
/**
* @since 1.0.0
* @category Api interface
*/
export type $Port = Schema.Annotable<$Port, PortBrand, Brand.Brand.Unbranded<PortBrand>, never>;
/**
* An operating system port number.
*
* @since 1.0.0
* @category Schemas
* @example
* import * as Schema from "effect/Schema";
* import { Port, PortBrand } from "the-wireguard-effect/InternetSchemas";
*
* const port: PortBrand = PortBrand(8080);
* assert.strictEqual(port, 8080);
*
* const decodePort = Schema.decodeSync(Port);
* assert.strictEqual(decodePort(8080), 8080);
*
* assert.throws(() => decodePort(65536));
* assert.doesNotThrow(() => decodePort(8080));
*/
export const Port: $Port = Schema.Int.pipe(Schema.between(0, 2 ** 16 - 1))
.pipe(Schema.fromBrand(PortBrand))
.annotations({
identifier: "Port",
title: "An OS port number",
description: "An operating system's port number between 0 and 65535 (inclusive)",
});
/**
* @since 1.0.0
* @category Api interface
*/
export type $IPv4Family = Schema.Literal<["ipv4"]>;
/**
* @since 1.0.0
* @category Decoded types
*/
export type IPv4Family = Schema.Schema.Type<$IPv4Family>;
/**
* @since 1.0.0
* @category Schemas
*/
export const IPv4Family: $IPv4Family = Schema.Literal("ipv4").annotations({
identifier: "IPv4Family",
description: "An ipv4 family",
});
/**
* @since 1.0.0
* @category Branded types
*/
export type IPv4Brand = string & Brand.Brand<"IPv4">;
/**
* @since 1.0.0
* @category Branded constructors
*/
export const IPv4Brand = Brand.nominal<IPv4Brand>();
/**
* @since 1.0.0
* @category Api interface
*/
export type $IPv4 = Schema.transform<
Schema.filter<typeof Schema.String>,
Schema.Struct<{
family: $IPv4Family;
ip: Schema.BrandSchema<IPv4Brand, Brand.Brand.Unbranded<IPv4Brand>, never>;
}>
>;
/**
* @since 1.0.0
* @category Decoded types
*/
export type IPv4 = Schema.Schema.Type<$IPv4>;
/**
* @since 1.0.0
* @category Encoded types
*/
export type IPv4Encoded = Schema.Schema.Encoded<$IPv4>;
/**
* An IPv4 address.
*
* @since 1.0.0
* @category Schemas
* @example
* import * as Schema from "effect/Schema";
* import { IPv4 } from "the-wireguard-effect/InternetSchemas";
*
* const decodeIPv4 = Schema.decodeSync(IPv4);
* assert.deepEqual(decodeIPv4("1.1.1.1"), {
* family: "ipv4",
* ip: "1.1.1.1",
* });
*
* assert.throws(() => decodeIPv4("1.1.a.1"));
* assert.doesNotThrow(() => decodeIPv4("1.1.1.2"));
*/
export const IPv4: $IPv4 = Schema.transform(
Function.pipe(
Schema.String,
Schema.filter((str) => net.isIPv4(str))
),
Schema.Struct({
family: IPv4Family,
ip: Schema.String.pipe(Schema.fromBrand(IPv4Brand)),
}),
{
encode: ({ ip }) => ip,
decode: (ip) => ({ ip, family: "ipv4" }) as const,
}
).annotations({
identifier: "IPv4",
title: "An ipv4 address",
description: "An ipv4 address in dot-decimal notation with no leading zeros",
});
/**
* @since 1.0.0
* @category Branded types
*/
export type IPv4BigintBrand = bigint & Brand.Brand<"IPv4Bigint">;
/**
* @since 1.0.0
* @category Branded constructors
*/
export const IPv4BigintBrand = Brand.nominal<IPv4BigintBrand>();
/**
* @since 1.0.0
* @category Api interface
*/
export type $IPv4Bigint = Schema.transformOrFail<
$IPv4,
Schema.Struct<{
family: $IPv4Family;
value: Schema.BrandSchema<IPv4BigintBrand, Brand.Brand.Unbranded<IPv4BigintBrand>, never>;
}>,
never
>;
/**
* @since 1.0.0
* @category Decoded types
*/
export type IPv4Bigint = Schema.Schema.Type<$IPv4Bigint>;
/**
* @since 1.0.0
* @category Encoded types
*/
export type IPv4BigintEncoded = Schema.Schema.Encoded<$IPv4Bigint>;
/**
* An IPv4 as a bigint.
*
* @since 1.0.0
* @category Schemas
* @example
* import * as Schema from "effect/Schema";
* import {
* IPv4Bigint,
* IPv4BigintBrand,
* } from "the-wireguard-effect/InternetSchemas";
*
* const x: IPv4BigintBrand = IPv4BigintBrand(748392749382n);
* assert.strictEqual(x, 748392749382n);
*
* const decodeIPv4Bigint = Schema.decodeSync(IPv4Bigint);
* const encodeIPv4Bigint = Schema.encodeSync(IPv4Bigint);
*
* assert.deepEqual(decodeIPv4Bigint("1.1.1.1"), {
* family: "ipv4",
* value: 16843009n,
* });
* assert.deepEqual(decodeIPv4Bigint("254.254.254.254"), {
* family: "ipv4",
* value: 4278124286n,
* });
*
* assert.strictEqual(
* encodeIPv4Bigint({
* value: IPv4BigintBrand(16843009n),
* family: "ipv4",
* }),
* "1.1.1.1"
* );
* assert.strictEqual(
* encodeIPv4Bigint({
* value: IPv4BigintBrand(4278124286n),
* family: "ipv4",
* }),
* "254.254.254.254"
* );
*/
export const IPv4Bigint: $IPv4Bigint = Schema.transformOrFail(
IPv4,
Schema.Struct({
family: IPv4Family,
value: Schema.BigIntFromSelf.pipe(Schema.fromBrand(IPv4BigintBrand)),
}),
{
encode: ({ value }) => {
const padded = value.toString(16).replace(/:/g, "").padStart(8, "0");
const groups: Array<number> = [];
for (let i = 0; i < 8; i += 2) {
const h = padded.slice(i, i + 2);
groups.push(parseInt(h, 16));
}
return Schema.decode(IPv4)(groups.join(".")).pipe(Effect.mapError(({ issue }) => issue));
},
decode: ({ ip }) =>
Function.pipe(
ip,
String.split("."),
Array.map((s) => Number.parseInt(s, 10)),
Array.map((n) => n.toString(16)),
Array.map(String.padStart(2, "0")),
Array.join(""),
(hex) => BigInt(`0x${hex}`),
(value) => ({ value, family: "ipv4" }) as const,
Effect.succeed
),
}
).annotations({
identifier: "IPv4Bigint",
description: "An ipv4 address as a bigint",
});
/**
* @since 1.0.0
* @category Api interface
*/
export type $IPv6Family = Schema.Literal<["ipv6"]>;
/**
* @since 1.0.0
* @category Decoded types
*/
export type IPv6Family = Schema.Schema.Type<$IPv6Family>;
/**
* @since 1.0.0
* @category Schemas
*/
export const IPv6Family: $IPv6Family = Schema.Literal("ipv6").annotations({
identifier: "IPv6Family",
description: "An ipv6 family",
});
/**
* @since 1.0.0
* @category Branded types
*/
export type IPv6Brand = string & Brand.Brand<"IPv6">;
/**
* @since 1.0.0
* @category Branded constructors
*/
export const IPv6Brand = Brand.nominal<IPv6Brand>();
/**
* @since 1.0.0
* @category Api interface
*/
export type $IPv6 = Schema.transform<
Schema.filter<typeof Schema.String>,
Schema.Struct<{
family: $IPv6Family;
ip: Schema.BrandSchema<IPv6Brand, Brand.Brand.Unbranded<IPv6Brand>, never>;
}>
>;
/**
* @since 1.0.0
* @category Decoded types
*/
export type IPv6 = Schema.Schema.Type<$IPv6>;
/**
* @since 1.0.0
* @category Encoded types
*/
export type IPv6Encoded = Schema.Schema.Encoded<$IPv6>;
/**
* An IPv6 address.
*
* @since 1.0.0
* @category Schemas
* @example
* import * as Schema from "effect/Schema";
* import { IPv6 } from "the-wireguard-effect/InternetSchemas";
*
* const decodeIPv6 = Schema.decodeSync(IPv6);
* assert.deepEqual(decodeIPv6("2001:0db8:85a3:0000:0000:8a2e:0370:7334"), {
* family: "ipv6",
* ip: "2001:0db8:85a3:0000:0000:8a2e:0370:7334",
* });
*
* assert.throws(() =>
* decodeIPv6("2001:0db8:85a3:0000:0000:8a2e:0370:7334:")
* );
* assert.throws(() => decodeIPv6("2001::85a3::0000::0370:7334"));
* assert.doesNotThrow(() =>
* decodeIPv6("2001:0db8:85a3:0000:0000:8a2e:0370:7334")
* );
*/
export const IPv6: $IPv6 = Schema.transform(
Function.pipe(
Schema.String,
Schema.filter((str) => net.isIPv6(str))
),
Schema.Struct({
family: IPv6Family,
ip: Schema.String.pipe(Schema.fromBrand(IPv6Brand)),
}),
{
encode: ({ ip }) => ip,
decode: (ip) => ({ ip, family: "ipv6" }) as const,
}
).annotations({
identifier: "IPv6",
description: "An ipv6 address",
});
/**
* @since 1.0.0
* @category Branded types
*/
export type IPv6BigintBrand = bigint & Brand.Brand<"IPv6Bigint">;
/**
* @since 1.0.0
* @category Branded constructors
*/
export const IPv6BigintBrand = Brand.nominal<IPv6BigintBrand>();
/**
* @since 1.0.0
* @category Api interface
*/
export type $IPv6Bigint = Schema.transformOrFail<
$IPv6,
Schema.Struct<{
family: $IPv6Family;
value: Schema.BrandSchema<IPv6BigintBrand, Brand.Brand.Unbranded<IPv6BigintBrand>, never>;
}>,
never
>;
/**
* @since 1.0.0
* @category Decoded types
*/
export type IPv6Bigint = Schema.Schema.Type<$IPv6Bigint>;
/**
* @since 1.0.0
* @category Encoded types
*/
export type IPv6BigintEncoded = Schema.Schema.Encoded<$IPv6Bigint>;
/**
* An IPv6 as a bigint.
*
* @since 1.0.0
* @category Schemas
* @example
* import * as Schema from "effect/Schema";
* import {
* IPv6Bigint,
* IPv6BigintBrand,
* } from "the-wireguard-effect/InternetSchemas";
*
* const y: IPv6BigintBrand = IPv6BigintBrand(748392749382n);
* assert.strictEqual(y, 748392749382n);
*
* const decodeIPv6Bigint = Schema.decodeSync(IPv6Bigint);
* const encodeIPv6Bigint = Schema.encodeSync(IPv6Bigint);
*
* assert.deepEqual(
* decodeIPv6Bigint("4cbd:ff70:e62b:a048:686c:4e7e:a68a:c377"),
* { value: 102007852745154114519525620108359287671n, family: "ipv6" }
* );
* assert.deepEqual(
* decodeIPv6Bigint("d8c6:3feb:46e6:b80c:5a07:6227:ac19:caf6"),
* { value: 288142618299897818094313964584331496182n, family: "ipv6" }
* );
*
* assert.deepEqual(
* encodeIPv6Bigint({
* value: IPv6BigintBrand(102007852745154114519525620108359287671n),
* family: "ipv6",
* }),
* "4cbd:ff70:e62b:a048:686c:4e7e:a68a:c377"
* );
* assert.deepEqual(
* encodeIPv6Bigint({
* value: IPv6BigintBrand(288142618299897818094313964584331496182n),
* family: "ipv6",
* }),
* "d8c6:3feb:46e6:b80c:5a07:6227:ac19:caf6"
* );
*/
export const IPv6Bigint: $IPv6Bigint = Schema.transformOrFail(
IPv6,
Schema.Struct({
family: IPv6Family,
value: Schema.BigIntFromSelf.pipe(Schema.fromBrand(IPv6BigintBrand)),
}),
{
encode: ({ value }) => {
const hex = value.toString(16).padStart(32, "0");
const groups = [];
for (let i = 0; i < 8; i++) {
groups.push(hex.slice(i * 4, (i + 1) * 4));
}
return Schema.decode(IPv6)(groups.join(":")).pipe(Effect.mapError(({ issue }) => issue));
},
decode: ({ ip }) => {
function paddedHex(octet: string): string {
return parseInt(octet, 16).toString(16).padStart(4, "0");
}
let groups: Array<string> = [];
const halves = ip.split("::");
// if (halves.length === 2) {
if (Tuple.isTupleOf(2)(halves)) {
let first = halves[0].split(":");
let last = halves[1].split(":");
if (first.length === 1 && first[0] === "") {
first = [];
}
if (last.length === 1 && last[0] === "") {
last = [];
}
const remaining = 8 - (first.length + last.length);
if (!remaining) {
throw new Error("Error parsing groups");
}
groups = groups.concat(first);
for (let i = 0; i < remaining; i++) {
groups.push("0");
}
groups = groups.concat(last);
} else if (halves.length === 1) {
groups = ip.split(":");
} else {
throw new Error("Too many :: groups found");
}
groups = groups.map((group: string) => parseInt(group, 16).toString(16));
if (groups.length !== 8) {
throw new Error("Invalid number of groups");
}
return Effect.succeed({ value: BigInt(`0x${groups.map(paddedHex).join("")}`), family: "ipv6" } as const);
},
}
).annotations({
identifier: "IPv6Bigint",
description: "An ipv6 address as a bigint",
});
/**
* @since 1.0.0
* @category Api interface
*/
export type $Family = Schema.Union<[$IPv4Family, $IPv6Family]>;
/**
* @since 1.0.0
* @category Decoded types
*/
export type Family = Schema.Schema.Type<$Family>;
/**
* @since 1.0.0
* @category Schemas
* @see {@link IPv4Family}
* @see {@link IPv6Family}
*/
export const Family: $Family = Schema.Union(IPv4Family, IPv6Family).annotations({
identifier: "Family",
description: "An ipv4 or ipv6 family",
});
/**
* @since 1.0.0
* @category Api interface
*/
export type $Address = Schema.Union<[$IPv4, $IPv6]>;
/**
* @since 1.0.0
* @category Decoded types
*/
export type Address = Schema.Schema.Type<$Address>;
/**
* @since 1.0.0
* @category Encoded types
*/
export type AddressEncoded = Schema.Schema.Encoded<$Address>;
/**
* An IP address, which is either an IPv4 or IPv6 address.
*
* @since 1.0.0
* @category Schemas
* @example
* import * as Schema from "effect/Schema";
* import { Address } from "the-wireguard-effect/InternetSchemas";
*
* const decodeAddress = Schema.decodeSync(Address);
*
* assert.throws(() => decodeAddress("1.1.b.1"));
* assert.throws(() =>
* decodeAddress("2001:0db8:85a3:0000:0000:8a2e:0370:7334:")
* );
*
* assert.doesNotThrow(() => decodeAddress("1.1.1.2"));
* assert.doesNotThrow(() =>
* decodeAddress("2001:0db8:85a3:0000:0000:8a2e:0370:7334")
* );
*
* @see {@link IPv4}
* @see {@link IPv6}
*/
export const Address: $Address = Schema.Union(IPv4, IPv6).annotations({
identifier: "Address",
description: "An ipv4 or ipv6 address",
});
/**
* @since 1.0.0
* @category Api interface
*/
export type $AddressBigint = Schema.Union<[$IPv4Bigint, $IPv6Bigint]>;
/**
* @since 1.0.0
* @category Decoded types
*/
export type AddressBigint = Schema.Schema.Type<$AddressBigint>;
/**
* @since 1.0.0
* @category Encoded types
*/
export type AddressBigintEncoded = Schema.Schema.Encoded<$AddressBigint>;
/**
* An IP address as a bigint.
*
* @since 1.0.0
* @category Schemas
*/
export const AddressBigint: $AddressBigint = Schema.Union(IPv4Bigint, IPv6Bigint).annotations({
identifier: "AddressBigint",
description: "An ipv4 or ipv6 address as a bigint",
});
/**
* @since 1.0.0
* @category Branded types
*/
export type IPv4CidrMaskBrand = number & Brand.Brand<"IPv4CidrMask">;
/**
* @since 1.0.0
* @category Branded constructors
*/
export const IPv4CidrMaskBrand = Brand.nominal<IPv4CidrMaskBrand>();
/**
* @since 1.0.0
* @category Api interface
*/
export type $IPv4CidrMask = Schema.Annotable<
$IPv4CidrMask,
IPv4CidrMaskBrand,
Brand.Brand.Unbranded<IPv4CidrMaskBrand>,
never
>;
/**
* @since 1.0.0
* @category Decoded types
*/
export type IPv4CidrMask = Schema.Schema.Type<$IPv4CidrMask>;
/**
* @since 1.0.0
* @category Encoded types
*/
export type IPv4CidrMaskEncoded = Schema.Schema.Encoded<$IPv4CidrMask>;
/**
* An ipv4 cidr mask, which is a number between 0 and 32.
*
* @since 1.0.0
* @category Schemas
* @example
* import * as Schema from "effect/Schema";
* import {
* IPv4CidrMask,
* IPv4CidrMaskBrand,
* } from "the-wireguard-effect/InternetSchemas";
*
* const mask: IPv4CidrMaskBrand = IPv4CidrMaskBrand(24);
* assert.strictEqual(mask, 24);
*
* const decodeMask = Schema.decodeSync(IPv4CidrMask);
* assert.strictEqual(decodeMask(24), 24);
*
* assert.throws(() => decodeMask(33));
* assert.doesNotThrow(() => decodeMask(0));
* assert.doesNotThrow(() => decodeMask(32));
*/
export const IPv4CidrMask: $IPv4CidrMask = Schema.Int.pipe(Schema.between(0, 32))
.pipe(Schema.fromBrand(IPv4CidrMaskBrand))
.annotations({
identifier: "IPv4CidrMask",
description: "An ipv4 cidr mask",
});
/**
* @since 1.0.0
* @category Branded types
*/
export type IPv6CidrMaskBrand = number & Brand.Brand<"IPv6CidrMask">;
/**
* @since 1.0.0
* @category Branded constructors
*/
export const IPv6CidrMaskBrand = Brand.nominal<IPv6CidrMaskBrand>();
/**
* @since 1.0.0
* @category Api interface
*/
export type $IPv6CidrMask = Schema.Annotable<
$IPv6CidrMask,
IPv6CidrMaskBrand,
Brand.Brand.Unbranded<IPv6CidrMaskBrand>,
never
>;
/**
* @since 1.0.0
* @category Decoded types
*/
export type IPv6CidrMask = Schema.Schema.Type<$IPv6CidrMask>;
/**
* @since 1.0.0
* @category Encoded types
*/
export type IPv6CidrMaskEncoded = Schema.Schema.Encoded<$IPv6CidrMask>;
/**
* An ipv6 cidr mask, which is a number between 0 and 128.
*
* @since 1.0.0
* @category Schemas
* @example
* import * as Schema from "effect/Schema";
* import {
* IPv6CidrMask,
* IPv6CidrMaskBrand,
* } from "the-wireguard-effect/InternetSchemas";
*
* const mask: IPv6CidrMaskBrand = IPv6CidrMaskBrand(64);
* assert.strictEqual(mask, 64);
*
* const decodeMask = Schema.decodeSync(IPv6CidrMask);
* assert.strictEqual(decodeMask(64), 64);
*
* assert.throws(() => decodeMask(129));
* assert.doesNotThrow(() => decodeMask(0));
* assert.doesNotThrow(() => decodeMask(128));
*/
export const IPv6CidrMask: $IPv6CidrMask = Schema.Int.pipe(Schema.between(0, 128))
.pipe(Schema.fromBrand(IPv6CidrMaskBrand))
.annotations({
identifier: "IPv6CidrMask",
description: "An ipv6 cidr mask",
});
/**
* @since 1.0.0
* @category Api interface
*/
export class CidrBlockBase<_Family extends Family> extends Schema.Class<CidrBlockBase<Family>>("CidrBlockMixin")({
address: Address,
mask: Schema.Union(IPv4CidrMask, IPv6CidrMask),
}) {
/** @since 1.0.0 */
public readonly family: Family = this.address.family;
/** @internal */
private onFamily<OnIPv4, OnIPv6>({
onIPv4,
onIPv6,
}: {
onIPv4: (self: CidrBlockBase<"ipv4">) => OnIPv4;
onIPv6: (self: CidrBlockBase<"ipv6">) => OnIPv6;
}): _Family extends IPv4Family ? OnIPv4 : _Family extends IPv6Family ? OnIPv6 : never {
type Ret = typeof this.address.family extends IPv4Family
? OnIPv4
: typeof this.address.family extends IPv6Family
? OnIPv6
: never;
const isIPv4 = (): this is CidrBlockBase<"ipv4"> => this.family === "ipv4";
const isIPv6 = (): this is CidrBlockBase<"ipv6"> => this.family === "ipv6";
if (isIPv4()) {
return onIPv4(this as CidrBlockBase<"ipv4">) as Ret;
} else if (isIPv6()) {
return onIPv6(this as CidrBlockBase<"ipv6">) as Ret;
} else {
return Function.absurd<Ret>(this.family as never);
}
}
/**
* The first address in the range given by this address' subnet, often
* referred to as the Network Address.
*
* @since 1.0.0
*/
protected get networkAddressAsBigint(): Effect.Effect<
_Family extends IPv4Family ? IPv4BigintBrand : _Family extends IPv6Family ? IPv6BigintBrand : never,
ParseResult.ParseError,
never
> {
return Effect.gen(this, function* () {
const bits = this.family === "ipv4" ? 32 : 128;
const bigIntegerAddress = yield* this.onFamily({
onIPv4: (self) => Schema.decode(IPv4Bigint)(self.address.ip),
onIPv6: (self) => Schema.decode(IPv6Bigint)(self.address.ip),
});
const intermediate = bigIntegerAddress.value.toString(2).padStart(bits, "0").slice(0, this.mask);
const networkAddressString = intermediate + "0".repeat(bits - this.mask);
const networkAddressBigInt = BigInt(`0b${networkAddressString}`);
return this.onFamily({
onIPv4: (_self) => IPv4BigintBrand(networkAddressBigInt),
onIPv6: (_self) => IPv6BigintBrand(networkAddressBigInt),
});
});
}
/**
* The first address in the range given by this address' subnet, often
* referred to as the Network Address.
*
* @since 1.0.0
*/
public networkAddress(): _Family extends IPv4Family
? Effect.Effect<IPv4, ParseResult.ParseError, never>
: _Family extends IPv6Family
? Effect.Effect<IPv6, ParseResult.ParseError, never>
: never {
return this.onFamily({
onIPv4: (self) =>
Function.pipe(
self.networkAddressAsBigint,
Effect.flatMap((value) => Schema.encode(IPv4Bigint)({ value, family: "ipv4" })),
Effect.flatMap(Schema.decode(IPv4))
),
onIPv6: (self) =>
Function.pipe(
self.networkAddressAsBigint,
Effect.flatMap((value) => Schema.encode(IPv6Bigint)({ value, family: "ipv6" })),
Effect.flatMap(Schema.decode(IPv6))
),
});
}
/**
* The last address in the range given by this address' subnet, often
* referred to as the Broadcast Address.
*
* @since 1.0.0
*/
protected get broadcastAddressAsBigint(): Effect.Effect<
_Family extends IPv4Family ? IPv4BigintBrand : _Family extends IPv6Family ? IPv6BigintBrand : never,
ParseResult.ParseError,
never
> {
return Effect.gen(this, function* () {
const bits = this.family === "ipv4" ? 32 : 128;
const bigIntegerAddress = yield* this.onFamily({
onIPv4: (self) => Schema.decode(IPv4Bigint)(self.address.ip),
onIPv6: (self) => Schema.decode(IPv6Bigint)(self.address.ip),
});
const intermediate = bigIntegerAddress.value.toString(2).padStart(bits, "0").slice(0, this.mask);
const broadcastAddressString = intermediate + "1".repeat(bits - this.mask);
const broadcastAddressBigInt = BigInt(`0b${broadcastAddressString}`);
return this.onFamily({
onIPv4: (_self) => IPv4BigintBrand(broadcastAddressBigInt),
onIPv6: (_self) => IPv6BigintBrand(broadcastAddressBigInt),
});
});
}
/**
* The last address in the range given by this address' subnet, often
* referred to as the Broadcast Address.
*
* @since 1.0.0
*/
public broadcastAddress(): _Family extends IPv4Family
? Effect.Effect<IPv4, ParseResult.ParseError, never>
: _Family extends IPv6Family
? Effect.Effect<IPv6, ParseResult.ParseError, never>
: never {
return this.onFamily({
onIPv4: (self) =>
Function.pipe(
self.broadcastAddressAsBigint,
Effect.flatMap((value) => Schema.encode(IPv4Bigint)({ value, family: "ipv4" })),
Effect.flatMap(Schema.decode(IPv4))
),
onIPv6: (self) =>
Function.pipe(
self.broadcastAddressAsBigint,
Effect.flatMap((value) => Schema.encode(IPv6Bigint)({ value, family: "ipv6" })),
Effect.flatMap(Schema.decode(IPv6))
),
});
}
/**
* A stream of all addresses in the range given by this address' subnet.
*
* @since 1.0.0
*/
public get range(): _Family extends IPv4Family
? Stream.Stream<IPv4, ParseResult.ParseError, never>
: _Family extends IPv6Family
? Stream.Stream<IPv6, ParseResult.ParseError, never>
: never {
return this.onFamily({
onIPv4: (self) =>
Effect.gen(function* () {
const minValue = yield* self.networkAddressAsBigint;
const maxValue = yield* self.broadcastAddressAsBigint;
return Function.pipe(
Stream.iterate(minValue, (x) => IPv4BigintBrand(x + 1n)),
Stream.takeWhile((n) => n <= maxValue),
Stream.flatMap((value) => Schema.encode(IPv4Bigint)({ value, family: "ipv4" })),
Stream.mapEffect(Schema.decode(IPv4))
);
}).pipe(Stream.unwrap),
onIPv6: (self) =>
Effect.gen(function* () {
const minValue = yield* self.networkAddressAsBigint;
const maxValue = yield* self.broadcastAddressAsBigint;
return Function.pipe(
Stream.iterate(minValue, (x) => IPv6BigintBrand(x + 1n)),
Stream.takeWhile((n) => n <= maxValue),
Stream.flatMap((value) => Schema.encode(IPv6Bigint)({ value, family: "ipv6" })),
Stream.mapEffect(Schema.decode(IPv6))
);
}).pipe(Stream.unwrap),
});
}
/**
* The total number of addresses in the range given by this address' subnet.
*
* @since 1.0.0
*/
public get total(): Effect.Effect<bigint, ParseResult.ParseError, never> {
return Effect.gen(this, function* () {
const minValue: bigint = yield* this.networkAddressAsBigint;
const maxValue: bigint = yield* this.broadcastAddressAsBigint;
return maxValue - minValue + 1n;
});
}
/**
* Finds the smallest CIDR block that contains all the given IP addresses.
*
* @since 1.0.0
*/
public static readonly cidrBlockForRange = <_Family extends Family>(
inputs: _Family extends IPv4Family ? Array.NonEmptyReadonlyArray<IPv4> : Array.NonEmptyReadonlyArray<IPv6>
): _Family extends IPv4Family
? Effect.Effect<CidrBlockBase<"ipv4">, ParseResult.ParseError, never>
: Effect.Effect<CidrBlockBase<"ipv6">, ParseResult.ParseError, never> =>
Effect.gen(function* () {
const bigIntMinAndMax = (args: Array.NonEmptyReadonlyArray<bigint>) => {
return args.reduce(
([min, max], e) => {
return [e < min ? e : min, e > max ? e : max] as const;
},
[args[0], args[0]] as const
);
};
const bigints = yield* Function.pipe(
inputs as Array.NonEmptyReadonlyArray<IPv4 | IPv6>,
Array.map((address) =>
address.family === "ipv4"
? Schema.decode(IPv4Bigint)(address.ip)
: Schema.decode(IPv6Bigint)(address.ip)
),
Array.map((x) => x as Effect.Effect<IPv4Bigint | IPv6Bigint, ParseResult.ParseError, never>),
Array.map(Effect.map(({ value }) => value)),
Effect.all
);
const bits = inputs[0].family === "ipv4" ? 32 : 128;
const [min, max] = bigIntMinAndMax(bigints);
const leadingZerosInMin = bits - min.toString(2).length;
const leadingZerosInMax = bits - max.toString(2).length;
const cidrMask = Math.min(leadingZerosInMin, leadingZerosInMax);
const cidrAddress =
inputs[0].family === "ipv4"
? yield* Schema.encode(IPv4Bigint)({ value: IPv4BigintBrand(min), family: "ipv4" })
: yield* Schema.encode(IPv6Bigint)({ value: IPv6BigintBrand(min), family: "ipv6" });
return yield* Schema.decode(CidrBlockFromString)(`${cidrAddress}/${cidrMask}`);
}) as _Family extends IPv4Family
? Effect.Effect<CidrBlockBase<"ipv4">, ParseResult.ParseError, never>
: Effect.Effect<CidrBlockBase<"ipv6">, ParseResult.ParseError, never>;
}
/**
* @since 1.0.0
* @category Api interface
*/
export type $IPv4CidrBlock = Schema.Annotable<
$IPv4CidrBlock,
CidrBlockBase<"ipv4">,
{
readonly address: string;
readonly mask: number;
},
never
>;
// export interface $IPv4CidrBlock
// extends Schema.transformOrFail<
// Schema.Struct<{
// address: $IPv4;
// mask: $IPv4CidrMask;
// }>,
// typeof CidrBlockBase<"ipv4">,
// never
// > {}
/**
* @since 1.0.0
* @category Decoded types
*/
export type IPv4CidrBlock = CidrBlockBase<"ipv4">;
/**
* @since 1.0.0
* @category Encoded types
*/
export type IPv4CidrBlockEncoded = Schema.Schema.Encoded<$IPv4CidrBlock>;
/**
* @since 1.0.0
* @category Schemas
*/
export const IPv4CidrBlock: $IPv4CidrBlock = Schema.transformOrFail(
Schema.Struct({ address: IPv4, mask: IPv4CidrMask }),
CidrBlockBase,
{
encode: (data) =>
Effect.gen(function* () {
const address = yield* Schema.decode(IPv4)(data.address);
const mask = yield* Schema.decode(IPv4CidrMask)(data.mask);
return { address, mask } as const;
}).pipe(Effect.mapError(({ issue }) => issue)),
decode: (data) => ParseResult.succeed({ address: data.address.ip, mask: data.mask }),
}
).annotations({
identifier: "IPv4CidrBlock",
description: "An ipv4 cidr block",
});
/**
* @since 1.0.0
* @category Api interface
*/
export type $IPv4CidrBlockFromString = Schema.Annotable<
$IPv4CidrBlockFromString,
CidrBlockBase<"ipv4">,
`${string}/${number}`,
never
>;
/**
* @since 1.0.0
* @category Decoded types
*/
export type IPv4CidrBlockFromString = Schema.Schema.Type<$IPv4CidrBlockFromString>;
/**
* @since 1.0.0
* @category Encoded types
*/
export type IPv4CidrBlockFromStringEncoded = Schema.Schema.Encoded<$IPv4CidrBlockFromString>;
/**
* A schema that transforms a `string` into a `CidrBlock`.
*
* @since 1.0.0
* @category Schemas
*/
export const IPv4CidrBlockFromString: $IPv4CidrBlockFromString = Schema.transform(
Schema.TemplateLiteral(Schema.String, Schema.Literal("/"), Schema.Number),
IPv4CidrBlock,
{
decode: (str) => {
const [address, mask] = internal.splitLiteral(str, "/");
return { address, mask: Number.parseInt(mask, 10) } as const;
},
encode: ({ address, mask }) => `${address}/${mask}` as const,
}
).annotations({
identifier: "IPv4CidrBlockFromString",
description: "An ipv4 cidr block from string",
});
/**
* @since 1.0.0
* @category Api interface
*/
export type $IPv6CidrBlock = Schema.transformOrFail<
Schema.Struct<{
address: $IPv6;
mask: $IPv6CidrMask;
}>,
typeof CidrBlockBase<"ipv6">,
never
>;
/**
* @since 1.0.0
* @category Decoded types
*/
export type IPv6CidrBlock = CidrBlockBase<"ipv6">;
/**
* @since 1.0.0
* @category Encoded types
*/
export type IPv6CidrBlockEncoded = Schema.Schema.Encoded<$IPv6CidrBlock>;
/**
* @since 1.0.0
* @category Schemas
*/
export const IPv6CidrBlock: $IPv6CidrBlock = Schema.transformOrFail(
Schema.Struct({ address: IPv6, mask: IPv6CidrMask }),
CidrBlockBase,
{
encode: (data) =>
Effect.gen(function* () {
const address = yield* Schema.decode(IPv6)(data.address);
const mask = yield* Schema.decode(IPv6CidrMask)(data.mask);
return { address, mask } as const;
}).pipe(Effect.mapError(({ issue }) => issue)),
decode: (data) => ParseResult.succeed({ address: data.address.ip, mask: data.mask }),
}
).annotations({
identifier: "IPv6CidrBlock",
description: "An ipv6 cidr block",
});
/**
* @since 1.0.0
* @category Api interface
*/
export type $IPv6CidrBlockFromString = Schema.Annotable<
$IPv6CidrBlockFromString,
CidrBlockBase<"ipv6">,
`${string}/${number}`,
never
>;
/**
* @since 1.0.0
* @category Decoded types
*/
export type IPv6CidrBlockFromString = Schema.Schema.Type<$IPv6CidrBlockFromString>;
/**
* @since 1.0.0
* @category Encoded types
*/
export type IPv6CidrBlockFromStringEncoded = Schema.Schema.Encoded<$IPv6CidrBlockFromString>;
/**
* A schema that transforms a `string` into a `CidrBlock`.
*
* @since 1.0.0
* @category Schemas
*/
export const IPv6CidrBlockFromString: $IPv6CidrBlockFromString = Schema.transform(
Schema.TemplateLiteral(Schema.String, Schema.Literal("/"), Schema.Number),
IPv6CidrBlock,
{
decode: (str) => {
const [address, mask] = internal.splitLiteral(str, "/");
return { address, mask: Number.parseInt(mask, 10) } as const;
},
encode: ({ address, mask }) => `${address}/${mask}` as const,
}
).annotations({
identifier: "IPv6CidrBlockFromString",
description: "An ipv6 cidr block from string",
});
/**
* @since 1.0.0
* @category Api interface
*/
export type $CidrBlock = Schema.Union<[$IPv4CidrBlock, $IPv6CidrBlock]>;
/**
* @since 1.0.0
* @category Schemas
*/
export const CidrBlock: $CidrBlock = Schema.Union(IPv4CidrBlock, IPv6CidrBlock);
/**
* @since 1.0.0
* @category Api interface
*/
export type $CidrBlockFromString = Schema.Annotable<
$CidrBlockFromString,
CidrBlockBase<"ipv4"> | CidrBlockBase<"ipv6">,
`${string}/${number}`,
never
>;
/**
* @since 1.0.0
* @category Decoded types
*/
export type CidrBlockFromString = Schema.Schema.Type<$CidrBlockFromString>;
/**
* @since 1.0.0
* @category Encoded types
*/
export type CidrBlockFromStringEncoded = Schema.Schema.Encoded<$CidrBlockFromString>;
/**
* A schema that transforms a `string` into a `CidrBlock`.
*
* @since 1.0.0
* @category Schemas
*/
export const CidrBlockFromString: $CidrBlockFromString = Schema.transform(
Schema.TemplateLiteral(Schema.String, Schema.Literal("/"), Schema.Number),
CidrBlock,
{
decode: (str) => {
const [address, mask] = internal.splitLiteral(str, "/");
return { address, mask: Number.parseInt(mask, 10) } as const;
},
encode: ({ address, mask }) => `${address}/${mask}` as const,
}
).annotations({
identifier: "CidrBlockFromString",
description: "A cidr block",
});
/**
* @since 1.0.0
* @category Api interface
*/
export type $IPv4Endpoint = Schema.Annotable<
$IPv4Endpoint,
{ readonly address: IPv4; readonly natPort: PortBrand; readonly listenPort: PortBrand },
| `${string}:${number}`
| `${string}:${number}:${number}`
| { readonly ip: string; readonly port: number; readonly family: IPv4Family }
| { readonly ip: string; readonly natPort: number; readonly listenPort: number; readonly family: IPv4Family },
never
>;
/**
* @since 1.0.0
* @category Decoded types
*/
export type IPv4Endpoint = Schema.Schema.Type<$IPv4Endpoint>;
/**
* @since 1.0.0
* @category Encoded types
*/
export type IPv4EndpointEncoded = Schema.Schema.Encoded<$IPv4Endpoint>;
/**
* An IPv4 wireguard endpoint, which consists of an IPv4 address followed by a
* nat port then an optional local port. If only one port is provided, it is
* assumed that the nat port and listen port are the same.
*
* @since 1.0.0
* @category Schemas
* @example
* import * as Schema from "effect/Schema";
* import { IPv4Endpoint } from "the-wireguard-effect/InternetSchemas";
*
* const decodeEndpoint = Schema.decodeSync(IPv4Endpoint);
* const endpoint1 = decodeEndpoint("1.2.3.4:51820");
* const endpoint2 = decodeEndpoint("1.2.3.4:51820:41820");
*
* const endpoint3 = decodeEndpoint({
* ip: "1.2.3.4",
* port: 51820,
* family: "ipv4",
* });
*
* const endpoint4 = decodeEndpoint({
* ip: "1.2.3.4",
* natPort: 51820,
* listenPort: 41820,
* family: "ipv4",
* });
*/
export const IPv4Endpoint: $IPv4Endpoint = Schema.transform(
Schema.Union(
Schema.Struct({ ip: Schema.String, port: Schema.Number, family: IPv4Family }),
Schema.Struct({ ip: Schema.String, natPort: Schema.Number, listenPort: Schema.Number, family: IPv4Family }),
Schema.TemplateLiteral(Schema.String, Schema.Literal(":"), Schema.Number),
Schema.TemplateLiteral(Schema.String, Schema.Literal(":"), Schema.Number, Schema.Literal(":"), Schema.Number)
),
Schema.Struct({ address: IPv4, natPort: Port, listenPort: Port }),
{
decode: (data) => {
const isObjectInput = !Predicate.isString(data);
const [ip, natPort, listenPort] = isObjectInput
? ([
data.ip,
"natPort" in data ? (`${data.natPort}` as const) : (`${data.port}` as const),
"listenPort" in data ? (`${data.listenPort}` as const) : undefined,
] as const)
: internal.splitLiteral(data, ":");
const natPortParsed = Number.parseInt(natPort, 10);
const listenPortParsed = Predicate.isNotUndefined(listenPort)
? Number.parseInt(listenPort, 10)
: natPortParsed;
return { address: ip, natPort: natPortParsed, listenPort: listenPortParsed };
},
encode: ({ address, listenPort, natPort }) => `${address}:${natPort}:${listenPort}` as const,
}
).annotations({
identifier: "IPv4Endpoint",
description: "An ipv4 wireguard endpoint",
});
/**
* @since 1.0.0
* @category Api interface
*/
export type $IPv6Endpoint = Schema.Annotable<
$IPv6Endpoint,
{ readonly address: IPv6; readonly natPort: PortBrand; readonly listenPort: PortBrand },
| `[${string}]:${number}`
| `[${string}]:${number}:${number}`
| { readonly ip: string; readonly port: number; family: IPv6Family }
| { readonly ip: string; readonly natPort: number; readonly listenPort: number; family: IPv6Family },
never
>;
/**
* @since 1.0.0
* @category Decoded types
*/
export type IPv6Endpoint = Schema.Schema.Type<$IPv6Endpoint>;
/**
* @since 1.0.0
* @category Encoded types
*/
export type IPv6EndpointEncoded = Schema.Schema.Encoded<$IPv6Endpoint>;
/**
* An IPv6 wireguard endpoint, which consists of an IPv6 address in square
* brackets followed by a nat port then an optional local port. If only one port
* is provided, it is assumed that the nat port and listen port are the same.
*
* @since 1.0.0
* @category Schemas
* @example
* import * as Schema from "effect/Schema";
* import { IPv6Endpoint } from "the-wireguard-effect/InternetSchemas";
*
* const decodeEndpoint = Schema.decodeSync(IPv6Endpoint);
* const endpoint1 = decodeEndpoint(
* "[2001:0db8:85a3:0000:0000:8a2e:0370:7334]:51820"
* );
* const endpoint2 = decodeEndpoint(
* "[2001:0db8:85a3:0000:0000:8a2e:0370:7334]:51820:41820"
* );
*
* const endpoint3 = decodeEndpoint({
* ip: "2001:0db8:85a3:0000:0000:8a2e:0370:7334",
* port: 51820,
* family: "ipv6",
* });
*
* const endpoint4 = decodeEndpoint({
* ip: "2001:0db8:85a3:0000:0000:8a2e:0370:7334",
* natPort: 51820,
* listenPort: 41820,
* family: "ipv6",
* });
*/
export const IPv6Endpoint: $IPv6Endpoint = Schema.transform(
Schema.Union(
Schema.Struct({ ip: Schema.String, port: Schema.Number, family: IPv6Family }),
Schema.Struct({ ip: Schema.String, natPort: Schema.Number, listenPort: Schema.Number, family: IPv6Family }),
Schema.TemplateLiteral(
Schema.Literal("["),
Schema.String,
Schema.Literal("]"),
Schema.Literal(":"),
Schema.Number
),
Schema.TemplateLiteral(
Schema.Literal("["),
Schema.String,
Schema.Literal("]"),
Schema.Literal(":"),
Schema.Number,
Schema.Literal(":"),
Schema.Number
)
),
Schema.Struct({ address: IPv6, natPort: Port, listenPort: Port }),
{
decode: (data) => {
const isObjectInput = !Predicate.isString(data);
const [ip, natPort, listenPort] = isObjectInput
? ([
data.ip,
"natPort" in data ? (`${data.natPort}` as const) : (`${data.port}` as const),
"listenPort" in data ? (`${data.listenPort}` as const) : undefined,
] as const)
: ([
internal.splitLiteral(data, "]")[0].slice(1),
...internal.tail(internal.splitLiteral(internal.splitLiteral(data, "]")[1], ":")),
] as const);
const natPortParsed = Number.parseInt(natPort, 10);
const listenPortParsed = Predicate.isNotUndefined(listenPort)
? Number.parseInt(listenPort, 10)
: natPortParsed;
return { address: ip.slice(1), natPort: natPortParsed, listenPort: listenPortParsed } as const;
},
encode: ({ address, listenPort, natPort }) => `[${address}]:${natPort}:${listenPort}` as const,
}
).annotations({
identifier: "IPv6Endpoint",
description: "An ipv6 wireguard endpoint",
});
/**
* @since 1.0.0
* @category Api interface
*/
export type $HostnameEndpoint = Schema.Annotable<
$HostnameEndpoint,
{ readonly host: string; readonly natPort: PortBrand; readonly listenPort: PortBrand },
| `${string}:${number}`
| `${string}:${number}:${number}`
| { readonly host: string; readonly port: number }
| { readonly host: string; readonly natPort: number; readonly listenPort: number },
never
>;
/**
* @since 1.0.0
* @category Decoded types
*/
export type HostnameEndpoint = Schema.Schema.Type<$HostnameEndpoint>;
/**
* @since 1.0.0
* @category Encoded types
*/
export type HostnameEndpointEncoded = Schema.Schema.Encoded<$HostnameEndpoint>;
/**
* A hostname wireguard endpoint, which consists of a hostname followed by a\
* Nat port then an optional local port. If only one port is provided, it is
* assumed that the nat port and listen port are the same.
*
* @since 1.0.0
* @category Schemas
*/
export const HostnameEndpoint: $HostnameEndpoint = Schema.transform(
Schema.Union(
Schema.Struct({ host: Schema.String, port: Schema.Number }),
Schema.Struct({ host: Schema.String, natPort: Schema.Number, listenPort: Schema.Number }),
Schema.TemplateLiteral(Schema.String, Schema.Literal(":"), Schema.Number),
Schema.TemplateLiteral(Schema.String, Schema.Literal(":"), Schema.Number, Schema.Literal(":"), Schema.Number)
),
Schema.Struct({ host: Schema.String, natPort: Port, listenPort: Port }),
{
decode: (data) => {
const isObjectInput = !Predicate.isString(data);
const [host, natPort, listenPort] = isObjectInput
? ([
data.host,
"natPort" in data ? (`${data.natPort}` as const) : (`${data.port}` as const),
"listenPort" in data ? (`${data.listenPort}` as const) : undefined,
] as const)
: internal.splitLiteral(data, ":");
const natPortParsed = Number.parseInt(natPort, 10);
const listenPortParsed = Predicate.isNotUndefined(listenPort)
? Number.parseInt(listenPort, 10)
: natPortParsed;
return { host, natPort: natPortParsed, listenPort: listenPortParsed };
},
encode: ({ host, listenPort, natPort }) => `${host}:${natPort}:${listenPort}` as const,
}
).annotations({
identifier: "HostnameEndpoint",
description: "A hostname endpoint",
});
/**
* @since 1.0.0
* @category Api interface
*/
export type $Endpoint = Schema.Union<[$IPv4Endpoint, $IPv6Endpoint, $HostnameEndpoint]>;
/**
* @since 1.0.0
* @category Decoded types
*/
export type Endpoint = Schema.Schema.Type<$Endpoint>;
/**
* @since 1.0.0
* @category Encoded types
*/
export type EndpointEncoded = Schema.Schema.Encoded<$Endpoint>;
/**
* A wireguard endpoint, which is either an IPv4 or IPv6 endpoint.
*
* @since 1.0.0
* @category Schemas
* @example
* import * as Schema from "effect/Schema";
*
* import { Endpoint } from "the-wireguard-effect/InternetSchemas";
*
* const decodeEndpoint = Schema.decodeSync(Endpoint);
* const endpoint1 = decodeEndpoint("1.2.3.4:51820");
* const endpoint2 = decodeEndpoint("1.2.3.4:51820:41820");
*
* const endpoint3 = decodeEndpoint({
* ip: "1.2.3.4",
* port: 51820,
* family: "ipv4",
* });
*
* const endpoint4: Endpoint = decodeEndpoint({
* ip: "1.2.3.4",
* natPort: 51820,
* listenPort: 41820,
* family: "ipv4",
* });
*
* const endpoint5 = decodeEndpoint(
* "[2001:0db8:85a3:0000:0000:8a2e:0370:7334]:51820"
* );
* const endpoint6 = decodeEndpoint(
* "[2001:0db8:85a3:0000:0000:8a2e:0370:7334]:51820:41820"
* );
*
* const endpoint7 = decodeEndpoint({
* ip: "2001:0db8:85a3:0000:0000:8a2e:0370:7334",
* port: 51820,
* family: "ipv6",
* });
*
* const endpoint8: Endpoint = decodeEndpoint({
* ip: "2001:0db8:85a3:0000:0000:8a2e:0370:7334",
* natPort: 51820,
* listenPort: 41820,
* family: "ipv6",
* });
*
* @see {@link IPv4Endpoint}
* @see {@link IPv6Endpoint}
* @see {@link HostnameEndpoint}
*/
export const Endpoint: $Endpoint = Schema.Union(IPv4Endpoint, IPv6Endpoint, HostnameEndpoint).annotations({
identifier: "Endpoint",
description: "An ipv4, ipv6, or hostname wireguard endpoint",
});
/**
* @since 1.0.0
* @category Api interface
*/
export type $IPv4SetupData = Schema.Tuple<[$IPv4Endpoint, $IPv4]>;
/**
* @since 1.0.0
* @category Decoded types
*/
export type IPv4SetupData = Schema.Schema.Type<$IPv4SetupData>;
/**
* @since 1.0.0
* @category Encoded types
*/
export type IPv4SetupDataEncoded = Schema.Schema.Encoded<$IPv4SetupData>;
/**
* A wireguard setup data, which consists of an endpoint followed by an address.
*
* @since 1.0.0
* @category Schemas
* @example
* import * as Schema from "effect/Schema";
* import { SetupData } from "the-wireguard-effect/InternetSchemas";
*
* const decodeSetupData = Schema.decodeSync(SetupData);
* const setupData = decodeSetupData(["1.1.1.1:51280", "10.0.0.1"]);
*
* @see {@link IPv4}
* @see {@link IPv4EndpointSchema}
*/
export const IPv4SetupData: $IPv4SetupData = Schema.Tuple(IPv4Endpoint, IPv4).annotations({
identifier: "SetupData",
description: "A wireguard setup data",
});
/**
* @since 1.0.0
* @category Api interface
*/
export type $IPv6SetupData = Schema.Tuple<[$IPv6Endpoint, $IPv6]>;
/**
* @since 1.0.0
* @category Decoded types
*/
export type IPv6SetupData = Schema.Schema.Type<$IPv6SetupData>;
/**
* @since 1.0.0
* @category Encoded types
*/
export type IPv6SetupDataEncoded = Schema.Schema.Encoded<$IPv6SetupData>;
/**
* A wireguard setup data, wh