{"ast":null,"code":"\"use strict\";\n\nvar _Object$assign = require(\"@babel/runtime-corejs2/core-js/object/assign\");\n\nvar _Promise = require(\"@babel/runtime-corejs2/core-js/promise\");\n\nvar _Object$defineProperty = require(\"@babel/runtime-corejs2/core-js/object/define-property\");\n\nvar __importDefault = this && this.__importDefault || function (mod) {\n  return mod && mod.__esModule ? mod : {\n    \"default\": mod\n  };\n};\n\n_Object$defineProperty(exports, \"__esModule\", {\n  value: true\n});\n\nconst url_1 = require(\"url\");\n\nconst mitt_1 = __importDefault(require(\"../mitt\"));\n\nconst utils_1 = require(\"../utils\");\n\nconst is_dynamic_1 = require(\"./utils/is-dynamic\");\n\nconst route_matcher_1 = require(\"./utils/route-matcher\");\n\nconst route_regex_1 = require(\"./utils/route-regex\");\n\nfunction addBasePath(path) {\n  // @ts-ignore variable is always a string\n  const p = process.env.__NEXT_ROUTER_BASEPATH;\n  return path.indexOf(p) !== 0 ? p + path : path;\n}\n\nfunction toRoute(path) {\n  return path.replace(/\\/$/, '') || '/';\n}\n\nclass Router {\n  constructor(pathname, query, as, {\n    initialProps,\n    pageLoader,\n    App,\n    wrapApp,\n    Component,\n    err,\n    subscription\n  }) {\n    // Static Data Cache\n    this.sdc = {};\n\n    this.onPopState = e => {\n      if (!e.state) {\n        // We get state as undefined for two reasons.\n        //  1. With older safari (< 8) and older chrome (< 34)\n        //  2. When the URL changed with #\n        //\n        // In the both cases, we don't need to proceed and change the route.\n        // (as it's already changed)\n        // But we can simply replace the state with the new changes.\n        // Actually, for (1) we don't need to nothing. But it's hard to detect that event.\n        // So, doing the following for (1) does no harm.\n        const {\n          pathname,\n          query\n        } = this;\n        this.changeState('replaceState', utils_1.formatWithValidation({\n          pathname,\n          query\n        }), utils_1.getURL());\n        return;\n      } // Make sure we don't re-render on initial load,\n      // can be caused by navigating back from an external site\n\n\n      if (e.state && this.isSsr && e.state.url === this.pathname && e.state.as === this.asPath) {\n        return;\n      } // If the downstream application returns falsy, return.\n      // They will then be responsible for handling the event.\n\n\n      if (this._bps && !this._bps(e.state)) {\n        return;\n      }\n\n      const {\n        url,\n        as,\n        options\n      } = e.state;\n\n      if (false) {\n        if (typeof url === 'undefined' || typeof as === 'undefined') {\n          console.warn('`popstate` event triggered but `event.state` did not have `url` or `as` https://err.sh/zeit/next.js/popstate-state-empty');\n        }\n      }\n\n      this.replace(url, as, options);\n    };\n\n    this._getStaticData = (asPath, _cachedData) => {\n      let pathname = url_1.parse(asPath).pathname;\n      pathname = !pathname || pathname === '/' ? '/index' : pathname;\n      return true && (_cachedData = this.sdc[pathname]) ? _Promise.resolve(_cachedData) : fetch( // @ts-ignore __NEXT_DATA__\n      `/_next/data/${__NEXT_DATA__.buildId}${pathname}.json`).then(res => {\n        if (!res.ok) {\n          throw new Error(`Failed to load static props`);\n        }\n\n        return res.json();\n      }).then(data => {\n        this.sdc[pathname] = data;\n        return data;\n      }).catch(err => {\n        ;\n        err.code = 'PAGE_LOAD_ERROR';\n        throw err;\n      });\n    }; // represents the current component key\n\n\n    this.route = toRoute(pathname); // set up the component cache (by route keys)\n\n    this.components = {}; // We should not keep the cache, if there's an error\n    // Otherwise, this cause issues when when going back and\n    // come again to the errored page.\n\n    if (pathname !== '/_error') {\n      this.components[this.route] = {\n        Component,\n        props: initialProps,\n        err\n      };\n    }\n\n    this.components['/_app'] = {\n      Component: App\n    }; // Backwards compat for Router.router.events\n    // TODO: Should be remove the following major version as it was never documented\n    // @ts-ignore backwards compatibility\n\n    this.events = Router.events;\n    this.pageLoader = pageLoader;\n    this.pathname = pathname;\n    this.query = query; // if auto prerendered and dynamic route wait to update asPath\n    // until after mount to prevent hydration mismatch\n\n    this.asPath = // @ts-ignore this is temporarily global (attached to window)\n    is_dynamic_1.isDynamicRoute(pathname) && __NEXT_DATA__.autoExport ? pathname : as;\n    this.sub = subscription;\n    this.clc = null;\n    this._wrapApp = wrapApp; // make sure to ignore extra popState in safari on navigating\n    // back from external site\n\n    this.isSsr = true;\n\n    if (false) {\n      // in order for `e.state` to work on the `onpopstate` event\n      // we have to register the initial route upon initialization\n      this.changeState('replaceState', utils_1.formatWithValidation({\n        pathname,\n        query\n      }), as);\n      window.addEventListener('popstate', this.onPopState);\n    }\n  } // @deprecated backwards compatibility even though it's a private method.\n\n\n  static _rewriteUrlForNextExport(url) {\n    if (process.env.__NEXT_EXPORT_TRAILING_SLASH) {\n      const rewriteUrlForNextExport = require('./rewrite-url-for-export').rewriteUrlForNextExport;\n\n      return rewriteUrlForNextExport(url);\n    } else {\n      return url;\n    }\n  }\n\n  update(route, mod) {\n    const Component = mod.default || mod;\n    const data = this.components[route];\n\n    if (!data) {\n      throw new Error(`Cannot update unavailable route: ${route}`);\n    }\n\n    const newData = _Object$assign(_Object$assign({}, data), {\n      Component\n    });\n\n    this.components[route] = newData; // pages/_app.js updated\n\n    if (route === '/_app') {\n      this.notify(this.components[this.route]);\n      return;\n    }\n\n    if (route === this.route) {\n      this.notify(newData);\n    }\n  }\n\n  reload() {\n    window.location.reload();\n  }\n  /**\n   * Go back in history\n   */\n\n\n  back() {\n    window.history.back();\n  }\n  /**\n   * Performs a `pushState` with arguments\n   * @param url of the route\n   * @param as masks `url` for the browser\n   * @param options object you can define `shallow` and other options\n   */\n\n\n  push(url, as = url, options = {}) {\n    return this.change('pushState', url, as, options);\n  }\n  /**\n   * Performs a `replaceState` with arguments\n   * @param url of the route\n   * @param as masks `url` for the browser\n   * @param options object you can define `shallow` and other options\n   */\n\n\n  replace(url, as = url, options = {}) {\n    return this.change('replaceState', url, as, options);\n  }\n\n  change(method, _url, _as, options) {\n    return new _Promise((resolve, reject) => {\n      if (!options._h) {\n        this.isSsr = false;\n      } // marking route changes as a navigation start entry\n\n\n      if (utils_1.ST) {\n        performance.mark('routeChange');\n      } // If url and as provided as an object representation,\n      // we'll format them into the string version here.\n\n\n      const url = typeof _url === 'object' ? utils_1.formatWithValidation(_url) : _url;\n      let as = typeof _as === 'object' ? utils_1.formatWithValidation(_as) : _as; // Add the ending slash to the paths. So, we can serve the\n      // \"<page>/index.html\" directly for the SSR page.\n\n      if (process.env.__NEXT_EXPORT_TRAILING_SLASH) {\n        const rewriteUrlForNextExport = require('./rewrite-url-for-export').rewriteUrlForNextExport; // @ts-ignore this is temporarily global (attached to window)\n\n\n        if (__NEXT_DATA__.nextExport) {\n          as = rewriteUrlForNextExport(as);\n        }\n      }\n\n      this.abortComponentLoad(as); // If the url change is only related to a hash change\n      // We should not proceed. We should only change the state.\n      // WARNING: `_h` is an internal option for handing Next.js client-side\n      // hydration. Your app should _never_ use this property. It may change at\n      // any time without notice.\n\n      if (!options._h && this.onlyAHashChange(as)) {\n        this.asPath = as;\n        Router.events.emit('hashChangeStart', as);\n        this.changeState(method, url, addBasePath(as));\n        this.scrollToHash(as);\n        Router.events.emit('hashChangeComplete', as);\n        return resolve(true);\n      }\n\n      const {\n        pathname,\n        query,\n        protocol\n      } = url_1.parse(url, true);\n\n      if (!pathname || protocol) {\n        if (false) {\n          throw new Error(`Invalid href passed to router: ${url} https://err.sh/zeit/next.js/invalid-href-passed`);\n        }\n\n        return resolve(false);\n      } // If asked to change the current URL we should reload the current page\n      // (not location.reload() but reload getInitialProps and other Next.js stuffs)\n      // We also need to set the method = replaceState always\n      // as this should not go into the history (That's how browsers work)\n      // We should compare the new asPath to the current asPath, not the url\n\n\n      if (!this.urlIsNew(as)) {\n        method = 'replaceState';\n      } // @ts-ignore pathname is always a string\n\n\n      const route = toRoute(pathname);\n      const {\n        shallow = false\n      } = options;\n\n      if (is_dynamic_1.isDynamicRoute(route)) {\n        const {\n          pathname: asPathname\n        } = url_1.parse(as);\n        const routeMatch = route_matcher_1.getRouteMatcher(route_regex_1.getRouteRegex(route))(asPathname);\n\n        if (!routeMatch) {\n          const error = `The provided \\`as\\` value (${asPathname}) is incompatible with the \\`href\\` value (${route}). ` + `Read more: https://err.sh/zeit/next.js/incompatible-href-as`;\n\n          if (false) {\n            throw new Error(error);\n          } else {\n            console.error(error);\n          }\n\n          return resolve(false);\n        } // Merge params into `query`, overwriting any specified in search\n\n\n        _Object$assign(query, routeMatch);\n      }\n\n      Router.events.emit('routeChangeStart', as); // If shallow is true and the route exists in the router cache we reuse the previous result\n      // @ts-ignore pathname is always a string\n\n      this.getRouteInfo(route, pathname, query, as, shallow).then(routeInfo => {\n        const {\n          error\n        } = routeInfo;\n\n        if (error && error.cancelled) {\n          return resolve(false);\n        }\n\n        Router.events.emit('beforeHistoryChange', as);\n        this.changeState(method, url, addBasePath(as), options);\n        const hash = window.location.hash.substring(1);\n\n        if (false) {\n          const appComp = this.components['/_app'].Component;\n          window.next.isPrerendered = appComp.getInitialProps === appComp.origGetInitialProps && !routeInfo.Component.getInitialProps;\n        } // @ts-ignore pathname is always defined\n\n\n        this.set(route, pathname, query, as, _Object$assign(_Object$assign({}, routeInfo), {\n          hash\n        }));\n\n        if (error) {\n          Router.events.emit('routeChangeError', error, as);\n          throw error;\n        }\n\n        Router.events.emit('routeChangeComplete', as);\n        return resolve(true);\n      }, reject);\n    });\n  }\n\n  changeState(method, url, as, options = {}) {\n    if (false) {\n      if (typeof window.history === 'undefined') {\n        console.error(`Warning: window.history is not available.`);\n        return;\n      } // @ts-ignore method should always exist on history\n\n\n      if (typeof window.history[method] === 'undefined') {\n        console.error(`Warning: window.history.${method} is not available`);\n        return;\n      }\n    }\n\n    if (method !== 'pushState' || utils_1.getURL() !== as) {\n      // @ts-ignore method should always exist on history\n      window.history[method]({\n        url,\n        as,\n        options\n      }, null, as);\n    }\n  }\n\n  getRouteInfo(route, pathname, query, as, shallow = false) {\n    const cachedRouteInfo = this.components[route]; // If there is a shallow route transition possible\n    // If the route is already rendered on the screen.\n\n    if (shallow && cachedRouteInfo && this.route === route) {\n      return _Promise.resolve(cachedRouteInfo);\n    }\n\n    return new _Promise((resolve, reject) => {\n      if (cachedRouteInfo) {\n        return resolve(cachedRouteInfo);\n      }\n\n      this.fetchComponent(route).then(Component => resolve({\n        Component\n      }), reject);\n    }).then(routeInfo => {\n      const {\n        Component\n      } = routeInfo;\n\n      if (false) {\n        const {\n          isValidElementType\n        } = require('react-is');\n\n        if (!isValidElementType(Component)) {\n          throw new Error(`The default export is not a React Component in page: \"${pathname}\"`);\n        }\n      }\n\n      return this._getData(() => Component.__N_SSG ? this._getStaticData(as) : this.getInitialProps(Component, // we provide AppTree later so this needs to be `any`\n      {\n        pathname,\n        query,\n        asPath: as\n      })).then(props => {\n        routeInfo.props = props;\n        this.components[route] = routeInfo;\n        return routeInfo;\n      });\n    }).catch(err => {\n      return new _Promise(resolve => {\n        if (err.code === 'PAGE_LOAD_ERROR') {\n          // If we can't load the page it could be one of following reasons\n          //  1. Page doesn't exists\n          //  2. Page does exist in a different zone\n          //  3. Internal error while loading the page\n          // So, doing a hard reload is the proper way to deal with this.\n          window.location.href = as; // Changing the URL doesn't block executing the current code path.\n          // So, we need to mark it as a cancelled error and stop the routing logic.\n\n          err.cancelled = true; // @ts-ignore TODO: fix the control flow here\n\n          return resolve({\n            error: err\n          });\n        }\n\n        if (err.cancelled) {\n          // @ts-ignore TODO: fix the control flow here\n          return resolve({\n            error: err\n          });\n        }\n\n        resolve(this.fetchComponent('/_error').then(Component => {\n          const routeInfo = {\n            Component,\n            err\n          };\n          return new _Promise(resolve => {\n            this.getInitialProps(Component, {\n              err,\n              pathname,\n              query\n            }).then(props => {\n              routeInfo.props = props;\n              routeInfo.error = err;\n              resolve(routeInfo);\n            }, gipErr => {\n              console.error('Error in error page `getInitialProps`: ', gipErr);\n              routeInfo.error = err;\n              routeInfo.props = {};\n              resolve(routeInfo);\n            });\n          });\n        }));\n      });\n    });\n  }\n\n  set(route, pathname, query, as, data) {\n    this.route = route;\n    this.pathname = pathname;\n    this.query = query;\n    this.asPath = as;\n    this.notify(data);\n  }\n  /**\n   * Callback to execute before replacing router state\n   * @param cb callback to be executed\n   */\n\n\n  beforePopState(cb) {\n    this._bps = cb;\n  }\n\n  onlyAHashChange(as) {\n    if (!this.asPath) return false;\n    const [oldUrlNoHash, oldHash] = this.asPath.split('#');\n    const [newUrlNoHash, newHash] = as.split('#'); // Makes sure we scroll to the provided hash if the url/hash are the same\n\n    if (newHash && oldUrlNoHash === newUrlNoHash && oldHash === newHash) {\n      return true;\n    } // If the urls are change, there's more than a hash change\n\n\n    if (oldUrlNoHash !== newUrlNoHash) {\n      return false;\n    } // If the hash has changed, then it's a hash only change.\n    // This check is necessary to handle both the enter and\n    // leave hash === '' cases. The identity case falls through\n    // and is treated as a next reload.\n\n\n    return oldHash !== newHash;\n  }\n\n  scrollToHash(as) {\n    const [, hash] = as.split('#'); // Scroll to top if the hash is just `#` with no value\n\n    if (hash === '') {\n      window.scrollTo(0, 0);\n      return;\n    } // First we check if the element by id is found\n\n\n    const idEl = document.getElementById(hash);\n\n    if (idEl) {\n      idEl.scrollIntoView();\n      return;\n    } // If there's no element with the id, we check the `name` property\n    // To mirror browsers\n\n\n    const nameEl = document.getElementsByName(hash)[0];\n\n    if (nameEl) {\n      nameEl.scrollIntoView();\n    }\n  }\n\n  urlIsNew(asPath) {\n    return this.asPath !== asPath;\n  }\n  /**\n   * Prefetch `page` code, you may wait for the data during `page` rendering.\n   * This feature only works in production!\n   * @param url of prefetched `page`\n   */\n\n\n  prefetch(url) {\n    return new _Promise((resolve, reject) => {\n      const {\n        pathname,\n        protocol\n      } = url_1.parse(url);\n\n      if (!pathname || protocol) {\n        if (false) {\n          throw new Error(`Invalid href passed to router: ${url} https://err.sh/zeit/next.js/invalid-href-passed`);\n        }\n\n        return;\n      } // Prefetch is not supported in development mode because it would trigger on-demand-entries\n\n\n      if (false) {\n        return;\n      } // @ts-ignore pathname is always defined\n\n\n      const route = toRoute(pathname);\n      this.pageLoader.prefetch(route).then(resolve, reject);\n    });\n  }\n\n  async fetchComponent(route) {\n    let cancelled = false;\n\n    const cancel = this.clc = () => {\n      cancelled = true;\n    };\n\n    const Component = await this.pageLoader.loadPage(route);\n\n    if (cancelled) {\n      const error = new Error(`Abort fetching component for route: \"${route}\"`);\n      error.cancelled = true;\n      throw error;\n    }\n\n    if (cancel === this.clc) {\n      this.clc = null;\n    }\n\n    return Component;\n  }\n\n  _getData(fn) {\n    let cancelled = false;\n\n    const cancel = () => {\n      cancelled = true;\n    };\n\n    this.clc = cancel;\n    return fn().then(data => {\n      if (cancel === this.clc) {\n        this.clc = null;\n      }\n\n      if (cancelled) {\n        const err = new Error('Loading initial props cancelled');\n        err.cancelled = true;\n        throw err;\n      }\n\n      return data;\n    });\n  }\n\n  getInitialProps(Component, ctx) {\n    const {\n      Component: App\n    } = this.components['/_app'];\n\n    const AppTree = this._wrapApp(App);\n\n    ctx.AppTree = AppTree;\n    return utils_1.loadGetInitialProps(App, {\n      AppTree,\n      Component,\n      router: this,\n      ctx\n    });\n  }\n\n  abortComponentLoad(as) {\n    if (this.clc) {\n      const e = new Error('Route Cancelled');\n      e.cancelled = true;\n      Router.events.emit('routeChangeError', e, as);\n      this.clc();\n      this.clc = null;\n    }\n  }\n\n  notify(data) {\n    this.sub(data, this.components['/_app'].Component);\n  }\n\n}\n\nexports.default = Router;\nRouter.events = mitt_1.default();","map":null,"metadata":{},"sourceType":"script"}