parseLocator = allegedLocator => {
  const errorPrefix = `Invalid locator ${q(allegedLocator)}:`;

  if (!URL.canParse(allegedLocator)) {
    throw makeError(`${errorPrefix} Invalid URL.`);
  }
  const url = new URL(allegedLocator);

  if (!allegedLocator.startsWith('endo://')) {
    throw makeError(`${errorPrefix} Invalid protocol.`);
  }

  const node = url.host;
  if (!isValidNumber(node)) {
    throw makeError(`${errorPrefix} Invalid node identifier.`);
  }

  if (
    url.searchParams.size !== 2 ||
    !url.searchParams.has('id') ||
    !url.searchParams.has('type')
  ) {
    throw makeError(`${errorPrefix} Invalid search params.`);
  }

  const number = url.searchParams.get('id');
  if (number === null || !isValidNumber(number)) {
    throw makeError(`${errorPrefix} Invalid id.`);
  }

  const formulaType = url.searchParams.get('type');
  if (formulaType === null || !isValidLocatorType(formulaType)) {
    throw makeError(`${errorPrefix} Invalid type.`);
  }

  return { formulaType, node, number };
}
@param {string} allegedLocator
@returns {{ formulaType: string, node: string, number: string }}