/* eslint no-console:0 */ import {DefaultIssuePlugin} from 'sentry/plugins/defaultIssuePlugin'; import {DefaultPlugin} from 'sentry/plugins/defaultPlugin'; import type SessionStackPlugin from 'sentry/plugins/sessionstack'; import type {Plugin} from 'sentry/types/integrations'; import {defined} from 'sentry/utils'; type PluginComponent = | typeof DefaultIssuePlugin | typeof DefaultPlugin | typeof SessionStackPlugin; export default class Registry { plugins: Record = {}; assetCache: Record = {}; isLoaded(data: Plugin) { return defined(this.plugins[data.id]); } load( data: Plugin, callback: (instance: DefaultIssuePlugin | DefaultPlugin | SessionStackPlugin) => void ) { let remainingAssets = data.assets.length; // TODO(dcramer): we should probably register all valid plugins const finishLoad = () => { if (!defined(this.plugins[data.id])) { if (data.type === 'issue-tracking') { this.plugins[data.id] = DefaultIssuePlugin; } else { this.plugins[data.id] = DefaultPlugin; } } console.info( '[plugins] Loaded ' + data.id + ' as {' + this.plugins[data.id].name + '}' ); callback(this.get(data)); }; if (remainingAssets === 0) { finishLoad(); return; } const onAssetLoaded = function () { remainingAssets--; if (remainingAssets === 0) { finishLoad(); } }; const onAssetFailed = function (asset: {url: string}) { remainingAssets--; console.error('[plugins] Failed to load asset ' + asset.url); if (remainingAssets === 0) { finishLoad(); } }; // TODO(dcramer): what do we do on failed asset loading? data.assets.forEach(asset => { if (!defined(this.assetCache[asset.url])) { console.info('[plugins] Loading asset for ' + data.id + ': ' + asset.url); const s = document.createElement('script'); s.src = asset.url; s.onload = onAssetLoaded.bind(this); s.onerror = onAssetFailed.bind(this, asset); s.async = true; document.body.appendChild(s); this.assetCache[asset.url] = s; } else { onAssetLoaded(); } }); } get(data: Plugin) { const cls = this.plugins[data.id]; if (!defined(cls)) { throw new Error('Attempted to ``get`` an unloaded plugin: ' + data.id); } return new cls(data); } add(id: string, cls: PluginComponent) { this.plugins[id] = cls; } }