diff --git a/x-pack/plugins/transform/public/app/sections/create_transform/components/advanced_runtime_mappings_editor/advanced_runtime_mappings_editor.tsx b/x-pack/plugins/transform/public/app/sections/create_transform/components/advanced_runtime_mappings_editor/advanced_runtime_mappings_editor.tsx index 087bae97e287e..23c4cfcefe8ef 100644 --- a/x-pack/plugins/transform/public/app/sections/create_transform/components/advanced_runtime_mappings_editor/advanced_runtime_mappings_editor.tsx +++ b/x-pack/plugins/transform/public/app/sections/create_transform/components/advanced_runtime_mappings_editor/advanced_runtime_mappings_editor.tsx @@ -13,6 +13,7 @@ import { EuiCodeEditor } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { StepDefineFormHook } from '../step_define'; +import { isRuntimeMappings } from '../step_define/common/types'; export const AdvancedRuntimeMappingsEditor: FC = memo( ({ @@ -43,8 +44,8 @@ export const AdvancedRuntimeMappingsEditor: FC]/g; @@ -77,7 +77,7 @@ export function getPivotDropdownOptions( // Support for runtime_mappings that are defined by queries let runtimeFields: Field[] = []; - if (isPopulatedObject(runtimeMappings)) { + if (isRuntimeMappings(runtimeMappings)) { runtimeFields = Object.keys(runtimeMappings).map((fieldName) => { const field = runtimeMappings[fieldName]; return { name: fieldName, type: getKibanaFieldTypeFromEsType(field.type) }; diff --git a/x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/common/types.test.ts b/x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/common/types.test.ts new file mode 100644 index 0000000000000..b4948fd65aa2d --- /dev/null +++ b/x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/common/types.test.ts @@ -0,0 +1,51 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { isRuntimeField, isRuntimeMappings } from './types'; + +describe('Transform: step_define type guards', () => { + it('isRuntimeField()', () => { + expect(isRuntimeField(1)).toBe(false); + expect(isRuntimeField(null)).toBe(false); + expect(isRuntimeField([])).toBe(false); + expect(isRuntimeField({})).toBe(false); + expect(isRuntimeField({ someAttribute: 'someValue' })).toBe(false); + expect(isRuntimeField({ type: 'wrong-type' })).toBe(false); + expect(isRuntimeField({ type: 'keyword', someAttribute: 'some value' })).toBe(false); + + expect(isRuntimeField({ type: 'keyword' })).toBe(true); + expect(isRuntimeField({ type: 'keyword', script: 'some script' })).toBe(true); + }); + + it('isRuntimeMappings()', () => { + expect(isRuntimeMappings(1)).toBe(false); + expect(isRuntimeMappings(null)).toBe(false); + expect(isRuntimeMappings([])).toBe(false); + expect(isRuntimeMappings({})).toBe(false); + expect(isRuntimeMappings({ someAttribute: 'someValue' })).toBe(false); + expect(isRuntimeMappings({ fieldName1: { type: 'keyword' }, fieldName2: 'someValue' })).toBe( + false + ); + expect( + isRuntimeMappings({ + fieldName1: { type: 'keyword' }, + fieldName2: { type: 'keyword', someAttribute: 'some value' }, + }) + ).toBe(false); + + expect(isRuntimeMappings({ fieldName: { type: 'keyword' } })).toBe(true); + expect( + isRuntimeMappings({ fieldName1: { type: 'keyword' }, fieldName2: { type: 'keyword' } }) + ).toBe(true); + expect( + isRuntimeMappings({ + fieldName1: { type: 'keyword' }, + fieldName2: { type: 'keyword', script: 'some script' }, + }) + ).toBe(true); + }); +}); diff --git a/x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/common/types.ts b/x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/common/types.ts index 6c9293a6d13cf..3fe78a4be84ea 100644 --- a/x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/common/types.ts +++ b/x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/common/types.ts @@ -24,6 +24,8 @@ import { } from '../../../../../../../common/types/transform'; import { LatestFunctionConfig } from '../../../../../../../common/api_schemas/transforms'; +import { isPopulatedObject } from '../../../../../common/utils/object_utils'; + export interface ErrorMessage { query: string; message: string; @@ -70,10 +72,25 @@ export interface StepDefineExposedState { isRuntimeMappingsEditorEnabled: boolean; } +export function isRuntimeField(arg: any): arg is RuntimeField { + return ( + isPopulatedObject(arg) && + ((Object.keys(arg).length === 1 && arg.hasOwnProperty('type')) || + (Object.keys(arg).length === 2 && + arg.hasOwnProperty('type') && + arg.hasOwnProperty('script'))) && + RUNTIME_FIELD_TYPES.includes(arg.type) + ); +} + +export function isRuntimeMappings(arg: any): arg is RuntimeMappings { + return isPopulatedObject(arg) && Object.values(arg).every((d) => isRuntimeField(d)); +} + export function isPivotPartialRequest(arg: any): arg is { pivot: PivotConfigDefinition } { - return typeof arg === 'object' && arg.hasOwnProperty('pivot'); + return isPopulatedObject(arg) && arg.hasOwnProperty('pivot'); } export function isLatestPartialRequest(arg: any): arg is { latest: LatestFunctionConfig } { - return typeof arg === 'object' && arg.hasOwnProperty('latest'); + return isPopulatedObject(arg) && arg.hasOwnProperty('latest'); }