{"version":3,"file":"url.cjs","sourceRoot":"","sources":["../src/url.ts"],"names":[],"mappings":";;;AACA,2CAAyC;AAEzC,uCAA+D;AAIlD,QAAA,YAAY,GAAG,CAAC,GAAG,CAAC,CAAC;AAErB,QAAA,UAAU,GAAG,CAAC,OAAO,CAAC,CAAC;AAEpC;;;;;;;;;GASG;AACH,SAAgB,gBAAgB,CAAC,GAAW;IAK1C,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;IACzB,MAAM,EAAE,QAAQ,EAAE,GAAG,GAAG,CAAC;IACzB,IAAI,QAAQ,KAAK,WAAW,EAAE,CAAC;QAC7B,MAAM,IAAI,KAAK,CACb,+EAA+E,QAAQ,IAAI,CAC5F,CAAC;IACJ,CAAC;IAED,kFAAkF;IAClF,kFAAkF;IAClF,MAAM,CAAC,SAAS,EAAE,GAAG,YAAY,CAAC,GAAG,GAAG,CAAC,IAAI;SAC1C,OAAO,CAAC,aAAa,EAAE,EAAE,CAAC;SAC1B,KAAK,CAAC,GAAG,CAAC,CAAC;IACd,MAAM,IAAI,GAAG,IAAI,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;IAE1C,QAAQ,SAAS,EAAE,CAAC;QAClB,KAAK,QAAQ;YACX,IAAA,cAAM,EACJ,oBAAY,CAAC,QAAQ,CAAC,IAAI,CAAC,EAC3B,0BAA0B,IAAI,sCAAsC,CACrE,CAAC;YACF,OAAO;gBACL,SAAS;gBACT,IAAI;aACL,CAAC;QACJ,KAAK,MAAM;YACT,OAAO,aAAa,CAAC,IAAI,CAAC,CAAC;QAC7B;YACE,MAAM,IAAI,KAAK,CACb,4EAA4E,SAAS,IAAI,CAC1F,CAAC;IACN,CAAC;AACH,CAAC;AArCD,4CAqCC;AAED;;;;;;GAMG;AACH,SAAS,aAAa,CAAC,IAAY;IAKjC,MAAM,gBAAgB,GAAG,uBAAuB,CAAC;IACjD,MAAM,YAAY,GAAG,IAAA,uBAAe,EAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IACpD,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC;IACtE,MAAM,YAAY,GAAG,YAAY,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;IAClD,MAAM,UAAU,GAAG,YAAY,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC3C,MAAM,aAAa,GAAG,IAAI,UAAU,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC,EAAE,CAAC;IAC9D,IAAI,aAAa,CAAC;IAClB,IAAI,QAAQ,KAAK,QAAQ,EAAE,CAAC;QAC1B,MAAM,CAAC,aAAa,EAAE,AAAD,EAAG,GAAG,IAAI,CAAC,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QAC3D,aAAa,GAAG,GAAG,aAAa,KAAK,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;QACtD,mGAAmG;QACnG,wEAAwE;QACxE,IAAA,cAAM,EACJ,kBAAU,CAAC,QAAQ,CAAC,aAAa,CAAC,EAClC,GAAG,gBAAgB,qBAAqB,CACzC,CAAC;IACJ,CAAC;SAAM,CAAC;QACN,aAAa,GAAG,YAAY;YAC1B,CAAC,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,IAAI,UAAU,CAAC,CAAC,CAAC,EAAE;YACrC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;QAClB,IAAA,cAAM,EACJ,YAAY;YACV,CAAC,CAAC,UAAU,CAAC,MAAM,KAAK,CAAC,IAAI,kBAAU,CAAC,QAAQ,CAAC,aAAa,CAAC;YAC/D,CAAC,CAAC,UAAU,CAAC,MAAM,KAAK,CAAC,IAAI,kBAAU,CAAC,QAAQ,CAAC,aAAa,CAAC,EACjE,GAAG,gBAAgB,qBAAqB,CACzC,CAAC;IACJ,CAAC;IACD,MAAM,MAAM,GAAG,GAAG,QAAQ,GAAG,aAAa,EAAE,CAAC;IAC7C,IAAA,2BAAmB,EAAC,MAAM,CAAC,CAAC;IAE5B,OAAO;QACL,SAAS,EAAE,MAAmB;QAC9B,MAAM;QACN,IAAI,EAAE,aAAa;KACpB,CAAC;AACJ,CAAC","sourcesContent":["import { type SnapId } from '@metamask/snaps-sdk';\nimport { assert } from '@metamask/utils';\n\nimport { assertIsValidSnapId, stripSnapPrefix } from './snaps';\n\nexport type Authority = 'client' | 'snap';\n\nexport const CLIENT_PATHS = ['/'];\n\nexport const SNAP_PATHS = ['/home'];\n\n/**\n * Parse a url string to an object containing the authority, path and Snap id (if snap authority).\n * This also validates the url before parsing it.\n *\n * Note: The Snap id returned from this function should always be validated to be an installed snap.\n *\n * @param str - The url string to validate and parse.\n * @returns A parsed url object.\n * @throws If the authority or path is invalid.\n */\nexport function parseMetaMaskUrl(str: string): {\n  authority: Authority;\n  snapId?: SnapId;\n  path: string;\n} {\n  const url = new URL(str);\n  const { protocol } = url;\n  if (protocol !== 'metamask:') {\n    throw new Error(\n      `Unable to parse URL. Expected the protocol to be \"metamask:\", but received \"${protocol}\".`,\n    );\n  }\n\n  // The browser version of URL differs from the Node version so we rely on the href\n  // property to grab the relevant parts of the url instead of hostname and pathname\n  const [authority, ...pathElements] = url.href\n    .replace('metamask://', '')\n    .split('/');\n  const path = `/${pathElements.join('/')}`;\n\n  switch (authority) {\n    case 'client':\n      assert(\n        CLIENT_PATHS.includes(path),\n        `Unable to navigate to \"${path}\". The provided path is not allowed.`,\n      );\n      return {\n        authority,\n        path,\n      };\n    case 'snap':\n      return parseSnapPath(path);\n    default:\n      throw new Error(\n        `Expected \"metamask:\" URL to start with \"client\" or \"snap\", but received \"${authority}\".`,\n      );\n  }\n}\n\n/**\n * Parse a snap path and throws if it is invalid, returns an object with link data otherwise.\n *\n * @param path - The snap path to be parsed.\n * @returns A parsed url object.\n * @throws If the path or Snap id is invalid.\n */\nfunction parseSnapPath(path: string): {\n  authority: Authority;\n  snapId: SnapId;\n  path: string;\n} {\n  const baseErrorMessage = 'Invalid MetaMask url:';\n  const strippedPath = stripSnapPrefix(path.slice(1));\n  const location = path.slice(1).startsWith('npm:') ? 'npm:' : 'local:';\n  const isNameSpaced = strippedPath.startsWith('@');\n  const pathTokens = strippedPath.split('/');\n  const lastPathToken = `/${pathTokens[pathTokens.length - 1]}`;\n  let partialSnapId;\n  if (location === 'local:') {\n    const [localProtocol, , ...rest] = pathTokens.slice(0, -1);\n    partialSnapId = `${localProtocol}//${rest.join('/')}`;\n    // we can't make assumptions of the structure of the local snap url since it can have a nested path\n    // so we only check that the last path token is one of the allowed paths\n    assert(\n      SNAP_PATHS.includes(lastPathToken),\n      `${baseErrorMessage} invalid snap path.`,\n    );\n  } else {\n    partialSnapId = isNameSpaced\n      ? `${pathTokens[0]}/${pathTokens[1]}`\n      : pathTokens[0];\n    assert(\n      isNameSpaced\n        ? pathTokens.length === 3 && SNAP_PATHS.includes(lastPathToken)\n        : pathTokens.length === 2 && SNAP_PATHS.includes(lastPathToken),\n      `${baseErrorMessage} invalid snap path.`,\n    );\n  }\n  const snapId = `${location}${partialSnapId}`;\n  assertIsValidSnapId(snapId);\n\n  return {\n    authority: 'snap' as Authority,\n    snapId,\n    path: lastPathToken,\n  };\n}\n"]}