@perses-dev/plugin-system 0.18.0 → 0.20.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.
@@ -26,8 +26,8 @@ function _interopRequireDefault(obj) {
26
26
  };
27
27
  }
28
28
  describe('PluginEditor', ()=>{
29
- const renderComponent = ()=>{
30
- const testValue = {
29
+ const renderComponent = ({ pluginType ='Panel' , defaultPluginKinds , value } = {})=>{
30
+ const testValue = value || {
31
31
  kind: 'BertPanel1',
32
32
  spec: {
33
33
  option1: 'Option1Value'
@@ -39,13 +39,15 @@ describe('PluginEditor', ()=>{
39
39
  const [value, setValue] = (0, _react1.useState)(testValue);
40
40
  onChange = jest.fn((v)=>setValue(v));
41
41
  return /*#__PURE__*/ (0, _jsxRuntime.jsx)(_pluginEditor.PluginEditor, {
42
- pluginType: "Panel",
42
+ pluginType: pluginType,
43
43
  pluginKindLabel: "Panel Type",
44
44
  value: value,
45
45
  onChange: onChange
46
46
  });
47
47
  }
48
- (0, _test.renderWithContext)(/*#__PURE__*/ (0, _jsxRuntime.jsx)(TestHelperForm, {}));
48
+ (0, _test.renderWithContext)(/*#__PURE__*/ (0, _jsxRuntime.jsx)(TestHelperForm, {}), undefined, {
49
+ defaultPluginKinds
50
+ });
49
51
  return {
50
52
  onChange
51
53
  };
@@ -113,4 +115,36 @@ describe('PluginEditor', ()=>{
113
115
  editor = await _react.screen.findByLabelText('BertPanel1 editor');
114
116
  expect(editor).toHaveValue('MyNewValue');
115
117
  });
118
+ describe('when defaultPluginKinds specified in plugin registry', ()=>{
119
+ it('uses default kind when one is not provided', async ()=>{
120
+ renderComponent({
121
+ pluginType: 'Panel',
122
+ defaultPluginKinds: {
123
+ Panel: 'BertPanel2'
124
+ },
125
+ value: {
126
+ kind: '',
127
+ spec: {}
128
+ }
129
+ });
130
+ // Wait for default panel kind to load.
131
+ const pluginKind = _react.screen.getByRole('button', {
132
+ name: 'Panel Type'
133
+ });
134
+ await (0, _react.waitFor)(()=>expect(pluginKind).toHaveTextContent('Bert Panel 2'));
135
+ });
136
+ it('does not use default when kind is provided', async ()=>{
137
+ renderComponent({
138
+ pluginType: 'Panel',
139
+ defaultPluginKinds: {
140
+ Panel: 'BertPanel2'
141
+ }
142
+ });
143
+ // Wait for specified panel kind to load.
144
+ const pluginKind = _react.screen.getByRole('button', {
145
+ name: 'Panel Type'
146
+ });
147
+ await (0, _react.waitFor)(()=>expect(pluginKind).toHaveTextContent('Bert Panel 1'));
148
+ });
149
+ });
116
150
  });
@@ -40,9 +40,12 @@ function usePluginEditor(props) {
40
40
  }
41
41
  byPluginType[value.kind] = value.spec;
42
42
  });
43
+ const { defaultPluginKinds } = (0, _runtime.usePluginRegistry)();
44
+ const defaultPluginKind = defaultPluginKinds === null || defaultPluginKinds === void 0 ? void 0 : defaultPluginKinds[pluginType];
45
+ const initPendingKind = !value.kind && defaultPluginKind ? defaultPluginKind : '';
43
46
  // When kind changes and we haven't loaded that plugin before, we will need to enter a "pending" state so that we
44
47
  // can generate proper initial spec values that match the new plugin kind
45
- const [pendingKind, setPendingKind] = (0, _react.useState)('');
48
+ const [pendingKind, setPendingKind] = (0, _react.useState)(initPendingKind);
46
49
  const { data: plugin , isFetching , error } = (0, _runtime.usePlugin)(pluginType, pendingKind);
47
50
  (0, _react.useEffect)(()=>{
48
51
  // Nothing to do if no new plugin kind is pending
@@ -24,7 +24,7 @@ const _react = require("react");
24
24
  const _runtime = require("../../runtime");
25
25
  const _pluginIndexes = require("./plugin-indexes");
26
26
  function PluginRegistry(props) {
27
- const { pluginLoader: { getInstalledPlugins , importPluginModule } , children , } = props;
27
+ const { pluginLoader: { getInstalledPlugins , importPluginModule } , children , defaultPluginKinds , } = props;
28
28
  const getPluginIndexes = (0, _pluginIndexes.usePluginIndexes)(getInstalledPlugins);
29
29
  // De-dupe calls to import plugin modules
30
30
  const importCache = (0, _react.useRef)(new Map());
@@ -71,10 +71,12 @@ function PluginRegistry(props) {
71
71
  // Create the registry's context value and render
72
72
  const context = (0, _react.useMemo)(()=>({
73
73
  getPlugin,
74
- listPluginMetadata
74
+ listPluginMetadata,
75
+ defaultPluginKinds
75
76
  }), [
76
77
  getPlugin,
77
- listPluginMetadata
78
+ listPluginMetadata,
79
+ defaultPluginKinds
78
80
  ]);
79
81
  return /*#__PURE__*/ (0, _jsxRuntime.jsx)(_runtime.PluginRegistryContext.Provider, {
80
82
  value: context,
@@ -30,7 +30,7 @@ const testLogger = {
30
30
  // Don't log network errors in tests to the console
31
31
  }
32
32
  };
33
- function renderWithContext(ui, options) {
33
+ function renderWithContext(ui, renderOptions, contextOptions) {
34
34
  // Create a new QueryClient for each test to avoid caching issues
35
35
  const queryClient = new _reactQuery.QueryClient({
36
36
  defaultOptions: {
@@ -45,7 +45,8 @@ function renderWithContext(ui, options) {
45
45
  client: queryClient,
46
46
  children: /*#__PURE__*/ (0, _jsxRuntime.jsx)(_pluginRegistry.PluginRegistry, {
47
47
  pluginLoader: _testPlugins.testPluginLoader,
48
+ defaultPluginKinds: contextOptions === null || contextOptions === void 0 ? void 0 : contextOptions.defaultPluginKinds,
48
49
  children: ui
49
50
  })
50
- }), options);
51
+ }), renderOptions);
51
52
  }
@@ -17,8 +17,8 @@ import { useState } from 'react';
17
17
  import { renderWithContext } from '../../test';
18
18
  import { PluginEditor } from './PluginEditor';
19
19
  describe('PluginEditor', ()=>{
20
- const renderComponent = ()=>{
21
- const testValue = {
20
+ const renderComponent = ({ pluginType ='Panel' , defaultPluginKinds , value } = {})=>{
21
+ const testValue = value || {
22
22
  kind: 'BertPanel1',
23
23
  spec: {
24
24
  option1: 'Option1Value'
@@ -30,13 +30,15 @@ describe('PluginEditor', ()=>{
30
30
  const [value, setValue] = useState(testValue);
31
31
  onChange = jest.fn((v)=>setValue(v));
32
32
  return /*#__PURE__*/ _jsx(PluginEditor, {
33
- pluginType: "Panel",
33
+ pluginType: pluginType,
34
34
  pluginKindLabel: "Panel Type",
35
35
  value: value,
36
36
  onChange: onChange
37
37
  });
38
38
  }
39
- renderWithContext(/*#__PURE__*/ _jsx(TestHelperForm, {}));
39
+ renderWithContext(/*#__PURE__*/ _jsx(TestHelperForm, {}), undefined, {
40
+ defaultPluginKinds
41
+ });
40
42
  return {
41
43
  onChange
42
44
  };
@@ -104,6 +106,38 @@ describe('PluginEditor', ()=>{
104
106
  editor = await screen.findByLabelText('BertPanel1 editor');
105
107
  expect(editor).toHaveValue('MyNewValue');
106
108
  });
109
+ describe('when defaultPluginKinds specified in plugin registry', ()=>{
110
+ it('uses default kind when one is not provided', async ()=>{
111
+ renderComponent({
112
+ pluginType: 'Panel',
113
+ defaultPluginKinds: {
114
+ Panel: 'BertPanel2'
115
+ },
116
+ value: {
117
+ kind: '',
118
+ spec: {}
119
+ }
120
+ });
121
+ // Wait for default panel kind to load.
122
+ const pluginKind = screen.getByRole('button', {
123
+ name: 'Panel Type'
124
+ });
125
+ await waitFor(()=>expect(pluginKind).toHaveTextContent('Bert Panel 2'));
126
+ });
127
+ it('does not use default when kind is provided', async ()=>{
128
+ renderComponent({
129
+ pluginType: 'Panel',
130
+ defaultPluginKinds: {
131
+ Panel: 'BertPanel2'
132
+ }
133
+ });
134
+ // Wait for specified panel kind to load.
135
+ const pluginKind = screen.getByRole('button', {
136
+ name: 'Panel Type'
137
+ });
138
+ await waitFor(()=>expect(pluginKind).toHaveTextContent('Bert Panel 1'));
139
+ });
140
+ });
107
141
  });
108
142
 
109
143
  //# sourceMappingURL=PluginEditor.test.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/PluginEditor/PluginEditor.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 userEvent from '@testing-library/user-event';\nimport { screen, waitFor } from '@testing-library/react';\nimport { useState } from 'react';\nimport { renderWithContext } from '../../test';\nimport { PluginEditor } from './PluginEditor';\nimport { PluginEditorProps } from './plugin-editor-api';\n\ndescribe('PluginEditor', () => {\n const renderComponent = () => {\n const testValue: PluginEditorProps['value'] = { kind: 'BertPanel1', spec: { option1: 'Option1Value' } };\n\n // A test helper component that includes the state that's controlled from outside\n let onChange: jest.Mocked<PluginEditorProps['onChange']> = jest.fn();\n function TestHelperForm() {\n const [value, setValue] = useState(testValue);\n onChange = jest.fn((v) => setValue(v));\n\n return <PluginEditor pluginType=\"Panel\" pluginKindLabel=\"Panel Type\" value={value} onChange={onChange} />;\n }\n\n renderWithContext(<TestHelperForm />);\n return { onChange };\n };\n\n // Opens the PluginKindSelect and waits for loading to finish (i.e. options to appear)\n const openPluginKind = async () => {\n const select = screen.getByRole('button', { name: 'Panel Type' });\n userEvent.click(select);\n const options = await screen.findAllByRole('option');\n return options;\n };\n\n it('shows plugin kind and spec editor', async () => {\n renderComponent();\n\n const pluginKind = screen.getByRole('button', { name: 'Panel Type' });\n await waitFor(() => expect(pluginKind).toHaveTextContent('Bert Panel 1'));\n const specEditor = await screen.findByLabelText('BertPanel1 editor');\n expect(specEditor).toHaveValue('Option1Value');\n });\n\n it('initializes kind and spec together', async () => {\n const { onChange } = renderComponent();\n\n // Switch to a new plugin kind\n await openPluginKind();\n const newPluginKind = screen.getByRole('option', { name: 'Bert Panel 2' });\n userEvent.click(newPluginKind);\n\n // Wait for the editor of the other plugin\n const newEditor = await screen.findByLabelText('BertPanel2 editor');\n expect(newEditor).toBeInTheDocument();\n expect(newEditor).toHaveValue('');\n\n // Make sure onChange was only called once (i.e. initializes both kind and spec at the same time\n expect(onChange).toHaveBeenCalledTimes(1);\n expect(onChange).toHaveBeenCalledWith({ kind: 'BertPanel2', spec: { option2: '' } });\n });\n\n it('remembers previous spec values', async () => {\n renderComponent();\n\n // Use the current editor to make a change to the spec value\n let editor = await screen.findByLabelText('BertPanel1 editor');\n userEvent.clear(editor);\n userEvent.type(editor, 'MyNewValue');\n\n // Switch to a new plugin kind\n await openPluginKind();\n const newPluginKind = screen.getByRole('option', { name: 'Bert Panel 2' });\n userEvent.click(newPluginKind);\n\n // Wait for the other editor to appear, then switch back\n const newEditor = await screen.findByLabelText('BertPanel2 editor');\n expect(newEditor).toHaveValue('');\n await openPluginKind();\n const oldPluginKind = screen.getByRole('option', { name: 'Bert Panel 1' });\n userEvent.click(oldPluginKind);\n\n // Make sure the editor from the first plugin appears and has our modified value from before the switch\n editor = await screen.findByLabelText('BertPanel1 editor');\n expect(editor).toHaveValue('MyNewValue');\n });\n});\n"],"names":["userEvent","screen","waitFor","useState","renderWithContext","PluginEditor","describe","renderComponent","testValue","kind","spec","option1","onChange","jest","fn","TestHelperForm","value","setValue","v","pluginType","pluginKindLabel","openPluginKind","select","getByRole","name","click","options","findAllByRole","it","pluginKind","expect","toHaveTextContent","specEditor","findByLabelText","toHaveValue","newPluginKind","newEditor","toBeInTheDocument","toHaveBeenCalledTimes","toHaveBeenCalledWith","option2","editor","clear","type","oldPluginKind"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/components/PluginEditor/PluginEditor.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 userEvent from '@testing-library/user-event';\nimport { screen, waitFor } from '@testing-library/react';\nimport { useState } from 'react';\nimport { renderWithContext } from '../../test';\nimport { DefaultPluginKinds } from '../../model';\nimport { PluginEditor } from './PluginEditor';\nimport { PluginEditorProps } from './plugin-editor-api';\n\ntype RenderComponentOptions = {\n pluginType?: PluginEditorProps['pluginType'];\n defaultPluginKinds?: DefaultPluginKinds;\n value?: PluginEditorProps['value'];\n};\n\ndescribe('PluginEditor', () => {\n const renderComponent = ({ pluginType = 'Panel', defaultPluginKinds, value }: RenderComponentOptions = {}) => {\n const testValue: PluginEditorProps['value'] = value || { kind: 'BertPanel1', spec: { option1: 'Option1Value' } };\n\n // A test helper component that includes the state that's controlled from outside\n let onChange: jest.Mocked<PluginEditorProps['onChange']> = jest.fn();\n function TestHelperForm() {\n const [value, setValue] = useState(testValue);\n onChange = jest.fn((v) => setValue(v));\n\n return <PluginEditor pluginType={pluginType} pluginKindLabel=\"Panel Type\" value={value} onChange={onChange} />;\n }\n\n renderWithContext(<TestHelperForm />, undefined, { defaultPluginKinds });\n return { onChange };\n };\n\n // Opens the PluginKindSelect and waits for loading to finish (i.e. options to appear)\n const openPluginKind = async () => {\n const select = screen.getByRole('button', { name: 'Panel Type' });\n userEvent.click(select);\n const options = await screen.findAllByRole('option');\n return options;\n };\n\n it('shows plugin kind and spec editor', async () => {\n renderComponent();\n\n const pluginKind = screen.getByRole('button', { name: 'Panel Type' });\n await waitFor(() => expect(pluginKind).toHaveTextContent('Bert Panel 1'));\n const specEditor = await screen.findByLabelText('BertPanel1 editor');\n expect(specEditor).toHaveValue('Option1Value');\n });\n\n it('initializes kind and spec together', async () => {\n const { onChange } = renderComponent();\n\n // Switch to a new plugin kind\n await openPluginKind();\n const newPluginKind = screen.getByRole('option', { name: 'Bert Panel 2' });\n userEvent.click(newPluginKind);\n\n // Wait for the editor of the other plugin\n const newEditor = await screen.findByLabelText('BertPanel2 editor');\n expect(newEditor).toBeInTheDocument();\n expect(newEditor).toHaveValue('');\n\n // Make sure onChange was only called once (i.e. initializes both kind and spec at the same time\n expect(onChange).toHaveBeenCalledTimes(1);\n expect(onChange).toHaveBeenCalledWith({ kind: 'BertPanel2', spec: { option2: '' } });\n });\n\n it('remembers previous spec values', async () => {\n renderComponent();\n\n // Use the current editor to make a change to the spec value\n let editor = await screen.findByLabelText('BertPanel1 editor');\n userEvent.clear(editor);\n userEvent.type(editor, 'MyNewValue');\n\n // Switch to a new plugin kind\n await openPluginKind();\n const newPluginKind = screen.getByRole('option', { name: 'Bert Panel 2' });\n userEvent.click(newPluginKind);\n\n // Wait for the other editor to appear, then switch back\n const newEditor = await screen.findByLabelText('BertPanel2 editor');\n expect(newEditor).toHaveValue('');\n await openPluginKind();\n const oldPluginKind = screen.getByRole('option', { name: 'Bert Panel 1' });\n userEvent.click(oldPluginKind);\n\n // Make sure the editor from the first plugin appears and has our modified value from before the switch\n editor = await screen.findByLabelText('BertPanel1 editor');\n expect(editor).toHaveValue('MyNewValue');\n });\n\n describe('when defaultPluginKinds specified in plugin registry', () => {\n it('uses default kind when one is not provided', async () => {\n renderComponent({\n pluginType: 'Panel',\n defaultPluginKinds: {\n Panel: 'BertPanel2',\n },\n value: { kind: '', spec: {} },\n });\n\n // Wait for default panel kind to load.\n const pluginKind = screen.getByRole('button', { name: 'Panel Type' });\n await waitFor(() => expect(pluginKind).toHaveTextContent('Bert Panel 2'));\n });\n\n it('does not use default when kind is provided', async () => {\n renderComponent({ pluginType: 'Panel', defaultPluginKinds: { Panel: 'BertPanel2' } });\n\n // Wait for specified panel kind to load.\n const pluginKind = screen.getByRole('button', { name: 'Panel Type' });\n await waitFor(() => expect(pluginKind).toHaveTextContent('Bert Panel 1'));\n });\n });\n});\n"],"names":["userEvent","screen","waitFor","useState","renderWithContext","PluginEditor","describe","renderComponent","pluginType","defaultPluginKinds","value","testValue","kind","spec","option1","onChange","jest","fn","TestHelperForm","setValue","v","pluginKindLabel","undefined","openPluginKind","select","getByRole","name","click","options","findAllByRole","it","pluginKind","expect","toHaveTextContent","specEditor","findByLabelText","toHaveValue","newPluginKind","newEditor","toBeInTheDocument","toHaveBeenCalledTimes","toHaveBeenCalledWith","option2","editor","clear","type","oldPluginKind","Panel"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"plugin-editor-api.d.ts","sourceRoot":"","sources":["../../../src/components/PluginEditor/plugin-editor-api.ts"],"names":[],"mappings":";AAaA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,WAAW,EAAY,MAAM,kBAAkB,CAAC;AAGrE,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAOzC,aAAK,eAAe,GAAG,UAAU,GAAG,OAAO,GAAG,UAAU,CAAC;AAEzD,MAAM,WAAW,iBAAkB,SAAQ,IAAI,CAAC,QAAQ,EAAE,eAAe,CAAC;IACxE,UAAU,EAAE,UAAU,CAAC;IACvB,eAAe,EAAE,MAAM,CAAC;IACxB,KAAK,EAAE,UAAU,CAAC,WAAW,CAAC,CAAC;IAC/B,QAAQ,EAAE,CAAC,IAAI,EAAE,UAAU,CAAC,WAAW,CAAC,KAAK,IAAI,CAAC;CACnD;AAID;;GAEG;AACH,oBAAY,oBAAoB,GAAG,IAAI,CAAC,iBAAiB,EAAE,YAAY,GAAG,OAAO,GAAG,UAAU,CAAC,CAAC;AAEhG;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,oBAAoB;;;;;;EA2E1D"}
1
+ {"version":3,"file":"plugin-editor-api.d.ts","sourceRoot":"","sources":["../../../src/components/PluginEditor/plugin-editor-api.ts"],"names":[],"mappings":";AAaA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,WAAW,EAAY,MAAM,kBAAkB,CAAC;AAGrE,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAOzC,aAAK,eAAe,GAAG,UAAU,GAAG,OAAO,GAAG,UAAU,CAAC;AAEzD,MAAM,WAAW,iBAAkB,SAAQ,IAAI,CAAC,QAAQ,EAAE,eAAe,CAAC;IACxE,UAAU,EAAE,UAAU,CAAC;IACvB,eAAe,EAAE,MAAM,CAAC;IACxB,KAAK,EAAE,UAAU,CAAC,WAAW,CAAC,CAAC;IAC/B,QAAQ,EAAE,CAAC,IAAI,EAAE,UAAU,CAAC,WAAW,CAAC,KAAK,IAAI,CAAC;CACnD;AAID;;GAEG;AACH,oBAAY,oBAAoB,GAAG,IAAI,CAAC,iBAAiB,EAAE,YAAY,GAAG,OAAO,GAAG,UAAU,CAAC,CAAC;AAEhG;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,oBAAoB;;;;;;EA+E1D"}
@@ -13,7 +13,7 @@
13
13
  import { useEvent } from '@perses-dev/core';
14
14
  import { useState, useRef, useEffect } from 'react';
15
15
  import { produce } from 'immer';
16
- import { usePlugin } from '../../runtime';
16
+ import { usePlugin, usePluginRegistry } from '../../runtime';
17
17
  /**
18
18
  * Returns the state/handlers that power the `PluginEditor` component. Useful for custom components that want to provide
19
19
  * a different UI, but want the same behavior of changing `kind` and `spec` together on plugin kind changes. Also
@@ -37,9 +37,12 @@ import { usePlugin } from '../../runtime';
37
37
  }
38
38
  byPluginType[value.kind] = value.spec;
39
39
  });
40
+ const { defaultPluginKinds } = usePluginRegistry();
41
+ const defaultPluginKind = defaultPluginKinds === null || defaultPluginKinds === void 0 ? void 0 : defaultPluginKinds[pluginType];
42
+ const initPendingKind = !value.kind && defaultPluginKind ? defaultPluginKind : '';
40
43
  // When kind changes and we haven't loaded that plugin before, we will need to enter a "pending" state so that we
41
44
  // can generate proper initial spec values that match the new plugin kind
42
- const [pendingKind, setPendingKind] = useState('');
45
+ const [pendingKind, setPendingKind] = useState(initPendingKind);
43
46
  const { data: plugin , isFetching , error } = usePlugin(pluginType, pendingKind);
44
47
  useEffect(()=>{
45
48
  // Nothing to do if no new plugin kind is pending
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/PluginEditor/plugin-editor-api.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\nimport { BoxProps } from '@mui/material';\nimport { Definition, UnknownSpec, useEvent } from '@perses-dev/core';\nimport { useState, useRef, useEffect } from 'react';\nimport { produce } from 'immer';\nimport { PluginType } from '../../model';\nimport { PluginKindSelectProps } from '../PluginKindSelect';\nimport { PluginSpecEditorProps } from '../PluginSpecEditor';\nimport { usePlugin } from '../../runtime';\n\n// Props on MUI Box that we don't want people to pass because we're either redefining them or providing them in\n// this component\ntype OmittedMuiProps = 'children' | 'value' | 'onChange';\n\nexport interface PluginEditorProps extends Omit<BoxProps, OmittedMuiProps> {\n pluginType: PluginType;\n pluginKindLabel: string;\n value: Definition<UnknownSpec>;\n onChange: (next: Definition<UnknownSpec>) => void;\n}\n\ntype PreviousSpecState = Record<string, Record<string, UnknownSpec>>;\n\n/**\n * Props needed by the usePluginEditor hook.\n */\nexport type UsePluginEditorProps = Pick<PluginEditorProps, 'pluginType' | 'value' | 'onChange'>;\n\n/**\n * Returns the state/handlers that power the `PluginEditor` component. Useful for custom components that want to provide\n * a different UI, but want the same behavior of changing `kind` and `spec` together on plugin kind changes. Also\n * remembers previous `spec` values that it's seen, allowing and restores those values if a user switches the plugin\n * kind back.\n */\nexport function usePluginEditor(props: UsePluginEditorProps) {\n const { pluginType, value } = props;\n\n // Keep a stable reference so we don't run the effect below when we don't need to\n const onChange = useEvent(props.onChange);\n\n // The previous spec state for PluginType and kind and a helper function for remembering current values\n const prevSpecState = useRef<PreviousSpecState>({\n [pluginType]: { [value.kind]: value.spec },\n });\n\n const rememberCurrentSpecState = useEvent(() => {\n let byPluginType = prevSpecState.current[pluginType];\n if (byPluginType === undefined) {\n byPluginType = {};\n prevSpecState.current[pluginType] = byPluginType;\n }\n byPluginType[value.kind] = value.spec;\n });\n\n // When kind changes and we haven't loaded that plugin before, we will need to enter a \"pending\" state so that we\n // can generate proper initial spec values that match the new plugin kind\n const [pendingKind, setPendingKind] = useState('');\n const { data: plugin, isFetching, error } = usePlugin(pluginType, pendingKind);\n\n useEffect(() => {\n // Nothing to do if no new plugin kind is pending\n if (pendingKind === '') return;\n\n // Can't get spec value until we have a plugin\n if (plugin === undefined) return;\n\n // Fire an onChange to change to the pending kind with initial values from the plugin\n rememberCurrentSpecState();\n onChange({\n kind: pendingKind,\n spec: plugin.createInitialOptions(),\n });\n setPendingKind('');\n }, [pendingKind, plugin, rememberCurrentSpecState, onChange]);\n\n /**\n * When the user tries to change the plugin kind, make sure we have the correct spec for that plugin kind before we\n * make the switch.\n */\n const onKindChange: PluginKindSelectProps['onChange'] = (e) => {\n const nextKind = e.target.value;\n\n // If we already have state for this plugin type/kind from a previous selection, just use it\n const previousState = prevSpecState.current[pluginType]?.[nextKind];\n if (previousState !== undefined) {\n rememberCurrentSpecState();\n onChange({\n kind: nextKind,\n spec: previousState,\n });\n return;\n }\n\n // Otherwise, kick off the async loading process\n setPendingKind(nextKind);\n };\n\n /**\n * Spec changes are independent and always just set the spec state.\n */\n const onSpecChange: PluginSpecEditorProps['onChange'] = (next) => {\n onChange(\n produce(value, (draft) => {\n draft.spec = next;\n })\n );\n };\n\n return { pendingKind, isLoading: isFetching, error, onKindChange, onSpecChange };\n}\n"],"names":["useEvent","useState","useRef","useEffect","produce","usePlugin","usePluginEditor","props","pluginType","value","onChange","prevSpecState","kind","spec","rememberCurrentSpecState","byPluginType","current","undefined","pendingKind","setPendingKind","data","plugin","isFetching","error","createInitialOptions","onKindChange","e","nextKind","target","previousState","onSpecChange","next","draft","isLoading"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/components/PluginEditor/plugin-editor-api.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\nimport { BoxProps } from '@mui/material';\nimport { Definition, UnknownSpec, useEvent } from '@perses-dev/core';\nimport { useState, useRef, useEffect } from 'react';\nimport { produce } from 'immer';\nimport { PluginType } from '../../model';\nimport { PluginKindSelectProps } from '../PluginKindSelect';\nimport { PluginSpecEditorProps } from '../PluginSpecEditor';\nimport { usePlugin, usePluginRegistry } from '../../runtime';\n\n// Props on MUI Box that we don't want people to pass because we're either redefining them or providing them in\n// this component\ntype OmittedMuiProps = 'children' | 'value' | 'onChange';\n\nexport interface PluginEditorProps extends Omit<BoxProps, OmittedMuiProps> {\n pluginType: PluginType;\n pluginKindLabel: string;\n value: Definition<UnknownSpec>;\n onChange: (next: Definition<UnknownSpec>) => void;\n}\n\ntype PreviousSpecState = Record<string, Record<string, UnknownSpec>>;\n\n/**\n * Props needed by the usePluginEditor hook.\n */\nexport type UsePluginEditorProps = Pick<PluginEditorProps, 'pluginType' | 'value' | 'onChange'>;\n\n/**\n * Returns the state/handlers that power the `PluginEditor` component. Useful for custom components that want to provide\n * a different UI, but want the same behavior of changing `kind` and `spec` together on plugin kind changes. Also\n * remembers previous `spec` values that it's seen, allowing and restores those values if a user switches the plugin\n * kind back.\n */\nexport function usePluginEditor(props: UsePluginEditorProps) {\n const { pluginType, value } = props;\n\n // Keep a stable reference so we don't run the effect below when we don't need to\n const onChange = useEvent(props.onChange);\n\n // The previous spec state for PluginType and kind and a helper function for remembering current values\n const prevSpecState = useRef<PreviousSpecState>({\n [pluginType]: { [value.kind]: value.spec },\n });\n\n const rememberCurrentSpecState = useEvent(() => {\n let byPluginType = prevSpecState.current[pluginType];\n if (byPluginType === undefined) {\n byPluginType = {};\n prevSpecState.current[pluginType] = byPluginType;\n }\n byPluginType[value.kind] = value.spec;\n });\n\n const { defaultPluginKinds } = usePluginRegistry();\n const defaultPluginKind = defaultPluginKinds?.[pluginType];\n const initPendingKind = !value.kind && defaultPluginKind ? defaultPluginKind : '';\n\n // When kind changes and we haven't loaded that plugin before, we will need to enter a \"pending\" state so that we\n // can generate proper initial spec values that match the new plugin kind\n const [pendingKind, setPendingKind] = useState(initPendingKind);\n const { data: plugin, isFetching, error } = usePlugin(pluginType, pendingKind);\n\n useEffect(() => {\n // Nothing to do if no new plugin kind is pending\n if (pendingKind === '') return;\n\n // Can't get spec value until we have a plugin\n if (plugin === undefined) return;\n\n // Fire an onChange to change to the pending kind with initial values from the plugin\n rememberCurrentSpecState();\n onChange({\n kind: pendingKind,\n spec: plugin.createInitialOptions(),\n });\n setPendingKind('');\n }, [pendingKind, plugin, rememberCurrentSpecState, onChange]);\n\n /**\n * When the user tries to change the plugin kind, make sure we have the correct spec for that plugin kind before we\n * make the switch.\n */\n const onKindChange: PluginKindSelectProps['onChange'] = (e) => {\n const nextKind = e.target.value;\n\n // If we already have state for this plugin type/kind from a previous selection, just use it\n const previousState = prevSpecState.current[pluginType]?.[nextKind];\n if (previousState !== undefined) {\n rememberCurrentSpecState();\n onChange({\n kind: nextKind,\n spec: previousState,\n });\n return;\n }\n\n // Otherwise, kick off the async loading process\n setPendingKind(nextKind);\n };\n\n /**\n * Spec changes are independent and always just set the spec state.\n */\n const onSpecChange: PluginSpecEditorProps['onChange'] = (next) => {\n onChange(\n produce(value, (draft) => {\n draft.spec = next;\n })\n );\n };\n\n return { pendingKind, isLoading: isFetching, error, onKindChange, onSpecChange };\n}\n"],"names":["useEvent","useState","useRef","useEffect","produce","usePlugin","usePluginRegistry","usePluginEditor","props","pluginType","value","onChange","prevSpecState","kind","spec","rememberCurrentSpecState","byPluginType","current","undefined","defaultPluginKinds","defaultPluginKind","initPendingKind","pendingKind","setPendingKind","data","plugin","isFetching","error","createInitialOptions","onKindChange","e","nextKind","target","previousState","onSpecChange","next","draft","isLoading"],"mappings":"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"}
@@ -1,8 +1,9 @@
1
1
  /// <reference types="react" />
2
- import { PluginLoader } from '../../model';
2
+ import { PluginLoader, DefaultPluginKinds } from '../../model';
3
3
  export interface PluginRegistryProps {
4
4
  children?: React.ReactNode;
5
5
  pluginLoader: PluginLoader;
6
+ defaultPluginKinds?: DefaultPluginKinds;
6
7
  }
7
8
  /**
8
9
  * PluginRegistryContext provider that keeps track of all available plugins and provides an API for getting them or
@@ -1 +1 @@
1
- {"version":3,"file":"PluginRegistry.d.ts","sourceRoot":"","sources":["../../../src/components/PluginRegistry/PluginRegistry.tsx"],"names":[],"mappings":";AAeA,OAAO,EAAkE,YAAY,EAAE,MAAM,aAAa,CAAC;AAI3G,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,YAAY,EAAE,YAAY,CAAC;CAC5B;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,mBAAmB,eAgExD"}
1
+ {"version":3,"file":"PluginRegistry.d.ts","sourceRoot":"","sources":["../../../src/components/PluginRegistry/PluginRegistry.tsx"],"names":[],"mappings":";AAeA,OAAO,EAKL,YAAY,EACZ,kBAAkB,EACnB,MAAM,aAAa,CAAC;AAIrB,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,YAAY,EAAE,YAAY,CAAC;IAC3B,kBAAkB,CAAC,EAAE,kBAAkB,CAAC;CACzC;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,mBAAmB,eAoExD"}
@@ -19,7 +19,7 @@ import { usePluginIndexes, getTypeAndKindKey } from './plugin-indexes';
19
19
  * PluginRegistryContext provider that keeps track of all available plugins and provides an API for getting them or
20
20
  * querying the metadata about them.
21
21
  */ export function PluginRegistry(props) {
22
- const { pluginLoader: { getInstalledPlugins , importPluginModule } , children , } = props;
22
+ const { pluginLoader: { getInstalledPlugins , importPluginModule } , children , defaultPluginKinds , } = props;
23
23
  const getPluginIndexes = usePluginIndexes(getInstalledPlugins);
24
24
  // De-dupe calls to import plugin modules
25
25
  const importCache = useRef(new Map());
@@ -66,10 +66,12 @@ import { usePluginIndexes, getTypeAndKindKey } from './plugin-indexes';
66
66
  // Create the registry's context value and render
67
67
  const context = useMemo(()=>({
68
68
  getPlugin,
69
- listPluginMetadata
69
+ listPluginMetadata,
70
+ defaultPluginKinds
70
71
  }), [
71
72
  getPlugin,
72
- listPluginMetadata
73
+ listPluginMetadata,
74
+ defaultPluginKinds
73
75
  ]);
74
76
  return /*#__PURE__*/ _jsx(PluginRegistryContext.Provider, {
75
77
  value: context,
@@ -1 +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 { UnknownSpec, useEvent } from '@perses-dev/core';\nimport { useRef, useCallback, useMemo } from 'react';\nimport { PluginModuleResource, PluginType, PluginImplementation, Plugin, PluginLoader } from '../../model';\nimport { PluginRegistryContext } from '../../runtime';\nimport { usePluginIndexes, getTypeAndKindKey } from './plugin-indexes';\n\nexport interface PluginRegistryProps {\n children?: React.ReactNode;\n pluginLoader: PluginLoader;\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 {\n pluginLoader: { getInstalledPlugins, importPluginModule },\n children,\n } = 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<UnknownSpec>>;\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","PluginRegistryContext","usePluginIndexes","getTypeAndKindKey","PluginRegistry","props","pluginLoader","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
+ {"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 { UnknownSpec, useEvent } from '@perses-dev/core';\nimport { useRef, useCallback, useMemo } from 'react';\nimport {\n PluginModuleResource,\n PluginType,\n PluginImplementation,\n Plugin,\n PluginLoader,\n DefaultPluginKinds,\n} from '../../model';\nimport { PluginRegistryContext } from '../../runtime';\nimport { usePluginIndexes, getTypeAndKindKey } from './plugin-indexes';\n\nexport interface PluginRegistryProps {\n children?: React.ReactNode;\n pluginLoader: PluginLoader;\n defaultPluginKinds?: DefaultPluginKinds;\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 {\n pluginLoader: { getInstalledPlugins, importPluginModule },\n children,\n defaultPluginKinds,\n } = 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<UnknownSpec>>;\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(\n () => ({ getPlugin, listPluginMetadata, defaultPluginKinds }),\n [getPlugin, listPluginMetadata, defaultPluginKinds]\n );\n return <PluginRegistryContext.Provider value={context}>{children}</PluginRegistryContext.Provider>;\n}\n"],"names":["useEvent","useRef","useCallback","useMemo","PluginRegistryContext","usePluginIndexes","getTypeAndKindKey","PluginRegistry","props","pluginLoader","getInstalledPlugins","importPluginModule","children","defaultPluginKinds","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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"}
@@ -47,4 +47,8 @@ export interface SupportedPlugins {
47
47
  * The implementation for a given plugin type.
48
48
  */
49
49
  export declare type PluginImplementation<Type extends PluginType> = SupportedPlugins[Type];
50
+ /**
51
+ * Default plugin kinds by plugin type.
52
+ */
53
+ export declare type DefaultPluginKinds = Partial<Record<PluginType, string>>;
50
54
  //# sourceMappingURL=plugins.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"plugins.d.ts","sourceRoot":"","sources":["../../src/model/plugins.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AACzD,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACvC,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAEvC;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,cAAc,CAAC;IACrB,QAAQ,EAAE,QAAQ,CAAC;IACnB,IAAI,EAAE,UAAU,CAAC;CAClB;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,cAAc,EAAE,CAAC;CAC3B;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,UAAU,EAAE,UAAU,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE;QACP,IAAI,EAAE,MAAM,CAAC;QACb,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB,CAAC;CACH;AAED;;;GAGG;AACH,oBAAY,UAAU,GAAG;KAEtB,CAAC,IAAI,MAAM,gBAAgB,GAAG,gBAAgB,CAAC,CAAC,CAAC,SAAS,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,KAAK;CAC3F,CAAC,MAAM,gBAAgB,CAAC,CAAC;AAE1B;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,cAAc,CAAC;IACzB,KAAK,EAAE,WAAW,CAAC;IACnB,eAAe,EAAE,qBAAqB,CAAC;IACvC,UAAU,EAAE,gBAAgB,CAAC;CAC9B;AAED;;GAEG;AACH,oBAAY,oBAAoB,CAAC,IAAI,SAAS,UAAU,IAAI,gBAAgB,CAAC,IAAI,CAAC,CAAC"}
1
+ {"version":3,"file":"plugins.d.ts","sourceRoot":"","sources":["../../src/model/plugins.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AACzD,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACvC,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAEvC;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,cAAc,CAAC;IACrB,QAAQ,EAAE,QAAQ,CAAC;IACnB,IAAI,EAAE,UAAU,CAAC;CAClB;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,cAAc,EAAE,CAAC;CAC3B;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,UAAU,EAAE,UAAU,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE;QACP,IAAI,EAAE,MAAM,CAAC;QACb,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB,CAAC;CACH;AAED;;;GAGG;AACH,oBAAY,UAAU,GAAG;KAEtB,CAAC,IAAI,MAAM,gBAAgB,GAAG,gBAAgB,CAAC,CAAC,CAAC,SAAS,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,KAAK;CAC3F,CAAC,MAAM,gBAAgB,CAAC,CAAC;AAE1B;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,cAAc,CAAC;IACzB,KAAK,EAAE,WAAW,CAAC;IACnB,eAAe,EAAE,qBAAqB,CAAC;IACvC,UAAU,EAAE,gBAAgB,CAAC;CAC9B;AAED;;GAEG;AACH,oBAAY,oBAAoB,CAAC,IAAI,SAAS,UAAU,IAAI,gBAAgB,CAAC,IAAI,CAAC,CAAC;AAEnF;;GAEG;AACH,oBAAY,kBAAkB,GAAG,OAAO,CAAC,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/model/plugins.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\nimport { Metadata, UnknownSpec } from '@perses-dev/core';\nimport { TimeSeriesQueryPlugin } from './time-series-queries';\nimport { PanelPlugin } from './panels';\nimport { VariablePlugin } from './variables';\nimport { DatasourcePlugin } from './datasource';\nimport { Plugin } from './plugin-base';\n\n/**\n * Information about a module/package that contains plugins.\n */\nexport interface PluginModuleResource {\n kind: 'PluginModule';\n metadata: Metadata;\n spec: PluginSpec;\n}\n\nexport interface PluginSpec {\n plugins: PluginMetadata[];\n}\n\n/**\n * Metadata about an individual plugin that's part of a PluginModule.\n */\nexport interface PluginMetadata {\n pluginType: PluginType;\n kind: string;\n display: {\n name: string;\n description?: string;\n };\n}\n\n/**\n * All supported plugin types. A plugin's implementation must extend from `Plugin<UnknownSpec>` to be considered a valid\n * `PluginType`.\n */\nexport type PluginType = {\n // Filter out implementations on SupportedPlugins that don't extend `Plugin<UnknownSpec>`\n [K in keyof SupportedPlugins]: SupportedPlugins[K] extends Plugin<UnknownSpec> ? K : never;\n}[keyof SupportedPlugins];\n\n/**\n * Map of plugin type key/string -> implementation type. Use Typescript module augmentation to extend the plugin system\n * with new plugin types.\n */\nexport interface SupportedPlugins {\n Variable: VariablePlugin;\n Panel: PanelPlugin;\n TimeSeriesQuery: TimeSeriesQueryPlugin;\n Datasource: DatasourcePlugin;\n}\n\n/**\n * The implementation for a given plugin type.\n */\nexport type PluginImplementation<Type extends PluginType> = SupportedPlugins[Type];\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,WAuDmF"}
1
+ {"version":3,"sources":["../../src/model/plugins.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\nimport { Metadata, UnknownSpec } from '@perses-dev/core';\nimport { TimeSeriesQueryPlugin } from './time-series-queries';\nimport { PanelPlugin } from './panels';\nimport { VariablePlugin } from './variables';\nimport { DatasourcePlugin } from './datasource';\nimport { Plugin } from './plugin-base';\n\n/**\n * Information about a module/package that contains plugins.\n */\nexport interface PluginModuleResource {\n kind: 'PluginModule';\n metadata: Metadata;\n spec: PluginSpec;\n}\n\nexport interface PluginSpec {\n plugins: PluginMetadata[];\n}\n\n/**\n * Metadata about an individual plugin that's part of a PluginModule.\n */\nexport interface PluginMetadata {\n pluginType: PluginType;\n kind: string;\n display: {\n name: string;\n description?: string;\n };\n}\n\n/**\n * All supported plugin types. A plugin's implementation must extend from `Plugin<UnknownSpec>` to be considered a valid\n * `PluginType`.\n */\nexport type PluginType = {\n // Filter out implementations on SupportedPlugins that don't extend `Plugin<UnknownSpec>`\n [K in keyof SupportedPlugins]: SupportedPlugins[K] extends Plugin<UnknownSpec> ? K : never;\n}[keyof SupportedPlugins];\n\n/**\n * Map of plugin type key/string -> implementation type. Use Typescript module augmentation to extend the plugin system\n * with new plugin types.\n */\nexport interface SupportedPlugins {\n Variable: VariablePlugin;\n Panel: PanelPlugin;\n TimeSeriesQuery: TimeSeriesQueryPlugin;\n Datasource: DatasourcePlugin;\n}\n\n/**\n * The implementation for a given plugin type.\n */\nexport type PluginImplementation<Type extends PluginType> = SupportedPlugins[Type];\n\n/**\n * Default plugin kinds by plugin type.\n */\nexport type DefaultPluginKinds = Partial<Record<PluginType, string>>;\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,WA4DqE"}
@@ -1,9 +1,10 @@
1
1
  /// <reference types="react" />
2
2
  import { UseQueryOptions } from '@tanstack/react-query';
3
- import { PluginImplementation, PluginMetadata, PluginType } from '../model';
3
+ import { DefaultPluginKinds, PluginImplementation, PluginMetadata, PluginType } from '../model';
4
4
  export interface PluginRegistryContextType {
5
5
  getPlugin<T extends PluginType>(pluginType: T, kind: string): Promise<PluginImplementation<T>>;
6
6
  listPluginMetadata(pluginType: PluginType): Promise<PluginMetadata[]>;
7
+ defaultPluginKinds?: DefaultPluginKinds;
7
8
  }
8
9
  export declare const PluginRegistryContext: import("react").Context<PluginRegistryContextType | undefined>;
9
10
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"plugin-registry.d.ts","sourceRoot":"","sources":["../../src/runtime/plugin-registry.ts"],"names":[],"mappings":";AAcA,OAAO,EAAwB,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC9E,OAAO,EAAE,oBAAoB,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAE5E,MAAM,WAAW,yBAAyB;IACxC,SAAS,CAAC,CAAC,SAAS,UAAU,EAAE,UAAU,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/F,kBAAkB,CAAC,UAAU,EAAE,UAAU,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,CAAC;CACvE;AAED,eAAO,MAAM,qBAAqB,gEAAkE,CAAC;AAErG;;;GAGG;AACH,wBAAgB,iBAAiB,8BAMhC;AAGD,aAAK,gBAAgB,CAAC,CAAC,SAAS,UAAU,IAAI,IAAI,CAChD,eAAe,CAAC,oBAAoB,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,oBAAoB,CAAC,CAAC,CAAC,EAAE,CAAC,MAAM,EAAE,UAAU,EAAE,MAAM,CAAC,CAAC,EACtG,UAAU,GAAG,SAAS,CACvB,CAAC;AAEF;;GAEG;AACH,wBAAgB,SAAS,CAAC,CAAC,SAAS,UAAU,EAAE,UAAU,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,gBAAgB,CAAC,CAAC,CAAC,kFAQzG;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,CAAC,SAAS,UAAU,EAAE,UAAU,EAAE,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,sFAU/F;AAGD,aAAK,4BAA4B,GAAG,IAAI,CACtC,eAAe,CAAC,cAAc,EAAE,EAAE,KAAK,EAAE,cAAc,EAAE,EAAE,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,EAChF,UAAU,GAAG,SAAS,CACvB,CAAC;AAEF;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,UAAU,EAAE,UAAU,EAAE,OAAO,CAAC,EAAE,4BAA4B,2EAGnG"}
1
+ {"version":3,"file":"plugin-registry.d.ts","sourceRoot":"","sources":["../../src/runtime/plugin-registry.ts"],"names":[],"mappings":";AAcA,OAAO,EAAwB,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC9E,OAAO,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAEhG,MAAM,WAAW,yBAAyB;IACxC,SAAS,CAAC,CAAC,SAAS,UAAU,EAAE,UAAU,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/F,kBAAkB,CAAC,UAAU,EAAE,UAAU,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,CAAC;IACtE,kBAAkB,CAAC,EAAE,kBAAkB,CAAC;CACzC;AAED,eAAO,MAAM,qBAAqB,gEAAkE,CAAC;AAErG;;;GAGG;AACH,wBAAgB,iBAAiB,8BAMhC;AAGD,aAAK,gBAAgB,CAAC,CAAC,SAAS,UAAU,IAAI,IAAI,CAChD,eAAe,CAAC,oBAAoB,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,oBAAoB,CAAC,CAAC,CAAC,EAAE,CAAC,MAAM,EAAE,UAAU,EAAE,MAAM,CAAC,CAAC,EACtG,UAAU,GAAG,SAAS,CACvB,CAAC;AAEF;;GAEG;AACH,wBAAgB,SAAS,CAAC,CAAC,SAAS,UAAU,EAAE,UAAU,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,gBAAgB,CAAC,CAAC,CAAC,kFAQzG;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,CAAC,SAAS,UAAU,EAAE,UAAU,EAAE,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,sFAU/F;AAGD,aAAK,4BAA4B,GAAG,IAAI,CACtC,eAAe,CAAC,cAAc,EAAE,EAAE,KAAK,EAAE,cAAc,EAAE,EAAE,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,EAChF,UAAU,GAAG,SAAS,CACvB,CAAC;AAEF;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,UAAU,EAAE,UAAU,EAAE,OAAO,CAAC,EAAE,4BAA4B,2EAGnG"}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/runtime/plugin-registry.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\nimport { createContext, useContext } from 'react';\nimport { useQuery, useQueries, UseQueryOptions } from '@tanstack/react-query';\nimport { PluginImplementation, PluginMetadata, PluginType } from '../model';\n\nexport interface PluginRegistryContextType {\n getPlugin<T extends PluginType>(pluginType: T, kind: string): Promise<PluginImplementation<T>>;\n listPluginMetadata(pluginType: PluginType): Promise<PluginMetadata[]>;\n}\n\nexport const PluginRegistryContext = createContext<PluginRegistryContextType | undefined>(undefined);\n\n/**\n * Use the PluginRegistry context directly. This is meant as an escape hatch for custom async flows. You should probably\n * be using `usePlugin` or `useListPluginMetadata` instead.\n */\nexport function usePluginRegistry() {\n const ctx = useContext(PluginRegistryContext);\n if (ctx === undefined) {\n throw new Error('PluginRegistryContext not found. Did you forget a provider?');\n }\n return ctx;\n}\n\n// Allows consumers to pass useQuery options from react-query when loading a plugin\ntype UsePluginOptions<T extends PluginType> = Omit<\n UseQueryOptions<PluginImplementation<T>, Error, PluginImplementation<T>, [string, PluginType, string]>,\n 'queryKey' | 'queryFn'\n>;\n\n/**\n * Loads a plugin and returns the plugin implementation, along with loading/error state.\n */\nexport function usePlugin<T extends PluginType>(pluginType: T, kind: string, options?: UsePluginOptions<T>) {\n // We never want to ask for a plugin when the kind isn't set yet, so disable those queries automatically\n options = {\n ...options,\n enabled: (options?.enabled ?? true) && kind !== '',\n };\n const { getPlugin } = usePluginRegistry();\n return useQuery(['getPlugin', pluginType, kind], () => getPlugin(pluginType, kind), options);\n}\n\n/**\n * Loads a list of plugins and returns the plugin implementation, along with loading/error state.\n */\nexport function usePlugins<T extends PluginType>(pluginType: T, plugins: Array<{ kind: string }>) {\n const { getPlugin } = usePluginRegistry();\n return useQueries({\n queries: plugins.map((p) => {\n return {\n queryKey: ['getPlugin', pluginType, p.kind],\n queryFn: () => getPlugin(pluginType, p.kind),\n };\n }),\n });\n}\n\n// Allow consumers to pass useQuery options from react-query when listing metadata\ntype UseListPluginMetadataOptions = Omit<\n UseQueryOptions<PluginMetadata[], Error, PluginMetadata[], [string, PluginType]>,\n 'queryKey' | 'queryFn'\n>;\n\n/**\n * Gets a list of plugin metadata for the specified plugin type and returns it, along with loading/error state.\n */\nexport function useListPluginMetadata(pluginType: PluginType, options?: UseListPluginMetadataOptions) {\n const { listPluginMetadata } = usePluginRegistry();\n return useQuery(['listPluginMetadata', pluginType], () => listPluginMetadata(pluginType), options);\n}\n"],"names":["createContext","useContext","useQuery","useQueries","PluginRegistryContext","undefined","usePluginRegistry","ctx","Error","usePlugin","pluginType","kind","options","enabled","getPlugin","usePlugins","plugins","queries","map","p","queryKey","queryFn","useListPluginMetadata","listPluginMetadata"],"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,SAASA,aAAa,EAAEC,UAAU,QAAQ,OAAO,CAAC;AAClD,SAASC,QAAQ,EAAEC,UAAU,QAAyB,uBAAuB,CAAC;AAQ9E,OAAO,MAAMC,qBAAqB,GAAGJ,aAAa,CAAwCK,SAAS,CAAC,CAAC;AAErG;;;CAGC,GACD,OAAO,SAASC,iBAAiB,GAAG;IAClC,MAAMC,GAAG,GAAGN,UAAU,CAACG,qBAAqB,CAAC,AAAC;IAC9C,IAAIG,GAAG,KAAKF,SAAS,EAAE;QACrB,MAAM,IAAIG,KAAK,CAAC,6DAA6D,CAAC,CAAC;IACjF,CAAC;IACD,OAAOD,GAAG,CAAC;AACb,CAAC;AAQD;;CAEC,GACD,OAAO,SAASE,SAAS,CAAuBC,UAAa,EAAEC,IAAY,EAAEC,OAA6B,EAAE;QAI9FA,GAAgB;IAH5B,wGAAwG;IACxGA,OAAO,GAAG;QACR,GAAGA,OAAO;QACVC,OAAO,EAAE,AAACD,CAAAA,CAAAA,GAAgB,GAAhBA,OAAO,aAAPA,OAAO,WAAS,GAAhBA,KAAAA,CAAgB,GAAhBA,OAAO,CAAEC,OAAO,cAAhBD,GAAgB,cAAhBA,GAAgB,GAAI,IAAI,CAAA,IAAKD,IAAI,KAAK,EAAE;KACnD,CAAC;IACF,MAAM,EAAEG,SAAS,CAAA,EAAE,GAAGR,iBAAiB,EAAE,AAAC;IAC1C,OAAOJ,QAAQ,CAAC;QAAC,WAAW;QAAEQ,UAAU;QAAEC,IAAI;KAAC,EAAE,IAAMG,SAAS,CAACJ,UAAU,EAAEC,IAAI,CAAC,EAAEC,OAAO,CAAC,CAAC;AAC/F,CAAC;AAED;;CAEC,GACD,OAAO,SAASG,UAAU,CAAuBL,UAAa,EAAEM,OAAgC,EAAE;IAChG,MAAM,EAAEF,SAAS,CAAA,EAAE,GAAGR,iBAAiB,EAAE,AAAC;IAC1C,OAAOH,UAAU,CAAC;QAChBc,OAAO,EAAED,OAAO,CAACE,GAAG,CAAC,CAACC,CAAC,GAAK;YAC1B,OAAO;gBACLC,QAAQ,EAAE;oBAAC,WAAW;oBAAEV,UAAU;oBAAES,CAAC,CAACR,IAAI;iBAAC;gBAC3CU,OAAO,EAAE,IAAMP,SAAS,CAACJ,UAAU,EAAES,CAAC,CAACR,IAAI,CAAC;aAC7C,CAAC;QACJ,CAAC,CAAC;KACH,CAAC,CAAC;AACL,CAAC;AAQD;;CAEC,GACD,OAAO,SAASW,qBAAqB,CAACZ,UAAsB,EAAEE,OAAsC,EAAE;IACpG,MAAM,EAAEW,kBAAkB,CAAA,EAAE,GAAGjB,iBAAiB,EAAE,AAAC;IACnD,OAAOJ,QAAQ,CAAC;QAAC,oBAAoB;QAAEQ,UAAU;KAAC,EAAE,IAAMa,kBAAkB,CAACb,UAAU,CAAC,EAAEE,OAAO,CAAC,CAAC;AACrG,CAAC"}
1
+ {"version":3,"sources":["../../src/runtime/plugin-registry.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\nimport { createContext, useContext } from 'react';\nimport { useQuery, useQueries, UseQueryOptions } from '@tanstack/react-query';\nimport { DefaultPluginKinds, PluginImplementation, PluginMetadata, PluginType } from '../model';\n\nexport interface PluginRegistryContextType {\n getPlugin<T extends PluginType>(pluginType: T, kind: string): Promise<PluginImplementation<T>>;\n listPluginMetadata(pluginType: PluginType): Promise<PluginMetadata[]>;\n defaultPluginKinds?: DefaultPluginKinds;\n}\n\nexport const PluginRegistryContext = createContext<PluginRegistryContextType | undefined>(undefined);\n\n/**\n * Use the PluginRegistry context directly. This is meant as an escape hatch for custom async flows. You should probably\n * be using `usePlugin` or `useListPluginMetadata` instead.\n */\nexport function usePluginRegistry() {\n const ctx = useContext(PluginRegistryContext);\n if (ctx === undefined) {\n throw new Error('PluginRegistryContext not found. Did you forget a provider?');\n }\n return ctx;\n}\n\n// Allows consumers to pass useQuery options from react-query when loading a plugin\ntype UsePluginOptions<T extends PluginType> = Omit<\n UseQueryOptions<PluginImplementation<T>, Error, PluginImplementation<T>, [string, PluginType, string]>,\n 'queryKey' | 'queryFn'\n>;\n\n/**\n * Loads a plugin and returns the plugin implementation, along with loading/error state.\n */\nexport function usePlugin<T extends PluginType>(pluginType: T, kind: string, options?: UsePluginOptions<T>) {\n // We never want to ask for a plugin when the kind isn't set yet, so disable those queries automatically\n options = {\n ...options,\n enabled: (options?.enabled ?? true) && kind !== '',\n };\n const { getPlugin } = usePluginRegistry();\n return useQuery(['getPlugin', pluginType, kind], () => getPlugin(pluginType, kind), options);\n}\n\n/**\n * Loads a list of plugins and returns the plugin implementation, along with loading/error state.\n */\nexport function usePlugins<T extends PluginType>(pluginType: T, plugins: Array<{ kind: string }>) {\n const { getPlugin } = usePluginRegistry();\n return useQueries({\n queries: plugins.map((p) => {\n return {\n queryKey: ['getPlugin', pluginType, p.kind],\n queryFn: () => getPlugin(pluginType, p.kind),\n };\n }),\n });\n}\n\n// Allow consumers to pass useQuery options from react-query when listing metadata\ntype UseListPluginMetadataOptions = Omit<\n UseQueryOptions<PluginMetadata[], Error, PluginMetadata[], [string, PluginType]>,\n 'queryKey' | 'queryFn'\n>;\n\n/**\n * Gets a list of plugin metadata for the specified plugin type and returns it, along with loading/error state.\n */\nexport function useListPluginMetadata(pluginType: PluginType, options?: UseListPluginMetadataOptions) {\n const { listPluginMetadata } = usePluginRegistry();\n return useQuery(['listPluginMetadata', pluginType], () => listPluginMetadata(pluginType), options);\n}\n"],"names":["createContext","useContext","useQuery","useQueries","PluginRegistryContext","undefined","usePluginRegistry","ctx","Error","usePlugin","pluginType","kind","options","enabled","getPlugin","usePlugins","plugins","queries","map","p","queryKey","queryFn","useListPluginMetadata","listPluginMetadata"],"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,SAASA,aAAa,EAAEC,UAAU,QAAQ,OAAO,CAAC;AAClD,SAASC,QAAQ,EAAEC,UAAU,QAAyB,uBAAuB,CAAC;AAS9E,OAAO,MAAMC,qBAAqB,GAAGJ,aAAa,CAAwCK,SAAS,CAAC,CAAC;AAErG;;;CAGC,GACD,OAAO,SAASC,iBAAiB,GAAG;IAClC,MAAMC,GAAG,GAAGN,UAAU,CAACG,qBAAqB,CAAC,AAAC;IAC9C,IAAIG,GAAG,KAAKF,SAAS,EAAE;QACrB,MAAM,IAAIG,KAAK,CAAC,6DAA6D,CAAC,CAAC;IACjF,CAAC;IACD,OAAOD,GAAG,CAAC;AACb,CAAC;AAQD;;CAEC,GACD,OAAO,SAASE,SAAS,CAAuBC,UAAa,EAAEC,IAAY,EAAEC,OAA6B,EAAE;QAI9FA,GAAgB;IAH5B,wGAAwG;IACxGA,OAAO,GAAG;QACR,GAAGA,OAAO;QACVC,OAAO,EAAE,AAACD,CAAAA,CAAAA,GAAgB,GAAhBA,OAAO,aAAPA,OAAO,WAAS,GAAhBA,KAAAA,CAAgB,GAAhBA,OAAO,CAAEC,OAAO,cAAhBD,GAAgB,cAAhBA,GAAgB,GAAI,IAAI,CAAA,IAAKD,IAAI,KAAK,EAAE;KACnD,CAAC;IACF,MAAM,EAAEG,SAAS,CAAA,EAAE,GAAGR,iBAAiB,EAAE,AAAC;IAC1C,OAAOJ,QAAQ,CAAC;QAAC,WAAW;QAAEQ,UAAU;QAAEC,IAAI;KAAC,EAAE,IAAMG,SAAS,CAACJ,UAAU,EAAEC,IAAI,CAAC,EAAEC,OAAO,CAAC,CAAC;AAC/F,CAAC;AAED;;CAEC,GACD,OAAO,SAASG,UAAU,CAAuBL,UAAa,EAAEM,OAAgC,EAAE;IAChG,MAAM,EAAEF,SAAS,CAAA,EAAE,GAAGR,iBAAiB,EAAE,AAAC;IAC1C,OAAOH,UAAU,CAAC;QAChBc,OAAO,EAAED,OAAO,CAACE,GAAG,CAAC,CAACC,CAAC,GAAK;YAC1B,OAAO;gBACLC,QAAQ,EAAE;oBAAC,WAAW;oBAAEV,UAAU;oBAAES,CAAC,CAACR,IAAI;iBAAC;gBAC3CU,OAAO,EAAE,IAAMP,SAAS,CAACJ,UAAU,EAAES,CAAC,CAACR,IAAI,CAAC;aAC7C,CAAC;QACJ,CAAC,CAAC;KACH,CAAC,CAAC;AACL,CAAC;AAQD;;CAEC,GACD,OAAO,SAASW,qBAAqB,CAACZ,UAAsB,EAAEE,OAAsC,EAAE;IACpG,MAAM,EAAEW,kBAAkB,CAAA,EAAE,GAAGjB,iBAAiB,EAAE,AAAC;IACnD,OAAOJ,QAAQ,CAAC;QAAC,oBAAoB;QAAEQ,UAAU;KAAC,EAAE,IAAMa,kBAAkB,CAACb,UAAU,CAAC,EAAEE,OAAO,CAAC,CAAC;AACrG,CAAC"}
@@ -1,8 +1,13 @@
1
1
  /// <reference types="react" />
2
2
  import { RenderOptions } from '@testing-library/react';
3
+ import { DefaultPluginKinds } from '../model';
4
+ declare type ContextOptions = {
5
+ defaultPluginKinds?: DefaultPluginKinds;
6
+ };
3
7
  /**
4
8
  * Test helper to render a React component with some common app-level providers, as well as the PluginRegistry
5
9
  * wrapped around it.
6
10
  */
7
- export declare function renderWithContext(ui: React.ReactNode, options?: Omit<RenderOptions, 'queries'>): import("@testing-library/react").RenderResult<typeof import("@testing-library/dom/types/queries"), HTMLElement, HTMLElement>;
11
+ export declare function renderWithContext(ui: React.ReactNode, renderOptions?: Omit<RenderOptions, 'queries'>, contextOptions?: ContextOptions): import("@testing-library/react").RenderResult<typeof import("@testing-library/dom/types/queries"), HTMLElement, HTMLElement>;
12
+ export {};
8
13
  //# sourceMappingURL=render.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../../src/test/render.tsx"],"names":[],"mappings":";AAaA,OAAO,EAAU,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAa/D;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,KAAK,CAAC,SAAS,EAAE,OAAO,CAAC,EAAE,IAAI,CAAC,aAAa,EAAE,SAAS,CAAC,gIAY9F"}
1
+ {"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../../src/test/render.tsx"],"names":[],"mappings":";AAaA,OAAO,EAAU,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAG/D,OAAO,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAW9C,aAAK,cAAc,GAAG;IACpB,kBAAkB,CAAC,EAAE,kBAAkB,CAAC;CACzC,CAAC;AAEF;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,EAAE,EAAE,KAAK,CAAC,SAAS,EACnB,aAAa,CAAC,EAAE,IAAI,CAAC,aAAa,EAAE,SAAS,CAAC,EAC9C,cAAc,CAAC,EAAE,cAAc,gIAehC"}
@@ -25,7 +25,7 @@ const testLogger = {
25
25
  /**
26
26
  * Test helper to render a React component with some common app-level providers, as well as the PluginRegistry
27
27
  * wrapped around it.
28
- */ export function renderWithContext(ui, options) {
28
+ */ export function renderWithContext(ui, renderOptions, contextOptions) {
29
29
  // Create a new QueryClient for each test to avoid caching issues
30
30
  const queryClient = new QueryClient({
31
31
  defaultOptions: {
@@ -40,9 +40,10 @@ const testLogger = {
40
40
  client: queryClient,
41
41
  children: /*#__PURE__*/ _jsx(PluginRegistry, {
42
42
  pluginLoader: testPluginLoader,
43
+ defaultPluginKinds: contextOptions === null || contextOptions === void 0 ? void 0 : contextOptions.defaultPluginKinds,
43
44
  children: ui
44
45
  })
45
- }), options);
46
+ }), renderOptions);
46
47
  }
47
48
 
48
49
  //# sourceMappingURL=render.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/test/render.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 { render, RenderOptions } from '@testing-library/react';\nimport { QueryClient, QueryClientProvider } from '@tanstack/react-query';\nimport { PluginRegistry } from '../components/PluginRegistry';\nimport { testPluginLoader } from './test-plugins';\n\nconst testLogger = {\n log: console.log,\n warn: console.warn,\n error: () => {\n // Don't log network errors in tests to the console\n },\n};\n\n/**\n * Test helper to render a React component with some common app-level providers, as well as the PluginRegistry\n * wrapped around it.\n */\nexport function renderWithContext(ui: React.ReactNode, options?: Omit<RenderOptions, 'queries'>) {\n // Create a new QueryClient for each test to avoid caching issues\n const queryClient = new QueryClient({\n defaultOptions: { queries: { refetchOnWindowFocus: false, retry: false } },\n logger: testLogger,\n });\n return render(\n <QueryClientProvider client={queryClient}>\n <PluginRegistry pluginLoader={testPluginLoader}>{ui}</PluginRegistry>\n </QueryClientProvider>,\n options\n );\n}\n"],"names":["render","QueryClient","QueryClientProvider","PluginRegistry","testPluginLoader","testLogger","log","console","warn","error","renderWithContext","ui","options","queryClient","defaultOptions","queries","refetchOnWindowFocus","retry","logger","client","pluginLoader"],"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,SAASA,MAAM,QAAuB,wBAAwB,CAAC;AAC/D,SAASC,WAAW,EAAEC,mBAAmB,QAAQ,uBAAuB,CAAC;AACzE,SAASC,cAAc,QAAQ,8BAA8B,CAAC;AAC9D,SAASC,gBAAgB,QAAQ,gBAAgB,CAAC;AAElD,MAAMC,UAAU,GAAG;IACjBC,GAAG,EAAEC,OAAO,CAACD,GAAG;IAChBE,IAAI,EAAED,OAAO,CAACC,IAAI;IAClBC,KAAK,EAAE,IAAM;IACX,mDAAmD;IACrD,CAAC;CACF,AAAC;AAEF;;;CAGC,GACD,OAAO,SAASC,iBAAiB,CAACC,EAAmB,EAAEC,OAAwC,EAAE;IAC/F,iEAAiE;IACjE,MAAMC,WAAW,GAAG,IAAIZ,WAAW,CAAC;QAClCa,cAAc,EAAE;YAAEC,OAAO,EAAE;gBAAEC,oBAAoB,EAAE,KAAK;gBAAEC,KAAK,EAAE,KAAK;aAAE;SAAE;QAC1EC,MAAM,EAAEb,UAAU;KACnB,CAAC,AAAC;IACH,OAAOL,MAAM,eACX,KAACE,mBAAmB;QAACiB,MAAM,EAAEN,WAAW;kBACtC,cAAA,KAACV,cAAc;YAACiB,YAAY,EAAEhB,gBAAgB;sBAAGO,EAAE;UAAkB;MACjD,EACtBC,OAAO,CACR,CAAC;AACJ,CAAC"}
1
+ {"version":3,"sources":["../../src/test/render.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 { render, RenderOptions } from '@testing-library/react';\nimport { QueryClient, QueryClientProvider } from '@tanstack/react-query';\nimport { PluginRegistry } from '../components/PluginRegistry';\nimport { DefaultPluginKinds } from '../model';\nimport { testPluginLoader } from './test-plugins';\n\nconst testLogger = {\n log: console.log,\n warn: console.warn,\n error: () => {\n // Don't log network errors in tests to the console\n },\n};\n\ntype ContextOptions = {\n defaultPluginKinds?: DefaultPluginKinds;\n};\n\n/**\n * Test helper to render a React component with some common app-level providers, as well as the PluginRegistry\n * wrapped around it.\n */\nexport function renderWithContext(\n ui: React.ReactNode,\n renderOptions?: Omit<RenderOptions, 'queries'>,\n contextOptions?: ContextOptions\n) {\n // Create a new QueryClient for each test to avoid caching issues\n const queryClient = new QueryClient({\n defaultOptions: { queries: { refetchOnWindowFocus: false, retry: false } },\n logger: testLogger,\n });\n return render(\n <QueryClientProvider client={queryClient}>\n <PluginRegistry pluginLoader={testPluginLoader} defaultPluginKinds={contextOptions?.defaultPluginKinds}>\n {ui}\n </PluginRegistry>\n </QueryClientProvider>,\n renderOptions\n );\n}\n"],"names":["render","QueryClient","QueryClientProvider","PluginRegistry","testPluginLoader","testLogger","log","console","warn","error","renderWithContext","ui","renderOptions","contextOptions","queryClient","defaultOptions","queries","refetchOnWindowFocus","retry","logger","client","pluginLoader","defaultPluginKinds"],"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,SAASA,MAAM,QAAuB,wBAAwB,CAAC;AAC/D,SAASC,WAAW,EAAEC,mBAAmB,QAAQ,uBAAuB,CAAC;AACzE,SAASC,cAAc,QAAQ,8BAA8B,CAAC;AAE9D,SAASC,gBAAgB,QAAQ,gBAAgB,CAAC;AAElD,MAAMC,UAAU,GAAG;IACjBC,GAAG,EAAEC,OAAO,CAACD,GAAG;IAChBE,IAAI,EAAED,OAAO,CAACC,IAAI;IAClBC,KAAK,EAAE,IAAM;IACX,mDAAmD;IACrD,CAAC;CACF,AAAC;AAMF;;;CAGC,GACD,OAAO,SAASC,iBAAiB,CAC/BC,EAAmB,EACnBC,aAA8C,EAC9CC,cAA+B,EAC/B;IACA,iEAAiE;IACjE,MAAMC,WAAW,GAAG,IAAIb,WAAW,CAAC;QAClCc,cAAc,EAAE;YAAEC,OAAO,EAAE;gBAAEC,oBAAoB,EAAE,KAAK;gBAAEC,KAAK,EAAE,KAAK;aAAE;SAAE;QAC1EC,MAAM,EAAEd,UAAU;KACnB,CAAC,AAAC;IACH,OAAOL,MAAM,eACX,KAACE,mBAAmB;QAACkB,MAAM,EAAEN,WAAW;kBACtC,cAAA,KAACX,cAAc;YAACkB,YAAY,EAAEjB,gBAAgB;YAAEkB,kBAAkB,EAAET,cAAc,aAAdA,cAAc,WAAoB,GAAlCA,KAAAA,CAAkC,GAAlCA,cAAc,CAAES,kBAAkB;sBACnGX,EAAE;UACY;MACG,EACtBC,aAAa,CACd,CAAC;AACJ,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@perses-dev/plugin-system",
3
- "version": "0.18.0",
3
+ "version": "0.20.0",
4
4
  "description": "The plugin feature in Pereses",
5
5
  "license": "Apache-2.0",
6
6
  "homepage": "https://github.com/perses/perses/blob/main/README.md",
@@ -27,8 +27,8 @@
27
27
  "lint:fix": "eslint --fix src --ext .ts,.tsx"
28
28
  },
29
29
  "dependencies": {
30
- "@perses-dev/components": "^0.18.0",
31
- "@perses-dev/core": "^0.18.0",
30
+ "@perses-dev/components": "^0.20.0",
31
+ "@perses-dev/core": "^0.20.0",
32
32
  "immer": "^9.0.15",
33
33
  "use-immer": "^0.7.0",
34
34
  "use-query-params": "^2.1.2"