{"version":3,"file":"path-safety.mjs","names":[],"sources":["../../src/core/path-safety.ts"],"sourcesContent":["import { ExplorerError } from \"./errors.js\";\n\nfunction decodePathSegment(value: string, label: string): string {\n  let decoded: string;\n  try {\n    decoded = decodeURIComponent(value);\n  } catch {\n    throw new ExplorerError(`${label} contains malformed percent-encoding`);\n  }\n\n  try {\n    return decodeURIComponent(decoded);\n  } catch {\n    return decoded;\n  }\n}\n\nfunction hasPathTraversal(value: string): boolean {\n  return value === \"..\" || value === \".\" || value.includes(\"../\") || value.includes(\"..\\\\\");\n}\n\n/**\n * Validate a string is safe to interpolate into a URL path segment.\n *\n * Rejects empty values, traversal, separators, delimiters, encoded separators, and control bytes.\n * Use this for values interpolated into URL paths, not query parameters.\n *\n * @param {string} value - Candidate path segment.\n * @param {string} label - Human-readable field name used in failures.\n * @throws {ExplorerError} When the input is unsafe.\n */\nexport function assertSafePathSegment(value: string, label = \"value\"): void {\n  if (typeof value !== \"string\") throw new ExplorerError(`${label} must be a string`);\n  if (value.length === 0 || /^\\s*$/.test(value)) throw new ExplorerError(`${label} is empty`);\n\n  const decoded = decodePathSegment(value, label);\n  // oxlint-disable-next-line no-control-regex -- Control chars are precisely what this boundary rejects.\n  if (/[/\\x00-\\x1F\\\\?#]/.test(decoded)) {\n    throw new ExplorerError(`${label} contains path separator or control char`);\n  }\n  if (hasPathTraversal(decoded)) {\n    throw new ExplorerError(`${label} contains path traversal sequence`);\n  }\n}\n"],"mappings":";AAEA,SAAS,kBAAkB,OAAe,OAAuB;CAC/D,IAAI;CACJ,IAAI;EACF,UAAU,mBAAmB,KAAK;CACpC,QAAQ;EACN,MAAM,IAAI,cAAc,GAAG,MAAM,qCAAqC;CACxE;CAEA,IAAI;EACF,OAAO,mBAAmB,OAAO;CACnC,QAAQ;EACN,OAAO;CACT;AACF;AAEA,SAAS,iBAAiB,OAAwB;CAChD,OAAO,UAAU,QAAQ,UAAU,OAAO,MAAM,SAAS,KAAK,KAAK,MAAM,SAAS,MAAM;AAC1F"}