{"version":3,"file":"LocationService.cjs","sources":["../../../src/services/LocationService.tsx"],"sourcesContent":["import * as H from 'history';\nimport React, { useContext } from 'react';\nimport { BehaviorSubject, type Observable } from 'rxjs';\n\nimport { deprecationWarning, type UrlQueryMap, urlUtil } from '@grafana/data';\nimport { attachDebugger, createLogger } from '@grafana/ui';\n\nimport { config } from '../config';\n\nimport { type LocationUpdate } from './LocationSrv';\n\n/**\n * @public\n * A wrapper to help work with browser location and history\n */\nexport interface LocationService {\n  partial: (query: Record<string, any>, replace?: boolean) => void;\n  push: (location: H.Path | H.LocationDescriptor<any>) => void;\n  replace: (location: H.Path | H.LocationDescriptor<any>) => void;\n  reload: () => void;\n  getLocation: () => H.Location;\n  getHistory: () => H.History;\n  getSearch: () => URLSearchParams;\n  getSearchObject: () => UrlQueryMap;\n  getLocationObservable: () => Observable<H.Location>;\n\n  /**\n   * This is from the old LocationSrv interface\n   * @deprecated use partial, push or replace instead */\n  update: (update: LocationUpdate) => void;\n}\n\n/**\n * Wraps `H.History` so every navigation — programmatic push/replace,\n * `<Link>` clicks, and `<a href>` rendering via createHref — flows through\n * `appendOrgId` at one chokepoint. `getHistory()` returns `this`, so\n * react-router uses the wrapper too.\n * @internal\n */\nexport class HistoryWrapper implements LocationService, H.History {\n  private readonly base: H.History;\n  private locationObservable: BehaviorSubject<H.Location>;\n  private orgIdGetter?: () => number;\n  private singleHistoryEntryMode = false;\n\n  constructor(history?: H.History) {\n    this.base =\n      history ||\n      (process.env.NODE_ENV === 'test'\n        ? H.createMemoryHistory({ initialEntries: ['/'] })\n        : H.createBrowserHistory({ basename: config.appSubUrl ?? '/' }));\n\n    this.locationObservable = new BehaviorSubject(this.base.location);\n    this.base.listen((location) => this.locationObservable.next(location));\n  }\n\n  // The history library mutates these on the base instance after each\n  // navigation, so getters keep readers in sync.\n  get length() {\n    return this.base.length;\n  }\n  get action() {\n    return this.base.action;\n  }\n  get location() {\n    return this.base.location;\n  }\n\n  // Every member below is an arrow class field, not a prototype method, because callers alias\n  // them off the instance (`const m = history.push; m(loc)` in react-router, `const update =\n  // locationService.partial` in AlertmanagerContext). Arrow fields auto-bind, so `this` — and\n  // therefore the orgId injection — survives being detached. Do not convert these back to\n  // methods without binding them in the constructor.\n  push: H.History['push'] = (location, state) =>\n    this.singleHistoryEntryMode\n      ? this.base.replace(this.appendOrgId(location), state)\n      : this.base.push(this.appendOrgId(location), state);\n  replace: H.History['replace'] = (location, state) => this.base.replace(this.appendOrgId(location), state);\n  createHref: H.History['createHref'] = (location) => this.base.createHref(this.appendOrgId(location));\n\n  go: H.History['go'] = (n) => this.base.go(n);\n  goBack: H.History['goBack'] = () => this.base.goBack();\n  goForward: H.History['goForward'] = () => this.base.goForward();\n  block: H.History['block'] = (prompt) => this.base.block(prompt);\n  listen: H.History['listen'] = (listener) => this.base.listen(listener);\n\n  setOrgIdGetter = (fn: () => number) => {\n    this.orgIdGetter = fn;\n  };\n\n  // While enabled, `push` behaves as `replace`, so everything navigated to stays within\n  // the entry that was current when the mode was enabled\n  setSingleHistoryEntryMode = (enabled: boolean) => {\n    this.singleHistoryEntryMode = enabled;\n  };\n\n  // The only prototype method left: the overloads are needed because `base.createHref` accepts\n  // only a LocationDescriptorObject, and an arrow field cannot carry overloads without a cast.\n  // Safe because it is on neither LocationService nor H.History, so nothing detaches it — every\n  // caller reaches it as `this.appendOrgId(...)` from the bound arrow fields above.\n  appendOrgId(location: H.LocationDescriptorObject): H.LocationDescriptorObject;\n  appendOrgId(location: H.Path | H.LocationDescriptor): H.Path | H.LocationDescriptor;\n  appendOrgId(location: H.Path | H.LocationDescriptor): H.Path | H.LocationDescriptor {\n    const orgId = this.orgIdGetter?.() ?? 0;\n    if (!Number.isFinite(orgId) || orgId <= 0) {\n      return location;\n    }\n    const orgIdStr = String(Math.floor(orgId));\n\n    if (typeof location === 'string') {\n      const url = new URL(location, 'http://_');\n      if (url.searchParams.has('orgId')) {\n        return location;\n      }\n      url.searchParams.set('orgId', orgIdStr);\n      // A query- or hash-only string is a relative navigation that keeps the\n      // current path; omitting pathname lets the router preserve it instead of\n      // resolving to '/'.\n      const relative = location.startsWith('?') || location.startsWith('#');\n      return relative\n        ? { search: url.search, hash: url.hash }\n        : { pathname: url.pathname, search: url.search, hash: url.hash };\n    }\n\n    const params = new URLSearchParams(location.search ?? '');\n    if (params.has('orgId')) {\n      return location;\n    }\n    params.set('orgId', orgIdStr);\n    return { ...location, search: `?${params.toString()}` };\n  }\n\n  // LocationService\n  getLocationObservable = () => {\n    return this.locationObservable.asObservable();\n  };\n\n  getHistory = () => {\n    return this;\n  };\n\n  getSearch = () => {\n    return new URLSearchParams(this.base.location.search);\n  };\n\n  getLocation = () => {\n    return this.base.location;\n  };\n\n  getSearchObject = () => {\n    return locationSearchToObject(this.base.location.search);\n  };\n\n  partial = (query: Record<string, any>, replace?: boolean) => {\n    const currentLocation = this.base.location;\n    const newQuery = this.getSearchObject();\n\n    for (const key in query) {\n      // removing params with null | undefined\n      if (query[key] === null || query[key] === undefined) {\n        delete newQuery[key];\n      } else {\n        newQuery[key] = query[key];\n      }\n    }\n\n    const updatedUrl = urlUtil.renderUrl(currentLocation.pathname, newQuery);\n\n    if (replace) {\n      this.replace(updatedUrl, currentLocation.state);\n    } else {\n      this.push(updatedUrl, currentLocation.state);\n    }\n  };\n\n  reload = () => {\n    const state = this.base.location.state;\n    let prevCounter: number | undefined;\n    if (state !== null && typeof state === 'object' && 'routeReloadCounter' in state) {\n      const counter = state.routeReloadCounter;\n      if (typeof counter === 'number') {\n        prevCounter = counter;\n      }\n    }\n    this.base.replace({\n      ...this.base.location,\n      state: { routeReloadCounter: prevCounter !== undefined ? prevCounter + 1 : 1 },\n    });\n  };\n\n  /** @deprecated use partial, push or replace instead */\n  update = (options: LocationUpdate) => {\n    deprecationWarning('LocationSrv', 'update', 'partial, push or replace');\n    if (options.partial && options.query) {\n      this.partial(options.query, options.partial);\n    } else {\n      const newLocation: H.LocationDescriptor = {\n        pathname: options.path,\n      };\n      if (options.query) {\n        newLocation.search = urlUtil.toUrlParams(options.query);\n      }\n      if (options.replace) {\n        this.replace(newLocation);\n      } else {\n        this.push(newLocation);\n      }\n    }\n  };\n}\n\n/**\n * @public\n * Parses a location search string to an object\n * */\nexport function locationSearchToObject(search: string | number): UrlQueryMap {\n  let queryString = typeof search === 'number' ? String(search) : search;\n\n  if (queryString.length > 0) {\n    if (queryString.startsWith('?')) {\n      return urlUtil.parseKeyValue(queryString.substring(1));\n    }\n    return urlUtil.parseKeyValue(queryString);\n  }\n\n  return {};\n}\n\n/**\n * @public\n */\nexport let locationService: LocationService = new HistoryWrapper();\n\n/**\n * Used for tests only\n * @internal\n */\nexport const setLocationService = (location: LocationService) => {\n  if (process.env.NODE_ENV !== 'test') {\n    throw new Error('locationService can be only overriden in test environment');\n  }\n  locationService = location;\n};\n\nconst navigationLog = createLogger('Router');\n\n/** @internal */\nexport const navigationLogger = navigationLog.logger;\n\n// For debugging purposes the location service is attached to global _debug variable\nattachDebugger('location', locationService, navigationLog);\n\n// Simple context so the location service can be used without being a singleton\nconst LocationServiceContext = React.createContext<LocationService | undefined>(undefined);\n\nexport function useLocationService(): LocationService {\n  const service = useContext(LocationServiceContext);\n  if (!service) {\n    throw new Error('useLocationService must be used within a LocationServiceProvider');\n  }\n  return service;\n}\n\nexport const LocationServiceProvider: React.FC<{ service: LocationService; children: React.ReactNode }> = ({\n  service,\n  children,\n}) => {\n  return <LocationServiceContext.Provider value={service}>{children}</LocationServiceContext.Provider>;\n};\n"],"names":["urlUtil","deprecationWarning","H","config","BehaviorSubject","locationService","createLogger","attachDebugger","React","useContext"],"mappings":"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"}