diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index b5ab11ee3dd..b6492e30065 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -428,8 +428,6 @@ /packages/grafana-ui/src/graveyard/TimeSeries/ @grafana/dataviz-squad /packages/grafana-ui/src/utils/storybook/ @grafana/plugins-platform-frontend -/plugins-bundled/ @grafana/plugins-platform-frontend - # root files, mostly frontend /.browserslistrc @grafana/frontend-ops /package.json @grafana/frontend-ops diff --git a/.github/pr-commands.json b/.github/pr-commands.json index fa5dd96fd95..1803aa29a8a 100644 --- a/.github/pr-commands.json +++ b/.github/pr-commands.json @@ -14,7 +14,6 @@ "public/**/*", "packages/**/*", "e2e/**/*", - "plugins-bundled/**/*", "scripts/build/release-packages.sh", "scripts/circle-release-next-packages.sh", "scripts/ci-frontend-metrics.sh", @@ -437,4 +436,4 @@ "action": "updateLabel", "addLabel": "area/panel/table" } -] \ No newline at end of file +] diff --git a/.github/renovate.json5 b/.github/renovate.json5 index 3e76842a4e3..6cc2ac80423 100644 --- a/.github/renovate.json5 +++ b/.github/renovate.json5 @@ -19,7 +19,7 @@ "nx" ], includePaths: ["package.json", "packages/**", "public/app/plugins/**"], - ignorePaths: ["emails/**", "plugins-bundled/**", "**/mocks/**"], + ignorePaths: ["emails/**", "**/mocks/**"], labels: ["area/frontend", "dependencies", "no-changelog"], postUpdateOptions: ["yarnDedupeHighest"], packageRules: [ diff --git a/Dockerfile b/Dockerfile index 44840f15f46..5c78116f47b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -16,7 +16,6 @@ WORKDIR /tmp/grafana COPY package.json project.json nx.json yarn.lock .yarnrc.yml ./ COPY .yarn .yarn COPY packages packages -COPY plugins-bundled plugins-bundled COPY public public COPY LICENSE ./ COPY conf/defaults.ini ./conf/defaults.ini diff --git a/Makefile b/Makefile index 88657f0cf77..7002e669b89 100644 --- a/Makefile +++ b/Makefile @@ -211,7 +211,6 @@ build-cli: ## Build Grafana CLI application. build-js: ## Build frontend assets. @echo "build frontend" yarn run build - yarn run plugins:build-bundled PLUGIN_ID ?= diff --git a/docs/sources/explore/get-started-with-explore.md b/docs/sources/explore/get-started-with-explore.md index 321bc709cbb..7e78e4e80c3 100644 --- a/docs/sources/explore/get-started-with-explore.md +++ b/docs/sources/explore/get-started-with-explore.md @@ -43,7 +43,7 @@ In order to access Explore, you must have either the `editor` or `administrator` Refer to [Role-based access control (RBAC)](https://grafana.com/docs/grafana//administration/roles-and-permissions/access-control/) in Grafana Enterprise to understand how you can manage Explore with role-based permissions. {{< admonition type="note" >}} -If you are using Grafana Cloud, open a [support ticket in the Cloud Portal](/https://grafana.com/auth/sign-in) to enable the `viewers_can_edit` option. +If you are using Grafana Cloud, open a [support ticket in the Cloud Portal](https://grafana.com/auth/sign-in) to enable the `viewers_can_edit` option. {{< /admonition >}} ## Explore elements diff --git a/docs/sources/setup-grafana/configure-grafana/feature-toggles/index.md b/docs/sources/setup-grafana/configure-grafana/feature-toggles/index.md index f9267ad1eb5..8c25a54b410 100644 --- a/docs/sources/setup-grafana/configure-grafana/feature-toggles/index.md +++ b/docs/sources/setup-grafana/configure-grafana/feature-toggles/index.md @@ -232,6 +232,7 @@ Experimental features might be changed or removed without prior notice. | `k8SFolderCounts` | Enable folder's api server counts | | `k8SFolderMove` | Enable folder's api server move | | `teamHttpHeadersMimir` | Enables LBAC for datasources for Mimir to apply LBAC filtering of metrics to the client requests for users in teams | +| `queryLibraryDashboards` | Enables Query Library feature in Dashboards | ## Development feature toggles diff --git a/package.json b/package.json index b6ab089bc35..90bbe52276b 100644 --- a/package.json +++ b/package.json @@ -50,7 +50,7 @@ "themes-generate": "esbuild --target=es6 ./scripts/cli/generateSassVariableFiles.ts --bundle --platform=node --tsconfig=./scripts/cli/tsconfig.json | node", "themes:usage": "eslint . --ignore-pattern '*.test.ts*' --ignore-pattern '*.spec.ts*' --cache --plugin '@grafana' --rule '{ @grafana/theme-token-usage: \"error\" }'", "typecheck": "tsc --noEmit && yarn run packages:typecheck", - "plugins:build-bundled": "find plugins-bundled -name package.json -not -path '*/node_modules/*' -execdir yarn build \\;", + "plugins:build-bundled": "echo 'bundled plugins are no longer supported'", "watch": "yarn start -d watch,start core:start --watchTheme", "ci:test-frontend": "yarn run test:ci", "i18n:stats": "node ./scripts/cli/reportI18nStats.mjs", @@ -213,7 +213,7 @@ "ngtemplate-loader": "2.1.0", "node-notifier": "10.0.1", "nx": "19.8.2", - "postcss": "8.4.49", + "postcss": "8.5.1", "postcss-loader": "8.1.1", "postcss-reporter": "7.1.0", "postcss-scss": "4.0.9", @@ -437,7 +437,6 @@ "packages": [ "packages/*", "packages/!(grafana-icons)/**", - "plugins-bundled/internal/*", "public/app/plugins/*/*", "e2e/test-plugins/*" ] diff --git a/packages/grafana-data/package.json b/packages/grafana-data/package.json index a647ed0fc70..088e8776df9 100644 --- a/packages/grafana-data/package.json +++ b/packages/grafana-data/package.json @@ -51,7 +51,7 @@ "moment": "2.30.1", "moment-timezone": "0.5.46", "ol": "7.4.0", - "papaparse": "5.4.1", + "papaparse": "5.5.1", "react-use": "17.6.0", "rxjs": "7.8.1", "string-hash": "^1.1.3", diff --git a/packages/grafana-data/src/types/featureToggles.gen.ts b/packages/grafana-data/src/types/featureToggles.gen.ts index 8c01b34d83e..f1dff9d6a38 100644 --- a/packages/grafana-data/src/types/featureToggles.gen.ts +++ b/packages/grafana-data/src/types/featureToggles.gen.ts @@ -252,4 +252,5 @@ export interface FeatureToggles { teamHttpHeadersMimir?: boolean; ABTestFeatureToggleA?: boolean; ABTestFeatureToggleB?: boolean; + queryLibraryDashboards?: boolean; } diff --git a/packages/grafana-runtime/src/index.ts b/packages/grafana-runtime/src/index.ts index ed6bbb27128..0c64456428b 100644 --- a/packages/grafana-runtime/src/index.ts +++ b/packages/grafana-runtime/src/index.ts @@ -57,3 +57,12 @@ export { hasPermission, hasPermissionInMetadata, hasAllPermissions, hasAnyPermis export { QueryEditorWithMigration } from './components/QueryEditorWithMigration'; export { type MigrationHandler, isMigrationHandler, migrateQuery, migrateRequest } from './utils/migrationHandler'; export { usePluginUserStorage } from './utils/userStorage'; +export { + type CorrelationsService, + type CorrelationData, + type CorrelationsData, + type CorrelationExternal, + type CorrelationQuery, + getCorrelationsService, + setCorrelationsService, +} from './services/CorrelationsService'; diff --git a/packages/grafana-runtime/src/services/CorrelationsService.ts b/packages/grafana-runtime/src/services/CorrelationsService.ts new file mode 100644 index 00000000000..3cd8da0ec52 --- /dev/null +++ b/packages/grafana-runtime/src/services/CorrelationsService.ts @@ -0,0 +1,126 @@ +import { + DataFrame, + DataLinkPostProcessor, + DataLinkTransformationConfig, + DataSourceInstanceSettings, + TimeRange, +} from '@grafana/data'; + +export type CorrelationConfigQuery = { + field: string; + target: object; // for queries, this contains anything that would go in the query editor, so any extension off DataQuery a datasource would have, and needs to be generic. + transformations?: DataLinkTransformationConfig[]; +}; + +export type CorrelationConfigExternal = { + field: string; + target: { + url: string; // For external, this simply contains a URL + }; + transformations?: DataLinkTransformationConfig[]; +}; + +type CorrelationBase = { + uid: string; + sourceUID: string; + label?: string; + description?: string; + provisioned: boolean; + orgId?: number; +}; + +/** + * @alpha + */ +export type CorrelationExternal = CorrelationBase & { + type: 'external'; + config: CorrelationConfigExternal; +}; + +/** + * @alpha + */ +export type CorrelationQuery = CorrelationBase & { + type: 'query'; + config: CorrelationConfigQuery; + targetUID: string; +}; + +/** + * @alpha + */ +export type CorrelationData = + | (Omit & { + source: DataSourceInstanceSettings; + }) + | (Omit & { + source: DataSourceInstanceSettings; + target: DataSourceInstanceSettings; + }); + +/** + * @alpha + */ +export interface CorrelationsData { + correlations: CorrelationData[]; + page: number; + limit: number; + totalCount: number; +} + +/** + * Used to work with user defined correlations. + * Should be accessed via {@link getCorrelationsService} function. + * + * @alpha + */ +export interface CorrelationsService { + /** + * Creates data links in data frames from provided correlations + * + * @param dataFrames list of data frames to be processed + * @param correlations list of of possible correlations that can be applied + * @param dataFrameRefIdToDataSourceUid a map that for provided refId references corresponding data source ui + */ + attachCorrelationsToDataFrames: ( + dataFrames: DataFrame[], + correlations: CorrelationData[], + dataFrameRefIdToDataSourceUid: Record + ) => DataFrame[]; + + /** + * Creates a link post processor function that handles correlation transformations + * + * @param timeRange The current time range + */ + correlationsDataLinkPostProcessorFactory: (timeRange: TimeRange) => DataLinkPostProcessor; + + /** + * Loads all the correlations defined for the given data sources. + * + * @param sourceUIDs Data source UIDs + */ + getCorrelationsBySourceUIDs: (sourceUIDs: string[]) => Promise; +} + +let singletonInstance: CorrelationsService; + +/** + * Used during startup by Grafana to set the CorrelationsService so it is available + * via {@link getCorrelationsService} to the rest of the application. + * + * @internal + */ +export function setCorrelationsService(instance: CorrelationsService) { + console.log('setCorrelationsService', instance); + singletonInstance = instance; +} + +/** + * Used to retrieve the {@link CorrelationsService}. + * + * @alpha + */ +export function getCorrelationsService(): CorrelationsService { + return singletonInstance; +} diff --git a/pkg/plugins/manager/installer.go b/pkg/plugins/manager/installer.go index cd445383d2e..6c5713c55b0 100644 --- a/pkg/plugins/manager/installer.go +++ b/pkg/plugins/manager/installer.go @@ -95,7 +95,7 @@ func (m *PluginInstaller) install(ctx context.Context, pluginID, version string, return nil, err } if plugin, exists := m.plugin(ctx, pluginID, version); exists { - if plugin.IsCorePlugin() || plugin.IsBundledPlugin() { + if plugin.IsCorePlugin() { return nil, plugins.ErrInstallCorePlugin } @@ -194,7 +194,7 @@ func (m *PluginInstaller) Remove(ctx context.Context, pluginID, version string) return plugins.ErrPluginNotInstalled } - if plugin.IsCorePlugin() || plugin.IsBundledPlugin() { + if plugin.IsCorePlugin() { return plugins.ErrUninstallCorePlugin } diff --git a/pkg/plugins/manager/installer_test.go b/pkg/plugins/manager/installer_test.go index d89a63e3c5b..ae2025445e1 100644 --- a/pkg/plugins/manager/installer_test.go +++ b/pkg/plugins/manager/installer_test.go @@ -212,37 +212,28 @@ func TestPluginManager_Add_Remove(t *testing.T) { }) }) - t.Run("Can't update core or bundled plugin", func(t *testing.T) { - tcs := []struct { - class plugins.Class - }{ - {class: plugins.ClassCore}, - {class: plugins.ClassBundled}, + t.Run("Can't update core plugin", func(t *testing.T) { + p := createPlugin(t, testPluginID, plugins.ClassCore, true, true, func(plugin *plugins.Plugin) { + plugin.Info.Version = "1.0.0" + }) + + reg := &fakes.FakePluginRegistry{ + Store: map[string]*plugins.Plugin{ + testPluginID: p, + }, } - for _, tc := range tcs { - p := createPlugin(t, testPluginID, tc.class, true, true, func(plugin *plugins.Plugin) { - plugin.Info.Version = "1.0.0" - }) + pm := New(reg, &fakes.FakeLoader{}, &fakes.FakePluginRepo{}, &fakes.FakePluginStorage{}, storage.SimpleDirNameGeneratorFunc, &fakes.FakeAuthService{}) + err := pm.Add(context.Background(), p.ID, "3.2.0", testCompatOpts()) + require.ErrorIs(t, err, plugins.ErrInstallCorePlugin) - reg := &fakes.FakePluginRegistry{ - Store: map[string]*plugins.Plugin{ - testPluginID: p, - }, - } + err = pm.Add(context.Background(), testPluginID, "", testCompatOpts()) + require.Equal(t, plugins.ErrInstallCorePlugin, err) - pm := New(reg, &fakes.FakeLoader{}, &fakes.FakePluginRepo{}, &fakes.FakePluginStorage{}, storage.SimpleDirNameGeneratorFunc, &fakes.FakeAuthService{}) - err := pm.Add(context.Background(), p.ID, "3.2.0", testCompatOpts()) - require.ErrorIs(t, err, plugins.ErrInstallCorePlugin) - - err = pm.Add(context.Background(), testPluginID, "", testCompatOpts()) - require.Equal(t, plugins.ErrInstallCorePlugin, err) - - t.Run(fmt.Sprintf("Can't uninstall %s plugin", tc.class), func(t *testing.T) { - err = pm.Remove(context.Background(), p.ID, p.Info.Version) - require.Equal(t, plugins.ErrUninstallCorePlugin, err) - }) - } + t.Run("Can't uninstall core plugin", func(t *testing.T) { + err = pm.Remove(context.Background(), p.ID, p.Info.Version) + require.Equal(t, plugins.ErrUninstallCorePlugin, err) + }) }) t.Run("Can install multiple dependency levels", func(t *testing.T) { diff --git a/pkg/plugins/manager/loader/loader_test.go b/pkg/plugins/manager/loader/loader_test.go index c4cf2d4faf7..3472727f127 100644 --- a/pkg/plugins/manager/loader/loader_test.go +++ b/pkg/plugins/manager/loader/loader_test.go @@ -124,56 +124,6 @@ func TestLoader_Load(t *testing.T) { }, }, }, - { - name: "Load a Bundled plugin", - class: plugins.ClassBundled, - cfg: &config.PluginManagementCfg{}, - pluginPaths: []string{"../testdata/valid-v2-signature"}, - want: []*plugins.Plugin{ - { - JSONData: plugins.JSONData{ - ID: "test-datasource", - Type: plugins.TypeDataSource, - Name: "Test", - Info: plugins.Info{ - Author: plugins.InfoLink{ - Name: "Will Browne", - URL: "https://willbrowne.com", - }, - Version: "1.0.0", - Logos: plugins.Logos{ - Small: "public/img/icn-datasource.svg", - Large: "public/img/icn-datasource.svg", - }, - Description: "Test", - }, - Dependencies: plugins.Dependencies{ - GrafanaVersion: "*", - Plugins: []plugins.Dependency{}, - Extensions: plugins.ExtensionsDependencies{ - ExposedComponents: []string{}, - }, - }, - Extensions: plugins.Extensions{ - AddedLinks: []plugins.AddedLink{}, - AddedComponents: []plugins.AddedComponent{}, - ExposedComponents: []plugins.ExposedComponent{}, - ExtensionPoints: []plugins.ExtensionPoint{}, - }, - Executable: "test", - Backend: true, - State: "alpha", - }, - Module: "public/plugins/test-datasource/module.js", - BaseURL: "public/plugins/test-datasource", - FS: mustNewStaticFSForTests(t, filepath.Join(parentDir, "testdata/valid-v2-signature/plugin/")), - Signature: "valid", - SignatureType: plugins.SignatureTypeGrafana, - SignatureOrg: "Grafana Labs", - Class: plugins.ClassBundled, - }, - }, - }, { name: "Load plugin with symbolic links", class: plugins.ClassExternal, diff --git a/pkg/plugins/manager/signature/signature.go b/pkg/plugins/manager/signature/signature.go index 57a205c58df..153fafdaf95 100644 --- a/pkg/plugins/manager/signature/signature.go +++ b/pkg/plugins/manager/signature/signature.go @@ -49,7 +49,7 @@ func (s *Validation) ValidateSignature(plugin *plugins.Plugin) error { } } - if plugin.IsCorePlugin() || plugin.IsBundledPlugin() { + if plugin.IsCorePlugin() { return nil } diff --git a/pkg/plugins/manager/sources/sources.go b/pkg/plugins/manager/sources/sources.go index 353f6fe3046..767d0aedeb5 100644 --- a/pkg/plugins/manager/sources/sources.go +++ b/pkg/plugins/manager/sources/sources.go @@ -24,7 +24,6 @@ func ProvideService(cfg *setting.Cfg) *Service { func (s *Service) List(_ context.Context) []plugins.PluginSource { r := []plugins.PluginSource{ NewLocalSource(plugins.ClassCore, corePluginPaths(s.cfg.StaticRootPath)), - NewLocalSource(plugins.ClassBundled, []string{s.cfg.BundledPluginsPath}), } r = append(r, s.externalPluginSources()...) r = append(r, s.pluginSettingSources()...) diff --git a/pkg/plugins/manager/sources/sources_test.go b/pkg/plugins/manager/sources/sources_test.go index f4a941ddf0b..3719b021a18 100644 --- a/pkg/plugins/manager/sources/sources_test.go +++ b/pkg/plugins/manager/sources/sources_test.go @@ -17,9 +17,8 @@ func TestSources_List(t *testing.T) { require.NoError(t, err) cfg := &setting.Cfg{ - StaticRootPath: testdata, - PluginsPath: filepath.Join(testdata, "pluginRootWithDist"), - BundledPluginsPath: filepath.Join(testdata, "unsigned-panel"), + StaticRootPath: testdata, + PluginsPath: filepath.Join(testdata, "pluginRootWithDist"), PluginSettings: setting.PluginSettings{ "foo": map[string]string{ "path": filepath.Join(testdata, "test-app"), @@ -35,7 +34,7 @@ func TestSources_List(t *testing.T) { ctx := context.Background() - require.Len(t, srcs, 6) + require.Len(t, srcs, 5) require.Equal(t, srcs[0].PluginClass(ctx), plugins.ClassCore) require.Equal(t, srcs[0].PluginURIs(ctx), []string{ @@ -48,15 +47,17 @@ func TestSources_List(t *testing.T) { require.Equal(t, plugins.SignatureType(""), sig.Type) require.Equal(t, "", sig.SigningOrg) - require.Equal(t, srcs[1].PluginClass(ctx), plugins.ClassBundled) - require.Equal(t, srcs[1].PluginURIs(ctx), []string{filepath.Join(testdata, "unsigned-panel")}) + require.Equal(t, srcs[1].PluginClass(ctx), plugins.ClassExternal) + require.Equal(t, srcs[1].PluginURIs(ctx), []string{ + filepath.Join(testdata, "pluginRootWithDist", "datasource"), + }) sig, exists = srcs[1].DefaultSignature(ctx) require.False(t, exists) require.Equal(t, plugins.Signature{}, sig) require.Equal(t, srcs[2].PluginClass(ctx), plugins.ClassExternal) require.Equal(t, srcs[2].PluginURIs(ctx), []string{ - filepath.Join(testdata, "pluginRootWithDist", "datasource"), + filepath.Join(testdata, "pluginRootWithDist", "dist"), }) sig, exists = srcs[2].DefaultSignature(ctx) require.False(t, exists) @@ -64,17 +65,9 @@ func TestSources_List(t *testing.T) { require.Equal(t, srcs[3].PluginClass(ctx), plugins.ClassExternal) require.Equal(t, srcs[3].PluginURIs(ctx), []string{ - filepath.Join(testdata, "pluginRootWithDist", "dist"), - }) - sig, exists = srcs[3].DefaultSignature(ctx) - require.False(t, exists) - require.Equal(t, plugins.Signature{}, sig) - - require.Equal(t, srcs[4].PluginClass(ctx), plugins.ClassExternal) - require.Equal(t, srcs[4].PluginURIs(ctx), []string{ filepath.Join(testdata, "pluginRootWithDist", "panel"), }) - sig, exists = srcs[4].DefaultSignature(ctx) + sig, exists = srcs[3].DefaultSignature(ctx) require.False(t, exists) require.Equal(t, plugins.Signature{}, sig) }) @@ -84,9 +77,8 @@ func TestSources_List(t *testing.T) { require.NoError(t, err) cfg := &setting.Cfg{ - StaticRootPath: testdata, - PluginsPath: filepath.Join(testdata, "symbolic-plugin-dirs"), - BundledPluginsPath: filepath.Join(testdata, "unsigned-panel"), + StaticRootPath: testdata, + PluginsPath: filepath.Join(testdata, "symbolic-plugin-dirs"), } s := ProvideService(cfg) ctx := context.Background() @@ -107,10 +99,6 @@ func TestSources_List(t *testing.T) { filepath.Join(testdata, "app", "plugins", "panel"): {}, }, "should include core plugins") - require.Equal(t, uris[plugins.ClassBundled], map[string]struct{}{ - filepath.Join(testdata, "unsigned-panel"): {}, - }, "should include bundle plugin") - require.Equal(t, uris[plugins.ClassExternal], map[string]struct{}{ filepath.Join(testdata, "symbolic-plugin-dirs", "plugin"): {}, }, "should include external symlinked plugin") diff --git a/pkg/plugins/plugins.go b/pkg/plugins/plugins.go index 08325f8fb40..3239927747b 100644 --- a/pkg/plugins/plugins.go +++ b/pkg/plugins/plugins.go @@ -494,19 +494,14 @@ func (p *Plugin) IsCorePlugin() bool { return p.Class == ClassCore } -func (p *Plugin) IsBundledPlugin() bool { - return p.Class == ClassBundled -} - func (p *Plugin) IsExternalPlugin() bool { - return !p.IsCorePlugin() && !p.IsBundledPlugin() + return !p.IsCorePlugin() } type Class string const ( ClassCore Class = "core" - ClassBundled Class = "bundled" ClassExternal Class = "external" ClassCDN Class = "cdn" ) diff --git a/pkg/services/featuremgmt/registry.go b/pkg/services/featuremgmt/registry.go index 5fd9f61794d..f68c5134c7b 100644 --- a/pkg/services/featuremgmt/registry.go +++ b/pkg/services/featuremgmt/registry.go @@ -1743,6 +1743,13 @@ var ( Expression: "false", HideFromDocs: true, }, + { + Name: "queryLibraryDashboards", + Description: "Enables Query Library feature in Dashboards", + Stage: FeatureStageExperimental, + Owner: grafanaFrontendPlatformSquad, + AllowSelfServe: false, + }, } ) diff --git a/pkg/services/featuremgmt/toggles_gen.csv b/pkg/services/featuremgmt/toggles_gen.csv index c414b28d25a..2eba503f6f5 100644 --- a/pkg/services/featuremgmt/toggles_gen.csv +++ b/pkg/services/featuremgmt/toggles_gen.csv @@ -233,3 +233,4 @@ improvedExternalSessionHandlingSAML,preview,@grafana/identity-access-team,false, teamHttpHeadersMimir,experimental,@grafana/identity-access-team,false,false,false ABTestFeatureToggleA,experimental,@grafana/sharing-squad,false,false,false ABTestFeatureToggleB,experimental,@grafana/sharing-squad,false,false,false +queryLibraryDashboards,experimental,@grafana/grafana-frontend-platform,false,false,false diff --git a/pkg/services/featuremgmt/toggles_gen.go b/pkg/services/featuremgmt/toggles_gen.go index 8ff9b539d28..f74b6bcdb13 100644 --- a/pkg/services/featuremgmt/toggles_gen.go +++ b/pkg/services/featuremgmt/toggles_gen.go @@ -942,4 +942,8 @@ const ( // FlagABTestFeatureToggleB // Test feature toggle to see how cohorts could be set up AB testing FlagABTestFeatureToggleB = "ABTestFeatureToggleB" + + // FlagQueryLibraryDashboards + // Enables Query Library feature in Dashboards + FlagQueryLibraryDashboards = "queryLibraryDashboards" ) diff --git a/pkg/services/featuremgmt/toggles_gen.json b/pkg/services/featuremgmt/toggles_gen.json index a5704c0ffa0..0ee59b47d73 100644 --- a/pkg/services/featuremgmt/toggles_gen.json +++ b/pkg/services/featuremgmt/toggles_gen.json @@ -3210,6 +3210,21 @@ "codeowner": "@grafana/grafana-frontend-platform" } }, + { + "metadata": { + "name": "queryLibraryDashboards", + "resourceVersion": "1736850377404", + "creationTimestamp": "2025-01-14T10:24:54Z", + "annotations": { + "grafana.app/updatedTimestamp": "2025-01-14 10:26:17.404592 +0000 UTC" + } + }, + "spec": { + "description": "Enables Query Library feature in Dashboards", + "stage": "experimental", + "codeowner": "@grafana/grafana-frontend-platform" + } + }, { "metadata": { "name": "queryOverLive", diff --git a/pkg/services/pluginsintegration/loader/loader_test.go b/pkg/services/pluginsintegration/loader/loader_test.go index 9395d9b6f29..06466240b9e 100644 --- a/pkg/services/pluginsintegration/loader/loader_test.go +++ b/pkg/services/pluginsintegration/loader/loader_test.go @@ -124,56 +124,6 @@ func TestLoader_Load(t *testing.T) { }, }, }, - { - name: "Load a Bundled plugin", - class: plugins.ClassBundled, - cfg: &config.PluginManagementCfg{}, - pluginPaths: []string{filepath.Join(testDataDir(t), "valid-v2-signature")}, - want: []*plugins.Plugin{ - { - JSONData: plugins.JSONData{ - ID: "test-datasource", - Type: plugins.TypeDataSource, - Name: "Test", - Info: plugins.Info{ - Author: plugins.InfoLink{ - Name: "Will Browne", - URL: "https://willbrowne.com", - }, - Version: "1.0.0", - Logos: plugins.Logos{ - Small: "public/img/icn-datasource.svg", - Large: "public/img/icn-datasource.svg", - }, - Description: "Test", - }, - Dependencies: plugins.Dependencies{ - GrafanaVersion: "*", - Plugins: []plugins.Dependency{}, - Extensions: plugins.ExtensionsDependencies{ - ExposedComponents: []string{}, - }, - }, - Extensions: plugins.Extensions{ - AddedLinks: []plugins.AddedLink{}, - AddedComponents: []plugins.AddedComponent{}, - ExposedComponents: []plugins.ExposedComponent{}, - ExtensionPoints: []plugins.ExtensionPoint{}, - }, - Executable: "test", - Backend: true, - State: "alpha", - }, - Module: "public/plugins/test-datasource/module.js", - BaseURL: "public/plugins/test-datasource", - FS: mustNewStaticFSForTests(t, filepath.Join(testDataDir(t), "valid-v2-signature/plugin/")), - Signature: "valid", - SignatureType: plugins.SignatureTypeGrafana, - SignatureOrg: "Grafana Labs", - Class: plugins.ClassBundled, - }, - }, - }, { name: "Load plugin with symbolic links", class: plugins.ClassExternal, @@ -672,7 +622,7 @@ func TestLoader_Load_CustomSource(t *testing.T) { }, }, FS: mustNewStaticFSForTests(t, filepath.Join(testDataDir(t), "cdn/plugin")), - Class: plugins.ClassBundled, + Class: plugins.ClassExternal, Signature: plugins.SignatureStatusValid, BaseURL: "https://cdn.example.com/grafana-worldmap-panel/0.3.3/public/plugins/grafana-worldmap-panel", Module: "https://cdn.example.com/grafana-worldmap-panel/0.3.3/public/plugins/grafana-worldmap-panel/module.js", @@ -681,7 +631,7 @@ func TestLoader_Load_CustomSource(t *testing.T) { l := newLoader(t, cfg, fakes.NewFakePluginRegistry(), fakes.NewFakeProcessManager(), fakes.NewFakeBackendProcessProvider(), newFakeErrorTracker()) got, err := l.Load(context.Background(), &fakes.FakePluginSource{ PluginClassFunc: func(ctx context.Context) plugins.Class { - return plugins.ClassBundled + return plugins.ClassExternal }, PluginURIsFunc: func(ctx context.Context) []string { return pluginPaths @@ -1170,11 +1120,6 @@ func TestLoader_AngularClass(t *testing.T) { class: plugins.ClassCore, expAngularDetectionRun: false, }, - { - name: "bundled plugin should skip angular detection", - class: plugins.ClassBundled, - expAngularDetectionRun: false, - }, { name: "external plugin should run angular detection", class: plugins.ClassExternal, diff --git a/pkg/services/pluginsintegration/pipeline/steps.go b/pkg/services/pluginsintegration/pipeline/steps.go index 0c82d3f07a3..3e33fda53be 100644 --- a/pkg/services/pluginsintegration/pipeline/steps.go +++ b/pkg/services/pluginsintegration/pipeline/steps.go @@ -121,9 +121,9 @@ func (r *RegisterActionSets) Register(ctx context.Context, p *plugins.Plugin) (* return p, nil } -// ReportBuildMetrics reports build information for all plugins, except core and bundled plugins. +// ReportBuildMetrics reports build information for all plugins, except core plugins. func ReportBuildMetrics(_ context.Context, p *plugins.Plugin) (*plugins.Plugin, error) { - if !p.IsCorePlugin() && !p.IsBundledPlugin() { + if !p.IsCorePlugin() { metrics.SetPluginBuildInformation(p.ID, string(p.Type), p.Info.Version, string(p.Signature)) } diff --git a/pkg/services/pluginsintegration/plugins_integration_test.go b/pkg/services/pluginsintegration/plugins_integration_test.go index ff5e93a6a61..8b2e9af7439 100644 --- a/pkg/services/pluginsintegration/plugins_integration_test.go +++ b/pkg/services/pluginsintegration/plugins_integration_test.go @@ -55,15 +55,11 @@ func TestIntegrationPluginManager(t *testing.T) { staticRootPath, err := filepath.Abs("../../../public/") require.NoError(t, err) - bundledPluginsPath, err := filepath.Abs("../../../plugins-bundled/internal") - require.NoError(t, err) - features := featuremgmt.WithFeatures() cfg := &setting.Cfg{ - Raw: ini.Empty(), - StaticRootPath: staticRootPath, - BundledPluginsPath: bundledPluginsPath, - Azure: &azsettings.AzureSettings{}, + Raw: ini.Empty(), + StaticRootPath: staticRootPath, + Azure: &azsettings.AzureSettings{}, PluginSettings: map[string]map[string]string{ "test-app": { "path": "../../plugins/manager/testdata/test-app", diff --git a/pkg/services/pluginsintegration/pluginstore/store_test.go b/pkg/services/pluginsintegration/pluginstore/store_test.go index a4ac6434ff3..587d7e6d68c 100644 --- a/pkg/services/pluginsintegration/pluginstore/store_test.go +++ b/pkg/services/pluginsintegration/pluginstore/store_test.go @@ -27,7 +27,7 @@ func TestStore_ProvideService(t *testing.T) { return []plugins.PluginSource{ &fakes.FakePluginSource{ PluginClassFunc: func(ctx context.Context) plugins.Class { - return plugins.ClassBundled + return "foobar" }, PluginURIsFunc: func(ctx context.Context) []string { return []string{"path1"} diff --git a/pkg/services/updatechecker/plugins_test.go b/pkg/services/updatechecker/plugins_test.go index 370d3d160d9..d0d1ff22d2f 100644 --- a/pkg/services/updatechecker/plugins_test.go +++ b/pkg/services/updatechecker/plugins_test.go @@ -165,7 +165,7 @@ func TestPluginUpdateChecker_checkForUpdates(t *testing.T) { Info: plugins.Info{Version: "2.5.7"}, Type: plugins.TypePanel, }, - Class: plugins.ClassBundled, + Class: plugins.ClassExternal, }, { JSONData: plugins.JSONData{ diff --git a/pkg/setting/setting.go b/pkg/setting/setting.go index 8cead64f27f..c08a1fedf62 100644 --- a/pkg/setting/setting.go +++ b/pkg/setting/setting.go @@ -135,7 +135,6 @@ type Cfg struct { DataPath string LogsPath string PluginsPath string - BundledPluginsPath string EnterpriseLicensePath string // SMTP email settings @@ -1102,7 +1101,8 @@ func (cfg *Cfg) parseINIFile(iniFile *ini.File) error { cfg.InstanceName = valueAsString(iniFile.Section(""), "instance_name", "unknown_instance_name") plugins := valueAsString(iniFile.Section("paths"), "plugins", "") cfg.PluginsPath = makeAbsolute(plugins, cfg.HomePath) - cfg.BundledPluginsPath = makeAbsolute("plugins-bundled", cfg.HomePath) + provisioning := valueAsString(iniFile.Section("paths"), "provisioning", "") + cfg.ProvisioningPath = makeAbsolute(provisioning, cfg.HomePath) if err := cfg.readServerSettings(iniFile); err != nil { return err diff --git a/pkg/tests/api/plugins/api_plugins_test.go b/pkg/tests/api/plugins/api_plugins_test.go index ba04251c1fb..43e1eaa678a 100644 --- a/pkg/tests/api/plugins/api_plugins_test.go +++ b/pkg/tests/api/plugins/api_plugins_test.go @@ -100,7 +100,7 @@ func TestIntegrationPlugins(t *testing.T) { t.Run("List", func(t *testing.T) { testCases := []testCase{ { - desc: "should return all loaded core and bundled plugins", + desc: "should return all loaded core plugins", url: "http://%s/api/plugins", expStatus: http.StatusOK, expRespPath: "expectedListResp.json", diff --git a/plugins-bundled/.gitignore b/plugins-bundled/.gitignore deleted file mode 100644 index c1bdb1e0c92..00000000000 --- a/plugins-bundled/.gitignore +++ /dev/null @@ -1,9 +0,0 @@ -# packaged by toolkit -dist -coverage - -# Ignore external git configs -external - -# this file is added automatically -.prettierrc.js \ No newline at end of file diff --git a/plugins-bundled/README.md b/plugins-bundled/README.md deleted file mode 100644 index 05cb8c8c4f3..00000000000 --- a/plugins-bundled/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# Bundled Plugins - -Bundled plugins are built as true plugins, and managed by the grafana install. - -TODO: the packaging system should move all `dist` items to the root and remove sources. diff --git a/plugins-bundled/external.json b/plugins-bundled/external.json deleted file mode 100644 index a5b818f5302..00000000000 --- a/plugins-bundled/external.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "plugins": [] -} diff --git a/public/app/app.ts b/public/app/app.ts index 17ba4c04d73..7cd4d4fbd69 100644 --- a/public/app/app.ts +++ b/public/app/app.ts @@ -40,6 +40,7 @@ import { setCurrentUser, setChromeHeaderHeightHook, setPluginLinksHook, + setCorrelationsService, } from '@grafana/runtime'; import { setPanelDataErrorView } from '@grafana/runtime/src/components/PanelDataErrorView'; import { setPanelRenderer } from '@grafana/runtime/src/components/PanelRenderer'; @@ -60,6 +61,7 @@ import { initializeCrashDetection } from './core/crash'; import { initializeI18n } from './core/internationalization'; import { setMonacoEnv } from './core/monacoEnv'; import { interceptLinkClicks } from './core/navigation/patch/interceptLinkClicks'; +import { CorrelationsService } from './core/services/CorrelationsService'; import { NewFrontendAssetsChecker } from './core/services/NewFrontendAssetsChecker'; import { backendSrv } from './core/services/backend_srv'; import { contextSrv, RedirectToUrlKey } from './core/services/context_srv'; @@ -146,6 +148,7 @@ export class GrafanaApp { setPluginPage(PluginPage); setPanelDataErrorView(PanelDataErrorView); setLocationSrv(locationService); + setCorrelationsService(new CorrelationsService()); setEmbeddedDashboard(EmbeddedDashboardLazy); setTimeZoneResolver(() => config.bootData.user.timezone); initGrafanaLive(); diff --git a/public/app/core/services/CorrelationsService.ts b/public/app/core/services/CorrelationsService.ts new file mode 100644 index 00000000000..d4332a86e05 --- /dev/null +++ b/public/app/core/services/CorrelationsService.ts @@ -0,0 +1,22 @@ +import { DataFrame, TimeRange } from '@grafana/data'; +import type { CorrelationData, CorrelationsService as CorrelationsServiceInterface } from '@grafana/runtime'; +import { attachCorrelationsToDataFrames, getCorrelationsBySourceUIDs } from 'app/features/correlations/utils'; +import { exploreDataLinkPostProcessorFactory } from 'app/features/explore/utils/links'; + +export class CorrelationsService implements CorrelationsServiceInterface { + attachCorrelationsToDataFrames( + dataFrames: DataFrame[], + correlations: CorrelationData[], + dataFrameRefIdToDataSourceUid: Record + ) { + return attachCorrelationsToDataFrames(dataFrames, correlations, dataFrameRefIdToDataSourceUid); + } + + correlationsDataLinkPostProcessorFactory(timeRange: TimeRange) { + return exploreDataLinkPostProcessorFactory(undefined, timeRange); + } + + getCorrelationsBySourceUIDs(sourceUIDs: string[]) { + return getCorrelationsBySourceUIDs(sourceUIDs); + } +} diff --git a/public/app/features/correlations/CorrelationsPage.tsx b/public/app/features/correlations/CorrelationsPage.tsx index 163f18b6435..9028fba1446 100644 --- a/public/app/features/correlations/CorrelationsPage.tsx +++ b/public/app/features/correlations/CorrelationsPage.tsx @@ -3,7 +3,7 @@ import { negate } from 'lodash'; import { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react'; import { DataSourceInstanceSettings, GrafanaTheme2 } from '@grafana/data'; -import { isFetchError, reportInteraction } from '@grafana/runtime'; +import { CorrelationData, isFetchError, reportInteraction } from '@grafana/runtime'; import { Badge, Button, @@ -28,7 +28,7 @@ import { AddCorrelationForm } from './Forms/AddCorrelationForm'; import { EditCorrelationForm } from './Forms/EditCorrelationForm'; import { EmptyCorrelationsCTA } from './components/EmptyCorrelationsCTA'; import type { Correlation, RemoveCorrelationParams } from './types'; -import { CorrelationData, useCorrelations } from './useCorrelations'; +import { useCorrelations } from './useCorrelations'; const sortDatasource: SortByFn = (a, b, column) => a.values[column].name.localeCompare(b.values[column].name); diff --git a/public/app/features/correlations/Forms/ConfigureCorrelationTargetForm.tsx b/public/app/features/correlations/Forms/ConfigureCorrelationTargetForm.tsx index 75f9aac81aa..2818bebb4b8 100644 --- a/public/app/features/correlations/Forms/ConfigureCorrelationTargetForm.tsx +++ b/public/app/features/correlations/Forms/ConfigureCorrelationTargetForm.tsx @@ -2,11 +2,12 @@ import { css } from '@emotion/css'; import { Controller, FieldError, useFormContext, useWatch } from 'react-hook-form'; import { DataSourceInstanceSettings, GrafanaTheme2 } from '@grafana/data'; +import { CorrelationExternal } from '@grafana/runtime'; import { Field, FieldSet, Input, Select, useStyles2 } from '@grafana/ui'; import { Trans, t } from 'app/core/internationalization'; import { DataSourcePicker } from 'app/features/datasources/components/picker/DataSourcePicker'; -import { CorrelationType, ExternalTypeTarget } from '../types'; +import { CorrelationType } from '../types'; import { QueryEditorField } from './QueryEditorField'; import { useCorrelationsFormContext } from './correlationsFormContext'; @@ -146,7 +147,7 @@ export const ConfigureCorrelationTargetForm = () => { }, }} render={({ field: { onChange, value } }) => { - const castVal = value as ExternalTypeTarget; // the target under "query" type can contain anything a datasource query contains + const castVal = value as CorrelationExternal['config']['target']; // the target under "query" type can contain anything a datasource query contains return ( & { - source: DataSourceInstanceSettings; - }) - | (Omit & { - source: DataSourceInstanceSettings; - target: DataSourceInstanceSettings; - }); - -export interface CorrelationsData { - correlations: CorrelationData[]; - page: number; - limit: number; - totalCount: number; -} - const toEnrichedCorrelationData = ({ sourceUID, ...correlation }: Correlation): CorrelationData | undefined => { const sourceDatasource = getDataSourceSrv().getInstanceSettings(sourceUID); const targetDatasource = diff --git a/public/app/features/correlations/utils.test.ts b/public/app/features/correlations/utils.test.ts index f182b3c85c3..4caf7b60b82 100644 --- a/public/app/features/correlations/utils.test.ts +++ b/public/app/features/correlations/utils.test.ts @@ -1,7 +1,6 @@ import { DataFrame, DataFrameType, DataSourceInstanceSettings, FieldType, toDataFrame } from '@grafana/data'; -import { config } from '@grafana/runtime'; +import { config, CorrelationData } from '@grafana/runtime'; -import { CorrelationData } from './useCorrelations'; import { attachCorrelationsToDataFrames } from './utils'; describe('correlations utils', () => { diff --git a/public/app/features/correlations/utils.ts b/public/app/features/correlations/utils.ts index f7778bb16bb..1a6f97157da 100644 --- a/public/app/features/correlations/utils.ts +++ b/public/app/features/correlations/utils.ts @@ -1,20 +1,21 @@ import { lastValueFrom } from 'rxjs'; import { DataFrame, DataLinkConfigOrigin } from '@grafana/data'; -import { config, createMonitoringLogger, getBackendSrv, getDataSourceSrv } from '@grafana/runtime'; +import { + config, + CorrelationData, + CorrelationsData, + createMonitoringLogger, + getBackendSrv, + getDataSourceSrv, +} from '@grafana/runtime'; import { ExploreItemState } from 'app/types'; import { formatValueName } from '../explore/PrometheusListView/ItemLabels'; import { parseLogsFrame } from '../logs/logsFrame'; import { CreateCorrelationParams, CreateCorrelationResponse } from './types'; -import { - CorrelationData, - CorrelationsData, - CorrelationsResponse, - getData, - toEnrichedCorrelationsData, -} from './useCorrelations'; +import { CorrelationsResponse, getData, toEnrichedCorrelationsData } from './useCorrelations'; type DataFrameRefIdToDataSourceUid = Record; @@ -85,7 +86,7 @@ const decorateDataFrameWithInternalDataLinks = (dataFrame: DataFrame, correlatio }; /* -If a correlation was made based on the log line field prior to the loki data plane, they would use the field "Line" +If a correlation was made based on the log line field prior to the loki data plane, they would use the field "Line" Change it to use whatever the body field name is post-loki data plane */ diff --git a/public/app/features/explore/state/correlations.ts b/public/app/features/explore/state/correlations.ts index cbf50fa81f6..4e093ca3669 100644 --- a/public/app/features/explore/state/correlations.ts +++ b/public/app/features/explore/state/correlations.ts @@ -1,11 +1,10 @@ import { Observable } from 'rxjs'; import { DataLinkTransformationConfig } from '@grafana/data'; -import { getDataSourceSrv, reportInteraction } from '@grafana/runtime'; +import { CorrelationData, getDataSourceSrv, reportInteraction } from '@grafana/runtime'; import { notifyApp } from 'app/core/actions'; import { createErrorNotification } from 'app/core/copy/appNotification'; import { CreateCorrelationParams } from 'app/features/correlations/types'; -import { CorrelationData } from 'app/features/correlations/useCorrelations'; import { getCorrelationsBySourceUIDs, createCorrelation, generateDefaultLabel } from 'app/features/correlations/utils'; import { store } from 'app/store/store'; import { ThunkResult } from 'app/types'; diff --git a/public/app/features/explore/state/explorePane.ts b/public/app/features/explore/state/explorePane.ts index b83eb938b3b..601ceea2dae 100644 --- a/public/app/features/explore/state/explorePane.ts +++ b/public/app/features/explore/state/explorePane.ts @@ -11,9 +11,9 @@ import { ExploreCorrelationHelperData, EventBusExtended, } from '@grafana/data'; +import { CorrelationData } from '@grafana/runtime'; import { DataQuery, DataSourceRef } from '@grafana/schema'; import { getQueryKeys } from 'app/core/utils/explore'; -import { CorrelationData } from 'app/features/correlations/useCorrelations'; import { getCorrelationsBySourceUIDs } from 'app/features/correlations/utils'; import { getTimeZone } from 'app/features/profile/state/selectors'; import { createAsyncThunk, ThunkResult } from 'app/types'; diff --git a/public/app/features/explore/utils/decorators.test.ts b/public/app/features/explore/utils/decorators.test.ts index b61a87f89ec..5e2e1517eee 100644 --- a/public/app/features/explore/utils/decorators.test.ts +++ b/public/app/features/explore/utils/decorators.test.ts @@ -10,9 +10,9 @@ import { DataSourceApi, DataSourceInstanceSettings, } from '@grafana/data'; +import { CorrelationData } from '@grafana/runtime'; import { DataSourceJsonData, DataQuery } from '@grafana/schema'; import TableModel from 'app/core/TableModel'; -import { CorrelationData } from 'app/features/correlations/useCorrelations'; import { ExplorePanelData } from 'app/types'; import { diff --git a/public/app/features/explore/utils/decorators.ts b/public/app/features/explore/utils/decorators.ts index b09f0b61b61..08dc24b6a7d 100644 --- a/public/app/features/explore/utils/decorators.ts +++ b/public/app/features/explore/utils/decorators.ts @@ -14,12 +14,11 @@ import { getRawDisplayProcessor, DataSourceApi, } from '@grafana/data'; -import { config } from '@grafana/runtime'; +import { config, CorrelationData } from '@grafana/runtime'; import { DataQuery } from '@grafana/schema'; import { refreshIntervalToSortOrder } from '../../../core/utils/explore'; import { ExplorePanelData } from '../../../types'; -import { CorrelationData } from '../../correlations/useCorrelations'; import { attachCorrelationsToDataFrames } from '../../correlations/utils'; import { dataFrameToLogsModel } from '../../logs/logsModel'; import { sortLogsResult } from '../../logs/utils'; diff --git a/public/app/types/explore.ts b/public/app/types/explore.ts index 865d656e3dc..11ac0ad84d0 100644 --- a/public/app/types/explore.ts +++ b/public/app/types/explore.ts @@ -19,10 +19,9 @@ import { ExploreCorrelationHelperData, DataLinkTransformationConfig, } from '@grafana/data'; +import { CorrelationData } from '@grafana/runtime'; import { RichHistorySearchFilters, RichHistorySettings } from 'app/core/utils/richHistoryTypes'; -import { CorrelationData } from '../features/correlations/useCorrelations'; - export type ExploreQueryParams = UrlQueryMap; export enum CORRELATION_EDITOR_POST_CONFIRM_ACTION { diff --git a/yarn.lock b/yarn.lock index e29fb0b3a70..92c372a43b2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3151,7 +3151,7 @@ __metadata: moment: "npm:2.30.1" moment-timezone: "npm:0.5.46" ol: "npm:7.4.0" - papaparse: "npm:5.4.1" + papaparse: "npm:5.5.1" react: "npm:18.2.0" react-dom: "npm:18.2.0" react-use: "npm:17.6.0" @@ -17616,7 +17616,7 @@ __metadata: ol: "npm:7.4.0" ol-ext: "npm:4.0.24" pluralize: "npm:^8.0.0" - postcss: "npm:8.4.49" + postcss: "npm:8.5.1" postcss-loader: "npm:8.1.1" postcss-reporter: "npm:7.1.0" postcss-scss: "npm:4.0.9" @@ -22204,7 +22204,7 @@ __metadata: languageName: node linkType: hard -"nanoid@npm:^3.3.7": +"nanoid@npm:^3.3.8": version: 3.3.8 resolution: "nanoid@npm:3.3.8" bin: @@ -23354,10 +23354,10 @@ __metadata: languageName: node linkType: hard -"papaparse@npm:5.4.1": - version: 5.4.1 - resolution: "papaparse@npm:5.4.1" - checksum: 10/5e6dc978187182ad2efa1d264ffe73d2042cd23b8fb1dcb0b0f5c8c7c772c11e3eb4e166fb0893880ed24529a96abe9065d704cc5b4cb96abf037413cfe43788 +"papaparse@npm:5.5.1": + version: 5.5.1 + resolution: "papaparse@npm:5.5.1" + checksum: 10/6c3b47bd316cf11936641abe5590c6fb1e5b04297d1c594965a44dba89cc0f26b4e4d61eb1933352c538a30c4915d110628d14cf4d60cef0b8245c9a26477602 languageName: node linkType: hard @@ -24262,14 +24262,14 @@ __metadata: languageName: node linkType: hard -"postcss@npm:8.4.49, postcss@npm:^8.4.33, postcss@npm:^8.4.38, postcss@npm:^8.4.49": - version: 8.4.49 - resolution: "postcss@npm:8.4.49" +"postcss@npm:8.5.1, postcss@npm:^8.4.33, postcss@npm:^8.4.38, postcss@npm:^8.4.49": + version: 8.5.1 + resolution: "postcss@npm:8.5.1" dependencies: - nanoid: "npm:^3.3.7" + nanoid: "npm:^3.3.8" picocolors: "npm:^1.1.1" source-map-js: "npm:^1.2.1" - checksum: 10/28fe1005b1339870e0a5006375ba5ac1213fd69800f79e7db09c398e074421ba6e162898e94f64942fed554037fd292db3811d87835d25ab5ef7f3c9daacb6ca + checksum: 10/1fbd28753143f7f03e4604813639918182b15343c7ad0f4e72f3875fc2cc0b8494c887f55dc05008fad5fbf1e1e908ce2edbbce364a91f84dcefb71edf7cd31d languageName: node linkType: hard