diff --git a/src/plugins/data_views/server/routes/fields_for.test.ts b/src/plugins/data_views/server/routes/fields_for.test.ts new file mode 100644 index 00000000000000..57d1465f8a9ee8 --- /dev/null +++ b/src/plugins/data_views/server/routes/fields_for.test.ts @@ -0,0 +1,52 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { parseMetaFields } from './fields_for'; + +describe('_fields_for_wildcard', () => { + describe('parseMetaFields', () => { + it('should throw if receiving a string of comma-separated values', () => { + const value = '_source,_id'; + expect(() => parseMetaFields(value)).toThrowErrorMatchingInlineSnapshot( + `"metaFields should be an array of field names, a JSON-stringified array of field names, or a single field name"` + ); + }); + + it('should parse a stringified list of values', () => { + const value = JSON.stringify(['_source', '_id']); + const fields = parseMetaFields(value); + expect(fields).toMatchInlineSnapshot(` + Array [ + "_source", + "_id", + ] + `); + }); + + it('should wrap a single value in an array', () => { + const value = '_source'; + const fields = parseMetaFields(value); + expect(fields).toMatchInlineSnapshot(` + Array [ + "_source", + ] + `); + }); + + it('should return the array if already an array', () => { + const value = ['_source', '_id']; + const fields = parseMetaFields(value); + expect(fields).toMatchInlineSnapshot(` + Array [ + "_source", + "_id", + ] + `); + }); + }); +}); diff --git a/src/plugins/data_views/server/routes/fields_for.ts b/src/plugins/data_views/server/routes/fields_for.ts index 415077258966de..8719fd5ce75491 100644 --- a/src/plugins/data_views/server/routes/fields_for.ts +++ b/src/plugins/data_views/server/routes/fields_for.ts @@ -17,14 +17,24 @@ import { import { IndexPatternsFetcher } from '../fetcher'; import type { DataViewsServerPluginStart, DataViewsServerPluginStartDependencies } from '../types'; -const parseMetaFields = (metaFields: string | string[]) => { - let parsedFields: string[] = []; - if (typeof metaFields === 'string') { - parsedFields = JSON.parse(metaFields); - } else { - parsedFields = metaFields; +/** + * Accepts one of the following: + * 1. An array of field names + * 2. A JSON-stringified array of field names + * 3. A single field name (not comma-separated) + * @returns an array of field names + * @param metaFields + */ +export const parseMetaFields = (metaFields: string | string[]): string[] => { + if (Array.isArray(metaFields)) return metaFields; + try { + return JSON.parse(metaFields); + } catch (e) { + if (!metaFields.includes(',')) return [metaFields]; + throw new Error( + 'metaFields should be an array of field names, a JSON-stringified array of field names, or a single field name' + ); } - return parsedFields; }; const path = '/api/index_patterns/_fields_for_wildcard'; @@ -32,7 +42,7 @@ const path = '/api/index_patterns/_fields_for_wildcard'; type IBody = { index_filter?: estypes.QueryDslQueryContainer } | undefined; interface IQuery { pattern: string; - meta_fields: string[]; + meta_fields: string | string[]; type?: string; rollup_index?: string; allow_no_index?: boolean; diff --git a/test/api_integration/apis/data_views/fields_for_wildcard_route/params.js b/test/api_integration/apis/data_views/fields_for_wildcard_route/params.js index b91c307cc1743a..595d12f38c5014 100644 --- a/test/api_integration/apis/data_views/fields_for_wildcard_route/params.js +++ b/test/api_integration/apis/data_views/fields_for_wildcard_route/params.js @@ -49,6 +49,15 @@ export default function ({ getService }) { }) .expect(200)); + it('accepts single meta_fields query param', () => + supertest + .get('/api/index_patterns/_fields_for_wildcard') + .query({ + pattern: '*', + meta_fields: ['_id'], + }) + .expect(200)); + it('rejects a comma-separated list of meta_fields', () => supertest .get('/api/index_patterns/_fields_for_wildcard')