UNPKG

@grafana/runtime

Version:
1 lines • 199 kB
{"version":3,"file":"index.cjs","sources":["../../src/services/backendSrv.ts","../../src/services/AngularLoader.ts","../../src/services/dataSourceSrv.ts","../../src/services/LocationSrv.ts","../../src/services/EchoSrv.ts","../../src/services/templateSrv.ts","../../src/services/legacyAngularInjector.ts","../../src/services/live.ts","../../src/config.ts","../../src/services/LocationService.tsx","../../src/services/appEvents.ts","../../src/analytics/utils.ts","../../src/services/SidecarService_EXPERIMENTAL.ts","../../src/services/SidecarContext_EXPERIMENTAL.ts","../../src/services/pluginExtensions/utils.ts","../../src/services/pluginExtensions/getPluginExtensions.ts","../../src/services/pluginExtensions/usePluginExtensions.ts","../../src/services/pluginExtensions/usePluginComponent.ts","../../src/services/pluginExtensions/usePluginComponents.ts","../../src/services/pluginExtensions/usePluginLinks.ts","../../src/services/pluginExtensions/usePluginFunctions.ts","../../src/services/user.ts","../../src/services/RuntimeDataSource.ts","../../src/services/ScopesContext.ts","../../src/analytics/types.ts","../../src/utils/plugin.ts","../../src/utils/licensing.ts","../../src/utils/logging.ts","../../src/utils/toDataQueryError.ts","../../src/utils/queryResponse.ts","../../src/utils/publicDashboardQueryHandler.ts","../../src/utils/DataSourceWithBackend.ts","../../src/components/PanelRenderer.tsx","../../src/components/PanelDataErrorView.tsx","../../src/services/QueryRunner.ts","../../src/components/PluginPage.tsx","../../src/components/DataSourcePicker.tsx","../../src/analytics/plugins/eventProperties.ts","../../src/analytics/plugins/usePluginInteractionReporter.ts","../../src/utils/returnToPrevious.ts","../../src/utils/chromeHeaderHeight.ts","../../src/components/EmbeddedDashboard.tsx","../../src/utils/rbac.ts","../../src/utils/migrationHandler.ts","../../src/components/QueryEditorWithMigration.tsx","../../src/utils/userStorage.tsx","../../src/components/FolderPicker.tsx","../../src/services/CorrelationsService.ts"],"sourcesContent":["import { Observable } from 'rxjs';\n\n/**\n * Used to initiate a remote call via the {@link BackendSrv}\n *\n * @public\n */\nexport type BackendSrvRequest = {\n /**\n * Request URL\n */\n url: string;\n\n /**\n * Number of times to retry the remote call if it fails.\n */\n retry?: number;\n\n /**\n * HTTP headers that should be passed along with the remote call.\n * Please have a look at {@link https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API | Fetch API}\n * for supported headers.\n */\n headers?: Record<string, any>;\n\n /**\n * HTTP verb to perform in the remote call GET, POST, PUT etc.\n */\n method?: string;\n\n /**\n * Set to false an success application alert box will not be shown for successful PUT, DELETE, POST requests\n */\n showSuccessAlert?: boolean;\n\n /**\n * Set to false to not show an application alert box for request errors\n */\n showErrorAlert?: boolean;\n\n /**\n * Provided by the initiator to identify a particular remote call. An example\n * of this is when a datasource plugin triggers a query. If the request id already\n * exist the backendSrv will try to cancel and replace the previous call with the\n * new one.\n */\n requestId?: string;\n\n /**\n * Set to to true to not include call in query inspector\n */\n hideFromInspector?: boolean;\n\n /**\n * The data to send\n */\n data?: any;\n\n /**\n * Query params\n */\n params?: Record<string, any>;\n\n /**\n * Define how the response object should be parsed. See:\n *\n * https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Sending_and_Receiving_Binary_Data\n *\n * By default values are json parsed from text\n */\n responseType?: 'json' | 'text' | 'arraybuffer' | 'blob';\n\n /**\n * Used to cancel an open connection\n * https://developer.mozilla.org/en-US/docs/Web/API/AbortController\n */\n abortSignal?: AbortSignal;\n\n /**\n * The credentials read-only property of the Request interface indicates whether the user agent should send cookies from the other domain in the case of cross-origin requests.\n */\n credentials?: RequestCredentials;\n\n /**\n * @deprecated withCredentials is deprecated in favor of credentials\n */\n withCredentials?: boolean;\n};\n\n/**\n * Response for fetch function in {@link BackendSrv}\n *\n * @public\n */\nexport interface FetchResponse<T = any> {\n data: T;\n readonly status: number;\n readonly statusText: string;\n readonly ok: boolean;\n readonly headers: Headers;\n readonly redirected: boolean;\n readonly type: ResponseType;\n readonly url: string;\n readonly config: BackendSrvRequest;\n readonly traceId?: string;\n}\n\n/**\n * Error type for fetch function in {@link BackendSrv}\n *\n * @public\n */\nexport interface FetchErrorDataProps {\n message?: string;\n status?: string;\n error?: string | any;\n}\n\n/**\n * Error type for fetch function in {@link BackendSrv}\n *\n * @public\n */\nexport interface FetchError<T = any> {\n status: number;\n statusText?: string;\n data: T;\n message?: string;\n cancelled?: boolean;\n isHandled?: boolean;\n config: BackendSrvRequest;\n traceId?: string;\n}\n\nexport function isFetchError<T = any>(e: unknown): e is FetchError<T> {\n return typeof e === 'object' && e !== null && 'status' in e && 'data' in e;\n}\n\n/**\n * Used to communicate via http(s) to a remote backend such as the Grafana backend,\n * a datasource etc. The BackendSrv is using the {@link https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API | Fetch API}\n * under the hood to handle all the communication.\n *\n * The request function can be used to perform a remote call by specifying a {@link BackendSrvRequest}.\n * To make the BackendSrv a bit easier to use we have added a couple of shorthand functions that will\n * use default values executing the request.\n *\n * @remarks\n * By default, Grafana displays an error message alert if the remote call fails. To prevent this from\n * happening `showErrorAlert = true` on the options object.\n *\n * @public\n */\nexport interface BackendSrv {\n get<T = any>(url: string, params?: any, requestId?: string, options?: Partial<BackendSrvRequest>): Promise<T>;\n delete<T = unknown>(url: string, data?: unknown, options?: Partial<BackendSrvRequest>): Promise<T>;\n post<T = any>(url: string, data?: unknown, options?: Partial<BackendSrvRequest>): Promise<T>;\n patch<T = any>(url: string, data?: unknown, options?: Partial<BackendSrvRequest>): Promise<T>;\n put<T = any>(url: string, data?: unknown, options?: Partial<BackendSrvRequest>): Promise<T>;\n\n /**\n * @deprecated Use the `.fetch()` function instead. If you prefer to work with a promise\n * wrap the Observable returned by fetch with the lastValueFrom function, or use the get|delete|post|patch|put methods.\n * This method is going to be private from Grafana 10.\n */\n request<T = unknown>(options: BackendSrvRequest): Promise<T>;\n\n /**\n * Special function used to communicate with datasources that will emit core\n * events that the Grafana QueryInspector and QueryEditor is listening for to be able\n * to display datasource query information. Can be skipped by adding `option.silent`\n * when initializing the request.\n *\n * @deprecated Use the fetch function instead\n */\n datasourceRequest<T = unknown>(options: BackendSrvRequest): Promise<FetchResponse<T>>;\n\n /**\n * Observable http request interface\n */\n fetch<T>(options: BackendSrvRequest): Observable<FetchResponse<T>>;\n\n /**\n * Observe each raw chunk in the response. This is useful when reading values from\n * a long living HTTP connection like the kubernetes WATCH command.\n *\n * Each chunk includes the full response headers and the `data` property is filled with the chunk.\n */\n chunked(options: BackendSrvRequest): Observable<FetchResponse<Uint8Array | undefined>>;\n}\n\nlet singletonInstance: BackendSrv;\n\n/**\n * Used during startup by Grafana to set the BackendSrv so it is available\n * via the {@link getBackendSrv} to the rest of the application.\n *\n * @internal\n */\nexport const setBackendSrv = (instance: BackendSrv) => {\n singletonInstance = instance;\n};\n\n/**\n * Used to retrieve the {@link BackendSrv} that can be used to communicate\n * via http(s) to a remote backend such as the Grafana backend, a datasource etc.\n *\n * @public\n */\nexport const getBackendSrv = (): BackendSrv => singletonInstance;\n","/**\n * Used to enable rendering of Angular components within a\n * React component without losing proper typings.\n *\n * @example\n * ```typescript\n * class Component extends PureComponent<Props> {\n * element: HTMLElement;\n * angularComponent: AngularComponent;\n *\n * componentDidMount() {\n * const template = '<angular-component />' // angular template here;\n * const scopeProps = { ctrl: angularController }; // angular scope properties here\n * const loader = getAngularLoader();\n * this.angularComponent = loader.load(this.element, scopeProps, template);\n * }\n *\n * componentWillUnmount() {\n * if (this.angularComponent) {\n * this.angularComponent.destroy();\n * }\n * }\n *\n * render() {\n * return (\n * <div ref={element => (this.element = element)} />\n * );\n * }\n * }\n * ```\n *\n * @public\n */\nexport interface AngularComponent {\n /**\n * Should be called when the React component will unmount.\n */\n destroy(): void;\n /**\n * Can be used to trigger a re-render of the Angular component.\n */\n digest(): void;\n /**\n * Used to access the Angular scope from the React component.\n */\n getScope(): any;\n}\n\n/**\n * Used to load an Angular component from the context of a React component.\n * Please see the {@link AngularComponent} for a proper example.\n *\n * @public\n */\nexport interface AngularLoader {\n /**\n *\n * @param elem - the element that the Angular component will be loaded into.\n * @param scopeProps - values that will be accessed via the Angular scope.\n * @param template - template used by the Angular component.\n */\n load(elem: any, scopeProps: any, template: string): AngularComponent;\n}\n\nlet instance: AngularLoader;\n\n/**\n * Used during startup by Grafana to set the AngularLoader so it is available\n * via the {@link getAngularLoader} to the rest of the application.\n *\n * @internal\n */\nexport function setAngularLoader(v: AngularLoader) {\n instance = v;\n}\n\n/**\n * Used to retrieve the {@link AngularLoader} that enables the use of Angular\n * components within a React component.\n *\n * Please see the {@link AngularComponent} for a proper example.\n *\n * @public\n */\nexport function getAngularLoader(): AngularLoader {\n return instance;\n}\n","import { ScopedVars, DataSourceApi, DataSourceInstanceSettings, DataSourceRef } from '@grafana/data';\n\nimport { RuntimeDataSource } from './RuntimeDataSource';\n\n/**\n * This is the entry point for communicating with a datasource that is added as\n * a plugin (both external and internal). Via this service you will get access\n * to the {@link @grafana/data#DataSourceApi | DataSourceApi} that have a rich API for\n * communicating with the datasource.\n *\n * @public\n */\nexport interface DataSourceSrv {\n /**\n * Returns the requested dataSource. If it cannot be found it rejects the promise.\n * @param ref - The datasource identifier, it can be a name, UID or DataSourceRef (an object with UID),\n * @param scopedVars - variables used to interpolate a templated passed as name.\n */\n get(ref?: DataSourceRef | string | null, scopedVars?: ScopedVars): Promise<DataSourceApi>;\n\n /**\n * Get a list of data sources\n */\n getList(filters?: GetDataSourceListFilters): DataSourceInstanceSettings[];\n\n /**\n * Get settings and plugin metadata by name or uid\n */\n getInstanceSettings(\n ref?: DataSourceRef | string | null,\n scopedVars?: ScopedVars\n ): DataSourceInstanceSettings | undefined;\n\n /**\n * Reloads the DataSourceSrv\n */\n reload(): void;\n\n /**\n * Registers a runtime data source. Make sure your data source uid is unique.\n */\n registerRuntimeDataSource(entry: RuntimeDataSourceRegistration): void;\n}\n\nexport interface RuntimeDataSourceRegistration {\n dataSource: RuntimeDataSource;\n}\n\n/** @public */\nexport interface GetDataSourceListFilters {\n /** Include mixed data source by setting this to true */\n mixed?: boolean;\n\n /** Only return data sources that support metrics response */\n metrics?: boolean;\n\n /** Only return data sources that support tracing response */\n tracing?: boolean;\n\n /** Only return data sources that support logging response */\n logs?: boolean;\n\n /** Only return data sources that support annotations */\n annotations?: boolean;\n\n /** Only filter data sources that support alerting */\n alerting?: boolean;\n\n /**\n * By default only data sources that can be queried will be returned. Meaning they have tracing,\n * metrics, logs or annotations flag set in plugin.json file\n * */\n all?: boolean;\n\n /** Set to true to return dashboard data source */\n dashboard?: boolean;\n\n /** Set to true to return data source variables */\n variables?: boolean;\n\n /** filter list by plugin */\n pluginId?: string;\n\n /** apply a function to filter */\n filter?: (dataSource: DataSourceInstanceSettings) => boolean;\n\n /** Only returns datasources matching the specified types (ie. Loki, Prometheus) */\n type?: string | string[];\n}\n\nlet singletonInstance: DataSourceSrv;\n\n/**\n * Used during startup by Grafana to set the DataSourceSrv so it is available\n * via the {@link getDataSourceSrv} to the rest of the application.\n *\n * @internal\n */\nexport function setDataSourceSrv(instance: DataSourceSrv) {\n singletonInstance = instance;\n}\n\n/**\n * Used to retrieve the {@link DataSourceSrv} that is the entry point for communicating with\n * a datasource that is added as a plugin (both external and internal).\n *\n * @public\n */\nexport function getDataSourceSrv(): DataSourceSrv {\n return singletonInstance;\n}\n","import { UrlQueryMap } from '@grafana/data';\n\n/**\n * @public\n * @deprecated in favor of {@link locationService} and will be removed in Grafana 9\n */\nexport interface LocationUpdate {\n /**\n * Target path where you automatically wants to navigate the user.\n */\n path?: string;\n\n /**\n * Specify this value if you want to add values to the query string of the URL.\n */\n query?: UrlQueryMap;\n\n /**\n * If set to true, the query argument will be added to the existing URL.\n */\n partial?: boolean;\n\n /**\n * Used internally to sync the Redux state from Angular to make sure that the Redux location\n * state is in sync when navigating using the Angular router.\n *\n * @remarks\n * Do not change this unless you are the Angular router.\n *\n * @internal\n */\n routeParams?: UrlQueryMap;\n\n /*\n * If set to true, this will replace URL state (ie. cause no new browser history).\n */\n replace?: boolean;\n}\n\n/**\n * If you need to automatically navigate the user to a new place in the application this should\n * be done via the LocationSrv and it will make sure to update the application state accordingly.\n *\n * @public\n * @deprecated in favor of {@link locationService} and will be removed in Grafana 9\n */\nexport interface LocationSrv {\n update(options: LocationUpdate): void;\n}\n\nlet singletonInstance: LocationSrv;\n\n/**\n * Used during startup by Grafana to set the LocationSrv so it is available\n * via the {@link getLocationSrv} to the rest of the application.\n *\n * @internal\n */\nexport function setLocationSrv(instance: LocationSrv) {\n singletonInstance = instance;\n}\n\n/**\n * Used to retrieve the {@link LocationSrv} that can be used to automatically navigate\n * the user to a new place in Grafana.\n *\n * @public\n * @deprecated in favor of {@link locationService} and will be removed in Grafana 9\n */\nexport function getLocationSrv(): LocationSrv {\n return singletonInstance;\n}\n","/**\n * Describes a size with width/height\n *\n * @public\n */\nexport interface SizeMeta {\n width: number;\n height: number;\n}\n\n/**\n * Describes the meta information that are sent together with each event.\n *\n * @public\n */\nexport interface EchoMeta {\n screenSize: SizeMeta;\n windowSize: SizeMeta;\n userAgent: string;\n url?: string;\n path?: string;\n /**\n * A unique browser session\n */\n sessionId: string;\n /**\n * The current user's username used to login into Grafana e.g. email.\n */\n userLogin: string;\n /**\n * The current user's unique identifier.\n */\n userId: number;\n /**\n * True when user is logged in into Grafana.\n */\n userSignedIn: boolean;\n /**\n * Current user's role\n */\n orgRole: string | '';\n /**\n * Current user's org\n */\n orgId: number;\n /**\n * A millisecond epoch\n */\n ts: number;\n /**\n * A highres timestamp since navigation start\n */\n timeSinceNavigationStart: number;\n}\n\n/**\n * Describes echo backends that can be registered to receive of events.\n *\n * @public\n */\nexport interface EchoBackend<T extends EchoEvent = any, O = any> {\n options: O;\n supportedEvents: EchoEventType[];\n flush: () => void;\n addEvent: (event: T) => void;\n}\n\n/**\n * Describes an echo event.\n *\n * @public\n */\nexport interface EchoEvent<T extends EchoEventType = any, P = any> {\n type: EchoEventType;\n /**\n * Event payload containing event specific data.\n */\n payload: P;\n meta: EchoMeta;\n}\n\n/**\n * Supported echo event types that can be sent via the {@link EchoSrv}.\n *\n * @public\n */\nexport enum EchoEventType {\n Performance = 'performance',\n MetaAnalytics = 'meta-analytics',\n Pageview = 'pageview',\n Interaction = 'interaction',\n ExperimentView = 'experimentview',\n GrafanaJavascriptAgent = 'grafana-javascript-agent',\n}\n\n/**\n * Used to send events to all the registered backends. This should be accessed via the\n * {@link getEchoSrv} function. Will, by default, flush events to the backends every\n * 10s or when the flush function is triggered.\n *\n * @public\n */\nexport interface EchoSrv {\n /**\n * Call this to flush current events to the echo backends.\n */\n flush(): void;\n /**\n * Add a new echo backend to the list of backends that will receive events.\n */\n addBackend(backend: EchoBackend): void;\n /**\n * Call this to add event that will be sent to the echo backends upon next\n * flush.\n *\n * @param event - Object containing event information.\n * @param meta - Object that will extend/override the default meta object.\n */\n addEvent<T extends EchoEvent>(event: Omit<T, 'meta'>, meta?: {}): void;\n}\n\nlet singletonInstance: EchoSrv;\n\n/**\n * Used during startup by Grafana to set the EchoSrv so it is available\n * via the {@link getEchoSrv} to the rest of the application.\n *\n * @internal\n */\nexport function setEchoSrv(instance: EchoSrv) {\n // Check if there were any events reported to the FakeEchoSrv (before the main EchoSrv was initialized), and track them\n if (singletonInstance instanceof FakeEchoSrv) {\n for (const item of singletonInstance.buffer) {\n instance.addEvent(item.event, item.meta);\n }\n }\n\n singletonInstance = instance;\n}\n\n/**\n * Used to retrieve the {@link EchoSrv} that can be used to report events to registered\n * echo backends.\n *\n * @public\n */\nexport function getEchoSrv(): EchoSrv {\n if (!singletonInstance) {\n singletonInstance = new FakeEchoSrv();\n }\n\n return singletonInstance;\n}\n\n/**\n * Used to register echo backends that will receive Grafana echo events during application\n * runtime.\n *\n * @public\n */\nexport const registerEchoBackend = (backend: EchoBackend) => {\n getEchoSrv().addBackend(backend);\n};\n\nexport class FakeEchoSrv implements EchoSrv {\n buffer: Array<{ event: Omit<EchoEvent, 'meta'>; meta?: {} | undefined }> = [];\n\n flush(): void {\n this.buffer = [];\n }\n\n addBackend(backend: EchoBackend): void {}\n\n addEvent<T extends EchoEvent>(event: Omit<T, 'meta'>, meta?: {} | undefined): void {\n this.buffer.push({ event, meta });\n }\n}\n","import { ScopedVars, TimeRange, TypedVariableModel } from '@grafana/data';\n\n/**\n * Can be used to gain more information about an interpolation operation\n */\nexport interface VariableInterpolation {\n /** The full matched expression including, example: ${varName.field:regex} */\n match: string;\n /** In the expression ${varName.field:regex} variableName is varName */\n variableName: string;\n /** In the expression ${varName.fields[0].name:regex} the fieldPath is fields[0].name */\n fieldPath?: string;\n /** In the expression ${varName:regex} the regex part is the format */\n format?: string;\n /** The formatted value of the variable expresion. Will equal match when variable not found or scopedVar was undefined or null **/\n value: string;\n // When value === match this will be true, meaning the variable was not found\n found?: boolean;\n}\n\n/**\n * Via the TemplateSrv consumers get access to all the available template variables\n * that can be used within the current active dashboard.\n *\n * For a more in-depth description visit: https://grafana.com/docs/grafana/latest/reference/templating\n * @public\n */\nexport interface TemplateSrv {\n /**\n * List the dashboard variables\n */\n getVariables(): TypedVariableModel[];\n\n /**\n * Replace the values within the target string. See also {@link InterpolateFunction}\n *\n * Note: interpolations array is being mutated by replace function by adding information about variables that\n * have been interpolated during replacement. Variables that were specified in the target but not found in\n * the list of available variables are also added to the array. See {@link VariableInterpolation} for more details.\n *\n * @param {VariableInterpolation[]} interpolations an optional map that is updated with interpolated variables\n */\n replace(\n target?: string,\n scopedVars?: ScopedVars,\n format?: string | Function,\n interpolations?: VariableInterpolation[]\n ): string;\n\n /**\n * Checks if a target contains template variables.\n */\n containsTemplate(target?: string): boolean;\n\n /**\n * Update the current time range to be used when interpolating __from / __to variables.\n */\n updateTimeRange(timeRange: TimeRange): void;\n}\n\nlet singletonInstance: TemplateSrv;\n\n/**\n * Used during startup by Grafana to set the TemplateSrv so it is available\n * via the {@link getTemplateSrv} to the rest of the application.\n *\n * @internal\n */\nexport const setTemplateSrv = (instance: TemplateSrv) => {\n singletonInstance = instance;\n};\n\n/**\n * Used to retrieve the {@link TemplateSrv} that can be used to fetch available\n * template variables.\n *\n * @public\n */\nexport const getTemplateSrv = (): TemplateSrv => singletonInstance;\n","import { auto } from 'angular';\n\nlet singleton: auto.IInjectorService;\n\n/**\n * Used during startup by Grafana to temporarily expose the angular injector to\n * pure javascript plugins using {@link getLegacyAngularInjector}.\n *\n * @internal\n */\nexport const setLegacyAngularInjector = (instance: auto.IInjectorService) => {\n singleton = instance;\n};\n\n/**\n * WARNING: this function provides a temporary way for plugins to access anything in the\n * angular injector. While the migration from angular to react continues, there are a few\n * options that do not yet have good alternatives. Note that use of this function will\n * be removed in the future.\n *\n * @beta\n */\nexport const getLegacyAngularInjector = (): auto.IInjectorService => singleton;\n","import { Observable } from 'rxjs';\n\nimport {\n DataFrameJSON,\n DataQueryRequest,\n DataQueryResponse,\n LiveChannelAddress,\n LiveChannelEvent,\n LiveChannelPresenceStatus,\n StreamingFrameOptions,\n} from '@grafana/data';\n\n/**\n * @alpha -- experimental\n */\nexport interface LiveDataFilter {\n fields?: string[];\n}\n\n// StreamingFrameAction and StreamingFrameOptions are now in @grafana/data\nexport { StreamingFrameAction, type StreamingFrameOptions } from '@grafana/data';\n\n/**\n * @alpha\n */\nexport interface LiveDataStreamOptions {\n addr: LiveChannelAddress;\n frame?: DataFrameJSON; // initial results\n key?: string;\n buffer?: Partial<StreamingFrameOptions>;\n filter?: LiveDataFilter;\n}\n\n/**\n * @alpha -- experimental: send a normal query request over websockt\n */\nexport interface LiveQueryDataOptions {\n request: DataQueryRequest;\n body: unknown; // processed queries, same as sent to `/api/query/ds`\n}\n\n/**\n * @alpha -- experimental\n */\nexport interface GrafanaLiveSrv {\n /**\n * Listen for changes to the main service\n */\n getConnectionState(): Observable<boolean>;\n\n /**\n * Watch for messages in a channel\n */\n getStream<T>(address: LiveChannelAddress): Observable<LiveChannelEvent<T>>;\n\n /**\n * Connect to a channel and return results as DataFrames\n */\n getDataStream(options: LiveDataStreamOptions): Observable<DataQueryResponse>;\n\n /**\n * Execute a query over the live websocket and potentiall subscribe to a live channel.\n *\n * Since the initial request and subscription are on the same socket, this will support HA setups\n *\n * @alpha -- this function requires the feature toggle `queryOverLive` to be set\n */\n getQueryData(options: LiveQueryDataOptions): Observable<DataQueryResponse>;\n\n /**\n * For channels that support presence, this will request the current state from the server.\n *\n * Join and leave messages will be sent to the open stream\n */\n getPresence(address: LiveChannelAddress): Promise<LiveChannelPresenceStatus>;\n\n /**\n * Publish into a channel\n *\n * @alpha -- experimental\n */\n publish(address: LiveChannelAddress, data: unknown): Promise<unknown>;\n}\n\nlet singletonInstance: GrafanaLiveSrv;\n\n/**\n * Used during startup by Grafana to set the GrafanaLiveSrv so it is available\n * via the {@link getGrafanaLiveSrv} to the rest of the application.\n *\n * @internal\n */\nexport const setGrafanaLiveSrv = (instance: GrafanaLiveSrv) => {\n singletonInstance = instance;\n};\n\n/**\n * Used to retrieve the GrafanaLiveSrv that allows you to subscribe to\n * server side events and streams\n *\n * @alpha -- experimental\n */\nexport const getGrafanaLiveSrv = (): GrafanaLiveSrv => singletonInstance;\n","import { merge } from 'lodash';\n\nimport {\n AuthSettings,\n BootData,\n BuildInfo,\n DataSourceInstanceSettings,\n FeatureToggles,\n GrafanaConfig,\n GrafanaTheme,\n GrafanaTheme2,\n LicenseInfo,\n MapLayerOptions,\n OAuthSettings,\n PanelPluginMeta,\n systemDateFormats,\n SystemDateFormatSettings,\n getThemeById,\n AngularMeta,\n PluginLoadingStrategy,\n PluginDependencies,\n PluginExtensions,\n} from '@grafana/data';\n\nexport interface AzureSettings {\n cloud?: string;\n clouds?: AzureCloudInfo[];\n managedIdentityEnabled: boolean;\n workloadIdentityEnabled: boolean;\n userIdentityEnabled: boolean;\n userIdentityFallbackCredentialsEnabled: boolean;\n azureEntraPasswordCredentialsEnabled: boolean;\n}\n\nexport interface AzureCloudInfo {\n name: string;\n displayName: string;\n}\n\nexport type AppPluginConfig = {\n id: string;\n path: string;\n version: string;\n preload: boolean;\n angular: AngularMeta;\n loadingStrategy: PluginLoadingStrategy;\n dependencies: PluginDependencies;\n extensions: PluginExtensions;\n moduleHash?: string;\n};\n\nexport type PreinstalledPlugin = {\n id: string;\n version: string;\n};\n\nexport class GrafanaBootConfig implements GrafanaConfig {\n publicDashboardAccessToken?: string;\n publicDashboardsEnabled = true;\n snapshotEnabled = true;\n datasources: { [str: string]: DataSourceInstanceSettings } = {};\n panels: { [key: string]: PanelPluginMeta } = {};\n apps: Record<string, AppPluginConfig> = {};\n auth: AuthSettings = {};\n minRefreshInterval = '';\n appUrl = '';\n appSubUrl = '';\n namespace = 'default';\n windowTitlePrefix = '';\n buildInfo: BuildInfo;\n newPanelTitle = '';\n bootData: BootData;\n externalUserMngLinkUrl = '';\n externalUserMngLinkName = '';\n externalUserMngInfo = '';\n externalUserMngAnalytics = false;\n externalUserMngAnalyticsParams = '';\n allowOrgCreate = false;\n feedbackLinksEnabled = true;\n disableLoginForm = false;\n defaultDatasource = ''; // UID\n angularSupportEnabled = false;\n authProxyEnabled = false;\n exploreEnabled = false;\n queryHistoryEnabled = false;\n helpEnabled = false;\n profileEnabled = false;\n newsFeedEnabled = true;\n ldapEnabled = false;\n jwtHeaderName = '';\n jwtUrlLogin = false;\n sigV4AuthEnabled = false;\n azureAuthEnabled = false;\n secureSocksDSProxyEnabled = false;\n samlEnabled = false;\n samlName = '';\n autoAssignOrg = true;\n verifyEmailEnabled = false;\n oauth: OAuthSettings = {};\n rbacEnabled = true;\n disableUserSignUp = false;\n loginHint = '';\n passwordHint = '';\n loginError: string | undefined = undefined;\n viewersCanEdit = false;\n editorsCanAdmin = false;\n disableSanitizeHtml = false;\n trustedTypesDefaultPolicyEnabled = false;\n cspReportOnlyEnabled = false;\n liveEnabled = true;\n /** @deprecated Use `theme2` instead. */\n theme: GrafanaTheme;\n theme2: GrafanaTheme2;\n featureToggles: FeatureToggles = {};\n anonymousEnabled = false;\n anonymousDeviceLimit: number | undefined = undefined;\n licenseInfo: LicenseInfo = {} as LicenseInfo;\n rendererAvailable = false;\n rendererVersion = '';\n rendererDefaultImageWidth = 1000;\n rendererDefaultImageHeight = 500;\n rendererDefaultImageScale = 1;\n secretsManagerPluginEnabled = false;\n supportBundlesEnabled = false;\n http2Enabled = false;\n dateFormats?: SystemDateFormatSettings;\n grafanaJavascriptAgent = {\n enabled: false,\n customEndpoint: '',\n apiKey: '',\n allInstrumentationsEnabled: false,\n errorInstrumentalizationEnabled: true,\n consoleInstrumentalizationEnabled: false,\n webVitalsInstrumentalizationEnabled: false,\n tracingInstrumentalizationEnabled: false,\n };\n pluginCatalogURL = 'https://grafana.com/grafana/plugins/';\n pluginAdminEnabled = true;\n pluginAdminExternalManageEnabled = false;\n pluginCatalogHiddenPlugins: string[] = [];\n pluginCatalogManagedPlugins: string[] = [];\n pluginCatalogPreinstalledPlugins: PreinstalledPlugin[] = [];\n pluginsCDNBaseURL = '';\n expressionsEnabled = false;\n awsAllowedAuthProviders: string[] = [];\n awsAssumeRoleEnabled = false;\n azure: AzureSettings = {\n managedIdentityEnabled: false,\n workloadIdentityEnabled: false,\n userIdentityEnabled: false,\n userIdentityFallbackCredentialsEnabled: false,\n azureEntraPasswordCredentialsEnabled: false,\n };\n caching = {\n enabled: false,\n };\n geomapDefaultBaseLayerConfig?: MapLayerOptions;\n geomapDisableCustomBaseLayer?: boolean;\n unifiedAlertingEnabled = false;\n unifiedAlerting = {\n minInterval: '',\n alertStateHistoryBackend: undefined,\n alertStateHistoryPrimary: undefined,\n };\n applicationInsightsConnectionString?: string;\n applicationInsightsEndpointUrl?: string;\n recordedQueries = {\n enabled: true,\n };\n featureHighlights = {\n enabled: false,\n };\n reporting = {\n enabled: true,\n };\n analytics = {\n enabled: true,\n };\n googleAnalyticsId: undefined;\n googleAnalytics4Id: undefined;\n googleAnalytics4SendManualPageViews = false;\n rudderstackWriteKey: undefined;\n rudderstackDataPlaneUrl: undefined;\n rudderstackSdkUrl: undefined;\n rudderstackConfigUrl: undefined;\n rudderstackIntegrationsUrl: undefined;\n analyticsConsoleReporting = false;\n dashboardPerformanceMetrics: string[] = [];\n sqlConnectionLimits = {\n maxOpenConns: 100,\n maxIdleConns: 100,\n connMaxLifetime: 14400,\n };\n defaultDatasourceManageAlertsUiToggle = true;\n\n tokenExpirationDayLimit: undefined;\n enableFrontendSandboxForPlugins: string[] = [];\n sharedWithMeFolderUID: string | undefined;\n rootFolderUID: string | undefined;\n localFileSystemAvailable: boolean | undefined;\n cloudMigrationIsTarget: boolean | undefined;\n cloudMigrationFeedbackURL = '';\n cloudMigrationPollIntervalMs = 2000;\n reportingStaticContext?: Record<string, string>;\n exploreDefaultTimeOffset = '1h';\n exploreHideLogsDownload: boolean | undefined;\n\n /**\n * Language used in Grafana's UI. This is after the user's preference (or deteceted locale) is resolved to one of\n * Grafana's supported language.\n */\n language: string | undefined;\n\n constructor(options: GrafanaBootConfig) {\n this.bootData = options.bootData;\n\n const defaults = {\n datasources: {},\n windowTitlePrefix: 'Grafana - ',\n panels: {},\n newPanelTitle: 'Panel Title',\n playlist_timespan: '1m',\n unsaved_changes_warning: true,\n appUrl: '',\n appSubUrl: '',\n buildInfo: {\n version: '1.0',\n commit: '1',\n env: 'production',\n },\n viewersCanEdit: false,\n editorsCanAdmin: false,\n disableSanitizeHtml: false,\n };\n\n merge(this, defaults, options);\n\n this.buildInfo = options.buildInfo || defaults.buildInfo;\n\n if (this.dateFormats) {\n systemDateFormats.update(this.dateFormats);\n }\n\n overrideFeatureTogglesFromUrl(this);\n overrideFeatureTogglesFromLocalStorage(this);\n\n if (this.featureToggles.disableAngular) {\n this.angularSupportEnabled = false;\n }\n\n // Creating theme after applying feature toggle overrides in case we need to toggle anything\n this.theme2 = getThemeById(this.bootData.user.theme);\n this.bootData.user.lightTheme = this.theme2.isLight;\n this.theme = this.theme2.v1;\n }\n}\n\n// localstorage key: grafana.featureToggles\n// example value: panelEditor=1,panelInspector=1\nfunction overrideFeatureTogglesFromLocalStorage(config: GrafanaBootConfig) {\n const featureToggles = config.featureToggles;\n const localStorageKey = 'grafana.featureToggles';\n const localStorageValue = window.localStorage.getItem(localStorageKey);\n if (localStorageValue) {\n const features = localStorageValue.split(',');\n for (const feature of features) {\n const [featureName, featureValue] = feature.split('=');\n const toggleState = featureValue === 'true' || featureValue === '1';\n // eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n featureToggles[featureName as keyof FeatureToggles] = toggleState;\n console.log(`Setting feature toggle ${featureName} = ${toggleState} via localstorage`);\n }\n }\n}\n\nfunction overrideFeatureTogglesFromUrl(config: GrafanaBootConfig) {\n if (window.location.href.indexOf('__feature') === -1) {\n return;\n }\n\n const isDevelopment = config.buildInfo.env === 'development';\n\n // Although most flags can not be changed from the URL in production,\n // some of them are safe (and useful!) to change dynamically from the browser URL\n const safeRuntimeFeatureFlags = new Set(['queryServiceFromUI', 'dashboardSceneSolo']);\n\n const params = new URLSearchParams(window.location.search);\n params.forEach((value, key) => {\n if (key.startsWith('__feature.')) {\n const featureToggles = config.featureToggles as Record<string, boolean>;\n const featureName = key.substring(10);\n\n const toggleState = value === 'true' || value === ''; // browser rewrites true as ''\n if (toggleState !== featureToggles[key]) {\n if (isDevelopment || safeRuntimeFeatureFlags.has(featureName)) {\n featureToggles[featureName] = toggleState;\n console.log(`Setting feature toggle ${featureName} = ${toggleState} via url`);\n } else {\n console.log(`Unable to change feature toggle ${featureName} via url in production.`);\n }\n }\n }\n });\n}\n\nconst bootData = (window as any).grafanaBootData || {\n settings: {},\n user: {},\n navTree: [],\n};\n\nconst options = bootData.settings;\noptions.bootData = bootData;\n\n/**\n * Use this to access the {@link GrafanaBootConfig} for the current running Grafana instance.\n *\n * @public\n */\nexport const config = new GrafanaBootConfig(options);\n","import * as H from 'history';\nimport React, { useContext } from 'react';\nimport { BehaviorSubject, Observable } from 'rxjs';\n\nimport { deprecationWarning, UrlQueryMap, urlUtil } from '@grafana/data';\nimport { attachDebugger, createLogger } from '@grafana/ui';\n\nimport { config } from '../config';\n\nimport { 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/** @internal */\nexport class HistoryWrapper implements LocationService {\n private readonly history: H.History;\n private locationObservable: BehaviorSubject<H.Location>;\n\n constructor(history?: H.History) {\n // If no history passed create an in memory one if being called from test\n this.history =\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.history.location);\n\n this.history.listen((location) => {\n this.locationObservable.next(location);\n });\n\n this.partial = this.partial.bind(this);\n this.push = this.push.bind(this);\n this.replace = this.replace.bind(this);\n this.getSearch = this.getSearch.bind(this);\n this.getHistory = this.getHistory.bind(this);\n this.getLocation = this.getLocation.bind(this);\n }\n\n getLocationObservable() {\n return this.locationObservable.asObservable();\n }\n\n getHistory() {\n return this.history;\n }\n\n getSearch() {\n return new URLSearchParams(this.history.location.search);\n }\n\n partial(query: Record<string, any>, replace?: boolean) {\n const currentLocation = this.history.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.history.replace(updatedUrl, this.history.location.state);\n } else {\n this.history.push(updatedUrl, this.history.location.state);\n }\n }\n\n push(location: H.Path | H.LocationDescriptor) {\n this.history.push(location);\n }\n\n replace(location: H.Path | H.LocationDescriptor) {\n this.history.replace(location);\n }\n\n reload() {\n const prevState = (this.history.location.state as any)?.routeReloadCounter;\n this.history.replace({\n ...this.history.location,\n state: { routeReloadCounter: prevState ? prevState + 1 : 1 },\n });\n }\n\n getLocation() {\n return this.history.location;\n }\n\n getSearchObject() {\n return locationSearchToObject(this.history.location.search);\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","import { BusEventBase, BusEventWithPayload, EventBus, GrafanaTheme2, PanelModel, TimeRange } from '@grafana/data';\n\n/**\n * Called when a dashboard is refreshed\n *\n * @public\n */\nexport class RefreshEvent extends BusEventBase {\n static type = 'refresh';\n}\n\n/**\n * Called when the theme settings change\n *\n * @public\n */\nexport class ThemeChangedEvent extends BusEventWithPayload<GrafanaTheme2> {\n static type = 'theme-changed';\n}\n\n/**\n * Called when time range is updated\n *\n * @public\n */\nexport class TimeRangeUpdatedEvent extends BusEventWithPayload<TimeRange> {\n static type = 'time-range-updated';\n}\n\n/**\n * Called to copy a panel JSON into local storage\n *\n * @public\n */\nexport class CopyPanelEvent extends BusEventWithPayload<PanelModel> {\n static type = 'copy-panel';\n}\n\n// Internal singleton instance\nlet singletonInstance: EventBus;\n\n/**\n * Used during startup by Grafana to set the setAppEvents so it is available\n * via the {@link setAppEvents} to the rest of the application.\n *\n * @internal\n */\nexport function setAppEvents(instance: EventBus) {\n singletonInstance = instance;\n}\n\n/**\n * Used to retrieve an event bus that manages application level events\n *\n * @public\n */\nexport function getAppEvents(): EventBus {\n return singletonInstance;\n}\n","import { config } from '../config';\nimport { locationService } from '../services';\nimport { getEchoSrv, EchoEventType } from '../services/EchoSrv';\n\nimport {\n ExperimentViewEchoEvent,\n InteractionEchoEvent,\n MetaAnalyticsEvent,\n MetaAnalyticsEventPayload,\n PageviewEchoEvent,\n} from './types';\n\n/**\n * Helper function to report meta analytics to the {@link EchoSrv}.\n *\n * @public\n */\nexport const reportMetaAnalytics = (payload: MetaAnalyticsEventPayload) => {\n getEchoSrv().addEvent<MetaAnalyticsEvent>({\n type: EchoEventType.MetaAnalytics,\n payload,\n });\n};\n\n/**\n * Helper function to report pageview events to the {@link EchoSrv}.\n *\n * @public\n */\nexport const reportPageview = () => {\n const location = locationService.getLocation();\n const page = `${config.appSubUrl ?? ''}${location.pathname}${location.search}${location.hash}`;\n getEchoSrv().addEvent<PageviewEchoEvent>({\n type: EchoEventType.Pageview,\n payload: {\n page,\n },\n });\n};\n\n/**\n * Helper function to report interaction events to the {@link EchoSrv}.\n *\n * @public\n */\nexport const reportInteraction = (interactionName: string, properties?: Record<string, unknown>) => {\n // get static reporting context and append it to properties\n if (config.reportingStaticContext && config.reportingStaticContext instanceof Object) {\n properties = { ...properties, ...config.reportingStaticContext };\n }\n getEchoSrv().addEvent<InteractionEchoEvent>({\n type: EchoEventType.Interaction,\n payload: {\n interactionName,\n properties,\n },\n });\n};\n\n/**\n * Helper function to report experimentview events to the {@link EchoSrv}.\n *\n * @public\n */\nexport const reportExperimentView = (id: string, group: string, variant: string) => {\n getEchoSrv().addEvent<ExperimentViewEchoEvent>({\n type: EchoEventType.ExperimentView,\n payload: {\n experimentId: id,\n experimentGroup: group,\n experimentVariant: variant,\n },\n });\n};\n","import * as H from 'history';\nimport { pick } from 'lodash';\nimport { BehaviorSubject, map, Observable } from 'rxjs';\n\nimport { reportInteraction } from '../analytics/utils';\nimport { config } from '../config';\n\nimport { HistoryWrapper, locationService as mainLocationService, LocationService } from './LocationService';\n\n// Only allow sidecar to be opened on these routes. It does not seem to make sense to keep the sidecar opened on\n// config/admin pages for example.\n// At this moment let's be restrictive about where the sidecar can show and add more routes if there is a need.\nconst ALLOW_ROUTES = [\n /(^\\/d\\/)/, // dashboards\n /^\\/explore/, // explore + explore metrics\n /^\\/a\\/[^\\/]+/, // app plugins\n /^\\/alerting/,\n];\n\n/**\n * This is a service that handles state and operation of a sidecar feature (sideview to render a second app in grafana).\n * At this moment this is highly experimental and if used should be understood to break easily with newer versions.\n * None of this functionality works without a feature toggle `appSidecar` being enabled.\n *\n * Right now this being in a single service is more of a practical tradeoff for easier isolation in the future these\n * APIs may be integrated into other services or features like app extensions, plugin system etc.\n *\n * @experimental\n */\nexport class SidecarService_EXPERIMENTAL {\n private _initialContext: BehaviorSubject<unknown | undefined>;\n\n private sidecarLocationService: LocationService;\n private mainLocationService: LocationService;\n\n // If true we don't close the sidecar when user navigates to another app or part of Grafana from where the sidecar\n // was opened.\n private follow = false;\n\n // Keep track of where the sidecar was originally opened for autoclose behaviour.\n private mainLocationWhenOpened: string | undefined;\n\n private mainOnAllowedRoute = false;\n\n constructor(mainLocationService: LocationService) {\n this._initialContext = new BehaviorSubject<unknown | undefined>(undefined);\n this.mainLocationService = mainLocationService;\n this.sidecarLocationService = new HistoryWrapper(\n createLocationStorageHistory({ storageKey: 'grafana.sidecar.history' })\n );\n this.handleMainLocationChanges();\n }\n\n private assertFeatureEnabled() {\n if (!config.featureToggles.appSidecar) {\n console.warn('The `appSidecar` feature toggle is not enabled, doing nothing.');\n return false;\n }\n\n return true;\n }\n\n private updateMainLocationWhenOpened() {\n const pathname = this.mainLocationService.getLocation().pathname;\n for (const route of ALLOW_ROUTES) {\n const match = pathname.match(route)?.[0];\n if (match) {\n this.mainLocationWhenOpened = match;\n return;\n }\n }\n }\n\n /**\n * Every time the main location changes we check if we should keep the sidecar open or close it based on list\n * of allowed routes and also based on the follow flag when opening the app.\n */\n private handleMainLocationChanges() {\n this.mainOnAllowedRoute = ALLOW_ROUTES.some((prefix) =>\n this.mainLocationService.getLocation().pathname.match(prefix)\n );\n\n this.mainLocationService.getLocationObservable().subscribe((location) => {\n this.mainOnAllowedRoute = ALLOW_ROUTES.some((prefix) => location.pathname.match(prefix));\n\n if (!this.activePluginId) {\n return;\n }\n\n if (!this.mainOnAllowedRoute) {\n this.closeApp();\n return;\n }\n\n // We check if we moved to some other app or part of grafana from where we opened the sidecar.\n const isTheSameLocation = Boolean(\n this.mainLocationWhenOpened && location.pathname.startsWith(this.mainLocationWhenOpened)\n );\n\n if (!(isTheSameLocation || this.follow)) {\n this.closeApp();\n }\n });\n }\n\n /**\n * Get current app id of the app in sidecar. This is most probably provisional. In the future\n * this should be driven by URL addressing so that routi