From abc0e8fb89480387e953250949e4adbd23562fdc Mon Sep 17 00:00:00 2001 From: "sentry[bot]" <39604003+sentry[bot]@users.noreply.github.com> Date: Thu, 21 May 2026 12:41:52 +0000 Subject: [PATCH] fix(plugins): Guard against non-array data in pluginsStore.onFetchAllSuccess --- static/app/stores/pluginsStore.tsx | 85 ++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 static/app/stores/pluginsStore.tsx diff --git a/static/app/stores/pluginsStore.tsx b/static/app/stores/pluginsStore.tsx new file mode 100644 index 00000000000000..c97ea499c450dc --- /dev/null +++ b/static/app/stores/pluginsStore.tsx @@ -0,0 +1,85 @@ +import {createStore} from 'reflux'; + +import type {Plugin} from 'sentry/types/integrations'; + +import type {StrictStoreDefinition} from './types'; + +type State = { + error: Error | null; + loading: boolean; + pageLinks: string | null; + plugins: Plugin[]; +}; + +interface PluginsStoreDefinition extends StrictStoreDefinition { + onFetchAllError(err: Error): void; + onFetchAllSuccess(data: Plugin[], options: {pageLinks?: string | null}): void; + onFetchAllStart(): void; + reset(): void; + triggerState(): void; +} + +const storeConfig: PluginsStoreDefinition = { + plugins: new Map(), + + state: { + plugins: [], + loading: true, + error: null, + pageLinks: null, + }, + + init() { + // XXX: Do not use `this.listenTo` in this store. We avoid usage of reflux + // listeners due to their leaky nature in tests. + this.reset(); + }, + + reset() { + this.plugins = new Map(); + this.state = { + plugins: [], + loading: true, + error: null, + pageLinks: null, + }; + }, + + triggerState() { + this.trigger({ + ...this.state, + plugins: this.plugins ? [...this.plugins.values()] : [], + }); + }, + + onFetchAllStart() { + this.state.loading = true; + this.state.error = null; + this.triggerState(); + }, + + onFetchAllSuccess(data: Plugin[], {pageLinks}: {pageLinks?: string | null}) { + const dataArray = Array.isArray(data) ? data : []; + this.plugins = new Map(dataArray.map(plugin => [plugin.id, plugin])); + this.state.pageLinks = pageLinks || null; + this.state.loading = false; + this.triggerState(); + }, + + onFetchAllError(err: Error) { + this.plugins = null; + this.state.loading = false; + this.state.error = err; + this.triggerState(); + }, + + getState() { + return { + ...this.state, + plugins: this.plugins ? [...this.plugins.values()] : [], + }; + }, +}; + +const PluginsStore = createStore(storeConfig); +export default PluginsStore; \ No newline at end of file