[Query] Es query/field base (#103177)

* remove es query dependency on format.convert

* FieldBase

* fix types

* types

* Fix type imports

* test types

* fix jest

* rename

* docs

* comment
This commit is contained in:
Liza Katz 2021-06-30 13:07:27 +01:00 committed by GitHub
parent 0ef542041b
commit 2bc801c8ef
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
44 changed files with 148 additions and 292 deletions

View file

@ -13,11 +13,11 @@ esFilters: {
FILTERS: typeof FILTERS;
FilterStateStore: typeof FilterStateStore;
buildEmptyFilter: (isPinned: boolean, index?: string | undefined) => import("../common").Filter;
buildPhrasesFilter: (field: import("../common").IFieldType, params: any[], indexPattern: import("../common").IndexPatternBase) => import("../common").PhrasesFilter;
buildExistsFilter: (field: import("../common").IFieldType, indexPattern: import("../common").IndexPatternBase) => import("../common").ExistsFilter;
buildPhraseFilter: (field: import("../common").IFieldType, value: any, indexPattern: import("../common").IndexPatternBase) => import("../common").PhraseFilter;
buildPhrasesFilter: (field: import("../common").IndexPatternFieldBase, params: any[], indexPattern: import("../common").IndexPatternBase) => import("../common").PhrasesFilter;
buildExistsFilter: (field: import("../common").IndexPatternFieldBase, indexPattern: import("../common").IndexPatternBase) => import("../common").ExistsFilter;
buildPhraseFilter: (field: import("../common").IndexPatternFieldBase, value: any, indexPattern: import("../common").IndexPatternBase) => import("../common").PhraseFilter;
buildQueryFilter: (query: any, index: string, alias: string) => import("../common").QueryStringFilter;
buildRangeFilter: (field: import("../common").IFieldType, params: import("../common").RangeFilterParams, indexPattern: import("../common").IndexPatternBase, formattedValue?: string | undefined) => import("../common").RangeFilter;
buildRangeFilter: (field: import("../common").IndexPatternFieldBase, params: import("../common").RangeFilterParams, indexPattern: import("../common").IndexPatternBase, formattedValue?: string | undefined) => import("../common").RangeFilter;
isPhraseFilter: (filter: any) => filter is import("../common").PhraseFilter;
isExistsFilter: (filter: any) => filter is import("../common").ExistsFilter;
isPhrasesFilter: (filter: any) => filter is import("../common").PhrasesFilter;

View file

@ -1,11 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) &gt; [IFieldType](./kibana-plugin-plugins-data-public.ifieldtype.md) &gt; [lang](./kibana-plugin-plugins-data-public.ifieldtype.lang.md)
## IFieldType.lang property
<b>Signature:</b>
```typescript
lang?: estypes.ScriptLanguage;
```

View file

@ -12,7 +12,7 @@
<b>Signature:</b>
```typescript
export interface IFieldType
export interface IFieldType extends IndexPatternFieldBase
```
## Properties
@ -26,15 +26,9 @@ export interface IFieldType
| [esTypes](./kibana-plugin-plugins-data-public.ifieldtype.estypes.md) | <code>string[]</code> | |
| [filterable](./kibana-plugin-plugins-data-public.ifieldtype.filterable.md) | <code>boolean</code> | |
| [format](./kibana-plugin-plugins-data-public.ifieldtype.format.md) | <code>any</code> | |
| [lang](./kibana-plugin-plugins-data-public.ifieldtype.lang.md) | <code>estypes.ScriptLanguage</code> | |
| [name](./kibana-plugin-plugins-data-public.ifieldtype.name.md) | <code>string</code> | |
| [readFromDocValues](./kibana-plugin-plugins-data-public.ifieldtype.readfromdocvalues.md) | <code>boolean</code> | |
| [script](./kibana-plugin-plugins-data-public.ifieldtype.script.md) | <code>string</code> | |
| [scripted](./kibana-plugin-plugins-data-public.ifieldtype.scripted.md) | <code>boolean</code> | |
| [searchable](./kibana-plugin-plugins-data-public.ifieldtype.searchable.md) | <code>boolean</code> | |
| [sortable](./kibana-plugin-plugins-data-public.ifieldtype.sortable.md) | <code>boolean</code> | |
| [subType](./kibana-plugin-plugins-data-public.ifieldtype.subtype.md) | <code>IFieldSubType</code> | |
| [toSpec](./kibana-plugin-plugins-data-public.ifieldtype.tospec.md) | <code>(options?: {</code><br/><code> getFormatterForField?: IndexPattern['getFormatterForField'];</code><br/><code> }) =&gt; FieldSpec</code> | |
| [type](./kibana-plugin-plugins-data-public.ifieldtype.type.md) | <code>string</code> | |
| [visualizable](./kibana-plugin-plugins-data-public.ifieldtype.visualizable.md) | <code>boolean</code> | |

View file

@ -1,11 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) &gt; [IFieldType](./kibana-plugin-plugins-data-public.ifieldtype.md) &gt; [name](./kibana-plugin-plugins-data-public.ifieldtype.name.md)
## IFieldType.name property
<b>Signature:</b>
```typescript
name: string;
```

View file

@ -1,11 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) &gt; [IFieldType](./kibana-plugin-plugins-data-public.ifieldtype.md) &gt; [script](./kibana-plugin-plugins-data-public.ifieldtype.script.md)
## IFieldType.script property
<b>Signature:</b>
```typescript
script?: string;
```

View file

@ -1,11 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) &gt; [IFieldType](./kibana-plugin-plugins-data-public.ifieldtype.md) &gt; [scripted](./kibana-plugin-plugins-data-public.ifieldtype.scripted.md)
## IFieldType.scripted property
<b>Signature:</b>
```typescript
scripted?: boolean;
```

View file

@ -1,11 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) &gt; [IFieldType](./kibana-plugin-plugins-data-public.ifieldtype.md) &gt; [subType](./kibana-plugin-plugins-data-public.ifieldtype.subtype.md)
## IFieldType.subType property
<b>Signature:</b>
```typescript
subType?: IFieldSubType;
```

View file

@ -1,11 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) &gt; [IFieldType](./kibana-plugin-plugins-data-public.ifieldtype.md) &gt; [type](./kibana-plugin-plugins-data-public.ifieldtype.type.md)
## IFieldType.type property
<b>Signature:</b>
```typescript
type: string;
```

View file

@ -0,0 +1,11 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) &gt; [IIndexPattern](./kibana-plugin-plugins-data-public.iindexpattern.md) &gt; [fields](./kibana-plugin-plugins-data-public.iindexpattern.fields.md)
## IIndexPattern.fields property
<b>Signature:</b>
```typescript
fields: IFieldType[];
```

View file

@ -20,6 +20,7 @@ export interface IIndexPattern extends IndexPatternBase
| Property | Type | Description |
| --- | --- | --- |
| [fieldFormatMap](./kibana-plugin-plugins-data-public.iindexpattern.fieldformatmap.md) | <code>Record&lt;string, SerializedFieldFormat&lt;unknown&gt; &#124; undefined&gt;</code> | |
| [fields](./kibana-plugin-plugins-data-public.iindexpattern.fields.md) | <code>IFieldType[]</code> | |
| [getFormatterForField](./kibana-plugin-plugins-data-public.iindexpattern.getformatterforfield.md) | <code>(field: IndexPatternField &#124; IndexPatternField['spec'] &#124; IFieldType) =&gt; FieldFormat</code> | Look up a formatter for a given field |
| [timeFieldName](./kibana-plugin-plugins-data-public.iindexpattern.timefieldname.md) | <code>string</code> | |
| [title](./kibana-plugin-plugins-data-public.iindexpattern.title.md) | <code>string</code> | |

View file

@ -9,7 +9,9 @@
```typescript
getAggregationRestrictions(): Record<string, Record<string, {
agg?: string | undefined;
interval?: number | undefined;
interval?: number | undefined; /**
* Get last saved saved object fields
*/
fixed_interval?: string | undefined;
calendar_interval?: string | undefined;
delay?: string | undefined;
@ -20,7 +22,9 @@ getAggregationRestrictions(): Record<string, Record<string, {
`Record<string, Record<string, {
agg?: string | undefined;
interval?: number | undefined;
interval?: number | undefined; /**
* Get last saved saved object fields
*/
fixed_interval?: string | undefined;
calendar_interval?: string | undefined;
delay?: string | undefined;

View file

@ -37,7 +37,7 @@ export declare class IndexPatternField implements IFieldType
| [searchable](./kibana-plugin-plugins-data-public.indexpatternfield.searchable.md) | | <code>boolean</code> | |
| [sortable](./kibana-plugin-plugins-data-public.indexpatternfield.sortable.md) | | <code>boolean</code> | |
| [spec](./kibana-plugin-plugins-data-public.indexpatternfield.spec.md) | | <code>FieldSpec</code> | |
| [subType](./kibana-plugin-plugins-data-public.indexpatternfield.subtype.md) | | <code>import(&quot;../types&quot;).IFieldSubType &#124; undefined</code> | |
| [subType](./kibana-plugin-plugins-data-public.indexpatternfield.subtype.md) | | <code>import(&quot;../..&quot;).IFieldSubType &#124; undefined</code> | |
| [type](./kibana-plugin-plugins-data-public.indexpatternfield.type.md) | | <code>string</code> | |
| [visualizable](./kibana-plugin-plugins-data-public.indexpatternfield.visualizable.md) | | <code>boolean</code> | |

View file

@ -7,5 +7,5 @@
<b>Signature:</b>
```typescript
get subType(): import("../types").IFieldSubType | undefined;
get subType(): import("../..").IFieldSubType | undefined;
```

View file

@ -19,7 +19,7 @@ toJSON(): {
searchable: boolean;
aggregatable: boolean;
readFromDocValues: boolean;
subType: import("../types").IFieldSubType | undefined;
subType: import("../..").IFieldSubType | undefined;
customLabel: string | undefined;
};
```
@ -37,7 +37,7 @@ toJSON(): {
searchable: boolean;
aggregatable: boolean;
readFromDocValues: boolean;
subType: import("../types").IFieldSubType | undefined;
subType: import("../..").IFieldSubType | undefined;
customLabel: string | undefined;
}`

View file

@ -11,11 +11,11 @@ esFilters: {
buildQueryFilter: (query: any, index: string, alias: string) => import("../common").QueryStringFilter;
buildCustomFilter: typeof buildCustomFilter;
buildEmptyFilter: (isPinned: boolean, index?: string | undefined) => import("../common").Filter;
buildExistsFilter: (field: import("../common").IFieldType, indexPattern: import("../common").IndexPatternBase) => import("../common").ExistsFilter;
buildExistsFilter: (field: import("../common").IndexPatternFieldBase, indexPattern: import("../common").IndexPatternBase) => import("../common").ExistsFilter;
buildFilter: typeof buildFilter;
buildPhraseFilter: (field: import("../common").IFieldType, value: any, indexPattern: import("../common").IndexPatternBase) => import("../common").PhraseFilter;
buildPhrasesFilter: (field: import("../common").IFieldType, params: any[], indexPattern: import("../common").IndexPatternBase) => import("../common").PhrasesFilter;
buildRangeFilter: (field: import("../common").IFieldType, params: import("../common").RangeFilterParams, indexPattern: import("../common").IndexPatternBase, formattedValue?: string | undefined) => import("../common").RangeFilter;
buildPhraseFilter: (field: import("../common").IndexPatternFieldBase, value: any, indexPattern: import("../common").IndexPatternBase) => import("../common").PhraseFilter;
buildPhrasesFilter: (field: import("../common").IndexPatternFieldBase, params: any[], indexPattern: import("../common").IndexPatternBase) => import("../common").PhrasesFilter;
buildRangeFilter: (field: import("../common").IndexPatternFieldBase, params: import("../common").RangeFilterParams, indexPattern: import("../common").IndexPatternBase, formattedValue?: string | undefined) => import("../common").RangeFilter;
isFilterDisabled: (filter: import("../common").Filter) => boolean;
}
```

View file

@ -1,11 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) &gt; [IFieldType](./kibana-plugin-plugins-data-server.ifieldtype.md) &gt; [lang](./kibana-plugin-plugins-data-server.ifieldtype.lang.md)
## IFieldType.lang property
<b>Signature:</b>
```typescript
lang?: estypes.ScriptLanguage;
```

View file

@ -12,7 +12,7 @@
<b>Signature:</b>
```typescript
export interface IFieldType
export interface IFieldType extends IndexPatternFieldBase
```
## Properties
@ -26,15 +26,9 @@ export interface IFieldType
| [esTypes](./kibana-plugin-plugins-data-server.ifieldtype.estypes.md) | <code>string[]</code> | |
| [filterable](./kibana-plugin-plugins-data-server.ifieldtype.filterable.md) | <code>boolean</code> | |
| [format](./kibana-plugin-plugins-data-server.ifieldtype.format.md) | <code>any</code> | |
| [lang](./kibana-plugin-plugins-data-server.ifieldtype.lang.md) | <code>estypes.ScriptLanguage</code> | |
| [name](./kibana-plugin-plugins-data-server.ifieldtype.name.md) | <code>string</code> | |
| [readFromDocValues](./kibana-plugin-plugins-data-server.ifieldtype.readfromdocvalues.md) | <code>boolean</code> | |
| [script](./kibana-plugin-plugins-data-server.ifieldtype.script.md) | <code>string</code> | |
| [scripted](./kibana-plugin-plugins-data-server.ifieldtype.scripted.md) | <code>boolean</code> | |
| [searchable](./kibana-plugin-plugins-data-server.ifieldtype.searchable.md) | <code>boolean</code> | |
| [sortable](./kibana-plugin-plugins-data-server.ifieldtype.sortable.md) | <code>boolean</code> | |
| [subType](./kibana-plugin-plugins-data-server.ifieldtype.subtype.md) | <code>IFieldSubType</code> | |
| [toSpec](./kibana-plugin-plugins-data-server.ifieldtype.tospec.md) | <code>(options?: {</code><br/><code> getFormatterForField?: IndexPattern['getFormatterForField'];</code><br/><code> }) =&gt; FieldSpec</code> | |
| [type](./kibana-plugin-plugins-data-server.ifieldtype.type.md) | <code>string</code> | |
| [visualizable](./kibana-plugin-plugins-data-server.ifieldtype.visualizable.md) | <code>boolean</code> | |

View file

@ -1,11 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) &gt; [IFieldType](./kibana-plugin-plugins-data-server.ifieldtype.md) &gt; [name](./kibana-plugin-plugins-data-server.ifieldtype.name.md)
## IFieldType.name property
<b>Signature:</b>
```typescript
name: string;
```

View file

@ -1,11 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) &gt; [IFieldType](./kibana-plugin-plugins-data-server.ifieldtype.md) &gt; [script](./kibana-plugin-plugins-data-server.ifieldtype.script.md)
## IFieldType.script property
<b>Signature:</b>
```typescript
script?: string;
```

View file

@ -1,11 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) &gt; [IFieldType](./kibana-plugin-plugins-data-server.ifieldtype.md) &gt; [scripted](./kibana-plugin-plugins-data-server.ifieldtype.scripted.md)
## IFieldType.scripted property
<b>Signature:</b>
```typescript
scripted?: boolean;
```

View file

@ -1,11 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) &gt; [IFieldType](./kibana-plugin-plugins-data-server.ifieldtype.md) &gt; [subType](./kibana-plugin-plugins-data-server.ifieldtype.subtype.md)
## IFieldType.subType property
<b>Signature:</b>
```typescript
subType?: IFieldSubType;
```

View file

@ -1,11 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) &gt; [IFieldType](./kibana-plugin-plugins-data-server.ifieldtype.md) &gt; [type](./kibana-plugin-plugins-data-server.ifieldtype.type.md)
## IFieldType.type property
<b>Signature:</b>
```typescript
type: string;
```

View file

@ -9,7 +9,9 @@
```typescript
getAggregationRestrictions(): Record<string, Record<string, {
agg?: string | undefined;
interval?: number | undefined;
interval?: number | undefined; /**
* Get last saved saved object fields
*/
fixed_interval?: string | undefined;
calendar_interval?: string | undefined;
delay?: string | undefined;
@ -20,7 +22,9 @@ getAggregationRestrictions(): Record<string, Record<string, {
`Record<string, Record<string, {
agg?: string | undefined;
interval?: number | undefined;
interval?: number | undefined; /**
* Get last saved saved object fields
*/
fixed_interval?: string | undefined;
calendar_interval?: string | undefined;
delay?: string | undefined;

View file

@ -6,7 +6,6 @@
* Side Public License, v 1.
*/
import { IFieldType } from '../../index_patterns';
import { Filter } from '../filters';
import { IndexPatternBase } from './types';
@ -26,5 +25,5 @@ export function filterMatchesIndex(filter: Filter, indexPattern?: IndexPatternBa
return filter.meta.index === indexPattern.id;
}
return indexPattern.fields.some((field: IFieldType) => field.name === filter.meta.key);
return indexPattern.fields.some((field) => field.name === filter.meta.key);
}

View file

@ -10,7 +10,6 @@ import { handleNestedFilter } from './handle_nested_filter';
import { fields } from '../../index_patterns/mocks';
import { buildPhraseFilter, buildQueryFilter } from '../filters';
import { IndexPatternBase } from './types';
import { IFieldType } from '../../index_patterns';
describe('handleNestedFilter', function () {
const indexPattern: IndexPatternBase = {
@ -45,8 +44,12 @@ describe('handleNestedFilter', function () {
});
it('should return filter untouched if it does not target a field from the given index pattern', () => {
const field = { ...getField('extension'), name: 'notarealfield' };
const filter = buildPhraseFilter(field as IFieldType, 'jpg', indexPattern);
const field = getField('extension');
const unrealField = {
...field!,
name: 'notarealfield',
};
const filter = buildPhraseFilter(unrealField, 'jpg', indexPattern);
const result = handleNestedFilter(filter, indexPattern);
expect(result).toBe(filter);
});

View file

@ -11,4 +11,4 @@ export { buildQueryFromFilters } from './from_filters';
export { luceneStringToDsl } from './lucene_string_to_dsl';
export { decorateQuery } from './decorate_query';
export { getEsQueryConfig } from './get_es_query_config';
export { IndexPatternBase } from './types';
export { IndexPatternBase, IndexPatternFieldBase, IFieldSubType } from './types';

View file

@ -6,9 +6,32 @@
* Side Public License, v 1.
*/
import { IFieldType } from '../../index_patterns';
import type { estypes } from '@elastic/elasticsearch';
export interface IFieldSubType {
multi?: { parent: string };
nested?: { path: string };
}
export interface IndexPatternFieldBase {
name: string;
/**
* Kibana field type
*/
type: string;
subType?: IFieldSubType;
/**
* Scripted field painless script
*/
script?: string;
/**
* Scripted field langauge
* Painless is the only valid scripted field language
*/
lang?: estypes.ScriptLanguage;
scripted?: boolean;
}
export interface IndexPatternBase {
fields: IFieldType[];
fields: IndexPatternFieldBase[];
id?: string;
}

View file

@ -6,7 +6,8 @@
* Side Public License, v 1.
*/
import { IFieldType, IndexPatternBase } from '../..';
import { IndexPatternFieldBase, IndexPatternBase } from '../..';
import {
Filter,
FILTERS,
@ -20,7 +21,7 @@ import {
export function buildFilter(
indexPattern: IndexPatternBase,
field: IFieldType,
field: IndexPatternFieldBase,
type: FILTERS,
negate: boolean,
disabled: boolean,
@ -60,7 +61,7 @@ export function buildCustomFilter(
function buildBaseFilter(
indexPattern: IndexPatternBase,
field: IFieldType,
field: IndexPatternFieldBase,
type: FILTERS,
params: any
): Filter {

View file

@ -7,8 +7,7 @@
*/
import { Filter, FilterMeta } from './meta_filter';
import { IFieldType } from '../../index_patterns';
import { IndexPatternBase } from '..';
import { IndexPatternFieldBase, IndexPatternBase } from '..';
export type ExistsFilterMeta = FilterMeta;
@ -27,7 +26,7 @@ export const getExistsFilterField = (filter: ExistsFilter) => {
return filter.exists && filter.exists.field;
};
export const buildExistsFilter = (field: IFieldType, indexPattern: IndexPatternBase) => {
export const buildExistsFilter = (field: IndexPatternFieldBase, indexPattern: IndexPatternBase) => {
return {
meta: {
index: indexPattern.id,

View file

@ -8,8 +8,7 @@
import type { estypes } from '@elastic/elasticsearch';
import { get, isPlainObject } from 'lodash';
import { Filter, FilterMeta } from './meta_filter';
import { IFieldType } from '../../index_patterns';
import { IndexPatternBase } from '..';
import { IndexPatternFieldBase, IndexPatternBase } from '..';
export type PhraseFilterMeta = FilterMeta & {
params?: {
@ -59,7 +58,7 @@ export const getPhraseFilterValue = (filter: PhraseFilter): PhraseFilterValue =>
};
export const buildPhraseFilter = (
field: IFieldType,
field: IndexPatternFieldBase,
value: any,
indexPattern: IndexPatternBase
): PhraseFilter => {
@ -82,7 +81,7 @@ export const buildPhraseFilter = (
}
};
export const getPhraseScript = (field: IFieldType, value: string) => {
export const getPhraseScript = (field: IndexPatternFieldBase, value: string) => {
const convertedValue = getConvertedValueForField(field, value);
const script = buildInlineScriptForPhraseFilter(field);
@ -106,7 +105,7 @@ export const getPhraseScript = (field: IFieldType, value: string) => {
* https://github.com/elastic/elasticsearch/issues/20941
* https://github.com/elastic/elasticsearch/pull/22201
**/
export const getConvertedValueForField = (field: IFieldType, value: any) => {
export const getConvertedValueForField = (field: IndexPatternFieldBase, value: any) => {
if (typeof value !== 'boolean' && field.type === 'boolean') {
if ([1, 'true'].includes(value)) {
return true;

View file

@ -9,8 +9,7 @@
import { Filter, FilterMeta } from './meta_filter';
import { getPhraseScript } from './phrase_filter';
import { FILTERS } from './index';
import { IFieldType } from '../../index_patterns';
import { IndexPatternBase } from '../es_query';
import { IndexPatternFieldBase, IndexPatternBase } from '../es_query';
export type PhrasesFilterMeta = FilterMeta & {
params: string[]; // The unformatted values
@ -33,7 +32,7 @@ export const getPhrasesFilterField = (filter: PhrasesFilter) => {
// Creates a filter where the given field matches one or more of the given values
// params should be an array of values
export const buildPhrasesFilter = (
field: IFieldType,
field: IndexPatternFieldBase,
params: any[],
indexPattern: IndexPatternBase
) => {

View file

@ -9,15 +9,15 @@
import { each } from 'lodash';
import { buildRangeFilter, getRangeFilterField, RangeFilter } from './range_filter';
import { fields, getField } from '../../index_patterns/mocks';
import { IIndexPattern, IFieldType } from '../../index_patterns';
import { IndexPatternBase, IndexPatternFieldBase } from '../es_query';
describe('Range filter builder', () => {
let indexPattern: IIndexPattern;
let indexPattern: IndexPatternBase;
beforeEach(() => {
indexPattern = {
id: 'id',
} as IIndexPattern;
} as IndexPatternBase;
});
it('should be a function', () => {
@ -130,7 +130,7 @@ describe('Range filter builder', () => {
});
describe('when given params where one side is infinite', () => {
let field: IFieldType;
let field: IndexPatternFieldBase;
let filter: RangeFilter;
beforeEach(() => {
@ -160,7 +160,7 @@ describe('Range filter builder', () => {
});
describe('when given params where both sides are infinite', () => {
let field: IFieldType;
let field: IndexPatternFieldBase;
let filter: RangeFilter;
beforeEach(() => {
@ -186,9 +186,9 @@ describe('Range filter builder', () => {
});
describe('getRangeFilterField', function () {
const indexPattern: IIndexPattern = ({
const indexPattern: IndexPatternBase = ({
fields,
} as unknown) as IIndexPattern;
} as unknown) as IndexPatternBase;
test('should return the name of the field a range query is targeting', () => {
const field = indexPattern.fields.find((patternField) => patternField.name === 'bytes');

View file

@ -8,8 +8,7 @@
import type { estypes } from '@elastic/elasticsearch';
import { map, reduce, mapValues, get, keys, pickBy } from 'lodash';
import { Filter, FilterMeta } from './meta_filter';
import { IFieldType } from '../../index_patterns';
import { IndexPatternBase } from '..';
import { IndexPatternBase, IndexPatternFieldBase } from '..';
const OPERANDS_IN_RANGE = 2;
@ -83,13 +82,13 @@ export const getRangeFilterField = (filter: RangeFilter) => {
return filter.range && Object.keys(filter.range)[0];
};
const formatValue = (field: IFieldType, params: any[]) =>
const formatValue = (params: any[]) =>
map(params, (val: any, key: string) => get(operators, key) + val).join(' ');
// Creates a filter where the value for the given field is in the given range
// params should be an object containing `lt`, `lte`, `gt`, and/or `gte`
export const buildRangeFilter = (
field: IFieldType,
field: IndexPatternFieldBase,
params: RangeFilterParams,
indexPattern: IndexPatternBase,
formattedValue?: string
@ -124,7 +123,7 @@ export const buildRangeFilter = (
filter.meta.field = field.name;
} else if (field.scripted) {
filter.script = getRangeScript(field, params);
filter.script.script.params.value = formatValue(field, filter.script.script.params);
filter.script.script.params.value = formatValue(filter.script.script.params);
filter.meta.field = field.name;
} else {
@ -135,7 +134,7 @@ export const buildRangeFilter = (
return filter as RangeFilter;
};
export const getRangeScript = (field: IFieldType, params: RangeFilterParams) => {
export const getRangeScript = (field: IndexPatternFieldBase, params: RangeFilterParams) => {
const knownParams = mapValues(
pickBy(params, (val, key: any) => key in operators),
(value) => (field.type === 'number' && typeof value === 'string' ? parseFloat(value) : value)

View file

@ -6,9 +6,8 @@
* Side Public License, v 1.
*/
import { get } from 'lodash';
import * as literal from '../node_types/literal';
import { KueryNode, IFieldType, IndexPatternBase } from '../../..';
import { KueryNode, IndexPatternFieldBase, IndexPatternBase } from '../../..';
export function buildNodeParams(fieldName: string) {
return {
@ -30,9 +29,9 @@ export function toElasticsearchQuery(
value: context?.nested ? `${context.nested.path}.${fieldNameArg.value}` : fieldNameArg.value,
};
const fieldName = literal.toElasticsearchQuery(fullFieldNameArg);
const field = get(indexPattern, 'fields', []).find((fld: IFieldType) => fld.name === fieldName);
const field = indexPattern?.fields?.find((fld: IndexPatternFieldBase) => fld.name === fieldName);
if (field && (field as IFieldType).scripted) {
if (field?.scripted) {
throw new Error(`Exists query does not support scripted fields`);
}
return {

View file

@ -9,7 +9,7 @@
import _ from 'lodash';
import { nodeTypes } from '../node_types';
import * as ast from '../ast';
import { IndexPatternBase, KueryNode, IFieldType, LatLon } from '../../..';
import { IndexPatternBase, KueryNode, LatLon } from '../../..';
export function buildNodeParams(fieldName: string, params: any) {
params = _.pick(params, 'topLeft', 'bottomRight');
@ -36,8 +36,8 @@ export function toElasticsearchQuery(
value: context?.nested ? `${context.nested.path}.${fieldNameArg.value}` : fieldNameArg.value,
};
const fieldName = nodeTypes.literal.toElasticsearchQuery(fullFieldNameArg) as string;
const fieldList: IFieldType[] = indexPattern?.fields ?? [];
const field = fieldList.find((fld: IFieldType) => fld.name === fieldName);
const fieldList = indexPattern?.fields ?? [];
const field = fieldList.find((fld) => fld.name === fieldName);
const queryParams = args.reduce((acc: any, arg: any) => {
const snakeArgName = _.snakeCase(arg.name);

View file

@ -8,7 +8,7 @@
import { nodeTypes } from '../node_types';
import * as ast from '../ast';
import { IndexPatternBase, KueryNode, IFieldType, LatLon } from '../../..';
import { IndexPatternBase, KueryNode, LatLon } from '../../..';
import { LiteralTypeBuildNode } from '../node_types/types';
export function buildNodeParams(fieldName: string, points: LatLon[]) {
@ -35,8 +35,8 @@ export function toElasticsearchQuery(
value: context?.nested ? `${context.nested.path}.${fieldNameArg.value}` : fieldNameArg.value,
};
const fieldName = nodeTypes.literal.toElasticsearchQuery(fullFieldNameArg) as string;
const fieldList: IFieldType[] = indexPattern?.fields ?? [];
const field = fieldList.find((fld: IFieldType) => fld.name === fieldName);
const fieldList = indexPattern?.fields ?? [];
const field = fieldList.find((fld) => fld.name === fieldName);
const queryParams = {
points: points.map((point: LiteralTypeBuildNode) => {
return ast.toElasticsearchQuery(point, indexPattern, config, context);

View file

@ -11,7 +11,7 @@ import { getPhraseScript } from '../../filters';
import { getFields } from './utils/get_fields';
import { getTimeZoneFromSettings } from '../../utils';
import { getFullFieldNameNode } from './utils/get_full_field_name_node';
import { IndexPatternBase, KueryNode, IFieldType } from '../../..';
import { IndexPatternBase, KueryNode, IndexPatternFieldBase } from '../../..';
import * as ast from '../ast';
@ -100,7 +100,7 @@ export function toElasticsearchQuery(
return { match_all: {} };
}
const queries = fields!.reduce((accumulator: any, field: IFieldType) => {
const queries = fields!.reduce((accumulator: any, field: IndexPatternFieldBase) => {
const wrapWithNestedQuery = (query: any) => {
// Wildcards can easily include nested and non-nested fields. There isn't a good way to let
// users handle this themselves so we automatically add nested queries in this scenario.

View file

@ -13,7 +13,7 @@ import { getRangeScript, RangeFilterParams } from '../../filters';
import { getFields } from './utils/get_fields';
import { getTimeZoneFromSettings } from '../../utils';
import { getFullFieldNameNode } from './utils/get_full_field_name_node';
import { IndexPatternBase, KueryNode, IFieldType } from '../../..';
import { IndexPatternBase, KueryNode } from '../../..';
export function buildNodeParams(fieldName: string, params: RangeFilterParams) {
const paramsToMap = _.pick(params, 'gt', 'lt', 'gte', 'lte', 'format');
@ -62,7 +62,7 @@ export function toElasticsearchQuery(
});
}
const queries = fields!.map((field: IFieldType) => {
const queries = fields!.map((field) => {
const wrapWithNestedQuery = (query: any) => {
// Wildcards can easily include nested and non-nested fields. There isn't a good way to let
// users handle this themselves so we automatically add nested queries in this scenario.

View file

@ -6,21 +6,21 @@
* Side Public License, v 1.
*/
import { IndexPatternBase } from '../../..';
import { fields } from '../../../../index_patterns/mocks';
import { nodeTypes } from '../../index';
import { IIndexPattern, IFieldType } from '../../../../index_patterns';
// @ts-ignore
import { getFields } from './get_fields';
describe('getFields', () => {
let indexPattern: IIndexPattern;
let indexPattern: IndexPatternBase;
beforeEach(() => {
indexPattern = ({
fields,
} as unknown) as IIndexPattern;
} as unknown) as IndexPatternBase;
});
describe('field names without a wildcard', () => {
@ -41,14 +41,14 @@ describe('getFields', () => {
});
test('should not match a wildcard in a literal node', () => {
const indexPatternWithWildField = {
const indexPatternWithWildField: IndexPatternBase = ({
title: 'wildIndex',
fields: [
{
name: 'foo*',
},
],
} as IIndexPattern;
} as unknown) as IndexPatternBase;
const fieldNameNode = nodeTypes.literal.buildNode('foo*');
const results = getFields(fieldNameNode, indexPatternWithWildField);
@ -76,8 +76,8 @@ describe('getFields', () => {
expect(Array.isArray(results)).toBeTruthy();
expect(results).toHaveLength(2);
expect(results!.find((field: IFieldType) => field.name === 'machine.os')).toBeDefined();
expect(results!.find((field: IFieldType) => field.name === 'machine.os.raw')).toBeDefined();
expect(results!.find((field) => field.name === 'machine.os')).toBeDefined();
expect(results!.find((field) => field.name === 'machine.os.raw')).toBeDefined();
});
});
});

View file

@ -7,7 +7,7 @@
*/
import { getFields } from './get_fields';
import { IndexPatternBase, IFieldType, KueryNode } from '../../../..';
import { IndexPatternBase, IndexPatternFieldBase, KueryNode } from '../../../..';
export function getFullFieldNameNode(
rootNameNode: any,
@ -27,7 +27,7 @@ export function getFullFieldNameNode(
}
const fields = getFields(fullFieldNameNode, indexPattern);
const errors = fields!.reduce((acc: any, field: IFieldType) => {
const errors = fields!.reduce((acc: any, field: IndexPatternFieldBase) => {
const nestedPathFromField =
field.subType && field.subType.nested ? field.subType.nested.path : undefined;

View file

@ -5,18 +5,13 @@
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import type { estypes } from '@elastic/elasticsearch';
import { FieldSpec, IFieldSubType, IndexPattern } from '../..';
import { IndexPatternFieldBase, FieldSpec, IndexPattern } from '../..';
/**
* @deprecated
* Use IndexPatternField or FieldSpec instead
*/
export interface IFieldType {
name: string;
type: string;
script?: string;
lang?: estypes.ScriptLanguage;
export interface IFieldType extends IndexPatternFieldBase {
count?: number;
// esTypes might be undefined on old index patterns that have not been refreshed since we added
// this prop. It is also undefined on scripted fields.
@ -27,8 +22,6 @@ export interface IFieldType {
sortable?: boolean;
visualizable?: boolean;
readFromDocValues?: boolean;
scripted?: boolean;
subType?: IFieldSubType;
displayName?: string;
customLabel?: string;
format?: any;

View file

@ -9,7 +9,7 @@ import type { estypes } from '@elastic/elasticsearch';
import { ToastInputFields, ErrorToastOptions } from 'src/core/public/notifications';
// eslint-disable-next-line
import type { SavedObject } from 'src/core/server';
import type { IndexPatternBase } from '../es_query';
import type { IndexPatternFieldBase, IFieldSubType, IndexPatternBase } from '../es_query';
import { IFieldType } from './fields';
import { RUNTIME_FIELD_TYPES } from './constants';
import { SerializedFieldFormat } from '../../../expressions/common';
@ -32,6 +32,7 @@ export interface RuntimeField {
*/
export interface IIndexPattern extends IndexPatternBase {
title: string;
fields: IFieldType[];
/**
* Type is used for identifying rollup indices, otherwise left undefined
*/
@ -149,12 +150,6 @@ export type AggregationRestrictions = Record<
time_zone?: string;
}
>;
export interface IFieldSubType {
multi?: { parent: string };
nested?: { path: string };
}
export interface TypeMeta {
aggs?: Record<string, AggregationRestrictions>;
[key: string]: any;
@ -183,30 +178,17 @@ export interface FieldSpecExportFmt {
/**
* Serialized version of IndexPatternField
*/
export interface FieldSpec {
export interface FieldSpec extends IndexPatternFieldBase {
/**
* Popularity count is used by discover
*/
count?: number;
/**
* Scripted field painless script
*/
script?: string;
/**
* Scripted field langauge
* Painless is the only valid scripted field language
*/
lang?: estypes.ScriptLanguage;
conflictDescriptions?: Record<string, string[]>;
format?: SerializedFieldFormat;
name: string;
type: string;
esTypes?: string[];
scripted?: boolean;
searchable: boolean;
aggregatable: boolean;
readFromDocValues?: boolean;
subType?: IFieldSubType;
indexed?: boolean;
customLabel?: string;
runtimeField?: RuntimeField;

View file

@ -808,11 +808,11 @@ export const esFilters: {
FILTERS: typeof FILTERS;
FilterStateStore: typeof FilterStateStore;
buildEmptyFilter: (isPinned: boolean, index?: string | undefined) => import("../common").Filter;
buildPhrasesFilter: (field: import("../common").IFieldType, params: any[], indexPattern: import("../common").IndexPatternBase) => import("../common").PhrasesFilter;
buildExistsFilter: (field: import("../common").IFieldType, indexPattern: import("../common").IndexPatternBase) => import("../common").ExistsFilter;
buildPhraseFilter: (field: import("../common").IFieldType, value: any, indexPattern: import("../common").IndexPatternBase) => import("../common").PhraseFilter;
buildPhrasesFilter: (field: import("../common").IndexPatternFieldBase, params: any[], indexPattern: import("../common").IndexPatternBase) => import("../common").PhrasesFilter;
buildExistsFilter: (field: import("../common").IndexPatternFieldBase, indexPattern: import("../common").IndexPatternBase) => import("../common").ExistsFilter;
buildPhraseFilter: (field: import("../common").IndexPatternFieldBase, value: any, indexPattern: import("../common").IndexPatternBase) => import("../common").PhraseFilter;
buildQueryFilter: (query: any, index: string, alias: string) => import("../common").QueryStringFilter;
buildRangeFilter: (field: import("../common").IFieldType, params: import("../common").RangeFilterParams, indexPattern: import("../common").IndexPatternBase, formattedValue?: string | undefined) => import("../common").RangeFilter;
buildRangeFilter: (field: import("../common").IndexPatternFieldBase, params: import("../common").RangeFilterParams, indexPattern: import("../common").IndexPatternBase, formattedValue?: string | undefined) => import("../common").RangeFilter;
isPhraseFilter: (filter: any) => filter is import("../common").PhraseFilter;
isExistsFilter: (filter: any) => filter is import("../common").ExistsFilter;
isPhrasesFilter: (filter: any) => filter is import("../common").PhrasesFilter;
@ -1242,10 +1242,11 @@ export interface IFieldSubType {
};
}
// Warning: (ae-forgotten-export) The symbol "IndexPatternFieldBase" needs to be exported by the entry point index.d.ts
// Warning: (ae-missing-release-tag) "IFieldType" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public @deprecated (undocumented)
export interface IFieldType {
export interface IFieldType extends IndexPatternFieldBase {
// (undocumented)
aggregatable?: boolean;
// (undocumented)
@ -1261,28 +1262,16 @@ export interface IFieldType {
// (undocumented)
format?: any;
// (undocumented)
lang?: estypes.ScriptLanguage;
// (undocumented)
name: string;
// (undocumented)
readFromDocValues?: boolean;
// (undocumented)
script?: string;
// (undocumented)
scripted?: boolean;
// (undocumented)
searchable?: boolean;
// (undocumented)
sortable?: boolean;
// (undocumented)
subType?: IFieldSubType;
// (undocumented)
toSpec?: (options?: {
getFormatterForField?: IndexPattern['getFormatterForField'];
}) => FieldSpec;
// (undocumented)
type: string;
// (undocumented)
visualizable?: boolean;
}
@ -1295,6 +1284,8 @@ export interface IIndexPattern extends IndexPatternBase {
//
// (undocumented)
fieldFormatMap?: Record<string, SerializedFieldFormat<unknown> | undefined>;
// (undocumented)
fields: IFieldType[];
getFormatterForField?: (field: IndexPatternField | IndexPatternField['spec'] | IFieldType) => FieldFormat;
// (undocumented)
getTimeField?(): IFieldType | undefined;
@ -1394,7 +1385,9 @@ export class IndexPattern implements IIndexPattern {
// (undocumented)
getAggregationRestrictions(): Record<string, Record<string, {
agg?: string | undefined;
interval?: number | undefined;
interval?: number | undefined; /**
* Get last saved saved object fields
*/
fixed_interval?: string | undefined;
calendar_interval?: string | undefined;
delay?: string | undefined;
@ -1560,7 +1553,7 @@ export class IndexPatternField implements IFieldType {
// (undocumented)
readonly spec: FieldSpec;
// (undocumented)
get subType(): import("../types").IFieldSubType | undefined;
get subType(): import("../..").IFieldSubType | undefined;
// (undocumented)
toJSON(): {
count: number;
@ -1574,7 +1567,7 @@ export class IndexPatternField implements IFieldType {
searchable: boolean;
aggregatable: boolean;
readFromDocValues: boolean;
subType: import("../types").IFieldSubType | undefined;
subType: import("../..").IFieldSubType | undefined;
customLabel: string | undefined;
};
// (undocumented)
@ -2731,13 +2724,13 @@ export interface WaitUntilNextSessionCompletesOptions {
// Warnings were encountered during analysis:
//
// src/plugins/data/common/es_query/filters/exists_filter.ts:20:3 - (ae-forgotten-export) The symbol "ExistsFilterMeta" needs to be exported by the entry point index.d.ts
// src/plugins/data/common/es_query/filters/exists_filter.ts:21:3 - (ae-forgotten-export) The symbol "FilterExistsProperty" needs to be exported by the entry point index.d.ts
// src/plugins/data/common/es_query/filters/exists_filter.ts:19:3 - (ae-forgotten-export) The symbol "ExistsFilterMeta" needs to be exported by the entry point index.d.ts
// src/plugins/data/common/es_query/filters/exists_filter.ts:20:3 - (ae-forgotten-export) The symbol "FilterExistsProperty" needs to be exported by the entry point index.d.ts
// src/plugins/data/common/es_query/filters/match_all_filter.ts:17:3 - (ae-forgotten-export) The symbol "MatchAllFilterMeta" needs to be exported by the entry point index.d.ts
// src/plugins/data/common/es_query/filters/meta_filter.ts:43:3 - (ae-forgotten-export) The symbol "FilterState" needs to be exported by the entry point index.d.ts
// src/plugins/data/common/es_query/filters/meta_filter.ts:44:3 - (ae-forgotten-export) The symbol "FilterMeta" needs to be exported by the entry point index.d.ts
// src/plugins/data/common/es_query/filters/phrase_filter.ts:23:3 - (ae-forgotten-export) The symbol "PhraseFilterMeta" needs to be exported by the entry point index.d.ts
// src/plugins/data/common/es_query/filters/phrases_filter.ts:21:3 - (ae-forgotten-export) The symbol "PhrasesFilterMeta" needs to be exported by the entry point index.d.ts
// src/plugins/data/common/es_query/filters/phrase_filter.ts:22:3 - (ae-forgotten-export) The symbol "PhraseFilterMeta" needs to be exported by the entry point index.d.ts
// src/plugins/data/common/es_query/filters/phrases_filter.ts:20:3 - (ae-forgotten-export) The symbol "PhrasesFilterMeta" needs to be exported by the entry point index.d.ts
// src/plugins/data/common/index_patterns/index_patterns/index_pattern.ts:65:5 - (ae-forgotten-export) The symbol "FormatFieldFn" needs to be exported by the entry point index.d.ts
// src/plugins/data/common/index_patterns/index_patterns/index_pattern.ts:138:7 - (ae-forgotten-export) The symbol "FieldAttrSet" needs to be exported by the entry point index.d.ts
// src/plugins/data/common/index_patterns/index_patterns/index_pattern.ts:169:7 - (ae-forgotten-export) The symbol "RuntimeField" needs to be exported by the entry point index.d.ts

View file

@ -447,11 +447,11 @@ export const esFilters: {
buildQueryFilter: (query: any, index: string, alias: string) => import("../common").QueryStringFilter;
buildCustomFilter: typeof buildCustomFilter;
buildEmptyFilter: (isPinned: boolean, index?: string | undefined) => import("../common").Filter;
buildExistsFilter: (field: import("../common").IFieldType, indexPattern: import("../common").IndexPatternBase) => import("../common").ExistsFilter;
buildExistsFilter: (field: import("../common").IndexPatternFieldBase, indexPattern: import("../common").IndexPatternBase) => import("../common").ExistsFilter;
buildFilter: typeof buildFilter;
buildPhraseFilter: (field: import("../common").IFieldType, value: any, indexPattern: import("../common").IndexPatternBase) => import("../common").PhraseFilter;
buildPhrasesFilter: (field: import("../common").IFieldType, params: any[], indexPattern: import("../common").IndexPatternBase) => import("../common").PhrasesFilter;
buildRangeFilter: (field: import("../common").IFieldType, params: import("../common").RangeFilterParams, indexPattern: import("../common").IndexPatternBase, formattedValue?: string | undefined) => import("../common").RangeFilter;
buildPhraseFilter: (field: import("../common").IndexPatternFieldBase, value: any, indexPattern: import("../common").IndexPatternBase) => import("../common").PhraseFilter;
buildPhrasesFilter: (field: import("../common").IndexPatternFieldBase, params: any[], indexPattern: import("../common").IndexPatternBase) => import("../common").PhrasesFilter;
buildRangeFilter: (field: import("../common").IndexPatternFieldBase, params: import("../common").RangeFilterParams, indexPattern: import("../common").IndexPatternBase, formattedValue?: string | undefined) => import("../common").RangeFilter;
isFilterDisabled: (filter: import("../common").Filter) => boolean;
};
@ -693,10 +693,11 @@ export interface IFieldSubType {
};
}
// Warning: (ae-forgotten-export) The symbol "IndexPatternFieldBase" needs to be exported by the entry point index.d.ts
// Warning: (ae-missing-release-tag) "IFieldType" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public @deprecated (undocumented)
export interface IFieldType {
export interface IFieldType extends IndexPatternFieldBase {
// (undocumented)
aggregatable?: boolean;
// (undocumented)
@ -712,21 +713,11 @@ export interface IFieldType {
// (undocumented)
format?: any;
// (undocumented)
lang?: estypes.ScriptLanguage;
// (undocumented)
name: string;
// (undocumented)
readFromDocValues?: boolean;
// (undocumented)
script?: string;
// (undocumented)
scripted?: boolean;
// (undocumented)
searchable?: boolean;
// (undocumented)
sortable?: boolean;
// (undocumented)
subType?: IFieldSubType;
// Warning: (ae-forgotten-export) The symbol "FieldSpec" needs to be exported by the entry point index.d.ts
//
// (undocumented)
@ -734,8 +725,6 @@ export interface IFieldType {
getFormatterForField?: IndexPattern['getFormatterForField'];
}) => FieldSpec;
// (undocumented)
type: string;
// (undocumented)
visualizable?: boolean;
}
@ -780,7 +769,9 @@ export class IndexPattern implements IIndexPattern {
// (undocumented)
getAggregationRestrictions(): Record<string, Record<string, {
agg?: string | undefined;
interval?: number | undefined;
interval?: number | undefined; /**
* Get last saved saved object fields
*/
fixed_interval?: string | undefined;
calendar_interval?: string | undefined;
delay?: string | undefined;