Move Expression function typings from Canvas to OSS.

This commit is contained in:
Luke Elmers 2019-05-30 13:37:37 -06:00 committed by GitHub
parent b75bbd6904
commit 100b088573
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 394 additions and 33 deletions

View file

@ -17,17 +17,29 @@
* under the License.
*/
// @ts-ignore
import { boolean } from './boolean';
// @ts-ignore
import { datatable } from './datatable';
// @ts-ignore
import { error } from './error';
// @ts-ignore
import { filter } from './filter';
// @ts-ignore
import { image } from './image';
// @ts-ignore
import { nullType } from './null';
// @ts-ignore
import { number } from './number';
// @ts-ignore
import { pointseries } from './pointseries';
// @ts-ignore
import { render } from './render';
// @ts-ignore
import { shape } from './shape';
// @ts-ignore
import { string } from './string';
// @ts-ignore
import { style } from './style';
import { kibanaContext } from './kibana_context';
import { kibanaDatatable } from './kibana_datatable';
@ -48,3 +60,6 @@ export const typeSpecs = [
kibanaContext,
kibanaDatatable,
];
export { KibanaContext } from './kibana_context';
export { KibanaDatatable } from './kibana_datatable';

View file

@ -17,12 +17,23 @@
* under the License.
*/
import { Filters, Query, TimeRange } from 'ui/visualize';
const name = 'kibana_context';
export interface KibanaContext {
type: typeof name;
query?: Query;
filters?: Filters;
timeRange?: TimeRange;
}
export const kibanaContext = () => ({
name: 'kibana_context',
name,
from: {
null: () => {
return {
type: 'kibana_context',
type: name,
};
},
},
@ -32,5 +43,5 @@ export const kibanaContext = () => ({
type: 'null',
};
},
}
},
});

View file

@ -19,14 +19,32 @@
import { map } from 'lodash';
const name = 'kibana_datatable';
interface Column {
id: string;
name: string;
}
interface Row {
[key: string]: unknown;
}
export interface KibanaDatatable {
type: typeof name;
columns: Column[];
rows: Row[];
}
export const kibanaDatatable = () => ({
name: 'kibana_datatable',
name,
from: {
datatable: context => {
// TODO: import datatable types here instead of using any
datatable: (context: any) => {
return {
type: 'kibana_datatable',
type: name,
rows: context.rows,
columns: context.columns.map(column => {
columns: context.columns.map((column: any) => {
return {
id: column.name,
name: column.name,
@ -34,15 +52,16 @@ export const kibanaDatatable = () => ({
}),
};
},
pointseries: context => {
const columns = map(context.columns, (column, name) => {
return { id: name, name, ...column };
// TODO: import pointseries types here instead of using any
pointseries: (context: any) => {
const columns = map(context.columns, (column, n) => {
return { id: n, name: n, ...column };
});
return {
type: 'kibana_datatable',
type: name,
rows: context.rows,
columns: columns,
columns,
};
}
},
},
});

View file

@ -19,11 +19,15 @@
import { get } from 'lodash';
import { i18n } from '@kbn/i18n';
// @ts-ignore
import { CourierRequestHandlerProvider } from 'ui/vis/request_handlers/courier';
import { AggConfigs } from 'ui/vis/agg_configs';
// @ts-ignore
import { AggConfigs } from 'ui/vis/agg_configs.js';
// need to get rid of angular from these
// @ts-ignore
import { IndexPatternsProvider } from 'ui/index_patterns';
// @ts-ignore
import { SearchSourceProvider } from 'ui/courier/search_source';
import { FilterBarQueryFilterProvider } from 'ui/filter_manager/query_filter';
@ -32,37 +36,56 @@ import chrome from 'ui/chrome';
const courierRequestHandlerProvider = CourierRequestHandlerProvider;
const courierRequestHandler = courierRequestHandlerProvider().handler;
export const esaggs = () => ({
name: 'esaggs',
import { ExpressionFunction } from '../../types';
import { KibanaContext, KibanaDatatable } from '../../common/types';
const name = 'esaggs';
type Context = KibanaContext | null;
interface Arguments {
index: string | null;
metricsAtAllLevels: boolean;
partialRows: boolean;
aggConfigs: string;
}
type Return = Promise<KibanaDatatable>;
export const esaggs = (): ExpressionFunction<typeof name, Context, Arguments, Return> => ({
name,
type: 'kibana_datatable',
context: {
types: [
'kibana_context',
'null',
],
types: ['kibana_context', 'null'],
},
help: i18n.translate('interpreter.functions.esaggs.help', { defaultMessage: 'Run AggConfig aggregation' }),
help: i18n.translate('interpreter.functions.esaggs.help', {
defaultMessage: 'Run AggConfig aggregation',
}),
args: {
index: {
types: ['string', 'null'],
default: null,
help: '',
},
metricsAtAllLevels: {
types: ['boolean'],
default: false,
help: '',
},
partialRows: {
types: ['boolean'],
default: false,
help: '',
},
aggConfigs: {
types: ['string'],
default: '""',
help: '',
},
},
async fn(context, args, handlers) {
const $injector = await chrome.dangerouslyGetActiveInjector();
const Private = $injector.get('Private');
const Private: Function = $injector.get('Private');
const indexPatterns = Private(IndexPatternsProvider);
const SearchSource = Private(SearchSourceProvider);
const queryFilter = Private(FilterBarQueryFilterProvider);
@ -76,9 +99,9 @@ export const esaggs = () => ({
searchSource.setField('index', indexPattern);
searchSource.setField('size', 0);
const response = await courierRequestHandler({
searchSource: searchSource,
aggs: aggs,
const response: Pick<KibanaDatatable, 'columns' | 'rows'> = await courierRequestHandler({
searchSource,
aggs,
timeRange: get(context, 'timeRange', null),
query: get(context, 'query', null),
filters: get(context, 'filters', null),

View file

@ -0,0 +1,20 @@
/*
* 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 * from '../types';

View file

@ -0,0 +1,142 @@
/*
* 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 { KnownTypeToString, TypeString, UnmappedTypeStrings } from './common';
/**
* This type represents all of the possible combinations of properties of an
* Argument in an Expression Function. The presence or absence of certain fields
* influence the shape and presence of others within each `arg` in the specification.
*/
export type ArgumentType<T> =
| SingleArgumentType<T>
| MultipleArgumentType<T>
| UnresolvedSingleArgumentType<T>
| UnresolvedMultipleArgumentType<T>;
/**
* Map the type within the the generic array to a string-based
* representation of the type.
*/
// prettier-ignore
type ArrayTypeToArgumentString<T> =
T extends Array<infer ElementType> ? TypeString<ElementType> :
T extends null ? 'null' :
never;
/**
* Map the return type of the function within the generic to a
* string-based representation of the return type.
*/
// prettier-ignore
type UnresolvedTypeToArgumentString<T> =
T extends (...args: any) => infer ElementType ? TypeString<ElementType> :
T extends null ? 'null' :
never;
/**
* Map the array-based return type of the function within the generic to a
* string-based representation of the return type.
*/
// prettier-ignore
type UnresolvedArrayTypeToArgumentString<T> =
T extends Array<(...args: any) => infer ElementType> ? TypeString<ElementType> :
T extends (...args: any) => infer ElementType ? ArrayTypeToArgumentString<ElementType> :
T extends null ? 'null' :
never;
/** A type containing properties common to all Function Arguments. */
interface BaseArgumentType<T> {
/** Alternate names for the Function valid for use in the Expression Editor */
aliases?: string[];
/** Help text for the Argument to be displayed in the Expression Editor */
help: string;
/** Default options for the Argument */
options?: T[];
/**
* Is this Argument required?
* @default false
*/
required?: boolean;
/**
* If false, the Argument is supplied as a function to be invoked in the
* implementation, rather than a value.
* @default true
*/
resolve?: boolean;
/** Names of types that are valid values of the Argument. */
types?: string[];
/** The optional default value of the Argument. */
default?: T | string;
/**
* If true, multiple values may be supplied to the Argument.
* @default false
*/
multi?: boolean;
}
/**
* The `types` array in a `FunctionSpec` should contain string
* representations of the `ArgumentsSpec` types:
*
* `someArgument: boolean | string` results in `types: ['boolean', 'string']`
*/
type SingleArgumentType<T> = BaseArgumentType<T> & {
multi?: false;
resolve?: true;
types?: Array<KnownTypeToString<T> | UnmappedTypeStrings>;
};
/**
* If the `multi` property on the argument is true, the `types` array should
* contain string representations of the `ArgumentsSpec` array types:
*
* `someArgument: boolean[] | string[]` results in: `types: ['boolean', 'string']`
*/
type MultipleArgumentType<T> = BaseArgumentType<T> & {
multi: true;
resolve?: true;
types?: Array<ArrayTypeToArgumentString<T> | UnmappedTypeStrings>;
};
/**
* If the `resolve` property on the arugument is false, the `types` array, if
* present, should contain string representations of the result of the argument
* function:
*
* `someArgument: () => string` results in `types: ['string']`
*/
type UnresolvedSingleArgumentType<T> = BaseArgumentType<T> & {
multi?: false;
resolve: false;
types?: Array<UnresolvedTypeToArgumentString<T> | UnmappedTypeStrings>;
};
/**
* If the `resolve` property on the arugument is false, the `types` array, if
* present, should contain string representations of the result of the argument
* function:
*
* `someArgument: () => string[]` results in `types: ['string']`
*/
type UnresolvedMultipleArgumentType<T> = BaseArgumentType<T> & {
multi: true;
resolve: false;
types?: Array<UnresolvedArrayTypeToArgumentString<T> | UnmappedTypeStrings>;
};

View file

@ -0,0 +1,60 @@
/*
* 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.
*/
/**
* This can convert a type into a known Expression string representation of
* that type. For example, `TypeToString<Datatable>` will resolve to `'datatable'`.
* This allows Expression Functions to continue to specify their type in a
* simple string format.
*/
export type TypeToString<T> = KnownTypeToString<T> | UnmappedTypeStrings;
/**
* Map the type of the generic to a string-based representation of the type.
*
* If the provided generic is its own type interface, we use the value of
* the `type` key as a string literal type for it.
*/
// prettier-ignore
export type KnownTypeToString<T> =
T extends string ? 'string' :
T extends boolean ? 'boolean' :
T extends number ? 'number' :
T extends null ? 'null' :
T extends { type: string } ? T['type'] :
never;
/**
* If the type extends a Promise, we still need to return the string representation:
*
* `someArgument: Promise<boolean | string>` results in `types: ['boolean', 'string']`
*/
export type TypeString<T> = KnownTypeToString<UnwrapPromise<T>>;
/**
* Types used in Expressions that don't map to a primitive cleanly:
*
* `date` is typed as a number or string, and represents a date
*/
export type UnmappedTypeStrings = 'date' | 'filter';
/**
* Utility type: extracts returned type from a Promise.
*/
export type UnwrapPromise<T> = T extends Promise<infer P> ? P : T;

View file

@ -0,0 +1,47 @@
/*
* 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 { ArgumentType } from './arguments';
import { TypeToString, UnwrapPromise } from './common';
/**
* A generic type which represents an Expression Function definition.
*/
export interface ExpressionFunction<Name extends string, Context, Arguments, Return> {
/** Arguments for the Function */
args: { [key in keyof Arguments]: ArgumentType<Arguments[key]> };
aliases?: string[];
context?: {
types: Array<TypeToString<Context>>;
};
/** Help text displayed in the Expression editor */
help: string;
/** The name of the Function */
name: Name;
/** The type of the Function */
type?: TypeToString<UnwrapPromise<Return>>;
/** The implementation of the Function */
fn(context: Context, args: Arguments, handlers: FunctionHandlers): Return;
}
// TODO: Handlers can be passed to the `fn` property of the Function. At the moment, these Functions
// are not strongly defined.
interface FunctionHandlers {
[key: string]: (...args: any) => any;
}

View file

@ -0,0 +1,29 @@
/*
* 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 { ArgumentType } from './arguments';
export {
TypeToString,
KnownTypeToString,
TypeString,
UnmappedTypeStrings,
UnwrapPromise,
} from './common';
export { ExpressionFunction } from './functions';
export * from '../common/types';

View file

@ -21,17 +21,12 @@
import { fromExpression } from '@kbn/interpreter/common';
// @ts-ignore
import { getInterpreter } from 'plugins/interpreter/interpreter';
// @ts-ignore
import { KibanaContext } from 'plugins/interpreter/types';
import { Adapters } from 'ui/inspector';
import { Filters, Query, TimeRange } from 'ui/visualize';
export interface InitialContextObject {
timeRange?: TimeRange;
filters?: Filters;
query?: Query;
}
export type getInitialContextFunction = () => InitialContextObject;
type getInitialContextFunction = () => KibanaContext;
export interface RunPipelineHandlers {
getInitialContext: getInitialContextFunction;