@perses-dev/plugin-system 0.55.0-beta.9 → 0.55.0-rc.0

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 (130) 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/HTTPProxyTimeoutEditor.d.ts +11 -0
  12. package/dist/components/HTTPSettingsEditor/HTTPProxyTimeoutEditor.d.ts.map +1 -0
  13. package/dist/components/HTTPSettingsEditor/HTTPProxyTimeoutEditor.js +58 -0
  14. package/dist/components/HTTPSettingsEditor/HTTPProxyTimeoutEditor.js.map +1 -0
  15. package/dist/components/HTTPSettingsEditor/HTTPSettingsEditor.d.ts +1 -1
  16. package/dist/components/HTTPSettingsEditor/HTTPSettingsEditor.d.ts.map +1 -1
  17. package/dist/components/HTTPSettingsEditor/HTTPSettingsEditor.js +44 -15
  18. package/dist/components/HTTPSettingsEditor/HTTPSettingsEditor.js.map +1 -1
  19. package/dist/components/ItemSelectionActionsOptionsEditor/ItemSelectionActionsOptionsEditor.d.ts.map +1 -1
  20. package/dist/components/ItemSelectionActionsOptionsEditor/ItemSelectionActionsOptionsEditor.js +7 -1
  21. package/dist/components/ItemSelectionActionsOptionsEditor/ItemSelectionActionsOptionsEditor.js.map +1 -1
  22. package/dist/components/LinksEditor/LinksEditor.js +5 -0
  23. package/dist/components/LinksEditor/LinksEditor.js.map +1 -1
  24. package/dist/components/MultiQueryEditor/MultiQueryEditor.d.ts.map +1 -1
  25. package/dist/components/MultiQueryEditor/MultiQueryEditor.js +16 -1
  26. package/dist/components/MultiQueryEditor/MultiQueryEditor.js.map +1 -1
  27. package/dist/components/PanelSpecEditor/PanelSpecEditor.d.ts.map +1 -1
  28. package/dist/components/PanelSpecEditor/PanelSpecEditor.js +4 -1
  29. package/dist/components/PanelSpecEditor/PanelSpecEditor.js.map +1 -1
  30. package/dist/components/PluginEditor/plugin-editor-api.d.ts +7 -1
  31. package/dist/components/PluginEditor/plugin-editor-api.d.ts.map +1 -1
  32. package/dist/components/PluginEditor/plugin-editor-api.js +54 -41
  33. package/dist/components/PluginEditor/plugin-editor-api.js.map +1 -1
  34. package/dist/components/PluginKindSelect/PluginKindSelect.d.ts +14 -0
  35. package/dist/components/PluginKindSelect/PluginKindSelect.d.ts.map +1 -1
  36. package/dist/components/PluginKindSelect/PluginKindSelect.js +187 -23
  37. package/dist/components/PluginKindSelect/PluginKindSelect.js.map +1 -1
  38. package/dist/components/PluginRegistry/PluginRegistry.d.ts.map +1 -1
  39. package/dist/components/PluginRegistry/PluginRegistry.js +72 -7
  40. package/dist/components/PluginRegistry/PluginRegistry.js.map +1 -1
  41. package/dist/components/PluginRegistry/plugin-indexes.d.ts +1 -0
  42. package/dist/components/PluginRegistry/plugin-indexes.d.ts.map +1 -1
  43. package/dist/components/PluginRegistry/plugin-indexes.js +6 -1
  44. package/dist/components/PluginRegistry/plugin-indexes.js.map +1 -1
  45. package/dist/components/PluginSpecEditor/PluginSpecEditor.d.ts.map +1 -1
  46. package/dist/components/PluginSpecEditor/PluginSpecEditor.js +6 -2
  47. package/dist/components/PluginSpecEditor/PluginSpecEditor.js.map +1 -1
  48. package/dist/components/TimeRangeControls/TimeRangeControls.d.ts.map +1 -1
  49. package/dist/components/TimeRangeControls/TimeRangeControls.js +0 -2
  50. package/dist/components/TimeRangeControls/TimeRangeControls.js.map +1 -1
  51. package/dist/components/Variables/VariableEditorForm/VariablePreview.js +1 -1
  52. package/dist/components/Variables/VariableEditorForm/VariablePreview.js.map +1 -1
  53. package/dist/components/Variables/variable-model.d.ts.map +1 -1
  54. package/dist/components/Variables/variable-model.js +7 -2
  55. package/dist/components/Variables/variable-model.js.map +1 -1
  56. package/dist/model/datasource.d.ts +3 -0
  57. package/dist/model/datasource.d.ts.map +1 -1
  58. package/dist/model/datasource.js.map +1 -1
  59. package/dist/model/plugin-loading.d.ts +1 -0
  60. package/dist/model/plugin-loading.d.ts.map +1 -1
  61. package/dist/model/plugin-loading.js.map +1 -1
  62. package/dist/model/plugins.d.ts +11 -0
  63. package/dist/model/plugins.d.ts.map +1 -1
  64. package/dist/model/plugins.js.map +1 -1
  65. package/dist/remote/PluginLoaderComponent.d.ts.map +1 -1
  66. package/dist/remote/PluginLoaderComponent.js +28 -15
  67. package/dist/remote/PluginLoaderComponent.js.map +1 -1
  68. package/dist/remote/PluginRuntime.d.ts.map +1 -1
  69. package/dist/remote/PluginRuntime.js +32 -24
  70. package/dist/remote/PluginRuntime.js.map +1 -1
  71. package/dist/remote/remotePluginLoader.d.ts.map +1 -1
  72. package/dist/remote/remotePluginLoader.js +1 -0
  73. package/dist/remote/remotePluginLoader.js.map +1 -1
  74. package/dist/runtime/DataQueriesProvider/DataQueriesProvider.js +21 -15
  75. package/dist/runtime/DataQueriesProvider/DataQueriesProvider.js.map +1 -1
  76. package/dist/runtime/TimeRangeProvider/TimeRangeProvider.d.ts.map +1 -1
  77. package/dist/runtime/TimeRangeProvider/TimeRangeProvider.js +23 -1
  78. package/dist/runtime/TimeRangeProvider/TimeRangeProvider.js.map +1 -1
  79. package/dist/runtime/TimeRangeProvider/TimeRangeProviders.d.ts +3 -1
  80. package/dist/runtime/TimeRangeProvider/TimeRangeProviders.d.ts.map +1 -1
  81. package/dist/runtime/TimeRangeProvider/TimeRangeProviders.js +2 -2
  82. package/dist/runtime/TimeRangeProvider/TimeRangeProviders.js.map +1 -1
  83. package/dist/runtime/TimeRangeProvider/query-params.js +7 -9
  84. package/dist/runtime/TimeRangeProvider/query-params.js.map +1 -1
  85. package/dist/runtime/UsageMetricsProvider.d.ts.map +1 -1
  86. package/dist/runtime/UsageMetricsProvider.js +24 -20
  87. package/dist/runtime/UsageMetricsProvider.js.map +1 -1
  88. package/dist/runtime/alerts-queries.d.ts.map +1 -1
  89. package/dist/runtime/alerts-queries.js +6 -2
  90. package/dist/runtime/alerts-queries.js.map +1 -1
  91. package/dist/runtime/annotations.d.ts +8 -0
  92. package/dist/runtime/annotations.d.ts.map +1 -1
  93. package/dist/runtime/annotations.js +47 -83
  94. package/dist/runtime/annotations.js.map +1 -1
  95. package/dist/runtime/datasources.d.ts +4 -0
  96. package/dist/runtime/datasources.d.ts.map +1 -1
  97. package/dist/runtime/datasources.js +4 -3
  98. package/dist/runtime/datasources.js.map +1 -1
  99. package/dist/runtime/log-queries.d.ts.map +1 -1
  100. package/dist/runtime/log-queries.js +3 -1
  101. package/dist/runtime/log-queries.js.map +1 -1
  102. package/dist/runtime/plugin-registry.d.ts +23 -8
  103. package/dist/runtime/plugin-registry.d.ts.map +1 -1
  104. package/dist/runtime/plugin-registry.js +52 -16
  105. package/dist/runtime/plugin-registry.js.map +1 -1
  106. package/dist/runtime/profile-queries.d.ts.map +1 -1
  107. package/dist/runtime/profile-queries.js +3 -1
  108. package/dist/runtime/profile-queries.js.map +1 -1
  109. package/dist/runtime/silences-queries.d.ts.map +1 -1
  110. package/dist/runtime/silences-queries.js +6 -2
  111. package/dist/runtime/silences-queries.js.map +1 -1
  112. package/dist/runtime/time-series-queries.d.ts.map +1 -1
  113. package/dist/runtime/time-series-queries.js +10 -3
  114. package/dist/runtime/time-series-queries.js.map +1 -1
  115. package/dist/runtime/trace-queries.d.ts.map +1 -1
  116. package/dist/runtime/trace-queries.js +6 -2
  117. package/dist/runtime/trace-queries.js.map +1 -1
  118. package/dist/runtime/variables.d.ts +6 -0
  119. package/dist/runtime/variables.d.ts.map +1 -1
  120. package/dist/runtime/variables.js +17 -1
  121. package/dist/runtime/variables.js.map +1 -1
  122. package/dist/utils/index.d.ts +1 -0
  123. package/dist/utils/index.d.ts.map +1 -1
  124. package/dist/utils/index.js +1 -0
  125. package/dist/utils/index.js.map +1 -1
  126. package/dist/utils/plugin-versions.d.ts +18 -0
  127. package/dist/utils/plugin-versions.d.ts.map +1 -0
  128. package/dist/utils/plugin-versions.js +52 -0
  129. package/dist/utils/plugin-versions.js.map +1 -0
  130. package/package.json +6 -5
@@ -14,11 +14,12 @@ 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";
21
21
  let instance = null;
22
+ const DEFAULT_PLUGINS_ASSETS_BASE_URL = '/plugins';
22
23
  function createSharedModuleLoader(loadModule) {
23
24
  return async ()=>{
24
25
  const module = await loadModule();
@@ -104,51 +105,51 @@ const getPluginRuntime = ()=>{
104
105
  }
105
106
  },
106
107
  '@perses-dev/spec': {
107
- version: '0.3.0-beta.8',
108
+ version: '0.3.0-rc.0',
108
109
  lib: ()=>getHostSharedModule('@perses-dev/spec'),
109
110
  shareConfig: {
110
111
  singleton: true,
111
- requiredVersion: '^0.3.0-beta.8'
112
+ requiredVersion: '^0.3.0-rc.0'
112
113
  }
113
114
  },
114
115
  '@perses-dev/client': {
115
- version: '0.55.0-beta.8',
116
+ version: '0.55.0-rc.0',
116
117
  lib: ()=>getHostSharedModule('@perses-dev/client'),
117
118
  shareConfig: {
118
119
  singleton: true,
119
- requiredVersion: '^0.55.0-beta.8'
120
+ requiredVersion: '^0.55.0-rc.0'
120
121
  }
121
122
  },
122
123
  '@perses-dev/components': {
123
- version: '0.55.0-beta.8',
124
+ version: '0.55.0-rc.0',
124
125
  lib: ()=>getHostSharedModule('@perses-dev/components'),
125
126
  shareConfig: {
126
127
  singleton: true,
127
- requiredVersion: '^0.55.0-beta.8'
128
+ requiredVersion: '^0.55.0-rc.0'
128
129
  }
129
130
  },
130
131
  '@perses-dev/plugin-system': {
131
- version: '0.55.0-beta.8',
132
+ version: '0.55.0-rc.0',
132
133
  lib: ()=>getHostSharedModule('@perses-dev/plugin-system'),
133
134
  shareConfig: {
134
135
  singleton: true,
135
- requiredVersion: '^0.55.0-beta.8'
136
+ requiredVersion: '^0.55.0-rc.0'
136
137
  }
137
138
  },
138
139
  '@perses-dev/explore': {
139
- version: '0.55.0-beta.8',
140
+ version: '0.55.0-rc.0',
140
141
  lib: ()=>getHostSharedModule('@perses-dev/explore'),
141
142
  shareConfig: {
142
143
  singleton: true,
143
- requiredVersion: '^0.55.0-beta.8'
144
+ requiredVersion: '^0.55.0-rc.0'
144
145
  }
145
146
  },
146
147
  '@perses-dev/dashboards': {
147
- version: '0.55.0-beta.8',
148
+ version: '0.55.0-rc.0',
148
149
  lib: ()=>getHostSharedModule('@perses-dev/dashboards'),
149
150
  shareConfig: {
150
151
  singleton: true,
151
- requiredVersion: '^0.55.0-beta.8'
152
+ requiredVersion: '^0.55.0-rc.0'
152
153
  }
153
154
  },
154
155
  // Below are the shared modules that are used by the plugins and are loaded asynchronously on demand using get rather than lib.
@@ -203,6 +204,8 @@ const getPluginRuntime = ()=>{
203
204
  },
204
205
  'mdi-material-ui': {
205
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
206
209
  get: createSharedModuleLoader(()=>import("mdi-material-ui")),
207
210
  shareConfig: {
208
211
  singleton: true,
@@ -237,7 +240,7 @@ const registerRemote = (name, registry, version, baseURL)=>{
237
240
  version,
238
241
  registry
239
242
  ].filter(Boolean).join('~');
240
- const prefix = baseURL || '/plugins';
243
+ const prefix = baseURL ?? DEFAULT_PLUGINS_ASSETS_BASE_URL;
241
244
  const remoteEntryURL = `${prefix}/${nameVersionRegistry}/mf-manifest.json`;
242
245
  pluginRuntime.registerRemotes([
243
246
  {
@@ -256,18 +259,23 @@ export const loadPlugin = async (target)=>{
256
259
  return pluginRuntime.loadRemote(`${registryName}/${pluginName}`);
257
260
  };
258
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
+ ]);
259
276
  return {
260
277
  pluginRuntime: getPluginRuntime(),
261
- loadPlugin: ()=>{
262
- const { moduleName, name: pluginName, registry, version, baseURL } = plugin;
263
- return loadPlugin({
264
- moduleName,
265
- pluginName,
266
- registry,
267
- version,
268
- baseURL
269
- });
270
- }
278
+ loadPlugin: load
271
279
  };
272
280
  }
273
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\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.8',\n lib: () => getHostSharedModule('@perses-dev/spec'),\n shareConfig: {\n singleton: true,\n requiredVersion: '^0.3.0-beta.8',\n },\n },\n '@perses-dev/client': {\n version: '0.55.0-beta.8',\n lib: () => getHostSharedModule('@perses-dev/client'),\n shareConfig: {\n singleton: true,\n requiredVersion: '^0.55.0-beta.8',\n },\n },\n '@perses-dev/components': {\n version: '0.55.0-beta.8',\n lib: () => getHostSharedModule('@perses-dev/components'),\n shareConfig: {\n singleton: true,\n requiredVersion: '^0.55.0-beta.8',\n },\n },\n '@perses-dev/plugin-system': {\n version: '0.55.0-beta.8',\n lib: () => getHostSharedModule('@perses-dev/plugin-system'),\n shareConfig: {\n singleton: true,\n requiredVersion: '^0.55.0-beta.8',\n },\n },\n '@perses-dev/explore': {\n version: '0.55.0-beta.8',\n lib: () => getHostSharedModule('@perses-dev/explore'),\n shareConfig: {\n singleton: true,\n requiredVersion: '^0.55.0-beta.8',\n },\n },\n '@perses-dev/dashboards': {\n version: '0.55.0-beta.8',\n lib: () => getHostSharedModule('@perses-dev/dashboards'),\n shareConfig: {\n singleton: true,\n requiredVersion: '^0.55.0-beta.8',\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 || '/plugins';\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","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-rc.0',\n lib: () => getHostSharedModule('@perses-dev/spec'),\n shareConfig: {\n singleton: true,\n requiredVersion: '^0.3.0-rc.0',\n },\n },\n '@perses-dev/client': {\n version: '0.55.0-rc.0',\n lib: () => getHostSharedModule('@perses-dev/client'),\n shareConfig: {\n singleton: true,\n requiredVersion: '^0.55.0-rc.0',\n },\n },\n '@perses-dev/components': {\n version: '0.55.0-rc.0',\n lib: () => getHostSharedModule('@perses-dev/components'),\n shareConfig: {\n singleton: true,\n requiredVersion: '^0.55.0-rc.0',\n },\n },\n '@perses-dev/plugin-system': {\n version: '0.55.0-rc.0',\n lib: () => getHostSharedModule('@perses-dev/plugin-system'),\n shareConfig: {\n singleton: true,\n requiredVersion: '^0.55.0-rc.0',\n },\n },\n '@perses-dev/explore': {\n version: '0.55.0-rc.0',\n lib: () => getHostSharedModule('@perses-dev/explore'),\n shareConfig: {\n singleton: true,\n requiredVersion: '^0.55.0-rc.0',\n },\n },\n '@perses-dev/dashboards': {\n version: '0.55.0-rc.0',\n lib: () => getHostSharedModule('@perses-dev/dashboards'),\n shareConfig: {\n singleton: true,\n requiredVersion: '^0.55.0-rc.0',\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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"}
@@ -1 +1 @@
1
- {"version":3,"file":"remotePluginLoader.d.ts","sourceRoot":"","sources":["../../src/remote/remotePluginLoader.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,KAAK,EAAE,YAAY,EAAoD,MAAM,2BAA2B,CAAC;AAgChH,KAAK,yBAAyB,GAAG;IAC/B;;;QAGI;IACJ,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;QAGI;IACJ,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;OAEG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,CAAC;AAwBF;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,CAAC,EAAE,yBAAyB,GAAG,YAAY,CA0DpF"}
1
+ {"version":3,"file":"remotePluginLoader.d.ts","sourceRoot":"","sources":["../../src/remote/remotePluginLoader.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,KAAK,EAAE,YAAY,EAAoD,MAAM,2BAA2B,CAAC;AAgChH,KAAK,yBAAyB,GAAG;IAC/B;;;QAGI;IACJ,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;QAGI;IACJ,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;OAEG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,CAAC;AAwBF;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,CAAC,EAAE,yBAAyB,GAAG,YAAY,CA2DpF"}
@@ -40,6 +40,7 @@ const paramToOptions = (options)=>{
40
40
  const { pluginsApiPath, pluginsAssetsPath } = paramToOptions(options);
41
41
  const fetchFn = options?.fetchFn ?? defaultFetch;
42
42
  return {
43
+ baseURL: pluginsAssetsPath,
43
44
  getInstalledPlugins: async ()=>{
44
45
  const pluginsResponse = await fetchFn(pluginsApiPath);
45
46
  const plugins = await pluginsResponse.json();
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/remote/remotePluginLoader.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 { fetch as defaultFetch } from '@perses-dev/client';\nimport type { FetchFn } from '@perses-dev/client';\nimport type { PluginLoader, PluginMetadata, PluginModuleResource, PluginType } from '@perses-dev/plugin-system';\nimport { getPluginModuleCompoundKey } from '@perses-dev/plugin-system';\n\nimport type { RemotePluginModule } from './PersesPlugin.types';\nimport { loadPlugin } from './PluginRuntime';\n\nconst isPluginMetadata = (plugin: unknown): plugin is PluginMetadata => {\n return (\n typeof plugin === 'object' &&\n plugin !== null &&\n 'kind' in plugin &&\n 'spec' in plugin &&\n typeof plugin.spec === 'object' &&\n plugin.spec !== null &&\n 'name' in plugin.spec\n );\n};\n\nconst isPluginModuleResource = (pluginModule: unknown): pluginModule is PluginModuleResource => {\n return (\n typeof pluginModule === 'object' &&\n pluginModule !== null &&\n 'metadata' in pluginModule &&\n 'spec' in pluginModule &&\n typeof pluginModule.spec === 'object' &&\n pluginModule.spec !== null &&\n 'plugins' in pluginModule.spec &&\n Array.isArray(pluginModule.spec.plugins) &&\n pluginModule.spec.plugins.every(isPluginMetadata)\n );\n};\n\ntype RemotePluginLoaderOptions = {\n /**\n * The API path for fetching available Perses plugins. Used to construct the full URL to the `/api/v1/plugins` endpoint.\n * @default ''\n **/\n apiPrefix?: string;\n /**\n * The base URL for loading plugin assets (e.g., JavaScript files). Used to construct the full URL to the `/plugins` directory\n * @default ''\n **/\n baseURL?: string;\n /**\n * Optional custom fetch function to use for network requests. If not provided, the default fetch implementation will be used.\n */\n fetchFn?: FetchFn;\n};\n\ntype ParsedPluginOptions = {\n pluginsApiPath: string;\n pluginsAssetsPath: string;\n};\n\nconst DEFAULT_PLUGINS_API_PATH = '/api/v1/plugins';\nconst DEFAULT_PLUGINS_ASSETS_PATH = '/plugins';\n\nconst paramToOptions = (options?: RemotePluginLoaderOptions): ParsedPluginOptions => {\n if (options === undefined) {\n return {\n pluginsApiPath: DEFAULT_PLUGINS_API_PATH,\n pluginsAssetsPath: DEFAULT_PLUGINS_ASSETS_PATH,\n };\n }\n\n return {\n pluginsApiPath: `${options?.apiPrefix ?? ''}${DEFAULT_PLUGINS_API_PATH}`,\n pluginsAssetsPath: `${options?.baseURL ?? ''}${DEFAULT_PLUGINS_ASSETS_PATH}`,\n };\n};\n\n/**\n * Get a PluginLoader that fetches the list of installed plugins from a remote server and loads them as needed.\n * @param options - Optional configuration options for the remote plugin loader.\n */\nexport function remotePluginLoader(options?: RemotePluginLoaderOptions): PluginLoader {\n const { pluginsApiPath, pluginsAssetsPath } = paramToOptions(options);\n const fetchFn = options?.fetchFn ?? defaultFetch;\n\n return {\n getInstalledPlugins: async (): Promise<PluginModuleResource[]> => {\n const pluginsResponse = await fetchFn(pluginsApiPath);\n\n const plugins = await pluginsResponse.json();\n let pluginModules: PluginModuleResource[] = [];\n\n if (Array.isArray(plugins)) {\n pluginModules = plugins.filter(isPluginModuleResource);\n } else {\n console.error('RemotePluginLoader: Error loading plugins, response is not an array');\n }\n\n if (!pluginModules.length) {\n console.error('RemotePluginLoader: No valid plugins found');\n }\n\n return pluginModules;\n },\n importPluginModule: async (resource): Promise<RemotePluginModule> => {\n const { name: pluginModuleName, version, registry } = resource.metadata;\n\n const pluginModule: RemotePluginModule = {};\n\n const loadPromises = resource.spec.plugins.map(async (plugin) => {\n const remotePluginModule = await loadPlugin({\n moduleName: pluginModuleName,\n pluginName: plugin.spec.name,\n registry,\n version,\n baseURL: pluginsAssetsPath,\n });\n\n const remotePlugin = remotePluginModule?.[plugin.spec.name];\n if (remotePlugin) {\n return { kind: plugin.kind as PluginType, name: plugin.spec.name, remotePlugin };\n } else {\n console.error(`RemotePluginLoader: Error loading plugin ${plugin.spec.name}`);\n return null;\n }\n });\n\n const loadedPlugins = await Promise.all(loadPromises);\n\n loadedPlugins.forEach((item) => {\n if (item?.remotePlugin) {\n pluginModule[getPluginModuleCompoundKey({ kind: item.kind, name: item.name, registry, version })] =\n item.remotePlugin;\n }\n });\n\n return pluginModule;\n },\n };\n}\n"],"names":["fetch","defaultFetch","getPluginModuleCompoundKey","loadPlugin","isPluginMetadata","plugin","spec","isPluginModuleResource","pluginModule","Array","isArray","plugins","every","DEFAULT_PLUGINS_API_PATH","DEFAULT_PLUGINS_ASSETS_PATH","paramToOptions","options","undefined","pluginsApiPath","pluginsAssetsPath","apiPrefix","baseURL","remotePluginLoader","fetchFn","getInstalledPlugins","pluginsResponse","json","pluginModules","filter","console","error","length","importPluginModule","resource","name","pluginModuleName","version","registry","metadata","loadPromises","map","remotePluginModule","moduleName","pluginName","remotePlugin","kind","loadedPlugins","Promise","all","forEach","item"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/remote/remotePluginLoader.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 { fetch as defaultFetch } from '@perses-dev/client';\nimport type { FetchFn } from '@perses-dev/client';\nimport type { PluginLoader, PluginMetadata, PluginModuleResource, PluginType } from '@perses-dev/plugin-system';\nimport { getPluginModuleCompoundKey } from '@perses-dev/plugin-system';\n\nimport type { RemotePluginModule } from './PersesPlugin.types';\nimport { loadPlugin } from './PluginRuntime';\n\nconst isPluginMetadata = (plugin: unknown): plugin is PluginMetadata => {\n return (\n typeof plugin === 'object' &&\n plugin !== null &&\n 'kind' in plugin &&\n 'spec' in plugin &&\n typeof plugin.spec === 'object' &&\n plugin.spec !== null &&\n 'name' in plugin.spec\n );\n};\n\nconst isPluginModuleResource = (pluginModule: unknown): pluginModule is PluginModuleResource => {\n return (\n typeof pluginModule === 'object' &&\n pluginModule !== null &&\n 'metadata' in pluginModule &&\n 'spec' in pluginModule &&\n typeof pluginModule.spec === 'object' &&\n pluginModule.spec !== null &&\n 'plugins' in pluginModule.spec &&\n Array.isArray(pluginModule.spec.plugins) &&\n pluginModule.spec.plugins.every(isPluginMetadata)\n );\n};\n\ntype RemotePluginLoaderOptions = {\n /**\n * The API path for fetching available Perses plugins. Used to construct the full URL to the `/api/v1/plugins` endpoint.\n * @default ''\n **/\n apiPrefix?: string;\n /**\n * The base URL for loading plugin assets (e.g., JavaScript files). Used to construct the full URL to the `/plugins` directory\n * @default ''\n **/\n baseURL?: string;\n /**\n * Optional custom fetch function to use for network requests. If not provided, the default fetch implementation will be used.\n */\n fetchFn?: FetchFn;\n};\n\ntype ParsedPluginOptions = {\n pluginsApiPath: string;\n pluginsAssetsPath: string;\n};\n\nconst DEFAULT_PLUGINS_API_PATH = '/api/v1/plugins';\nconst DEFAULT_PLUGINS_ASSETS_PATH = '/plugins';\n\nconst paramToOptions = (options?: RemotePluginLoaderOptions): ParsedPluginOptions => {\n if (options === undefined) {\n return {\n pluginsApiPath: DEFAULT_PLUGINS_API_PATH,\n pluginsAssetsPath: DEFAULT_PLUGINS_ASSETS_PATH,\n };\n }\n\n return {\n pluginsApiPath: `${options?.apiPrefix ?? ''}${DEFAULT_PLUGINS_API_PATH}`,\n pluginsAssetsPath: `${options?.baseURL ?? ''}${DEFAULT_PLUGINS_ASSETS_PATH}`,\n };\n};\n\n/**\n * Get a PluginLoader that fetches the list of installed plugins from a remote server and loads them as needed.\n * @param options - Optional configuration options for the remote plugin loader.\n */\nexport function remotePluginLoader(options?: RemotePluginLoaderOptions): PluginLoader {\n const { pluginsApiPath, pluginsAssetsPath } = paramToOptions(options);\n const fetchFn = options?.fetchFn ?? defaultFetch;\n\n return {\n baseURL: pluginsAssetsPath,\n getInstalledPlugins: async (): Promise<PluginModuleResource[]> => {\n const pluginsResponse = await fetchFn(pluginsApiPath);\n\n const plugins = await pluginsResponse.json();\n let pluginModules: PluginModuleResource[] = [];\n\n if (Array.isArray(plugins)) {\n pluginModules = plugins.filter(isPluginModuleResource);\n } else {\n console.error('RemotePluginLoader: Error loading plugins, response is not an array');\n }\n\n if (!pluginModules.length) {\n console.error('RemotePluginLoader: No valid plugins found');\n }\n\n return pluginModules;\n },\n importPluginModule: async (resource): Promise<RemotePluginModule> => {\n const { name: pluginModuleName, version, registry } = resource.metadata;\n\n const pluginModule: RemotePluginModule = {};\n\n const loadPromises = resource.spec.plugins.map(async (plugin) => {\n const remotePluginModule = await loadPlugin({\n moduleName: pluginModuleName,\n pluginName: plugin.spec.name,\n registry,\n version,\n baseURL: pluginsAssetsPath,\n });\n\n const remotePlugin = remotePluginModule?.[plugin.spec.name];\n if (remotePlugin) {\n return { kind: plugin.kind as PluginType, name: plugin.spec.name, remotePlugin };\n } else {\n console.error(`RemotePluginLoader: Error loading plugin ${plugin.spec.name}`);\n return null;\n }\n });\n\n const loadedPlugins = await Promise.all(loadPromises);\n\n loadedPlugins.forEach((item) => {\n if (item?.remotePlugin) {\n pluginModule[getPluginModuleCompoundKey({ kind: item.kind, name: item.name, registry, version })] =\n item.remotePlugin;\n }\n });\n\n return pluginModule;\n },\n };\n}\n"],"names":["fetch","defaultFetch","getPluginModuleCompoundKey","loadPlugin","isPluginMetadata","plugin","spec","isPluginModuleResource","pluginModule","Array","isArray","plugins","every","DEFAULT_PLUGINS_API_PATH","DEFAULT_PLUGINS_ASSETS_PATH","paramToOptions","options","undefined","pluginsApiPath","pluginsAssetsPath","apiPrefix","baseURL","remotePluginLoader","fetchFn","getInstalledPlugins","pluginsResponse","json","pluginModules","filter","console","error","length","importPluginModule","resource","name","pluginModuleName","version","registry","metadata","loadPromises","map","remotePluginModule","moduleName","pluginName","remotePlugin","kind","loadedPlugins","Promise","all","forEach","item"],"mappings":"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"}
@@ -31,21 +31,27 @@ export function useDataQueriesContext() {
31
31
  }
32
32
  export function useDataQueries(queryType) {
33
33
  const ctx = useDataQueriesContext();
34
- // Filter query definitions based on the specified query type
35
- const filteredQueryDefinitions = ctx.queryDefinitions.filter((definition)=>definition.kind === queryType);
36
- // Filter the query results based on the specified query type
37
- const filteredQueryResults = ctx.queryResults.filter((queryResult)=>queryResult?.definition?.kind === queryType);
38
- // Filter the errors based on the specified query type
39
- const filteredErrors = ctx.errors.filter((errors, index)=>ctx.queryResults[index]?.definition?.kind === queryType);
40
- // Create a new context object with the filtered results and errors
41
- return {
42
- queryDefinitions: filteredQueryDefinitions,
43
- queryResults: filteredQueryResults,
44
- isFetching: filteredQueryResults.some((result)=>result.isFetching),
45
- isLoading: filteredQueryResults.some((result)=>result.isLoading),
46
- refetchAll: ctx.refetchAll,
47
- errors: filteredErrors
48
- };
34
+ // Keep result arrays stable during local panel interactions so downstream chart
35
+ // transformations can reuse their memoized results.
36
+ return useMemo(()=>{
37
+ const filteredQueryDefinitions = ctx.queryDefinitions.filter((definition)=>definition.kind === queryType);
38
+ const filteredQueryResults = ctx.queryResults.filter((queryResult)=>queryResult?.definition?.kind === queryType);
39
+ const filteredErrors = ctx.errors.filter((_error, index)=>ctx.queryResults[index]?.definition?.kind === queryType);
40
+ return {
41
+ queryDefinitions: filteredQueryDefinitions,
42
+ queryResults: filteredQueryResults,
43
+ isFetching: filteredQueryResults.some((result)=>result.isFetching),
44
+ isLoading: filteredQueryResults.some((result)=>result.isLoading),
45
+ refetchAll: ctx.refetchAll,
46
+ errors: filteredErrors
47
+ };
48
+ }, [
49
+ ctx.queryDefinitions,
50
+ ctx.queryResults,
51
+ ctx.errors,
52
+ ctx.refetchAll,
53
+ queryType
54
+ ]);
49
55
  }
50
56
  export function DataQueriesProvider(props) {
51
57
  const { definitions, options, children, queryOptions } = props;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/runtime/DataQueriesProvider/DataQueriesProvider.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 type { QueryType, TimeSeriesQueryDefinition } from '@perses-dev/spec';\nimport type { ReactElement } from 'react';\nimport { createContext, useCallback, useContext, useMemo } from 'react';\n\nimport type { AlertsQueryDefinition } from '../alerts-queries';\nimport { useAlertsQueries } from '../alerts-queries';\nimport type { JsonQueryDefinition } from '../json-queries';\nimport { useJsonQueries } from '../json-queries';\nimport type { LogQueryDefinition } from '../log-queries';\nimport { useLogQueries } from '../log-queries';\nimport type { ProfileQueryDefinition } from '../profile-queries';\nimport { useProfileQueries } from '../profile-queries';\nimport type { SilencesQueryDefinition } from '../silences-queries';\nimport { useSilencesQueries } from '../silences-queries';\nimport { useTimeSeriesQueries } from '../time-series-queries';\nimport type { TraceQueryDefinition } from '../trace-queries';\nimport { useTraceQueries } from '../trace-queries';\nimport { useUsageMetrics } from '../UsageMetricsProvider';\nimport type { DataQueriesProviderProps, UseDataQueryResults, DataQueriesContextType, QueryData } from './model';\nimport { transformQueryResults } from './model';\n\nexport const DataQueriesContext = createContext<DataQueriesContextType | undefined>(undefined);\n\nexport function useDataQueriesContext(): DataQueriesContextType {\n const ctx = useContext(DataQueriesContext);\n if (ctx === undefined) {\n throw new Error('No DataQueriesContext found. Did you forget a Provider?');\n }\n return ctx;\n}\n\nexport function useDataQueries<T extends keyof QueryType>(queryType: T): UseDataQueryResults<QueryType[T]> {\n const ctx = useDataQueriesContext();\n\n // Filter query definitions based on the specified query type\n const filteredQueryDefinitions = ctx.queryDefinitions.filter((definition) => definition.kind === queryType);\n\n // Filter the query results based on the specified query type\n const filteredQueryResults = ctx.queryResults.filter(\n (queryResult) => queryResult?.definition?.kind === queryType,\n ) as Array<QueryData<QueryType[T]>>;\n\n // Filter the errors based on the specified query type\n const filteredErrors = ctx.errors.filter((errors, index) => ctx.queryResults[index]?.definition?.kind === queryType);\n\n // Create a new context object with the filtered results and errors\n return {\n queryDefinitions: filteredQueryDefinitions,\n queryResults: filteredQueryResults,\n isFetching: filteredQueryResults.some((result) => result.isFetching),\n isLoading: filteredQueryResults.some((result) => result.isLoading),\n refetchAll: ctx.refetchAll,\n errors: filteredErrors,\n };\n}\n\nexport function DataQueriesProvider(props: DataQueriesProviderProps): ReactElement {\n const { definitions, options, children, queryOptions } = props;\n\n const usageMetrics = useUsageMetrics();\n\n // Filter definitions for time series query and other future query plugins\n const timeSeriesQueries = definitions.filter(\n (definition) => definition.kind === 'TimeSeriesQuery',\n ) as TimeSeriesQueryDefinition[];\n const timeSeriesResults = useTimeSeriesQueries(timeSeriesQueries, options, queryOptions);\n\n const traceQueries = definitions.filter((definition) => definition.kind === 'TraceQuery') as TraceQueryDefinition[];\n const traceResults = useTraceQueries(traceQueries);\n\n const profileQueries = definitions.filter(\n (definition) => definition.kind === 'ProfileQuery',\n ) as ProfileQueryDefinition[];\n const profileResults = useProfileQueries(profileQueries);\n\n const logQueries = definitions.filter((definition) => definition.kind === 'LogQuery') as LogQueryDefinition[];\n const logResults = useLogQueries(logQueries);\n\n const alertsQueries = definitions.filter(\n (definition) => definition.kind === 'AlertsQuery',\n ) as AlertsQueryDefinition[];\n const alertsResults = useAlertsQueries(alertsQueries);\n\n const silencesQueries = definitions.filter(\n (definition) => definition.kind === 'SilencesQuery',\n ) as SilencesQueryDefinition[];\n const silencesResults = useSilencesQueries(silencesQueries);\n\n const jsonQueries = definitions.filter((definition) => definition.kind === 'JsonQuery') as JsonQueryDefinition[];\n const jsonResults = useJsonQueries(jsonQueries);\n\n const refetchAll = useCallback(() => {\n timeSeriesResults.forEach((result) => result.refetch());\n traceResults.forEach((result) => result.refetch());\n profileResults.forEach((result) => result.refetch());\n logResults.forEach((result) => result.refetch());\n alertsResults.forEach((result) => result.refetch());\n silencesResults.forEach((result) => result.refetch());\n jsonResults.forEach((result) => result.refetch());\n }, [timeSeriesResults, traceResults, profileResults, logResults, alertsResults, silencesResults, jsonResults]);\n\n const ctx = useMemo(() => {\n const mergedQueryResults = [\n ...transformQueryResults(timeSeriesResults, timeSeriesQueries),\n ...transformQueryResults(traceResults, traceQueries),\n ...transformQueryResults(profileResults, profileQueries),\n ...transformQueryResults(logResults, logQueries),\n ...transformQueryResults(alertsResults, alertsQueries),\n ...transformQueryResults(silencesResults, silencesQueries),\n ...transformQueryResults(jsonResults, jsonQueries),\n ];\n\n if (queryOptions?.enabled) {\n for (const result of mergedQueryResults) {\n if (!result.isLoading && !result.isFetching && !result.error) {\n usageMetrics.markQuery(result.definition, 'success');\n } else if (result.error) {\n usageMetrics.markQuery(result.definition, 'error');\n } else {\n usageMetrics.markQuery(result.definition, 'pending');\n }\n }\n }\n\n return {\n queryDefinitions: definitions,\n queryResults: mergedQueryResults,\n isFetching: mergedQueryResults.some((result) => result.isFetching),\n isLoading: mergedQueryResults.some((result) => result.isLoading),\n refetchAll,\n errors: mergedQueryResults.map((result) => result.error),\n };\n }, [\n alertsQueries,\n alertsResults,\n logQueries,\n logResults,\n profileQueries,\n profileResults,\n silencesQueries,\n silencesResults,\n jsonQueries,\n jsonResults,\n timeSeriesQueries,\n timeSeriesResults,\n traceQueries,\n traceResults,\n definitions,\n queryOptions?.enabled,\n refetchAll,\n usageMetrics,\n ]);\n\n return <DataQueriesContext.Provider value={ctx}>{children}</DataQueriesContext.Provider>;\n}\n"],"names":["createContext","useCallback","useContext","useMemo","useAlertsQueries","useJsonQueries","useLogQueries","useProfileQueries","useSilencesQueries","useTimeSeriesQueries","useTraceQueries","useUsageMetrics","transformQueryResults","DataQueriesContext","undefined","useDataQueriesContext","ctx","Error","useDataQueries","queryType","filteredQueryDefinitions","queryDefinitions","filter","definition","kind","filteredQueryResults","queryResults","queryResult","filteredErrors","errors","index","isFetching","some","result","isLoading","refetchAll","DataQueriesProvider","props","definitions","options","children","queryOptions","usageMetrics","timeSeriesQueries","timeSeriesResults","traceQueries","traceResults","profileQueries","profileResults","logQueries","logResults","alertsQueries","alertsResults","silencesQueries","silencesResults","jsonQueries","jsonResults","forEach","refetch","mergedQueryResults","enabled","error","markQuery","map","Provider","value"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/runtime/DataQueriesProvider/DataQueriesProvider.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 type { QueryType, TimeSeriesQueryDefinition } from '@perses-dev/spec';\nimport type { ReactElement } from 'react';\nimport { createContext, useCallback, useContext, useMemo } from 'react';\n\nimport type { AlertsQueryDefinition } from '../alerts-queries';\nimport { useAlertsQueries } from '../alerts-queries';\nimport type { JsonQueryDefinition } from '../json-queries';\nimport { useJsonQueries } from '../json-queries';\nimport type { LogQueryDefinition } from '../log-queries';\nimport { useLogQueries } from '../log-queries';\nimport type { ProfileQueryDefinition } from '../profile-queries';\nimport { useProfileQueries } from '../profile-queries';\nimport type { SilencesQueryDefinition } from '../silences-queries';\nimport { useSilencesQueries } from '../silences-queries';\nimport { useTimeSeriesQueries } from '../time-series-queries';\nimport type { TraceQueryDefinition } from '../trace-queries';\nimport { useTraceQueries } from '../trace-queries';\nimport { useUsageMetrics } from '../UsageMetricsProvider';\nimport type { DataQueriesProviderProps, UseDataQueryResults, DataQueriesContextType, QueryData } from './model';\nimport { transformQueryResults } from './model';\n\nexport const DataQueriesContext = createContext<DataQueriesContextType | undefined>(undefined);\n\nexport function useDataQueriesContext(): DataQueriesContextType {\n const ctx = useContext(DataQueriesContext);\n if (ctx === undefined) {\n throw new Error('No DataQueriesContext found. Did you forget a Provider?');\n }\n return ctx;\n}\n\nexport function useDataQueries<T extends keyof QueryType>(queryType: T): UseDataQueryResults<QueryType[T]> {\n const ctx = useDataQueriesContext();\n\n // Keep result arrays stable during local panel interactions so downstream chart\n // transformations can reuse their memoized results.\n return useMemo(() => {\n const filteredQueryDefinitions = ctx.queryDefinitions.filter((definition) => definition.kind === queryType);\n const filteredQueryResults = ctx.queryResults.filter(\n (queryResult) => queryResult?.definition?.kind === queryType,\n ) as Array<QueryData<QueryType[T]>>;\n const filteredErrors = ctx.errors.filter(\n (_error, index) => ctx.queryResults[index]?.definition?.kind === queryType,\n );\n\n return {\n queryDefinitions: filteredQueryDefinitions,\n queryResults: filteredQueryResults,\n isFetching: filteredQueryResults.some((result) => result.isFetching),\n isLoading: filteredQueryResults.some((result) => result.isLoading),\n refetchAll: ctx.refetchAll,\n errors: filteredErrors,\n };\n }, [ctx.queryDefinitions, ctx.queryResults, ctx.errors, ctx.refetchAll, queryType]);\n}\n\nexport function DataQueriesProvider(props: DataQueriesProviderProps): ReactElement {\n const { definitions, options, children, queryOptions } = props;\n\n const usageMetrics = useUsageMetrics();\n\n // Filter definitions for time series query and other future query plugins\n const timeSeriesQueries = definitions.filter(\n (definition) => definition.kind === 'TimeSeriesQuery',\n ) as TimeSeriesQueryDefinition[];\n const timeSeriesResults = useTimeSeriesQueries(timeSeriesQueries, options, queryOptions);\n\n const traceQueries = definitions.filter((definition) => definition.kind === 'TraceQuery') as TraceQueryDefinition[];\n const traceResults = useTraceQueries(traceQueries);\n\n const profileQueries = definitions.filter(\n (definition) => definition.kind === 'ProfileQuery',\n ) as ProfileQueryDefinition[];\n const profileResults = useProfileQueries(profileQueries);\n\n const logQueries = definitions.filter((definition) => definition.kind === 'LogQuery') as LogQueryDefinition[];\n const logResults = useLogQueries(logQueries);\n\n const alertsQueries = definitions.filter(\n (definition) => definition.kind === 'AlertsQuery',\n ) as AlertsQueryDefinition[];\n const alertsResults = useAlertsQueries(alertsQueries);\n\n const silencesQueries = definitions.filter(\n (definition) => definition.kind === 'SilencesQuery',\n ) as SilencesQueryDefinition[];\n const silencesResults = useSilencesQueries(silencesQueries);\n\n const jsonQueries = definitions.filter((definition) => definition.kind === 'JsonQuery') as JsonQueryDefinition[];\n const jsonResults = useJsonQueries(jsonQueries);\n\n const refetchAll = useCallback(() => {\n timeSeriesResults.forEach((result) => result.refetch());\n traceResults.forEach((result) => result.refetch());\n profileResults.forEach((result) => result.refetch());\n logResults.forEach((result) => result.refetch());\n alertsResults.forEach((result) => result.refetch());\n silencesResults.forEach((result) => result.refetch());\n jsonResults.forEach((result) => result.refetch());\n }, [timeSeriesResults, traceResults, profileResults, logResults, alertsResults, silencesResults, jsonResults]);\n\n const ctx = useMemo(() => {\n const mergedQueryResults = [\n ...transformQueryResults(timeSeriesResults, timeSeriesQueries),\n ...transformQueryResults(traceResults, traceQueries),\n ...transformQueryResults(profileResults, profileQueries),\n ...transformQueryResults(logResults, logQueries),\n ...transformQueryResults(alertsResults, alertsQueries),\n ...transformQueryResults(silencesResults, silencesQueries),\n ...transformQueryResults(jsonResults, jsonQueries),\n ];\n\n if (queryOptions?.enabled) {\n for (const result of mergedQueryResults) {\n if (!result.isLoading && !result.isFetching && !result.error) {\n usageMetrics.markQuery(result.definition, 'success');\n } else if (result.error) {\n usageMetrics.markQuery(result.definition, 'error');\n } else {\n usageMetrics.markQuery(result.definition, 'pending');\n }\n }\n }\n\n return {\n queryDefinitions: definitions,\n queryResults: mergedQueryResults,\n isFetching: mergedQueryResults.some((result) => result.isFetching),\n isLoading: mergedQueryResults.some((result) => result.isLoading),\n refetchAll,\n errors: mergedQueryResults.map((result) => result.error),\n };\n }, [\n alertsQueries,\n alertsResults,\n logQueries,\n logResults,\n profileQueries,\n profileResults,\n silencesQueries,\n silencesResults,\n jsonQueries,\n jsonResults,\n timeSeriesQueries,\n timeSeriesResults,\n traceQueries,\n traceResults,\n definitions,\n queryOptions?.enabled,\n refetchAll,\n usageMetrics,\n ]);\n\n return <DataQueriesContext.Provider value={ctx}>{children}</DataQueriesContext.Provider>;\n}\n"],"names":["createContext","useCallback","useContext","useMemo","useAlertsQueries","useJsonQueries","useLogQueries","useProfileQueries","useSilencesQueries","useTimeSeriesQueries","useTraceQueries","useUsageMetrics","transformQueryResults","DataQueriesContext","undefined","useDataQueriesContext","ctx","Error","useDataQueries","queryType","filteredQueryDefinitions","queryDefinitions","filter","definition","kind","filteredQueryResults","queryResults","queryResult","filteredErrors","errors","_error","index","isFetching","some","result","isLoading","refetchAll","DataQueriesProvider","props","definitions","options","children","queryOptions","usageMetrics","timeSeriesQueries","timeSeriesResults","traceQueries","traceResults","profileQueries","profileResults","logQueries","logResults","alertsQueries","alertsResults","silencesQueries","silencesResults","jsonQueries","jsonResults","forEach","refetch","mergedQueryResults","enabled","error","markQuery","map","Provider","value"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"TimeRangeProvider.d.ts","sourceRoot":"","sources":["../../../src/runtime/TimeRangeProvider/TimeRangeProvider.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,iBAAiB,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAG1F,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAC1C,OAAO,KAA+E,MAAM,OAAO,CAAC;AAKpG,MAAM,WAAW,sBAAsB;IACrC,SAAS,EAAE,cAAc,CAAC;IAC1B,eAAe,CAAC,EAAE,cAAc,CAAC;IACjC,YAAY,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,CAAC;IAC9C,kBAAkB,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,CAAC;IACpD,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC5B;AAED,MAAM,WAAW,SAAS;IACxB,SAAS,EAAE,cAAc,CAAC;IAC1B,iBAAiB,EAAE,iBAAiB,CAAC;IACrC,YAAY,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,CAAC;IAC9C,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,eAAe,CAAC,EAAE,cAAc,CAAC;IACjC,mBAAmB,EAAE,MAAM,CAAC;IAC5B,kBAAkB,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,CAAC;CACrD;AAED,eAAO,MAAM,gBAAgB,sCAAkD,CAAC;AAEhF,wBAAgB,mBAAmB,IAAI,SAAS,CAM/C;AAED;;GAEG;AACH,wBAAgB,YAAY,IAAI,SAAS,CAExC;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAIzD;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,sBAAsB,GAAG,YAAY,CAoF7E"}
1
+ {"version":3,"file":"TimeRangeProvider.d.ts","sourceRoot":"","sources":["../../../src/runtime/TimeRangeProvider/TimeRangeProvider.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,iBAAiB,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAG1F,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAC1C,OAAO,KAA+E,MAAM,OAAO,CAAC;AAKpG,MAAM,WAAW,sBAAsB;IACrC,SAAS,EAAE,cAAc,CAAC;IAC1B,eAAe,CAAC,EAAE,cAAc,CAAC;IACjC,YAAY,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,CAAC;IAC9C,kBAAkB,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,CAAC;IACpD,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC5B;AAED,MAAM,WAAW,SAAS;IACxB,SAAS,EAAE,cAAc,CAAC;IAC1B,iBAAiB,EAAE,iBAAiB,CAAC;IACrC,YAAY,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,CAAC;IAC9C,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,eAAe,CAAC,EAAE,cAAc,CAAC;IACjC,mBAAmB,EAAE,MAAM,CAAC;IAC5B,kBAAkB,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,CAAC;CACrD;AAED,eAAO,MAAM,gBAAgB,sCAAkD,CAAC;AAEhF,wBAAgB,mBAAmB,IAAI,SAAS,CAM/C;AAED;;GAEG;AACH,wBAAgB,YAAY,IAAI,SAAS,CAExC;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAIzD;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,sBAAsB,GAAG,YAAY,CA0F7E"}
@@ -82,13 +82,35 @@ export function useTimeRangeContext() {
82
82
  ],
83
83
  type: 'inactive'
84
84
  }));
85
+ queryClient.invalidateQueries({
86
+ queryKey: [
87
+ 'annotation'
88
+ ]
89
+ }).finally(()=>queryClient.removeQueries({
90
+ queryKey: [
91
+ 'annotation'
92
+ ],
93
+ type: 'inactive'
94
+ }));
85
95
  }, [
86
96
  queryClient,
87
97
  timeRange
88
98
  ]);
89
- // Auto refresh is only refreshing queries of panels
99
+ // Auto refresh is only refreshing queries of panels, including their annotations
90
100
  const autoRefresh = useCallback(()=>{
91
101
  setAbsoluteTimeRange(isRelativeTimeRange(timeRange) ? toAbsoluteTimeRange(timeRange) : timeRange);
102
+ queryClient.invalidateQueries({
103
+ queryKey: [
104
+ 'annotation'
105
+ ]
106
+ }).finally(()=>{
107
+ queryClient.removeQueries({
108
+ queryKey: [
109
+ 'annotation'
110
+ ],
111
+ type: 'inactive'
112
+ });
113
+ });
92
114
  queryClient.invalidateQueries({
93
115
  queryKey: [
94
116
  'query'
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/runtime/TimeRangeProvider/TimeRangeProvider.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 type { AbsoluteTimeRange, DurationString, TimeRangeValue } from '@perses-dev/spec';\nimport { isRelativeTimeRange, toAbsoluteTimeRange, getSuggestedStepMs } from '@perses-dev/spec';\nimport { useQueryClient } from '@tanstack/react-query';\nimport type { ReactElement } from 'react';\nimport React, { createContext, useCallback, useContext, useEffect, useMemo, useState } from 'react';\n\nimport { getRefreshIntervalInMs } from './refresh-interval';\nimport { useDisableAutoRefreshSetting } from './TimeRangeSettingsProvider';\n\nexport interface TimeRangeProviderProps {\n timeRange: TimeRangeValue;\n refreshInterval?: DurationString;\n setTimeRange: (value: TimeRangeValue) => void;\n setRefreshInterval: (value: DurationString) => void;\n children?: React.ReactNode;\n}\n\nexport interface TimeRange {\n timeRange: TimeRangeValue;\n absoluteTimeRange: AbsoluteTimeRange; // resolved absolute time for plugins to use\n setTimeRange: (value: TimeRangeValue) => void;\n refresh: () => void;\n refreshInterval?: DurationString;\n refreshIntervalInMs: number;\n setRefreshInterval: (value: DurationString) => void;\n}\n\nexport const TimeRangeContext = createContext<TimeRange | undefined>(undefined);\n\nexport function useTimeRangeContext(): TimeRange {\n const ctx = useContext(TimeRangeContext);\n if (ctx === undefined) {\n throw new Error('No TimeRangeContext found. Did you forget a Provider?');\n }\n return ctx;\n}\n\n/**\n * Get and set the current resolved time range at runtime.\n */\nexport function useTimeRange(): TimeRange {\n return useTimeRangeContext();\n}\n\n/**\n * Gets the suggested step for a graph query in ms for the currently selected time range.\n */\nexport function useSuggestedStepMs(width?: number): number {\n const { absoluteTimeRange } = useTimeRange();\n if (width === undefined) return 0;\n return getSuggestedStepMs(absoluteTimeRange, width);\n}\n\n/**\n * Provider implementation that supplies the time range state at runtime.\n */\nexport function TimeRangeProvider(props: TimeRangeProviderProps): ReactElement {\n const { timeRange, refreshInterval, children, setTimeRange, setRefreshInterval } = props;\n const disableAutoRefresh = useDisableAutoRefreshSetting();\n\n const queryClient = useQueryClient();\n const [absoluteTimeRange, setAbsoluteTimeRange] = useState<AbsoluteTimeRange>(\n isRelativeTimeRange(timeRange) ? toAbsoluteTimeRange(timeRange) : timeRange,\n );\n\n const handleSetTimeRange = useCallback(\n (value: TimeRangeValue) => {\n setTimeRange(value);\n setAbsoluteTimeRange(isRelativeTimeRange(value) ? toAbsoluteTimeRange(value) : value);\n },\n [setTimeRange],\n );\n\n // When auto-refresh is disabled by admin, leave URL/spec values untouched and no-op changes.\n const handleSetRefreshInterval = useCallback(\n (value: DurationString) => {\n if (disableAutoRefresh) {\n return;\n }\n setRefreshInterval(value);\n },\n [disableAutoRefresh, setRefreshInterval],\n );\n\n // Refresh is called when clicking on the refresh button, it refreshes all queries including variables\n const refresh = useCallback(() => {\n setAbsoluteTimeRange(isRelativeTimeRange(timeRange) ? toAbsoluteTimeRange(timeRange) : timeRange);\n queryClient\n .invalidateQueries({ queryKey: ['query'] })\n .finally(() => queryClient.removeQueries({ queryKey: ['query'], type: 'inactive' }));\n queryClient\n .invalidateQueries({ queryKey: ['variable'] })\n .finally(() => queryClient.removeQueries({ queryKey: ['variable'], type: 'inactive' }));\n }, [queryClient, timeRange]);\n\n // Auto refresh is only refreshing queries of panels\n const autoRefresh = useCallback(() => {\n setAbsoluteTimeRange(isRelativeTimeRange(timeRange) ? toAbsoluteTimeRange(timeRange) : timeRange);\n queryClient.invalidateQueries({ queryKey: ['query'] }).finally(() => {\n queryClient.removeQueries({ queryKey: ['query'], type: 'inactive' });\n queryClient.removeQueries({ queryKey: ['variable'], type: 'inactive' }); // Timerange is in queryKey, can lead to memory leak when using relative timerange\n });\n }, [queryClient, timeRange]);\n\n // Gate the timer only — do not rewrite refreshInterval / ?refresh= so re-enabling restores them.\n const refreshIntervalInMs = useMemo(\n () => (disableAutoRefresh ? 0 : getRefreshIntervalInMs(refreshInterval)),\n [disableAutoRefresh, refreshInterval],\n );\n useEffect(() => {\n if (refreshIntervalInMs > 0) {\n const interval = setInterval(() => {\n autoRefresh();\n }, refreshIntervalInMs);\n\n return (): void => clearInterval(interval);\n }\n }, [autoRefresh, refreshIntervalInMs]);\n\n const ctx = useMemo(() => {\n return {\n timeRange: timeRange,\n setTimeRange: handleSetTimeRange,\n absoluteTimeRange: absoluteTimeRange,\n refresh,\n refreshInterval: refreshInterval,\n refreshIntervalInMs: refreshIntervalInMs,\n setRefreshInterval: handleSetRefreshInterval,\n };\n }, [\n absoluteTimeRange,\n handleSetTimeRange,\n refresh,\n refreshInterval,\n refreshIntervalInMs,\n handleSetRefreshInterval,\n timeRange,\n ]);\n\n return <TimeRangeContext.Provider value={ctx}>{children}</TimeRangeContext.Provider>;\n}\n"],"names":["isRelativeTimeRange","toAbsoluteTimeRange","getSuggestedStepMs","useQueryClient","React","createContext","useCallback","useContext","useEffect","useMemo","useState","getRefreshIntervalInMs","useDisableAutoRefreshSetting","TimeRangeContext","undefined","useTimeRangeContext","ctx","Error","useTimeRange","useSuggestedStepMs","width","absoluteTimeRange","TimeRangeProvider","props","timeRange","refreshInterval","children","setTimeRange","setRefreshInterval","disableAutoRefresh","queryClient","setAbsoluteTimeRange","handleSetTimeRange","value","handleSetRefreshInterval","refresh","invalidateQueries","queryKey","finally","removeQueries","type","autoRefresh","refreshIntervalInMs","interval","setInterval","clearInterval","Provider"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/runtime/TimeRangeProvider/TimeRangeProvider.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 type { AbsoluteTimeRange, DurationString, TimeRangeValue } from '@perses-dev/spec';\nimport { isRelativeTimeRange, toAbsoluteTimeRange, getSuggestedStepMs } from '@perses-dev/spec';\nimport { useQueryClient } from '@tanstack/react-query';\nimport type { ReactElement } from 'react';\nimport React, { createContext, useCallback, useContext, useEffect, useMemo, useState } from 'react';\n\nimport { getRefreshIntervalInMs } from './refresh-interval';\nimport { useDisableAutoRefreshSetting } from './TimeRangeSettingsProvider';\n\nexport interface TimeRangeProviderProps {\n timeRange: TimeRangeValue;\n refreshInterval?: DurationString;\n setTimeRange: (value: TimeRangeValue) => void;\n setRefreshInterval: (value: DurationString) => void;\n children?: React.ReactNode;\n}\n\nexport interface TimeRange {\n timeRange: TimeRangeValue;\n absoluteTimeRange: AbsoluteTimeRange; // resolved absolute time for plugins to use\n setTimeRange: (value: TimeRangeValue) => void;\n refresh: () => void;\n refreshInterval?: DurationString;\n refreshIntervalInMs: number;\n setRefreshInterval: (value: DurationString) => void;\n}\n\nexport const TimeRangeContext = createContext<TimeRange | undefined>(undefined);\n\nexport function useTimeRangeContext(): TimeRange {\n const ctx = useContext(TimeRangeContext);\n if (ctx === undefined) {\n throw new Error('No TimeRangeContext found. Did you forget a Provider?');\n }\n return ctx;\n}\n\n/**\n * Get and set the current resolved time range at runtime.\n */\nexport function useTimeRange(): TimeRange {\n return useTimeRangeContext();\n}\n\n/**\n * Gets the suggested step for a graph query in ms for the currently selected time range.\n */\nexport function useSuggestedStepMs(width?: number): number {\n const { absoluteTimeRange } = useTimeRange();\n if (width === undefined) return 0;\n return getSuggestedStepMs(absoluteTimeRange, width);\n}\n\n/**\n * Provider implementation that supplies the time range state at runtime.\n */\nexport function TimeRangeProvider(props: TimeRangeProviderProps): ReactElement {\n const { timeRange, refreshInterval, children, setTimeRange, setRefreshInterval } = props;\n const disableAutoRefresh = useDisableAutoRefreshSetting();\n\n const queryClient = useQueryClient();\n const [absoluteTimeRange, setAbsoluteTimeRange] = useState<AbsoluteTimeRange>(\n isRelativeTimeRange(timeRange) ? toAbsoluteTimeRange(timeRange) : timeRange,\n );\n\n const handleSetTimeRange = useCallback(\n (value: TimeRangeValue) => {\n setTimeRange(value);\n setAbsoluteTimeRange(isRelativeTimeRange(value) ? toAbsoluteTimeRange(value) : value);\n },\n [setTimeRange],\n );\n\n // When auto-refresh is disabled by admin, leave URL/spec values untouched and no-op changes.\n const handleSetRefreshInterval = useCallback(\n (value: DurationString) => {\n if (disableAutoRefresh) {\n return;\n }\n setRefreshInterval(value);\n },\n [disableAutoRefresh, setRefreshInterval],\n );\n\n // Refresh is called when clicking on the refresh button, it refreshes all queries including variables\n const refresh = useCallback(() => {\n setAbsoluteTimeRange(isRelativeTimeRange(timeRange) ? toAbsoluteTimeRange(timeRange) : timeRange);\n queryClient\n .invalidateQueries({ queryKey: ['query'] })\n .finally(() => queryClient.removeQueries({ queryKey: ['query'], type: 'inactive' }));\n queryClient\n .invalidateQueries({ queryKey: ['variable'] })\n .finally(() => queryClient.removeQueries({ queryKey: ['variable'], type: 'inactive' }));\n queryClient\n .invalidateQueries({ queryKey: ['annotation'] })\n .finally(() => queryClient.removeQueries({ queryKey: ['annotation'], type: 'inactive' }));\n }, [queryClient, timeRange]);\n\n // Auto refresh is only refreshing queries of panels, including their annotations\n const autoRefresh = useCallback(() => {\n setAbsoluteTimeRange(isRelativeTimeRange(timeRange) ? toAbsoluteTimeRange(timeRange) : timeRange);\n queryClient.invalidateQueries({ queryKey: ['annotation'] }).finally(() => {\n queryClient.removeQueries({ queryKey: ['annotation'], type: 'inactive' });\n });\n queryClient.invalidateQueries({ queryKey: ['query'] }).finally(() => {\n queryClient.removeQueries({ queryKey: ['query'], type: 'inactive' });\n queryClient.removeQueries({ queryKey: ['variable'], type: 'inactive' }); // Timerange is in queryKey, can lead to memory leak when using relative timerange\n });\n }, [queryClient, timeRange]);\n\n // Gate the timer only — do not rewrite refreshInterval / ?refresh= so re-enabling restores them.\n const refreshIntervalInMs = useMemo(\n () => (disableAutoRefresh ? 0 : getRefreshIntervalInMs(refreshInterval)),\n [disableAutoRefresh, refreshInterval],\n );\n useEffect(() => {\n if (refreshIntervalInMs > 0) {\n const interval = setInterval(() => {\n autoRefresh();\n }, refreshIntervalInMs);\n\n return (): void => clearInterval(interval);\n }\n }, [autoRefresh, refreshIntervalInMs]);\n\n const ctx = useMemo(() => {\n return {\n timeRange: timeRange,\n setTimeRange: handleSetTimeRange,\n absoluteTimeRange: absoluteTimeRange,\n refresh,\n refreshInterval: refreshInterval,\n refreshIntervalInMs: refreshIntervalInMs,\n setRefreshInterval: handleSetRefreshInterval,\n };\n }, [\n absoluteTimeRange,\n handleSetTimeRange,\n refresh,\n refreshInterval,\n refreshIntervalInMs,\n handleSetRefreshInterval,\n timeRange,\n ]);\n\n return <TimeRangeContext.Provider value={ctx}>{children}</TimeRangeContext.Provider>;\n}\n"],"names":["isRelativeTimeRange","toAbsoluteTimeRange","getSuggestedStepMs","useQueryClient","React","createContext","useCallback","useContext","useEffect","useMemo","useState","getRefreshIntervalInMs","useDisableAutoRefreshSetting","TimeRangeContext","undefined","useTimeRangeContext","ctx","Error","useTimeRange","useSuggestedStepMs","width","absoluteTimeRange","TimeRangeProvider","props","timeRange","refreshInterval","children","setTimeRange","setRefreshInterval","disableAutoRefresh","queryClient","setAbsoluteTimeRange","handleSetTimeRange","value","handleSetRefreshInterval","refresh","invalidateQueries","queryKey","finally","removeQueries","type","autoRefresh","refreshIntervalInMs","interval","setInterval","clearInterval","Provider"],"mappings":"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"}
@@ -4,8 +4,10 @@ import React from 'react';
4
4
  export interface TimeRangeProvidersProps {
5
5
  initialTimeRange: TimeRangeValue;
6
6
  initialRefreshInterval?: DurationString;
7
+ /** Seed for useTimeZoneParams when URL ?tz= is absent (default: local). */
8
+ initialTimeZone?: string;
7
9
  children?: React.ReactNode;
8
10
  }
9
- export declare function TimeRangeProviderWithQueryParams({ initialTimeRange, initialRefreshInterval, children, }: TimeRangeProvidersProps): ReactElement;
11
+ export declare function TimeRangeProviderWithQueryParams({ initialTimeRange, initialRefreshInterval, initialTimeZone, children, }: TimeRangeProvidersProps): ReactElement;
10
12
  export declare function TimeRangeProviderBasic({ initialTimeRange, initialRefreshInterval, children, }: TimeRangeProvidersProps): ReactElement;
11
13
  //# sourceMappingURL=TimeRangeProviders.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"TimeRangeProviders.d.ts","sourceRoot":"","sources":["../../../src/runtime/TimeRangeProvider/TimeRangeProviders.tsx"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACvE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAC1C,OAAO,KAAK,MAAM,OAAO,CAAC;AAK1B,MAAM,WAAW,uBAAuB;IACtC,gBAAgB,EAAE,cAAc,CAAC;IACjC,sBAAsB,CAAC,EAAE,cAAc,CAAC;IACxC,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC5B;AAED,wBAAgB,gCAAgC,CAAC,EAC/C,gBAAgB,EAChB,sBAAsB,EACtB,QAAQ,GACT,EAAE,uBAAuB,GAAG,YAAY,CAexC;AAED,wBAAgB,sBAAsB,CAAC,EACrC,gBAAgB,EAChB,sBAAsB,EACtB,QAAQ,GACT,EAAE,uBAAuB,GAAG,YAAY,CAcxC"}
1
+ {"version":3,"file":"TimeRangeProviders.d.ts","sourceRoot":"","sources":["../../../src/runtime/TimeRangeProvider/TimeRangeProviders.tsx"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACvE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAC1C,OAAO,KAAK,MAAM,OAAO,CAAC;AAK1B,MAAM,WAAW,uBAAuB;IACtC,gBAAgB,EAAE,cAAc,CAAC;IACjC,sBAAsB,CAAC,EAAE,cAAc,CAAC;IACxC,2EAA2E;IAC3E,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC5B;AAED,wBAAgB,gCAAgC,CAAC,EAC/C,gBAAgB,EAChB,sBAAsB,EACtB,eAAyB,EACzB,QAAQ,GACT,EAAE,uBAAuB,GAAG,YAAY,CAexC;AAED,wBAAgB,sBAAsB,CAAC,EACrC,gBAAgB,EAChB,sBAAsB,EACtB,QAAQ,GACT,EAAE,uBAAuB,GAAG,YAAY,CAcxC"}
@@ -15,10 +15,10 @@ import { TimeZoneProvider } from "@perses-dev/components";
15
15
  import React from "react";
16
16
  import { useSetRefreshIntervalParams, useTimeRangeParams, useTimeZoneParams } from "./query-params.js";
17
17
  import { TimeRangeProvider } from "./TimeRangeProvider.js";
18
- export function TimeRangeProviderWithQueryParams({ initialTimeRange, initialRefreshInterval, children }) {
18
+ export function TimeRangeProviderWithQueryParams({ initialTimeRange, initialRefreshInterval, initialTimeZone = 'local', children }) {
19
19
  const { timeRange, setTimeRange } = useTimeRangeParams(initialTimeRange);
20
20
  const { refreshInterval, setRefreshInterval } = useSetRefreshIntervalParams(initialRefreshInterval);
21
- const { timeZone } = useTimeZoneParams('local');
21
+ const { timeZone } = useTimeZoneParams(initialTimeZone);
22
22
  return /*#__PURE__*/ _jsx(TimeRangeProvider, {
23
23
  timeRange: timeRange,
24
24
  refreshInterval: refreshInterval,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/runtime/TimeRangeProvider/TimeRangeProviders.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 { TimeZoneProvider } from '@perses-dev/components';\nimport type { DurationString, TimeRangeValue } from '@perses-dev/spec';\nimport type { ReactElement } from 'react';\nimport React from 'react';\n\nimport { useSetRefreshIntervalParams, useTimeRangeParams, useTimeZoneParams } from './query-params';\nimport { TimeRangeProvider } from './TimeRangeProvider';\n\nexport interface TimeRangeProvidersProps {\n initialTimeRange: TimeRangeValue;\n initialRefreshInterval?: DurationString;\n children?: React.ReactNode;\n}\n\nexport function TimeRangeProviderWithQueryParams({\n initialTimeRange,\n initialRefreshInterval,\n children,\n}: TimeRangeProvidersProps): ReactElement {\n const { timeRange, setTimeRange } = useTimeRangeParams(initialTimeRange);\n const { refreshInterval, setRefreshInterval } = useSetRefreshIntervalParams(initialRefreshInterval);\n const { timeZone } = useTimeZoneParams('local');\n\n return (\n <TimeRangeProvider\n timeRange={timeRange}\n refreshInterval={refreshInterval}\n setTimeRange={setTimeRange}\n setRefreshInterval={setRefreshInterval}\n >\n <TimeZoneProvider timeZone={timeZone}>{children}</TimeZoneProvider>\n </TimeRangeProvider>\n );\n}\n\nexport function TimeRangeProviderBasic({\n initialTimeRange,\n initialRefreshInterval,\n children,\n}: TimeRangeProvidersProps): ReactElement {\n const [timeRange, setTimeRange] = React.useState<TimeRangeValue>(initialTimeRange);\n const [refreshInterval, setRefreshInterval] = React.useState<DurationString | undefined>(initialRefreshInterval);\n\n return (\n <TimeRangeProvider\n timeRange={timeRange}\n refreshInterval={refreshInterval}\n setTimeRange={setTimeRange}\n setRefreshInterval={setRefreshInterval}\n >\n {children}\n </TimeRangeProvider>\n );\n}\n"],"names":["TimeZoneProvider","React","useSetRefreshIntervalParams","useTimeRangeParams","useTimeZoneParams","TimeRangeProvider","TimeRangeProviderWithQueryParams","initialTimeRange","initialRefreshInterval","children","timeRange","setTimeRange","refreshInterval","setRefreshInterval","timeZone","TimeRangeProviderBasic","useState"],"mappings":";AAAA,+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,gBAAgB,QAAQ,yBAAyB;AAG1D,OAAOC,WAAW,QAAQ;AAE1B,SAASC,2BAA2B,EAAEC,kBAAkB,EAAEC,iBAAiB,QAAQ,oBAAiB;AACpG,SAASC,iBAAiB,QAAQ,yBAAsB;AAQxD,OAAO,SAASC,iCAAiC,EAC/CC,gBAAgB,EAChBC,sBAAsB,EACtBC,QAAQ,EACgB;IACxB,MAAM,EAAEC,SAAS,EAAEC,YAAY,EAAE,GAAGR,mBAAmBI;IACvD,MAAM,EAAEK,eAAe,EAAEC,kBAAkB,EAAE,GAAGX,4BAA4BM;IAC5E,MAAM,EAAEM,QAAQ,EAAE,GAAGV,kBAAkB;IAEvC,qBACE,KAACC;QACCK,WAAWA;QACXE,iBAAiBA;QACjBD,cAAcA;QACdE,oBAAoBA;kBAEpB,cAAA,KAACb;YAAiBc,UAAUA;sBAAWL;;;AAG7C;AAEA,OAAO,SAASM,uBAAuB,EACrCR,gBAAgB,EAChBC,sBAAsB,EACtBC,QAAQ,EACgB;IACxB,MAAM,CAACC,WAAWC,aAAa,GAAGV,MAAMe,QAAQ,CAAiBT;IACjE,MAAM,CAACK,iBAAiBC,mBAAmB,GAAGZ,MAAMe,QAAQ,CAA6BR;IAEzF,qBACE,KAACH;QACCK,WAAWA;QACXE,iBAAiBA;QACjBD,cAAcA;QACdE,oBAAoBA;kBAEnBJ;;AAGP"}
1
+ {"version":3,"sources":["../../../src/runtime/TimeRangeProvider/TimeRangeProviders.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 { TimeZoneProvider } from '@perses-dev/components';\nimport type { DurationString, TimeRangeValue } from '@perses-dev/spec';\nimport type { ReactElement } from 'react';\nimport React from 'react';\n\nimport { useSetRefreshIntervalParams, useTimeRangeParams, useTimeZoneParams } from './query-params';\nimport { TimeRangeProvider } from './TimeRangeProvider';\n\nexport interface TimeRangeProvidersProps {\n initialTimeRange: TimeRangeValue;\n initialRefreshInterval?: DurationString;\n /** Seed for useTimeZoneParams when URL ?tz= is absent (default: local). */\n initialTimeZone?: string;\n children?: React.ReactNode;\n}\n\nexport function TimeRangeProviderWithQueryParams({\n initialTimeRange,\n initialRefreshInterval,\n initialTimeZone = 'local',\n children,\n}: TimeRangeProvidersProps): ReactElement {\n const { timeRange, setTimeRange } = useTimeRangeParams(initialTimeRange);\n const { refreshInterval, setRefreshInterval } = useSetRefreshIntervalParams(initialRefreshInterval);\n const { timeZone } = useTimeZoneParams(initialTimeZone);\n\n return (\n <TimeRangeProvider\n timeRange={timeRange}\n refreshInterval={refreshInterval}\n setTimeRange={setTimeRange}\n setRefreshInterval={setRefreshInterval}\n >\n <TimeZoneProvider timeZone={timeZone}>{children}</TimeZoneProvider>\n </TimeRangeProvider>\n );\n}\n\nexport function TimeRangeProviderBasic({\n initialTimeRange,\n initialRefreshInterval,\n children,\n}: TimeRangeProvidersProps): ReactElement {\n const [timeRange, setTimeRange] = React.useState<TimeRangeValue>(initialTimeRange);\n const [refreshInterval, setRefreshInterval] = React.useState<DurationString | undefined>(initialRefreshInterval);\n\n return (\n <TimeRangeProvider\n timeRange={timeRange}\n refreshInterval={refreshInterval}\n setTimeRange={setTimeRange}\n setRefreshInterval={setRefreshInterval}\n >\n {children}\n </TimeRangeProvider>\n );\n}\n"],"names":["TimeZoneProvider","React","useSetRefreshIntervalParams","useTimeRangeParams","useTimeZoneParams","TimeRangeProvider","TimeRangeProviderWithQueryParams","initialTimeRange","initialRefreshInterval","initialTimeZone","children","timeRange","setTimeRange","refreshInterval","setRefreshInterval","timeZone","TimeRangeProviderBasic","useState"],"mappings":";AAAA,+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,gBAAgB,QAAQ,yBAAyB;AAG1D,OAAOC,WAAW,QAAQ;AAE1B,SAASC,2BAA2B,EAAEC,kBAAkB,EAAEC,iBAAiB,QAAQ,oBAAiB;AACpG,SAASC,iBAAiB,QAAQ,yBAAsB;AAUxD,OAAO,SAASC,iCAAiC,EAC/CC,gBAAgB,EAChBC,sBAAsB,EACtBC,kBAAkB,OAAO,EACzBC,QAAQ,EACgB;IACxB,MAAM,EAAEC,SAAS,EAAEC,YAAY,EAAE,GAAGT,mBAAmBI;IACvD,MAAM,EAAEM,eAAe,EAAEC,kBAAkB,EAAE,GAAGZ,4BAA4BM;IAC5E,MAAM,EAAEO,QAAQ,EAAE,GAAGX,kBAAkBK;IAEvC,qBACE,KAACJ;QACCM,WAAWA;QACXE,iBAAiBA;QACjBD,cAAcA;QACdE,oBAAoBA;kBAEpB,cAAA,KAACd;YAAiBe,UAAUA;sBAAWL;;;AAG7C;AAEA,OAAO,SAASM,uBAAuB,EACrCT,gBAAgB,EAChBC,sBAAsB,EACtBE,QAAQ,EACgB;IACxB,MAAM,CAACC,WAAWC,aAAa,GAAGX,MAAMgB,QAAQ,CAAiBV;IACjE,MAAM,CAACM,iBAAiBC,mBAAmB,GAAGb,MAAMgB,QAAQ,CAA6BT;IAEzF,qBACE,KAACH;QACCM,WAAWA;QACXE,iBAAiBA;QACjBD,cAAcA;QACdE,oBAAoBA;kBAEnBJ;;AAGP"}
@@ -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
  ]);