diff --git a/packages/kbn-securitysolution-autocomplete/BUILD.bazel b/packages/kbn-securitysolution-autocomplete/BUILD.bazel index 8e403a215d81d..c29f6d6badc6f 100644 --- a/packages/kbn-securitysolution-autocomplete/BUILD.bazel +++ b/packages/kbn-securitysolution-autocomplete/BUILD.bazel @@ -36,6 +36,7 @@ SRC_DEPS = [ "//packages/kbn-i18n", "//packages/kbn-securitysolution-io-ts-list-types", "//packages/kbn-securitysolution-list-hooks", + "//packages/kbn-es-query", "@npm//@babel/core", "@npm//babel-loader", "@npm//@elastic/eui", diff --git a/packages/kbn-securitysolution-autocomplete/README.md b/packages/kbn-securitysolution-autocomplete/README.md index fb500ca0761e3..6212b9719679e 100644 --- a/packages/kbn-securitysolution-autocomplete/README.md +++ b/packages/kbn-securitysolution-autocomplete/README.md @@ -12,7 +12,7 @@ This hook uses the kibana `services.data.autocomplete.getValueSuggestions()` ser This component can be used to display available indexPattern fields. It requires an indexPattern to be passed in and will show an error state if value is not one of the available indexPattern fields. Users will be able to select only one option. -The `onChange` handler is passed `IFieldType[]`. +The `onChange` handler is passed `IndexPatternFieldBase[]`. ```js { diff --git a/packages/kbn-securitysolution-autocomplete/src/field/index.tsx b/packages/kbn-securitysolution-autocomplete/src/field/index.tsx index 43342079ef92b..69408e919bb1e 100644 --- a/packages/kbn-securitysolution-autocomplete/src/field/index.tsx +++ b/packages/kbn-securitysolution-autocomplete/src/field/index.tsx @@ -8,11 +8,7 @@ import React, { useCallback, useMemo, useState } from 'react'; import { EuiComboBox, EuiComboBoxOptionOption } from '@elastic/eui'; - -// TODO: I have to use any here for now, but once this is available below, we should use the correct types, https://github.com/elastic/kibana/issues/105731 -// import { IFieldType, IIndexPattern } from '../../../../../../../../src/plugins/data/common'; -type IFieldType = any; -type IIndexPattern = any; +import { IndexPatternBase, IndexPatternFieldBase } from '@kbn/es-query'; import { getGenericComboBoxProps, @@ -24,14 +20,14 @@ const AS_PLAIN_TEXT = { asPlainText: true }; interface OperatorProps { fieldInputWidth?: number; fieldTypeFilter?: string[]; - indexPattern: IIndexPattern | undefined; + indexPattern: IndexPatternBase | undefined; isClearable: boolean; isDisabled: boolean; isLoading: boolean; isRequired?: boolean; - onChange: (a: IFieldType[]) => void; + onChange: (a: IndexPatternFieldBase[]) => void; placeholder: string; - selectedField: IFieldType | undefined; + selectedField: IndexPatternFieldBase | undefined; } export const FieldComponent: React.FC = ({ @@ -60,7 +56,7 @@ export const FieldComponent: React.FC = ({ const handleValuesChange = useCallback( (newOptions: EuiComboBoxOptionOption[]): void => { - const newValues: IFieldType[] = newOptions.map( + const newValues: IndexPatternFieldBase[] = newOptions.map( ({ label }) => availableFields[labels.indexOf(label)] ); onChange(newValues); @@ -98,13 +94,13 @@ export const FieldComponent: React.FC = ({ FieldComponent.displayName = 'Field'; interface ComboBoxFields { - availableFields: IFieldType[]; - selectedFields: IFieldType[]; + availableFields: IndexPatternFieldBase[]; + selectedFields: IndexPatternFieldBase[]; } const getComboBoxFields = ( - indexPattern: IIndexPattern | undefined, - selectedField: IFieldType | undefined, + indexPattern: IndexPatternBase | undefined, + selectedField: IndexPatternFieldBase | undefined, fieldTypeFilter: string[] ): ComboBoxFields => { const existingFields = getExistingFields(indexPattern); @@ -117,27 +113,29 @@ const getComboBoxFields = ( const getComboBoxProps = (fields: ComboBoxFields): GetGenericComboBoxPropsReturn => { const { availableFields, selectedFields } = fields; - return getGenericComboBoxProps({ + return getGenericComboBoxProps({ getLabel: (field) => field.name, options: availableFields, selectedOptions: selectedFields, }); }; -const getExistingFields = (indexPattern: IIndexPattern | undefined): IFieldType[] => { +const getExistingFields = (indexPattern: IndexPatternBase | undefined): IndexPatternFieldBase[] => { return indexPattern != null ? indexPattern.fields : []; }; -const getSelectedFields = (selectedField: IFieldType | undefined): IFieldType[] => { +const getSelectedFields = ( + selectedField: IndexPatternFieldBase | undefined +): IndexPatternFieldBase[] => { return selectedField ? [selectedField] : []; }; const getAvailableFields = ( - existingFields: IFieldType[], - selectedFields: IFieldType[], + existingFields: IndexPatternFieldBase[], + selectedFields: IndexPatternFieldBase[], fieldTypeFilter: string[] -): IFieldType[] => { - const fieldsByName = new Map(); +): IndexPatternFieldBase[] => { + const fieldsByName = new Map(); existingFields.forEach((f) => fieldsByName.set(f.name, f)); selectedFields.forEach((f) => fieldsByName.set(f.name, f)); diff --git a/packages/kbn-securitysolution-autocomplete/src/field_value_lists/index.tsx b/packages/kbn-securitysolution-autocomplete/src/field_value_lists/index.tsx index 4064ff11962bd..093643c3a5469 100644 --- a/packages/kbn-securitysolution-autocomplete/src/field_value_lists/index.tsx +++ b/packages/kbn-securitysolution-autocomplete/src/field_value_lists/index.tsx @@ -10,14 +10,11 @@ import React, { useCallback, useEffect, useMemo, useState } from 'react'; import { EuiComboBox, EuiComboBoxOptionOption, EuiFormRow } from '@elastic/eui'; import type { ListSchema } from '@kbn/securitysolution-io-ts-list-types'; import { useFindLists } from '@kbn/securitysolution-list-hooks'; +import { IndexPatternFieldBase } from '@kbn/es-query'; import { filterFieldToList } from '../filter_field_to_list'; import { getGenericComboBoxProps } from '../get_generic_combo_box_props'; -// TODO: I have to use any here for now, but once this is available below, we should use the correct types, https://github.com/elastic/kibana/issues/105731 -// import { IFieldType } from '../../../../../../../src/plugins/data/common'; -type IFieldType = any; - // TODO: I have to use any here for now, but once this is available below, we should use the correct types, https://github.com/elastic/kibana/issues/100715 // import { HttpStart } from 'kibana/public'; type HttpStart = any; @@ -34,7 +31,7 @@ interface AutocompleteFieldListsProps { onChange: (arg: ListSchema) => void; placeholder: string; rowLabel?: string; - selectedField: IFieldType | undefined; + selectedField: IndexPatternFieldBase | undefined; selectedValue: string | undefined; } diff --git a/packages/kbn-securitysolution-autocomplete/src/field_value_match/index.test.tsx b/packages/kbn-securitysolution-autocomplete/src/field_value_match/index.test.tsx index d695088245622..c0690774965c3 100644 --- a/packages/kbn-securitysolution-autocomplete/src/field_value_match/index.test.tsx +++ b/packages/kbn-securitysolution-autocomplete/src/field_value_match/index.test.tsx @@ -54,7 +54,7 @@ describe('AutocompleteFieldMatchComponent', () => { placeholder="Placeholder text" rowLabel={'Row Label'} selectedField={getField('ip')} - selectedValue="126.45.211.34" + selectedValue="127.0.0.1" /> ); @@ -79,7 +79,7 @@ describe('AutocompleteFieldMatchComponent', () => { onError={jest.fn()} placeholder="Placeholder text" selectedField={getField('ip')} - selectedValue="126.45.211.34" + selectedValue="127.0.0.1" /> ); @@ -104,7 +104,7 @@ describe('AutocompleteFieldMatchComponent', () => { onError={jest.fn()} placeholder="Placeholder text" selectedField={getField('ip')} - selectedValue="126.45.211.34" + selectedValue="127.0.0.1" /> ); wrapper.find('[data-test-subj="valuesAutocompleteMatch"] button').at(0).simulate('click'); @@ -131,7 +131,7 @@ describe('AutocompleteFieldMatchComponent', () => { onError={jest.fn()} placeholder="Placeholder text" selectedField={getField('ip')} - selectedValue="126.45.211.34" + selectedValue="127.0.0.1" /> ); @@ -158,13 +158,13 @@ describe('AutocompleteFieldMatchComponent', () => { onError={jest.fn()} placeholder="Placeholder text" selectedField={getField('ip')} - selectedValue="126.45.211.34" + selectedValue="127.0.0.1" /> ); expect( wrapper.find('[data-test-subj="valuesAutocompleteMatch"] EuiComboBoxPill').at(0).text() - ).toEqual('126.45.211.34'); + ).toEqual('127.0.0.1'); }); test('it invokes "onChange" when new value created', async () => { @@ -190,9 +190,9 @@ describe('AutocompleteFieldMatchComponent', () => { ((wrapper.find(EuiComboBox).props() as unknown) as { onCreateOption: (a: string) => void; - }).onCreateOption('126.45.211.34'); + }).onCreateOption('127.0.0.1'); - expect(mockOnChange).toHaveBeenCalledWith('126.45.211.34'); + expect(mockOnChange).toHaveBeenCalledWith('127.0.0.1'); }); test('it invokes "onChange" when new value selected', async () => { diff --git a/packages/kbn-securitysolution-autocomplete/src/field_value_match/index.tsx b/packages/kbn-securitysolution-autocomplete/src/field_value_match/index.tsx index 8199967489515..9088517adbe58 100644 --- a/packages/kbn-securitysolution-autocomplete/src/field_value_match/index.tsx +++ b/packages/kbn-securitysolution-autocomplete/src/field_value_match/index.tsx @@ -14,6 +14,8 @@ import { EuiComboBoxOptionOption, EuiComboBox, } from '@elastic/eui'; +import { IndexPatternBase, IndexPatternFieldBase } from '@kbn/es-query'; + import { uniq } from 'lodash'; import { ListOperatorTypeEnum as OperatorTypeEnum } from '@kbn/securitysolution-io-ts-list-types'; @@ -22,11 +24,6 @@ import { ListOperatorTypeEnum as OperatorTypeEnum } from '@kbn/securitysolution- // import { AutocompleteStart } from '../../../../../../../src/plugins/data/public'; type AutocompleteStart = any; -// TODO: I have to use any here for now, but once this is available below, we should use the correct types, https://github.com/elastic/kibana/issues/105731 -// import { IFieldType, IIndexPattern } from '../../../../../../../../src/plugins/data/common'; -type IFieldType = any; -type IIndexPattern = any; - import * as i18n from '../translations'; import { useFieldValueAutocomplete } from '../hooks/use_field_value_autocomplete'; import { @@ -44,9 +41,9 @@ const SINGLE_SELECTION = { asPlainText: true }; interface AutocompleteFieldMatchProps { placeholder: string; - selectedField: IFieldType | undefined; + selectedField: IndexPatternFieldBase | undefined; selectedValue: string | undefined; - indexPattern: IIndexPattern | undefined; + indexPattern: IndexPatternBase | undefined; isLoading: boolean; isDisabled: boolean; isClearable: boolean; diff --git a/packages/kbn-securitysolution-autocomplete/src/field_value_match_any/index.test.tsx b/packages/kbn-securitysolution-autocomplete/src/field_value_match_any/index.test.tsx index a3ca97874908e..389761c9a6dfc 100644 --- a/packages/kbn-securitysolution-autocomplete/src/field_value_match_any/index.test.tsx +++ b/packages/kbn-securitysolution-autocomplete/src/field_value_match_any/index.test.tsx @@ -64,7 +64,7 @@ describe('AutocompleteFieldMatchAnyComponent', () => { placeholder="Placeholder text" rowLabel={'Row Label'} selectedField={getField('ip')} - selectedValue={['126.45.211.34']} + selectedValue={['127.0.0.1']} /> ); @@ -124,7 +124,7 @@ describe('AutocompleteFieldMatchAnyComponent', () => { placeholder="Placeholder text" rowLabel={'Row Label'} selectedField={getField('ip')} - selectedValue={['126.45.211.34']} + selectedValue={['127.0.0.1']} /> ); @@ -155,13 +155,13 @@ describe('AutocompleteFieldMatchAnyComponent', () => { placeholder="Placeholder text" rowLabel={'Row Label'} selectedField={getField('ip')} - selectedValue={['126.45.211.34']} + selectedValue={['127.0.0.1']} /> ); expect( wrapper.find(`[data-test-subj="valuesAutocompleteMatchAny"] EuiComboBoxPill`).at(0).text() - ).toEqual('126.45.211.34'); + ).toEqual('127.0.0.1'); }); test('it invokes "onChange" when new value created', async () => { @@ -191,9 +191,9 @@ describe('AutocompleteFieldMatchAnyComponent', () => { ((wrapper.find(EuiComboBox).props() as unknown) as { onCreateOption: (a: string) => void; - }).onCreateOption('126.45.211.34'); + }).onCreateOption('127.0.0.1'); - expect(mockOnChange).toHaveBeenCalledWith(['126.45.211.34']); + expect(mockOnChange).toHaveBeenCalledWith(['127.0.0.1']); }); test('it invokes "onChange" when new value selected', async () => { diff --git a/packages/kbn-securitysolution-autocomplete/src/field_value_match_any/index.tsx b/packages/kbn-securitysolution-autocomplete/src/field_value_match_any/index.tsx index 338c4baa8bc6f..bfcafd199dc32 100644 --- a/packages/kbn-securitysolution-autocomplete/src/field_value_match_any/index.tsx +++ b/packages/kbn-securitysolution-autocomplete/src/field_value_match_any/index.tsx @@ -10,16 +10,12 @@ import React, { useCallback, useMemo, useState } from 'react'; import { EuiComboBox, EuiComboBoxOptionOption, EuiFormRow } from '@elastic/eui'; import { uniq } from 'lodash'; import { ListOperatorTypeEnum as OperatorTypeEnum } from '@kbn/securitysolution-io-ts-list-types'; +import { IndexPatternBase, IndexPatternFieldBase } from '@kbn/es-query'; // TODO: I have to use any here for now, but once this is available below, we should use the correct types, https://github.com/elastic/kibana/issues/100715 // import { AutocompleteStart } from '../../../../../../../src/plugins/data/public'; type AutocompleteStart = any; -// TODO: I have to use any here for now, but once this is available below, we should use the correct types, https://github.com/elastic/kibana/issues/105731 -// import { IFieldType, IIndexPattern } from '../../../../../../../../src/plugins/data/common'; -type IFieldType = any; -type IIndexPattern = any; - import * as i18n from '../translations'; import { getGenericComboBoxProps, @@ -30,9 +26,9 @@ import { paramIsValid } from '../param_is_valid'; interface AutocompleteFieldMatchAnyProps { placeholder: string; - selectedField: IFieldType | undefined; + selectedField: IndexPatternFieldBase | undefined; selectedValue: string[]; - indexPattern: IIndexPattern | undefined; + indexPattern: IndexPatternBase | undefined; isLoading: boolean; isDisabled: boolean; isClearable: boolean; diff --git a/packages/kbn-securitysolution-autocomplete/src/fields/index.mock.ts b/packages/kbn-securitysolution-autocomplete/src/fields/index.mock.ts index 5938ed34547a1..a79325e25343f 100644 --- a/packages/kbn-securitysolution-autocomplete/src/fields/index.mock.ts +++ b/packages/kbn-securitysolution-autocomplete/src/fields/index.mock.ts @@ -6,11 +6,12 @@ * Side Public License, v 1. */ -// Copied from "src/plugins/data/common/index_patterns/fields/fields.mocks.ts" -// but without types. +import { IndexPatternFieldBase } from '@kbn/es-query'; + +// Copied from "src/plugins/data/common/index_patterns/fields/fields.mocks.ts" but with the types changed to "IndexPatternFieldBase" since that type is compatible. // TODO: This should move out once those mocks are directly useable or in their own package, https://github.com/elastic/kibana/issues/100715 -export const fields = [ +export const fields: IndexPatternFieldBase[] = ([ { name: 'bytes', type: 'number', @@ -308,6 +309,6 @@ export const fields = [ readFromDocValues: false, subType: { nested: { path: 'nestedField.nestedChild' } }, }, -]; +] as unknown) as IndexPatternFieldBase[]; export const getField = (name: string) => fields.find((field) => field.name === name); diff --git a/packages/kbn-securitysolution-autocomplete/src/filter_field_to_list/index.test.ts b/packages/kbn-securitysolution-autocomplete/src/filter_field_to_list/index.test.ts index 1022849ffda36..cb39adb9fde26 100644 --- a/packages/kbn-securitysolution-autocomplete/src/filter_field_to_list/index.test.ts +++ b/packages/kbn-securitysolution-autocomplete/src/filter_field_to_list/index.test.ts @@ -10,10 +10,7 @@ import { filterFieldToList } from '.'; import type { ListSchema } from '@kbn/securitysolution-io-ts-list-types'; import { getListResponseMock } from '../list_schema/index.mock'; - -// TODO: I have to use any here for now, but once this is available below, we should use the correct types, https://github.com/elastic/kibana/issues/105731 -// import { IFieldType } from '../../../../../../../src/plugins/data/common'; -type IFieldType = any; +import { IndexPatternFieldBase } from '@kbn/es-query'; describe('#filterFieldToList', () => { test('it returns empty array if given a undefined for field', () => { @@ -22,13 +19,20 @@ describe('#filterFieldToList', () => { }); test('it returns empty array if filed does not contain esTypes', () => { - const field: IFieldType = { name: 'some-name', type: 'some-type' }; + const field: IndexPatternFieldBase = { + name: 'some-name', + type: 'some-type', + }; const filter = filterFieldToList([], field); expect(filter).toEqual([]); }); test('it returns single filtered list of ip_range -> ip', () => { - const field: IFieldType = { esTypes: ['ip'], name: 'some-name', type: 'ip' }; + const field: IndexPatternFieldBase & { esTypes: string[] } = { + esTypes: ['ip'], + name: 'some-name', + type: 'ip', + }; const listItem: ListSchema = { ...getListResponseMock(), type: 'ip_range' }; const filter = filterFieldToList([listItem], field); const expected: ListSchema[] = [listItem]; @@ -36,7 +40,11 @@ describe('#filterFieldToList', () => { }); test('it returns single filtered list of ip -> ip', () => { - const field: IFieldType = { esTypes: ['ip'], name: 'some-name', type: 'ip' }; + const field: IndexPatternFieldBase & { esTypes: string[] } = { + esTypes: ['ip'], + name: 'some-name', + type: 'ip', + }; const listItem: ListSchema = { ...getListResponseMock(), type: 'ip' }; const filter = filterFieldToList([listItem], field); const expected: ListSchema[] = [listItem]; @@ -44,7 +52,11 @@ describe('#filterFieldToList', () => { }); test('it returns single filtered list of keyword -> keyword', () => { - const field: IFieldType = { esTypes: ['keyword'], name: 'some-name', type: 'keyword' }; + const field: IndexPatternFieldBase & { esTypes: string[] } = { + esTypes: ['keyword'], + name: 'some-name', + type: 'keyword', + }; const listItem: ListSchema = { ...getListResponseMock(), type: 'keyword' }; const filter = filterFieldToList([listItem], field); const expected: ListSchema[] = [listItem]; @@ -52,7 +64,11 @@ describe('#filterFieldToList', () => { }); test('it returns single filtered list of text -> text', () => { - const field: IFieldType = { esTypes: ['text'], name: 'some-name', type: 'text' }; + const field: IndexPatternFieldBase & { esTypes: string[] } = { + esTypes: ['text'], + name: 'some-name', + type: 'text', + }; const listItem: ListSchema = { ...getListResponseMock(), type: 'text' }; const filter = filterFieldToList([listItem], field); const expected: ListSchema[] = [listItem]; @@ -60,7 +76,11 @@ describe('#filterFieldToList', () => { }); test('it returns 2 filtered lists of ip_range -> ip', () => { - const field: IFieldType = { esTypes: ['ip'], name: 'some-name', type: 'ip' }; + const field: IndexPatternFieldBase & { esTypes: string[] } = { + esTypes: ['ip'], + name: 'some-name', + type: 'ip', + }; const listItem1: ListSchema = { ...getListResponseMock(), type: 'ip_range' }; const listItem2: ListSchema = { ...getListResponseMock(), type: 'ip_range' }; const filter = filterFieldToList([listItem1, listItem2], field); @@ -69,7 +89,11 @@ describe('#filterFieldToList', () => { }); test('it returns 1 filtered lists of ip_range -> ip if the 2nd is not compatible type', () => { - const field: IFieldType = { esTypes: ['ip'], name: 'some-name', type: 'ip' }; + const field: IndexPatternFieldBase & { esTypes: string[] } = { + esTypes: ['ip'], + name: 'some-name', + type: 'ip', + }; const listItem1: ListSchema = { ...getListResponseMock(), type: 'ip_range' }; const listItem2: ListSchema = { ...getListResponseMock(), type: 'text' }; const filter = filterFieldToList([listItem1, listItem2], field); diff --git a/packages/kbn-securitysolution-autocomplete/src/filter_field_to_list/index.ts b/packages/kbn-securitysolution-autocomplete/src/filter_field_to_list/index.ts index b2e48c25f9b51..51ce349fa39fd 100644 --- a/packages/kbn-securitysolution-autocomplete/src/filter_field_to_list/index.ts +++ b/packages/kbn-securitysolution-autocomplete/src/filter_field_to_list/index.ts @@ -7,19 +7,23 @@ */ import { ListSchema } from '@kbn/securitysolution-io-ts-list-types'; +import { IndexPatternFieldBase } from '@kbn/es-query'; import { typeMatch } from '../type_match'; -// TODO: I have to use any here for now, but once this is available below, we should use the correct types, https://github.com/elastic/kibana/issues/105731 -// import { IFieldType, IIndexPattern } from '../../../../../../../../src/plugins/data/common'; -type IFieldType = any; - /** * Given an array of lists and optionally a field this will return all * the lists that match against the field based on the types from the field + * + * NOTE: That we support one additional property from "FieldSpec" located here: + * src/plugins/data/common/index_patterns/fields/types.ts + * This type property is esTypes. If it exists and is on there we will read off the esTypes. * @param lists The lists to match against the field * @param field The field to check against the list to see if they are compatible */ -export const filterFieldToList = (lists: ListSchema[], field?: IFieldType): ListSchema[] => { +export const filterFieldToList = ( + lists: ListSchema[], + field?: IndexPatternFieldBase & { esTypes?: string[] } +): ListSchema[] => { if (field != null) { const { esTypes = [] } = field; return lists.filter(({ type }) => esTypes.some((esType: string) => typeMatch(type, esType))); diff --git a/packages/kbn-securitysolution-autocomplete/src/get_operators/index.test.ts b/packages/kbn-securitysolution-autocomplete/src/get_operators/index.test.ts index e473df104fa6a..9ed9c6358c397 100644 --- a/packages/kbn-securitysolution-autocomplete/src/get_operators/index.test.ts +++ b/packages/kbn-securitysolution-autocomplete/src/get_operators/index.test.ts @@ -31,13 +31,8 @@ describe('#getOperators', () => { test('it returns "isOperator" when field type is "nested"', () => { const operator = getOperators({ - aggregatable: false, - count: 0, - esTypes: ['text'], name: 'nestedField', - readFromDocValues: false, scripted: false, - searchable: true, subType: { nested: { path: 'nestedField' } }, type: 'nested', }); diff --git a/packages/kbn-securitysolution-autocomplete/src/get_operators/index.ts b/packages/kbn-securitysolution-autocomplete/src/get_operators/index.ts index 39d2779e2dc44..b50bd57608e7a 100644 --- a/packages/kbn-securitysolution-autocomplete/src/get_operators/index.ts +++ b/packages/kbn-securitysolution-autocomplete/src/get_operators/index.ts @@ -6,9 +6,7 @@ * Side Public License, v 1. */ -// TODO: I have to use any here for now, but once this is available below, we should use the correct types, https://github.com/elastic/kibana/issues/105731 -// import { IFieldType } from '../../../../../../../src/plugins/data/common'; -type IFieldType = any; +import { IndexPatternFieldBase } from '@kbn/es-query'; import { EXCEPTION_OPERATORS, @@ -22,10 +20,10 @@ import { /** * Returns the appropriate operators given a field type * - * @param field IFieldType selected field + * @param field IndexPatternFieldBase selected field * */ -export const getOperators = (field: IFieldType | undefined): OperatorOption[] => { +export const getOperators = (field: IndexPatternFieldBase | undefined): OperatorOption[] => { if (field == null) { return [isOperator]; } else if (field.type === 'boolean') { diff --git a/packages/kbn-securitysolution-autocomplete/src/hooks/use_field_value_autocomplete/index.test.ts b/packages/kbn-securitysolution-autocomplete/src/hooks/use_field_value_autocomplete/index.test.ts index 534daa021cf4a..04b674758f952 100644 --- a/packages/kbn-securitysolution-autocomplete/src/hooks/use_field_value_autocomplete/index.test.ts +++ b/packages/kbn-securitysolution-autocomplete/src/hooks/use_field_value_autocomplete/index.test.ts @@ -16,6 +16,7 @@ import { } from '.'; import { getField } from '../../fields/index.mock'; import { autocompleteStartMock } from '../../autocomplete/index.mock'; +import { IndexPatternFieldBase } from '@kbn/es-query'; // Copied from "src/plugins/data/common/index_patterns/index_pattern.stub.ts" // TODO: Remove this in favor of the above if/when it is ported, https://github.com/elastic/kibana/issues/100715 @@ -152,6 +153,11 @@ describe('use_field_value_autocomplete', () => { const suggestionsMock = jest.fn().mockResolvedValue([]); await act(async () => { + const selectedField: IndexPatternFieldBase | undefined = getField('nestedField.child'); + if (selectedField == null) { + throw new TypeError('selectedField for this test should always be defined'); + } + const { signal } = new AbortController(); const { waitForNextUpdate } = renderHook< UseFieldValueAutocompleteProps, @@ -166,7 +172,7 @@ describe('use_field_value_autocomplete', () => { indexPattern: stubIndexPatternWithFields, operatorType: OperatorTypeEnum.MATCH, query: '', - selectedField: { ...getField('nestedField.child'), name: 'child' }, + selectedField: { ...selectedField, name: 'child' }, }) ); // Note: initial `waitForNextUpdate` is hook initialization diff --git a/packages/kbn-securitysolution-autocomplete/src/hooks/use_field_value_autocomplete/index.ts b/packages/kbn-securitysolution-autocomplete/src/hooks/use_field_value_autocomplete/index.ts index b4dec1615e3ed..2b65051a6c67d 100644 --- a/packages/kbn-securitysolution-autocomplete/src/hooks/use_field_value_autocomplete/index.ts +++ b/packages/kbn-securitysolution-autocomplete/src/hooks/use_field_value_autocomplete/index.ts @@ -9,19 +9,15 @@ import { useEffect, useRef, useState } from 'react'; import { debounce } from 'lodash'; import { ListOperatorTypeEnum as OperatorTypeEnum } from '@kbn/securitysolution-io-ts-list-types'; +import { IndexPatternBase, IndexPatternFieldBase } from '@kbn/es-query'; // TODO: I have to use any here for now, but once this is available below, we should use the correct types, https://github.com/elastic/kibana/issues/100715 // import { AutocompleteStart } from '../../../../../../../../src/plugins/data/public'; type AutocompleteStart = any; -// TODO: I have to use any here for now, but once this is available below, we should use the correct types, https://github.com/elastic/kibana/issues/105731 -// import { IFieldType, IIndexPattern } from '../../../../../../../../src/plugins/data/common'; -type IFieldType = any; -type IIndexPattern = any; - interface FuncArgs { - fieldSelected: IFieldType | undefined; - patterns: IIndexPattern | undefined; + fieldSelected: IndexPatternFieldBase | undefined; + patterns: IndexPatternBase | undefined; searchQuery: string; value: string | string[] | undefined; } @@ -33,10 +29,10 @@ export type UseFieldValueAutocompleteReturn = [boolean, boolean, string[], Func export interface UseFieldValueAutocompleteProps { autocompleteService: AutocompleteStart; fieldValue: string | string[] | undefined; - indexPattern: IIndexPattern | undefined; + indexPattern: IndexPatternBase | undefined; operatorType: OperatorTypeEnum; query: string; - selectedField: IFieldType | undefined; + selectedField: IndexPatternFieldBase | undefined; } /** * Hook for using the field value autocomplete service diff --git a/packages/kbn-securitysolution-autocomplete/src/operator/index.test.tsx b/packages/kbn-securitysolution-autocomplete/src/operator/index.test.tsx index fed7007b49636..e2af384215c25 100644 --- a/packages/kbn-securitysolution-autocomplete/src/operator/index.test.tsx +++ b/packages/kbn-securitysolution-autocomplete/src/operator/index.test.tsx @@ -160,13 +160,8 @@ describe('operator', () => { operator={isOperator} placeholder="Placeholder text" selectedField={{ - aggregatable: false, - count: 0, - esTypes: ['text'], name: 'nestedField', - readFromDocValues: false, scripted: false, - searchable: true, subType: { nested: { path: 'nestedField' } }, type: 'nested', }} diff --git a/packages/kbn-securitysolution-autocomplete/src/operator/index.tsx b/packages/kbn-securitysolution-autocomplete/src/operator/index.tsx index 08f058fd57819..dc12de7c398c3 100644 --- a/packages/kbn-securitysolution-autocomplete/src/operator/index.tsx +++ b/packages/kbn-securitysolution-autocomplete/src/operator/index.tsx @@ -9,10 +9,7 @@ import React, { useCallback, useMemo } from 'react'; import { EuiComboBox, EuiComboBoxOptionOption } from '@elastic/eui'; import { OperatorOption } from '@kbn/securitysolution-list-utils'; - -// TODO: I have to use any here for now, but once this is available below, we should use the correct types, https://github.com/elastic/kibana/issues/105731 -// import { IFieldType } from '../../../../../../../src/plugins/data/common'; -type IFieldType = any; +import { IndexPatternFieldBase } from '@kbn/es-query'; import { getOperators } from '../get_operators'; import { @@ -31,7 +28,7 @@ interface OperatorState { operatorInputWidth?: number; operatorOptions?: OperatorOption[]; placeholder: string; - selectedField: IFieldType | undefined; + selectedField: IndexPatternFieldBase | undefined; } export const OperatorComponent: React.FC = ({ diff --git a/packages/kbn-securitysolution-autocomplete/src/param_is_valid/index.ts b/packages/kbn-securitysolution-autocomplete/src/param_is_valid/index.ts index 5b596b4b62408..17de850e92984 100644 --- a/packages/kbn-securitysolution-autocomplete/src/param_is_valid/index.ts +++ b/packages/kbn-securitysolution-autocomplete/src/param_is_valid/index.ts @@ -7,12 +7,9 @@ */ import dateMath from '@elastic/datemath'; +import { IndexPatternFieldBase } from '@kbn/es-query'; import { checkEmptyValue } from '../check_empty_value'; -// TODO: I have to use any here for now, but once this is available below, we should use the correct types, https://github.com/elastic/kibana/issues/105731 -// import { IFieldType } from '../../../../../../../src/plugins/data/common'; -type IFieldType = any; - import * as i18n from '../translations'; /** @@ -25,7 +22,7 @@ import * as i18n from '../translations'; */ export const paramIsValid = ( param: string | undefined, - field: IFieldType | undefined, + field: IndexPatternFieldBase | undefined, isRequired: boolean, touched: boolean ): string | undefined => { diff --git a/packages/kbn-securitysolution-list-utils/BUILD.bazel b/packages/kbn-securitysolution-list-utils/BUILD.bazel index 0d257a95f0259..cb6ddbd7f91d5 100644 --- a/packages/kbn-securitysolution-list-utils/BUILD.bazel +++ b/packages/kbn-securitysolution-list-utils/BUILD.bazel @@ -32,6 +32,7 @@ SRC_DEPS = [ "//packages/kbn-securitysolution-list-constants", "//packages/kbn-securitysolution-io-ts-list-types", "//packages/kbn-securitysolution-utils", + "//packages/kbn-es-query", "@npm//lodash", "@npm//tslib", ] diff --git a/packages/kbn-securitysolution-list-utils/src/build_exception_filter/index.ts b/packages/kbn-securitysolution-list-utils/src/build_exception_filter/index.ts index 72db4991a49a4..77e369dbcac74 100644 --- a/packages/kbn-securitysolution-list-utils/src/build_exception_filter/index.ts +++ b/packages/kbn-securitysolution-list-utils/src/build_exception_filter/index.ts @@ -21,17 +21,10 @@ import { entriesNested, OsTypeArray, } from '@kbn/securitysolution-io-ts-list-types'; +import { Filter } from '@kbn/es-query'; import { hasLargeValueList } from '../has_large_value_list'; -/** - * Originally this was an import type of: - * import type { Filter } from '../../../../../src/plugins/data/common'; - * TODO: Once we have the type for this within kbn packages, replace this with that one - * @deprecated - */ -type Filter = any; - type NonListEntry = EntryMatch | EntryMatchAny | EntryNested | EntryExists; interface ExceptionListItemNonLargeList extends ExceptionListItemSchema { entries: NonListEntry[]; @@ -190,7 +183,7 @@ export const buildExceptionFilter = ({ } else { const chunks = chunkExceptions(exceptionsWithoutLargeValueLists, chunkSize); - const filters = chunks.map((exceptionsChunk) => { + const filters = chunks.map((exceptionsChunk) => { const orClauses = createOrClauses(exceptionsChunk); return { diff --git a/packages/kbn-securitysolution-list-utils/src/helpers/index.ts b/packages/kbn-securitysolution-list-utils/src/helpers/index.ts index 38446b2a08ec0..eeab05fadb126 100644 --- a/packages/kbn-securitysolution-list-utils/src/helpers/index.ts +++ b/packages/kbn-securitysolution-list-utils/src/helpers/index.ts @@ -28,11 +28,7 @@ import { exceptionListItemSchema, nestedEntryItem, } from '@kbn/securitysolution-io-ts-list-types'; - -// TODO: I have to use any here for now, but once this is available below, we should use the correct types -// import { IFieldType, IIndexPattern } from '../../../../../../../src/plugins/data/public'; -type IFieldType = any; -type IIndexPattern = any; +import { IndexPatternBase, IndexPatternFieldBase } from '@kbn/es-query'; import { EXCEPTION_OPERATORS, @@ -282,17 +278,17 @@ export const getUpdatedEntriesOnDelete = ( * add nested entry, should only show nested fields, if item is the parent * field of a nested entry, we only display the parent field * - * @param patterns IIndexPattern containing available fields on rule index + * @param patterns IndexPatternBase containing available fields on rule index * @param item exception item entry * set to add a nested field */ export const getFilteredIndexPatterns = ( - patterns: IIndexPattern, + patterns: IndexPatternBase, item: FormattedBuilderEntry, type: ExceptionListType, - preFilter?: (i: IIndexPattern, t: ExceptionListType, o?: OsTypeArray) => IIndexPattern, + preFilter?: (i: IndexPatternBase, t: ExceptionListType, o?: OsTypeArray) => IndexPatternBase, osTypes?: OsTypeArray -): IIndexPattern => { +): IndexPatternBase => { const indexPatterns = preFilter != null ? preFilter(patterns, type, osTypes) : patterns; if (item.nested === 'child' && item.parent != null) { @@ -300,7 +296,6 @@ export const getFilteredIndexPatterns = ( return { ...indexPatterns, fields: indexPatterns.fields - // @ts-expect-error This will go away once we type IField from any .filter((indexField) => { const fieldHasCommonParentPath = indexField.subType != null && @@ -310,7 +305,6 @@ export const getFilteredIndexPatterns = ( return fieldHasCommonParentPath; }) - // @ts-expect-error This will go away once we type IField from any .map((f) => { const [fieldNameWithoutParentPath] = f.name.split('.').slice(-1); return { ...f, name: fieldNameWithoutParentPath }; @@ -324,7 +318,6 @@ export const getFilteredIndexPatterns = ( return { ...indexPatterns, fields: indexPatterns.fields.filter( - // @ts-expect-error This will go away once we type IField from any (field) => field.subType != null && field.subType.nested != null ), }; @@ -342,7 +335,7 @@ export const getFilteredIndexPatterns = ( */ export const getEntryOnFieldChange = ( item: FormattedBuilderEntry, - newField: IFieldType + newField: IndexPatternFieldBase ): { index: number; updatedEntry: BuilderEntry } => { const { parent, entryIndex, nested } = item; const newChildFieldValue = newField != null ? newField.name.split('.').slice(-1)[0] : ''; @@ -657,9 +650,9 @@ export const getCorrespondingKeywordField = ({ fields, selectedField, }: { - fields: IFieldType[]; + fields: IndexPatternFieldBase[]; selectedField: string | undefined; -}): IFieldType | undefined => { +}): IndexPatternFieldBase | undefined => { const selectedFieldBits = selectedField != null && selectedField !== '' ? selectedField.split('.') : []; const selectedFieldIsTextType = selectedFieldBits.slice(-1)[0] === 'text'; @@ -679,7 +672,7 @@ export const getCorrespondingKeywordField = ({ * Formats the entry into one that is easily usable for the UI, most of the * complexity was introduced with nested fields * - * @param patterns IIndexPattern containing available fields on rule index + * @param patterns IndexPatternBase containing available fields on rule index * @param item exception item entry * @param itemIndex entry index * @param parent nested entries hold copy of their parent for use in various logic @@ -687,7 +680,7 @@ export const getCorrespondingKeywordField = ({ * was added to ensure that nested items could be identified with their parent entry */ export const getFormattedBuilderEntry = ( - indexPattern: IIndexPattern, + indexPattern: IndexPatternBase, item: BuilderEntry, itemIndex: number, parent: EntryNested | undefined, @@ -695,7 +688,6 @@ export const getFormattedBuilderEntry = ( ): FormattedBuilderEntry => { const { fields } = indexPattern; const field = parent != null ? `${parent.field}.${item.field}` : item.field; - // @ts-expect-error This will go away once we type IField from any const [foundField] = fields.filter(({ name }) => field != null && field === name); const correspondingKeywordField = getCorrespondingKeywordField({ fields, @@ -734,7 +726,7 @@ export const getFormattedBuilderEntry = ( * Formats the entries to be easily usable for the UI, most of the * complexity was introduced with nested fields * - * @param patterns IIndexPattern containing available fields on rule index + * @param patterns IndexPatternBase containing available fields on rule index * @param entries exception item entries * @param addNested boolean noting whether or not UI is currently * set to add a nested field @@ -743,7 +735,7 @@ export const getFormattedBuilderEntry = ( * was added to ensure that nested items could be identified with their parent entry */ export const getFormattedBuilderEntries = ( - indexPattern: IIndexPattern, + indexPattern: IndexPatternBase, entries: BuilderEntry[], parent?: EntryNested, parentIndex?: number @@ -765,13 +757,14 @@ export const getFormattedBuilderEntries = ( entryIndex: index, field: isNewNestedEntry ? undefined - : { + : // This type below is really a FieldSpec type from "src/plugins/data/common/index_patterns/fields/types.ts", we cast it here to keep using the IndexPatternFieldBase interface + ({ aggregatable: false, esTypes: ['nested'], name: item.field != null ? item.field : '', searchable: false, type: 'string', - }, + } as IndexPatternFieldBase), id: item.id != null ? item.id : `${index}`, nested: 'parent', operator: isOperator, diff --git a/packages/kbn-securitysolution-list-utils/src/types/index.ts b/packages/kbn-securitysolution-list-utils/src/types/index.ts index 537ac06a49f34..68896f1811472 100644 --- a/packages/kbn-securitysolution-list-utils/src/types/index.ts +++ b/packages/kbn-securitysolution-list-utils/src/types/index.ts @@ -6,6 +6,7 @@ * Side Public License, v 1. */ +import { IndexPatternFieldBase } from '@kbn/es-query'; import type { CreateExceptionListItemSchema, Entry, @@ -30,21 +31,15 @@ export interface OperatorOption { type: OperatorTypeEnum; } -/** - * @deprecated Use the one from core once it is in its own package which will be from: - * Original import was // import { IFieldType } from '../../../../../../../src/plugins/data/common'; - */ -type IFieldType = any; - export interface FormattedBuilderEntry { id: string; - field: IFieldType | undefined; + field: IndexPatternFieldBase | undefined; operator: OperatorOption; value: string | string[] | undefined; nested: 'parent' | 'child' | undefined; entryIndex: number; parent: { parent: BuilderEntryNested; parentIndex: number } | undefined; - correspondingKeywordField: IFieldType | undefined; + correspondingKeywordField: IndexPatternFieldBase | undefined; } export interface EmptyEntry { diff --git a/x-pack/plugins/lists/public/exceptions/components/builder/builder.stories.tsx b/x-pack/plugins/lists/public/exceptions/components/builder/builder.stories.tsx index f11cb7546b417..da320e871072c 100644 --- a/x-pack/plugins/lists/public/exceptions/components/builder/builder.stories.tsx +++ b/x-pack/plugins/lists/public/exceptions/components/builder/builder.stories.tsx @@ -113,7 +113,7 @@ export default { }, indexPatterns: { description: - '`IIndexPattern` - index patterns used to populate field options and value autocomplete.', + '`IndexPatternBase` - index patterns used to populate field options and value autocomplete.', type: { required: true, }, @@ -195,7 +195,7 @@ export default { }, listTypeSpecificIndexPatternFilter: { description: - '`(pattern: IIndexPattern, type: ExceptionListType) => IIndexPattern` - callback invoked when index patterns filtered. Optional to be used if you would only like certain fields displayed.', + '`(pattern: IndexPatternBase, type: ExceptionListType) => IndexPatternBase` - callback invoked when index patterns filtered. Optional to be used if you would only like certain fields displayed.', type: { required: false, }, diff --git a/x-pack/plugins/lists/public/exceptions/components/builder/entry_renderer.stories.tsx b/x-pack/plugins/lists/public/exceptions/components/builder/entry_renderer.stories.tsx index dd67381c30934..9bf2ca0fc017a 100644 --- a/x-pack/plugins/lists/public/exceptions/components/builder/entry_renderer.stories.tsx +++ b/x-pack/plugins/lists/public/exceptions/components/builder/entry_renderer.stories.tsx @@ -102,7 +102,7 @@ export default { }, indexPattern: { description: - '`IIndexPattern` - index patterns used to populate field options and value autocomplete.', + '`IndexPatternBase` - index patterns used to populate field options and value autocomplete.', type: { required: true, }, diff --git a/x-pack/plugins/lists/public/exceptions/components/builder/entry_renderer.test.tsx b/x-pack/plugins/lists/public/exceptions/components/builder/entry_renderer.test.tsx index 4d22a883ad846..f692ad96988cf 100644 --- a/x-pack/plugins/lists/public/exceptions/components/builder/entry_renderer.test.tsx +++ b/x-pack/plugins/lists/public/exceptions/components/builder/entry_renderer.test.tsx @@ -20,6 +20,7 @@ import { isOperator, } from '@kbn/securitysolution-list-utils'; import { useFindLists } from '@kbn/securitysolution-list-hooks'; +import { FieldSpec } from 'src/plugins/data/common'; import { fields, @@ -374,31 +375,33 @@ describe('BuilderEntryItem', () => { }); test('it uses "correspondingKeywordField" if it exists', () => { + const correspondingKeywordField: FieldSpec = { + aggregatable: true, + count: 0, + esTypes: ['keyword'], + name: 'extension', + readFromDocValues: true, + scripted: false, + searchable: true, + type: 'string', + }; + const field: FieldSpec = { + aggregatable: false, + count: 0, + esTypes: ['text'], + name: 'extension.text', + readFromDocValues: true, + scripted: false, + searchable: false, + type: 'string', + }; wrapper = mount( { ((wrapper.find(EuiComboBox).at(2).props() as unknown) as { onCreateOption: (a: string) => void; - }).onCreateOption('126.45.211.34'); + }).onCreateOption('127.0.0.1'); expect(mockOnChange).toHaveBeenCalledWith( - { field: 'ip', id: '123', operator: 'excluded', type: 'match', value: '126.45.211.34' }, + { field: 'ip', id: '123', operator: 'excluded', type: 'match', value: '127.0.0.1' }, 0 ); }); @@ -576,10 +579,10 @@ describe('BuilderEntryItem', () => { ((wrapper.find(EuiComboBox).at(2).props() as unknown) as { onCreateOption: (a: string) => void; - }).onCreateOption('126.45.211.34'); + }).onCreateOption('127.0.0.1'); expect(mockOnChange).toHaveBeenCalledWith( - { field: 'ip', id: '123', operator: 'included', type: 'match_any', value: ['126.45.211.34'] }, + { field: 'ip', id: '123', operator: 'included', type: 'match_any', value: ['127.0.0.1'] }, 0 ); }); diff --git a/x-pack/plugins/lists/public/exceptions/components/builder/entry_renderer.tsx b/x-pack/plugins/lists/public/exceptions/components/builder/entry_renderer.tsx index d7741b3fe0ff1..19349c4eff9b8 100644 --- a/x-pack/plugins/lists/public/exceptions/components/builder/entry_renderer.tsx +++ b/x-pack/plugins/lists/public/exceptions/components/builder/entry_renderer.tsx @@ -35,9 +35,9 @@ import { FieldComponent, OperatorComponent, } from '@kbn/securitysolution-autocomplete'; +import { IndexPatternBase, IndexPatternFieldBase } from '@kbn/es-query'; import { AutocompleteStart } from '../../../../../../../src/plugins/data/public'; -import { IFieldType, IIndexPattern } from '../../../../../../../src/plugins/data/common'; import { HttpStart } from '../../../../../../../src/core/public'; import { getEmptyValue } from '../../../common/empty_value'; @@ -52,15 +52,15 @@ export interface EntryItemProps { autocompleteService: AutocompleteStart; entry: FormattedBuilderEntry; httpService: HttpStart; - indexPattern: IIndexPattern; + indexPattern: IndexPatternBase; showLabel: boolean; osTypes?: OsTypeArray; listType: ExceptionListType; listTypeSpecificIndexPatternFilter?: ( - pattern: IIndexPattern, + pattern: IndexPatternBase, type: ExceptionListType, osTypes?: OsTypeArray - ) => IIndexPattern; + ) => IndexPatternBase; onChange: (arg: BuilderEntry, i: number) => void; onlyShowListOperators?: boolean; setErrorsExist: (arg: boolean) => void; @@ -90,7 +90,7 @@ export const BuilderEntryItem: React.FC = ({ ); const handleFieldChange = useCallback( - ([newField]: IFieldType[]): void => { + ([newField]: IndexPatternFieldBase[]): void => { const { updatedEntry, index } = getEntryOnFieldChange(entry, newField); onChange(updatedEntry, index); }, diff --git a/x-pack/plugins/lists/public/exceptions/components/builder/exception_item_renderer.tsx b/x-pack/plugins/lists/public/exceptions/components/builder/exception_item_renderer.tsx index eee5b8b1e992d..04d7606bda23e 100644 --- a/x-pack/plugins/lists/public/exceptions/components/builder/exception_item_renderer.tsx +++ b/x-pack/plugins/lists/public/exceptions/components/builder/exception_item_renderer.tsx @@ -18,8 +18,7 @@ import { getFormattedBuilderEntries, getUpdatedEntriesOnDelete, } from '@kbn/securitysolution-list-utils'; - -import { IIndexPattern } from '../../../../../../../src/plugins/data/common'; +import { IndexPatternBase } from '@kbn/es-query'; import { BuilderAndBadgeComponent } from './and_badge'; import { BuilderEntryDeleteButtonComponent } from './entry_delete_button'; @@ -47,15 +46,15 @@ interface BuilderExceptionListItemProps { exceptionItem: ExceptionsBuilderExceptionItem; exceptionItemIndex: number; osTypes?: OsTypeArray; - indexPattern: IIndexPattern; + indexPattern: IndexPatternBase; andLogicIncluded: boolean; isOnlyItem: boolean; listType: ExceptionListType; listTypeSpecificIndexPatternFilter?: ( - pattern: IIndexPattern, + pattern: IndexPatternBase, type: ExceptionListType, osTypes?: OsTypeArray - ) => IIndexPattern; + ) => IndexPatternBase; onDeleteExceptionItem: (item: ExceptionsBuilderExceptionItem, index: number) => void; onChangeExceptionItem: (item: ExceptionsBuilderExceptionItem, index: number) => void; setErrorsExist: (arg: boolean) => void; diff --git a/x-pack/plugins/lists/public/exceptions/components/builder/exception_items_renderer.tsx b/x-pack/plugins/lists/public/exceptions/components/builder/exception_items_renderer.tsx index 1b68ef07657a8..14c3fbda31e22 100644 --- a/x-pack/plugins/lists/public/exceptions/components/builder/exception_items_renderer.tsx +++ b/x-pack/plugins/lists/public/exceptions/components/builder/exception_items_renderer.tsx @@ -30,8 +30,9 @@ import { getDefaultNestedEmptyEntry, getNewExceptionItem, } from '@kbn/securitysolution-list-utils'; +import { IndexPatternBase } from '@kbn/es-query'; -import { AutocompleteStart, IIndexPattern } from '../../../../../../../src/plugins/data/public'; +import { AutocompleteStart } from '../../../../../../../src/plugins/data/public'; import { AndOrBadge } from '../and_or_badge'; import { BuilderExceptionListItemComponent } from './exception_item_renderer'; @@ -75,7 +76,7 @@ export interface ExceptionBuilderProps { exceptionListItems: ExceptionsBuilderExceptionItem[]; httpService: HttpStart; osTypes?: OsTypeArray; - indexPatterns: IIndexPattern; + indexPatterns: IndexPatternBase; isAndDisabled: boolean; isNestedDisabled: boolean; isOrDisabled: boolean; @@ -83,9 +84,9 @@ export interface ExceptionBuilderProps { listNamespaceType: NamespaceType; listType: ExceptionListType; listTypeSpecificIndexPatternFilter?: ( - pattern: IIndexPattern, + pattern: IndexPatternBase, type: ExceptionListType - ) => IIndexPattern; + ) => IndexPatternBase; onChange: (arg: OnChangeProps) => void; ruleName: string; isDisabled?: boolean; diff --git a/x-pack/plugins/lists/public/exceptions/components/builder/helpers.test.ts b/x-pack/plugins/lists/public/exceptions/components/builder/helpers.test.ts index afeac2d1bf4de..8592408dde56e 100644 --- a/x-pack/plugins/lists/public/exceptions/components/builder/helpers.test.ts +++ b/x-pack/plugins/lists/public/exceptions/components/builder/helpers.test.ts @@ -52,6 +52,7 @@ import { isOneOfOperator, isOperator, } from '@kbn/securitysolution-list-utils'; +import { IndexPatternBase, IndexPatternFieldBase } from '@kbn/es-query'; import { ENTRIES_WITH_IDS } from '../../../../common/constants.mock'; import { getEntryExistsMock } from '../../../../common/schemas/types/entry_exists.mock'; @@ -60,7 +61,7 @@ import { fields, getField, } from '../../../../../../../src/plugins/data/common/index_patterns/fields/fields.mocks'; -import { IFieldType, IIndexPattern } from '../../../../../../../src/plugins/data/common'; +import { FieldSpec } from '../../../../../../../src/plugins/data/common'; import { getEntryNestedMock } from '../../../../common/schemas/types/entry_nested.mock'; import { getEntryMatchMock } from '../../../../common/schemas/types/entry_match.mock'; import { getEntryMatchAnyMock } from '../../../../common/schemas/types/entry_match_any.mock'; @@ -93,7 +94,7 @@ const getEntryMatchAnyWithIdMock = (): EntryMatchAny & { id: string } => ({ id: '123', }); -const getMockIndexPattern = (): IIndexPattern => ({ +const getMockIndexPattern = (): IndexPatternBase => ({ fields, id: '1234', title: 'logstash-*', @@ -131,7 +132,11 @@ const getMockNestedBuilderEntry = (): FormattedBuilderEntry => ({ const getMockNestedParentBuilderEntry = (): FormattedBuilderEntry => ({ correspondingKeywordField: undefined, entryIndex: 0, - field: { ...getField('nestedField.child'), esTypes: ['nested'], name: 'nestedField' }, + field: { + ...getField('nestedField.child'), + esTypes: ['nested'], + name: 'nestedField', + } as FieldSpec, id: '123', nested: 'parent', operator: isOperator, @@ -163,10 +168,13 @@ const mockEndpointFields = [ }, ]; -export const getEndpointField = (name: string): IFieldType => - mockEndpointFields.find((field) => field.name === name) as IFieldType; +export const getEndpointField = (name: string): IndexPatternFieldBase => + mockEndpointFields.find((field) => field.name === name) as IndexPatternFieldBase; -const filterIndexPatterns = (patterns: IIndexPattern, type: ExceptionListType): IIndexPattern => { +const filterIndexPatterns = ( + patterns: IndexPatternBase, + type: ExceptionListType +): IndexPatternBase => { return type === 'endpoint' ? { ...patterns, @@ -181,10 +189,10 @@ describe('Exception builder helpers', () => { describe('#getFilteredIndexPatterns', () => { describe('list type detections', () => { test('it returns nested fields that match parent value when "item.nested" is "child"', () => { - const payloadIndexPattern: IIndexPattern = getMockIndexPattern(); + const payloadIndexPattern = getMockIndexPattern(); const payloadItem: FormattedBuilderEntry = getMockNestedBuilderEntry(); const output = getFilteredIndexPatterns(payloadIndexPattern, payloadItem, 'detection'); - const expected: IIndexPattern = { + const expected: IndexPatternBase = { fields: [{ ...getField('nestedField.child'), name: 'child' }], id: '1234', title: 'logstash-*', @@ -193,10 +201,10 @@ describe('Exception builder helpers', () => { }); test('it returns only parent nested field when "item.nested" is "parent" and nested parent field is not undefined', () => { - const payloadIndexPattern: IIndexPattern = getMockIndexPattern(); + const payloadIndexPattern = getMockIndexPattern(); const payloadItem: FormattedBuilderEntry = getMockNestedParentBuilderEntry(); const output = getFilteredIndexPatterns(payloadIndexPattern, payloadItem, 'detection'); - const expected: IIndexPattern = { + const expected: IndexPatternBase & { fields: Array> } = { fields: [{ ...getField('nestedField.child'), esTypes: ['nested'], name: 'nestedField' }], id: '1234', title: 'logstash-*', @@ -205,13 +213,13 @@ describe('Exception builder helpers', () => { }); test('it returns only nested fields when "item.nested" is "parent" and nested parent field is undefined', () => { - const payloadIndexPattern: IIndexPattern = getMockIndexPattern(); + const payloadIndexPattern = getMockIndexPattern(); const payloadItem: FormattedBuilderEntry = { ...getMockNestedParentBuilderEntry(), field: undefined, }; const output = getFilteredIndexPatterns(payloadIndexPattern, payloadItem, 'detection'); - const expected: IIndexPattern = { + const expected: IndexPatternBase = { fields: [ { ...getField('nestedField.child') }, { ...getField('nestedField.nestedChild.doublyNestedChild') }, @@ -223,10 +231,10 @@ describe('Exception builder helpers', () => { }); test('it returns all fields unfiletered if "item.nested" is not "child" or "parent"', () => { - const payloadIndexPattern: IIndexPattern = getMockIndexPattern(); + const payloadIndexPattern = getMockIndexPattern(); const payloadItem: FormattedBuilderEntry = getMockBuilderEntry(); const output = getFilteredIndexPatterns(payloadIndexPattern, payloadItem, 'detection'); - const expected: IIndexPattern = { + const expected: IndexPatternBase = { fields: [...fields], id: '1234', title: 'logstash-*', @@ -236,7 +244,7 @@ describe('Exception builder helpers', () => { }); describe('list type endpoint', () => { - let payloadIndexPattern: IIndexPattern = getMockIndexPattern(); + let payloadIndexPattern = getMockIndexPattern(); beforeAll(() => { payloadIndexPattern = { @@ -264,7 +272,7 @@ describe('Exception builder helpers', () => { value: 'some value', }; const output = getFilteredIndexPatterns(payloadIndexPattern, payloadItem, 'endpoint'); - const expected: IIndexPattern = { + const expected: IndexPatternBase = { fields: [{ ...getEndpointField('file.Ext.code_signature.status'), name: 'status' }], id: '1234', title: 'logstash-*', @@ -273,33 +281,35 @@ describe('Exception builder helpers', () => { }); test('it returns only parent nested field when "item.nested" is "parent" and nested parent field is not undefined', () => { + const field: FieldSpec = { + ...getEndpointField('file.Ext.code_signature.status'), + esTypes: ['nested'], + name: 'file.Ext.code_signature', + } as FieldSpec; const payloadItem: FormattedBuilderEntry = { ...getMockNestedParentBuilderEntry(), - field: { - ...getEndpointField('file.Ext.code_signature.status'), - esTypes: ['nested'], - name: 'file.Ext.code_signature', - }, + field, }; const output = getFilteredIndexPatterns(payloadIndexPattern, payloadItem, 'endpoint'); - const expected: IIndexPattern = { - fields: [ - { - aggregatable: false, - count: 0, - esTypes: ['nested'], - name: 'file.Ext.code_signature', - readFromDocValues: false, - scripted: false, - searchable: true, - subType: { - nested: { - path: 'file.Ext.code_signature', - }, + const fieldsExpected: FieldSpec[] = [ + { + aggregatable: false, + count: 0, + esTypes: ['nested'], + name: 'file.Ext.code_signature', + readFromDocValues: false, + scripted: false, + searchable: true, + subType: { + nested: { + path: 'file.Ext.code_signature', }, - type: 'string', }, - ], + type: 'string', + }, + ]; + const expected: IndexPatternBase = { + fields: fieldsExpected, id: '1234', title: 'logstash-*', }; @@ -317,7 +327,7 @@ describe('Exception builder helpers', () => { 'endpoint', filterIndexPatterns ); - const expected: IIndexPattern = { + const expected: IndexPatternBase = { fields: [getEndpointField('file.Ext.code_signature.status')], id: '1234', title: 'logstash-*', @@ -333,30 +343,31 @@ describe('Exception builder helpers', () => { 'endpoint', filterIndexPatterns ); - const expected: IIndexPattern = { - fields: [ - { - aggregatable: false, - count: 0, - esTypes: ['keyword'], - name: 'file.path.caseless', - readFromDocValues: false, - scripted: false, - searchable: true, - type: 'string', - }, - { - aggregatable: false, - count: 0, - esTypes: ['text'], - name: 'file.Ext.code_signature.status', - readFromDocValues: false, - scripted: false, - searchable: true, - subType: { nested: { path: 'file.Ext.code_signature' } }, - type: 'string', - }, - ], + const fieldsExpected: FieldSpec[] = [ + { + aggregatable: false, + count: 0, + esTypes: ['keyword'], + name: 'file.path.caseless', + readFromDocValues: false, + scripted: false, + searchable: true, + type: 'string', + }, + { + aggregatable: false, + count: 0, + esTypes: ['text'], + name: 'file.Ext.code_signature.status', + readFromDocValues: false, + scripted: false, + searchable: true, + subType: { nested: { path: 'file.Ext.code_signature' } }, + type: 'string', + }, + ]; + const expected: IndexPatternBase = { + fields: fieldsExpected, id: '1234', title: 'logstash-*', }; @@ -626,7 +637,7 @@ describe('Exception builder helpers', () => { describe('#getEntryOnFieldChange', () => { test('it returns nested entry with single new subentry when "item.nested" is "parent"', () => { const payloadItem: FormattedBuilderEntry = getMockNestedParentBuilderEntry(); - const payloadIFieldType: IFieldType = getField('nestedField.child'); + const payloadIFieldType = getField('nestedField.child'); const output = getEntryOnFieldChange(payloadItem, payloadIFieldType); const expected: { updatedEntry: BuilderEntry & { id?: string }; index: number } = { index: 0, @@ -663,7 +674,7 @@ describe('Exception builder helpers', () => { parentIndex: 0, }, }; - const payloadIFieldType: IFieldType = getField('nestedField.child'); + const payloadIFieldType = getField('nestedField.child'); const output = getEntryOnFieldChange(payloadItem, payloadIFieldType); const expected: { updatedEntry: BuilderEntry & { id?: string }; index: number } = { index: 0, @@ -688,7 +699,7 @@ describe('Exception builder helpers', () => { test('it returns field of type "match" with updated field if not a nested entry', () => { const payloadItem: FormattedBuilderEntry = getMockBuilderEntry(); - const payloadIFieldType: IFieldType = getField('ip'); + const payloadIFieldType = getField('ip'); const output = getEntryOnFieldChange(payloadItem, payloadIFieldType); const expected: { updatedEntry: BuilderEntry & { id?: string }; index: number } = { index: 0, @@ -1023,7 +1034,7 @@ describe('Exception builder helpers', () => { describe('#getFormattedBuilderEntries', () => { test('it returns formatted entry with field undefined if it unable to find a matching index pattern field', () => { - const payloadIndexPattern: IIndexPattern = getMockIndexPattern(); + const payloadIndexPattern = getMockIndexPattern(); const payloadItems: BuilderEntry[] = [getEntryMatchWithIdMock()]; const output = getFormattedBuilderEntries(payloadIndexPattern, payloadItems); const expected: FormattedBuilderEntry[] = [ @@ -1042,26 +1053,37 @@ describe('Exception builder helpers', () => { }); test('it returns formatted entries when no nested entries exist', () => { - const payloadIndexPattern: IIndexPattern = getMockIndexPattern(); + const payloadIndexPattern = getMockIndexPattern(); const payloadItems: BuilderEntry[] = [ { ...getEntryMatchWithIdMock(), field: 'ip', value: 'some ip' }, { ...getEntryMatchAnyWithIdMock(), field: 'extension', value: ['some extension'] }, ]; const output = getFormattedBuilderEntries(payloadIndexPattern, payloadItems); + const field1: FieldSpec = { + aggregatable: true, + count: 0, + esTypes: ['ip'], + name: 'ip', + readFromDocValues: true, + scripted: false, + searchable: true, + type: 'ip', + }; + const field2: FieldSpec = { + aggregatable: true, + count: 0, + esTypes: ['keyword'], + name: 'extension', + readFromDocValues: true, + scripted: false, + searchable: true, + type: 'string', + }; const expected: FormattedBuilderEntry[] = [ { correspondingKeywordField: undefined, entryIndex: 0, - field: { - aggregatable: true, - count: 0, - esTypes: ['ip'], - name: 'ip', - readFromDocValues: true, - scripted: false, - searchable: true, - type: 'ip', - }, + field: field1, id: '123', nested: undefined, operator: isOperator, @@ -1071,16 +1093,7 @@ describe('Exception builder helpers', () => { { correspondingKeywordField: undefined, entryIndex: 1, - field: { - aggregatable: true, - count: 0, - esTypes: ['keyword'], - name: 'extension', - readFromDocValues: true, - scripted: false, - searchable: true, - type: 'string', - }, + field: field2, id: '123', nested: undefined, operator: isOneOfOperator, @@ -1092,7 +1105,7 @@ describe('Exception builder helpers', () => { }); test('it returns formatted entries when nested entries exist', () => { - const payloadIndexPattern: IIndexPattern = getMockIndexPattern(); + const payloadIndexPattern = getMockIndexPattern(); const payloadParent: EntryNested = { ...getEntryNestedWithIdMock(), entries: [{ ...getEntryMatchWithIdMock(), field: 'child' }], @@ -1104,20 +1117,43 @@ describe('Exception builder helpers', () => { ]; const output = getFormattedBuilderEntries(payloadIndexPattern, payloadItems); + const field1: FieldSpec = { + aggregatable: true, + count: 0, + esTypes: ['ip'], + name: 'ip', + readFromDocValues: true, + scripted: false, + searchable: true, + type: 'ip', + }; + const field2: FieldSpec = { + aggregatable: false, + esTypes: ['nested'], + name: 'nestedField', + searchable: false, + type: 'string', + }; + const field3: FieldSpec = { + aggregatable: false, + count: 0, + esTypes: ['text'], + name: 'child', + readFromDocValues: false, + scripted: false, + searchable: true, + subType: { + nested: { + path: 'nestedField', + }, + }, + type: 'string', + }; const expected: FormattedBuilderEntry[] = [ { correspondingKeywordField: undefined, entryIndex: 0, - field: { - aggregatable: true, - count: 0, - esTypes: ['ip'], - name: 'ip', - readFromDocValues: true, - scripted: false, - searchable: true, - type: 'ip', - }, + field: field1, id: '123', nested: undefined, operator: isOperator, @@ -1127,13 +1163,7 @@ describe('Exception builder helpers', () => { { correspondingKeywordField: undefined, entryIndex: 1, - field: { - aggregatable: false, - esTypes: ['nested'], - name: 'nestedField', - searchable: false, - type: 'string', - }, + field: field2, id: '123', nested: 'parent', operator: isOperator, @@ -1143,21 +1173,7 @@ describe('Exception builder helpers', () => { { correspondingKeywordField: undefined, entryIndex: 0, - field: { - aggregatable: false, - count: 0, - esTypes: ['text'], - name: 'child', - readFromDocValues: false, - scripted: false, - searchable: true, - subType: { - nested: { - path: 'nestedField', - }, - }, - type: 'string', - }, + field: field3, id: '123', nested: 'child', operator: isOperator, @@ -1248,7 +1264,7 @@ describe('Exception builder helpers', () => { describe('#getFormattedBuilderEntry', () => { test('it returns entry with a value for "correspondingKeywordField" when "item.field" is of type "text" and matching keyword field exists', () => { - const payloadIndexPattern: IIndexPattern = { + const payloadIndexPattern: IndexPatternBase = { ...getMockIndexPattern(), fields: [ ...fields, @@ -1276,19 +1292,20 @@ describe('Exception builder helpers', () => { undefined, undefined ); + const field: FieldSpec = { + aggregatable: false, + count: 0, + esTypes: ['text'], + name: 'machine.os.raw.text', + readFromDocValues: true, + scripted: false, + searchable: false, + type: 'string', + }; const expected: FormattedBuilderEntry = { correspondingKeywordField: getField('machine.os.raw'), entryIndex: 0, - field: { - aggregatable: false, - count: 0, - esTypes: ['text'], - name: 'machine.os.raw.text', - readFromDocValues: true, - scripted: false, - searchable: false, - type: 'string', - }, + field, id: '123', nested: undefined, operator: isOperator, @@ -1299,7 +1316,7 @@ describe('Exception builder helpers', () => { }); test('it returns "FormattedBuilderEntry" with value "nested" of "child" when "parent" and "parentIndex" are defined', () => { - const payloadIndexPattern: IIndexPattern = getMockIndexPattern(); + const payloadIndexPattern = getMockIndexPattern(); const payloadItem: BuilderEntry = { ...getEntryMatchWithIdMock(), field: 'child' }; const payloadParent: EntryNested = { ...getEntryNestedWithIdMock(), @@ -1313,24 +1330,25 @@ describe('Exception builder helpers', () => { payloadParent, 1 ); + const field: FieldSpec = { + aggregatable: false, + count: 0, + esTypes: ['text'], + name: 'child', + readFromDocValues: false, + scripted: false, + searchable: true, + subType: { + nested: { + path: 'nestedField', + }, + }, + type: 'string', + }; const expected: FormattedBuilderEntry = { correspondingKeywordField: undefined, entryIndex: 0, - field: { - aggregatable: false, - count: 0, - esTypes: ['text'], - name: 'child', - readFromDocValues: false, - scripted: false, - searchable: true, - subType: { - nested: { - path: 'nestedField', - }, - }, - type: 'string', - }, + field, id: '123', nested: 'child', operator: isOperator, @@ -1349,7 +1367,7 @@ describe('Exception builder helpers', () => { }); test('it returns non nested "FormattedBuilderEntry" when "parent" and "parentIndex" are not defined', () => { - const payloadIndexPattern: IIndexPattern = getMockIndexPattern(); + const payloadIndexPattern = getMockIndexPattern(); const payloadItem: BuilderEntry = { ...getEntryMatchWithIdMock(), field: 'ip', @@ -1362,19 +1380,20 @@ describe('Exception builder helpers', () => { undefined, undefined ); + const field: FieldSpec = { + aggregatable: true, + count: 0, + esTypes: ['ip'], + name: 'ip', + readFromDocValues: true, + scripted: false, + searchable: true, + type: 'ip', + }; const expected: FormattedBuilderEntry = { correspondingKeywordField: undefined, entryIndex: 0, - field: { - aggregatable: true, - count: 0, - esTypes: ['ip'], - name: 'ip', - readFromDocValues: true, - scripted: false, - searchable: true, - type: 'ip', - }, + field, id: '123', nested: undefined, operator: isOperator, diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/helpers.test.tsx b/x-pack/plugins/security_solution/public/common/components/exceptions/helpers.test.tsx index af8058e25adc6..5347ee875181b 100644 --- a/x-pack/plugins/security_solution/public/common/components/exceptions/helpers.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/exceptions/helpers.test.tsx @@ -41,14 +41,14 @@ import { getEntryMatchMock } from '../../../../../lists/common/schemas/types/ent import { getCommentsArrayMock } from '../../../../../lists/common/schemas/types/comment.mock'; import { fields } from '../../../../../../../src/plugins/data/common/index_patterns/fields/fields.mocks'; import { ENTRIES, OLD_DATE_RELATIVE_TO_DATE_NOW } from '../../../../../lists/common/constants.mock'; -import { IFieldType, IIndexPattern } from 'src/plugins/data/common'; import { CodeSignature } from '../../../../common/ecs/file'; +import { IndexPatternBase } from '@kbn/es-query'; jest.mock('uuid', () => ({ v4: jest.fn().mockReturnValue('123'), })); -const getMockIndexPattern = (): IIndexPattern => ({ +const getMockIndexPattern = (): IndexPatternBase => ({ fields, id: '1234', title: 'logstash-*', @@ -91,9 +91,6 @@ const mockLinuxEndpointFields = [ }, ]; -export const getEndpointField = (name: string) => - mockEndpointFields.find((field) => field.name === name) as IFieldType; - describe('Exception helpers', () => { beforeEach(() => { moment.tz.setDefault('UTC'); @@ -367,7 +364,7 @@ describe('Exception helpers', () => { name: 'nested.field', }, ], - } as IIndexPattern; + } as IndexPatternBase; test('it should return false with an empty array', () => { const payload: ExceptionListItemSchema[] = []; diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/helpers.tsx b/x-pack/plugins/security_solution/public/common/components/exceptions/helpers.tsx index f8260062f6974..613d295545461 100644 --- a/x-pack/plugins/security_solution/public/common/components/exceptions/helpers.tsx +++ b/x-pack/plugins/security_solution/public/common/components/exceptions/helpers.tsx @@ -33,10 +33,10 @@ import { addIdToEntries, ExceptionsBuilderExceptionItem, } from '@kbn/securitysolution-list-utils'; +import { IndexPatternBase } from '@kbn/es-query'; import * as i18n from './translations'; import { AlertData, Flattened } from './types'; -import { IIndexPattern } from '../../../../../../../src/plugins/data/common'; import { Ecs } from '../../../../common/ecs'; import { CodeSignature } from '../../../../common/ecs/file'; import { WithCopyToClipboard } from '../../lib/clipboard/with_copy_to_clipboard'; @@ -46,10 +46,10 @@ import exceptionableEndpointFields from './exceptionable_endpoint_fields.json'; import exceptionableEndpointEventFields from './exceptionable_endpoint_event_fields.json'; export const filterIndexPatterns = ( - patterns: IIndexPattern, + patterns: IndexPatternBase, type: ExceptionListType, osTypes?: OsTypeArray -): IIndexPattern => { +): IndexPatternBase => { switch (type) { case 'endpoint': const osFilterForEndpoint: (name: string) => boolean = osTypes?.includes('linux') @@ -634,7 +634,7 @@ export const getPrepopulatedMemoryShellcodeException = ({ */ export const entryHasNonEcsType = ( exceptionItems: Array, - indexPatterns: IIndexPattern + indexPatterns: IndexPatternBase ): boolean => { const doesFieldNameExist = (exceptionEntry: Entry): boolean => { return indexPatterns.fields.some(({ name }) => name === exceptionEntry.field); diff --git a/x-pack/plugins/security_solution/public/common/components/threat_match/entry_item.tsx b/x-pack/plugins/security_solution/public/common/components/threat_match/entry_item.tsx index 49bd7824d6100..99c5b37046505 100644 --- a/x-pack/plugins/security_solution/public/common/components/threat_match/entry_item.tsx +++ b/x-pack/plugins/security_solution/public/common/components/threat_match/entry_item.tsx @@ -10,7 +10,8 @@ import { EuiFormRow, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import styled from 'styled-components'; import { FieldComponent } from '@kbn/securitysolution-autocomplete'; -import { IFieldType, IndexPattern } from '../../../../../../../src/plugins/data/common'; +import { IndexPatternFieldBase } from '@kbn/es-query'; +import { IndexPattern } from '../../../../../../../src/plugins/data/common'; import { FormattedEntry, Entry } from './types'; import * as i18n from './translations'; import { getEntryOnFieldChange, getEntryOnThreatFieldChange } from './helpers'; @@ -40,7 +41,7 @@ export const EntryItem: React.FC = ({ onChange, }): JSX.Element => { const handleFieldChange = useCallback( - ([newField]: IFieldType[]): void => { + ([newField]: IndexPatternFieldBase[]): void => { const { updatedEntry, index } = getEntryOnFieldChange(entry, newField); onChange(updatedEntry, index); }, @@ -48,7 +49,7 @@ export const EntryItem: React.FC = ({ ); const handleThreatFieldChange = useCallback( - ([newField]: IFieldType[]): void => { + ([newField]: IndexPatternFieldBase[]): void => { const { updatedEntry, index } = getEntryOnThreatFieldChange(entry, newField); onChange(updatedEntry, index); }, diff --git a/x-pack/plugins/security_solution/public/common/components/threat_match/helpers.test.tsx b/x-pack/plugins/security_solution/public/common/components/threat_match/helpers.test.tsx index d3e1dea2dd93e..24a0f94e05883 100644 --- a/x-pack/plugins/security_solution/public/common/components/threat_match/helpers.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/threat_match/helpers.test.tsx @@ -10,7 +10,7 @@ import { getField, } from '../../../../../../../src/plugins/data/common/index_patterns/fields/fields.mocks'; import { Entry, EmptyEntry, ThreatMapEntries, FormattedEntry } from './types'; -import { IndexPattern } from '../../../../../../../src/plugins/data/common'; +import { FieldSpec, IndexPattern } from '../../../../../../../src/plugins/data/common'; import moment from 'moment-timezone'; import { @@ -88,7 +88,7 @@ describe('Helpers', () => { searchable: false, aggregatable: false, readFromDocValues: true, - }, + } as FieldSpec, type: 'mapping', value: undefined, }; @@ -130,7 +130,7 @@ describe('Helpers', () => { searchable: true, aggregatable: true, readFromDocValues: false, - }, + } as FieldSpec, value: undefined, type: 'mapping', }, @@ -156,7 +156,7 @@ describe('Helpers', () => { searchable: true, aggregatable: true, readFromDocValues: false, - }, + } as FieldSpec, value: { name: 'machine.os', type: 'string', @@ -166,7 +166,7 @@ describe('Helpers', () => { searchable: true, aggregatable: true, readFromDocValues: false, - }, + } as FieldSpec, type: 'mapping', }, ]; @@ -192,7 +192,7 @@ describe('Helpers', () => { searchable: true, aggregatable: true, readFromDocValues: false, - }, + } as FieldSpec, type: 'mapping', value: { name: 'machine.os', @@ -203,7 +203,7 @@ describe('Helpers', () => { searchable: true, aggregatable: true, readFromDocValues: false, - }, + } as FieldSpec, entryIndex: 0, }, { diff --git a/x-pack/plugins/security_solution/public/common/components/threat_match/helpers.tsx b/x-pack/plugins/security_solution/public/common/components/threat_match/helpers.tsx index 89ace117f1301..3f8e5b1602db8 100644 --- a/x-pack/plugins/security_solution/public/common/components/threat_match/helpers.tsx +++ b/x-pack/plugins/security_solution/public/common/components/threat_match/helpers.tsx @@ -10,7 +10,8 @@ import { i18n } from '@kbn/i18n'; import { addIdToItem } from '@kbn/securitysolution-utils'; import { ThreatMap, threatMap, ThreatMapping } from '@kbn/securitysolution-io-ts-alerting-types'; -import { IndexPattern, IFieldType } from '../../../../../../../src/plugins/data/common'; +import { IndexPatternFieldBase } from '@kbn/es-query'; +import { IndexPattern } from '../../../../../../../src/plugins/data/common'; import { Entry, FormattedEntry, ThreatMapEntries, EmptyEntry } from './types'; import { ValidationFunc } from '../../../../../../../src/plugins/es_ui_shared/static/forms/hook_form_lib'; import { ERROR_CODE } from '../../../../../../../src/plugins/es_ui_shared/static/forms/helpers/field_validators/types'; @@ -90,7 +91,7 @@ export const getUpdatedEntriesOnDelete = ( */ export const getEntryOnFieldChange = ( item: FormattedEntry, - newField: IFieldType + newField: IndexPatternFieldBase ): { updatedEntry: Entry; index: number } => { const { entryIndex } = item; return { @@ -113,7 +114,7 @@ export const getEntryOnFieldChange = ( */ export const getEntryOnThreatFieldChange = ( item: FormattedEntry, - newField: IFieldType + newField: IndexPatternFieldBase ): { updatedEntry: Entry; index: number } => { const { entryIndex } = item; return { diff --git a/x-pack/plugins/security_solution/public/common/components/threat_match/types.ts b/x-pack/plugins/security_solution/public/common/components/threat_match/types.ts index 3d4fa19ac5794..3d3a18b425e01 100644 --- a/x-pack/plugins/security_solution/public/common/components/threat_match/types.ts +++ b/x-pack/plugins/security_solution/public/common/components/threat_match/types.ts @@ -5,14 +5,14 @@ * 2.0. */ +import { IndexPatternFieldBase } from '@kbn/es-query'; import { ThreatMap, ThreatMapEntry } from '@kbn/securitysolution-io-ts-alerting-types'; -import { IFieldType } from '../../../../../../../src/plugins/data/common'; export interface FormattedEntry { id: string; - field: IFieldType | undefined; + field: IndexPatternFieldBase | undefined; type: 'mapping'; - value: IFieldType | undefined; + value: IndexPatternFieldBase | undefined; entryIndex: number; } diff --git a/x-pack/plugins/security_solution/public/detections/components/rules/autocomplete_field/index.tsx b/x-pack/plugins/security_solution/public/detections/components/rules/autocomplete_field/index.tsx index 16caed9086e61..22fabcd15b194 100644 --- a/x-pack/plugins/security_solution/public/detections/components/rules/autocomplete_field/index.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/rules/autocomplete_field/index.tsx @@ -8,15 +8,14 @@ import React, { useCallback, useMemo } from 'react'; import { EuiFormRow } from '@elastic/eui'; import { FieldComponent } from '@kbn/securitysolution-autocomplete'; +import { IndexPatternBase, IndexPatternFieldBase } from '@kbn/es-query'; import { FieldHook } from '../../../../../../../../src/plugins/es_ui_shared/static/forms/hook_form_lib'; -import { IFieldType } from '../../../../../../../../src/plugins/data/common/index_patterns/fields'; -import { IIndexPattern } from '../../../../../../../../src/plugins/data/common'; interface AutocompleteFieldProps { dataTestSubj: string; field: FieldHook; idAria: string; - indices: IIndexPattern; + indices: IndexPatternBase; isDisabled: boolean; fieldType: string; placeholder?: string; @@ -32,7 +31,7 @@ export const AutocompleteField = ({ placeholder, }: AutocompleteFieldProps) => { const handleFieldChange = useCallback( - ([newField]: IFieldType[]): void => { + ([newField]: IndexPatternFieldBase[]): void => { // TODO: Update onChange type in FieldComponent as newField can be undefined field.setValue(newField?.name ?? ''); }, diff --git a/x-pack/plugins/security_solution/public/detections/components/rules/risk_score_mapping/index.tsx b/x-pack/plugins/security_solution/public/detections/components/rules/risk_score_mapping/index.tsx index eef18a502c270..e9cbcb6c38268 100644 --- a/x-pack/plugins/security_solution/public/detections/components/rules/risk_score_mapping/index.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/rules/risk_score_mapping/index.tsx @@ -21,11 +21,10 @@ import styled from 'styled-components'; import { noop } from 'lodash/fp'; import { RiskScoreMapping } from '@kbn/securitysolution-io-ts-alerting-types'; import { FieldComponent } from '@kbn/securitysolution-autocomplete'; +import { IndexPatternBase, IndexPatternFieldBase } from '@kbn/es-query'; import * as i18n from './translations'; import { FieldHook } from '../../../../../../../../src/plugins/es_ui_shared/static/forms/hook_form_lib'; import { AboutStepRiskScore } from '../../../pages/detection_engine/rules/types'; -import { IFieldType } from '../../../../../../../../src/plugins/data/common/index_patterns/fields'; -import { IIndexPattern } from '../../../../../../../../src/plugins/data/common/index_patterns'; const NestedContent = styled.div` margin-left: 24px; @@ -47,7 +46,7 @@ interface RiskScoreFieldProps { dataTestSubj: string; field: FieldHook; idAria: string; - indices: IIndexPattern; + indices: IndexPatternBase; isDisabled: boolean; placeholder?: string; } @@ -79,7 +78,7 @@ export const RiskScoreField = ({ ); const handleRiskScoreMappingChange = useCallback( - ([newField]: IFieldType[]): void => { + ([newField]: IndexPatternFieldBase[]): void => { setValue({ value, isMappingChecked, @@ -232,14 +231,17 @@ export const RiskScoreField = ({ }; /** - * Looks for field metadata (IFieldType) in existing index pattern. - * If specified field doesn't exist, returns a stub IFieldType created based on the mapping -- + * Looks for field metadata (IndexPatternFieldBase) in existing index pattern. + * If specified field doesn't exist, returns a stub IndexPatternFieldBase created based on the mapping -- * because the field might not have been indexed yet, but we still need to display the mapping. * * @param mapping Mapping of a specified field name to risk score. * @param pattern Existing index pattern. */ -const getFieldTypeByMapping = (mapping: RiskScoreMapping, pattern: IIndexPattern): IFieldType => { +const getFieldTypeByMapping = ( + mapping: RiskScoreMapping, + pattern: IndexPatternBase +): IndexPatternFieldBase => { const field = mapping?.[0]?.field ?? ''; const [knownFieldType] = pattern.fields.filter(({ name }) => field != null && field === name); return knownFieldType ?? { name: field, type: 'number' }; diff --git a/x-pack/plugins/security_solution/public/detections/components/rules/severity_mapping/index.tsx b/x-pack/plugins/security_solution/public/detections/components/rules/severity_mapping/index.tsx index d4fbdc31fbcae..4eca6f32d0c1f 100644 --- a/x-pack/plugins/security_solution/public/detections/components/rules/severity_mapping/index.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/rules/severity_mapping/index.tsx @@ -29,14 +29,11 @@ import { AutocompleteFieldMatchComponent, } from '@kbn/securitysolution-autocomplete'; +import { IndexPatternBase, IndexPatternFieldBase } from '@kbn/es-query'; import * as i18n from './translations'; import { FieldHook } from '../../../../../../../../src/plugins/es_ui_shared/static/forms/hook_form_lib'; import { SeverityOptionItem } from '../step_about_rule/data'; import { AboutStepSeverity } from '../../../pages/detection_engine/rules/types'; -import { - IFieldType, - IIndexPattern, -} from '../../../../../../../../src/plugins/data/common/index_patterns'; import { useKibana } from '../../../../common/lib/kibana'; const NestedContent = styled.div` @@ -59,7 +56,7 @@ interface SeverityFieldProps { dataTestSubj: string; field: FieldHook; idAria: string; - indices: IIndexPattern; + indices: IndexPatternBase; isDisabled: boolean; options: SeverityOptionItem[]; } @@ -88,7 +85,7 @@ export const SeverityField = ({ ); const handleFieldChange = useCallback( - (index: number, severity: Severity, [newField]: IFieldType[]): void => { + (index: number, severity: Severity, [newField]: IndexPatternFieldBase[]): void => { const newMappingItems: SeverityMapping = [ { ...mapping[index], @@ -298,8 +295,8 @@ export const SeverityField = ({ }; /** - * Looks for field metadata (IFieldType) in existing index pattern. - * If specified field doesn't exist, returns a stub IFieldType created based on the mapping -- + * Looks for field metadata (IndexPatternFieldBase) in existing index pattern. + * If specified field doesn't exist, returns a stub IndexPatternFieldBase created based on the mapping -- * because the field might not have been indexed yet, but we still need to display the mapping. * * @param mapping Mapping of a specified field name + value to a certain severity value. @@ -307,8 +304,8 @@ export const SeverityField = ({ */ const getFieldTypeByMapping = ( mapping: SeverityMappingItem, - pattern: IIndexPattern -): IFieldType => { + pattern: IndexPatternBase +): IndexPatternFieldBase => { const { field } = mapping; const [knownFieldType] = pattern.fields.filter(({ name }) => field === name); return knownFieldType ?? { name: field, type: 'string' };