Spaces:
Paused
Paused
File size: 2,611 Bytes
8c741f6 | 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 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 | import { assert } from '@hapi/hoek';
import { ipVersions } from './uri';
interface Options {
/**
* The required CIDR mode.
*
* @default 'optional'
*/
readonly cidr?: Cidr;
/**
* The allowed versions.
*
* @default ['ipv4', 'ipv6', 'ipvfuture']
*/
readonly version?: Version | Version[];
}
type Cidr = 'optional' | 'required' | 'forbidden';
type Version = 'ipv4' | 'ipv6' | 'ipvfuture';
interface Expression {
/** The CIDR mode. */
cidr: Cidr;
/** The raw regular expression string. */
raw: string;
/** The regular expression. */
regex: RegExp;
/** The array of versions allowed. */
versions: Version[];
}
/**
* Generates a regular expression used to validate IP addresses.
*
* @param options - optional settings.
*
* @returns an object with the regular expression and meta data.
*/
export function ipRegex(options: Options = {}): Expression {
// CIDR
const cidr = options.cidr || 'optional';
assert(
['required', 'optional', 'forbidden'].includes(cidr),
'options.cidr must be one of required, optional, forbidden'
);
// Versions
assert(
options.version === undefined || typeof options.version === 'string' || Array.isArray(options.version),
'options.version must be a string or an array of string'
);
let versions = options.version || ['ipv4', 'ipv6', 'ipvfuture'];
if (!Array.isArray(versions)) {
versions = [versions];
}
assert(versions.length >= 1, 'options.version must have at least 1 version specified');
for (const version of versions) {
assert(typeof version === 'string' && version === version.toLowerCase(), 'Invalid options.version value');
assert(
['ipv4', 'ipv6', 'ipvfuture'].includes(version),
'options.version contains unknown version ' + version + ' - must be one of ipv4, ipv6, ipvfuture'
);
}
versions = Array.from(new Set(versions));
// Regex
const parts = versions.map((version) => {
// Forbidden
if (cidr === 'forbidden') {
return ipVersions[version];
}
// Required
const cidrpart = `\\/${version === 'ipv4' ? ipVersions.v4Cidr : ipVersions.v6Cidr}`;
if (cidr === 'required') {
return `${ipVersions[version]}${cidrpart}`;
}
// Optional
return `${ipVersions[version]}(?:${cidrpart})?`;
});
const raw = `(?:${parts.join('|')})`;
const regex = new RegExp(`^${raw}$`);
return { cidr, versions, regex, raw };
}
|