/**
 * Tools to help generate wireguard configs for common situations.
 *
 * @since 1.0.0
 */
import * as Array from "effect/Array";
import * as Effect from "effect/Effect";
import * as ParseResult from "effect/ParseResult";
import * as Record from "effect/Record";
import * as InternetSchemas from "./InternetSchemas.js";
import * as WireguardConfig from "./WireguardConfig.js";
import * as WireguardErrors from "./WireguardErrors.js";
import * as WireguardKey from "./WireguardKey.js";
/** A node in the network can either have an ipv4 or ipv6 address. */
type WireguardIPv4RoamingPeer = InternetSchemas.IPv4;
type WireguardIPv6RoamingPeer = InternetSchemas.IPv6;
type WireguardRoamingPeer = WireguardIPv4RoamingPeer | WireguardIPv6RoamingPeer;
/**
 * A server in the network can either have an ipv4 address pool or ipv6 address
 * pool.
 */
type WireguardIPv4Server = InternetSchemas.IPv4SetupData | InternetSchemas.HostnameIPv4SetupData;
type WireguardIPv6Server = InternetSchemas.IPv6SetupData | InternetSchemas.HostnameIPv6SetupData;
type WireguardServer = WireguardIPv4Server | WireguardIPv6Server;
/**
 * Every node in the network must have a public+private key pair and possibly a
 * preshare key as well.
 */
type Keys = {
    publicKey: WireguardKey.WireguardKey;
    privateKey: WireguardKey.WireguardKey;
    preshareKey?: WireguardKey.WireguardKey;
};
/**
 * The nodes in the network must be homogeneous (either all ipv4 or all ipv6).
 * If you want dual stack, you must have two separate networks.
 */
type WireguardIPv4Node = WireguardIPv4Server | WireguardIPv4RoamingPeer;
type WireguardIPv6Node = WireguardIPv6Server | WireguardIPv6RoamingPeer;
/**
 * Base layer containing just the nodes in the network.
 *
 * @since 1.0.0
 * @category WireguardGenerate
 */
export type NodesLayer<Nodes extends readonly [node1: WireguardIPv4Node, node2: WireguardIPv4Node, ...rest: Array<WireguardIPv4Node>] | readonly [node1: WireguardIPv6Node, node2: WireguardIPv6Node, ...rest: Array<WireguardIPv6Node>]> = {
    nodes: Nodes;
    wireguardNetworkCidr: Nodes[0] extends WireguardIPv4Node ? InternetSchemas.IPv4CidrBlock : Nodes[0] extends WireguardIPv6Node ? InternetSchemas.IPv6CidrBlock : never;
};
/**
 * Layer containing the keys for each node in the network.
 *
 * @since 1.0.0
 * @category WireguardGenerate
 */
export type keysLayer<Nodes extends readonly [node1: WireguardIPv4Node, node2: WireguardIPv4Node, ...rest: Array<WireguardIPv4Node>] | readonly [node1: WireguardIPv6Node, node2: WireguardIPv6Node, ...rest: Array<WireguardIPv6Node>]> = NodesLayer<Nodes> & {
    keys: Record.ReadonlyRecord<Extract<Nodes[number], WireguardRoamingPeer>["ip"] | Extract<Nodes[number], WireguardServer>[1]["ip"], Keys>;
};
/**
 * Layer containing the connections for each node in the network.
 *
 * @since 1.0.0
 * @category WireguardGenerate
 */
export type ConnectionsLayer<Nodes extends readonly [node1: WireguardIPv4Node, node2: WireguardIPv4Node, ...rest: Array<WireguardIPv4Node>] | readonly [node1: WireguardIPv6Node, node2: WireguardIPv6Node, ...rest: Array<WireguardIPv6Node>]> = keysLayer<Nodes> & {
    connections: Record.ReadonlyRecord<Extract<Nodes[number], WireguardRoamingPeer>["ip"] | Extract<Nodes[number], WireguardServer>[1]["ip"], Array.NonEmptyReadonlyArray<Extract<Nodes[number], WireguardRoamingPeer>["ip"] | Extract<Nodes[number], WireguardServer>[1]["ip"]>>;
};
/**
 * Layer containing the allowed IPs for each node in the network.
 *
 * @since 1.0.0
 * @category WireguardGenerate
 */
export type AllowedIPsLayer<Nodes extends readonly [node1: WireguardIPv4Node, node2: WireguardIPv4Node, ...rest: Array<WireguardIPv4Node>] | readonly [node1: WireguardIPv6Node, node2: WireguardIPv6Node, ...rest: Array<WireguardIPv6Node>]> = ConnectionsLayer<Nodes> & {
    allowedIPs: Record.ReadonlyRecord<Extract<Nodes[number], WireguardRoamingPeer>["ip"] | Extract<Nodes[number], WireguardServer>[1]["ip"], Array.NonEmptyReadonlyArray<{
        block: InternetSchemas.CidrBlockFromStringEncoded;
        from: Extract<Nodes[number], WireguardRoamingPeer>["ip"] | Extract<Nodes[number], WireguardServer>[1]["ip"];
    }>>;
};
/**
 * The final network type.
 *
 * @since 1.0.0
 * @category WireguardGenerate
 */
export type WireguardNetwork<Nodes extends readonly [node1: WireguardIPv4Node, node2: WireguardIPv4Node, ...rest: Array<WireguardIPv4Node>] | readonly [node1: WireguardIPv6Node, node2: WireguardIPv6Node, ...rest: Array<WireguardIPv6Node>]> = AllowedIPsLayer<Nodes>;
/**
 * Generates private+public keys for all nodes in the network.
 *
 * @since 1.0.0
 * @category Key Transformers
 */
export declare const generateKeys: <Nodes extends readonly [node1: WireguardIPv4Node, node2: WireguardIPv4Node, ...rest: Array<WireguardIPv4Node>] | readonly [node1: WireguardIPv6Node, node2: WireguardIPv6Node, ...rest: Array<WireguardIPv6Node>]>(nodesLayer: NodesLayer<Nodes>) => keysLayer<Nodes>;
/**
 * Generates preshare keys for all nodes in the network.
 *
 * @since 1.0.0
 * @category Key Transformers
 */
export declare const addPreshareKeys: <Nodes extends readonly [node1: WireguardIPv4Node, node2: WireguardIPv4Node, ...rest: Array<WireguardIPv4Node>] | readonly [node1: WireguardIPv6Node, node2: WireguardIPv6Node, ...rest: Array<WireguardIPv6Node>]>(keysLayer: keysLayer<Nodes>) => keysLayer<Nodes>;
/**
 * Generates connections in a star pattern for all nodes in the network.
 *
 * @since 1.0.0
 * @category Connection Transformers
 */
export declare const generateStarConnections: <Nodes extends readonly [node1: WireguardIPv4Node, node2: WireguardIPv4Node, ...rest: Array<WireguardIPv4Node>] | readonly [node1: WireguardIPv6Node, node2: WireguardIPv6Node, ...rest: Array<WireguardIPv6Node>]>(keysLayer: keysLayer<Nodes>) => ConnectionsLayer<Nodes>;
/**
 * Generates connections in a hub and spoke pattern for all nodes in the
 * network.
 *
 * @since 1.0.0
 * @category Connection Transformers
 */
export declare const generateHubAndSpokeConnections: <Nodes extends readonly [node1: WireguardIPv4Node, node2: WireguardIPv4Node, ...rest: Array<WireguardIPv4Node>] | readonly [node1: WireguardIPv6Node, node2: WireguardIPv6Node, ...rest: Array<WireguardIPv6Node>]>(keysLayer: keysLayer<Nodes>) => ConnectionsLayer<Nodes>;
/**
 * Adds a direct connection between two nodes in the network.
 *
 * @since 1.0.0
 * @category Connection Transformers
 */
export declare const addConnection: (<Nodes extends readonly [node1: WireguardIPv4Node, node2: WireguardIPv4Node, ...rest: Array<WireguardIPv4Node>] | readonly [node1: WireguardIPv6Node, node2: WireguardIPv6Node, ...rest: Array<WireguardIPv6Node>]>(from: Extract<Nodes[number], WireguardRoamingPeer>["ip"] | Extract<Nodes[number], WireguardServer>[1]["ip"], to: Extract<Nodes[number], WireguardRoamingPeer>["ip"] | Extract<Nodes[number], WireguardServer>[1]["ip"]) => (connectionsLayer: ConnectionsLayer<Nodes>) => ConnectionsLayer<Nodes>) & (<Nodes extends readonly [node1: WireguardIPv4Node, node2: WireguardIPv4Node, ...rest: Array<WireguardIPv4Node>] | readonly [node1: WireguardIPv6Node, node2: WireguardIPv6Node, ...rest: Array<WireguardIPv6Node>]>(connectionsLayer: ConnectionsLayer<Nodes>, from: Extract<Nodes[number], WireguardRoamingPeer>["ip"] | Extract<Nodes[number], WireguardServer>[1]["ip"], to: Extract<Nodes[number], WireguardRoamingPeer>["ip"] | Extract<Nodes[number], WireguardServer>[1]["ip"]) => ConnectionsLayer<Nodes>);
/**
 * Generates the allowed IPs for each node in the network based on the
 * connections is has to the other nodes.
 *
 * @since 1.0.0
 * @category AllowedIPs Transformers
 */
export declare const computeAllowedIPsFromConnections: <Nodes extends readonly [node1: WireguardIPv4Node, node2: WireguardIPv4Node, ...rest: Array<WireguardIPv4Node>] | readonly [node1: WireguardIPv6Node, node2: WireguardIPv6Node, ...rest: Array<WireguardIPv6Node>]>(connectionsLayer: ConnectionsLayer<Nodes>) => AllowedIPsLayer<Nodes>;
/**
 * Adds an allowed IP to a node in the network.
 *
 * @since 1.0.0
 * @category AllowedIPs Transformers
 */
export declare const addAllowedIPs: (<Nodes extends readonly [node1: WireguardIPv4Node, node2: WireguardIPv4Node, ...rest: Array<WireguardIPv4Node>] | readonly [node1: WireguardIPv6Node, node2: WireguardIPv6Node, ...rest: Array<WireguardIPv6Node>]>(nodeToIp: Extract<Nodes[number], WireguardRoamingPeer>["ip"] | Extract<Nodes[number], WireguardServer>[1]["ip"], nodeFromIp: Extract<Nodes[number], WireguardRoamingPeer>["ip"] | Extract<Nodes[number], WireguardServer>[1]["ip"], cidrs: Array.NonEmptyReadonlyArray<InternetSchemas.IPv4CidrBlock | InternetSchemas.IPv6CidrBlock | InternetSchemas.CidrBlockFromStringEncoded>) => (allowedIPsLayer: AllowedIPsLayer<Nodes>) => AllowedIPsLayer<Nodes>) & (<Nodes extends readonly [node1: WireguardIPv4Node, node2: WireguardIPv4Node, ...rest: Array<WireguardIPv4Node>] | readonly [node1: WireguardIPv6Node, node2: WireguardIPv6Node, ...rest: Array<WireguardIPv6Node>]>(allowedIPsLayer: AllowedIPsLayer<Nodes>, nodeToIp: Extract<Nodes[number], WireguardRoamingPeer>["ip"] | Extract<Nodes[number], WireguardServer>[1]["ip"], nodeFromIp: Extract<Nodes[number], WireguardRoamingPeer>["ip"] | Extract<Nodes[number], WireguardServer>[1]["ip"], cidrs: Array.NonEmptyReadonlyArray<InternetSchemas.IPv4CidrBlock | InternetSchemas.IPv6CidrBlock | InternetSchemas.CidrBlockFromStringEncoded>) => AllowedIPsLayer<Nodes>);
/**
 * Converts a network into configs.
 *
 * @since 1.0.0
 * @category Generator
 */
export declare const toConfigs: <Nodes extends readonly [node1: WireguardIPv4Node, node2: WireguardIPv4Node, ...rest: Array<WireguardIPv4Node>] | readonly [node1: WireguardIPv6Node, node2: WireguardIPv6Node, ...rest: Array<WireguardIPv6Node>]>({ allowedIPs, connections, keys, nodes, wireguardNetworkCidr, }: WireguardNetwork<Nodes>) => Effect.Effect<readonly [WireguardConfig.WireguardConfig, WireguardConfig.WireguardConfig, ...ReadonlyArray<WireguardConfig.WireguardConfig>], ParseResult.ParseError | WireguardErrors.WireguardError, never>;
/**
 * Use your phone or computer to remotely access just the wireguard server.
 *
 * @since 1.0.0
 * @category Generators
 */
export declare const generateRemoteAccessToServer: <Nodes extends readonly [server: WireguardIPv4Server, client: WireguardIPv4Node] | readonly [server: WireguardIPv6Server, client: WireguardIPv6Node], NetworkCidr extends Nodes[0] extends WireguardIPv4Node ? InternetSchemas.IPv4CidrBlock : Nodes[0] extends WireguardIPv6Node ? InternetSchemas.IPv6CidrBlock : never>(options: {
    nodes: Nodes;
    wireguardNetworkCidr: NetworkCidr;
}) => WireguardNetwork<Nodes>;
/**
 * Builds on "Remote access to server", allowing you to access your entire LAN
 * as well.
 *
 * @since 1.0.0
 * @category Generators
 */
export declare const generateRemoteAccessToLan: <Nodes extends readonly [server: WireguardIPv4Server, client: WireguardIPv4Node] | readonly [server: WireguardIPv6Server, client: WireguardIPv6Node], NetworkCidr1 extends Nodes[0] extends WireguardIPv4Node ? InternetSchemas.IPv4CidrBlock : Nodes[0] extends WireguardIPv6Node ? InternetSchemas.IPv6CidrBlock : never, NetworkCidr2 extends Nodes[0] extends WireguardIPv4Server ? InternetSchemas.IPv4CidrBlock | Array.NonEmptyArray<InternetSchemas.IPv4CidrBlock> : Nodes[0] extends WireguardIPv6Server ? InternetSchemas.IPv6CidrBlock | Array.NonEmptyArray<InternetSchemas.IPv6CidrBlock> : never>(options: {
    nodes: Nodes;
    wireguardNetworkCidr: NetworkCidr1;
    lanNetworkCidr: NetworkCidr2;
}) => WireguardNetwork<Nodes>;
/**
 * Allows two servers to connect to each other.
 *
 * @since 1.0.0
 * @category Generators
 */
export declare const generateServerToServerAccess: <Nodes extends readonly [server1: WireguardIPv4Server, server2: WireguardIPv4Server] | readonly [server1: WireguardIPv6Server, server2: WireguardIPv6Server], NetworkCidr extends Nodes[0] extends WireguardIPv4Node ? InternetSchemas.IPv4CidrBlock : Nodes[0] extends WireguardIPv6Node ? InternetSchemas.IPv6CidrBlock : never>(options: {
    nodes: Nodes;
    wireguardNetworkCidr: NetworkCidr;
}) => WireguardNetwork<Nodes>;
/**
 * Builds on "Server to server access", allowing two entire networks to
 * communicate.
 *
 * @since 1.0.0
 * @category Generators
 */
export declare const generateLanToLanAccess: <Nodes extends readonly [server1: WireguardIPv4Server, server2: WireguardIPv4Server] | readonly [server1: WireguardIPv6Server, server2: WireguardIPv6Server], NetworkCidr1 extends Nodes[0] extends WireguardIPv4Node ? InternetSchemas.IPv4CidrBlock : Nodes[0] extends WireguardIPv6Node ? InternetSchemas.IPv6CidrBlock : never, NetworkCidr2 extends Nodes[0] extends WireguardIPv4Server ? InternetSchemas.IPv4CidrBlock | Array.NonEmptyArray<InternetSchemas.IPv4CidrBlock> : Nodes[0] extends WireguardIPv6Server ? InternetSchemas.IPv6CidrBlock | Array.NonEmptyArray<InternetSchemas.IPv6CidrBlock> : never, NetworkCidr3 extends Nodes[1] extends WireguardIPv4Server ? InternetSchemas.IPv4CidrBlock | Array.NonEmptyArray<InternetSchemas.IPv4CidrBlock> : Nodes[1] extends WireguardIPv6Server ? InternetSchemas.IPv6CidrBlock | Array.NonEmptyArray<InternetSchemas.IPv6CidrBlock> : never>(options: {
    nodes: Nodes;
    server1Lan: NetworkCidr2;
    server2Lan: NetworkCidr3;
    wireguardNetworkCidr: NetworkCidr1;
}) => WireguardNetwork<Nodes>;
/**
 * Builds on "Remote access to server", except that all of the VPN clients can
 * connect to each other as well. Note: all traffic between nodes must pass
 * through the server.
 *
 * @since 1.0.0
 * @category Generators
 */
export declare const generateServerHubAndSpokeAccess: <Nodes extends readonly [server: WireguardIPv4Server, ...nodes: Array.NonEmptyReadonlyArray<WireguardIPv4Node>] | readonly [server: WireguardIPv6Server, ...nodes: Array.NonEmptyReadonlyArray<WireguardIPv6Node>], NetworkCidr extends Nodes[0] extends WireguardIPv4Node ? InternetSchemas.IPv4CidrBlock : Nodes[0] extends WireguardIPv6Node ? InternetSchemas.IPv6CidrBlock : never>(options: {
    nodes: Nodes;
    wireguardNetworkCidr: NetworkCidr;
}) => WireguardNetwork<Nodes>;
/**
 * Builds on "Server hub and spoke access", allowing you to access your entire
 * LAN as well.
 *
 * @since 1.0.0
 * @category Generators
 */
export declare const generateLanHubAndSpokeAccess: <Nodes extends readonly [server: WireguardIPv4Server, ...nodes: Array.NonEmptyReadonlyArray<WireguardIPv4Node>] | readonly [server: WireguardIPv6Server, ...nodes: Array.NonEmptyReadonlyArray<WireguardIPv6Node>], NetworkCidr extends Nodes[0] extends WireguardIPv4Node ? InternetSchemas.IPv4CidrBlock : Nodes[0] extends WireguardIPv6Node ? InternetSchemas.IPv6CidrBlock : never, NetworkCidr2 extends Nodes[0] extends WireguardIPv4Server ? InternetSchemas.IPv4CidrBlock | Array.NonEmptyArray<InternetSchemas.IPv4CidrBlock> : Nodes[0] extends WireguardIPv6Server ? InternetSchemas.IPv6CidrBlock | Array.NonEmptyArray<InternetSchemas.IPv6CidrBlock> : never>(options: {
    nodes: Nodes;
    lanNetworkCidr: NetworkCidr2;
    wireguardNetworkCidr: NetworkCidr;
}) => WireguardNetwork<Nodes>;
/**
 * Route specific traffic through a commercial WireGuard VPN provider.
 *
 * @since 1.0.0
 * @category Generators
 */
export declare const generateVpnTunneledAccess: <Nodes extends readonly [server: WireguardIPv4Server, client: WireguardIPv4Node] | readonly [server: WireguardIPv6Server, client: WireguardIPv6Node], NetworkCidr extends Nodes[0] extends WireguardIPv4Node ? InternetSchemas.IPv4CidrBlock : Nodes[0] extends WireguardIPv6Node ? InternetSchemas.IPv6CidrBlock : never>(options: {
    nodes: Nodes;
    wireguardNetworkCidr: NetworkCidr;
}) => WireguardNetwork<Nodes>;
/**
 * Securely access the Internet from untrusted networks by routing all of your
 * traffic through the VPN and out the server's internet connection.
 *
 * @since 1.0.0
 * @category Generators
 */
export declare const generateRemoteTunneledAccess: <Nodes extends readonly [server: WireguardIPv4Server, client: WireguardIPv4Node] | readonly [server: WireguardIPv6Server, client: WireguardIPv6Node], NetworkCidr1 extends Nodes[0] extends WireguardIPv4Node ? InternetSchemas.IPv4CidrBlock : Nodes[0] extends WireguardIPv6Node ? InternetSchemas.IPv6CidrBlock : never, NetworkCidr2 extends Nodes[0] extends WireguardIPv4Server ? InternetSchemas.IPv4CidrBlock | Array.NonEmptyArray<InternetSchemas.IPv4CidrBlock> : Nodes[0] extends WireguardIPv6Server ? InternetSchemas.IPv6CidrBlock | Array.NonEmptyArray<InternetSchemas.IPv6CidrBlock> : never>(options: {
    nodes: Nodes;
    lanNetworkCidr: NetworkCidr2;
    wireguardNetworkCidr: NetworkCidr1;
}) => WireguardNetwork<Nodes>;
export {};
//# sourceMappingURL=WireguardGenerate.d.ts.map