@perses-dev/plugin-system 0.8.0 → 0.9.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 (149) hide show
  1. package/dist/cjs/components/PluginRegistry/PluginRegistry.js +43 -29
  2. package/dist/cjs/components/PluginRegistry/PluginRegistry.test.js +114 -38
  3. package/dist/cjs/components/PluginRegistry/index.js +17 -18
  4. package/dist/cjs/components/PluginRegistry/plugin-indexes.js +23 -20
  5. package/dist/cjs/components/PluginRegistry/plugin-registry-model.js +17 -7
  6. package/dist/cjs/components/PluginRegistry/test-plugins/bert/index.js +22 -12
  7. package/dist/cjs/components/PluginRegistry/test-plugins/ernie/index.js +20 -8
  8. package/dist/cjs/components/PluginRegistry/test-plugins/index.js +59 -39
  9. package/dist/cjs/components/index.js +17 -20
  10. package/dist/cjs/index.js +19 -20
  11. package/dist/cjs/model/datasource.js +16 -0
  12. package/dist/cjs/model/index.js +21 -21
  13. package/dist/cjs/model/panels.js +4 -21
  14. package/dist/cjs/model/plugins.js +4 -7
  15. package/dist/cjs/model/time-series-queries.js +16 -0
  16. package/dist/cjs/model/variables.js +5 -17
  17. package/dist/cjs/model/visual-editing.js +10 -2
  18. package/dist/cjs/runtime/datasources.js +20 -13
  19. package/dist/cjs/runtime/index.js +22 -21
  20. package/dist/cjs/runtime/plugins.js +25 -22
  21. package/dist/cjs/runtime/query-string.js +17 -10
  22. package/dist/cjs/runtime/template-variables.js +34 -16
  23. package/dist/cjs/runtime/time-range.js +17 -10
  24. package/dist/cjs/runtime/time-series-queries.js +58 -0
  25. package/dist/cjs/test/render.js +32 -13
  26. package/dist/cjs/test/setup-tests.js +4 -10
  27. package/dist/cjs/utils/cache-keys.js +8 -7
  28. package/dist/components/PluginRegistry/PluginRegistry.js +81 -1
  29. package/dist/components/PluginRegistry/PluginRegistry.js.map +1 -0
  30. package/dist/components/PluginRegistry/PluginRegistry.test.js +142 -1
  31. package/dist/components/PluginRegistry/PluginRegistry.test.js.map +1 -0
  32. package/dist/components/PluginRegistry/index.js +16 -1
  33. package/dist/components/PluginRegistry/index.js.map +1 -0
  34. package/dist/components/PluginRegistry/plugin-indexes.js +66 -1
  35. package/dist/components/PluginRegistry/plugin-indexes.js.map +1 -0
  36. package/dist/components/PluginRegistry/plugin-registry-model.d.ts +1 -2
  37. package/dist/components/PluginRegistry/plugin-registry-model.d.ts.map +1 -1
  38. package/dist/components/PluginRegistry/plugin-registry-model.js +23 -1
  39. package/dist/components/PluginRegistry/plugin-registry-model.js.map +1 -0
  40. package/dist/components/PluginRegistry/test-plugins/bert/index.js +25 -1
  41. package/dist/components/PluginRegistry/test-plugins/bert/index.js.map +1 -0
  42. package/dist/components/PluginRegistry/test-plugins/ernie/index.d.ts.map +1 -1
  43. package/dist/components/PluginRegistry/test-plugins/ernie/index.js +30 -1
  44. package/dist/components/PluginRegistry/test-plugins/ernie/index.js.map +1 -0
  45. package/dist/components/PluginRegistry/test-plugins/index.js +35 -1
  46. package/dist/components/PluginRegistry/test-plugins/index.js.map +1 -0
  47. package/dist/components/index.d.ts +1 -3
  48. package/dist/components/index.d.ts.map +1 -1
  49. package/dist/components/index.js +15 -1
  50. package/dist/components/index.js.map +1 -0
  51. package/dist/index.js +17 -1
  52. package/dist/index.js.map +1 -0
  53. package/dist/model/datasource.d.ts +9 -0
  54. package/dist/model/datasource.d.ts.map +1 -0
  55. package/dist/model/datasource.js +15 -0
  56. package/dist/model/datasource.js.map +1 -0
  57. package/dist/model/index.d.ts +2 -1
  58. package/dist/model/index.d.ts.map +1 -1
  59. package/dist/model/index.js +20 -1
  60. package/dist/model/index.js.map +1 -0
  61. package/dist/model/panels.d.ts +7 -11
  62. package/dist/model/panels.d.ts.map +1 -1
  63. package/dist/model/panels.js +15 -1
  64. package/dist/model/panels.js.map +1 -0
  65. package/dist/model/plugins.d.ts +16 -25
  66. package/dist/model/plugins.d.ts.map +1 -1
  67. package/dist/model/plugins.js +15 -1
  68. package/dist/model/plugins.js.map +1 -0
  69. package/dist/model/time-series-queries.d.ts +28 -0
  70. package/dist/model/time-series-queries.d.ts.map +1 -0
  71. package/dist/model/time-series-queries.js +15 -0
  72. package/dist/model/time-series-queries.js.map +1 -0
  73. package/dist/model/variables.d.ts +16 -11
  74. package/dist/model/variables.d.ts.map +1 -1
  75. package/dist/model/variables.js +15 -1
  76. package/dist/model/variables.js.map +1 -0
  77. package/dist/model/visual-editing.d.ts +5 -6
  78. package/dist/model/visual-editing.d.ts.map +1 -1
  79. package/dist/model/visual-editing.js +15 -1
  80. package/dist/model/visual-editing.js.map +1 -0
  81. package/dist/runtime/datasources.d.ts +5 -9
  82. package/dist/runtime/datasources.d.ts.map +1 -1
  83. package/dist/runtime/datasources.js +23 -1
  84. package/dist/runtime/datasources.js.map +1 -0
  85. package/dist/runtime/index.d.ts +3 -1
  86. package/dist/runtime/index.d.ts.map +1 -1
  87. package/dist/runtime/index.js +20 -1
  88. package/dist/runtime/index.js.map +1 -0
  89. package/dist/runtime/plugins.d.ts +5 -14
  90. package/dist/runtime/plugins.d.ts.map +1 -1
  91. package/dist/runtime/plugins.js +33 -1
  92. package/dist/runtime/plugins.js.map +1 -0
  93. package/dist/runtime/query-string.js +25 -1
  94. package/dist/runtime/query-string.js.map +1 -0
  95. package/dist/runtime/template-variables.d.ts +10 -1
  96. package/dist/runtime/template-variables.d.ts.map +1 -1
  97. package/dist/runtime/template-variables.js +44 -1
  98. package/dist/runtime/template-variables.js.map +1 -0
  99. package/dist/runtime/time-range.js +25 -1
  100. package/dist/runtime/time-range.js.map +1 -0
  101. package/dist/runtime/time-series-queries.d.ts +14 -0
  102. package/dist/runtime/time-series-queries.d.ts.map +1 -0
  103. package/dist/runtime/time-series-queries.js +54 -0
  104. package/dist/runtime/time-series-queries.js.map +1 -0
  105. package/dist/test/render.d.ts.map +1 -1
  106. package/dist/test/render.js +42 -1
  107. package/dist/test/render.js.map +1 -0
  108. package/dist/test/setup-tests.d.ts.map +1 -1
  109. package/dist/test/setup-tests.js +16 -1
  110. package/dist/test/setup-tests.js.map +1 -0
  111. package/dist/utils/cache-keys.js +19 -1
  112. package/dist/utils/cache-keys.js.map +1 -0
  113. package/package.json +11 -8
  114. package/dist/cjs/components/PluginBoundary.js +0 -14
  115. package/dist/cjs/components/PluginLoadingBoundary/PluginLoader.js +0 -39
  116. package/dist/cjs/components/PluginLoadingBoundary/PluginLoadingBoundary.js +0 -85
  117. package/dist/cjs/components/PluginLoadingBoundary/index.js +0 -29
  118. package/dist/cjs/components/PluginRegistry/legacy/PluginRegistry.js +0 -57
  119. package/dist/cjs/components/PluginRegistry/legacy/index.js +0 -29
  120. package/dist/cjs/components/PluginRegistry/legacy/registry-state.js +0 -97
  121. package/dist/cjs/components/PluginRegistry/test-plugins/bert/plugin.json +0 -32
  122. package/dist/cjs/components/PluginRegistry/test-plugins/ernie/plugin.json +0 -24
  123. package/dist/cjs/model/graph-queries.js +0 -28
  124. package/dist/components/PluginBoundary.d.ts +0 -13
  125. package/dist/components/PluginBoundary.d.ts.map +0 -1
  126. package/dist/components/PluginBoundary.js +0 -1
  127. package/dist/components/PluginLoadingBoundary/PluginLoader.d.ts +0 -11
  128. package/dist/components/PluginLoadingBoundary/PluginLoader.d.ts.map +0 -1
  129. package/dist/components/PluginLoadingBoundary/PluginLoader.js +0 -1
  130. package/dist/components/PluginLoadingBoundary/PluginLoadingBoundary.d.ts +0 -27
  131. package/dist/components/PluginLoadingBoundary/PluginLoadingBoundary.d.ts.map +0 -1
  132. package/dist/components/PluginLoadingBoundary/PluginLoadingBoundary.js +0 -1
  133. package/dist/components/PluginLoadingBoundary/index.d.ts +0 -2
  134. package/dist/components/PluginLoadingBoundary/index.d.ts.map +0 -1
  135. package/dist/components/PluginLoadingBoundary/index.js +0 -1
  136. package/dist/components/PluginRegistry/legacy/PluginRegistry.d.ts +0 -29
  137. package/dist/components/PluginRegistry/legacy/PluginRegistry.d.ts.map +0 -1
  138. package/dist/components/PluginRegistry/legacy/PluginRegistry.js +0 -1
  139. package/dist/components/PluginRegistry/legacy/index.d.ts +0 -2
  140. package/dist/components/PluginRegistry/legacy/index.d.ts.map +0 -1
  141. package/dist/components/PluginRegistry/legacy/index.js +0 -1
  142. package/dist/components/PluginRegistry/legacy/registry-state.d.ts +0 -18
  143. package/dist/components/PluginRegistry/legacy/registry-state.d.ts.map +0 -1
  144. package/dist/components/PluginRegistry/legacy/registry-state.js +0 -1
  145. package/dist/components/PluginRegistry/test-plugins/bert/plugin.json +0 -32
  146. package/dist/components/PluginRegistry/test-plugins/ernie/plugin.json +0 -24
  147. package/dist/model/graph-queries.d.ts +0 -36
  148. package/dist/model/graph-queries.d.ts.map +0 -1
  149. package/dist/model/graph-queries.js +0 -1
@@ -1,5 +1,4 @@
1
- "use strict";
2
- // Copyright 2021 The Perses Authors
1
+ // Copyright 2022 The Perses Authors
3
2
  // Licensed under the Apache License, Version 2.0 (the "License");
4
3
  // you may not use this file except in compliance with the License.
5
4
  // You may obtain a copy of the License at
@@ -11,29 +10,48 @@
11
10
  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
11
  // See the License for the specific language governing permissions and
13
12
  // limitations under the License.
14
- Object.defineProperty(exports, "__esModule", { value: true });
15
- exports.useTemplateVariableValues = exports.TemplateVariableContext = void 0;
16
- const react_1 = require("react");
17
- exports.TemplateVariableContext = (0, react_1.createContext)(undefined);
13
+ "use strict";
14
+ Object.defineProperty(exports, "__esModule", {
15
+ value: true
16
+ });
17
+ function _export(target, all) {
18
+ for(var name in all)Object.defineProperty(target, name, {
19
+ enumerable: true,
20
+ get: all[name]
21
+ });
22
+ }
23
+ _export(exports, {
24
+ DEFAULT_ALL_VALUE: ()=>DEFAULT_ALL_VALUE,
25
+ TemplateVariableContext: ()=>TemplateVariableContext,
26
+ useTemplateVariableValues: ()=>useTemplateVariableValues
27
+ });
28
+ const _react = require("react");
29
+ const DEFAULT_ALL_VALUE = '$__all';
30
+ const TemplateVariableContext = (0, _react.createContext)(undefined);
18
31
  function useTemplateVariableContext() {
19
- const ctx = (0, react_1.useContext)(exports.TemplateVariableContext);
32
+ const ctx = (0, _react.useContext)(TemplateVariableContext);
20
33
  if (ctx === undefined) {
21
34
  throw new Error('No TemplateVariableContext found. Did you forget a Provider?');
22
35
  }
23
36
  return ctx;
24
37
  }
25
38
  function useTemplateVariableValues(names) {
26
- const { state } = useTemplateVariableContext();
39
+ const { state } = useTemplateVariableContext();
40
+ const values = (0, _react.useMemo)(()=>{
41
+ const values = {};
42
+ names === null || names === void 0 ? void 0 : names.forEach((name)=>{
43
+ const s = state[name];
44
+ if (s) {
45
+ values[name] = s;
46
+ }
47
+ });
48
+ return values;
49
+ }, [
50
+ state,
51
+ names
52
+ ]);
27
53
  if (names === undefined) {
28
54
  return state;
29
55
  }
30
- const values = {};
31
- names.forEach((name) => {
32
- const s = state[name];
33
- if (s) {
34
- values[name] = s;
35
- }
36
- });
37
56
  return values;
38
57
  }
39
- exports.useTemplateVariableValues = useTemplateVariableValues;
@@ -1,4 +1,3 @@
1
- "use strict";
2
1
  // Copyright 2022 The Perses Authors
3
2
  // Licensed under the Apache License, Version 2.0 (the "License");
4
3
  // you may not use this file except in compliance with the License.
@@ -11,18 +10,26 @@
11
10
  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
11
  // See the License for the specific language governing permissions and
13
12
  // limitations under the License.
14
- Object.defineProperty(exports, "__esModule", { value: true });
15
- exports.useTimeRange = exports.TimeRangeContext = void 0;
16
- const react_1 = require("react");
17
- exports.TimeRangeContext = (0, react_1.createContext)(undefined);
18
- /**
19
- * Gets the current TimeRange at runtime.
20
- */
13
+ "use strict";
14
+ Object.defineProperty(exports, "__esModule", {
15
+ value: true
16
+ });
17
+ function _export(target, all) {
18
+ for(var name in all)Object.defineProperty(target, name, {
19
+ enumerable: true,
20
+ get: all[name]
21
+ });
22
+ }
23
+ _export(exports, {
24
+ TimeRangeContext: ()=>TimeRangeContext,
25
+ useTimeRange: ()=>useTimeRange
26
+ });
27
+ const _react = require("react");
28
+ const TimeRangeContext = (0, _react.createContext)(undefined);
21
29
  function useTimeRange() {
22
- const ctx = (0, react_1.useContext)(exports.TimeRangeContext);
30
+ const ctx = (0, _react.useContext)(TimeRangeContext);
23
31
  if (ctx === undefined) {
24
32
  throw new Error('No TimeRangeContext found. Did you forget a Provider?');
25
33
  }
26
34
  return ctx;
27
35
  }
28
- exports.useTimeRange = useTimeRange;
@@ -0,0 +1,58 @@
1
+ // Copyright 2022 The Perses Authors
2
+ // Licensed under the Apache License, Version 2.0 (the "License");
3
+ // you may not use this file except in compliance with the License.
4
+ // You may obtain a copy of the License at
5
+ //
6
+ // http://www.apache.org/licenses/LICENSE-2.0
7
+ //
8
+ // Unless required by applicable law or agreed to in writing, software
9
+ // distributed under the License is distributed on an "AS IS" BASIS,
10
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+ // See the License for the specific language governing permissions and
12
+ // limitations under the License.
13
+ "use strict";
14
+ Object.defineProperty(exports, "__esModule", {
15
+ value: true
16
+ });
17
+ Object.defineProperty(exports, "useTimeSeriesQueryData", {
18
+ enumerable: true,
19
+ get: ()=>useTimeSeriesQueryData
20
+ });
21
+ const _reactQuery = require("@tanstack/react-query");
22
+ const _templateVariables = require("./template-variables");
23
+ const _timeRange = require("./time-range");
24
+ const _plugins = require("./plugins");
25
+ const _datasources = require("./datasources");
26
+ const useTimeSeriesQueryData = (definition, options)=>{
27
+ const { data: plugin } = (0, _plugins.usePlugin)('TimeSeriesQuery', definition.spec.plugin.kind);
28
+ // Build the context object from data available at runtime
29
+ const { timeRange } = (0, _timeRange.useTimeRange)();
30
+ const variableState = (0, _templateVariables.useTemplateVariableValues)();
31
+ const datasourceStore = (0, _datasources.useDatasourceStore)();
32
+ const context = {
33
+ suggestedStepMs: options === null || options === void 0 ? void 0 : options.suggestedStepMs,
34
+ timeRange,
35
+ variableState,
36
+ datasourceStore
37
+ };
38
+ const key = [
39
+ definition,
40
+ context
41
+ ];
42
+ const { data , isLoading , error } = (0, _reactQuery.useQuery)(key, ({ queryKey })=>{
43
+ // The 'enabled' option should prevent this from happening, but make TypeScript happy by checking
44
+ if (plugin === undefined) {
45
+ throw new Error('Expected plugin to be loaded');
46
+ }
47
+ const [definition, context] = queryKey;
48
+ return plugin.getTimeSeriesData(definition.spec.plugin.spec, context);
49
+ }, {
50
+ enabled: plugin !== undefined
51
+ });
52
+ // TODO: Stop aliasing fields, just return the hook results directly once we clean up query running in panels
53
+ return {
54
+ data,
55
+ loading: isLoading,
56
+ error: error !== null && error !== void 0 ? error : undefined
57
+ };
58
+ };
@@ -1,7 +1,3 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.renderWithContext = void 0;
4
- const jsx_runtime_1 = require("react/jsx-runtime");
5
1
  // Copyright 2022 The Perses Authors
6
2
  // Licensed under the Apache License, Version 2.0 (the "License");
7
3
  // you may not use this file except in compliance with the License.
@@ -14,14 +10,37 @@ const jsx_runtime_1 = require("react/jsx-runtime");
14
10
  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
11
  // See the License for the specific language governing permissions and
16
12
  // limitations under the License.
17
- const react_1 = require("@testing-library/react");
18
- const react_query_1 = require("react-query");
19
- // Don't retry in tests
20
- const queryClient = new react_query_1.QueryClient({ defaultOptions: { queries: { refetchOnWindowFocus: false, retry: false } } });
21
- /**
22
- * Test helper to render a React component with some common app-level providers wrapped around it.
23
- */
13
+ "use strict";
14
+ Object.defineProperty(exports, "__esModule", {
15
+ value: true
16
+ });
17
+ Object.defineProperty(exports, "renderWithContext", {
18
+ enumerable: true,
19
+ get: ()=>renderWithContext
20
+ });
21
+ const _jsxRuntime = require("react/jsx-runtime");
22
+ const _react = require("@testing-library/react");
23
+ const _reactQuery = require("@tanstack/react-query");
24
+ const testLogger = {
25
+ log: console.log,
26
+ warn: console.warn,
27
+ error: ()=>{
28
+ // Don't log network errors in tests to the console
29
+ }
30
+ };
24
31
  function renderWithContext(ui, options) {
25
- return (0, react_1.render)((0, jsx_runtime_1.jsx)(react_query_1.QueryClientProvider, { client: queryClient, children: ui }), options);
32
+ // Create a new QueryClient for each test to avoid caching issues
33
+ const queryClient = new _reactQuery.QueryClient({
34
+ defaultOptions: {
35
+ queries: {
36
+ refetchOnWindowFocus: false,
37
+ retry: false
38
+ }
39
+ },
40
+ logger: testLogger
41
+ });
42
+ return (0, _react.render)(/*#__PURE__*/ (0, _jsxRuntime.jsx)(_reactQuery.QueryClientProvider, {
43
+ client: queryClient,
44
+ children: ui
45
+ }), options);
26
46
  }
27
- exports.renderWithContext = renderWithContext;
@@ -1,4 +1,3 @@
1
- "use strict";
2
1
  // Copyright 2022 The Perses Authors
3
2
  // Licensed under the Apache License, Version 2.0 (the "License");
4
3
  // you may not use this file except in compliance with the License.
@@ -11,14 +10,9 @@
11
10
  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
11
  // See the License for the specific language governing permissions and
13
12
  // limitations under the License.
14
- Object.defineProperty(exports, "__esModule", { value: true });
15
- const react_query_1 = require("react-query");
16
13
  // Add testing library assertions
17
- require("@testing-library/jest-dom/extend-expect");
18
- (0, react_query_1.setLogger)({
19
- log: console.log,
20
- warn: console.warn,
21
- error: () => {
22
- // Don't log network errors to the console during tests
23
- },
14
+ "use strict";
15
+ Object.defineProperty(exports, "__esModule", {
16
+ value: true
24
17
  });
18
+ require("@testing-library/jest-dom/extend-expect");
@@ -1,4 +1,3 @@
1
- "use strict";
2
1
  // Copyright 2022 The Perses Authors
3
2
  // Licensed under the Apache License, Version 2.0 (the "License");
4
3
  // you may not use this file except in compliance with the License.
@@ -11,12 +10,14 @@
11
10
  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
11
  // See the License for the specific language governing permissions and
13
12
  // limitations under the License.
14
- Object.defineProperty(exports, "__esModule", { value: true });
15
- exports.getTypeAndKindKey = void 0;
16
- /**
17
- * Gets a unique key for a plugin type/kind that can be used as a cache key.
18
- */
13
+ "use strict";
14
+ Object.defineProperty(exports, "__esModule", {
15
+ value: true
16
+ });
17
+ Object.defineProperty(exports, "getTypeAndKindKey", {
18
+ enumerable: true,
19
+ get: ()=>getTypeAndKindKey
20
+ });
19
21
  function getTypeAndKindKey(pluginType, kind) {
20
22
  return `${pluginType}:${kind}`;
21
23
  }
22
- exports.getTypeAndKindKey = getTypeAndKindKey;
@@ -1 +1,81 @@
1
- import{jsx as _jsx}from"react/jsx-runtime";import{useEvent}from"@perses-dev/core";import{useRef,useCallback,useMemo}from"react";import{getTypeAndKindKey}from"../../utils/cache-keys";import{usePluginIndexes}from"./plugin-indexes";import{PluginRegistryContext}from"./plugin-registry-model";export function PluginRegistry(e){const{getInstalledPlugins:t,importPluginModule:n,children:r}=e,i=usePluginIndexes(t),s=useRef(new Map),u=useEvent((e=>{let t=s.current.get(e);return void 0===t&&(t=n(e),s.current.set(e,t),t.catch((()=>s.current.delete(e)))),t})),o=useCallback((async(e,t)=>{const n=await i(),r=getTypeAndKindKey(e,t),s=n.pluginResourcesByTypeAndKind.get(r);if(void 0===s)throw new Error(`A ${e} plugin for kind '${t}' is not installed`);const o=(await u(s))[t];if(void 0===o)throw new Error(`The ${e} plugin for kind '${t}' is missing from the ${s.metadata.name} plugin module`);return o}),[i,u]),l=useCallback((async e=>{var t;return null!==(t=(await i()).pluginMetadataByType.get(e))&&void 0!==t?t:[]}),[i]),a=useMemo((()=>({getPlugin:o,listPluginMetadata:l})),[o,l]);return _jsx(PluginRegistryContext.Provider,{value:a,children:r})}
1
+ // Copyright 2022 The Perses Authors
2
+ // Licensed under the Apache License, Version 2.0 (the "License");
3
+ // you may not use this file except in compliance with the License.
4
+ // You may obtain a copy of the License at
5
+ //
6
+ // http://www.apache.org/licenses/LICENSE-2.0
7
+ //
8
+ // Unless required by applicable law or agreed to in writing, software
9
+ // distributed under the License is distributed on an "AS IS" BASIS,
10
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+ // See the License for the specific language governing permissions and
12
+ // limitations under the License.
13
+ import { jsx as _jsx } from "react/jsx-runtime";
14
+ import { useEvent } from '@perses-dev/core';
15
+ import { useRef, useCallback, useMemo } from 'react';
16
+ import { getTypeAndKindKey } from '../../utils/cache-keys';
17
+ import { usePluginIndexes } from './plugin-indexes';
18
+ import { PluginRegistryContext } from './plugin-registry-model';
19
+ /**
20
+ * PluginRegistryContext provider that keeps track of all available plugins and provides an API for getting them or
21
+ * querying the metadata about them.
22
+ */ export function PluginRegistry(props) {
23
+ const { getInstalledPlugins , importPluginModule , children } = props;
24
+ const getPluginIndexes = usePluginIndexes(getInstalledPlugins);
25
+ // De-dupe calls to import plugin modules
26
+ const importCache = useRef(new Map());
27
+ // Do useEvent here since this accesses the importPluginModule prop and we want a stable reference to it for the
28
+ // callback below
29
+ const loadPluginModule = useEvent((resource)=>{
30
+ let request = importCache.current.get(resource);
31
+ if (request === undefined) {
32
+ request = importPluginModule(resource);
33
+ importCache.current.set(resource, request);
34
+ // Remove failed requests from the cache so they can potentially be retried
35
+ request.catch(()=>importCache.current.delete(resource));
36
+ }
37
+ return request;
38
+ });
39
+ const getPlugin = useCallback(async (pluginType, kind)=>{
40
+ // Get the indexes of the installed plugins
41
+ const pluginIndexes = await getPluginIndexes();
42
+ // Figure out what module the plugin is in by looking in the index
43
+ const typeAndKindKey = getTypeAndKindKey(pluginType, kind);
44
+ const resource = pluginIndexes.pluginResourcesByTypeAndKind.get(typeAndKindKey);
45
+ if (resource === undefined) {
46
+ throw new Error(`A ${pluginType} plugin for kind '${kind}' is not installed`);
47
+ }
48
+ // Treat the plugin module as a bunch of named exports that have plugins
49
+ const pluginModule = await loadPluginModule(resource);
50
+ // We currently assume that plugin modules will have named exports that match the kinds they handle
51
+ const plugin = pluginModule[kind];
52
+ if (plugin === undefined) {
53
+ throw new Error(`The ${pluginType} plugin for kind '${kind}' is missing from the ${resource.metadata.name} plugin module`);
54
+ }
55
+ return plugin;
56
+ }, [
57
+ getPluginIndexes,
58
+ loadPluginModule
59
+ ]);
60
+ const listPluginMetadata = useCallback(async (pluginType)=>{
61
+ const pluginIndexes = await getPluginIndexes();
62
+ var ref;
63
+ return (ref = pluginIndexes.pluginMetadataByType.get(pluginType)) !== null && ref !== void 0 ? ref : [];
64
+ }, [
65
+ getPluginIndexes
66
+ ]);
67
+ // Create the registry's context value and render
68
+ const context = useMemo(()=>({
69
+ getPlugin,
70
+ listPluginMetadata
71
+ }), [
72
+ getPlugin,
73
+ listPluginMetadata
74
+ ]);
75
+ return /*#__PURE__*/ _jsx(PluginRegistryContext.Provider, {
76
+ value: context,
77
+ children: children
78
+ });
79
+ }
80
+
81
+ //# sourceMappingURL=PluginRegistry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/components/PluginRegistry/PluginRegistry.tsx"],"sourcesContent":["// Copyright 2022 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 { useEvent } from '@perses-dev/core';\nimport { useRef, useCallback, useMemo } from 'react';\nimport { PluginModuleResource, PluginType, Plugin, PluginImplementation } from '../../model';\nimport { getTypeAndKindKey } from '../../utils/cache-keys';\nimport { GetInstalledPlugins, usePluginIndexes } from './plugin-indexes';\nimport { PluginRegistryContext } from './plugin-registry-model';\n\nexport interface PluginRegistryProps {\n children?: React.ReactNode;\n getInstalledPlugins: GetInstalledPlugins;\n importPluginModule: (resource: PluginModuleResource) => Promise<unknown>;\n}\n\n/**\n * PluginRegistryContext provider that keeps track of all available plugins and provides an API for getting them or\n * querying the metadata about them.\n */\nexport function PluginRegistry(props: PluginRegistryProps) {\n const { getInstalledPlugins, importPluginModule, children } = props;\n\n const getPluginIndexes = usePluginIndexes(getInstalledPlugins);\n\n // De-dupe calls to import plugin modules\n const importCache = useRef(new Map<PluginModuleResource, Promise<unknown>>());\n\n // Do useEvent here since this accesses the importPluginModule prop and we want a stable reference to it for the\n // callback below\n const loadPluginModule = useEvent((resource: PluginModuleResource) => {\n let request = importCache.current.get(resource);\n if (request === undefined) {\n request = importPluginModule(resource);\n importCache.current.set(resource, request);\n\n // Remove failed requests from the cache so they can potentially be retried\n request.catch(() => importCache.current.delete(resource));\n }\n return request;\n });\n\n const getPlugin = useCallback(\n async <T extends PluginType>(pluginType: T, kind: string): Promise<PluginImplementation<T>> => {\n // Get the indexes of the installed plugins\n const pluginIndexes = await getPluginIndexes();\n\n // Figure out what module the plugin is in by looking in the index\n const typeAndKindKey = getTypeAndKindKey(pluginType, kind);\n const resource = pluginIndexes.pluginResourcesByTypeAndKind.get(typeAndKindKey);\n if (resource === undefined) {\n throw new Error(`A ${pluginType} plugin for kind '${kind}' is not installed`);\n }\n\n // Treat the plugin module as a bunch of named exports that have plugins\n const pluginModule = (await loadPluginModule(resource)) as Record<string, Plugin>;\n\n // We currently assume that plugin modules will have named exports that match the kinds they handle\n const plugin = pluginModule[kind];\n if (plugin === undefined) {\n throw new Error(\n `The ${pluginType} plugin for kind '${kind}' is missing from the ${resource.metadata.name} plugin module`\n );\n }\n\n return plugin as PluginImplementation<T>;\n },\n [getPluginIndexes, loadPluginModule]\n );\n\n const listPluginMetadata = useCallback(\n async (pluginType: PluginType) => {\n const pluginIndexes = await getPluginIndexes();\n return pluginIndexes.pluginMetadataByType.get(pluginType) ?? [];\n },\n [getPluginIndexes]\n );\n\n // Create the registry's context value and render\n const context = useMemo(() => ({ getPlugin, listPluginMetadata }), [getPlugin, listPluginMetadata]);\n return <PluginRegistryContext.Provider value={context}>{children}</PluginRegistryContext.Provider>;\n}\n"],"names":["useEvent","useRef","useCallback","useMemo","getTypeAndKindKey","usePluginIndexes","PluginRegistryContext","PluginRegistry","props","getInstalledPlugins","importPluginModule","children","getPluginIndexes","importCache","Map","loadPluginModule","resource","request","current","get","undefined","set","catch","delete","getPlugin","pluginType","kind","pluginIndexes","typeAndKindKey","pluginResourcesByTypeAndKind","Error","pluginModule","plugin","metadata","name","listPluginMetadata","pluginMetadataByType","context","Provider","value"],"mappings":"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"}
@@ -1 +1,142 @@
1
- import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";import{screen}from"@testing-library/react";import{useListPluginMetadata,usePlugin}from"../../runtime/plugins";import{renderWithContext}from"../../test/render";import{PluginRegistry}from"./PluginRegistry";import{testRegistryProps}from"./test-plugins";describe("PluginRegistry",(()=>{const e=e=>{renderWithContext(_jsx(PluginRegistry,{...testRegistryProps,children:e}))};it("can load a plugin that exists",(async()=>{e(_jsx(PluginConsumer,{pluginType:"Variable",kind:"ErnieVariable"}));const t=await screen.findByText("Has plugin: true",void 0,{timeout:3e3});expect(t).toBeInTheDocument()})),it("errors when plugin is not installed",(async()=>{e(_jsx(PluginConsumer,{pluginType:"GraphQuery",kind:"NotInstalled"}));const t=await screen.findByText(/error:/i);expect(t).toBeInTheDocument(),expect(t).toHaveTextContent(/not installed/i)})),it("errors when plugin is missing from the module",(async()=>{e(_jsx(PluginConsumer,{pluginType:"Variable",kind:"MissingErnieVariable"}));const t=await screen.findByText(/error:/i);expect(t).toBeInTheDocument(),expect(t).toHaveTextContent(/missing/i)})),it("lists metadata for plugin metadata that exists",(async()=>{e(_jsx(MetadataConsumer,{pluginType:"Variable"}));const t=await screen.findByRole("table");expect(t).toBeInTheDocument();const n=screen.getAllByRole("row");expect(n).toHaveLength(3)})),it("lists metadata for plugin types with no plugins available",(async()=>{e(_jsx(MetadataConsumer,{pluginType:"GraphQuery"}));const t=await screen.findByRole("table");expect(t).toBeInTheDocument();const n=screen.queryAllByRole("row");expect(n).toHaveLength(0)}))}));const PluginConsumer=e=>{const{plugin:t,isLoading:n,error:i}=usePlugin(e.pluginType,e.kind);return i?_jsxs("div",{children:["Error: ",i.message]}):n?_jsx("div",{children:"Loading"}):_jsxs("div",{children:["Has plugin: ",(void 0!==t).toString()]})},MetadataConsumer=e=>{const{pluginMetadata:t,isLoading:n,error:i}=useListPluginMetadata(e.pluginType);return i?_jsxs("div",{children:["Error: ",i.message]}):n?_jsx("div",{children:"Loading"}):void 0===t?null:_jsx("table",{children:_jsx("tbody",{children:t.map((e=>_jsxs("tr",{children:[_jsx("td",{children:e.pluginType}),_jsx("td",{children:e.kind}),_jsx("td",{children:e.display.name}),_jsx("td",{children:e.display.description})]},e.kind)))})})};
1
+ // Copyright 2022 The Perses Authors
2
+ // Licensed under the Apache License, Version 2.0 (the "License");
3
+ // you may not use this file except in compliance with the License.
4
+ // You may obtain a copy of the License at
5
+ //
6
+ // http://www.apache.org/licenses/LICENSE-2.0
7
+ //
8
+ // Unless required by applicable law or agreed to in writing, software
9
+ // distributed under the License is distributed on an "AS IS" BASIS,
10
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+ // See the License for the specific language governing permissions and
12
+ // limitations under the License.
13
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
14
+ import React from 'react';
15
+ import { screen } from '@testing-library/react';
16
+ import { useListPluginMetadata, usePlugin } from '../../runtime/plugins';
17
+ import { renderWithContext } from '../../test/render';
18
+ import { PluginRegistry } from './PluginRegistry';
19
+ import { testRegistryProps } from './test-plugins';
20
+ describe('PluginRegistry', ()=>{
21
+ const renderPluginRegistry = (children)=>{
22
+ renderWithContext(/*#__PURE__*/ _jsx(PluginRegistry, {
23
+ ...testRegistryProps,
24
+ children: children
25
+ }));
26
+ };
27
+ it('can load a plugin that exists', async ()=>{
28
+ renderPluginRegistry(/*#__PURE__*/ _jsx(PluginConsumer, {
29
+ pluginType: "Variable",
30
+ kind: "ErnieVariable"
31
+ }));
32
+ const hasPlugin = await screen.findByText('Has plugin: true', undefined, {
33
+ timeout: 3000
34
+ });
35
+ expect(hasPlugin).toBeInTheDocument();
36
+ });
37
+ it('errors when plugin is not installed', async ()=>{
38
+ // This plugin is not in the test metadata at all
39
+ renderPluginRegistry(/*#__PURE__*/ _jsx(PluginConsumer, {
40
+ pluginType: "TimeSeriesQuery",
41
+ kind: "NotInstalled"
42
+ }));
43
+ const error = await screen.findByText(/error:/i);
44
+ expect(error).toBeInTheDocument();
45
+ expect(error).toHaveTextContent(/not installed/i);
46
+ });
47
+ it('errors when plugin is missing from the module', async ()=>{
48
+ // This plugin is in the test metadata, but the code is missing from the module
49
+ renderPluginRegistry(/*#__PURE__*/ _jsx(PluginConsumer, {
50
+ pluginType: "Variable",
51
+ kind: "MissingErnieVariable"
52
+ }));
53
+ const error = await screen.findByText(/error:/i);
54
+ expect(error).toBeInTheDocument();
55
+ expect(error).toHaveTextContent(/missing/i);
56
+ });
57
+ it('lists metadata for plugin metadata that exists', async ()=>{
58
+ // There should be 3 variable plugins across both test modules
59
+ renderPluginRegistry(/*#__PURE__*/ _jsx(MetadataConsumer, {
60
+ pluginType: "Variable"
61
+ }));
62
+ const table = await screen.findByRole('table');
63
+ expect(table).toBeInTheDocument();
64
+ const rows = screen.getAllByRole('row');
65
+ expect(rows).toHaveLength(3);
66
+ });
67
+ it('lists metadata for plugin types with no plugins available', async ()=>{
68
+ // There are no TimeSeriesQuery plugins in any of the test modules
69
+ renderPluginRegistry(/*#__PURE__*/ _jsx(MetadataConsumer, {
70
+ pluginType: "TimeSeriesQuery"
71
+ }));
72
+ const table = await screen.findByRole('table');
73
+ expect(table).toBeInTheDocument();
74
+ const rows = screen.queryAllByRole('row');
75
+ expect(rows).toHaveLength(0);
76
+ });
77
+ });
78
+ // A helper component for testing the PluginRegistry by calling usePlugin to load a plugin
79
+ const PluginConsumer = (props)=>{
80
+ const { data: plugin , isLoading , error } = usePlugin(props.pluginType, props.kind);
81
+ if (error) {
82
+ return /*#__PURE__*/ _jsxs("div", {
83
+ children: [
84
+ "Error: ",
85
+ error.message
86
+ ]
87
+ });
88
+ }
89
+ if (isLoading) {
90
+ return /*#__PURE__*/ _jsx("div", {
91
+ children: "Loading"
92
+ });
93
+ }
94
+ return /*#__PURE__*/ _jsxs("div", {
95
+ children: [
96
+ "Has plugin: ",
97
+ (plugin !== undefined).toString()
98
+ ]
99
+ });
100
+ };
101
+ // A helper component for testing the PluginRegistry metadata APIs by calling useListPluginMetadata
102
+ const MetadataConsumer = (props)=>{
103
+ const { data: pluginMetadata , isLoading , error } = useListPluginMetadata(props.pluginType);
104
+ if (error) {
105
+ return /*#__PURE__*/ _jsxs("div", {
106
+ children: [
107
+ "Error: ",
108
+ error.message
109
+ ]
110
+ });
111
+ }
112
+ if (isLoading) {
113
+ return /*#__PURE__*/ _jsx("div", {
114
+ children: "Loading"
115
+ });
116
+ }
117
+ if (pluginMetadata === undefined) {
118
+ return null;
119
+ }
120
+ return /*#__PURE__*/ _jsx("table", {
121
+ children: /*#__PURE__*/ _jsx("tbody", {
122
+ children: pluginMetadata.map((item)=>/*#__PURE__*/ _jsxs("tr", {
123
+ children: [
124
+ /*#__PURE__*/ _jsx("td", {
125
+ children: item.pluginType
126
+ }),
127
+ /*#__PURE__*/ _jsx("td", {
128
+ children: item.kind
129
+ }),
130
+ /*#__PURE__*/ _jsx("td", {
131
+ children: item.display.name
132
+ }),
133
+ /*#__PURE__*/ _jsx("td", {
134
+ children: item.display.description
135
+ })
136
+ ]
137
+ }, item.kind))
138
+ })
139
+ });
140
+ };
141
+
142
+ //# sourceMappingURL=PluginRegistry.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/components/PluginRegistry/PluginRegistry.test.tsx"],"sourcesContent":["// Copyright 2022 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 React from 'react';\nimport { screen } from '@testing-library/react';\nimport { PluginType } from '../../model';\nimport { useListPluginMetadata, usePlugin } from '../../runtime/plugins';\nimport { renderWithContext } from '../../test/render';\nimport { PluginRegistry } from './PluginRegistry';\nimport { testRegistryProps } from './test-plugins';\n\ndescribe('PluginRegistry', () => {\n const renderPluginRegistry = (children: React.ReactNode) => {\n renderWithContext(<PluginRegistry {...testRegistryProps}>{children}</PluginRegistry>);\n };\n\n it('can load a plugin that exists', async () => {\n renderPluginRegistry(<PluginConsumer pluginType=\"Variable\" kind=\"ErnieVariable\" />);\n\n const hasPlugin = await screen.findByText('Has plugin: true', undefined, { timeout: 3000 });\n expect(hasPlugin).toBeInTheDocument();\n });\n\n it('errors when plugin is not installed', async () => {\n // This plugin is not in the test metadata at all\n renderPluginRegistry(<PluginConsumer pluginType=\"TimeSeriesQuery\" kind=\"NotInstalled\" />);\n\n const error = await screen.findByText(/error:/i);\n expect(error).toBeInTheDocument();\n expect(error).toHaveTextContent(/not installed/i);\n });\n\n it('errors when plugin is missing from the module', async () => {\n // This plugin is in the test metadata, but the code is missing from the module\n renderPluginRegistry(<PluginConsumer pluginType=\"Variable\" kind=\"MissingErnieVariable\" />);\n\n const error = await screen.findByText(/error:/i);\n expect(error).toBeInTheDocument();\n expect(error).toHaveTextContent(/missing/i);\n });\n\n it('lists metadata for plugin metadata that exists', async () => {\n // There should be 3 variable plugins across both test modules\n renderPluginRegistry(<MetadataConsumer pluginType=\"Variable\" />);\n\n const table = await screen.findByRole('table');\n expect(table).toBeInTheDocument();\n const rows = screen.getAllByRole('row');\n expect(rows).toHaveLength(3);\n });\n\n it('lists metadata for plugin types with no plugins available', async () => {\n // There are no TimeSeriesQuery plugins in any of the test modules\n renderPluginRegistry(<MetadataConsumer pluginType=\"TimeSeriesQuery\" />);\n\n const table = await screen.findByRole('table');\n expect(table).toBeInTheDocument();\n const rows = screen.queryAllByRole('row');\n expect(rows).toHaveLength(0);\n });\n});\n\n// A helper component for testing the PluginRegistry by calling usePlugin to load a plugin\nconst PluginConsumer = (props: { pluginType: PluginType; kind: string }) => {\n const { data: plugin, isLoading, error } = usePlugin(props.pluginType, props.kind);\n if (error) {\n return <div>Error: {(error as Error).message}</div>;\n }\n if (isLoading) {\n return <div>Loading</div>;\n }\n return <div>Has plugin: {(plugin !== undefined).toString()}</div>;\n};\n\n// A helper component for testing the PluginRegistry metadata APIs by calling useListPluginMetadata\nconst MetadataConsumer = (props: { pluginType: PluginType }) => {\n const { data: pluginMetadata, isLoading, error } = useListPluginMetadata(props.pluginType);\n if (error) {\n return <div>Error: {(error as Error).message}</div>;\n }\n if (isLoading) {\n return <div>Loading</div>;\n }\n\n if (pluginMetadata === undefined) {\n return null;\n }\n\n return (\n <table>\n <tbody>\n {pluginMetadata.map((item) => (\n <tr key={item.kind}>\n <td>{item.pluginType}</td>\n <td>{item.kind}</td>\n <td>{item.display.name}</td>\n <td>{item.display.description}</td>\n </tr>\n ))}\n </tbody>\n </table>\n );\n};\n"],"names":["React","screen","useListPluginMetadata","usePlugin","renderWithContext","PluginRegistry","testRegistryProps","describe","renderPluginRegistry","children","it","PluginConsumer","pluginType","kind","hasPlugin","findByText","undefined","timeout","expect","toBeInTheDocument","error","toHaveTextContent","MetadataConsumer","table","findByRole","rows","getAllByRole","toHaveLength","queryAllByRole","props","data","plugin","isLoading","div","message","toString","pluginMetadata","tbody","map","item","tr","td","display","name","description"],"mappings":"AAAA,oCAAoC;AACpC,kEAAkE;AAClE,mEAAmE;AACnE,0CAA0C;AAC1C,EAAE;AACF,6CAA6C;AAC7C,EAAE;AACF,sEAAsE;AACtE,oEAAoE;AACpE,2EAA2E;AAC3E,sEAAsE;AACtE,iCAAiC;AAEjC;AAAA,OAAOA,KAAK,MAAM,OAAO,CAAC;AAC1B,SAASC,MAAM,QAAQ,wBAAwB,CAAC;AAEhD,SAASC,qBAAqB,EAAEC,SAAS,QAAQ,uBAAuB,CAAC;AACzE,SAASC,iBAAiB,QAAQ,mBAAmB,CAAC;AACtD,SAASC,cAAc,QAAQ,kBAAkB,CAAC;AAClD,SAASC,iBAAiB,QAAQ,gBAAgB,CAAC;AAEnDC,QAAQ,CAAC,gBAAgB,EAAE,IAAM;IAC/B,MAAMC,oBAAoB,GAAG,CAACC,QAAyB,GAAK;QAC1DL,iBAAiB,eAAC,KAACC,cAAc;YAAE,GAAGC,iBAAiB;sBAAGG,QAAQ;UAAkB,CAAC,CAAC;IACxF,CAAC,AAAC;IAEFC,EAAE,CAAC,+BAA+B,EAAE,UAAY;QAC9CF,oBAAoB,eAAC,KAACG,cAAc;YAACC,UAAU,EAAC,UAAU;YAACC,IAAI,EAAC,eAAe;UAAG,CAAC,CAAC;QAEpF,MAAMC,SAAS,GAAG,MAAMb,MAAM,CAACc,UAAU,CAAC,kBAAkB,EAAEC,SAAS,EAAE;YAAEC,OAAO,EAAE,IAAI;SAAE,CAAC,AAAC;QAC5FC,MAAM,CAACJ,SAAS,CAAC,CAACK,iBAAiB,EAAE,CAAC;IACxC,CAAC,CAAC,CAAC;IAEHT,EAAE,CAAC,qCAAqC,EAAE,UAAY;QACpD,iDAAiD;QACjDF,oBAAoB,eAAC,KAACG,cAAc;YAACC,UAAU,EAAC,iBAAiB;YAACC,IAAI,EAAC,cAAc;UAAG,CAAC,CAAC;QAE1F,MAAMO,KAAK,GAAG,MAAMnB,MAAM,CAACc,UAAU,WAAW,AAAC;QACjDG,MAAM,CAACE,KAAK,CAAC,CAACD,iBAAiB,EAAE,CAAC;QAClCD,MAAM,CAACE,KAAK,CAAC,CAACC,iBAAiB,kBAAkB,CAAC;IACpD,CAAC,CAAC,CAAC;IAEHX,EAAE,CAAC,+CAA+C,EAAE,UAAY;QAC9D,+EAA+E;QAC/EF,oBAAoB,eAAC,KAACG,cAAc;YAACC,UAAU,EAAC,UAAU;YAACC,IAAI,EAAC,sBAAsB;UAAG,CAAC,CAAC;QAE3F,MAAMO,KAAK,GAAG,MAAMnB,MAAM,CAACc,UAAU,WAAW,AAAC;QACjDG,MAAM,CAACE,KAAK,CAAC,CAACD,iBAAiB,EAAE,CAAC;QAClCD,MAAM,CAACE,KAAK,CAAC,CAACC,iBAAiB,YAAY,CAAC;IAC9C,CAAC,CAAC,CAAC;IAEHX,EAAE,CAAC,gDAAgD,EAAE,UAAY;QAC/D,8DAA8D;QAC9DF,oBAAoB,eAAC,KAACc,gBAAgB;YAACV,UAAU,EAAC,UAAU;UAAG,CAAC,CAAC;QAEjE,MAAMW,KAAK,GAAG,MAAMtB,MAAM,CAACuB,UAAU,CAAC,OAAO,CAAC,AAAC;QAC/CN,MAAM,CAACK,KAAK,CAAC,CAACJ,iBAAiB,EAAE,CAAC;QAClC,MAAMM,IAAI,GAAGxB,MAAM,CAACyB,YAAY,CAAC,KAAK,CAAC,AAAC;QACxCR,MAAM,CAACO,IAAI,CAAC,CAACE,YAAY,CAAC,CAAC,CAAC,CAAC;IAC/B,CAAC,CAAC,CAAC;IAEHjB,EAAE,CAAC,2DAA2D,EAAE,UAAY;QAC1E,kEAAkE;QAClEF,oBAAoB,eAAC,KAACc,gBAAgB;YAACV,UAAU,EAAC,iBAAiB;UAAG,CAAC,CAAC;QAExE,MAAMW,KAAK,GAAG,MAAMtB,MAAM,CAACuB,UAAU,CAAC,OAAO,CAAC,AAAC;QAC/CN,MAAM,CAACK,KAAK,CAAC,CAACJ,iBAAiB,EAAE,CAAC;QAClC,MAAMM,IAAI,GAAGxB,MAAM,CAAC2B,cAAc,CAAC,KAAK,CAAC,AAAC;QAC1CV,MAAM,CAACO,IAAI,CAAC,CAACE,YAAY,CAAC,CAAC,CAAC,CAAC;IAC/B,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,0FAA0F;AAC1F,MAAMhB,cAAc,GAAG,CAACkB,KAA+C,GAAK;IAC1E,MAAM,EAAEC,IAAI,EAAEC,MAAM,CAAA,EAAEC,SAAS,CAAA,EAAEZ,KAAK,CAAA,EAAE,GAAGjB,SAAS,CAAC0B,KAAK,CAACjB,UAAU,EAAEiB,KAAK,CAAChB,IAAI,CAAC,AAAC;IACnF,IAAIO,KAAK,EAAE;QACT,qBAAO,MAACa,KAAG;;gBAAC,SAAO;gBAAC,AAACb,KAAK,CAAWc,OAAO;;UAAO,CAAC;IACtD,CAAC;IACD,IAAIF,SAAS,EAAE;QACb,qBAAO,KAACC,KAAG;sBAAC,SAAO;UAAM,CAAC;IAC5B,CAAC;IACD,qBAAO,MAACA,KAAG;;YAAC,cAAY;YAAEF,CAAAA,MAAM,KAAKf,SAAS,CAAA,CAAEmB,QAAQ,EAAE;;MAAO,CAAC;AACpE,CAAC,AAAC;AAEF,mGAAmG;AACnG,MAAMb,gBAAgB,GAAG,CAACO,KAAiC,GAAK;IAC9D,MAAM,EAAEC,IAAI,EAAEM,cAAc,CAAA,EAAEJ,SAAS,CAAA,EAAEZ,KAAK,CAAA,EAAE,GAAGlB,qBAAqB,CAAC2B,KAAK,CAACjB,UAAU,CAAC,AAAC;IAC3F,IAAIQ,KAAK,EAAE;QACT,qBAAO,MAACa,KAAG;;gBAAC,SAAO;gBAAC,AAACb,KAAK,CAAWc,OAAO;;UAAO,CAAC;IACtD,CAAC;IACD,IAAIF,SAAS,EAAE;QACb,qBAAO,KAACC,KAAG;sBAAC,SAAO;UAAM,CAAC;IAC5B,CAAC;IAED,IAAIG,cAAc,KAAKpB,SAAS,EAAE;QAChC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,qBACE,KAACO,OAAK;kBACJ,cAAA,KAACc,OAAK;sBACHD,cAAc,CAACE,GAAG,CAAC,CAACC,IAAI,iBACvB,MAACC,IAAE;;sCACD,KAACC,IAAE;sCAAEF,IAAI,CAAC3B,UAAU;0BAAM;sCAC1B,KAAC6B,IAAE;sCAAEF,IAAI,CAAC1B,IAAI;0BAAM;sCACpB,KAAC4B,IAAE;sCAAEF,IAAI,CAACG,OAAO,CAACC,IAAI;0BAAM;sCAC5B,KAACF,IAAE;sCAAEF,IAAI,CAACG,OAAO,CAACE,WAAW;0BAAM;;mBAJ5BL,IAAI,CAAC1B,IAAI,CAKb,AACN,CAAC;UACI;MACF,CACR;AACJ,CAAC,AAAC"}
@@ -1 +1,16 @@
1
- export*from"./plugin-registry-model";export*from"./PluginRegistry";
1
+ // Copyright 2022 The Perses Authors
2
+ // Licensed under the Apache License, Version 2.0 (the "License");
3
+ // you may not use this file except in compliance with the License.
4
+ // You may obtain a copy of the License at
5
+ //
6
+ // http://www.apache.org/licenses/LICENSE-2.0
7
+ //
8
+ // Unless required by applicable law or agreed to in writing, software
9
+ // distributed under the License is distributed on an "AS IS" BASIS,
10
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+ // See the License for the specific language governing permissions and
12
+ // limitations under the License.
13
+ export * from './plugin-registry-model';
14
+ export * from './PluginRegistry';
15
+
16
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/components/PluginRegistry/index.ts"],"sourcesContent":["// Copyright 2022 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\nexport * from './plugin-registry-model';\nexport * from './PluginRegistry';\n"],"names":[],"mappings":"AAAA,oCAAoC;AACpC,kEAAkE;AAClE,mEAAmE;AACnE,0CAA0C;AAC1C,EAAE;AACF,6CAA6C;AAC7C,EAAE;AACF,sEAAsE;AACtE,oEAAoE;AACpE,2EAA2E;AAC3E,sEAAsE;AACtE,iCAAiC;AAEjC,cAAc,yBAAyB,CAAC;AACxC,cAAc,kBAAkB,CAAC"}
@@ -1 +1,66 @@
1
- import{useEvent}from"@perses-dev/core";import{useCallback,useRef}from"react";import{getTypeAndKindKey}from"../../utils/cache-keys";export function usePluginIndexes(e){const n=useEvent((async()=>{const n=await e(),t=new Map,o=new Map;for(const e of n)for(const n of e.spec.plugins){const{pluginType:r,kind:s}=n,u=getTypeAndKindKey(r,s);t.has(u)&&console.warn(`Got more than one ${r} plugin for kind ${s}`),t.set(u,e);let c=o.get(r);void 0===c&&(c=[],o.set(r,c)),c.push(n)}return{pluginResourcesByTypeAndKind:t,pluginMetadataByType:o}})),t=useRef(void 0);return useCallback((()=>{let e=t.current;return void 0===e&&(e=n(),t.current=e,e.catch((()=>void 0===t.current))),e}),[n])}
1
+ // Copyright 2022 The Perses Authors
2
+ // Licensed under the Apache License, Version 2.0 (the "License");
3
+ // you may not use this file except in compliance with the License.
4
+ // You may obtain a copy of the License at
5
+ //
6
+ // http://www.apache.org/licenses/LICENSE-2.0
7
+ //
8
+ // Unless required by applicable law or agreed to in writing, software
9
+ // distributed under the License is distributed on an "AS IS" BASIS,
10
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+ // See the License for the specific language governing permissions and
12
+ // limitations under the License.
13
+ import { useEvent } from '@perses-dev/core';
14
+ import { useCallback, useRef } from 'react';
15
+ import { getTypeAndKindKey } from '../../utils/cache-keys';
16
+ /**
17
+ * Returns an async callback for getting indexes of the installed plugin data.
18
+ */ export function usePluginIndexes(getInstalledPlugins) {
19
+ // Creates indexes from the installed plugins data (does useEvent because this accesses the getInstalledPlugins prop
20
+ // and we want a stable reference for the callback below)
21
+ const createPluginIndexes = useEvent(async ()=>{
22
+ const installedPlugins = await getInstalledPlugins();
23
+ // Create the two indexes from the installed plugins
24
+ const pluginResourcesByTypeAndKind = new Map();
25
+ const pluginMetadataByType = new Map();
26
+ for (const resource of installedPlugins){
27
+ for (const pluginMetadata of resource.spec.plugins){
28
+ const { pluginType , kind } = pluginMetadata;
29
+ // Index the plugin by type and kind to point at the module that contains it
30
+ const key = getTypeAndKindKey(pluginType, kind);
31
+ if (pluginResourcesByTypeAndKind.has(key)) {
32
+ console.warn(`Got more than one ${pluginType} plugin for kind ${kind}`);
33
+ }
34
+ pluginResourcesByTypeAndKind.set(key, resource);
35
+ // Index the metadata by plugin type
36
+ let list = pluginMetadataByType.get(pluginType);
37
+ if (list === undefined) {
38
+ list = [];
39
+ pluginMetadataByType.set(pluginType, list);
40
+ }
41
+ list.push(pluginMetadata);
42
+ }
43
+ }
44
+ return {
45
+ pluginResourcesByTypeAndKind,
46
+ pluginMetadataByType
47
+ };
48
+ });
49
+ // De-dupe creating plugin indexes (i.e. requests to get installed plugins)
50
+ const pluginIndexesCache = useRef(undefined);
51
+ const getPluginIndexes = useCallback(()=>{
52
+ let request = pluginIndexesCache.current;
53
+ if (request === undefined) {
54
+ request = createPluginIndexes();
55
+ pluginIndexesCache.current = request;
56
+ // Remove failed requests from the cache so they can potentially be retried
57
+ request.catch(()=>pluginIndexesCache.current === undefined);
58
+ }
59
+ return request;
60
+ }, [
61
+ createPluginIndexes
62
+ ]);
63
+ return getPluginIndexes;
64
+ }
65
+
66
+ //# sourceMappingURL=plugin-indexes.js.map