grafana/public/app/features/plugins/extensions/registry/AddedLinksRegistry.ts

107 lines
3.5 KiB
TypeScript
Raw Normal View History

import { ReplaySubject } from 'rxjs';
Plugin extensions: Introduce new registry for added links (#92343) * add added component registry * fix broken test * add tests for usePluginComponents hook * readd expose components * add type assertion exceptions to betterer results * use new addedComponent registry in legacy endpoints * remove unused code * cleanup * revert test code * remove commented code * initial commit * refactor sync method and hook * fix tests * subscribe to the correct registry * remove old registry * cleanup types * add use usePluginLinks hook * add more tests * fix import order * fix typo * fix and temporarly skip failing tests * wip * add hook tests * add more tests * remove old hook * fix versioning * add version to all extension point ids * remove cleanup * remove unused imports * revert touched file * fix test * test: remove hook creation * catch init error * send error to faro * fix broken hook * comment out call hook initialization * use the right import ofr isString * remove unused import * remove registryState type * pr feedback * Update public/app/features/plugins/extensions/validators.test.tsx Co-authored-by: Levente Balogh <balogh.levente.hu@gmail.com> * Update public/app/features/plugins/extensions/validators.test.tsx Co-authored-by: Levente Balogh <balogh.levente.hu@gmail.com> * remove no longer relevant comment * fix broken tests * Fixed test to verify that the memotization works properly. * simplify hooks --------- Co-authored-by: Levente Balogh <balogh.levente.hu@gmail.com> Co-authored-by: Marcus Andersson <marcus.andersson@grafana.com>
2024-08-30 16:09:01 +08:00
import { IconName, PluginExtensionAddedLinkConfig } from '@grafana/data';
import { PluginAddedLinksConfigureFunc, PluginExtensionEventHelpers } from '@grafana/data/src/types/pluginExtensions';
Plugin Extensions: Require meta-data to be defined in `plugin.json` during development mode (#93429) * feat: add extensions to the backend plugin model * feat: update the frontend plugin types * feat(pluginContext): return a `null` if there is no context found This will be necessary to understand if a certain hook is running inside a plugin context or not. * feat: add utility functions for checking extension configs * tests: fix failing tests due to the type updates * feat(AddedComponentsRegistry): validate plugin meta-info * feat(AddedLinksRegistry): validate meta-info * feat(ExposedComponentsRegistry): validate meta-info * feat(usePluginComponent): add meta-info validation * feat(usePluginComponents): add meta-info validation * feat(usePluginLinks): add meta-info validation * fix: only validate meta-info in registries if dev mode is enabled * tests: add unit tests for the restrictions functionality * tests: fix Go tests * fix(tests): revert accidental changes * fix: run goimports * fix: api tests * add nested app so that meta data can bested e2e tested * refactor(types): extract the ExtensionInfo into a separate type * refactor(extensions/utils): use Array.prototype.some() instead of .find() * refactor(usePluginLinks): update warning message * feat(usePluginExtensions()): validate plugin meta-info * Wip * fix(e2e): E2E tests for extensions * fix(extensions): allow multiple "/" slashes in the extension point id * fix(extensions/validators): stop validating the plugin id pattern --------- Co-authored-by: Erik Sundell <erik.sundell87@gmail.com>
2024-10-04 14:41:26 +08:00
import { isAddedLinkMetaInfoMissing, isGrafanaDevMode, logWarning } from '../utils';
Plugin extensions: Introduce new registry for added links (#92343) * add added component registry * fix broken test * add tests for usePluginComponents hook * readd expose components * add type assertion exceptions to betterer results * use new addedComponent registry in legacy endpoints * remove unused code * cleanup * revert test code * remove commented code * initial commit * refactor sync method and hook * fix tests * subscribe to the correct registry * remove old registry * cleanup types * add use usePluginLinks hook * add more tests * fix import order * fix typo * fix and temporarly skip failing tests * wip * add hook tests * add more tests * remove old hook * fix versioning * add version to all extension point ids * remove cleanup * remove unused imports * revert touched file * fix test * test: remove hook creation * catch init error * send error to faro * fix broken hook * comment out call hook initialization * use the right import ofr isString * remove unused import * remove registryState type * pr feedback * Update public/app/features/plugins/extensions/validators.test.tsx Co-authored-by: Levente Balogh <balogh.levente.hu@gmail.com> * Update public/app/features/plugins/extensions/validators.test.tsx Co-authored-by: Levente Balogh <balogh.levente.hu@gmail.com> * remove no longer relevant comment * fix broken tests * Fixed test to verify that the memotization works properly. * simplify hooks --------- Co-authored-by: Levente Balogh <balogh.levente.hu@gmail.com> Co-authored-by: Marcus Andersson <marcus.andersson@grafana.com>
2024-08-30 16:09:01 +08:00
import {
extensionPointEndsWithVersion,
isConfigureFnValid,
isGrafanaCoreExtensionPoint,
isLinkPathValid,
} from '../validators';
import { PluginExtensionConfigs, Registry, RegistryType } from './Registry';
export type AddedLinkRegistryItem<Context extends object = object> = {
pluginId: string;
extensionPointId: string;
title: string;
description: string;
path?: string;
onClick?: (event: React.MouseEvent | undefined, helpers: PluginExtensionEventHelpers<Context>) => void;
configure?: PluginAddedLinksConfigureFunc<Context>;
icon?: IconName;
category?: string;
};
export class AddedLinksRegistry extends Registry<AddedLinkRegistryItem[], PluginExtensionAddedLinkConfig> {
constructor(
options: {
registrySubject?: ReplaySubject<RegistryType<AddedLinkRegistryItem[]>>;
initialState?: RegistryType<AddedLinkRegistryItem[]>;
} = {}
) {
super(options);
Plugin extensions: Introduce new registry for added links (#92343) * add added component registry * fix broken test * add tests for usePluginComponents hook * readd expose components * add type assertion exceptions to betterer results * use new addedComponent registry in legacy endpoints * remove unused code * cleanup * revert test code * remove commented code * initial commit * refactor sync method and hook * fix tests * subscribe to the correct registry * remove old registry * cleanup types * add use usePluginLinks hook * add more tests * fix import order * fix typo * fix and temporarly skip failing tests * wip * add hook tests * add more tests * remove old hook * fix versioning * add version to all extension point ids * remove cleanup * remove unused imports * revert touched file * fix test * test: remove hook creation * catch init error * send error to faro * fix broken hook * comment out call hook initialization * use the right import ofr isString * remove unused import * remove registryState type * pr feedback * Update public/app/features/plugins/extensions/validators.test.tsx Co-authored-by: Levente Balogh <balogh.levente.hu@gmail.com> * Update public/app/features/plugins/extensions/validators.test.tsx Co-authored-by: Levente Balogh <balogh.levente.hu@gmail.com> * remove no longer relevant comment * fix broken tests * Fixed test to verify that the memotization works properly. * simplify hooks --------- Co-authored-by: Levente Balogh <balogh.levente.hu@gmail.com> Co-authored-by: Marcus Andersson <marcus.andersson@grafana.com>
2024-08-30 16:09:01 +08:00
}
mapToRegistry(
registry: RegistryType<AddedLinkRegistryItem[]>,
item: PluginExtensionConfigs<PluginExtensionAddedLinkConfig>
): RegistryType<AddedLinkRegistryItem[]> {
const { pluginId, configs } = item;
for (const config of configs) {
const { path, title, description, configure, onClick, targets } = config;
if (!title) {
logWarning(`Could not register added link with title '${title}'. Reason: Title is missing.`);
continue;
}
if (!description) {
logWarning(`Could not register added link with title '${title}'. Reason: Description is missing.`);
continue;
}
if (!isConfigureFnValid(configure)) {
logWarning(`Could not register added link with title '${title}'. Reason: configure is not a function.`);
continue;
}
if (!path && !onClick) {
logWarning(
`Could not register added link with title '${title}'. Reason: Either "path" or "onClick" is required.`
);
continue;
}
if (path && !isLinkPathValid(pluginId, path)) {
logWarning(
`Could not register added link with title '${title}'. Reason: The "path" is required and should start with "/a/${pluginId}/" (currently: "${path}"). Skipping the extension.`
);
continue;
}
Plugin Extensions: Require meta-data to be defined in `plugin.json` during development mode (#93429) * feat: add extensions to the backend plugin model * feat: update the frontend plugin types * feat(pluginContext): return a `null` if there is no context found This will be necessary to understand if a certain hook is running inside a plugin context or not. * feat: add utility functions for checking extension configs * tests: fix failing tests due to the type updates * feat(AddedComponentsRegistry): validate plugin meta-info * feat(AddedLinksRegistry): validate meta-info * feat(ExposedComponentsRegistry): validate meta-info * feat(usePluginComponent): add meta-info validation * feat(usePluginComponents): add meta-info validation * feat(usePluginLinks): add meta-info validation * fix: only validate meta-info in registries if dev mode is enabled * tests: add unit tests for the restrictions functionality * tests: fix Go tests * fix(tests): revert accidental changes * fix: run goimports * fix: api tests * add nested app so that meta data can bested e2e tested * refactor(types): extract the ExtensionInfo into a separate type * refactor(extensions/utils): use Array.prototype.some() instead of .find() * refactor(usePluginLinks): update warning message * feat(usePluginExtensions()): validate plugin meta-info * Wip * fix(e2e): E2E tests for extensions * fix(extensions): allow multiple "/" slashes in the extension point id * fix(extensions/validators): stop validating the plugin id pattern --------- Co-authored-by: Erik Sundell <erik.sundell87@gmail.com>
2024-10-04 14:41:26 +08:00
if (pluginId !== 'grafana' && isGrafanaDevMode() && isAddedLinkMetaInfoMissing(pluginId, config)) {
continue;
}
Plugin extensions: Introduce new registry for added links (#92343) * add added component registry * fix broken test * add tests for usePluginComponents hook * readd expose components * add type assertion exceptions to betterer results * use new addedComponent registry in legacy endpoints * remove unused code * cleanup * revert test code * remove commented code * initial commit * refactor sync method and hook * fix tests * subscribe to the correct registry * remove old registry * cleanup types * add use usePluginLinks hook * add more tests * fix import order * fix typo * fix and temporarly skip failing tests * wip * add hook tests * add more tests * remove old hook * fix versioning * add version to all extension point ids * remove cleanup * remove unused imports * revert touched file * fix test * test: remove hook creation * catch init error * send error to faro * fix broken hook * comment out call hook initialization * use the right import ofr isString * remove unused import * remove registryState type * pr feedback * Update public/app/features/plugins/extensions/validators.test.tsx Co-authored-by: Levente Balogh <balogh.levente.hu@gmail.com> * Update public/app/features/plugins/extensions/validators.test.tsx Co-authored-by: Levente Balogh <balogh.levente.hu@gmail.com> * remove no longer relevant comment * fix broken tests * Fixed test to verify that the memotization works properly. * simplify hooks --------- Co-authored-by: Levente Balogh <balogh.levente.hu@gmail.com> Co-authored-by: Marcus Andersson <marcus.andersson@grafana.com>
2024-08-30 16:09:01 +08:00
const extensionPointIds = Array.isArray(targets) ? targets : [targets];
for (const extensionPointId of extensionPointIds) {
if (!isGrafanaCoreExtensionPoint(extensionPointId) && !extensionPointEndsWithVersion(extensionPointId)) {
logWarning(
Plugin Extensions: Require meta-data to be defined in `plugin.json` during development mode (#93429) * feat: add extensions to the backend plugin model * feat: update the frontend plugin types * feat(pluginContext): return a `null` if there is no context found This will be necessary to understand if a certain hook is running inside a plugin context or not. * feat: add utility functions for checking extension configs * tests: fix failing tests due to the type updates * feat(AddedComponentsRegistry): validate plugin meta-info * feat(AddedLinksRegistry): validate meta-info * feat(ExposedComponentsRegistry): validate meta-info * feat(usePluginComponent): add meta-info validation * feat(usePluginComponents): add meta-info validation * feat(usePluginLinks): add meta-info validation * fix: only validate meta-info in registries if dev mode is enabled * tests: add unit tests for the restrictions functionality * tests: fix Go tests * fix(tests): revert accidental changes * fix: run goimports * fix: api tests * add nested app so that meta data can bested e2e tested * refactor(types): extract the ExtensionInfo into a separate type * refactor(extensions/utils): use Array.prototype.some() instead of .find() * refactor(usePluginLinks): update warning message * feat(usePluginExtensions()): validate plugin meta-info * Wip * fix(e2e): E2E tests for extensions * fix(extensions): allow multiple "/" slashes in the extension point id * fix(extensions/validators): stop validating the plugin id pattern --------- Co-authored-by: Erik Sundell <erik.sundell87@gmail.com>
2024-10-04 14:41:26 +08:00
`Added link "${config.title}: it's recommended to suffix the extension point id ("${extensionPointId}") with a version, e.g 'myorg-basic-app/extension-point/v1'.`
Plugin extensions: Introduce new registry for added links (#92343) * add added component registry * fix broken test * add tests for usePluginComponents hook * readd expose components * add type assertion exceptions to betterer results * use new addedComponent registry in legacy endpoints * remove unused code * cleanup * revert test code * remove commented code * initial commit * refactor sync method and hook * fix tests * subscribe to the correct registry * remove old registry * cleanup types * add use usePluginLinks hook * add more tests * fix import order * fix typo * fix and temporarly skip failing tests * wip * add hook tests * add more tests * remove old hook * fix versioning * add version to all extension point ids * remove cleanup * remove unused imports * revert touched file * fix test * test: remove hook creation * catch init error * send error to faro * fix broken hook * comment out call hook initialization * use the right import ofr isString * remove unused import * remove registryState type * pr feedback * Update public/app/features/plugins/extensions/validators.test.tsx Co-authored-by: Levente Balogh <balogh.levente.hu@gmail.com> * Update public/app/features/plugins/extensions/validators.test.tsx Co-authored-by: Levente Balogh <balogh.levente.hu@gmail.com> * remove no longer relevant comment * fix broken tests * Fixed test to verify that the memotization works properly. * simplify hooks --------- Co-authored-by: Levente Balogh <balogh.levente.hu@gmail.com> Co-authored-by: Marcus Andersson <marcus.andersson@grafana.com>
2024-08-30 16:09:01 +08:00
);
}
const { targets, ...registryItem } = config;
if (!(extensionPointId in registry)) {
registry[extensionPointId] = [];
}
registry[extensionPointId].push({ ...registryItem, pluginId, extensionPointId });
}
}
return registry;
}
// Returns a read-only version of the registry.
readOnly() {
return new AddedLinksRegistry({
registrySubject: this.registrySubject,
});
}
Plugin extensions: Introduce new registry for added links (#92343) * add added component registry * fix broken test * add tests for usePluginComponents hook * readd expose components * add type assertion exceptions to betterer results * use new addedComponent registry in legacy endpoints * remove unused code * cleanup * revert test code * remove commented code * initial commit * refactor sync method and hook * fix tests * subscribe to the correct registry * remove old registry * cleanup types * add use usePluginLinks hook * add more tests * fix import order * fix typo * fix and temporarly skip failing tests * wip * add hook tests * add more tests * remove old hook * fix versioning * add version to all extension point ids * remove cleanup * remove unused imports * revert touched file * fix test * test: remove hook creation * catch init error * send error to faro * fix broken hook * comment out call hook initialization * use the right import ofr isString * remove unused import * remove registryState type * pr feedback * Update public/app/features/plugins/extensions/validators.test.tsx Co-authored-by: Levente Balogh <balogh.levente.hu@gmail.com> * Update public/app/features/plugins/extensions/validators.test.tsx Co-authored-by: Levente Balogh <balogh.levente.hu@gmail.com> * remove no longer relevant comment * fix broken tests * Fixed test to verify that the memotization works properly. * simplify hooks --------- Co-authored-by: Levente Balogh <balogh.levente.hu@gmail.com> Co-authored-by: Marcus Andersson <marcus.andersson@grafana.com>
2024-08-30 16:09:01 +08:00
}