@freeword/meta
Version:
Meta package for Freeword: exports all core types, constants, and utilities from the src/ directory.
107 lines • 5.4 kB
JavaScript
import _ /**/ from 'lodash';
import { URLSTR, IPV4HOST, IPV6HOST, HOSTNAME, HOSTORIP, URLPATH } from "../consts/internal.js";
import { trimmed, alnum } from "../consts/AllPrimchecks.js";
import { bareint, coerce, FailedTransform, instance, num, str, union, ZodIssueCode, tupleOptionals, } from "./BootChecks.js";
// ***********************************************************************
//
// URL types
//
// ***********************************************************************
//
// URL types
//
// FIXME -- remove url in favor of URLStr
export const urlstr = trimmed.url().max(URLSTR.max).regex(URLSTR.re, URLSTR.msg);
export const ipv4host = trimmed.regex(IPV4HOST.re, IPV4HOST.msg).max(IPV4HOST.max);
export const ipv6host = trimmed.regex(IPV6HOST.re, IPV6HOST.msg).max(IPV6HOST.max);
export const hostname = trimmed.regex(HOSTNAME.re, HOSTNAME.msg).max(HOSTNAME.max);
export const hostorip = trimmed.regex(HOSTORIP.re, HOSTORIP.msg).max(HOSTORIP.max);
// Don't use this for validation; it's just to unpack -- actual validation will follow
const BOBO_HOST_OR_HOSTPORT_RE = /^(?:([A-Za-z0-9\.\-]+)|\[([A-Fa-f0-9:\.]+)\]):?(\d{1,5})?$/;
export const portnum = union([str.pipe(coerce.number()), num]).pipe(bareint.max(65535));
export const hostPortStr = str.max(1000).regex(BOBO_HOST_OR_HOSTPORT_RE);
export const hostPortPair = tupleOptionals([hostorip, portnum.nullable().optional()]);
// const tt1 = tuple([hostorip, portnum.nullable()])
// const tt2 = tupleOptionals([hostorip, portnum.nullable()])
// type TT1 = [Zcasted<typeof tt1>, Zsketch<typeof tt1>]
// type TT2 = [Zcasted<typeof tt2>, Zsketch<typeof tt2>]
export const strToHostPort = union([
hostPortStr.transform(_validishHostOrHostPortToHostPortPairZTransform).pipe(hostPortPair),
hostPortPair,
]).nullable().default(null);
export const urlobj = instance(URL);
export const liveurl = urlobj.or(str.url({ message: 'must be conventional URL' }).transform(_urlstrZtransform));
export const urlpath = str.regex(URLPATH.re, URLPATH.msg).transform(_urlpathZtransform);
export const parsedUrlpath = str.transform(_urlpathZtransform);
const _looseProtoMaybe = alnum.nullable().default('http');
/**
* generally intended to be called as [pathOrURL, hostPortStr?, protoStr?]:
* eg ['/foo', 'localhost:8080', 'https'] or ['https://whatever.com:8080/foo', undefined], etc
* For idempotence, may be called with URL object or URLStr;
* and the second arg may be a 'host:port', 'hostname', or [hostname?, port?] tuple*/
export const urlOrPathToLiveurl = liveurl.or(tupleOptionals([urlobj.or(str), strToHostPort, _looseProtoMaybe]).transform(_urlstrAndHostPortZtransform));
const EXACTLYONESLASH_RE = /^(?!^\/\/)\//;
function _validishHostOrHostPortToHostPortPairZTransform(val) {
const [_s, host, ipv6, port] = val.match(BOBO_HOST_OR_HOSTPORT_RE);
return [host ?? ipv6, port ? parseInt(port) : null];
}
function _urlpathZtransform(val, ctx) {
if (!EXACTLYONESLASH_RE.test(val)) {
ctx.addIssue({ code: ZodIssueCode.custom, message: 'just the /path part of a URL' });
return FailedTransform;
}
const parsedURLObj = URL.parse(val, 'http://placeholder');
if (!parsedURLObj) {
ctx.addIssue({ code: ZodIssueCode.custom, message: 'a conventional URL' });
return FailedTransform;
}
return parsedURLObj.pathname;
}
function _urlstrZtransform(val, ctx) {
if (val instanceof URL) {
return val;
}
const parsedURLObj = URL.parse(val);
if (!parsedURLObj) {
ctx.addIssue({ code: ZodIssueCode.custom, message: 'a conventional URL' });
return FailedTransform;
}
return parsedURLObj;
}
function _urlstrAndHostPortZtransform([pathOrURL, hostPortMaybe, protoMaybe = 'http'], ctx) {
if (pathOrURL instanceof URL) {
return pathOrURL;
}
const [hostnameMaybe = null, portMaybe = null] = hostPortMaybe ?? [];
if (!hostnameMaybe) {
return _urlstrZtransform(pathOrURL, ctx);
}
const portpart = portMaybe ? `:${portMaybe}` : '';
const baseurl = `${protoMaybe}://${hostnameMaybe}${portpart}`;
const parsedURLObj = URL.parse(pathOrURL, baseurl);
if (!parsedURLObj) {
ctx.addIssue({ code: ZodIssueCode.custom, message: 'must be conventional URL' });
return FailedTransform;
}
return parsedURLObj;
}
// function _foo(xx: _HostPortSketchTuple) { console.log(xx) }
// const examples = {
// ro1: ['http://localhost:9999/foo', null, 'http'],
// ro2: ['http://localhost:9999/foo', ['hh', 'b'], 'http'],
// ro3: ['http://localhost:9999/foo', ['hh', null], 'http'],
// ro4: ['http://localhost:9999/foo', ['hh', undefined], 'http'],
// ro5: ['http://localhost:9999/foo', ['hh', 123], 'http'],
// ro6: ['http://localhost:9999/foo', ['hh'], 'http'],
// ro7: ['http://localhost:9999/foo', ['hh'], 'http'],
// ro8: ['http://localhost:9999/foo', null, 'http'],
// ro9: ['http://localhost:9999/foo'],
// ro10: ['http://localhost:9999/foo', ['hh', 'b']],
// ro11: ['http://localhost:9999/foo', ['hh']],
// ro12: ['http://localhost:9999/foo', ['hh', 123]],
// ro13: ['http://localhost:9999/foo', ['hh', null]],
// } as const satisfies Record<string, _HostPortSketchTuple>
// function _bar(xx: keyof typeof examples, ctx: ZodCtx) {
// _foo(examples[xx]); _urlstrAndHostPortZtransform(examples[xx], ctx)
// }
//# sourceMappingURL=UrlChecks.js.map