diff --git a/.betterer.results b/.betterer.results index d323fe5b2f5..17e26b00966 100644 --- a/.betterer.results +++ b/.betterer.results @@ -502,8 +502,8 @@ exports[`better eslint`] = { [0, 0, 0, "Do not use any type assertions.", "1"], [0, 0, 0, "Do not use any type assertions.", "2"], [0, 0, 0, "Do not use any type assertions.", "3"], - [0, 0, 0, "Unexpected any. Specify a different type.", "4"], - [0, 0, 0, "Unexpected any. Specify a different type.", "5"] + [0, 0, 0, "Do not use any type assertions.", "4"], + [0, 0, 0, "Do not use any type assertions.", "5"] ], "packages/grafana-runtime/src/services/EchoSrv.ts:5381": [ [0, 0, 0, "Unexpected any. Specify a different type.", "0"], diff --git a/e2e-playwright/smoke-tests-suite/panels.spec.ts b/e2e-playwright/smoke-tests-suite/panels.spec.ts index c65bd0d28ce..822b0ad90b4 100644 --- a/e2e-playwright/smoke-tests-suite/panels.spec.ts +++ b/e2e-playwright/smoke-tests-suite/panels.spec.ts @@ -1,5 +1,5 @@ +import { BootData } from '@grafana/data'; import { test, expect } from '@grafana/plugin-e2e'; -import { GrafanaBootConfig } from '@grafana/runtime'; test.describe( 'Panels smokescreen', @@ -25,7 +25,7 @@ test.describe( const panelTypes = await page.evaluate(() => { // @grafana/plugin-e2e doesn't export the full bootdata config // eslint-disable-next-line @typescript-eslint/consistent-type-assertions - const win = window as typeof window & { grafanaBootData: GrafanaBootConfig['bootData'] }; + const win = window as typeof window & { grafanaBootData: BootData }; return win.grafanaBootData?.settings?.panels ?? {}; }); diff --git a/e2e/old-arch/smoke-tests-suite/panels_smokescreen.spec.ts b/e2e/old-arch/smoke-tests-suite/panels_smokescreen.spec.ts index 4e546c88e1b..36f091803d7 100644 --- a/e2e/old-arch/smoke-tests-suite/panels_smokescreen.spec.ts +++ b/e2e/old-arch/smoke-tests-suite/panels_smokescreen.spec.ts @@ -1,4 +1,4 @@ -import { GrafanaBootConfig } from '@grafana/runtime'; +import { BootData } from '@grafana/data'; import { e2e } from '../utils'; @@ -22,7 +22,7 @@ describe('Panels smokescreen', () => { visitDashboardAtStart: false, }); - cy.window().then((win: Cypress.AUTWindow & { grafanaBootData: GrafanaBootConfig['bootData'] }) => { + cy.window().then((win: Cypress.AUTWindow & { grafanaBootData: BootData }) => { // Loop through every panel type and ensure no crash Object.entries(win.grafanaBootData.settings.panels).forEach(([_, panel]) => { // TODO: Remove Flame Graph check as part of addressing #66803 diff --git a/packages/grafana-data/src/index.ts b/packages/grafana-data/src/index.ts index c530b03a6aa..d1d302275d1 100644 --- a/packages/grafana-data/src/index.ts +++ b/packages/grafana-data/src/index.ts @@ -451,8 +451,11 @@ export { getLinksSupplier } from './field/fieldOverrides'; // Types export { isUnsignedPluginSignature } from './types/pluginSignature'; export type { + AzureSettings, + AzureCloudInfo, CurrentUserDTO, AnalyticsSettings, + AppPluginConfig, BootData, OAuth, OAuthSettings, @@ -460,6 +463,8 @@ export type { GrafanaConfig, BuildInfo, LicenseInfo, + PreinstalledPlugin, + UnifiedAlertingConfig, } from './types/config'; export { availableIconsIndex, type IconName, isIconName, toIconName } from './types/icon'; export type { WithAccessControlMetadata } from './types/accesscontrol'; diff --git a/packages/grafana-data/src/transformations/matchers/nameMatcher.test.ts b/packages/grafana-data/src/transformations/matchers/nameMatcher.test.ts index f55bc1fce61..a8259b226d9 100644 --- a/packages/grafana-data/src/transformations/matchers/nameMatcher.test.ts +++ b/packages/grafana-data/src/transformations/matchers/nameMatcher.test.ts @@ -1,19 +1,18 @@ import { toDataFrame } from '../../dataframe/processDataFrame'; +import { BootData } from '../../types/config'; import { DataFrame, FieldType } from '../../types/dataFrame'; import { getFieldMatcher } from '../matchers'; import { FieldMatcherID } from './ids'; import { ByNamesMatcherMode } from './nameMatcher'; -// mock the default window.grafanaBootData settings -// eslint-disable-next-line -(window as any).grafanaBootData = { +window.grafanaBootData = { settings: { featureToggles: { dataplaneFrontendFallback: true, }, }, -}; +} as BootData; describe('Field Name by Regexp Matcher', () => { it('Match all with wildcard regex', () => { diff --git a/packages/grafana-data/src/transformations/matchers/nameMatcher.ts b/packages/grafana-data/src/transformations/matchers/nameMatcher.ts index 52d44a36b19..5a344ed4abd 100644 --- a/packages/grafana-data/src/transformations/matchers/nameMatcher.ts +++ b/packages/grafana-data/src/transformations/matchers/nameMatcher.ts @@ -109,8 +109,7 @@ export function fieldNameFallback(fields: Set) { // grafana-data does not have access to runtime so we are accessing the window object // to get access to the feature toggle - // eslint-disable-next-line - const useMatcherFallback = (window as any)?.grafanaBootData?.settings?.featureToggles?.dataplaneFrontendFallback; + const useMatcherFallback = window.grafanaBootData?.settings?.featureToggles?.dataplaneFrontendFallback; if (useMatcherFallback) { if (fields.has(TIME_SERIES_VALUE_FIELD_NAME)) { fallback = (field: Field, frame: DataFrame) => { diff --git a/packages/grafana-data/src/transformations/transformers/groupingToMatrix.ts b/packages/grafana-data/src/transformations/transformers/groupingToMatrix.ts index 2a9ae7eb03b..39614c52042 100644 --- a/packages/grafana-data/src/transformations/transformers/groupingToMatrix.ts +++ b/packages/grafana-data/src/transformations/transformers/groupingToMatrix.ts @@ -28,8 +28,7 @@ const DEFAULT_EMPTY_VALUE = SpecialValue.Empty; // grafana-data does not have access to runtime so we are accessing the window object // to get access to the feature toggle -// eslint-disable-next-line -const supportDataplaneFallback = (window as any)?.grafanaBootData?.settings?.featureToggles?.dataplaneFrontendFallback; +const supportDataplaneFallback = window.grafanaBootData?.settings?.featureToggles?.dataplaneFrontendFallback; export const groupingToMatrixTransformer: DataTransformerInfo = { id: DataTransformerID.groupingToMatrix, diff --git a/packages/grafana-data/src/transformations/transformers/utils.ts b/packages/grafana-data/src/transformations/transformers/utils.ts index 29ac89b29ee..9aa4d96a9e8 100644 --- a/packages/grafana-data/src/transformations/transformers/utils.ts +++ b/packages/grafana-data/src/transformations/transformers/utils.ts @@ -1,12 +1,6 @@ -import { BootData } from '../../types/config'; import { DataFrame } from '../../types/dataFrame'; import { SpecialValue } from '../../types/transformations'; -declare global { - interface Window { - grafanaBootData?: BootData; - } -} /** * Retrieve the maximum number of fields in a series of a dataframe. */ diff --git a/packages/grafana-data/src/types/config.ts b/packages/grafana-data/src/types/config.ts index 4c9e91e5c95..2ef0d54b2de 100644 --- a/packages/grafana-data/src/types/config.ts +++ b/packages/grafana-data/src/types/config.ts @@ -1,6 +1,5 @@ import { SystemDateFormatSettings } from '../datetime/formats'; import { MapLayerOptions } from '../geo/layer'; -import { GrafanaTheme2 } from '../themes/types'; import { DataSourceInstanceSettings } from './datasource'; import { FeatureToggles } from './featureToggles.gen'; @@ -8,9 +7,41 @@ import { IconName } from './icon'; import { NavLinkDTO } from './navModel'; import { OrgRole } from './orgs'; import { PanelPluginMeta } from './panel'; -import { GrafanaTheme } from './theme'; +import { AngularMeta, PluginDependencies, PluginExtensions, PluginLoadingStrategy } from './plugin'; import { TimeOption } from './time'; +export interface AzureSettings { + cloud?: string; + clouds?: AzureCloudInfo[]; + managedIdentityEnabled: boolean; + workloadIdentityEnabled: boolean; + userIdentityEnabled: boolean; + userIdentityFallbackCredentialsEnabled: boolean; + azureEntraPasswordCredentialsEnabled: boolean; +} + +export interface AzureCloudInfo { + name: string; + displayName: string; +} + +export type AppPluginConfig = { + id: string; + path: string; + version: string; + preload: boolean; + angular: AngularMeta; + loadingStrategy: PluginLoadingStrategy; + dependencies: PluginDependencies; + extensions: PluginExtensions; + moduleHash?: string; +}; + +export type PreinstalledPlugin = { + id: string; + version: string; +}; + /** * Describes the build information that will be available via the Grafana configuration. * @@ -21,7 +52,9 @@ export interface BuildInfo { version: string; // Version to show in the UI instead of version versionString: string; + buildstamp: number; commit: string; + commitShort: string; env: string; edition: GrafanaEdition; latestVersion: string; @@ -108,8 +141,9 @@ export interface AnalyticsSettings { intercomIdentifier?: string; } -/** Current user info included in bootData - * +/** + * Current user info included in bootData. + * Corresponds to `window.grafanaBootData.user` * @internal */ export interface CurrentUserDTO { @@ -139,8 +173,9 @@ export interface CurrentUserDTO { lightTheme: boolean; } -/** Contains essential user and config info - * +/** + * Contains essential user and config info. + * Corresponds to `window.grafanaBootData`. * @internal */ export interface BootData { @@ -155,21 +190,26 @@ export interface BootData { /** * Describes all the different Grafana configuration values available for an instance. - * + * Corresponds to `window.grafanaBootData.settings`. + * If you want to access these values, use the `config` object from `@grafana/runtime`. * @internal */ export interface GrafanaConfig { - publicDashboardAccessToken?: string; + publicDashboardAccessToken: string; publicDashboardsEnabled: boolean; snapshotEnabled: boolean; datasources: { [str: string]: DataSourceInstanceSettings }; panels: { [key: string]: PanelPluginMeta }; + apps: Record; auth: AuthSettings; minRefreshInterval: string; + appUrl: string; appSubUrl: string; + azure: AzureSettings; + jwtHeaderName: string; + jwtUrlLogin: boolean; windowTitlePrefix: string; buildInfo: BuildInfo; - bootData: BootData; externalUserMngLinkUrl: string; externalUserMngLinkName: string; externalUserMngInfo: string; @@ -178,6 +218,8 @@ export interface GrafanaConfig { allowOrgCreate: boolean; disableLoginForm: boolean; defaultDatasource: string; + defaultDatasourceManageAlertsUIToggle: boolean; + defaultAllowRecordingRulesTargetAlertsUIToggle: boolean; authProxyEnabled: boolean; exploreEnabled: boolean; queryHistoryEnabled: boolean; @@ -188,6 +230,9 @@ export interface GrafanaConfig { sigV4AuthEnabled: boolean; azureAuthEnabled: boolean; samlEnabled: boolean; + samlName: string; + awsAllowedAuthProviders: string[]; + awsAssumeRoleProvided: boolean; autoAssignOrg: boolean; verifyEmailEnabled: boolean; oauth: OAuthSettings; @@ -201,57 +246,77 @@ export interface GrafanaConfig { disableSanitizeHtml: boolean; trustedTypesDefaultPolicyEnabled: boolean; cspReportOnlyEnabled: boolean; + expressionsEnabled: boolean; liveEnabled: boolean; liveMessageSizeLimit: number; - /** @deprecated Use `theme2` instead. */ - theme: GrafanaTheme; - theme2: GrafanaTheme2; anonymousEnabled: boolean; - anonymousDeviceLimit: number | undefined; + anonymousDeviceLimit: number; featureToggles: FeatureToggles; licenseInfo: LicenseInfo; http2Enabled: boolean; dateFormats?: SystemDateFormatSettings; grafanaJavascriptAgent: GrafanaJavascriptAgentConfig; - geomapDefaultBaseLayer?: MapLayerOptions; - geomapDisableCustomBaseLayer?: boolean; + geomapDefaultBaseLayerConfig?: MapLayerOptions; + geomapDisableCustomBaseLayer: boolean; unifiedAlertingEnabled: boolean; unifiedAlerting: UnifiedAlertingConfig; feedbackLinksEnabled: boolean; supportBundlesEnabled: boolean; secureSocksDSProxyEnabled: boolean; - googleAnalyticsId: string | undefined; - googleAnalytics4Id: string | undefined; + enableFrontendSandboxForPlugins: string[]; + googleAnalyticsId: string; + googleAnalytics4Id: string; googleAnalytics4SendManualPageViews: boolean; - rudderstackWriteKey: string | undefined; - rudderstackDataPlaneUrl: string | undefined; - rudderstackSdkUrl: string | undefined; - rudderstackConfigUrl: string | undefined; - rudderstackIntegrationsUrl: string | undefined; + rudderstackWriteKey: string; + rudderstackDataPlaneUrl: string; + rudderstackSdkUrl: string; + rudderstackConfigUrl: string; + rudderstackIntegrationsUrl: string; + applicationInsightsConnectionString: string; + applicationInsightsEndpointUrl: string; analyticsConsoleReporting: boolean; + rendererAvailable: boolean; + rendererVersion: string; + rendererDefaultImageWidth: number; + rendererDefaultImageHeight: number; + rendererDefaultImageScale: number; dashboardPerformanceMetrics: string[]; panelSeriesLimit: number; sqlConnectionLimits: SqlConnectionLimits; - sharedWithMeFolderUID?: string; - rootFolderUID?: string; - localFileSystemAvailable?: boolean; - cloudMigrationIsTarget?: boolean; - listDashboardScopesEndpoint?: string; - listScopesEndpoint?: string; - reportingStaticContext?: Record; - exploreDefaultTimeOffset?: string; - exploreHideLogsDownload?: boolean; + sharedWithMeFolderUID: string; + rootFolderUID: string; + localFileSystemAvailable: boolean; + cloudMigrationIsTarget: boolean; + cloudMigrationPollIntervalMs: number; + pluginCatalogURL: string; + pluginAdminEnabled: boolean; + pluginAdminExternalManageEnabled: boolean; + pluginCatalogHiddenPlugins: string[]; + pluginCatalogManagedPlugins: string[]; + pluginCatalogPreinstalledPlugins: PreinstalledPlugin[]; + pluginsCDNBaseURL: string; + tokenExpirationDayLimit: number; + listDashboardScopesEndpoint: string; + listScopesEndpoint: string; + reportingStaticContext: Record; + exploreDefaultTimeOffset: string; + exploreHideLogsDownload: boolean; quickRanges?: TimeOption[]; // The namespace to use for kubernetes apiserver requests namespace: string; - - /** - * Language used in Grafana's UI. This is after the user's preference (or deteceted locale) is resolved to one of - * Grafana's supported language. - */ - language: string | undefined; - regionalFormat: string; + caching: { + enabled: boolean; + }; + recordedQueries: { + enabled: boolean; + }; + reporting: { + enabled: boolean; + }; + analytics: { + enabled: boolean; + }; } export interface SqlConnectionLimits { diff --git a/packages/grafana-runtime/src/config.ts b/packages/grafana-runtime/src/config.ts index d39d1526b5a..ba898a0860e 100644 --- a/packages/grafana-runtime/src/config.ts +++ b/packages/grafana-runtime/src/config.ts @@ -1,18 +1,20 @@ import { merge } from 'lodash'; import { + AppPluginConfig as AppPluginConfigGrafanaData, AuthSettings, + AzureSettings as AzureSettingsGrafanaData, BootData, BuildInfo, DataSourceInstanceSettings, FeatureToggles, - GrafanaConfig, GrafanaTheme, GrafanaTheme2, LicenseInfo, MapLayerOptions, OAuthSettings, PanelPluginMeta, + PreinstalledPlugin as PreinstalledPluginGrafanaData, systemDateFormats, SystemDateFormatSettings, getThemeById, @@ -21,8 +23,15 @@ import { PluginDependencies, PluginExtensions, TimeOption, + UnifiedAlertingConfig, + GrafanaConfig, + CurrentUserDTO, } from '@grafana/data'; +/** + * @deprecated Use the type from `@grafana/data` + */ +// TODO remove in G13 export interface AzureSettings { cloud?: string; clouds?: AzureCloudInfo[]; @@ -33,11 +42,19 @@ export interface AzureSettings { azureEntraPasswordCredentialsEnabled: boolean; } +/** + * @deprecated Use the type from `@grafana/data` + */ +// TODO remove in G13 export interface AzureCloudInfo { name: string; displayName: string; } +/** + * @deprecated Use the type from `@grafana/data` + */ +// TODO remove in G13 export type AppPluginConfig = { id: string; path: string; @@ -50,25 +67,37 @@ export type AppPluginConfig = { moduleHash?: string; }; +/** + * @deprecated Use the type from `@grafana/data` + */ +// TODO remove in G13 export type PreinstalledPlugin = { id: string; version: string; }; -export class GrafanaBootConfig implements GrafanaConfig { +/** + * Use to access Grafana config settings in application code. + * This takes `window.grafanaBootData.settings` as input and returns a config object. + */ +export class GrafanaBootConfig { publicDashboardAccessToken?: string; publicDashboardsEnabled = true; snapshotEnabled = true; datasources: { [str: string]: DataSourceInstanceSettings } = {}; panels: { [key: string]: PanelPluginMeta } = {}; - apps: Record = {}; + apps: Record = {}; auth: AuthSettings = {}; minRefreshInterval = ''; appUrl = ''; appSubUrl = ''; namespace = 'default'; - windowTitlePrefix = ''; - buildInfo: BuildInfo; + windowTitlePrefix = 'Grafana - '; + buildInfo: BuildInfo = { + version: '1.0', + commit: '1', + env: 'production', + } as BuildInfo; bootData: BootData; externalUserMngLinkUrl = ''; externalUserMngLinkName = ''; @@ -100,7 +129,7 @@ export class GrafanaBootConfig implements GrafanaConfig { disableUserSignUp = false; loginHint = ''; passwordHint = ''; - loginError: string | undefined = undefined; + loginError?: string; viewersCanEdit = false; disableSanitizeHtml = false; trustedTypesDefaultPolicyEnabled = false; @@ -112,7 +141,7 @@ export class GrafanaBootConfig implements GrafanaConfig { theme2: GrafanaTheme2; featureToggles: FeatureToggles = {}; anonymousEnabled = false; - anonymousDeviceLimit: number | undefined = undefined; + anonymousDeviceLimit?: number; licenseInfo: LicenseInfo = {} as LicenseInfo; rendererAvailable = false; rendererVersion = ''; @@ -137,12 +166,12 @@ export class GrafanaBootConfig implements GrafanaConfig { pluginAdminExternalManageEnabled = false; pluginCatalogHiddenPlugins: string[] = []; pluginCatalogManagedPlugins: string[] = []; - pluginCatalogPreinstalledPlugins: PreinstalledPlugin[] = []; + pluginCatalogPreinstalledPlugins: PreinstalledPluginGrafanaData[] = []; pluginsCDNBaseURL = ''; expressionsEnabled = false; awsAllowedAuthProviders: string[] = []; awsAssumeRoleEnabled = false; - azure: AzureSettings = { + azure: AzureSettingsGrafanaData = { managedIdentityEnabled: false, workloadIdentityEnabled: false, userIdentityEnabled: false, @@ -155,7 +184,7 @@ export class GrafanaBootConfig implements GrafanaConfig { geomapDefaultBaseLayerConfig?: MapLayerOptions; geomapDisableCustomBaseLayer?: boolean; unifiedAlertingEnabled = false; - unifiedAlerting = { + unifiedAlerting: UnifiedAlertingConfig = { minInterval: '', alertStateHistoryBackend: undefined, alertStateHistoryPrimary: undefined, @@ -176,14 +205,14 @@ export class GrafanaBootConfig implements GrafanaConfig { analytics = { enabled: true, }; - googleAnalyticsId: undefined; - googleAnalytics4Id: undefined; + googleAnalyticsId?: string; + googleAnalytics4Id?: string; googleAnalytics4SendManualPageViews = false; - rudderstackWriteKey: undefined; - rudderstackDataPlaneUrl: undefined; - rudderstackSdkUrl: undefined; - rudderstackConfigUrl: undefined; - rudderstackIntegrationsUrl: undefined; + rudderstackWriteKey?: string; + rudderstackDataPlaneUrl?: string; + rudderstackSdkUrl?: string; + rudderstackConfigUrl?: string; + rudderstackIntegrationsUrl?: string; analyticsConsoleReporting = false; dashboardPerformanceMetrics: string[] = []; panelSeriesLimit = 0; @@ -194,17 +223,16 @@ export class GrafanaBootConfig implements GrafanaConfig { }; defaultDatasourceManageAlertsUiToggle = true; defaultAllowRecordingRulesTargetAlertsUiToggle = true; - - tokenExpirationDayLimit: undefined; + tokenExpirationDayLimit?: number; enableFrontendSandboxForPlugins: string[] = []; - sharedWithMeFolderUID: string | undefined; - rootFolderUID: string | undefined; - localFileSystemAvailable: boolean | undefined; - cloudMigrationIsTarget: boolean | undefined; + sharedWithMeFolderUID?: string; + rootFolderUID?: string; + localFileSystemAvailable?: boolean; + cloudMigrationIsTarget?: boolean; cloudMigrationPollIntervalMs = 2000; reportingStaticContext?: Record; exploreDefaultTimeOffset = '1h'; - exploreHideLogsDownload: boolean | undefined; + exploreHideLogsDownload?: boolean; quickRanges?: TimeOption[]; /** @@ -218,30 +246,17 @@ export class GrafanaBootConfig implements GrafanaConfig { * This is the regionalFormat that is used for date formatting and other locale-specific features. */ regionalFormat: string; + listDashboardScopesEndpoint = ''; + listScopesEndpoint = ''; - constructor(options: GrafanaBootConfig) { + constructor( + options: BootData['settings'] & { + bootData: BootData; + } + ) { this.bootData = options.bootData; - const defaults = { - datasources: {}, - windowTitlePrefix: 'Grafana - ', - panels: {}, - playlist_timespan: '1m', - unsaved_changes_warning: true, - appUrl: '', - appSubUrl: '', - buildInfo: { - version: '1.0', - commit: '1', - env: 'production', - }, - viewersCanEdit: false, - disableSanitizeHtml: false, - }; - - merge(this, defaults, options); - - this.buildInfo = options.buildInfo || defaults.buildInfo; + merge(this, options); if (this.dateFormats) { systemDateFormats.update(this.dateFormats); @@ -256,9 +271,6 @@ export class GrafanaBootConfig implements GrafanaConfig { this.theme = this.theme2.v1; this.regionalFormat = options.bootData.user.regionalFormat; } - geomapDefaultBaseLayer?: MapLayerOptions | undefined; - listDashboardScopesEndpoint?: string | undefined; - listScopesEndpoint?: string | undefined; } // localstorage key: grafana.featureToggles @@ -309,7 +321,7 @@ function overrideFeatureTogglesFromUrl(config: GrafanaBootConfig) { }); } -let bootData = (window as any).grafanaBootData; +let bootData = window.grafanaBootData; if (!bootData) { if (process.env.NODE_ENV !== 'test') { @@ -317,18 +329,25 @@ if (!bootData) { } bootData = { - settings: {}, - user: {}, + assets: { + dark: '', + light: '', + }, + settings: {} as GrafanaConfig, + user: {} as CurrentUserDTO, navTree: [], }; } -const options = bootData.settings; -options.bootData = bootData; - /** * Use this to access the {@link GrafanaBootConfig} for the current running Grafana instance. * * @public */ -export const config = new GrafanaBootConfig(options); +export const config = new GrafanaBootConfig({ + ...bootData.settings, + // need to separately include bootData here + // this allows people to access the user object on config.bootData.user and maintains backwards compatibility + // TODO expose a user object (similar to `GrafanaBootConfig`) and deprecate this recursive bootData + bootData, +}); diff --git a/packages/grafana-ui/src/components/DateTimePickers/WeekStartPicker.tsx b/packages/grafana-ui/src/components/DateTimePickers/WeekStartPicker.tsx index 99ebf2d3b3a..0207dcb67a8 100644 --- a/packages/grafana-ui/src/components/DateTimePickers/WeekStartPicker.tsx +++ b/packages/grafana-ui/src/components/DateTimePickers/WeekStartPicker.tsx @@ -1,6 +1,5 @@ import { useCallback, useMemo } from 'react'; -import { BootData } from '@grafana/data'; import { selectors } from '@grafana/e2e-selectors'; import { t } from '@grafana/i18n'; @@ -23,12 +22,6 @@ export function isWeekStart(value: string): value is WeekStart { return ['saturday', 'sunday', 'monday'].includes(value); } -declare global { - interface Window { - grafanaBootData?: BootData; - } -} - /** * Returns the system or user defined week start (as defined in bootData) * Or you can pass in an override weekStart string and have it be validated and returned as WeekStart type if valid diff --git a/packages/grafana-ui/src/slate-plugins/suggestions.tsx b/packages/grafana-ui/src/slate-plugins/suggestions.tsx index 1d22c988822..de89e5c9263 100644 --- a/packages/grafana-ui/src/slate-plugins/suggestions.tsx +++ b/packages/grafana-ui/src/slate-plugins/suggestions.tsx @@ -1,8 +1,6 @@ import { debounce, sortBy } from 'lodash'; import { Editor, Plugin as SlatePlugin } from 'slate-react'; -import { BootData } from '@grafana/data'; - import { Typeahead } from '../components/Typeahead/Typeahead'; import { CompletionItem, SuggestionsState, TypeaheadInput, TypeaheadOutput } from '../types/completion'; import { SearchFunctionType, SearchFunctionMap } from '../utils/searchFunctions'; @@ -12,12 +10,6 @@ import TOKEN_MARK from './slate-prism/TOKEN_MARK'; export const TYPEAHEAD_DEBOUNCE = 250; -declare global { - interface Window { - grafanaBootData?: BootData; - } -} - // Commands added to the editor by this plugin. interface SuggestionsPluginCommands { selectSuggestion: (suggestion: CompletionItem) => Editor; diff --git a/public/app/app.ts b/public/app/app.ts index 5c48558c30c..1de53e89c3d 100644 --- a/public/app/app.ts +++ b/public/app/app.ts @@ -216,7 +216,7 @@ export class GrafanaApp { // Login redirect requires locationUtil to be initialized locationUtil.initialize({ - config, + config: window.grafanaBootData.settings, getTimeRangeForUrl: getTimeSrv().timeRangeForUrl, getVariablesUrlParams: getVariablesUrlParams, }); diff --git a/public/app/core/components/NestedFolderPicker/useFoldersQuery.test.tsx b/public/app/core/components/NestedFolderPicker/useFoldersQuery.test.tsx index cf0f0f67af1..23460388f4e 100644 --- a/public/app/core/components/NestedFolderPicker/useFoldersQuery.test.tsx +++ b/public/app/core/components/NestedFolderPicker/useFoldersQuery.test.tsx @@ -1,7 +1,6 @@ import { ReactNode } from 'react'; import { act, getWrapper, renderHook, waitFor } from 'test/test-utils'; -import { GrafanaConfig } from '@grafana/data'; import * as runtime from '@grafana/runtime'; import { setupMockServer } from '@grafana/test-utils/server'; import { getFolderFixtures } from '@grafana/test-utils/unstable'; @@ -23,7 +22,7 @@ const wrapper = ({ children }: { children: ReactNode }) => { }; describe('useFoldersQuery', () => { - let configBackup: GrafanaConfig; + let configBackup: runtime.GrafanaBootConfig; beforeAll(() => { configBackup = { ...runtime.config }; diff --git a/public/app/core/config.ts b/public/app/core/config.ts index ac3c63f01c6..6c757c9436a 100644 --- a/public/app/core/config.ts +++ b/public/app/core/config.ts @@ -1,6 +1,6 @@ import { PluginState } from '@grafana/data'; import { config, GrafanaBootConfig } from '@grafana/runtime'; -export { config, GrafanaBootConfig as Settings }; +export { config, type GrafanaBootConfig as Settings }; let grafanaConfig: GrafanaBootConfig = config; diff --git a/public/app/core/context/GrafanaContext.ts b/public/app/core/context/GrafanaContext.ts index 1f3bf86372b..edda20034cc 100644 --- a/public/app/core/context/GrafanaContext.ts +++ b/public/app/core/context/GrafanaContext.ts @@ -1,7 +1,6 @@ import { createContext, useCallback, useContext } from 'react'; -import { GrafanaConfig } from '@grafana/data'; -import { LocationService, locationService, BackendSrv } from '@grafana/runtime'; +import { LocationService, locationService, BackendSrv, GrafanaBootConfig } from '@grafana/runtime'; import { AppChromeService } from '../components/AppChrome/AppChromeService'; import { NewFrontendAssetsChecker } from '../services/NewFrontendAssetsChecker'; @@ -10,7 +9,7 @@ import { KeybindingSrv } from '../services/keybindingSrv'; export interface GrafanaContextType { backend: BackendSrv; location: LocationService; - config: GrafanaConfig; + config: GrafanaBootConfig; chrome: AppChromeService; keybindings: KeybindingSrv; newAssetsChecker: NewFrontendAssetsChecker; diff --git a/public/app/core/services/echo/backends/grafana-javascript-agent/GrafanaJavascriptAgentBackend.test.ts b/public/app/core/services/echo/backends/grafana-javascript-agent/GrafanaJavascriptAgentBackend.test.ts index 6e6188454d8..13d18fb8977 100644 --- a/public/app/core/services/echo/backends/grafana-javascript-agent/GrafanaJavascriptAgentBackend.test.ts +++ b/public/app/core/services/echo/backends/grafana-javascript-agent/GrafanaJavascriptAgentBackend.test.ts @@ -55,8 +55,10 @@ describe('GrafanaJavascriptAgentEchoBackend', () => { }); const buildInfo: BuildInfo = { + buildstamp: 12345, version: '1.0', commit: 'abcd123', + commitShort: 'abc', env: 'production', versionString: 'Grafana v1.0 (abcd123)', edition: GrafanaEdition.OpenSource, diff --git a/public/app/core/utils/explore.test.ts b/public/app/core/utils/explore.test.ts index d8d2b5343e9..4701cf7e019 100644 --- a/public/app/core/utils/explore.test.ts +++ b/public/app/core/utils/explore.test.ts @@ -7,7 +7,6 @@ import { LogsSortOrder, serializeStateToUrlParam, } from '@grafana/data'; -import { config } from '@grafana/runtime'; import { DataQuery } from '@grafana/schema'; import { RefreshPicker } from '@grafana/ui'; import { getTimeSrv } from 'app/features/dashboard/services/TimeSrv'; @@ -174,7 +173,7 @@ describe('getExploreUrl', () => { afterAll(() => { // Reset locationUtil locationUtil.initialize({ - config, + config: window.grafanaBootData.settings, getTimeRangeForUrl: getTimeSrv().timeRangeForUrl, getVariablesUrlParams: getVariablesUrlParams, }); diff --git a/public/app/features/alerting/unified/rule-editor/formDefaults.test.ts b/public/app/features/alerting/unified/rule-editor/formDefaults.test.ts index 88b3fbed717..8cdff983960 100644 --- a/public/app/features/alerting/unified/rule-editor/formDefaults.test.ts +++ b/public/app/features/alerting/unified/rule-editor/formDefaults.test.ts @@ -1,4 +1,3 @@ -import { GrafanaConfig } from '@grafana/data'; import { config, getDataSourceSrv } from '@grafana/runtime'; import { mockAlertQuery, mockDataSource, mockReduceExpression, mockThresholdExpression } from '../mocks'; @@ -201,8 +200,7 @@ describe('getDefaultManualRouting', () => { }); describe('getDefaultFormValues', () => { - // This is for Typescript. GrafanaBootConfig returns narrower types than GrafanaConfig - const grafanaConfig: GrafanaConfig = config; + const grafanaConfig = config; const uaConfig = grafanaConfig.unifiedAlerting; const mockGetInstanceSettings = jest.fn(); diff --git a/public/app/types/window.d.ts b/public/app/types/window.d.ts index c1614d622cd..3e31de78bd0 100644 --- a/public/app/types/window.d.ts +++ b/public/app/types/window.d.ts @@ -4,6 +4,7 @@ export declare global { __grafana_app_bundle_loaded: boolean; __grafana_public_path__: string; __grafana_load_failed: () => void; + grafanaBootData: import('@grafana/data').BootData; /** * (Potential) wait for API call to fetch boot data and place it on `window.grafanaBootData`. diff --git a/public/test/mocks/getGrafanaContextMock.ts b/public/test/mocks/getGrafanaContextMock.ts index fd6aaec843e..64e704986b7 100644 --- a/public/test/mocks/getGrafanaContextMock.ts +++ b/public/test/mocks/getGrafanaContextMock.ts @@ -1,5 +1,4 @@ -import { GrafanaConfig } from '@grafana/data'; -import { LocationService } from '@grafana/runtime'; +import { GrafanaBootConfig, LocationService } from '@grafana/runtime'; import { AppChromeService } from 'app/core/components/AppChrome/AppChromeService'; import { GrafanaContextType } from 'app/core/context/GrafanaContext'; import { NewFrontendAssetsChecker } from 'app/core/services/NewFrontendAssetsChecker'; @@ -14,7 +13,7 @@ export function getGrafanaContextMock(overrides: Partial = { // eslint-disable-next-line location: {} as LocationService, // eslint-disable-next-line - config: { featureToggles: {} } as GrafanaConfig, + config: { featureToggles: {} } as GrafanaBootConfig, // eslint-disable-next-line keybindings: { clearAndInitGlobalBindings: jest.fn(),