All files / src/brands proxyURL.ts

73.91% Statements 17/23
71.42% Branches 15/21
100% Functions 3/3
73.91% Lines 17/23

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53                3x 3x     3x   3x       3x   3x 3x       3x 3x       3x 3x       3x       3x     3x 2x   2x         2x    
import { Brand } from "@/utils/brand";
import { getErrorMessage } from "@/utils/getErrorMessage";
import { NoThrow } from "@/utils/NoThrow";
import z from "zod";
 
export type ProxyURLBrand = Brand<`http://${string}:${string}@${string}:${string}`, "ProxyURL">;
 
export function parseProxyURL(proxyURL: string) {
    Eif (proxyURL.startsWith("http://")) {
        proxyURL = proxyURL.slice(7); // "http://" is 7 chars, not 6
    }
 
    const parts = proxyURL.split("@");
 
    Iif (parts.length !== 2) {
        return NoThrow.createError("Invalid proxy URL: expected format user:pass@host:port");
    }
 
    const [credentials, hostPort] = parts;
 
    const credParts = credentials.split(":");
    Iif (credParts.length !== 2 || !credParts[0] || !credParts[1]) {
        return NoThrow.createError("Invalid proxy URL: expected username:password");
    }
 
    const hostParts = hostPort.split(":");
    Iif (hostParts.length !== 2 || !hostParts[0] || !hostParts[1]) {
        return NoThrow.createError("Invalid proxy URL: expected host:port");
    }
 
    const port = Number(hostParts[1]);
    Iif (!Number.isInteger(port) || port < 1 || port > 65535) {
        return NoThrow.createError("Invalid proxy URL: port must be an integer between 1 and 65535");
    }
 
    return createProxyURL(credParts[0], credParts[1], hostParts[0], port);
}
 
export function createProxyURL(username: string, password: string, host: string, port: number) {
    return NoThrow.success(`http://${username}:${password}@${host}:${port}` as ProxyURLBrand);
}
 
export const ProxyURLSchema = z.string().transform((value, context) => {
    const result = parseProxyURL(value);
 
    Iif (result.isErr()) {
        context.addIssue(getErrorMessage(result.error));
        return z.NEVER;
    }
 
    return result.value;
});