Expressions service (#36885)
This commit is contained in:
parent
5e59de262b
commit
3232fc80d1
|
@ -18,3 +18,5 @@
|
|||
*/
|
||||
|
||||
export { Registry } from './lib/registry';
|
||||
|
||||
export { fromExpression, Ast } from './lib/ast';
|
||||
|
|
22
packages/kbn-interpreter/src/common/lib/ast.d.ts
vendored
Normal file
22
packages/kbn-interpreter/src/common/lib/ast.d.ts
vendored
Normal file
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
export type Ast = unknown;
|
||||
|
||||
export declare function fromExpression(expression: string): Ast;
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import { useRef, useEffect } from 'react';
|
||||
import React from 'react';
|
||||
import { Ast } from '@kbn/interpreter/common';
|
||||
|
||||
import { ExpressionRunnerOptions, ExpressionRunner } from './expression_runner';
|
||||
|
||||
// Accept all options of the runner as props except for the
|
||||
// dom element which is provided by the component itself
|
||||
export type ExpressionRendererProps = Pick<
|
||||
ExpressionRunnerOptions,
|
||||
Exclude<keyof ExpressionRunnerOptions, 'element'>
|
||||
> & {
|
||||
expression: string | Ast;
|
||||
};
|
||||
|
||||
export type ExpressionRenderer = React.FC<ExpressionRendererProps>;
|
||||
|
||||
export const createRenderer = (run: ExpressionRunner): ExpressionRenderer => ({
|
||||
expression,
|
||||
...options
|
||||
}: ExpressionRendererProps) => {
|
||||
const mountpoint: React.MutableRefObject<null | HTMLDivElement> = useRef(null);
|
||||
|
||||
useEffect(
|
||||
() => {
|
||||
if (mountpoint.current) {
|
||||
run(expression, { ...options, element: mountpoint.current });
|
||||
}
|
||||
},
|
||||
[expression, mountpoint.current]
|
||||
);
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={el => {
|
||||
mountpoint.current = el;
|
||||
}}
|
||||
/>
|
||||
);
|
||||
};
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import { Ast, fromExpression } from '@kbn/interpreter/common';
|
||||
|
||||
import { RequestAdapter, DataAdapter } from 'ui/inspector/adapters';
|
||||
import { RenderFunctionsRegistry, Interpreter, Result } from './expressions_service';
|
||||
|
||||
export interface ExpressionRunnerOptions {
|
||||
// TODO use the real types here once they are ready
|
||||
context?: object;
|
||||
getInitialContext?: () => object;
|
||||
element?: Element;
|
||||
}
|
||||
|
||||
export type ExpressionRunner = (
|
||||
expression: string | Ast,
|
||||
options: ExpressionRunnerOptions
|
||||
) => Promise<Result>;
|
||||
|
||||
export const createRunFn = (
|
||||
renderersRegistry: RenderFunctionsRegistry,
|
||||
interpreterPromise: Promise<Interpreter>
|
||||
): ExpressionRunner => async (expressionOrAst, { element, context, getInitialContext }) => {
|
||||
// TODO: make interpreter initialization synchronous to avoid this
|
||||
const interpreter = await interpreterPromise;
|
||||
const ast =
|
||||
typeof expressionOrAst === 'string' ? fromExpression(expressionOrAst) : expressionOrAst;
|
||||
|
||||
const response = await interpreter.interpretAst(ast, context || { type: 'null' }, {
|
||||
getInitialContext: getInitialContext || (() => ({})),
|
||||
inspectorAdapters: {
|
||||
// TODO connect real adapters
|
||||
requests: new RequestAdapter(),
|
||||
data: new DataAdapter(),
|
||||
},
|
||||
});
|
||||
|
||||
if (element) {
|
||||
if (response.type === 'render' && response.as) {
|
||||
renderersRegistry.get(response.as).render(element, response.value, {
|
||||
onDestroy: fn => {
|
||||
// TODO implement
|
||||
},
|
||||
done: () => {
|
||||
// TODO implement
|
||||
},
|
||||
});
|
||||
} else {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('Unexpected result of expression', response);
|
||||
}
|
||||
}
|
||||
|
||||
return response;
|
||||
};
|
|
@ -0,0 +1,217 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import { fromExpression, Ast } from '@kbn/interpreter/common';
|
||||
|
||||
import {
|
||||
ExpressionsService,
|
||||
RenderFunctionsRegistry,
|
||||
RenderFunction,
|
||||
Interpreter,
|
||||
ExpressionsServiceDependencies,
|
||||
Result,
|
||||
ExpressionsSetup,
|
||||
} from './expressions_service';
|
||||
import { mount } from 'enzyme';
|
||||
import React from 'react';
|
||||
|
||||
const waitForInterpreterRun = async () => {
|
||||
// Wait for two ticks with empty callback queues
|
||||
// This makes sure the runFn promise and actual interpretAst
|
||||
// promise have been resolved and processed
|
||||
await new Promise(resolve => setTimeout(resolve));
|
||||
await new Promise(resolve => setTimeout(resolve));
|
||||
};
|
||||
|
||||
describe('expressions_service', () => {
|
||||
let interpreterMock: jest.Mocked<Interpreter>;
|
||||
let renderFunctionMock: jest.Mocked<RenderFunction>;
|
||||
let setupPluginsMock: ExpressionsServiceDependencies;
|
||||
const expressionResult: Result = { type: 'render', as: 'abc', value: {} };
|
||||
|
||||
let api: ExpressionsSetup;
|
||||
let testExpression: string;
|
||||
let testAst: Ast;
|
||||
|
||||
beforeEach(() => {
|
||||
interpreterMock = { interpretAst: jest.fn(_ => Promise.resolve(expressionResult)) };
|
||||
renderFunctionMock = ({
|
||||
render: jest.fn(),
|
||||
} as unknown) as jest.Mocked<RenderFunction>;
|
||||
setupPluginsMock = {
|
||||
interpreter: {
|
||||
getInterpreter: () => Promise.resolve({ interpreter: interpreterMock }),
|
||||
renderersRegistry: ({
|
||||
get: () => renderFunctionMock,
|
||||
} as unknown) as RenderFunctionsRegistry,
|
||||
},
|
||||
};
|
||||
api = new ExpressionsService().setup(setupPluginsMock);
|
||||
testExpression = 'test | expression';
|
||||
testAst = fromExpression(testExpression);
|
||||
});
|
||||
|
||||
describe('expression_runner', () => {
|
||||
it('should return run function', () => {
|
||||
expect(typeof api.run).toBe('function');
|
||||
});
|
||||
|
||||
it('should call the interpreter with parsed expression', async () => {
|
||||
await api.run(testExpression, { element: document.createElement('div') });
|
||||
expect(interpreterMock.interpretAst).toHaveBeenCalledWith(
|
||||
testAst,
|
||||
expect.anything(),
|
||||
expect.anything()
|
||||
);
|
||||
});
|
||||
|
||||
it('should call the interpreter with given context and getInitialContext functions', async () => {
|
||||
const getInitialContext = () => ({});
|
||||
const context = {};
|
||||
|
||||
await api.run(testExpression, { getInitialContext, context });
|
||||
const interpretCall = interpreterMock.interpretAst.mock.calls[0];
|
||||
|
||||
expect(interpretCall[1]).toBe(context);
|
||||
expect(interpretCall[2].getInitialContext).toBe(getInitialContext);
|
||||
});
|
||||
|
||||
it('should call the interpreter with passed in ast', async () => {
|
||||
await api.run(testAst, { element: document.createElement('div') });
|
||||
expect(interpreterMock.interpretAst).toHaveBeenCalledWith(
|
||||
testAst,
|
||||
expect.anything(),
|
||||
expect.anything()
|
||||
);
|
||||
});
|
||||
|
||||
it('should call the render function with the result and element', async () => {
|
||||
const element = document.createElement('div');
|
||||
|
||||
await api.run(testAst, { element });
|
||||
expect(renderFunctionMock.render).toHaveBeenCalledWith(
|
||||
element,
|
||||
expressionResult.value,
|
||||
expect.anything()
|
||||
);
|
||||
expect(interpreterMock.interpretAst).toHaveBeenCalledWith(
|
||||
testAst,
|
||||
expect.anything(),
|
||||
expect.anything()
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('expression_renderer', () => {
|
||||
it('should call interpreter and render function when called through react component', async () => {
|
||||
const ExpressionRenderer = api.ExpressionRenderer;
|
||||
|
||||
mount(<ExpressionRenderer expression={testExpression} />);
|
||||
|
||||
await waitForInterpreterRun();
|
||||
|
||||
expect(renderFunctionMock.render).toHaveBeenCalledWith(
|
||||
expect.any(Element),
|
||||
expressionResult.value,
|
||||
expect.anything()
|
||||
);
|
||||
expect(interpreterMock.interpretAst).toHaveBeenCalledWith(
|
||||
testAst,
|
||||
expect.anything(),
|
||||
expect.anything()
|
||||
);
|
||||
});
|
||||
|
||||
it('should call the interpreter with given context and getInitialContext functions', async () => {
|
||||
const getInitialContext = () => ({});
|
||||
const context = {};
|
||||
|
||||
const ExpressionRenderer = api.ExpressionRenderer;
|
||||
|
||||
mount(
|
||||
<ExpressionRenderer
|
||||
expression={testExpression}
|
||||
getInitialContext={getInitialContext}
|
||||
context={context}
|
||||
/>
|
||||
);
|
||||
|
||||
await waitForInterpreterRun();
|
||||
|
||||
const interpretCall = interpreterMock.interpretAst.mock.calls[0];
|
||||
|
||||
expect(interpretCall[1]).toBe(context);
|
||||
expect(interpretCall[2].getInitialContext).toBe(getInitialContext);
|
||||
});
|
||||
|
||||
it('should call interpreter and render function again if expression changes', async () => {
|
||||
const ExpressionRenderer = api.ExpressionRenderer;
|
||||
|
||||
const instance = mount(<ExpressionRenderer expression={testExpression} />);
|
||||
|
||||
await waitForInterpreterRun();
|
||||
|
||||
expect(renderFunctionMock.render).toHaveBeenCalledWith(
|
||||
expect.any(Element),
|
||||
expressionResult.value,
|
||||
expect.anything()
|
||||
);
|
||||
expect(interpreterMock.interpretAst).toHaveBeenCalledWith(
|
||||
testAst,
|
||||
expect.anything(),
|
||||
expect.anything()
|
||||
);
|
||||
|
||||
instance.setProps({ expression: 'supertest | expression ' });
|
||||
|
||||
await waitForInterpreterRun();
|
||||
|
||||
expect(renderFunctionMock.render).toHaveBeenCalledTimes(2);
|
||||
expect(interpreterMock.interpretAst).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
|
||||
it('should not call interpreter and render function again if expression does not change', async () => {
|
||||
const ast = fromExpression(testExpression);
|
||||
|
||||
const ExpressionRenderer = api.ExpressionRenderer;
|
||||
|
||||
const instance = mount(<ExpressionRenderer expression={testExpression} />);
|
||||
|
||||
await waitForInterpreterRun();
|
||||
|
||||
expect(renderFunctionMock.render).toHaveBeenCalledWith(
|
||||
expect.any(Element),
|
||||
expressionResult.value,
|
||||
expect.anything()
|
||||
);
|
||||
expect(interpreterMock.interpretAst).toHaveBeenCalledWith(
|
||||
ast,
|
||||
expect.anything(),
|
||||
expect.anything()
|
||||
);
|
||||
|
||||
instance.update();
|
||||
|
||||
await waitForInterpreterRun();
|
||||
|
||||
expect(renderFunctionMock.render).toHaveBeenCalledTimes(1);
|
||||
expect(interpreterMock.interpretAst).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,126 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import { Ast } from '@kbn/interpreter/common';
|
||||
|
||||
// TODO:
|
||||
// this type import and the types below them should be switched to the types of
|
||||
// the interpreter plugin itself once they are ready
|
||||
import { Registry } from '@kbn/interpreter/common';
|
||||
import { Adapters } from 'ui/inspector';
|
||||
import { Query, Filters, TimeRange } from 'ui/embeddable';
|
||||
import { createRenderer } from './expression_renderer';
|
||||
import { createRunFn } from './expression_runner';
|
||||
|
||||
export interface InitialContextObject {
|
||||
timeRange?: TimeRange;
|
||||
filters?: Filters;
|
||||
query?: Query;
|
||||
}
|
||||
|
||||
export type getInitialContextFunction = () => InitialContextObject;
|
||||
|
||||
export interface Handlers {
|
||||
getInitialContext: getInitialContextFunction;
|
||||
inspectorAdapters?: Adapters;
|
||||
}
|
||||
|
||||
type Context = object;
|
||||
export interface Result {
|
||||
type: string;
|
||||
as?: string;
|
||||
value?: unknown;
|
||||
}
|
||||
|
||||
interface RenderHandlers {
|
||||
done: () => void;
|
||||
onDestroy: (fn: () => void) => void;
|
||||
}
|
||||
|
||||
export interface RenderFunction {
|
||||
name: string;
|
||||
displayName: string;
|
||||
help: string;
|
||||
validate: () => void;
|
||||
reuseDomNode: boolean;
|
||||
render: (domNode: Element, data: unknown, handlers: RenderHandlers) => void;
|
||||
}
|
||||
|
||||
export type RenderFunctionsRegistry = Registry<unknown, RenderFunction>;
|
||||
|
||||
export interface Interpreter {
|
||||
interpretAst(ast: Ast, context: Context, handlers: Handlers): Promise<Result>;
|
||||
}
|
||||
|
||||
type InterpreterGetter = () => Promise<{ interpreter: Interpreter }>;
|
||||
|
||||
export interface ExpressionsServiceDependencies {
|
||||
interpreter: {
|
||||
renderersRegistry: RenderFunctionsRegistry;
|
||||
getInterpreter: InterpreterGetter;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Expressions Service
|
||||
* @internal
|
||||
*/
|
||||
export class ExpressionsService {
|
||||
public setup({
|
||||
interpreter: { renderersRegistry, getInterpreter },
|
||||
}: ExpressionsServiceDependencies) {
|
||||
const run = createRunFn(
|
||||
renderersRegistry,
|
||||
getInterpreter().then(({ interpreter }) => interpreter)
|
||||
);
|
||||
|
||||
return {
|
||||
/**
|
||||
* **experimential** This API is experimential and might be removed in the future
|
||||
* without notice
|
||||
*
|
||||
* Executes the given expression string or ast and renders the result into the
|
||||
* given DOM element.
|
||||
*
|
||||
*
|
||||
* @param expressionOrAst
|
||||
* @param element
|
||||
*/
|
||||
run,
|
||||
/**
|
||||
* **experimential** This API is experimential and might be removed in the future
|
||||
* without notice
|
||||
*
|
||||
* Component which executes and renders the given expression in a div element.
|
||||
* The expression is re-executed on updating the props.
|
||||
*
|
||||
* This is a React bridge of the `run` method
|
||||
* @param props
|
||||
*/
|
||||
ExpressionRenderer: createRenderer(run),
|
||||
};
|
||||
}
|
||||
|
||||
public stop() {
|
||||
// nothing to do here yet
|
||||
}
|
||||
}
|
||||
|
||||
/** @public */
|
||||
export type ExpressionsSetup = ReturnType<ExpressionsService['setup']>;
|
22
src/legacy/core_plugins/data/public/expressions/index.ts
Normal file
22
src/legacy/core_plugins/data/public/expressions/index.ts
Normal file
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
export { ExpressionsService, ExpressionsSetup } from './expressions_service';
|
||||
export { ExpressionRenderer, ExpressionRendererProps } from './expression_renderer';
|
||||
export { ExpressionRunner } from './expression_runner';
|
|
@ -17,6 +17,15 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
// TODO these are imports from the old plugin world.
|
||||
// Once the new platform is ready, they can get removed
|
||||
// and handled by the platform itself in the setup method
|
||||
// of the ExpressionExectorService
|
||||
// @ts-ignore
|
||||
import { getInterpreter } from 'plugins/interpreter/interpreter';
|
||||
// @ts-ignore
|
||||
import { renderersRegistry } from 'plugins/interpreter/registries';
|
||||
import { ExpressionsService, ExpressionsSetup } from './expressions';
|
||||
import { SearchService, SearchSetup } from './search';
|
||||
import { QueryService, QuerySetup } from './query';
|
||||
import { IndexPatternsService, IndexPatternsSetup } from './index_patterns';
|
||||
|
@ -25,18 +34,26 @@ class DataPlugin {
|
|||
private readonly indexPatterns: IndexPatternsService;
|
||||
private readonly search: SearchService;
|
||||
private readonly query: QueryService;
|
||||
private readonly expressions: ExpressionsService;
|
||||
|
||||
constructor() {
|
||||
this.indexPatterns = new IndexPatternsService();
|
||||
this.query = new QueryService();
|
||||
this.search = new SearchService();
|
||||
this.expressions = new ExpressionsService();
|
||||
}
|
||||
|
||||
public setup() {
|
||||
public setup(): DataSetup {
|
||||
return {
|
||||
indexPatterns: this.indexPatterns.setup(),
|
||||
search: this.search.setup(),
|
||||
query: this.query.setup(),
|
||||
expressions: this.expressions.setup({
|
||||
interpreter: {
|
||||
getInterpreter,
|
||||
renderersRegistry,
|
||||
},
|
||||
}),
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -44,6 +61,7 @@ class DataPlugin {
|
|||
this.indexPatterns.stop();
|
||||
this.search.stop();
|
||||
this.query.stop();
|
||||
this.expressions.stop();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -57,9 +75,13 @@ export const data = new DataPlugin().setup();
|
|||
/** @public */
|
||||
export interface DataSetup {
|
||||
indexPatterns: IndexPatternsSetup;
|
||||
expressions: ExpressionsSetup;
|
||||
search: SearchSetup;
|
||||
query: QuerySetup;
|
||||
}
|
||||
|
||||
/** @public types */
|
||||
export { ExpressionRenderer, ExpressionRendererProps, ExpressionRunner } from './expressions';
|
||||
|
||||
/** @public types */
|
||||
export { IndexPattern, StaticIndexPattern, StaticIndexPatternField, Field } from './index_patterns';
|
||||
|
|
|
@ -25,15 +25,15 @@ import { getInterpreter } from 'plugins/interpreter/interpreter';
|
|||
import { Adapters } from 'ui/inspector';
|
||||
import { Filters, Query, TimeRange } from 'ui/visualize';
|
||||
|
||||
interface InitialContextObject {
|
||||
export interface InitialContextObject {
|
||||
timeRange?: TimeRange;
|
||||
filters?: Filters;
|
||||
query?: Query;
|
||||
}
|
||||
|
||||
type getInitialContextFunction = () => InitialContextObject;
|
||||
export type getInitialContextFunction = () => InitialContextObject;
|
||||
|
||||
interface RunPipelineHandlers {
|
||||
export interface RunPipelineHandlers {
|
||||
getInitialContext: getInitialContextFunction;
|
||||
inspectorAdapters?: Adapters;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue