the-wireguard-effect
Version:
Cross platform wireguard api client for nodejs built on wireguard-go with effect-ts
1,076 lines • 34.6 kB
JavaScript
/**
* 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 /*#__PURE__*/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 /*#__PURE__*/Schema.compose(Schema.NumberFromString, DurationFromSeconds).annotations({
identifier: "DurationFromSecondsString",
description: "A duration from a string of seconds"
}) {}
/**
* @since 1.0.0
* @category Branded constructors
*/
export const PortBrand = /*#__PURE__*/Brand.nominal();
/**
* 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 = /*#__PURE__*/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 Schemas
*/
export const IPv4Family = /*#__PURE__*/Schema.Literal("ipv4").annotations({
identifier: "IPv4Family",
description: "An ipv4 family"
});
/**
* @since 1.0.0
* @category Branded constructors
*/
export const IPv4Brand = /*#__PURE__*/Brand.nominal();
/**
* 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 = /*#__PURE__*/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"
})
}).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 constructors
*/
export const IPv4BigintBrand = /*#__PURE__*/Brand.nominal();
/**
* 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 = /*#__PURE__*/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 = [];
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"
}), Effect.succeed)
}).annotations({
identifier: "IPv4Bigint",
description: "An ipv4 address as a bigint"
});
/**
* @since 1.0.0
* @category Schemas
*/
export const IPv6Family = /*#__PURE__*/Schema.Literal("ipv6").annotations({
identifier: "IPv6Family",
description: "An ipv6 family"
});
/**
* @since 1.0.0
* @category Branded constructors
*/
export const IPv6Brand = /*#__PURE__*/Brand.nominal();
/**
* 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 = /*#__PURE__*/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"
})
}).annotations({
identifier: "IPv6",
description: "An ipv6 address"
});
/**
* @since 1.0.0
* @category Branded constructors
*/
export const IPv6BigintBrand = /*#__PURE__*/Brand.nominal();
/**
* 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 = /*#__PURE__*/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) {
return parseInt(octet, 16).toString(16).padStart(4, "0");
}
let groups = [];
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 => 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"
});
}
}).annotations({
identifier: "IPv6Bigint",
description: "An ipv6 address as a bigint"
});
/**
* @since 1.0.0
* @category Schemas
* @see {@link IPv4Family}
* @see {@link IPv6Family}
*/
export const Family = /*#__PURE__*/Schema.Union(IPv4Family, IPv6Family).annotations({
identifier: "Family",
description: "An ipv4 or ipv6 family"
});
/**
* 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 = /*#__PURE__*/Schema.Union(IPv4, IPv6).annotations({
identifier: "Address",
description: "An ipv4 or ipv6 address"
});
/**
* An IP address as a bigint.
*
* @since 1.0.0
* @category Schemas
*/
export const AddressBigint = /*#__PURE__*/Schema.Union(IPv4Bigint, IPv6Bigint).annotations({
identifier: "AddressBigint",
description: "An ipv4 or ipv6 address as a bigint"
});
/**
* @since 1.0.0
* @category Branded constructors
*/
export const IPv4CidrMaskBrand = /*#__PURE__*/Brand.nominal();
/**
* 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 = /*#__PURE__*/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 constructors
*/
export const IPv6CidrMaskBrand = /*#__PURE__*/Brand.nominal();
/**
* 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 = /*#__PURE__*/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 extends /*#__PURE__*/Schema.Class("CidrBlockMixin")({
address: Address,
mask: /*#__PURE__*/Schema.Union(IPv4CidrMask, IPv6CidrMask)
}) {
/** @since 1.0.0 */
family = this.address.family;
/** @internal */
onFamily({
onIPv4,
onIPv6
}) {
const isIPv4 = () => this.family === "ipv4";
const isIPv6 = () => this.family === "ipv6";
if (isIPv4()) {
return onIPv4(this);
} else if (isIPv6()) {
return onIPv6(this);
} else {
return Function.absurd(this.family);
}
}
/**
* The first address in the range given by this address' subnet, often
* referred to as the Network Address.
*
* @since 1.0.0
*/
get networkAddressAsBigint() {
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
*/
networkAddress() {
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
*/
get broadcastAddressAsBigint() {
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
*/
broadcastAddress() {
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
*/
get range() {
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
*/
get total() {
return Effect.gen(this, function* () {
const minValue = yield* this.networkAddressAsBigint;
const maxValue = yield* this.broadcastAddressAsBigint;
return maxValue - minValue + 1n;
});
}
/**
* Finds the smallest CIDR block that contains all the given IP addresses.
*
* @since 1.0.0
*/
static cidrBlockForRange = inputs => Effect.gen(function* () {
const bigIntMinAndMax = args => {
return args.reduce(([min, max], e) => {
return [e < min ? e : min, e > max ? e : max];
}, [args[0], args[0]]);
};
const bigints = yield* Function.pipe(inputs, Array.map(address => address.family === "ipv4" ? Schema.decode(IPv4Bigint)(address.ip) : Schema.decode(IPv6Bigint)(address.ip)), Array.map(x => x), 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}`);
});
}
/**
* @since 1.0.0
* @category Schemas
*/
export const IPv4CidrBlock = /*#__PURE__*/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
};
}).pipe(Effect.mapError(({
issue
}) => issue)),
decode: data => ParseResult.succeed({
address: data.address.ip,
mask: data.mask
})
}).annotations({
identifier: "IPv4CidrBlock",
description: "An ipv4 cidr block"
});
/**
* A schema that transforms a `string` into a `CidrBlock`.
*
* @since 1.0.0
* @category Schemas
*/
export const IPv4CidrBlockFromString = /*#__PURE__*/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)
};
},
encode: ({
address,
mask
}) => `${address}/${mask}`
}).annotations({
identifier: "IPv4CidrBlockFromString",
description: "An ipv4 cidr block from string"
});
/**
* @since 1.0.0
* @category Schemas
*/
export const IPv6CidrBlock = /*#__PURE__*/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
};
}).pipe(Effect.mapError(({
issue
}) => issue)),
decode: data => ParseResult.succeed({
address: data.address.ip,
mask: data.mask
})
}).annotations({
identifier: "IPv6CidrBlock",
description: "An ipv6 cidr block"
});
/**
* A schema that transforms a `string` into a `CidrBlock`.
*
* @since 1.0.0
* @category Schemas
*/
export const IPv6CidrBlockFromString = /*#__PURE__*/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)
};
},
encode: ({
address,
mask
}) => `${address}/${mask}`
}).annotations({
identifier: "IPv6CidrBlockFromString",
description: "An ipv6 cidr block from string"
});
/**
* @since 1.0.0
* @category Schemas
*/
export const CidrBlock = /*#__PURE__*/Schema.Union(IPv4CidrBlock, IPv6CidrBlock);
/**
* A schema that transforms a `string` into a `CidrBlock`.
*
* @since 1.0.0
* @category Schemas
*/
export const CidrBlockFromString = /*#__PURE__*/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)
};
},
encode: ({
address,
mask
}) => `${address}/${mask}`
}).annotations({
identifier: "CidrBlockFromString",
description: "A cidr block"
});
/**
* 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 = /*#__PURE__*/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}` : `${data.port}`, "listenPort" in data ? `${data.listenPort}` : undefined] : 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}`
}).annotations({
identifier: "IPv4Endpoint",
description: "An ipv4 wireguard endpoint"
});
/**
* 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 = /*#__PURE__*/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}` : `${data.port}`, "listenPort" in data ? `${data.listenPort}` : undefined] : [internal.splitLiteral(data, "]")[0].slice(1), ...internal.tail(internal.splitLiteral(internal.splitLiteral(data, "]")[1], ":"))];
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
};
},
encode: ({
address,
listenPort,
natPort
}) => `[${address}]:${natPort}:${listenPort}`
}).annotations({
identifier: "IPv6Endpoint",
description: "An ipv6 wireguard endpoint"
});
/**
* 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 = /*#__PURE__*/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}` : `${data.port}`, "listenPort" in data ? `${data.listenPort}` : undefined] : 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}`
}).annotations({
identifier: "HostnameEndpoint",
description: "A hostname 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 = /*#__PURE__*/Schema.Union(IPv4Endpoint, IPv6Endpoint, HostnameEndpoint).annotations({
identifier: "Endpoint",
description: "An ipv4, ipv6, or hostname wireguard endpoint"
});
/**
* 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 = /*#__PURE__*/Schema.Tuple(IPv4Endpoint, IPv4).annotations({
identifier: "SetupData",
description: "A wireguard setup data"
});
/**
* 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 IPv6}
* @see {@link IPv6EndpointSchema}
*/
export const IPv6SetupData = /*#__PURE__*/Schema.Tuple(IPv6Endpoint, IPv6).annotations({
identifier: "SetupData",
description: "A wireguard setup data"
});
/**
* A wireguard setup data, which consists of an endpoint followed by an address.
*
* @since 1.0.0
* @category Schemas
* @see {@link IPv4}
* @see {@link HostnameEndpoint}
*/
export const HostnameIPv4SetupData = /*#__PURE__*/Schema.Tuple(HostnameEndpoint, IPv4).annotations({
identifier: "HostnameIPv4SetupData",
description: "A wireguard hostname+ipv4 setup data"
});
/**
* A wireguard setup data, which consists of an endpoint followed by an address.
*
* @since 1.0.0
* @category Schemas
* @see {@link IPv6}
* @see {@link HostnameEndpoint}
*/
export const HostnameIPv6SetupData = /*#__PURE__*/Schema.Tuple(HostnameEndpoint, IPv6).annotations({
identifier: "HostnameIPv6SetupData",
description: "A wireguard hostname+ipv6 setup data"
});
/**
* 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 Address}
* @see {@link Endpoint}
*/
export const SetupData = /*#__PURE__*/Schema.Union(IPv4SetupData, IPv6SetupData, HostnameIPv4SetupData, HostnameIPv6SetupData).annotations({
identifier: "SetupData",
description: "A wireguard setup data"
});
//# sourceMappingURL=InternetSchemas.js.map