url-ast
Version:
High-performance typed URL parser with AST-based analysis, automatic type casting, and route pattern matching for modern web applications
1,211 lines (1,199 loc) • 26.9 kB
JavaScript
"use strict";
var k = Object.defineProperty;
var z = Object.getOwnPropertyDescriptor;
var M = Object.getOwnPropertyNames;
var $ = Object.prototype.hasOwnProperty;
var H = (c, e) => {
for (var s in e)
k(c, s, { get: e[s], enumerable: !0 });
}, O = (c, e, s, n) => {
if (e && typeof e == "object" || typeof e == "function")
for (let r of M(e))
!$.call(c, r) && r !== s && k(c, r, { get: () => e[r], enumerable: !(n = z(e, r)) || n.enumerable });
return c;
};
var j = (c) => O(k({}, "__esModule", { value: !0 }), c);
// src/index.ts
var W = {};
H(W, {
AST: () => N,
Analyze: () => F,
CatchAllExpression: () => B,
ContentTypes: () => y,
Delimiters: () => f,
EncodingSymbols: () => P,
ErrorLog: () => p,
InternalExpression: () => m,
Node: () => d,
OriginExpression: () => T,
RawTokens: () => b,
delimitersValues: () => E
});
module.exports = j(W);
// src/types/node.ts
var f = /* @__PURE__ */ ((i) => (i[i.Ampersand = 38] = "Ampersand", i[i.Semicolon = 59] = "Semicolon", i[i.Hash = 35] = "Hash", i[i.Query = 63] = "Query", i[i.Colon = 58] = "Colon", i[i.Slash = 47] = "Slash", i[i.Asterisk = 42] = "Asterisk", i[i.LeftBracket = 91] = "LeftBracket", i[i.RightBracket = 93] = "RightBracket", i))(f || {}), P = /* @__PURE__ */ ((e) => (e[e.Equal = 61] = "Equal", e))(P || {}), T = /* @__PURE__ */ ((n) => (n[n.Protocol = 246] = "Protocol", n[n.Hostname = 245] = "Hostname", n[n.Port = 244] = "Port", n))(T || {}), B = /* @__PURE__ */ ((e) => (e[e.Point = 46] = "Point", e))(B || {}), m = /* @__PURE__ */ ((i) => (i[i.Null = 0] = "Null", i[i.Slug = 243] = "Slug", i[i.Ellipsis = 242] = "Ellipsis", i[i.Void = 250] = "Void", i[i.Path = 251] = "Path", i[i.Variable = 252] = "Variable", i[i.Fragment = 253] = "Fragment", i[i.Parameter = 254] = "Parameter", i[i.Value = 255] = "Value", i))(m || {}), y = /* @__PURE__ */ ((r) => (r[r.Boolean = 247] = "Boolean", r[r.String = 248] = "String", r[r.Number = 249] = "Number", r[r.Array = 250] = "Array", r))(y || {}), E = Object.values(f), b = {
...f,
...P,
...T,
...m,
...y
};
// src/utils/decodeURL.ts
var V = [
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
3,
3,
3,
3,
3,
3,
3,
3,
3,
3,
3,
3,
3,
3,
3,
3,
3,
3,
3,
3,
3,
3,
3,
3,
3,
3,
3,
3,
3,
3,
3,
3,
4,
4,
5,
5,
5,
5,
5,
5,
5,
5,
5,
5,
5,
5,
5,
5,
5,
5,
5,
5,
5,
5,
5,
5,
5,
5,
5,
5,
5,
5,
5,
5,
6,
7,
7,
7,
7,
7,
7,
7,
7,
7,
7,
7,
7,
8,
7,
7,
10,
9,
9,
9,
11,
4,
4,
4,
4,
4,
4,
4,
4,
4,
4,
4,
// The second part of the table maps a state to a new state when adding a
// transition.
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
12,
0,
0,
0,
0,
24,
36,
48,
60,
72,
84,
96,
0,
12,
12,
12,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
24,
0,
0,
0,
0,
0,
0,
0,
0,
0,
24,
24,
24,
0,
0,
0,
0,
0,
0,
0,
0,
0,
24,
24,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
48,
48,
48,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
48,
48,
0,
0,
0,
0,
0,
0,
0,
0,
0,
48,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
// The third part maps the current transition to a mask that needs to apply
// to the byte.
127,
63,
63,
63,
0,
31,
15,
15,
15,
7,
7,
7
], q = {
0: 0,
1: 1,
2: 2,
3: 3,
4: 4,
5: 5,
6: 6,
7: 7,
8: 8,
9: 9,
a: 10,
A: 10,
b: 11,
B: 11,
c: 12,
C: 12,
d: 13,
D: 13,
e: 14,
E: 14,
f: 15,
F: 15
};
function U(c, e) {
let s = q[c];
return s === void 0 ? 255 : s << e;
}
function w(c) {
let e = c.indexOf("%");
if (e === -1) return c;
let s = c.length, n = "", r = 0, t = 0, o = e, l = 12, a = e;
for (; a > -1 && a < s; ) {
let i = U(c[a + 1], 4), h = U(c[a + 2], 0), u = i | h, x = V[u];
if (l = V[256 + l + x], t = t << 6 | u & V[364 + x], l === 12)
n += c.slice(r, o), n += t <= 65535 ? String.fromCharCode(t) : String.fromCharCode(
55232 + (t >> 10),
56320 + (t & 1023)
), t = 0, r = a + 3, o = c.indexOf("%", r), a = o;
else {
if (l === 0)
return null;
if (a += 3, a < s && c.charCodeAt(a) === 37) continue;
return null;
}
}
return n + c.slice(r);
}
// src/utils/colors.ts
function C(c, e) {
return `\x1B[${e}m${c}\x1B[0m`;
}
var K = {
247: 92,
248: 93,
249: 94,
250: 95
}, S = {
246: 96,
245: 36,
244: 93,
47: 34,
58: 32,
38: 94,
63: 97,
35: 31,
42: 91,
91: 35,
93: 35,
61: 37,
251: 90,
254: 32,
255: 95,
242: 30,
243: 32,
253: 96,
252: 32
};
// src/utils/table.ts
function R(c) {
return c.replace(/\u001b\[[0-9;]*m/g, "");
}
function I(c, e) {
let s = R(c).length;
return c + " ".repeat(Math.max(0, e - s));
}
function D(c, e) {
let s = Object.keys(e), n = {};
for (let r of s)
n[r] = e[r].length;
for (let r of c)
for (let t of s) {
let o = r[t] || "", l = R(o).length;
l > n[t] && (n[t] = l);
}
return n;
}
function v(c, e) {
let s = D(c, e), n = Object.keys(e), r = n.map((l) => I(e[l], s[l])).join(" "), t = R(r).split("").map(() => "-").join(""), o = c.map((l) => n.map((a) => I(l[a] || "-", s[a])).join(" "));
return [r, t, ...o].join(`
`);
}
function L(c, e) {
return c.split("").map((n, r) => {
let t = r, o = e.find((a) => t >= a.start && t < a.end), l = o ? S[o.expression] ?? 37 : 37;
return C(n, l);
}).join("");
}
// src/controllers/Error.ts
var p = class {
constructor(e, s, n, r) {
this.code = e;
this.message = s;
this.start = n;
this.end = r;
}
/**
* Displays the error message with its location.
*/
display(e) {
return C(`Error [${this.code}] at col ${this.start}: ${this.message}
${e}
${" ".repeat(this.start)}${"^".repeat(Math.max(1, this.end - this.start))}`, 31);
}
};
// src/controllers/Node.ts
var d = class c {
constructor(e, s = 0, n = 0, r = 0, t = [254, 255].includes(this.expression) ? 248 : 0) {
this.id = e;
this.expression = s;
this.start = n;
this.end = r;
this.type = t;
}
static SIZE = 7;
setExpression(e) {
return this.expression = e, this;
}
setType(e) {
return this.type = e, this;
}
setPosition(e, s) {
return this.start = e, this.end = s, this;
}
writeToBuffer(e, s) {
e.writeUInt8(this.id, s), e.writeUInt8(this.expression, s + 1), e.writeUInt16LE(this.start, s + 2), e.writeUInt16LE(this.end, s + 4), e.writeUInt8(this.type, s + 6);
}
/** read a Node out of a Buffer at byte-offset `off` */
static fromBuffer(e) {
let s = [];
for (let n = 0; n < e.length; n += c.SIZE) {
let r = e.readUInt8(n), t = e.readUInt8(n + 1), o = e.readUInt16LE(n + 2), l = e.readUInt16LE(n + 4), a = e.readUInt16LE(n + 6);
s.push(new c(r, t, o, l, a));
}
return s;
}
};
// src/controllers/AST.ts
var N = class {
constructor(e, s = []) {
this.errors = s;
this.input = e;
let { expressions: n, nodes: r } = this.parser(this.input, this.errors);
this.nodes = r, this.expressions = n;
}
expressions;
input;
nodes;
/**
* Finds a Node by its index or its content string.
*
* @param {string | number} idOrName - Node index or content to search.
* @param {Node[]} [nodes=this.nodes] - Optional node array to search.
* @param {?string} [input] - Optional input string context.
* @returns {Node | undefined} The matching Node or undefined.
*/
getNode(e, s = this.nodes, n) {
let r = (t) => {
let o = s[t];
if (o)
return o;
};
switch (typeof e) {
case "string": {
let t = s.findIndex((o) => this.getContent(o, n) === e);
return t === -1 ? void 0 : r(t);
}
case "number":
return r(e);
}
}
/**
* Finds the Nth Node of a given expression type.
*
* @param {AllValues} type - Expression or delimiter type code.
* @param {number} [position=0] - Zero-based occurrence index.
* @param {Node[]} [nodes=this.nodes] - Optional node array to search.
* @returns {Node | undefined} The matching Node or undefined.
*/
getNodeByType(e, s = 0, n = this.nodes) {
let r = 0;
for (let t of n)
if (t.expression === e) {
if (r === s) return t;
r++;
}
}
/**
* Retrieves the declared type of a Node's next value token.
*
* @param {string | number} idOrName - Node index or content to search.
* @param {Node[]} [nodes=this.nodes] - Optional node array to search.
* @param {?string} [input] - Optional input string context.
*/
getType(e, s = this.nodes, n) {
let r = (t) => {
let o = s[t];
if (!(!o || o.expression !== 255))
return o.type;
};
switch (typeof e) {
case "string": {
let t = this.getNode(e, s, n);
return t ? r(t.id) : void 0;
}
case "number":
return r(e);
}
}
/**
* Extracts raw content string from a Node's start/end positions.
*
* @param {Node} node - The Node to extract from.
* @param {string} [input=this.input] - Optional input string context.
* @returns {string} The substring for the node.
*/
getContent(e, s = this.input) {
return s.slice(e.start, e.end);
}
/**
* Retrieves the raw value string following a parameter or variable Node.
*
* @param {string | number} idOrName - Node index or content to search.
* @param {Node[]} [nodes=this.nodes] - Optional node array to search.
* @param {?string} [input] - Optional input string context.
* @returns {string | undefined} The raw value, or undefined if absent.
*/
getValue(e, s = this.nodes, n) {
let r = this.getNode(e, s, n);
if (!r || ![254, 252].includes(r.expression)) return;
let t = this.getNode(r.id + 2, s, n);
if (!(!t || t.expression !== 255))
return this.getContent(t, n);
}
/**
* Prints a formatted table of nodes and colors the path output.
*
* @param {Node[]} [node=this.nodes] - Optional node array to display.
* @param {string} [input=this.input] - Optional input context for coloring.
*/
display(e = this.nodes, s = this.input) {
let n = e.map((t, o) => {
let l = s.slice(t.start, t.end), a = C(l, S[t.expression] ?? 37), i = b[t.expression] ?? "Unknown", h = b[t.type] ?? "";
return {
idx: String(o + 1),
symbol: a,
expr: i,
type: h,
start: String(t.start),
end: String(t.end)
};
});
return v(n, {
idx: "Id",
symbol: "Symbol",
expr: "Expression",
type: "Type",
start: "Start",
end: "End"
}) + `
Path: ` + L(s, e);
}
parser(e, s) {
let n = [], r = /* @__PURE__ */ new Set(), t = 0, o = 0, l = 0;
for (let a = 0; a < e.length; a++) {
let i = e.charCodeAt(a), h = e.charCodeAt(a + 1), u = n.length, x = e.charAt(a);
if (t === 250 && r.has(242) && h !== void 0) {
s.push(new p(
"E_UNEXPECTED_TOKEN",
"Unexpected token after catch-all '[]'. A catch-all must be the final element.",
a + 1,
e.length
));
break;
}
if ((t === 243 || t === 242) && E.includes(i) && i !== 93 && s.push(new p(
"E_INVALID_SYNTAX",
`Unexpected delimiter '${x}' inside a dynamic segment '[]'.`,
a,
a + 1
)), t === 251 && i === 47 && t !== 245 && s.push(new p(
"E_CONSECUTIVE_SLASHES",
"Consecutive slashes are not allowed in the path.",
a,
a + 1
)), !b[i]) {
let A = !h || E.includes(h) || h === 61 || t === 242;
if ((t === 251 || t === 252) && (h === 38 || h === 58 || t !== 252 && 61 === h) && s.push(new p(
"E_INVALID_SYNTAX",
`Unexpected token '${e[a + 1]}'. A path segment or variable cannot be followed by '${b[h]}'.`,
a + 1,
a + 2
)), t === 254 && (h === 58 || h === 47 || h === 63) && s.push(new p(
"E_INVALID_SYNTAX",
`Unexpected token '${e[a + 1]}'. A search parameter cannot be followed by '${b[h]}'.`,
a + 1,
a + 2
)), !A) continue;
switch (r.add(t), t) {
case 244:
case 253:
case 251:
case 243:
case 252: {
n.push(new d(u, t, o, a + 1)), t = 0;
continue;
}
case 0: {
let g = e.slice(l, a + 1);
switch (l = l <= o ? a + 1 : l, g) {
case "http": {
n.push(new d(u, 246, o, l));
break;
}
case "https": {
n.push(new d(u, 246, o, l));
break;
}
default: {
if (h !== 58 && h !== 47) {
n.push(new d(u, 254, o, l));
continue;
}
n.push(new d(u, 245, o, l)), h === 58 && (a += 2, o = a, t = 244);
continue;
}
}
a += 4, o = a, t = 245;
continue;
}
case 245: {
if (n.push(new d(u, t, o, a + 1)), h === 58) {
a += 2, o = a, t = 244;
continue;
}
t = 0;
continue;
}
case 242: {
if (i !== 46) {
r.delete(t), t = 243;
continue;
}
let g = e.substring(a, a + 3);
if (g !== "...") {
s.push(new p(
"E_INVALID_CATCH_ALL",
`Invalid catch-all syntax. Expected '[...]' but found an incomplete sequence near '${g}'.`,
o,
a + g.length
)), a += g.length - 1, t = 250;
continue;
}
a += 2, n.push(new d(u, t, o, a + 1)), o = a + 1, t = 243;
continue;
}
default: {
switch (l = l <= o ? a + 1 : l, e.slice(o, l)) {
case "number": {
n.push(new d(u, t, o, l, 249));
break;
}
case "boolean": {
n.push(new d(u, t, o, l, 247));
break;
}
case "string": {
n.push(new d(u, t, o, l, 248));
break;
}
case "array": {
n.push(new d(u, t, o, l, 250));
break;
}
default: {
n.push(new d(u, t, o, l));
break;
}
}
t = 0;
continue;
}
}
}
switch (i) {
case 35: {
t = 253;
break;
}
case 47: {
t = 251;
break;
}
case 38: {
t = 254;
break;
}
case 59: {
t = 254;
break;
}
case 63: {
t = 254;
break;
}
case 58: {
t = 252;
break;
}
case 42: {
t = 250;
break;
}
case 91: {
t = 242;
break;
}
case 93: {
t = 0;
break;
}
case 61: {
t = 255;
break;
}
}
n.push(new d(u, i, a, a + 1)), o = a + 1, r.add(t);
}
return { nodes: n, expressions: r };
}
};
// src/controllers/Analyze.ts
var F = class c {
input;
errors;
ast;
base;
isParser;
constructor(e, s) {
this.input = e, this.errors = [], s ? (this.base = s, this.isParser = !1) : this.isParser = !0, this.ast = new N(this.input, this.errors), this.errors.push(...this.ast.errors);
}
getParams() {
if (this.base && this.base.isParser) {
let s = {};
if (this.base.ast.expressions.has(252)) {
let n = this.base.ast.nodes.filter((r) => r.expression === 47);
for (let r = 0; r < n.length; r++) {
let t = this.base.ast.getNode(n[r].id + 2);
if (t?.expression !== 252) continue;
let o = this.base.ast.getType(t.id + 2) ?? 248, l = this.ast.getNodeByType(47, r);
if (!l) continue;
let a = this.ast.getNode(l?.id + 1);
if (a?.expression !== 251) continue;
let i = this.base.ast.getContent(t), h = this.ast.getContent(a);
s[i] = this.castValue(h, o, a.start, a.end);
}
}
return s;
}
let e = /* @__PURE__ */ new Set();
if (!this.ast.expressions.has(252)) return Array.from(e.values());
for (let s = 0; s < this.ast.nodes.length; s++) {
let n = this.ast.nodes[s];
if (!n || n?.expression !== 252) continue;
let r = w(this.ast.getContent(n));
if (r === null) {
this.errors.push(new p("E_DECODE_URI", "Failed to decode URI component for a variable.", n.start, n.end));
continue;
}
e.has(r) && this.errors.push(new p("E_DUPLICATE_PARAM", `Duplicate parameter name found: "${r}".`, n.start, n.end)), e.add(r);
}
return Array.from(e.values());
}
getSearchParams() {
if (this.base && this.base.isParser) {
let s = {};
if (!this.base.ast.expressions.has(254)) return s;
let n = this.base.ast.nodes.reduce(
(r, t) => {
if (t.expression !== 254) return r;
let o = this.base.ast.getContent(t), l = t.type !== 0 ? t.type : this.base.ast.getNode(t.id + 1)?.expression === 61 ? this.base.ast.getType(t.id + 2) ?? 248 : 248;
return r.set(o, l), r;
},
/* @__PURE__ */ new Map()
);
for (let r of this.ast.nodes) {
if (r.expression !== 254) continue;
let t = this.ast.getContent(r, this.input), o = n.get(t);
if (!o) continue;
let l = this.ast.getNode(r.id + 2), a = this.ast.getValue(r.id) ?? "";
s[t] = this.castValue(a, o, l?.start ?? r.start, l?.end ?? r.end);
}
return s;
}
let e = /* @__PURE__ */ new Map();
if (!this.ast.expressions.has(254)) return e;
for (let s = 0; s < this.ast.nodes.length; s++) {
let n = this.ast.nodes[s];
if (!n || n?.expression !== 254) continue;
let r = w(this.ast.getContent(n));
if (r === null) {
this.errors.push(new p("E_DECODE_URI", "Failed to decode URI component for a search parameter.", n.start, n.end));
continue;
}
s++;
let t = this.ast.nodes[s];
if (!t || t.expression !== 61) {
this.appendParam(e, r, "");
continue;
}
s++;
let o = this.ast.nodes[s];
if (!o || E.includes(o.type)) {
this.appendParam(e, r, "");
continue;
}
let l = this.ast.getContent(o);
if (l === null) {
this.errors.push(new p("E_DECODE_URI", "Failed to decode URI component for a search parameter value.", o.start, o.end));
continue;
}
this.appendParam(e, r, l);
}
return e;
}
getFragment() {
if (this.base) {
let e = {};
if (this.base.ast.expressions.has(253) && this.ast.expressions.has(253)) {
let s = this.base.ast.getNodeByType(253), n = this.ast.getNodeByType(253);
if (n && s) {
let r = this.base.ast.getContent(s), t = this.ast.getContent(n);
e[r] = t;
}
}
return e;
}
if (this.ast.expressions.has(253))
for (let e = 0; e < this.ast.nodes.length; e++) {
let s = this.ast.nodes[e];
if (!s || s?.expression !== 253) continue;
let n = w(this.ast.getContent(s));
if (n === null) {
this.errors.push(new p("E_DECODE_URI", "Failed to decode URI component for the fragment.", s.start, s.end));
return;
}
return n;
}
}
/**
* Extracts dynamic route parameters by navigating the base AST and finding corresponding
* values in the instance AST. It supports `[id]` and `[...slug]` formats.
*
* @returns {Record<string, string | string[]>} An object mapping parameter names to their extracted values.
*/
getStaticProps() {
let e = {};
if (!this.base)
return e;
let s = this.ast.nodes.filter((t) => t.expression === 251), n = 0;
for (let t = 0; t < this.base.ast.nodes.length; t++) {
let o = this.base.ast.nodes[t];
if (o) {
if (o.expression === 251) {
let l = s[n];
if (!l || this.base.ast.getContent(o) !== this.ast.getContent(l))
return {};
n++;
continue;
}
if (o.expression === 91) {
let l = this.base.ast.nodes[t + 1];
if (!l) continue;
if (l.expression === 242) {
let a = this.base.ast.nodes[t + 2], i = this.base.ast.nodes[t + 3];
if (!a || a.expression !== 243 || !i || i.expression !== 93) continue;
let h = this.base.ast.getContent(a), u = this.base.ast.nodes.slice(t + 4).filter((A) => A.expression === 251).length, x = s.slice(n, s.length - u);
e[h] = x.map((A) => this.ast.getContent(A)), t += 3;
break;
}
if (l.expression === 243) {
let a = this.base.ast.nodes[t + 2];
if (!a || a.expression !== 93) continue;
let i = this.base.ast.getContent(l), h = s[n];
h && (e[i] = this.ast.getContent(h), n++), t += 2;
}
}
}
}
let r = this.base.ast.nodes.filter((t) => t.expression === 251).length;
return !Object.keys(e).some((t) => Array.isArray(e[t])) && n !== s.length && s.length !== r + Object.keys(e).length ? {} : e;
}
/**
* Retrieves the pathname (path + variables) from the parsed template.
* @returns {string} The pathname (e.g., '/users/:id').
* @example
* ```ts
* const analyzer = new Analyze('http://localhost:3000/users/:userId/profile')
* console.log(analyzer.getPathname()) // '/users/:userId/profile'
* ```
*/
getPathname() {
let e = this.ast.nodes.find((n) => n.expression === 47), s = "/";
if (!e) return s;
for (let n = e.id + 1; n < this.ast.nodes.length; n++) {
let r = this.ast.nodes[n];
if ([63, 35].includes(r.expression))
break;
[
58,
47,
91,
93,
42,
251,
243,
242,
252
].includes(r.expression) && (s += this.ast.getContent(r));
}
return s;
}
/**
* Retrieves the port from the input URL, if present.
* @returns {string | undefined} The port string, or undefined if none.
* @example
* ```ts
* const analyzer = new Analyze('http://localhost:8080')
* console.log(analyzer.getPort()) // '8080'
* ```
*/
getPort() {
let e = this.ast.nodes.find((s) => s.expression === 244);
if (e)
return this.ast.getContent(e);
}
/**
* Retrieves the hostname from the input URL.
* @returns {string | undefined} The hostname, or undefined if not found.
* @example
* ```ts
* const analyzer = new Analyze('https://example.com/path')
* console.log(analyzer.getHostname()) // 'example.com'
* ```
*/
getHostname() {
let e = this.ast.nodes.find((s) => s.expression === 245);
if (e)
return this.ast.getContent(e);
}
/**
* Retrieves the protocol (http or https) from the input URL.
* @returns {string | undefined} The protocol, or undefined if not found.
* @example
* ```ts
* const analyzer = new Analyze('https://site.org')
* console.log(analyzer.getProtocol()) // 'https'
* ```
*/
getProtocol() {
let e = this.ast.nodes.find((s) => s.expression === 246);
if (e)
return this.ast.getContent(e);
}
setParser(e) {
this.base = e, this.isParser = !0;
}
/**
* Serializes the internal Node array into a Buffer representation.
* @returns {Buffer} The Buffer containing node data.
*/
getBuffer() {
let e = Buffer.alloc(this.ast.nodes.length * d.SIZE);
return this.ast.nodes.forEach((s, n) => s.writeToBuffer(e, n * d.SIZE)), e;
}
/**
* Checks if any errors were found during parsing.
* @returns {boolean} True if errors exist.
*/
hasErrors(e = this.errors) {
return e.length > 0;
}
/**
* Returns a formatted string of all parsing errors.
* @returns {string} The formatted error report.
*/
displayErrors(e = this.errors) {
return this.hasErrors(e) ? e.map((s) => s.display(this.input)).join(`
`) : "No errors found.";
}
/**
* Casts a raw string value to the given content type.
* Logs an error if casting fails.
*/
castValue(e, s, n, r) {
switch (s) {
case 247:
if (/^(?:true|1)$/i.test(e)) return !0;
if (/^(?:false|0)$/i.test(e)) return !1;
throw this.displayErrors([new p("E_CAST_BOOLEAN", `Invalid boolean value: "${e}". Expected 'true', 'false', '1', or '0'.`, n, r)]);
case 249: {
let t = Number(e);
if (Number.isNaN(t))
throw this.displayErrors([new p("E_CAST_NUMBER", `Invalid numeric value: "${e}".`, n, r)]);
return t;
}
case 250:
return e.split(",");
case 248:
default:
return e;
}
}
/**
* Adds or appends a parameter value into the map, handling duplicates.
*
* @private
* @param {Map<string, string | string[]>} map - The map to populate.
* @param {string} variable - Parameter name.
* @param {string} content - Parameter value.
*/
appendParam(e, s, n) {
let r = e.get(s);
switch (typeof r) {
case "string": {
e.set(s, [r, n]);
return;
}
case "undefined": {
e.set(s, n);
return;
}
default: {
e.set(s, [...r ?? [], n]);
return;
}
}
}
withParser(e) {
return new c(this.input, e);
}
};
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
AST,
Analyze,
CatchAllExpression,
ContentTypes,
Delimiters,
EncodingSymbols,
ErrorLog,
InternalExpression,
Node,
OriginExpression,
RawTokens,
delimitersValues
});