@perses-dev/plugin-system 0.55.0-beta.14 → 0.55.0-beta.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/dist/components/DatasourceSelect/DatasourceSelect.d.ts.map +1 -1
  2. package/dist/components/DatasourceSelect/DatasourceSelect.js +0 -1
  3. package/dist/components/DatasourceSelect/DatasourceSelect.js.map +1 -1
  4. package/dist/components/DatasourceTestConnectionButton/DatasourceTestConnectionButton.d.ts.map +1 -1
  5. package/dist/components/DatasourceTestConnectionButton/DatasourceTestConnectionButton.js +2 -7
  6. package/dist/components/DatasourceTestConnectionButton/DatasourceTestConnectionButton.js.map +1 -1
  7. package/dist/components/HTTPSettingsEditor/HTTPProxyOAuthPassthroughEditor.d.ts +11 -0
  8. package/dist/components/HTTPSettingsEditor/HTTPProxyOAuthPassthroughEditor.d.ts.map +1 -0
  9. package/dist/components/HTTPSettingsEditor/HTTPProxyOAuthPassthroughEditor.js +62 -0
  10. package/dist/components/HTTPSettingsEditor/HTTPProxyOAuthPassthroughEditor.js.map +1 -0
  11. package/dist/components/HTTPSettingsEditor/HTTPSettingsEditor.d.ts +1 -1
  12. package/dist/components/HTTPSettingsEditor/HTTPSettingsEditor.d.ts.map +1 -1
  13. package/dist/components/HTTPSettingsEditor/HTTPSettingsEditor.js +36 -13
  14. package/dist/components/HTTPSettingsEditor/HTTPSettingsEditor.js.map +1 -1
  15. package/dist/components/ItemSelectionActionsOptionsEditor/ItemSelectionActionsOptionsEditor.d.ts.map +1 -1
  16. package/dist/components/ItemSelectionActionsOptionsEditor/ItemSelectionActionsOptionsEditor.js +7 -1
  17. package/dist/components/ItemSelectionActionsOptionsEditor/ItemSelectionActionsOptionsEditor.js.map +1 -1
  18. package/dist/components/LinksEditor/LinksEditor.js +5 -0
  19. package/dist/components/LinksEditor/LinksEditor.js.map +1 -1
  20. package/dist/components/PluginEditor/plugin-editor-api.d.ts.map +1 -1
  21. package/dist/components/PluginEditor/plugin-editor-api.js +54 -46
  22. package/dist/components/PluginEditor/plugin-editor-api.js.map +1 -1
  23. package/dist/components/TimeRangeControls/TimeRangeControls.d.ts.map +1 -1
  24. package/dist/components/TimeRangeControls/TimeRangeControls.js +0 -2
  25. package/dist/components/TimeRangeControls/TimeRangeControls.js.map +1 -1
  26. package/dist/components/Variables/VariableEditorForm/VariablePreview.js +1 -1
  27. package/dist/components/Variables/VariableEditorForm/VariablePreview.js.map +1 -1
  28. package/dist/remote/PluginLoaderComponent.d.ts.map +1 -1
  29. package/dist/remote/PluginLoaderComponent.js +28 -15
  30. package/dist/remote/PluginLoaderComponent.js.map +1 -1
  31. package/dist/remote/PluginRuntime.d.ts.map +1 -1
  32. package/dist/remote/PluginRuntime.js +28 -21
  33. package/dist/remote/PluginRuntime.js.map +1 -1
  34. package/dist/runtime/TimeRangeProvider/query-params.js +7 -9
  35. package/dist/runtime/TimeRangeProvider/query-params.js.map +1 -1
  36. package/dist/runtime/UsageMetricsProvider.d.ts.map +1 -1
  37. package/dist/runtime/UsageMetricsProvider.js +24 -20
  38. package/dist/runtime/UsageMetricsProvider.js.map +1 -1
  39. package/package.json +3 -3
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/TimeRangeControls/TimeRangeControls.tsx"],"sourcesContent":["// Copyright The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport { Stack } from '@mui/material';\nimport type { TimeOption, TimeZoneOption } from '@perses-dev/components';\nimport {\n RefreshIntervalPicker,\n InfoTooltip,\n ToolbarIconButton,\n TimeRangeSelector,\n getTimeZoneOptions,\n buildRelativeTimeOption,\n} from '@perses-dev/components';\nimport type { AbsoluteTimeRange, DurationString, RelativeTimeRange } from '@perses-dev/spec';\nimport { parseDurationString } from '@perses-dev/spec';\nimport { milliseconds } from 'date-fns';\n// eslint-disable-next-line import/no-duplicates\nimport ZoomOut from 'mdi-material-ui/MinusCircleOutline';\n// eslint-disable-next-line import/no-duplicates\nimport ZoomIn from 'mdi-material-ui/PlusCircleOutline';\nimport RefreshIcon from 'mdi-material-ui/Refresh';\nimport type { ReactElement } from 'react';\nimport { useCallback } from 'react';\n\nimport { TOOLTIP_TEXT } from '../../constants/user-interface-text';\nimport { useTimeRange } from '../../runtime/TimeRangeProvider/TimeRangeProvider';\nimport {\n useShowCustomTimeRangeSetting,\n useTimeRangeOptionsSetting,\n useShowZoomRangeSetting,\n useDisableAutoRefreshSetting,\n useAutoRefreshIntervalsOptions,\n} from '../../runtime/TimeRangeProvider/TimeRangeSettingsProvider';\n\nconst DEFAULT_HEIGHT = '34px';\n\ninterface TimeRangeControlsProps {\n // The controls look best at heights >= 28 pixels\n heightPx?: number;\n showTimeRangeSelector?: boolean;\n showRefreshButton?: boolean;\n showRefreshInterval?: boolean;\n showCustomTimeRange?: boolean;\n showZoomButtons?: boolean;\n timePresets?: TimeOption[];\n refreshIntervalOptions?: TimeOption[];\n timeZone: string;\n onTimeZoneChange: (timeZone: TimeZoneOption) => void;\n}\n\nexport function TimeRangeControls({\n heightPx,\n showTimeRangeSelector = true,\n showRefreshButton = true,\n showRefreshInterval = true,\n showCustomTimeRange,\n showZoomButtons = true,\n timePresets,\n timeZone,\n refreshIntervalOptions,\n onTimeZoneChange,\n}: TimeRangeControlsProps): ReactElement {\n const { timeRange, setTimeRange, refresh, refreshInterval, setRefreshInterval } = useTimeRange();\n\n const showCustomTimeRangeValue = useShowCustomTimeRangeSetting(showCustomTimeRange);\n const showZoomInOutButtons = useShowZoomRangeSetting(showZoomButtons);\n const isAutoRefreshDisabled = useDisableAutoRefreshSetting();\n const timePresetsValue = useTimeRangeOptionsSetting(timePresets);\n const autoRefreshIntervalOptions = useAutoRefreshIntervalsOptions(refreshIntervalOptions);\n\n // Convert height to a string, then use the string for styling\n const height = heightPx === undefined ? DEFAULT_HEIGHT : `${heightPx}px`;\n\n // add time preset if one does not match duration given in time range, keeping the list ordered by duration\n if (\n 'pastDuration' in timeRange &&\n !timePresetsValue.some((option) => option.value.pastDuration === timeRange['pastDuration'])\n ) {\n const durationMs = milliseconds(parseDurationString(timeRange['pastDuration']));\n const insertionIndex = timePresetsValue.findIndex(\n (option) => milliseconds(parseDurationString(option.value.pastDuration)) > durationMs,\n );\n timePresetsValue.splice(\n insertionIndex === -1 ? timePresetsValue.length : insertionIndex,\n 0,\n buildRelativeTimeOption(timeRange['pastDuration']),\n );\n }\n\n // set the new refresh interval both in the dashboard context & as query param\n const handleRefreshIntervalChange = useCallback(\n (duration: DurationString) => {\n setRefreshInterval(duration);\n },\n [setRefreshInterval],\n );\n\n const fromDurationToMillis = (strDuration: string): number => {\n const duration = parseDurationString(strDuration);\n const millis =\n ((duration.seconds ?? 0) +\n (duration.minutes ?? 0) * 60 +\n (duration.hours ?? 0) * 3600 +\n (duration.days ?? 0) * 86400 +\n (duration.weeks ?? 0) * 7 * 86400 +\n (duration.months ?? 0) * 30.436875 * 86400 + // avg month duration is ok for zoom purposes\n (duration.years ?? 0) * 365.2425 * 86400) * // avg year duration is ok for zoom purposes\n 1000; // to milliseconds\n return millis;\n };\n\n // Function to double current time range, adding 50% before current start and 50% after current end\n const doubleTimeRange = (): AbsoluteTimeRange => {\n let newStart, newEnd, extendEndsBy;\n const now = new Date();\n if (Object.hasOwn(timeRange, 'start')) {\n // current range is absolute\n const absVal = timeRange as AbsoluteTimeRange;\n extendEndsBy = (absVal.end.getTime() - absVal.start.getTime()) / 2; // half it to add 50% before current start and after current end\n newStart = new Date(absVal.start.getTime() - extendEndsBy);\n newEnd = new Date(absVal.end.getTime() + extendEndsBy);\n } else {\n // current range is relative\n const relVal = timeRange as RelativeTimeRange;\n extendEndsBy = fromDurationToMillis(relVal.pastDuration) / 2;\n newEnd = typeof relVal.end === 'undefined' ? now : new Date(relVal.end.getTime() + extendEndsBy);\n newStart = new Date(newEnd.getTime() - extendEndsBy * 4);\n }\n if (newEnd.getTime() > now.getTime()) {\n // if the new computed end is in the future\n newEnd = now;\n newStart.setTime(now.getTime() - extendEndsBy * 4);\n }\n if (newStart.getTime() < 1) {\n newStart.setTime(1);\n }\n return { start: newStart, end: newEnd };\n };\n\n // Function to half current time range, cutting 25% before current start and 25% after current end\n const halfTimeRange = (): AbsoluteTimeRange => {\n let newStart, newEnd;\n if (Object.hasOwn(timeRange, 'start')) {\n const absVal = timeRange as AbsoluteTimeRange;\n const shrinkEndsBy = (absVal.end.getTime() - absVal.start.getTime()) / 4;\n newStart = new Date(absVal.start.getTime() + shrinkEndsBy);\n newEnd = new Date(absVal.end.getTime() - shrinkEndsBy);\n } else {\n const relVal = timeRange as RelativeTimeRange;\n const shrinkEndsBy = fromDurationToMillis(relVal.pastDuration) / 4; // 25% of it to cut after current start and before current end\n const endIsAbsolute = typeof relVal.end !== 'undefined';\n newEnd = endIsAbsolute ? new Date(relVal.end!.getTime() - shrinkEndsBy) : new Date();\n newStart = new Date(newEnd.getTime() - shrinkEndsBy * 2);\n }\n if (newStart.getTime() >= newEnd.getTime() - 1000) {\n newStart.setTime(newEnd.getTime() - 1000);\n }\n return { start: newStart, end: newEnd };\n };\n\n const setHalfTimeRange = (): void => setTimeRange(halfTimeRange());\n const setDoubleTimeRange = (): void => setTimeRange(doubleTimeRange());\n\n const handleTimeZoneChange = useCallback(\n (tz: TimeZoneOption) => {\n onTimeZoneChange(tz);\n },\n [onTimeZoneChange],\n );\n\n return (\n <Stack direction=\"row\" spacing={1}>\n {showTimeRangeSelector && (\n <TimeRangeSelector\n timeOptions={timePresetsValue}\n value={timeRange}\n onChange={setTimeRange}\n height={height}\n showCustomTimeRange={showCustomTimeRangeValue}\n timeZone={timeZone}\n timeZoneOptions={getTimeZoneOptions()}\n onTimeZoneChange={handleTimeZoneChange}\n />\n )}\n {showZoomInOutButtons && (\n <InfoTooltip description={TOOLTIP_TEXT.zoomOut}>\n <ToolbarIconButton aria-label={TOOLTIP_TEXT.zoomOut} onClick={setDoubleTimeRange} sx={{ height }}>\n <ZoomOut />\n </ToolbarIconButton>\n </InfoTooltip>\n )}\n {showZoomInOutButtons && (\n <InfoTooltip description={TOOLTIP_TEXT.zoomIn}>\n <ToolbarIconButton aria-label={TOOLTIP_TEXT.zoomIn} onClick={setHalfTimeRange} sx={{ height }}>\n <ZoomIn />\n </ToolbarIconButton>\n </InfoTooltip>\n )}\n {showRefreshButton && (\n <InfoTooltip description={TOOLTIP_TEXT.refresh}>\n <ToolbarIconButton aria-label={TOOLTIP_TEXT.refresh} onClick={refresh} sx={{ height }}>\n <RefreshIcon />\n </ToolbarIconButton>\n </InfoTooltip>\n )}\n {showRefreshInterval && !isAutoRefreshDisabled && (\n <InfoTooltip description={TOOLTIP_TEXT.refreshInterval}>\n <RefreshIntervalPicker\n timeOptions={autoRefreshIntervalOptions}\n value={\n /* TODO: There is a bug here which should be fixed in a proper way. (This is only a quick remedy)\n display: 1m has the pastDuration of 60s. Initially (if the persisted value is 1m) when the page is loaded, instead of 60s, 1m is passed down. \n This only happens for 1m, because for other items the display and the pastDuration are the same. Example 30s-30s\n HERE The value MUST always be pastDuration, otherwise the component would not work as expected. \n */\n autoRefreshIntervalOptions.some((i) => i.value.pastDuration === refreshInterval)\n ? refreshInterval\n : autoRefreshIntervalOptions.find((i) => i.display === refreshInterval)?.value.pastDuration\n }\n onChange={handleRefreshIntervalChange}\n height={height}\n />\n </InfoTooltip>\n )}\n </Stack>\n );\n}\n"],"names":["Stack","RefreshIntervalPicker","InfoTooltip","ToolbarIconButton","TimeRangeSelector","getTimeZoneOptions","buildRelativeTimeOption","parseDurationString","milliseconds","ZoomOut","ZoomIn","RefreshIcon","useCallback","TOOLTIP_TEXT","useTimeRange","useShowCustomTimeRangeSetting","useTimeRangeOptionsSetting","useShowZoomRangeSetting","useDisableAutoRefreshSetting","useAutoRefreshIntervalsOptions","DEFAULT_HEIGHT","TimeRangeControls","heightPx","showTimeRangeSelector","showRefreshButton","showRefreshInterval","showCustomTimeRange","showZoomButtons","timePresets","timeZone","refreshIntervalOptions","onTimeZoneChange","timeRange","setTimeRange","refresh","refreshInterval","setRefreshInterval","showCustomTimeRangeValue","showZoomInOutButtons","isAutoRefreshDisabled","timePresetsValue","autoRefreshIntervalOptions","height","undefined","some","option","value","pastDuration","durationMs","insertionIndex","findIndex","splice","length","handleRefreshIntervalChange","duration","fromDurationToMillis","strDuration","millis","seconds","minutes","hours","days","weeks","months","years","doubleTimeRange","newStart","newEnd","extendEndsBy","now","Date","Object","hasOwn","absVal","end","getTime","start","relVal","setTime","halfTimeRange","shrinkEndsBy","endIsAbsolute","setHalfTimeRange","setDoubleTimeRange","handleTimeZoneChange","tz","direction","spacing","timeOptions","onChange","timeZoneOptions","description","zoomOut","aria-label","onClick","sx","zoomIn","i","find","display"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/components/TimeRangeControls/TimeRangeControls.tsx"],"sourcesContent":["// Copyright The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport { Stack } from '@mui/material';\nimport type { TimeOption, TimeZoneOption } from '@perses-dev/components';\nimport {\n RefreshIntervalPicker,\n InfoTooltip,\n ToolbarIconButton,\n TimeRangeSelector,\n getTimeZoneOptions,\n buildRelativeTimeOption,\n} from '@perses-dev/components';\nimport type { AbsoluteTimeRange, DurationString, RelativeTimeRange } from '@perses-dev/spec';\nimport { parseDurationString } from '@perses-dev/spec';\nimport { milliseconds } from 'date-fns';\nimport ZoomOut from 'mdi-material-ui/MinusCircleOutline';\nimport ZoomIn from 'mdi-material-ui/PlusCircleOutline';\nimport RefreshIcon from 'mdi-material-ui/Refresh';\nimport type { ReactElement } from 'react';\nimport { useCallback } from 'react';\n\nimport { TOOLTIP_TEXT } from '../../constants/user-interface-text';\nimport { useTimeRange } from '../../runtime/TimeRangeProvider/TimeRangeProvider';\nimport {\n useShowCustomTimeRangeSetting,\n useTimeRangeOptionsSetting,\n useShowZoomRangeSetting,\n useDisableAutoRefreshSetting,\n useAutoRefreshIntervalsOptions,\n} from '../../runtime/TimeRangeProvider/TimeRangeSettingsProvider';\n\nconst DEFAULT_HEIGHT = '34px';\n\ninterface TimeRangeControlsProps {\n // The controls look best at heights >= 28 pixels\n heightPx?: number;\n showTimeRangeSelector?: boolean;\n showRefreshButton?: boolean;\n showRefreshInterval?: boolean;\n showCustomTimeRange?: boolean;\n showZoomButtons?: boolean;\n timePresets?: TimeOption[];\n refreshIntervalOptions?: TimeOption[];\n timeZone: string;\n onTimeZoneChange: (timeZone: TimeZoneOption) => void;\n}\n\nexport function TimeRangeControls({\n heightPx,\n showTimeRangeSelector = true,\n showRefreshButton = true,\n showRefreshInterval = true,\n showCustomTimeRange,\n showZoomButtons = true,\n timePresets,\n timeZone,\n refreshIntervalOptions,\n onTimeZoneChange,\n}: TimeRangeControlsProps): ReactElement {\n const { timeRange, setTimeRange, refresh, refreshInterval, setRefreshInterval } = useTimeRange();\n\n const showCustomTimeRangeValue = useShowCustomTimeRangeSetting(showCustomTimeRange);\n const showZoomInOutButtons = useShowZoomRangeSetting(showZoomButtons);\n const isAutoRefreshDisabled = useDisableAutoRefreshSetting();\n const timePresetsValue = useTimeRangeOptionsSetting(timePresets);\n const autoRefreshIntervalOptions = useAutoRefreshIntervalsOptions(refreshIntervalOptions);\n\n // Convert height to a string, then use the string for styling\n const height = heightPx === undefined ? DEFAULT_HEIGHT : `${heightPx}px`;\n\n // add time preset if one does not match duration given in time range, keeping the list ordered by duration\n if (\n 'pastDuration' in timeRange &&\n !timePresetsValue.some((option) => option.value.pastDuration === timeRange['pastDuration'])\n ) {\n const durationMs = milliseconds(parseDurationString(timeRange['pastDuration']));\n const insertionIndex = timePresetsValue.findIndex(\n (option) => milliseconds(parseDurationString(option.value.pastDuration)) > durationMs,\n );\n timePresetsValue.splice(\n insertionIndex === -1 ? timePresetsValue.length : insertionIndex,\n 0,\n buildRelativeTimeOption(timeRange['pastDuration']),\n );\n }\n\n // set the new refresh interval both in the dashboard context & as query param\n const handleRefreshIntervalChange = useCallback(\n (duration: DurationString) => {\n setRefreshInterval(duration);\n },\n [setRefreshInterval],\n );\n\n const fromDurationToMillis = (strDuration: string): number => {\n const duration = parseDurationString(strDuration);\n const millis =\n ((duration.seconds ?? 0) +\n (duration.minutes ?? 0) * 60 +\n (duration.hours ?? 0) * 3600 +\n (duration.days ?? 0) * 86400 +\n (duration.weeks ?? 0) * 7 * 86400 +\n (duration.months ?? 0) * 30.436875 * 86400 + // avg month duration is ok for zoom purposes\n (duration.years ?? 0) * 365.2425 * 86400) * // avg year duration is ok for zoom purposes\n 1000; // to milliseconds\n return millis;\n };\n\n // Function to double current time range, adding 50% before current start and 50% after current end\n const doubleTimeRange = (): AbsoluteTimeRange => {\n let newStart, newEnd, extendEndsBy;\n const now = new Date();\n if (Object.hasOwn(timeRange, 'start')) {\n // current range is absolute\n const absVal = timeRange as AbsoluteTimeRange;\n extendEndsBy = (absVal.end.getTime() - absVal.start.getTime()) / 2; // half it to add 50% before current start and after current end\n newStart = new Date(absVal.start.getTime() - extendEndsBy);\n newEnd = new Date(absVal.end.getTime() + extendEndsBy);\n } else {\n // current range is relative\n const relVal = timeRange as RelativeTimeRange;\n extendEndsBy = fromDurationToMillis(relVal.pastDuration) / 2;\n newEnd = typeof relVal.end === 'undefined' ? now : new Date(relVal.end.getTime() + extendEndsBy);\n newStart = new Date(newEnd.getTime() - extendEndsBy * 4);\n }\n if (newEnd.getTime() > now.getTime()) {\n // if the new computed end is in the future\n newEnd = now;\n newStart.setTime(now.getTime() - extendEndsBy * 4);\n }\n if (newStart.getTime() < 1) {\n newStart.setTime(1);\n }\n return { start: newStart, end: newEnd };\n };\n\n // Function to half current time range, cutting 25% before current start and 25% after current end\n const halfTimeRange = (): AbsoluteTimeRange => {\n let newStart, newEnd;\n if (Object.hasOwn(timeRange, 'start')) {\n const absVal = timeRange as AbsoluteTimeRange;\n const shrinkEndsBy = (absVal.end.getTime() - absVal.start.getTime()) / 4;\n newStart = new Date(absVal.start.getTime() + shrinkEndsBy);\n newEnd = new Date(absVal.end.getTime() - shrinkEndsBy);\n } else {\n const relVal = timeRange as RelativeTimeRange;\n const shrinkEndsBy = fromDurationToMillis(relVal.pastDuration) / 4; // 25% of it to cut after current start and before current end\n const endIsAbsolute = typeof relVal.end !== 'undefined';\n newEnd = endIsAbsolute ? new Date(relVal.end!.getTime() - shrinkEndsBy) : new Date();\n newStart = new Date(newEnd.getTime() - shrinkEndsBy * 2);\n }\n if (newStart.getTime() >= newEnd.getTime() - 1000) {\n newStart.setTime(newEnd.getTime() - 1000);\n }\n return { start: newStart, end: newEnd };\n };\n\n const setHalfTimeRange = (): void => setTimeRange(halfTimeRange());\n const setDoubleTimeRange = (): void => setTimeRange(doubleTimeRange());\n\n const handleTimeZoneChange = useCallback(\n (tz: TimeZoneOption) => {\n onTimeZoneChange(tz);\n },\n [onTimeZoneChange],\n );\n\n return (\n <Stack direction=\"row\" spacing={1}>\n {showTimeRangeSelector && (\n <TimeRangeSelector\n timeOptions={timePresetsValue}\n value={timeRange}\n onChange={setTimeRange}\n height={height}\n showCustomTimeRange={showCustomTimeRangeValue}\n timeZone={timeZone}\n timeZoneOptions={getTimeZoneOptions()}\n onTimeZoneChange={handleTimeZoneChange}\n />\n )}\n {showZoomInOutButtons && (\n <InfoTooltip description={TOOLTIP_TEXT.zoomOut}>\n <ToolbarIconButton aria-label={TOOLTIP_TEXT.zoomOut} onClick={setDoubleTimeRange} sx={{ height }}>\n <ZoomOut />\n </ToolbarIconButton>\n </InfoTooltip>\n )}\n {showZoomInOutButtons && (\n <InfoTooltip description={TOOLTIP_TEXT.zoomIn}>\n <ToolbarIconButton aria-label={TOOLTIP_TEXT.zoomIn} onClick={setHalfTimeRange} sx={{ height }}>\n <ZoomIn />\n </ToolbarIconButton>\n </InfoTooltip>\n )}\n {showRefreshButton && (\n <InfoTooltip description={TOOLTIP_TEXT.refresh}>\n <ToolbarIconButton aria-label={TOOLTIP_TEXT.refresh} onClick={refresh} sx={{ height }}>\n <RefreshIcon />\n </ToolbarIconButton>\n </InfoTooltip>\n )}\n {showRefreshInterval && !isAutoRefreshDisabled && (\n <InfoTooltip description={TOOLTIP_TEXT.refreshInterval}>\n <RefreshIntervalPicker\n timeOptions={autoRefreshIntervalOptions}\n value={\n /* TODO: There is a bug here which should be fixed in a proper way. (This is only a quick remedy)\n display: 1m has the pastDuration of 60s. Initially (if the persisted value is 1m) when the page is loaded, instead of 60s, 1m is passed down. \n This only happens for 1m, because for other items the display and the pastDuration are the same. Example 30s-30s\n HERE The value MUST always be pastDuration, otherwise the component would not work as expected. \n */\n autoRefreshIntervalOptions.some((i) => i.value.pastDuration === refreshInterval)\n ? refreshInterval\n : autoRefreshIntervalOptions.find((i) => i.display === refreshInterval)?.value.pastDuration\n }\n onChange={handleRefreshIntervalChange}\n height={height}\n />\n </InfoTooltip>\n )}\n </Stack>\n );\n}\n"],"names":["Stack","RefreshIntervalPicker","InfoTooltip","ToolbarIconButton","TimeRangeSelector","getTimeZoneOptions","buildRelativeTimeOption","parseDurationString","milliseconds","ZoomOut","ZoomIn","RefreshIcon","useCallback","TOOLTIP_TEXT","useTimeRange","useShowCustomTimeRangeSetting","useTimeRangeOptionsSetting","useShowZoomRangeSetting","useDisableAutoRefreshSetting","useAutoRefreshIntervalsOptions","DEFAULT_HEIGHT","TimeRangeControls","heightPx","showTimeRangeSelector","showRefreshButton","showRefreshInterval","showCustomTimeRange","showZoomButtons","timePresets","timeZone","refreshIntervalOptions","onTimeZoneChange","timeRange","setTimeRange","refresh","refreshInterval","setRefreshInterval","showCustomTimeRangeValue","showZoomInOutButtons","isAutoRefreshDisabled","timePresetsValue","autoRefreshIntervalOptions","height","undefined","some","option","value","pastDuration","durationMs","insertionIndex","findIndex","splice","length","handleRefreshIntervalChange","duration","fromDurationToMillis","strDuration","millis","seconds","minutes","hours","days","weeks","months","years","doubleTimeRange","newStart","newEnd","extendEndsBy","now","Date","Object","hasOwn","absVal","end","getTime","start","relVal","setTime","halfTimeRange","shrinkEndsBy","endIsAbsolute","setHalfTimeRange","setDoubleTimeRange","handleTimeZoneChange","tz","direction","spacing","timeOptions","onChange","timeZoneOptions","description","zoomOut","aria-label","onClick","sx","zoomIn","i","find","display"],"mappings":"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"}
@@ -115,7 +115,7 @@ export function VariableListPreview(props) {
115
115
  const { definition, sortMethod } = props;
116
116
  const { data, isFetching, error } = useListVariablePluginValues(definition);
117
117
  const errorMessage = error?.message;
118
- // oxlint-disable-next-line unicorn/no-array-sort Calling sort of object, not the built-in array sort function
118
+ // oxlint-disable-next-line unicorn/no-array-sort -- Calling sort of object, not the built-in array sort function
119
119
  const result = !sortMethod || sortMethod === 'none' || !data ? data : SORT_METHODS[sortMethod].sort(data);
120
120
  const variablePreview = useMemo(()=>/*#__PURE__*/ _jsx(VariablePreview, {
121
121
  values: result?.map((val)=>val.label || val.value),
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/components/Variables/VariableEditorForm/VariablePreview.tsx"],"sourcesContent":["// Copyright The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport { Alert, Box, Card, Chip, CircularProgress, IconButton, Stack, Typography } from '@mui/material';\nimport { InfoTooltip, useSnackbar } from '@perses-dev/components';\nimport type { ListVariableDefinition } from '@perses-dev/spec';\nimport Clipboard from 'mdi-material-ui/ClipboardOutline';\nimport type { ReactElement } from 'react';\nimport React, { useMemo, useState } from 'react';\n\nimport { TOOLTIP_TEXT } from '../../../constants';\nimport { useListVariablePluginValues } from '../variable-model';\nimport { SORT_METHODS } from './variable-editor-form-model';\n\nconst DEFAULT_MAX_PREVIEW_VALUES = 50;\n\ninterface VariablePreviewProps {\n values?: string[];\n isLoading?: boolean;\n error?: string;\n}\n\nexport function VariablePreview(props: VariablePreviewProps): ReactElement {\n const { values, isLoading, error } = props;\n const [maxValues, setMaxValues] = useState<number | undefined>(DEFAULT_MAX_PREVIEW_VALUES);\n const { infoSnackbar } = useSnackbar();\n const showAll = (): void => {\n setMaxValues(undefined);\n };\n let notShown = 0;\n\n if (values && values?.length > 0 && maxValues) {\n notShown = values.length - maxValues;\n }\n\n const variablePreviewState = useMemo((): ReactElement | null => {\n if (isLoading) {\n return (\n <Stack width=\"100%\" sx={{ alignItems: 'center', justifyContent: 'center' }}>\n <CircularProgress />\n </Stack>\n );\n } else if (error) {\n return <Alert severity=\"error\">{error}</Alert>;\n } else if (!values?.length) {\n return <Alert severity=\"info\">No results</Alert>;\n }\n return null;\n }, [error, isLoading, values]);\n\n return (\n <Box>\n <Stack direction=\"row\" spacing={1} alignItems=\"center\" mb={1}>\n <Typography variant=\"h4\">Preview Values</Typography>\n <InfoTooltip description={TOOLTIP_TEXT.copyVariableValues}>\n <IconButton\n onClick={async () => {\n if (values?.length) {\n await navigator.clipboard.writeText(values.map((value) => value).join(', '));\n infoSnackbar('Preview values copied to clipboard!');\n }\n }}\n size=\"small\"\n >\n <Clipboard />\n </IconButton>\n </InfoTooltip>\n </Stack>\n <Card variant=\"outlined\">\n <Box sx={{ display: 'flex', flexWrap: 'wrap', gap: 1, m: 2 }}>\n {variablePreviewState}\n {values\n ?.slice(0, maxValues)\n .filter((val) => val)\n .map((val, index) => (\n <Chip size=\"small\" key={index} label={val} />\n ))}\n {notShown > 0 && <Chip onClick={showAll} variant=\"outlined\" size=\"small\" label={`+${notShown} more`} />}\n </Box>\n </Card>\n </Box>\n );\n}\n\ninterface VariableListPreviewProps {\n definition: ListVariableDefinition;\n sortMethod?: keyof typeof SORT_METHODS;\n}\n\nexport function VariableListPreview(props: VariableListPreviewProps): ReactElement {\n const { definition, sortMethod } = props;\n const { data, isFetching, error } = useListVariablePluginValues(definition);\n const errorMessage = (error as Error)?.message;\n\n // oxlint-disable-next-line unicorn/no-array-sort Calling sort of object, not the built-in array sort function\n const result = !sortMethod || sortMethod === 'none' || !data ? data : SORT_METHODS[sortMethod].sort(data);\n\n const variablePreview = useMemo(\n () => (\n <VariablePreview\n values={result?.map((val) => val.label || val.value)}\n isLoading={isFetching}\n error={errorMessage}\n />\n ),\n [errorMessage, isFetching, result],\n );\n\n return variablePreview;\n}\n"],"names":["Alert","Box","Card","Chip","CircularProgress","IconButton","Stack","Typography","InfoTooltip","useSnackbar","Clipboard","React","useMemo","useState","TOOLTIP_TEXT","useListVariablePluginValues","SORT_METHODS","DEFAULT_MAX_PREVIEW_VALUES","VariablePreview","props","values","isLoading","error","maxValues","setMaxValues","infoSnackbar","showAll","undefined","notShown","length","variablePreviewState","width","sx","alignItems","justifyContent","severity","direction","spacing","mb","variant","description","copyVariableValues","onClick","navigator","clipboard","writeText","map","value","join","size","display","flexWrap","gap","m","slice","filter","val","index","label","VariableListPreview","definition","sortMethod","data","isFetching","errorMessage","message","result","sort","variablePreview"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../src/components/Variables/VariableEditorForm/VariablePreview.tsx"],"sourcesContent":["// Copyright The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport { Alert, Box, Card, Chip, CircularProgress, IconButton, Stack, Typography } from '@mui/material';\nimport { InfoTooltip, useSnackbar } from '@perses-dev/components';\nimport type { ListVariableDefinition } from '@perses-dev/spec';\nimport Clipboard from 'mdi-material-ui/ClipboardOutline';\nimport type { ReactElement } from 'react';\nimport React, { useMemo, useState } from 'react';\n\nimport { TOOLTIP_TEXT } from '../../../constants';\nimport { useListVariablePluginValues } from '../variable-model';\nimport { SORT_METHODS } from './variable-editor-form-model';\n\nconst DEFAULT_MAX_PREVIEW_VALUES = 50;\n\ninterface VariablePreviewProps {\n values?: string[];\n isLoading?: boolean;\n error?: string;\n}\n\nexport function VariablePreview(props: VariablePreviewProps): ReactElement {\n const { values, isLoading, error } = props;\n const [maxValues, setMaxValues] = useState<number | undefined>(DEFAULT_MAX_PREVIEW_VALUES);\n const { infoSnackbar } = useSnackbar();\n const showAll = (): void => {\n setMaxValues(undefined);\n };\n let notShown = 0;\n\n if (values && values?.length > 0 && maxValues) {\n notShown = values.length - maxValues;\n }\n\n const variablePreviewState = useMemo((): ReactElement | null => {\n if (isLoading) {\n return (\n <Stack width=\"100%\" sx={{ alignItems: 'center', justifyContent: 'center' }}>\n <CircularProgress />\n </Stack>\n );\n } else if (error) {\n return <Alert severity=\"error\">{error}</Alert>;\n } else if (!values?.length) {\n return <Alert severity=\"info\">No results</Alert>;\n }\n return null;\n }, [error, isLoading, values]);\n\n return (\n <Box>\n <Stack direction=\"row\" spacing={1} alignItems=\"center\" mb={1}>\n <Typography variant=\"h4\">Preview Values</Typography>\n <InfoTooltip description={TOOLTIP_TEXT.copyVariableValues}>\n <IconButton\n onClick={async () => {\n if (values?.length) {\n await navigator.clipboard.writeText(values.map((value) => value).join(', '));\n infoSnackbar('Preview values copied to clipboard!');\n }\n }}\n size=\"small\"\n >\n <Clipboard />\n </IconButton>\n </InfoTooltip>\n </Stack>\n <Card variant=\"outlined\">\n <Box sx={{ display: 'flex', flexWrap: 'wrap', gap: 1, m: 2 }}>\n {variablePreviewState}\n {values\n ?.slice(0, maxValues)\n .filter((val) => val)\n .map((val, index) => (\n <Chip size=\"small\" key={index} label={val} />\n ))}\n {notShown > 0 && <Chip onClick={showAll} variant=\"outlined\" size=\"small\" label={`+${notShown} more`} />}\n </Box>\n </Card>\n </Box>\n );\n}\n\ninterface VariableListPreviewProps {\n definition: ListVariableDefinition;\n sortMethod?: keyof typeof SORT_METHODS;\n}\n\nexport function VariableListPreview(props: VariableListPreviewProps): ReactElement {\n const { definition, sortMethod } = props;\n const { data, isFetching, error } = useListVariablePluginValues(definition);\n const errorMessage = (error as Error)?.message;\n\n // oxlint-disable-next-line unicorn/no-array-sort -- Calling sort of object, not the built-in array sort function\n const result = !sortMethod || sortMethod === 'none' || !data ? data : SORT_METHODS[sortMethod].sort(data);\n\n const variablePreview = useMemo(\n () => (\n <VariablePreview\n values={result?.map((val) => val.label || val.value)}\n isLoading={isFetching}\n error={errorMessage}\n />\n ),\n [errorMessage, isFetching, result],\n );\n\n return variablePreview;\n}\n"],"names":["Alert","Box","Card","Chip","CircularProgress","IconButton","Stack","Typography","InfoTooltip","useSnackbar","Clipboard","React","useMemo","useState","TOOLTIP_TEXT","useListVariablePluginValues","SORT_METHODS","DEFAULT_MAX_PREVIEW_VALUES","VariablePreview","props","values","isLoading","error","maxValues","setMaxValues","infoSnackbar","showAll","undefined","notShown","length","variablePreviewState","width","sx","alignItems","justifyContent","severity","direction","spacing","mb","variant","description","copyVariableValues","onClick","navigator","clipboard","writeText","map","value","join","size","display","flexWrap","gap","m","slice","filter","val","index","label","VariableListPreview","definition","sortMethod","data","isFetching","errorMessage","message","result","sort","variablePreview"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"PluginLoaderComponent.d.ts","sourceRoot":"","sources":["../../src/remote/PluginLoaderComponent.tsx"],"names":[],"mappings":"AA6BA,OAAO,KAAK,EAAE,YAAY,EAAsB,MAAM,sBAAsB,CAAC;AAG7E,UAAU,iBAAiB,CAAC,CAAC;IAC3B,MAAM,EAAE,YAAY,CAAC;IACrB,KAAK,CAAC,EAAE,CAAC,CAAC;IACV,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAYD,wBAAgB,qBAAqB,CAAC,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,iBAAiB,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,OAAO,GAAG,IAAI,CA2D3G"}
1
+ {"version":3,"file":"PluginLoaderComponent.d.ts","sourceRoot":"","sources":["../../src/remote/PluginLoaderComponent.tsx"],"names":[],"mappings":"AA4BA,OAAO,KAAK,EAAE,YAAY,EAAsB,MAAM,sBAAsB,CAAC;AAG7E,UAAU,iBAAiB,CAAC,CAAC;IAC3B,MAAM,EAAE,YAAY,CAAC;IACrB,KAAK,CAAC,EAAE,CAAC,CAAC;IACV,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAcD,wBAAgB,qBAAqB,CAAC,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,iBAAiB,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,OAAO,GAAG,IAAI,CAI3G"}
@@ -11,7 +11,7 @@ import { jsx as _jsx } from "react/jsx-runtime";
11
11
  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
12
  // See the License for the specific language governing permissions and
13
13
  // limitations under the License.
14
- /* eslint-disable @typescript-eslint/ban-ts-comment */ // Copyright The Perses Authors
14
+ // Copyright The Perses Authors
15
15
  // Licensed under the Apache License, Version 2.0 (the "License");
16
16
  // you may not use this file except in compliance with the License.
17
17
  // You may obtain a copy of the License at
@@ -23,32 +23,49 @@ import { jsx as _jsx } from "react/jsx-runtime";
23
23
  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
24
24
  // See the License for the specific language governing permissions and
25
25
  // limitations under the License.
26
- import { useEffect, useRef, useState } from "react";
26
+ import { useEffect, useState } from "react";
27
27
  import { usePluginRuntime } from "./PluginRuntime.js";
28
28
  function PluginContainer({ pluginFn, props }) {
29
+ 'use no memo'; // Remote plugin functions may call hooks; their invocation must run on every render.
29
30
  return pluginFn(props);
30
31
  }
31
32
  export function PluginLoaderComponent({ plugin, props, field }) {
33
+ // Reset loading state and plugin hooks together whenever the remote identity changes.
34
+ const key = JSON.stringify([
35
+ plugin.moduleName,
36
+ plugin.name,
37
+ plugin.registry,
38
+ plugin.version,
39
+ plugin.baseURL
40
+ ]);
41
+ return /*#__PURE__*/ _jsx(PluginLoaderSession, {
42
+ plugin: plugin,
43
+ props: props,
44
+ field: field
45
+ }, key);
46
+ }
47
+ function PluginLoaderSession({ plugin, props, field }) {
32
48
  const { loadPlugin } = usePluginRuntime({
33
49
  plugin
34
50
  });
35
51
  const [pluginModule, setPluginModule] = useState(null);
36
52
  const [error, setError] = useState(null);
37
- const name = `${plugin.moduleName}-${plugin.name}`;
38
- const previousPluginName = useRef(name);
39
53
  useEffect(()=>{
40
- previousPluginName.current = name;
41
- setError(null);
54
+ let cancelled = false;
42
55
  loadPlugin().then((module)=>{
43
- setPluginModule(module);
56
+ if (!cancelled) setPluginModule(module);
44
57
  }).catch((error)=>{
45
- setPluginModule(null);
58
+ if (cancelled) return;
46
59
  console.error(`PluginLoaderComponent: Error loading plugin ${plugin.name} from module ${plugin.moduleName}:`, error);
47
60
  setError(new Error(`PluginLoaderComponent: Error loading plugin ${plugin.name} from module ${plugin.moduleName}`));
48
61
  });
49
- // eslint-disable-next-line react-hooks/exhaustive-deps
62
+ return ()=>{
63
+ cancelled = true;
64
+ };
50
65
  }, [
51
- name
66
+ loadPlugin,
67
+ plugin.name,
68
+ plugin.moduleName
52
69
  ]);
53
70
  if (error) {
54
71
  throw error;
@@ -66,14 +83,10 @@ export function PluginLoaderComponent({ plugin, props, field }) {
66
83
  if (typeof pluginFunction !== 'function') {
67
84
  throw new Error(`PluginLoaderComponent: Plugin ${plugin.name} export is not a function`);
68
85
  }
69
- // make sure to re mount the plugin when changes, to avoid mismatch in hooks ordering when re rendering
70
- if (previousPluginName.current !== name) {
71
- return null;
72
- }
73
86
  return /*#__PURE__*/ _jsx(PluginContainer, {
74
87
  pluginFn: pluginFunction,
75
88
  props: props
76
- }, name);
89
+ });
77
90
  }
78
91
 
79
92
  //# sourceMappingURL=PluginLoaderComponent.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/remote/PluginLoaderComponent.tsx"],"sourcesContent":["// Copyright The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \\\"AS IS\\\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n/* eslint-disable @typescript-eslint/ban-ts-comment */\n// Copyright The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport { useEffect, useRef, useState } from 'react';\n\nimport type { PersesPlugin, RemotePluginModule } from './PersesPlugin.types';\nimport { usePluginRuntime } from './PluginRuntime';\n\ninterface PluginLoaderProps<P> {\n plugin: PersesPlugin;\n props?: P;\n field?: string;\n}\n\nfunction PluginContainer<P>({\n pluginFn,\n props,\n}: {\n pluginFn: (props: P | undefined) => JSX.Element;\n props: P | undefined;\n}): JSX.Element {\n return pluginFn(props);\n}\n\nexport function PluginLoaderComponent<P>({ plugin, props, field }: PluginLoaderProps<P>): JSX.Element | null {\n const { loadPlugin } = usePluginRuntime({ plugin });\n const [pluginModule, setPluginModule] = useState<RemotePluginModule | null>(null);\n const [error, setError] = useState<Error | null>(null);\n\n const name = `${plugin.moduleName}-${plugin.name}`;\n const previousPluginName = useRef<string>(name);\n\n useEffect(() => {\n previousPluginName.current = name;\n setError(null);\n\n loadPlugin()\n .then((module) => {\n setPluginModule(module);\n })\n .catch((error) => {\n setPluginModule(null);\n console.error(\n `PluginLoaderComponent: Error loading plugin ${plugin.name} from module ${plugin.moduleName}:`,\n error,\n );\n setError(\n new Error(`PluginLoaderComponent: Error loading plugin ${plugin.name} from module ${plugin.moduleName}`),\n );\n });\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [name]);\n\n if (error) {\n throw error;\n }\n\n if (!pluginModule) {\n return null;\n }\n\n let pluginFunction = pluginModule[plugin.name];\n\n if (field && pluginFunction && typeof pluginFunction === 'object' && field in pluginFunction) {\n pluginFunction = (pluginFunction as Record<string, unknown>)[field];\n }\n\n if (!pluginFunction) {\n throw new Error(`PluginLoaderComponent: Plugin module ${plugin.moduleName} does not have a ${plugin.name} export`);\n }\n\n if (typeof pluginFunction !== 'function') {\n throw new Error(`PluginLoaderComponent: Plugin ${plugin.name} export is not a function`);\n }\n\n // make sure to re mount the plugin when changes, to avoid mismatch in hooks ordering when re rendering\n if (previousPluginName.current !== name) {\n return null;\n }\n\n return (\n <PluginContainer key={name} pluginFn={pluginFunction as (props: P | undefined) => JSX.Element} props={props} />\n );\n}\n"],"names":["useEffect","useRef","useState","usePluginRuntime","PluginContainer","pluginFn","props","PluginLoaderComponent","plugin","field","loadPlugin","pluginModule","setPluginModule","error","setError","name","moduleName","previousPluginName","current","then","module","catch","console","Error","pluginFunction"],"mappings":";AAAA,+BAA+B;AAC/B,oEAAoE;AACpE,mEAAmE;AACnE,0CAA0C;AAC1C,EAAE;AACF,6CAA6C;AAC7C,EAAE;AACF,sEAAsE;AACtE,sEAAsE;AACtE,2EAA2E;AAC3E,sEAAsE;AACtE,iCAAiC;AAEjC,oDAAoD,GACpD,+BAA+B;AAC/B,kEAAkE;AAClE,mEAAmE;AACnE,0CAA0C;AAC1C,EAAE;AACF,6CAA6C;AAC7C,EAAE;AACF,sEAAsE;AACtE,oEAAoE;AACpE,2EAA2E;AAC3E,sEAAsE;AACtE,iCAAiC;AAEjC,SAASA,SAAS,EAAEC,MAAM,EAAEC,QAAQ,QAAQ,QAAQ;AAGpD,SAASC,gBAAgB,QAAQ,qBAAkB;AAQnD,SAASC,gBAAmB,EAC1BC,QAAQ,EACRC,KAAK,EAIN;IACC,OAAOD,SAASC;AAClB;AAEA,OAAO,SAASC,sBAAyB,EAAEC,MAAM,EAAEF,KAAK,EAAEG,KAAK,EAAwB;IACrF,MAAM,EAAEC,UAAU,EAAE,GAAGP,iBAAiB;QAAEK;IAAO;IACjD,MAAM,CAACG,cAAcC,gBAAgB,GAAGV,SAAoC;IAC5E,MAAM,CAACW,OAAOC,SAAS,GAAGZ,SAAuB;IAEjD,MAAMa,OAAO,GAAGP,OAAOQ,UAAU,CAAC,CAAC,EAAER,OAAOO,IAAI,EAAE;IAClD,MAAME,qBAAqBhB,OAAec;IAE1Cf,UAAU;QACRiB,mBAAmBC,OAAO,GAAGH;QAC7BD,SAAS;QAETJ,aACGS,IAAI,CAAC,CAACC;YACLR,gBAAgBQ;QAClB,GACCC,KAAK,CAAC,CAACR;YACND,gBAAgB;YAChBU,QAAQT,KAAK,CACX,CAAC,4CAA4C,EAAEL,OAAOO,IAAI,CAAC,aAAa,EAAEP,OAAOQ,UAAU,CAAC,CAAC,CAAC,EAC9FH;YAEFC,SACE,IAAIS,MAAM,CAAC,4CAA4C,EAAEf,OAAOO,IAAI,CAAC,aAAa,EAAEP,OAAOQ,UAAU,EAAE;QAE3G;IACF,uDAAuD;IACzD,GAAG;QAACD;KAAK;IAET,IAAIF,OAAO;QACT,MAAMA;IACR;IAEA,IAAI,CAACF,cAAc;QACjB,OAAO;IACT;IAEA,IAAIa,iBAAiBb,YAAY,CAACH,OAAOO,IAAI,CAAC;IAE9C,IAAIN,SAASe,kBAAkB,OAAOA,mBAAmB,YAAYf,SAASe,gBAAgB;QAC5FA,iBAAiB,AAACA,cAA0C,CAACf,MAAM;IACrE;IAEA,IAAI,CAACe,gBAAgB;QACnB,MAAM,IAAID,MAAM,CAAC,qCAAqC,EAAEf,OAAOQ,UAAU,CAAC,iBAAiB,EAAER,OAAOO,IAAI,CAAC,OAAO,CAAC;IACnH;IAEA,IAAI,OAAOS,mBAAmB,YAAY;QACxC,MAAM,IAAID,MAAM,CAAC,8BAA8B,EAAEf,OAAOO,IAAI,CAAC,yBAAyB,CAAC;IACzF;IAEA,uGAAuG;IACvG,IAAIE,mBAAmBC,OAAO,KAAKH,MAAM;QACvC,OAAO;IACT;IAEA,qBACE,KAACX;QAA2BC,UAAUmB;QAAyDlB,OAAOA;OAAhFS;AAE1B"}
1
+ {"version":3,"sources":["../../src/remote/PluginLoaderComponent.tsx"],"sourcesContent":["// Copyright The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \\\"AS IS\\\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// Copyright The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport { useEffect, useState } from 'react';\n\nimport type { PersesPlugin, RemotePluginModule } from './PersesPlugin.types';\nimport { usePluginRuntime } from './PluginRuntime';\n\ninterface PluginLoaderProps<P> {\n plugin: PersesPlugin;\n props?: P;\n field?: string;\n}\n\nfunction PluginContainer<P>({\n pluginFn,\n props,\n}: {\n pluginFn: (props: P | undefined) => JSX.Element;\n props: P | undefined;\n}): JSX.Element {\n 'use no memo'; // Remote plugin functions may call hooks; their invocation must run on every render.\n\n return pluginFn(props);\n}\n\nexport function PluginLoaderComponent<P>({ plugin, props, field }: PluginLoaderProps<P>): JSX.Element | null {\n // Reset loading state and plugin hooks together whenever the remote identity changes.\n const key = JSON.stringify([plugin.moduleName, plugin.name, plugin.registry, plugin.version, plugin.baseURL]);\n return <PluginLoaderSession key={key} plugin={plugin} props={props} field={field} />;\n}\n\nfunction PluginLoaderSession<P>({ plugin, props, field }: PluginLoaderProps<P>): JSX.Element | null {\n const { loadPlugin } = usePluginRuntime({ plugin });\n const [pluginModule, setPluginModule] = useState<RemotePluginModule | null>(null);\n const [error, setError] = useState<Error | null>(null);\n\n useEffect(() => {\n let cancelled = false;\n\n loadPlugin()\n .then((module) => {\n if (!cancelled) setPluginModule(module);\n })\n .catch((error) => {\n if (cancelled) return;\n console.error(\n `PluginLoaderComponent: Error loading plugin ${plugin.name} from module ${plugin.moduleName}:`,\n error,\n );\n setError(\n new Error(`PluginLoaderComponent: Error loading plugin ${plugin.name} from module ${plugin.moduleName}`),\n );\n });\n return (): void => {\n cancelled = true;\n };\n }, [loadPlugin, plugin.name, plugin.moduleName]);\n\n if (error) {\n throw error;\n }\n\n if (!pluginModule) {\n return null;\n }\n\n let pluginFunction = pluginModule[plugin.name];\n\n if (field && pluginFunction && typeof pluginFunction === 'object' && field in pluginFunction) {\n pluginFunction = (pluginFunction as Record<string, unknown>)[field];\n }\n\n if (!pluginFunction) {\n throw new Error(`PluginLoaderComponent: Plugin module ${plugin.moduleName} does not have a ${plugin.name} export`);\n }\n\n if (typeof pluginFunction !== 'function') {\n throw new Error(`PluginLoaderComponent: Plugin ${plugin.name} export is not a function`);\n }\n\n return <PluginContainer pluginFn={pluginFunction as (props: P | undefined) => JSX.Element} props={props} />;\n}\n"],"names":["useEffect","useState","usePluginRuntime","PluginContainer","pluginFn","props","PluginLoaderComponent","plugin","field","key","JSON","stringify","moduleName","name","registry","version","baseURL","PluginLoaderSession","loadPlugin","pluginModule","setPluginModule","error","setError","cancelled","then","module","catch","console","Error","pluginFunction"],"mappings":";AAAA,+BAA+B;AAC/B,oEAAoE;AACpE,mEAAmE;AACnE,0CAA0C;AAC1C,EAAE;AACF,6CAA6C;AAC7C,EAAE;AACF,sEAAsE;AACtE,sEAAsE;AACtE,2EAA2E;AAC3E,sEAAsE;AACtE,iCAAiC;AAEjC,+BAA+B;AAC/B,kEAAkE;AAClE,mEAAmE;AACnE,0CAA0C;AAC1C,EAAE;AACF,6CAA6C;AAC7C,EAAE;AACF,sEAAsE;AACtE,oEAAoE;AACpE,2EAA2E;AAC3E,sEAAsE;AACtE,iCAAiC;AAEjC,SAASA,SAAS,EAAEC,QAAQ,QAAQ,QAAQ;AAG5C,SAASC,gBAAgB,QAAQ,qBAAkB;AAQnD,SAASC,gBAAmB,EAC1BC,QAAQ,EACRC,KAAK,EAIN;IACC,eAAe,qFAAqF;IAEpG,OAAOD,SAASC;AAClB;AAEA,OAAO,SAASC,sBAAyB,EAAEC,MAAM,EAAEF,KAAK,EAAEG,KAAK,EAAwB;IACrF,sFAAsF;IACtF,MAAMC,MAAMC,KAAKC,SAAS,CAAC;QAACJ,OAAOK,UAAU;QAAEL,OAAOM,IAAI;QAAEN,OAAOO,QAAQ;QAAEP,OAAOQ,OAAO;QAAER,OAAOS,OAAO;KAAC;IAC5G,qBAAO,KAACC;QAA8BV,QAAQA;QAAQF,OAAOA;QAAOG,OAAOA;OAA1CC;AACnC;AAEA,SAASQ,oBAAuB,EAAEV,MAAM,EAAEF,KAAK,EAAEG,KAAK,EAAwB;IAC5E,MAAM,EAAEU,UAAU,EAAE,GAAGhB,iBAAiB;QAAEK;IAAO;IACjD,MAAM,CAACY,cAAcC,gBAAgB,GAAGnB,SAAoC;IAC5E,MAAM,CAACoB,OAAOC,SAAS,GAAGrB,SAAuB;IAEjDD,UAAU;QACR,IAAIuB,YAAY;QAEhBL,aACGM,IAAI,CAAC,CAACC;YACL,IAAI,CAACF,WAAWH,gBAAgBK;QAClC,GACCC,KAAK,CAAC,CAACL;YACN,IAAIE,WAAW;YACfI,QAAQN,KAAK,CACX,CAAC,4CAA4C,EAAEd,OAAOM,IAAI,CAAC,aAAa,EAAEN,OAAOK,UAAU,CAAC,CAAC,CAAC,EAC9FS;YAEFC,SACE,IAAIM,MAAM,CAAC,4CAA4C,EAAErB,OAAOM,IAAI,CAAC,aAAa,EAAEN,OAAOK,UAAU,EAAE;QAE3G;QACF,OAAO;YACLW,YAAY;QACd;IACF,GAAG;QAACL;QAAYX,OAAOM,IAAI;QAAEN,OAAOK,UAAU;KAAC;IAE/C,IAAIS,OAAO;QACT,MAAMA;IACR;IAEA,IAAI,CAACF,cAAc;QACjB,OAAO;IACT;IAEA,IAAIU,iBAAiBV,YAAY,CAACZ,OAAOM,IAAI,CAAC;IAE9C,IAAIL,SAASqB,kBAAkB,OAAOA,mBAAmB,YAAYrB,SAASqB,gBAAgB;QAC5FA,iBAAiB,AAACA,cAA0C,CAACrB,MAAM;IACrE;IAEA,IAAI,CAACqB,gBAAgB;QACnB,MAAM,IAAID,MAAM,CAAC,qCAAqC,EAAErB,OAAOK,UAAU,CAAC,iBAAiB,EAAEL,OAAOM,IAAI,CAAC,OAAO,CAAC;IACnH;IAEA,IAAI,OAAOgB,mBAAmB,YAAY;QACxC,MAAM,IAAID,MAAM,CAAC,8BAA8B,EAAErB,OAAOM,IAAI,CAAC,yBAAyB,CAAC;IACzF;IAEA,qBAAO,KAACV;QAAgBC,UAAUyB;QAAyDxB,OAAOA;;AACpG"}
@@ -1 +1 @@
1
- {"version":3,"file":"PluginRuntime.d.ts","sourceRoot":"","sources":["../../src/remote/PluginRuntime.tsx"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qCAAqC,CAAC;AAQ5E,OAAO,KAAK,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAa7E,MAAM,WAAW,iBAAiB;IAChC,kBAAkB,EAAE,OAAO,CAAC;IAC5B,oBAAoB,EAAE,OAAO,CAAC;IAC9B,wBAAwB,EAAE,OAAO,CAAC;IAClC,2BAA2B,EAAE,OAAO,CAAC;IACrC,qBAAqB,EAAE,OAAO,CAAC;IAC/B,wBAAwB,EAAE,OAAO,CAAC;CACnC;AAUD,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,iBAAiB,GAAG,IAAI,CAI1E;AA+ND,eAAO,MAAM,UAAU,WAAkB;IACvC,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,KAAG,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAOpC,CAAC;AAEF,wBAAgB,gBAAgB,CAAC,EAAE,MAAM,EAAE,EAAE;IAAE,MAAM,EAAE,YAAY,CAAA;CAAE,GAAG;IACtE,aAAa,EAAE,gBAAgB,CAAC;IAChC,UAAU,EAAE,MAAM,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,CAAC;CACtD,CAQA"}
1
+ {"version":3,"file":"PluginRuntime.d.ts","sourceRoot":"","sources":["../../src/remote/PluginRuntime.tsx"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qCAAqC,CAAC;AAQ5E,OAAO,KAAK,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAa7E,MAAM,WAAW,iBAAiB;IAChC,kBAAkB,EAAE,OAAO,CAAC;IAC5B,oBAAoB,EAAE,OAAO,CAAC;IAC9B,wBAAwB,EAAE,OAAO,CAAC;IAClC,2BAA2B,EAAE,OAAO,CAAC;IACrC,qBAAqB,EAAE,OAAO,CAAC;IAC/B,wBAAwB,EAAE,OAAO,CAAC;CACnC;AAUD,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,iBAAiB,GAAG,IAAI,CAI1E;AAiOD,eAAO,MAAM,UAAU,WAAkB;IACvC,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,KAAG,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAOpC,CAAC;AAEF,wBAAgB,gBAAgB,CAAC,EAAE,MAAM,EAAE,EAAE;IAAE,MAAM,EAAE,YAAY,CAAA;CAAE,GAAG;IACtE,aAAa,EAAE,gBAAgB,CAAC;IAChC,UAAU,EAAE,MAAM,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,CAAC;CACtD,CAWA"}
@@ -14,7 +14,7 @@ import * as EmotionReact from "@emotion/react";
14
14
  import * as EmotionStyled from "@emotion/styled";
15
15
  import { createInstance } from "@module-federation/enhanced/runtime";
16
16
  import * as ReactQuery from "@tanstack/react-query";
17
- import React from "react";
17
+ import React, { useCallback } from "react";
18
18
  import ReactDOM from "react-dom";
19
19
  import * as ReactHookForm from "react-hook-form";
20
20
  import * as ReactRouterDOM from "react-router-dom";
@@ -113,43 +113,43 @@ const getPluginRuntime = ()=>{
113
113
  }
114
114
  },
115
115
  '@perses-dev/client': {
116
- version: '0.55.0-beta.14',
116
+ version: '0.55.0-beta.15',
117
117
  lib: ()=>getHostSharedModule('@perses-dev/client'),
118
118
  shareConfig: {
119
119
  singleton: true,
120
- requiredVersion: '^0.55.0-beta.14'
120
+ requiredVersion: '^0.55.0-beta.15'
121
121
  }
122
122
  },
123
123
  '@perses-dev/components': {
124
- version: '0.55.0-beta.14',
124
+ version: '0.55.0-beta.15',
125
125
  lib: ()=>getHostSharedModule('@perses-dev/components'),
126
126
  shareConfig: {
127
127
  singleton: true,
128
- requiredVersion: '^0.55.0-beta.14'
128
+ requiredVersion: '^0.55.0-beta.15'
129
129
  }
130
130
  },
131
131
  '@perses-dev/plugin-system': {
132
- version: '0.55.0-beta.14',
132
+ version: '0.55.0-beta.15',
133
133
  lib: ()=>getHostSharedModule('@perses-dev/plugin-system'),
134
134
  shareConfig: {
135
135
  singleton: true,
136
- requiredVersion: '^0.55.0-beta.14'
136
+ requiredVersion: '^0.55.0-beta.15'
137
137
  }
138
138
  },
139
139
  '@perses-dev/explore': {
140
- version: '0.55.0-beta.14',
140
+ version: '0.55.0-beta.15',
141
141
  lib: ()=>getHostSharedModule('@perses-dev/explore'),
142
142
  shareConfig: {
143
143
  singleton: true,
144
- requiredVersion: '^0.55.0-beta.14'
144
+ requiredVersion: '^0.55.0-beta.15'
145
145
  }
146
146
  },
147
147
  '@perses-dev/dashboards': {
148
- version: '0.55.0-beta.14',
148
+ version: '0.55.0-beta.15',
149
149
  lib: ()=>getHostSharedModule('@perses-dev/dashboards'),
150
150
  shareConfig: {
151
151
  singleton: true,
152
- requiredVersion: '^0.55.0-beta.14'
152
+ requiredVersion: '^0.55.0-beta.15'
153
153
  }
154
154
  },
155
155
  // Below are the shared modules that are used by the plugins and are loaded asynchronously on demand using get rather than lib.
@@ -204,6 +204,8 @@ const getPluginRuntime = ()=>{
204
204
  },
205
205
  'mdi-material-ui': {
206
206
  version: '7.9.4',
207
+ // Federation must register the package root to satisfy existing plugin shared-module requests.
208
+ // oxlint-disable-next-line no-restricted-imports
207
209
  get: createSharedModuleLoader(()=>import("mdi-material-ui")),
208
210
  shareConfig: {
209
211
  singleton: true,
@@ -257,18 +259,23 @@ export const loadPlugin = async (target)=>{
257
259
  return pluginRuntime.loadRemote(`${registryName}/${pluginName}`);
258
260
  };
259
261
  export function usePluginRuntime({ plugin }) {
262
+ const { moduleName, name: pluginName, registry, version, baseURL } = plugin;
263
+ const load = useCallback(()=>loadPlugin({
264
+ moduleName,
265
+ pluginName,
266
+ registry,
267
+ version,
268
+ baseURL
269
+ }), [
270
+ moduleName,
271
+ pluginName,
272
+ registry,
273
+ version,
274
+ baseURL
275
+ ]);
260
276
  return {
261
277
  pluginRuntime: getPluginRuntime(),
262
- loadPlugin: ()=>{
263
- const { moduleName, name: pluginName, registry, version, baseURL } = plugin;
264
- return loadPlugin({
265
- moduleName,
266
- pluginName,
267
- registry,
268
- version,
269
- baseURL
270
- });
271
- }
278
+ loadPlugin: load
272
279
  };
273
280
  }
274
281
 
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/remote/PluginRuntime.tsx"],"sourcesContent":["// Copyright The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport * as EmotionReact from '@emotion/react';\nimport * as EmotionStyled from '@emotion/styled';\nimport type { ModuleFederation } from '@module-federation/enhanced/runtime';\nimport { createInstance } from '@module-federation/enhanced/runtime';\nimport * as ReactQuery from '@tanstack/react-query';\nimport React from 'react';\nimport ReactDOM from 'react-dom';\nimport * as ReactHookForm from 'react-hook-form';\nimport * as ReactRouterDOM from 'react-router-dom';\n\nimport type { PersesPlugin, RemotePluginModule } from './PersesPlugin.types';\n\nlet instance: ModuleFederation | null = null;\n\nconst DEFAULT_PLUGINS_ASSETS_BASE_URL = '/plugins';\n\nfunction createSharedModuleLoader<TModule>(loadModule: () => Promise<TModule>): () => Promise<() => TModule> {\n return async () => {\n const module = await loadModule();\n return () => module;\n };\n}\n\nexport interface HostSharedModules {\n '@perses-dev/spec': unknown;\n '@perses-dev/client': unknown;\n '@perses-dev/components': unknown;\n '@perses-dev/plugin-system': unknown;\n '@perses-dev/explore': unknown;\n '@perses-dev/dashboards': unknown;\n}\n\ntype HostSharedModuleName = keyof HostSharedModules;\n\nconst hostSharedModules = new Map<HostSharedModuleName, unknown>();\n\n/*\n * Shared singletons must be provided to Module Federation *synchronously* (via `lib`) so the host's\n * copy wins singleton negotiation to avoid loader deadlocks or multiple instances.\n */\nexport function registerHostSharedModules(modules: HostSharedModules): void {\n for (const [name, module] of Object.entries(modules) as Array<[HostSharedModuleName, unknown]>) {\n hostSharedModules.set(name, module);\n }\n}\n\nfunction getHostSharedModule(name: HostSharedModuleName): unknown {\n const module = hostSharedModules.get(name);\n if (!module) {\n throw new Error(\n `Shared module \"${name}\" was not registered before a plugin tried to consume it. ` +\n `Call registerHostSharedModules() during app bootstrap.`,\n );\n }\n return module;\n}\n\nconst getPluginRuntime = (): ModuleFederation => {\n if (instance === null) {\n const pluginRuntime = createInstance({\n name: '@perses/perses-ui-host',\n remotes: [], // all remotes are loaded dynamically\n shared: {\n react: {\n version: React.version,\n lib: () => React,\n shareConfig: {\n singleton: true,\n requiredVersion: `^${React.version}`,\n },\n },\n 'react-dom': {\n version: '18.3.1',\n lib: () => ReactDOM,\n shareConfig: {\n singleton: true,\n requiredVersion: `^18.3.1`,\n },\n },\n 'react-router-dom': {\n version: '6.30.4',\n lib: () => ReactRouterDOM,\n shareConfig: {\n singleton: true,\n requiredVersion: '^6.26.0',\n },\n },\n '@tanstack/react-query': {\n version: '4.44.0',\n lib: () => ReactQuery,\n shareConfig: {\n singleton: true,\n requiredVersion: '^4.39.1',\n },\n },\n 'react-hook-form': {\n version: '7.87.0',\n lib: () => ReactHookForm,\n shareConfig: {\n singleton: true,\n requiredVersion: '^7.87.0',\n },\n },\n '@emotion/react': {\n version: '11.14.0',\n lib: () => EmotionReact,\n shareConfig: {\n singleton: true,\n requiredVersion: '^11.11.3',\n },\n },\n '@emotion/styled': {\n version: '11.14.1',\n lib: () => EmotionStyled,\n shareConfig: {\n singleton: true,\n requiredVersion: '^11.11.0',\n },\n },\n '@perses-dev/spec': {\n version: '0.3.0-beta.10',\n lib: () => getHostSharedModule('@perses-dev/spec'),\n shareConfig: {\n singleton: true,\n requiredVersion: '^0.3.0-beta.10',\n },\n },\n '@perses-dev/client': {\n version: '0.55.0-beta.14',\n lib: () => getHostSharedModule('@perses-dev/client'),\n shareConfig: {\n singleton: true,\n requiredVersion: '^0.55.0-beta.14',\n },\n },\n '@perses-dev/components': {\n version: '0.55.0-beta.14',\n lib: () => getHostSharedModule('@perses-dev/components'),\n shareConfig: {\n singleton: true,\n requiredVersion: '^0.55.0-beta.14',\n },\n },\n '@perses-dev/plugin-system': {\n version: '0.55.0-beta.14',\n lib: () => getHostSharedModule('@perses-dev/plugin-system'),\n shareConfig: {\n singleton: true,\n requiredVersion: '^0.55.0-beta.14',\n },\n },\n '@perses-dev/explore': {\n version: '0.55.0-beta.14',\n lib: () => getHostSharedModule('@perses-dev/explore'),\n shareConfig: {\n singleton: true,\n requiredVersion: '^0.55.0-beta.14',\n },\n },\n '@perses-dev/dashboards': {\n version: '0.55.0-beta.14',\n lib: () => getHostSharedModule('@perses-dev/dashboards'),\n shareConfig: {\n singleton: true,\n requiredVersion: '^0.55.0-beta.14',\n },\n },\n // Below are the shared modules that are used by the plugins and are loaded asynchronously on demand using get rather than lib.\n // This is to avoid loading the modules if they are not used by the plugin.\n echarts: {\n version: '5.5.0',\n get: createSharedModuleLoader(() => import('echarts')),\n shareConfig: {\n singleton: true,\n requiredVersion: '^5.5.0',\n },\n },\n 'date-fns': {\n version: '4.2.1',\n get: createSharedModuleLoader(() => import('date-fns')),\n shareConfig: {\n singleton: true,\n requiredVersion: '^4.1.0',\n },\n },\n 'date-fns-tz': {\n version: '3.2.0',\n get: createSharedModuleLoader(() => import('date-fns-tz')),\n shareConfig: {\n singleton: true,\n requiredVersion: '^3.2.0',\n },\n },\n lodash: {\n version: '4.18.1',\n get: createSharedModuleLoader(() => import('lodash')),\n shareConfig: {\n singleton: true,\n requiredVersion: '^4.17.21',\n },\n },\n '@hookform/resolvers/zod': {\n version: '5.9.1',\n get: createSharedModuleLoader(() => import('@hookform/resolvers/zod')),\n shareConfig: {\n singleton: true,\n requiredVersion: '^5.9.1',\n },\n },\n 'use-resize-observer': {\n version: '9.1.0',\n get: createSharedModuleLoader(() => import('use-resize-observer')),\n shareConfig: {\n singleton: true,\n requiredVersion: '^9.1.0',\n },\n },\n 'mdi-material-ui': {\n version: '7.9.4',\n get: createSharedModuleLoader(() => import('mdi-material-ui')),\n shareConfig: {\n singleton: true,\n requiredVersion: '^7.4.0',\n },\n },\n immer: {\n version: '10.2.0',\n get: createSharedModuleLoader(() => import('immer')),\n shareConfig: {\n singleton: true,\n requiredVersion: '^10.1.1',\n },\n },\n },\n });\n\n instance = pluginRuntime;\n\n return instance;\n }\n return instance;\n};\n\nfunction getModuleFederationRemoteName(name: string, registry?: string, version?: string): string {\n return `${name}:${registry ?? ''}:${version ?? ''}`;\n}\n\nconst registerRemote = (name: string, registry?: string, version?: string, baseURL?: string): void => {\n const pluginRuntime = getPluginRuntime();\n const registryName = getModuleFederationRemoteName(name, registry, version);\n\n const existingRemote = pluginRuntime.options.remotes.find((remote) => remote.name === registryName);\n if (!existingRemote) {\n const nameVersionRegistry = [name, version, registry].filter(Boolean).join('~');\n const prefix = baseURL ?? DEFAULT_PLUGINS_ASSETS_BASE_URL;\n const remoteEntryURL = `${prefix}/${nameVersionRegistry}/mf-manifest.json`;\n\n pluginRuntime.registerRemotes([\n {\n name: registryName,\n entry: remoteEntryURL,\n alias: registryName,\n },\n ]);\n }\n};\n\nexport const loadPlugin = async (target: {\n moduleName: string;\n pluginName: string;\n registry?: string;\n version?: string;\n baseURL?: string;\n}): Promise<RemotePluginModule | null> => {\n const { moduleName, pluginName, registry, version, baseURL } = target;\n registerRemote(moduleName, registry, version, baseURL);\n\n const pluginRuntime = getPluginRuntime();\n const registryName = getModuleFederationRemoteName(moduleName, registry, version);\n return pluginRuntime.loadRemote<RemotePluginModule>(`${registryName}/${pluginName}`);\n};\n\nexport function usePluginRuntime({ plugin }: { plugin: PersesPlugin }): {\n pluginRuntime: ModuleFederation;\n loadPlugin: () => Promise<RemotePluginModule | null>;\n} {\n return {\n pluginRuntime: getPluginRuntime(),\n loadPlugin: (): Promise<RemotePluginModule | null> => {\n const { moduleName, name: pluginName, registry, version, baseURL } = plugin;\n return loadPlugin({ moduleName, pluginName, registry, version, baseURL });\n },\n };\n}\n"],"names":["EmotionReact","EmotionStyled","createInstance","ReactQuery","React","ReactDOM","ReactHookForm","ReactRouterDOM","instance","DEFAULT_PLUGINS_ASSETS_BASE_URL","createSharedModuleLoader","loadModule","module","hostSharedModules","Map","registerHostSharedModules","modules","name","Object","entries","set","getHostSharedModule","get","Error","getPluginRuntime","pluginRuntime","remotes","shared","react","version","lib","shareConfig","singleton","requiredVersion","echarts","lodash","immer","getModuleFederationRemoteName","registry","registerRemote","baseURL","registryName","existingRemote","options","find","remote","nameVersionRegistry","filter","Boolean","join","prefix","remoteEntryURL","registerRemotes","entry","alias","loadPlugin","target","moduleName","pluginName","loadRemote","usePluginRuntime","plugin"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/remote/PluginRuntime.tsx"],"sourcesContent":["// Copyright The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport * as EmotionReact from '@emotion/react';\nimport * as EmotionStyled from '@emotion/styled';\nimport type { ModuleFederation } from '@module-federation/enhanced/runtime';\nimport { createInstance } from '@module-federation/enhanced/runtime';\nimport * as ReactQuery from '@tanstack/react-query';\nimport React, { useCallback } from 'react';\nimport ReactDOM from 'react-dom';\nimport * as ReactHookForm from 'react-hook-form';\nimport * as ReactRouterDOM from 'react-router-dom';\n\nimport type { PersesPlugin, RemotePluginModule } from './PersesPlugin.types';\n\nlet instance: ModuleFederation | null = null;\n\nconst DEFAULT_PLUGINS_ASSETS_BASE_URL = '/plugins';\n\nfunction createSharedModuleLoader<TModule>(loadModule: () => Promise<TModule>): () => Promise<() => TModule> {\n return async () => {\n const module = await loadModule();\n return () => module;\n };\n}\n\nexport interface HostSharedModules {\n '@perses-dev/spec': unknown;\n '@perses-dev/client': unknown;\n '@perses-dev/components': unknown;\n '@perses-dev/plugin-system': unknown;\n '@perses-dev/explore': unknown;\n '@perses-dev/dashboards': unknown;\n}\n\ntype HostSharedModuleName = keyof HostSharedModules;\n\nconst hostSharedModules = new Map<HostSharedModuleName, unknown>();\n\n/*\n * Shared singletons must be provided to Module Federation *synchronously* (via `lib`) so the host's\n * copy wins singleton negotiation to avoid loader deadlocks or multiple instances.\n */\nexport function registerHostSharedModules(modules: HostSharedModules): void {\n for (const [name, module] of Object.entries(modules) as Array<[HostSharedModuleName, unknown]>) {\n hostSharedModules.set(name, module);\n }\n}\n\nfunction getHostSharedModule(name: HostSharedModuleName): unknown {\n const module = hostSharedModules.get(name);\n if (!module) {\n throw new Error(\n `Shared module \"${name}\" was not registered before a plugin tried to consume it. ` +\n `Call registerHostSharedModules() during app bootstrap.`,\n );\n }\n return module;\n}\n\nconst getPluginRuntime = (): ModuleFederation => {\n if (instance === null) {\n const pluginRuntime = createInstance({\n name: '@perses/perses-ui-host',\n remotes: [], // all remotes are loaded dynamically\n shared: {\n react: {\n version: React.version,\n lib: () => React,\n shareConfig: {\n singleton: true,\n requiredVersion: `^${React.version}`,\n },\n },\n 'react-dom': {\n version: '18.3.1',\n lib: () => ReactDOM,\n shareConfig: {\n singleton: true,\n requiredVersion: `^18.3.1`,\n },\n },\n 'react-router-dom': {\n version: '6.30.4',\n lib: () => ReactRouterDOM,\n shareConfig: {\n singleton: true,\n requiredVersion: '^6.26.0',\n },\n },\n '@tanstack/react-query': {\n version: '4.44.0',\n lib: () => ReactQuery,\n shareConfig: {\n singleton: true,\n requiredVersion: '^4.39.1',\n },\n },\n 'react-hook-form': {\n version: '7.87.0',\n lib: () => ReactHookForm,\n shareConfig: {\n singleton: true,\n requiredVersion: '^7.87.0',\n },\n },\n '@emotion/react': {\n version: '11.14.0',\n lib: () => EmotionReact,\n shareConfig: {\n singleton: true,\n requiredVersion: '^11.11.3',\n },\n },\n '@emotion/styled': {\n version: '11.14.1',\n lib: () => EmotionStyled,\n shareConfig: {\n singleton: true,\n requiredVersion: '^11.11.0',\n },\n },\n '@perses-dev/spec': {\n version: '0.3.0-beta.10',\n lib: () => getHostSharedModule('@perses-dev/spec'),\n shareConfig: {\n singleton: true,\n requiredVersion: '^0.3.0-beta.10',\n },\n },\n '@perses-dev/client': {\n version: '0.55.0-beta.15',\n lib: () => getHostSharedModule('@perses-dev/client'),\n shareConfig: {\n singleton: true,\n requiredVersion: '^0.55.0-beta.15',\n },\n },\n '@perses-dev/components': {\n version: '0.55.0-beta.15',\n lib: () => getHostSharedModule('@perses-dev/components'),\n shareConfig: {\n singleton: true,\n requiredVersion: '^0.55.0-beta.15',\n },\n },\n '@perses-dev/plugin-system': {\n version: '0.55.0-beta.15',\n lib: () => getHostSharedModule('@perses-dev/plugin-system'),\n shareConfig: {\n singleton: true,\n requiredVersion: '^0.55.0-beta.15',\n },\n },\n '@perses-dev/explore': {\n version: '0.55.0-beta.15',\n lib: () => getHostSharedModule('@perses-dev/explore'),\n shareConfig: {\n singleton: true,\n requiredVersion: '^0.55.0-beta.15',\n },\n },\n '@perses-dev/dashboards': {\n version: '0.55.0-beta.15',\n lib: () => getHostSharedModule('@perses-dev/dashboards'),\n shareConfig: {\n singleton: true,\n requiredVersion: '^0.55.0-beta.15',\n },\n },\n // Below are the shared modules that are used by the plugins and are loaded asynchronously on demand using get rather than lib.\n // This is to avoid loading the modules if they are not used by the plugin.\n echarts: {\n version: '5.5.0',\n get: createSharedModuleLoader(() => import('echarts')),\n shareConfig: {\n singleton: true,\n requiredVersion: '^5.5.0',\n },\n },\n 'date-fns': {\n version: '4.2.1',\n get: createSharedModuleLoader(() => import('date-fns')),\n shareConfig: {\n singleton: true,\n requiredVersion: '^4.1.0',\n },\n },\n 'date-fns-tz': {\n version: '3.2.0',\n get: createSharedModuleLoader(() => import('date-fns-tz')),\n shareConfig: {\n singleton: true,\n requiredVersion: '^3.2.0',\n },\n },\n lodash: {\n version: '4.18.1',\n get: createSharedModuleLoader(() => import('lodash')),\n shareConfig: {\n singleton: true,\n requiredVersion: '^4.17.21',\n },\n },\n '@hookform/resolvers/zod': {\n version: '5.9.1',\n get: createSharedModuleLoader(() => import('@hookform/resolvers/zod')),\n shareConfig: {\n singleton: true,\n requiredVersion: '^5.9.1',\n },\n },\n 'use-resize-observer': {\n version: '9.1.0',\n get: createSharedModuleLoader(() => import('use-resize-observer')),\n shareConfig: {\n singleton: true,\n requiredVersion: '^9.1.0',\n },\n },\n 'mdi-material-ui': {\n version: '7.9.4',\n // Federation must register the package root to satisfy existing plugin shared-module requests.\n // oxlint-disable-next-line no-restricted-imports\n get: createSharedModuleLoader(() => import('mdi-material-ui')),\n shareConfig: {\n singleton: true,\n requiredVersion: '^7.4.0',\n },\n },\n immer: {\n version: '10.2.0',\n get: createSharedModuleLoader(() => import('immer')),\n shareConfig: {\n singleton: true,\n requiredVersion: '^10.1.1',\n },\n },\n },\n });\n\n instance = pluginRuntime;\n\n return instance;\n }\n return instance;\n};\n\nfunction getModuleFederationRemoteName(name: string, registry?: string, version?: string): string {\n return `${name}:${registry ?? ''}:${version ?? ''}`;\n}\n\nconst registerRemote = (name: string, registry?: string, version?: string, baseURL?: string): void => {\n const pluginRuntime = getPluginRuntime();\n const registryName = getModuleFederationRemoteName(name, registry, version);\n\n const existingRemote = pluginRuntime.options.remotes.find((remote) => remote.name === registryName);\n if (!existingRemote) {\n const nameVersionRegistry = [name, version, registry].filter(Boolean).join('~');\n const prefix = baseURL ?? DEFAULT_PLUGINS_ASSETS_BASE_URL;\n const remoteEntryURL = `${prefix}/${nameVersionRegistry}/mf-manifest.json`;\n\n pluginRuntime.registerRemotes([\n {\n name: registryName,\n entry: remoteEntryURL,\n alias: registryName,\n },\n ]);\n }\n};\n\nexport const loadPlugin = async (target: {\n moduleName: string;\n pluginName: string;\n registry?: string;\n version?: string;\n baseURL?: string;\n}): Promise<RemotePluginModule | null> => {\n const { moduleName, pluginName, registry, version, baseURL } = target;\n registerRemote(moduleName, registry, version, baseURL);\n\n const pluginRuntime = getPluginRuntime();\n const registryName = getModuleFederationRemoteName(moduleName, registry, version);\n return pluginRuntime.loadRemote<RemotePluginModule>(`${registryName}/${pluginName}`);\n};\n\nexport function usePluginRuntime({ plugin }: { plugin: PersesPlugin }): {\n pluginRuntime: ModuleFederation;\n loadPlugin: () => Promise<RemotePluginModule | null>;\n} {\n const { moduleName, name: pluginName, registry, version, baseURL } = plugin;\n const load = useCallback(\n () => loadPlugin({ moduleName, pluginName, registry, version, baseURL }),\n [moduleName, pluginName, registry, version, baseURL],\n );\n\n return {\n pluginRuntime: getPluginRuntime(),\n loadPlugin: load,\n };\n}\n"],"names":["EmotionReact","EmotionStyled","createInstance","ReactQuery","React","useCallback","ReactDOM","ReactHookForm","ReactRouterDOM","instance","DEFAULT_PLUGINS_ASSETS_BASE_URL","createSharedModuleLoader","loadModule","module","hostSharedModules","Map","registerHostSharedModules","modules","name","Object","entries","set","getHostSharedModule","get","Error","getPluginRuntime","pluginRuntime","remotes","shared","react","version","lib","shareConfig","singleton","requiredVersion","echarts","lodash","immer","getModuleFederationRemoteName","registry","registerRemote","baseURL","registryName","existingRemote","options","find","remote","nameVersionRegistry","filter","Boolean","join","prefix","remoteEntryURL","registerRemotes","entry","alias","loadPlugin","target","moduleName","pluginName","loadRemote","usePluginRuntime","plugin","load"],"mappings":"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"}
@@ -12,7 +12,7 @@
12
12
  // limitations under the License.
13
13
  import { isRelativeTimeRange, isDurationString } from "@perses-dev/spec";
14
14
  import { getUnixTime, isDate } from "date-fns";
15
- import { useMemo, useCallback, useEffect, useState } from "react";
15
+ import { useMemo, useCallback, useEffect, useRef } from "react";
16
16
  import { useQueryParams, StringParam } from "use-query-params";
17
17
  /* Interprets an encoded string and returns either the string or null/undefined if not available */ function getEncodedValue(input, allowEmptyString) {
18
18
  // '' or []
@@ -106,22 +106,21 @@ export const timeZoneQueryConfig = {
106
106
  updateType: 'replaceIn'
107
107
  });
108
108
  // determine whether initial param had previously been populated to fix back btn
109
- const [paramsLoaded, setParamsLoaded] = useState(false);
109
+ const paramsLoaded = useRef(false);
110
110
  const { start } = query;
111
111
  useEffect(()=>{
112
112
  // when dashboard loaded with no params, default to dashboard duration
113
- if (!paramsLoaded && !start) {
113
+ if (!paramsLoaded.current && !start) {
114
114
  if (isRelativeTimeRange(initialTimeRange)) {
115
115
  setQuery({
116
116
  start: initialTimeRange.pastDuration,
117
117
  end: undefined
118
118
  });
119
- setParamsLoaded(true);
119
+ paramsLoaded.current = true;
120
120
  }
121
121
  }
122
122
  }, [
123
123
  initialTimeRange,
124
- paramsLoaded,
125
124
  start,
126
125
  setQuery
127
126
  ]);
@@ -172,19 +171,18 @@ export const timeZoneQueryConfig = {
172
171
  updateType: 'replaceIn'
173
172
  });
174
173
  // determine whether initial param had previously been populated to fix back btn
175
- const [paramsLoaded, setParamsLoaded] = useState(false);
174
+ const paramsLoaded = useRef(false);
176
175
  const { refresh } = query;
177
176
  useEffect(()=>{
178
177
  // when dashboard loaded with no params, default to dashboard refresh interval
179
- if (!paramsLoaded && !refresh) {
178
+ if (!paramsLoaded.current && !refresh) {
180
179
  setQuery({
181
180
  refresh: initialRefreshInterval
182
181
  });
183
- setParamsLoaded(true);
182
+ paramsLoaded.current = true;
184
183
  }
185
184
  }, [
186
185
  initialRefreshInterval,
187
- paramsLoaded,
188
186
  refresh,
189
187
  setQuery
190
188
  ]);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/runtime/TimeRangeProvider/query-params.ts"],"sourcesContent":["// Copyright The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport type { TimeRangeValue, DurationString, AbsoluteTimeRange } from '@perses-dev/spec';\nimport { isRelativeTimeRange, isDurationString } from '@perses-dev/spec';\nimport { getUnixTime, isDate } from 'date-fns';\nimport { useMemo, useCallback, useEffect, useState } from 'react';\nimport type { QueryParamConfig } from 'use-query-params';\nimport { useQueryParams, StringParam } from 'use-query-params';\n\nimport type { TimeRange } from './TimeRangeProvider';\n\nexport type TimeOptionValue = Date | DurationString | null | undefined;\n\n/* Interprets an encoded string and returns either the string or null/undefined if not available */\nfunction getEncodedValue(\n input: string | Array<string | null> | null | undefined,\n allowEmptyString?: boolean,\n): string | null | undefined {\n // '' or []\n if (!input || (input.length === 0 && (!allowEmptyString || (allowEmptyString && input !== '')))) {\n return null;\n }\n\n const str = input instanceof Array ? input[0] : input;\n if (str === null || str === undefined) {\n return str;\n }\n if (!allowEmptyString && str === '') {\n return null;\n }\n\n return str;\n}\n\n/* Encodes individual TimeRangeValue as a string, depends on whether start is relative or absolute */\nexport function encodeTimeRangeValue(timeOptionValue: TimeOptionValue): string | null | undefined {\n if (!timeOptionValue) {\n return timeOptionValue;\n }\n\n if (typeof timeOptionValue === 'string') {\n if (isDurationString(timeOptionValue)) {\n return timeOptionValue;\n }\n }\n return (getUnixTime(timeOptionValue) * 1000).toString();\n}\n\n/* Converts param input to supported relative or absolute time range format */\nexport function decodeTimeRangeValue(\n input: string | Array<string | null> | null | undefined,\n): Date | DurationString | null | undefined {\n const paramString = getEncodedValue(input);\n if (!paramString) return null;\n return isDurationString(paramString) ? paramString : new Date(Number(paramString));\n}\n\n/**\n * Custom TimeRangeValue param type\n * See: https://github.com/pbeshai/use-query-params/tree/master/packages/serialize-query-params#param-types\n */\nexport const TimeRangeParam: QueryParamConfig<TimeOptionValue, TimeOptionValue> = {\n encode: encodeTimeRangeValue,\n decode: decodeTimeRangeValue,\n equals: (valueA: TimeOptionValue, valueB: TimeOptionValue) => {\n if (valueA === valueB) return true;\n if (!valueA || !valueB) return valueA === valueB;\n return valueA.valueOf() === valueB.valueOf();\n },\n};\n\nexport const timeRangeQueryConfig = {\n start: TimeRangeParam,\n end: TimeRangeParam,\n};\n\nexport const refreshIntervalQueryConfig = {\n refresh: TimeRangeParam,\n};\n\nexport const timeZoneQueryConfig = {\n tz: StringParam,\n};\n\n/**\n * Gets the initial time range taking into account URL params and dashboard JSON duration\n * Sets start query param if it is empty on page load\n */\nexport function useInitialTimeRange(dashboardDuration: DurationString): TimeRangeValue {\n const [query] = useQueryParams(timeRangeQueryConfig, { updateType: 'replaceIn' });\n const { start, end } = query;\n\n return useMemo(() => {\n let initialTimeRange: TimeRangeValue = { pastDuration: dashboardDuration };\n if (!start) {\n return initialTimeRange;\n }\n const startStr = start.toString();\n if (isDurationString(startStr)) {\n initialTimeRange = { pastDuration: startStr };\n } else if (isDate(start) && isDate(end)) {\n initialTimeRange = { start: start, end: end } as AbsoluteTimeRange;\n }\n return initialTimeRange;\n }, [start, end, dashboardDuration]);\n}\n\n/**\n * Returns time range getter and setter, taking the URL query params.\n */\nexport function useTimeRangeParams(initialTimeRange: TimeRangeValue): Pick<TimeRange, 'timeRange' | 'setTimeRange'> {\n const [query, setQuery] = useQueryParams(timeRangeQueryConfig, { updateType: 'replaceIn' });\n // determine whether initial param had previously been populated to fix back btn\n const [paramsLoaded, setParamsLoaded] = useState<boolean>(false);\n\n const { start } = query;\n\n useEffect(() => {\n // when dashboard loaded with no params, default to dashboard duration\n if (!paramsLoaded && !start) {\n if (isRelativeTimeRange(initialTimeRange)) {\n setQuery({ start: initialTimeRange.pastDuration, end: undefined });\n setParamsLoaded(true);\n }\n }\n }, [initialTimeRange, paramsLoaded, start, setQuery]);\n\n const setTimeRange: TimeRange['setTimeRange'] = useCallback(\n (value: TimeRangeValue) => {\n if (isRelativeTimeRange(value)) {\n setQuery({ start: value.pastDuration, end: undefined });\n } else {\n setQuery(value);\n }\n },\n [setQuery],\n );\n\n return { timeRange: initialTimeRange, setTimeRange: setTimeRange };\n}\n\n/**\n * Gets the initial refresh interval taking into account URL params and dashboard JSON duration\n * Sets refresh query param if it is empty on page load\n */\nexport function useInitialRefreshInterval(dashboardDuration: DurationString): DurationString {\n const [query] = useQueryParams(refreshIntervalQueryConfig, { updateType: 'replaceIn' });\n const { refresh } = query;\n return useMemo(() => {\n let initialTimeRange: DurationString = dashboardDuration;\n if (!refresh) {\n return initialTimeRange;\n }\n const startStr = refresh.toString();\n if (isDurationString(startStr)) {\n initialTimeRange = startStr;\n }\n return initialTimeRange;\n }, [dashboardDuration, refresh]);\n}\n\n/**\n * Returns refresh interval getter and setter, taking the URL query params.\n */\nexport function useSetRefreshIntervalParams(\n initialRefreshInterval?: DurationString,\n): Pick<TimeRange, 'refreshInterval' | 'setRefreshInterval'> {\n const [query, setQuery] = useQueryParams(refreshIntervalQueryConfig, { updateType: 'replaceIn' });\n\n // determine whether initial param had previously been populated to fix back btn\n const [paramsLoaded, setParamsLoaded] = useState<boolean>(false);\n\n const { refresh } = query;\n\n useEffect(() => {\n // when dashboard loaded with no params, default to dashboard refresh interval\n if (!paramsLoaded && !refresh) {\n setQuery({ refresh: initialRefreshInterval });\n setParamsLoaded(true);\n }\n }, [initialRefreshInterval, paramsLoaded, refresh, setQuery]);\n\n const setRefreshInterval: TimeRange['setRefreshInterval'] = useCallback(\n (refresh: DurationString) => setQuery({ refresh }),\n [setQuery],\n );\n\n return {\n refreshInterval: initialRefreshInterval,\n setRefreshInterval: setRefreshInterval,\n };\n}\n\n/**\n * Returns timezone getter and setter, taking the URL query params.\n * Defaults to 'local' when not set.\n */\nexport function useTimeZoneParams(initialTimeZone?: string): { timeZone: string; setTimeZone: (tz: string) => void } {\n const [query, setQuery] = useQueryParams(timeZoneQueryConfig, { updateType: 'replaceIn' });\n const { tz } = query;\n\n const timeZone = (tz as string | undefined) ?? initialTimeZone ?? 'local';\n\n const setTimeZone = useCallback(\n (newTz: string) => {\n setQuery({ tz: newTz });\n },\n [setQuery],\n );\n\n return { timeZone, setTimeZone };\n}\n"],"names":["isRelativeTimeRange","isDurationString","getUnixTime","isDate","useMemo","useCallback","useEffect","useState","useQueryParams","StringParam","getEncodedValue","input","allowEmptyString","length","str","Array","undefined","encodeTimeRangeValue","timeOptionValue","toString","decodeTimeRangeValue","paramString","Date","Number","TimeRangeParam","encode","decode","equals","valueA","valueB","valueOf","timeRangeQueryConfig","start","end","refreshIntervalQueryConfig","refresh","timeZoneQueryConfig","tz","useInitialTimeRange","dashboardDuration","query","updateType","initialTimeRange","pastDuration","startStr","useTimeRangeParams","setQuery","paramsLoaded","setParamsLoaded","setTimeRange","value","timeRange","useInitialRefreshInterval","useSetRefreshIntervalParams","initialRefreshInterval","setRefreshInterval","refreshInterval","useTimeZoneParams","initialTimeZone","timeZone","setTimeZone","newTz"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/runtime/TimeRangeProvider/query-params.ts"],"sourcesContent":["// Copyright The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport type { TimeRangeValue, DurationString, AbsoluteTimeRange } from '@perses-dev/spec';\nimport { isRelativeTimeRange, isDurationString } from '@perses-dev/spec';\nimport { getUnixTime, isDate } from 'date-fns';\nimport { useMemo, useCallback, useEffect, useRef } from 'react';\nimport type { QueryParamConfig } from 'use-query-params';\nimport { useQueryParams, StringParam } from 'use-query-params';\n\nimport type { TimeRange } from './TimeRangeProvider';\n\nexport type TimeOptionValue = Date | DurationString | null | undefined;\n\n/* Interprets an encoded string and returns either the string or null/undefined if not available */\nfunction getEncodedValue(\n input: string | Array<string | null> | null | undefined,\n allowEmptyString?: boolean,\n): string | null | undefined {\n // '' or []\n if (!input || (input.length === 0 && (!allowEmptyString || (allowEmptyString && input !== '')))) {\n return null;\n }\n\n const str = input instanceof Array ? input[0] : input;\n if (str === null || str === undefined) {\n return str;\n }\n if (!allowEmptyString && str === '') {\n return null;\n }\n\n return str;\n}\n\n/* Encodes individual TimeRangeValue as a string, depends on whether start is relative or absolute */\nexport function encodeTimeRangeValue(timeOptionValue: TimeOptionValue): string | null | undefined {\n if (!timeOptionValue) {\n return timeOptionValue;\n }\n\n if (typeof timeOptionValue === 'string') {\n if (isDurationString(timeOptionValue)) {\n return timeOptionValue;\n }\n }\n return (getUnixTime(timeOptionValue) * 1000).toString();\n}\n\n/* Converts param input to supported relative or absolute time range format */\nexport function decodeTimeRangeValue(\n input: string | Array<string | null> | null | undefined,\n): Date | DurationString | null | undefined {\n const paramString = getEncodedValue(input);\n if (!paramString) return null;\n return isDurationString(paramString) ? paramString : new Date(Number(paramString));\n}\n\n/**\n * Custom TimeRangeValue param type\n * See: https://github.com/pbeshai/use-query-params/tree/master/packages/serialize-query-params#param-types\n */\nexport const TimeRangeParam: QueryParamConfig<TimeOptionValue, TimeOptionValue> = {\n encode: encodeTimeRangeValue,\n decode: decodeTimeRangeValue,\n equals: (valueA: TimeOptionValue, valueB: TimeOptionValue) => {\n if (valueA === valueB) return true;\n if (!valueA || !valueB) return valueA === valueB;\n return valueA.valueOf() === valueB.valueOf();\n },\n};\n\nexport const timeRangeQueryConfig = {\n start: TimeRangeParam,\n end: TimeRangeParam,\n};\n\nexport const refreshIntervalQueryConfig = {\n refresh: TimeRangeParam,\n};\n\nexport const timeZoneQueryConfig = {\n tz: StringParam,\n};\n\n/**\n * Gets the initial time range taking into account URL params and dashboard JSON duration\n * Sets start query param if it is empty on page load\n */\nexport function useInitialTimeRange(dashboardDuration: DurationString): TimeRangeValue {\n const [query] = useQueryParams(timeRangeQueryConfig, { updateType: 'replaceIn' });\n const { start, end } = query;\n\n return useMemo(() => {\n let initialTimeRange: TimeRangeValue = { pastDuration: dashboardDuration };\n if (!start) {\n return initialTimeRange;\n }\n const startStr = start.toString();\n if (isDurationString(startStr)) {\n initialTimeRange = { pastDuration: startStr };\n } else if (isDate(start) && isDate(end)) {\n initialTimeRange = { start: start, end: end } as AbsoluteTimeRange;\n }\n return initialTimeRange;\n }, [start, end, dashboardDuration]);\n}\n\n/**\n * Returns time range getter and setter, taking the URL query params.\n */\nexport function useTimeRangeParams(initialTimeRange: TimeRangeValue): Pick<TimeRange, 'timeRange' | 'setTimeRange'> {\n const [query, setQuery] = useQueryParams(timeRangeQueryConfig, { updateType: 'replaceIn' });\n // determine whether initial param had previously been populated to fix back btn\n const paramsLoaded = useRef(false);\n\n const { start } = query;\n\n useEffect(() => {\n // when dashboard loaded with no params, default to dashboard duration\n if (!paramsLoaded.current && !start) {\n if (isRelativeTimeRange(initialTimeRange)) {\n setQuery({ start: initialTimeRange.pastDuration, end: undefined });\n paramsLoaded.current = true;\n }\n }\n }, [initialTimeRange, start, setQuery]);\n\n const setTimeRange: TimeRange['setTimeRange'] = useCallback(\n (value: TimeRangeValue) => {\n if (isRelativeTimeRange(value)) {\n setQuery({ start: value.pastDuration, end: undefined });\n } else {\n setQuery(value);\n }\n },\n [setQuery],\n );\n\n return { timeRange: initialTimeRange, setTimeRange: setTimeRange };\n}\n\n/**\n * Gets the initial refresh interval taking into account URL params and dashboard JSON duration\n * Sets refresh query param if it is empty on page load\n */\nexport function useInitialRefreshInterval(dashboardDuration: DurationString): DurationString {\n const [query] = useQueryParams(refreshIntervalQueryConfig, { updateType: 'replaceIn' });\n const { refresh } = query;\n return useMemo(() => {\n let initialTimeRange: DurationString = dashboardDuration;\n if (!refresh) {\n return initialTimeRange;\n }\n const startStr = refresh.toString();\n if (isDurationString(startStr)) {\n initialTimeRange = startStr;\n }\n return initialTimeRange;\n }, [dashboardDuration, refresh]);\n}\n\n/**\n * Returns refresh interval getter and setter, taking the URL query params.\n */\nexport function useSetRefreshIntervalParams(\n initialRefreshInterval?: DurationString,\n): Pick<TimeRange, 'refreshInterval' | 'setRefreshInterval'> {\n const [query, setQuery] = useQueryParams(refreshIntervalQueryConfig, { updateType: 'replaceIn' });\n\n // determine whether initial param had previously been populated to fix back btn\n const paramsLoaded = useRef(false);\n\n const { refresh } = query;\n\n useEffect(() => {\n // when dashboard loaded with no params, default to dashboard refresh interval\n if (!paramsLoaded.current && !refresh) {\n setQuery({ refresh: initialRefreshInterval });\n paramsLoaded.current = true;\n }\n }, [initialRefreshInterval, refresh, setQuery]);\n\n const setRefreshInterval: TimeRange['setRefreshInterval'] = useCallback(\n (refresh: DurationString) => setQuery({ refresh }),\n [setQuery],\n );\n\n return {\n refreshInterval: initialRefreshInterval,\n setRefreshInterval: setRefreshInterval,\n };\n}\n\n/**\n * Returns timezone getter and setter, taking the URL query params.\n * Defaults to 'local' when not set.\n */\nexport function useTimeZoneParams(initialTimeZone?: string): { timeZone: string; setTimeZone: (tz: string) => void } {\n const [query, setQuery] = useQueryParams(timeZoneQueryConfig, { updateType: 'replaceIn' });\n const { tz } = query;\n\n const timeZone = (tz as string | undefined) ?? initialTimeZone ?? 'local';\n\n const setTimeZone = useCallback(\n (newTz: string) => {\n setQuery({ tz: newTz });\n },\n [setQuery],\n );\n\n return { timeZone, setTimeZone };\n}\n"],"names":["isRelativeTimeRange","isDurationString","getUnixTime","isDate","useMemo","useCallback","useEffect","useRef","useQueryParams","StringParam","getEncodedValue","input","allowEmptyString","length","str","Array","undefined","encodeTimeRangeValue","timeOptionValue","toString","decodeTimeRangeValue","paramString","Date","Number","TimeRangeParam","encode","decode","equals","valueA","valueB","valueOf","timeRangeQueryConfig","start","end","refreshIntervalQueryConfig","refresh","timeZoneQueryConfig","tz","useInitialTimeRange","dashboardDuration","query","updateType","initialTimeRange","pastDuration","startStr","useTimeRangeParams","setQuery","paramsLoaded","current","setTimeRange","value","timeRange","useInitialRefreshInterval","useSetRefreshIntervalParams","initialRefreshInterval","setRefreshInterval","refreshInterval","useTimeZoneParams","initialTimeZone","timeZone","setTimeZone","newTz"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"UsageMetricsProvider.d.ts","sourceRoot":"","sources":["../../src/runtime/UsageMetricsProvider.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAElD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACxD,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAGrD,KAAK,UAAU,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,CAAC;AAElD,UAAU,YAAY;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,MAAM,CAAC;IACxB,gBAAgB,EAAE,MAAM,CAAC;IACzB,gBAAgB,EAAE,MAAM,CAAC;IACzB,cAAc,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IACxC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,UAAU,iBAAiB;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED,UAAU,sBAAsB;IAC9B,SAAS,EAAE,CAAC,UAAU,EAAE,eAAe,EAAE,KAAK,EAAE,UAAU,KAAK,IAAI,CAAC;CACrE;AAED,eAAO,MAAM,mBAAmB,mDAAqD,CAAC;AAEtF,eAAO,MAAM,sBAAsB,QAAO,YAAY,GAAG,SAExD,CAAC;AAEF,eAAO,MAAM,eAAe,QAAO,sBA6BlC,CAAC;AAiBF,eAAO,MAAM,oBAAoB,gDAAiD,iBAAiB,KAAG,YAerG,CAAC"}
1
+ {"version":3,"file":"UsageMetricsProvider.d.ts","sourceRoot":"","sources":["../../src/runtime/UsageMetricsProvider.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAElD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACxD,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAGrD,KAAK,UAAU,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,CAAC;AAElD,UAAU,YAAY;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,MAAM,CAAC;IACxB,gBAAgB,EAAE,MAAM,CAAC;IACzB,gBAAgB,EAAE,MAAM,CAAC;IACzB,cAAc,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IACxC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,UAAU,iBAAiB;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED,UAAU,sBAAsB;IAC9B,SAAS,EAAE,CAAC,UAAU,EAAE,eAAe,EAAE,KAAK,EAAE,UAAU,KAAK,IAAI,CAAC;CACrE;AAED,eAAO,MAAM,mBAAmB,mDAAqD,CAAC;AAEtF,eAAO,MAAM,sBAAsB,QAAO,YAAY,GAAG,SAExD,CAAC;AAEF,eAAO,MAAM,eAAe,QAAO,sBAWlC,CAAC;AAsCF,eAAO,MAAM,oBAAoB,gDAAiD,iBAAiB,KAAG,YAgBrG,CAAC"}