diff --git a/x-pack/legacy/plugins/reporting/common/cancellation_token.test.ts b/x-pack/legacy/plugins/reporting/common/cancellation_token.test.ts index eac9b6a1a7f35f..5f820f460753ed 100644 --- a/x-pack/legacy/plugins/reporting/common/cancellation_token.test.ts +++ b/x-pack/legacy/plugins/reporting/common/cancellation_token.test.ts @@ -46,13 +46,4 @@ describe('Cancellation Token', () => { expect(onCancelled).toBeCalled(); }); - - it('throws an error when the callback is not a function', () => { - const cancellationToken = new CancellationToken(); - - expect(() => { - // @ts-ignore - cancellationToken.on('cool!'); - }).toThrowError('Expected callback to be a function'); - }); }); diff --git a/x-pack/legacy/plugins/reporting/export_types/csv/server/execute_job.ts b/x-pack/legacy/plugins/reporting/export_types/csv/server/execute_job.ts index ae603d93245a32..f35ffa0e45bfe1 100644 --- a/x-pack/legacy/plugins/reporting/export_types/csv/server/execute_job.ts +++ b/x-pack/legacy/plugins/reporting/export_types/csv/server/execute_job.ts @@ -5,13 +5,16 @@ */ import { i18n } from '@kbn/i18n'; -import { ExecuteJobFactory, ESQueueWorkerExecuteFn, ServerFacade } from '../../../types'; +import { + ExecuteJobFactory, + ESQueueWorkerExecuteFn, + FieldFormats, + ServerFacade, +} from '../../../types'; import { CSV_JOB_TYPE, PLUGIN_ID } from '../../../common/constants'; import { cryptoFactory, LevelLogger } from '../../../server/lib'; import { JobDocPayloadDiscoverCsv } from '../types'; -// @ts-ignore untyped module TODO import { createGenerateCsv } from './lib/generate_csv'; -// @ts-ignore untyped module TODO import { fieldFormatMapFactory } from './lib/field_format_map'; export const executeJobFactory: ExecuteJobFactory { - const fieldFormats = await server.fieldFormatServiceFactory(uiConfig); + const fieldFormats = (await server.fieldFormatServiceFactory(uiConfig)) as FieldFormats; return fieldFormatMapFactory(indexPatternSavedObject, fieldFormats); })(), (async () => { diff --git a/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/check_cells_for_formulas.test.ts b/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/check_cells_for_formulas.test.ts index 31f5a91e5a57b4..972ca1777bd731 100644 --- a/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/check_cells_for_formulas.test.ts +++ b/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/check_cells_for_formulas.test.ts @@ -3,6 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ + import { checkIfRowsHaveFormulas } from './check_cells_for_formulas'; const formulaValues = ['=', '+', '-', '@']; diff --git a/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/escape_value.js b/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/escape_value.js deleted file mode 100644 index 4031191c2f8123..00000000000000 --- a/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/escape_value.js +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -const nonAlphaNumRE = /[^a-zA-Z0-9]/; -const allDoubleQuoteRE = /"/g; - -export function createEscapeValue(quoteValues) { - return function escapeValue(val) { - if (quoteValues && nonAlphaNumRE.test(val)) { - return `"${val.replace(allDoubleQuoteRE, '""')}"`; - } - return val; - }; -} diff --git a/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/__tests__/escape_value.js b/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/escape_value.test.ts similarity index 91% rename from x-pack/legacy/plugins/reporting/export_types/csv/server/lib/__tests__/escape_value.js rename to x-pack/legacy/plugins/reporting/export_types/csv/server/lib/escape_value.test.ts index 02dc694e1555bc..64b021a2aeea84 100644 --- a/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/__tests__/escape_value.js +++ b/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/escape_value.test.ts @@ -5,11 +5,11 @@ */ import expect from '@kbn/expect'; -import { createEscapeValue } from '../escape_value'; +import { createEscapeValue } from './escape_value'; describe('escapeValue', function() { describe('quoteValues is true', function() { - let escapeValue; + let escapeValue: (val: string) => string; beforeEach(function() { escapeValue = createEscapeValue(true); }); @@ -44,7 +44,7 @@ describe('escapeValue', function() { }); describe('quoteValues is false', function() { - let escapeValue; + let escapeValue: (val: string) => string; beforeEach(function() { escapeValue = createEscapeValue(false); }); diff --git a/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/escape_value.ts b/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/escape_value.ts new file mode 100644 index 00000000000000..563de563350e9e --- /dev/null +++ b/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/escape_value.ts @@ -0,0 +1,22 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { RawValue } from './types'; + +const nonAlphaNumRE = /[^a-zA-Z0-9]/; +const allDoubleQuoteRE = /"/g; + +export function createEscapeValue(quoteValues: boolean): (val: RawValue) => string { + return function escapeValue(val: RawValue) { + if (val && typeof val === 'string') { + if (quoteValues && nonAlphaNumRE.test(val)) { + return `"${val.replace(allDoubleQuoteRE, '""')}"`; + } + } + + return val == null ? '' : val.toString(); + }; +} diff --git a/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/__tests__/field_format_map.js b/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/field_format_map.test.ts similarity index 83% rename from x-pack/legacy/plugins/reporting/export_types/csv/server/lib/__tests__/field_format_map.js rename to x-pack/legacy/plugins/reporting/export_types/csv/server/lib/field_format_map.test.ts index 5f6bc32f10d8be..b3384dd6ca51d1 100644 --- a/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/__tests__/field_format_map.js +++ b/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/field_format_map.test.ts @@ -5,13 +5,13 @@ */ import expect from '@kbn/expect'; - -import { FieldFormatsService } from '../../../../../../../../../src/legacy/ui/field_formats/mixin/field_formats_service'; +import { FieldFormatsService } from '../../../../../../../../src/legacy/ui/field_formats/mixin/field_formats_service'; // Reporting uses an unconventional directory structure so the linter marks this as a violation // eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { BytesFormat, NumberFormat } from '../../../../../../../../../src/plugins/data/server'; +import { BytesFormat, NumberFormat } from '../../../../../../../../src/plugins/data/server'; +import { fieldFormatMapFactory } from './field_format_map'; -import { fieldFormatMapFactory } from '../field_format_map'; +type ConfigValue = { number: { id: string; params: {} } } | string; describe('field format map', function() { const indexPatternSavedObject = { @@ -26,12 +26,12 @@ describe('field format map', function() { fieldFormatMap: '{"field1":{"id":"bytes","params":{"pattern":"0,0.[0]b"}}}', }, }; - const configMock = {}; + const configMock: Record = {}; configMock['format:defaultTypeMap'] = { number: { id: 'number', params: {} }, }; configMock['format:number:defaultPattern'] = '0,0.[000]'; - const getConfig = key => configMock[key]; + const getConfig = (key: string) => configMock[key]; const testValue = '4000'; const fieldFormats = new FieldFormatsService([BytesFormat, NumberFormat], getConfig); diff --git a/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/field_format_map.js b/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/field_format_map.ts similarity index 71% rename from x-pack/legacy/plugins/reporting/export_types/csv/server/lib/field_format_map.js rename to x-pack/legacy/plugins/reporting/export_types/csv/server/lib/field_format_map.ts index 17b7361ca07b0c..d013b5e75ee4df 100644 --- a/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/field_format_map.js +++ b/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/field_format_map.ts @@ -5,6 +5,16 @@ */ import _ from 'lodash'; +import { FieldFormats } from '../../../../types'; + +interface IndexPatternSavedObject { + attributes: { + fieldFormatMap: string; + }; + id: string; + type: string; + version: string; +} /** * Create a map of FieldFormat instances for index pattern fields @@ -13,10 +23,13 @@ import _ from 'lodash'; * @param {FieldFormatsService} fieldFormats * @return {Map} key: field name, value: FieldFormat instance */ -export function fieldFormatMapFactory(indexPatternSavedObject, fieldFormats) { +export function fieldFormatMapFactory( + indexPatternSavedObject: IndexPatternSavedObject, + fieldFormats: FieldFormats +) { const formatsMap = new Map(); - //Add FieldFormat instances for fields with custom formatters + // Add FieldFormat instances for fields with custom formatters if (_.has(indexPatternSavedObject, 'attributes.fieldFormatMap')) { const fieldFormatMap = JSON.parse(indexPatternSavedObject.attributes.fieldFormatMap); Object.keys(fieldFormatMap).forEach(fieldName => { @@ -28,9 +41,9 @@ export function fieldFormatMapFactory(indexPatternSavedObject, fieldFormats) { }); } - //Add default FieldFormat instances for all other fields + // Add default FieldFormat instances for all other fields const indexFields = JSON.parse(_.get(indexPatternSavedObject, 'attributes.fields', '[]')); - indexFields.forEach(field => { + indexFields.forEach((field: any) => { if (!formatsMap.has(field.name)) { formatsMap.set(field.name, fieldFormats.getDefaultInstance(field.type)); } diff --git a/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/__tests__/flatten_hit.js b/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/flatten_hit.test.ts similarity index 95% rename from x-pack/legacy/plugins/reporting/export_types/csv/server/lib/__tests__/flatten_hit.js rename to x-pack/legacy/plugins/reporting/export_types/csv/server/lib/flatten_hit.test.ts index 2169c7cab12362..1e06e78357399c 100644 --- a/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/__tests__/flatten_hit.js +++ b/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/flatten_hit.test.ts @@ -5,12 +5,14 @@ */ import expect from '@kbn/expect'; -import { createFlattenHit } from '../flatten_hit'; +import { createFlattenHit } from './flatten_hit'; + +type Hit = Record; describe('flattenHit', function() { - let flattenHit; - let hit; - let metaFields; + let flattenHit: (hit: Hit) => Record; + let hit: Hit; + let metaFields: string[]; beforeEach(function() { const fields = [ diff --git a/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/flatten_hit.js b/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/flatten_hit.ts similarity index 66% rename from x-pack/legacy/plugins/reporting/export_types/csv/server/lib/flatten_hit.js rename to x-pack/legacy/plugins/reporting/export_types/csv/server/lib/flatten_hit.ts index b1387a3ef310c5..328d49a27911c7 100644 --- a/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/flatten_hit.js +++ b/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/flatten_hit.ts @@ -6,9 +6,17 @@ import _ from 'lodash'; +type Hit = Record; +type FlattenHitFn = (hit: Hit) => Record; +type FlatHits = Record; + // TODO this logic should be re-used with Discover -export function createFlattenHit(fields, metaFields, conflictedTypesFields) { - const flattenSource = (flat, obj, keyPrefix) => { +export function createFlattenHit( + fields: string[], + metaFields: string[], + conflictedTypesFields: string[] +): FlattenHitFn { + const flattenSource = (flat: FlatHits, obj: object, keyPrefix = '') => { keyPrefix = keyPrefix ? keyPrefix + '.' : ''; _.forOwn(obj, (val, key) => { key = keyPrefix + key; @@ -31,17 +39,19 @@ export function createFlattenHit(fields, metaFields, conflictedTypesFields) { }); }; - const flattenMetaFields = (flat, hit) => { + const flattenMetaFields = (flat: Hit, hit: Hit) => { _.each(metaFields, meta => { if (meta === '_source') return; flat[meta] = hit[meta]; }); }; - const flattenFields = (flat, hitFields) => { + const flattenFields = (flat: FlatHits, hitFields: string[]) => { _.forOwn(hitFields, (val, key) => { - if (key[0] === '_' && !_.contains(metaFields, key)) return; - flat[key] = _.isArray(val) && val.length === 1 ? val[0] : val; + if (key) { + if (key[0] === '_' && !_.contains(metaFields, key)) return; + flat[key] = _.isArray(val) && val.length === 1 ? val[0] : val; + } }); }; diff --git a/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/__tests__/format_csv_values.js b/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/format_csv_values.test.ts similarity index 92% rename from x-pack/legacy/plugins/reporting/export_types/csv/server/lib/__tests__/format_csv_values.js rename to x-pack/legacy/plugins/reporting/export_types/csv/server/lib/format_csv_values.test.ts index 7401109ae80301..b38bad11794717 100644 --- a/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/__tests__/format_csv_values.js +++ b/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/format_csv_values.test.ts @@ -5,12 +5,12 @@ */ import expect from '@kbn/expect'; -import { createFormatCsvValues } from '../format_csv_values'; +import { createFormatCsvValues } from './format_csv_values'; describe('formatCsvValues', function() { const separator = ','; const fields = ['foo', 'bar']; - const mockEscapeValue = val => val; + const mockEscapeValue = (value: any, index: number, array: any[]) => value || ''; describe('with _source as one of the fields', function() { const formatsMap = new Map(); const formatCsvValues = createFormatCsvValues( @@ -62,7 +62,7 @@ describe('formatCsvValues', function() { describe('with field formats', function() { const mockFieldFormat = { - convert: val => String(val).toUpperCase(), + convert: (val: string) => String(val).toUpperCase(), }; const formatsMap = new Map(); formatsMap.set('bar', mockFieldFormat); diff --git a/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/format_csv_values.js b/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/format_csv_values.ts similarity index 72% rename from x-pack/legacy/plugins/reporting/export_types/csv/server/lib/format_csv_values.js rename to x-pack/legacy/plugins/reporting/export_types/csv/server/lib/format_csv_values.ts index 9083e8ce04f88c..0bcf0fc31beae5 100644 --- a/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/format_csv_values.js +++ b/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/format_csv_values.ts @@ -5,9 +5,15 @@ */ import { isObject, isNull, isUndefined } from 'lodash'; +import { RawValue } from './types'; -export function createFormatCsvValues(escapeValue, separator, fields, formatsMap) { - return function formatCsvValues(values) { +export function createFormatCsvValues( + escapeValue: (value: RawValue, index: number, array: RawValue[]) => string, + separator: string, + fields: string[], + formatsMap: any +) { + return function formatCsvValues(values: Record) { return fields .map(field => { let value; @@ -29,7 +35,7 @@ export function createFormatCsvValues(escapeValue, separator, fields, formatsMap return formattedValue; }) .map(value => (isObject(value) ? JSON.stringify(value) : value)) - .map(value => value.toString()) + .map(value => (value ? value.toString() : value)) .map(escapeValue) .join(separator); }; diff --git a/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/generate_csv.js b/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/generate_csv.ts similarity index 89% rename from x-pack/legacy/plugins/reporting/export_types/csv/server/lib/generate_csv.js rename to x-pack/legacy/plugins/reporting/export_types/csv/server/lib/generate_csv.ts index c13d24022c40c4..1986e68917ba86 100644 --- a/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/generate_csv.js +++ b/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/generate_csv.ts @@ -4,6 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ +import { Logger } from '../../../../types'; +import { GenerateCsvParams, SavedSearchGeneratorResult } from '../../types'; import { createFlattenHit } from './flatten_hit'; import { createFormatCsvValues } from './format_csv_values'; import { createEscapeValue } from './escape_value'; @@ -11,7 +13,7 @@ import { createHitIterator } from './hit_iterator'; import { MaxSizeStringBuilder } from './max_size_string_builder'; import { checkIfRowsHaveFormulas } from './check_cells_for_formulas'; -export function createGenerateCsv(logger) { +export function createGenerateCsv(logger: Logger) { const hitIterator = createHitIterator(logger); return async function generateCsv({ @@ -23,12 +25,13 @@ export function createGenerateCsv(logger) { callEndpoint, cancellationToken, settings, - }) { + }: GenerateCsvParams): Promise { const escapeValue = createEscapeValue(settings.quoteValues); const builder = new MaxSizeStringBuilder(settings.maxSizeBytes); const header = `${fields.map(escapeValue).join(settings.separator)}\n`; if (!builder.tryAppend(header)) { return { + size: 0, content: '', maxSizeReached: true, }; @@ -49,6 +52,10 @@ export function createGenerateCsv(logger) { while (true) { const { done, value: hit } = await iterator.next(); + if (!hit) { + break; + } + if (done) { break; } diff --git a/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/__tests__/hit_iterator.ts b/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/hit_iterator.test.ts similarity index 95% rename from x-pack/legacy/plugins/reporting/export_types/csv/server/lib/__tests__/hit_iterator.ts rename to x-pack/legacy/plugins/reporting/export_types/csv/server/lib/hit_iterator.test.ts index 20e373a4168af9..3765217de92859 100644 --- a/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/__tests__/hit_iterator.ts +++ b/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/hit_iterator.test.ts @@ -6,9 +6,9 @@ import expect from '@kbn/expect'; import sinon from 'sinon'; -import { CancellationToken } from '../../../../../common/cancellation_token'; -import { Logger, ScrollConfig } from '../../../../../types'; -import { createHitIterator } from '../hit_iterator'; +import { CancellationToken } from '../../../../common/cancellation_token'; +import { Logger, ScrollConfig } from '../../../../types'; +import { createHitIterator } from './hit_iterator'; const mockLogger = { error: new Function(), diff --git a/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/hit_iterator.ts b/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/hit_iterator.ts index 68836c01369e3f..90690b62ff4a41 100644 --- a/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/hit_iterator.ts +++ b/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/hit_iterator.ts @@ -3,8 +3,8 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import { SearchParams, SearchResponse } from 'elasticsearch'; +import { SearchParams, SearchResponse } from 'elasticsearch'; import { i18n } from '@kbn/i18n'; import { CancellationToken, ScrollConfig, Logger } from '../../../../types'; diff --git a/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/__tests__/max_size_string_builder.js b/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/max_size_string_builder.test.ts similarity index 97% rename from x-pack/legacy/plugins/reporting/export_types/csv/server/lib/__tests__/max_size_string_builder.js rename to x-pack/legacy/plugins/reporting/export_types/csv/server/lib/max_size_string_builder.test.ts index ddc4299ebcb455..843ff82e7c4bc9 100644 --- a/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/__tests__/max_size_string_builder.js +++ b/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/max_size_string_builder.test.ts @@ -5,7 +5,7 @@ */ import expect from '@kbn/expect'; -import { MaxSizeStringBuilder } from '../max_size_string_builder'; +import { MaxSizeStringBuilder } from './max_size_string_builder'; describe('MaxSizeStringBuilder', function() { describe('tryAppend', function() { diff --git a/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/max_size_string_builder.js b/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/max_size_string_builder.ts similarity index 83% rename from x-pack/legacy/plugins/reporting/export_types/csv/server/lib/max_size_string_builder.js rename to x-pack/legacy/plugins/reporting/export_types/csv/server/lib/max_size_string_builder.ts index b4bdfcc13b3f6e..70bc2030d290c6 100644 --- a/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/max_size_string_builder.js +++ b/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/max_size_string_builder.ts @@ -5,13 +5,17 @@ */ export class MaxSizeStringBuilder { - constructor(maxSizeBytes) { + private _buffer: Buffer; + private _size: number; + private _maxSize: number; + + constructor(maxSizeBytes: number) { this._buffer = Buffer.alloc(maxSizeBytes); this._size = 0; this._maxSize = maxSizeBytes; } - tryAppend(str) { + tryAppend(str: string) { const byteLength = Buffer.byteLength(str); if (this._size + byteLength <= this._maxSize) { this._buffer.write(str, this._size); diff --git a/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/types.d.ts b/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/types.d.ts new file mode 100644 index 00000000000000..b4dc7436649956 --- /dev/null +++ b/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/types.d.ts @@ -0,0 +1,7 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export type RawValue = string | object | null | undefined; diff --git a/x-pack/legacy/plugins/reporting/export_types/csv/types.d.ts b/x-pack/legacy/plugins/reporting/export_types/csv/types.d.ts index 9d1eb9cc1bd4d3..842330fa7c93f3 100644 --- a/x-pack/legacy/plugins/reporting/export_types/csv/types.d.ts +++ b/x-pack/legacy/plugins/reporting/export_types/csv/types.d.ts @@ -4,6 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ +import { CancellationToken } from '../../common/cancellation_token'; import { JobDocPayload, JobParamPostPayload, ConditionalHeaders, RequestFacade } from '../../types'; interface DocValueField { @@ -37,3 +38,75 @@ export interface JobDocPayloadDiscoverCsv extends JobDocPayload; + stored_fields: string[]; + } + | any; +} + +type EndpointCaller = (method: string, params: any) => Promise; + +type FormatsMap = Map< + string, + { + id: string; + params: { + pattern: string; + }; + } +>; + +export interface SavedSearchGeneratorResult { + content: string; + size: number; + maxSizeReached: boolean; + csvContainsFormulas?: boolean; +} + +export interface CsvResultFromSearch { + type: string; + result: SavedSearchGeneratorResult; +} + +export interface GenerateCsvParams { + searchRequest: SearchRequest; + callEndpoint: EndpointCaller; + fields: string[]; + formatsMap: FormatsMap; + metaFields: string[]; + conflictedTypesFields: string[]; + cancellationToken: CancellationToken; + settings: { + separator: string; + quoteValues: boolean; + timezone: string | null; + maxSizeBytes: number; + scroll: { duration: string; size: number }; + checkForFormulas?: boolean; + }; +} diff --git a/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/server/execute_job.ts b/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/server/execute_job.ts index e161d7afc84e27..69d9a173d40b38 100644 --- a/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/server/execute_job.ts +++ b/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/server/execute_job.ts @@ -18,13 +18,8 @@ import { CSV_FROM_SAVEDOBJECT_JOB_TYPE, PLUGIN_ID, } from '../../../common/constants'; -import { - CsvResultFromSearch, - JobParamsPanelCsv, - SearchPanel, - JobDocPayloadPanelCsv, - FakeRequest, -} from '../types'; +import { CsvResultFromSearch } from '../../csv/types'; +import { JobParamsPanelCsv, SearchPanel, JobDocPayloadPanelCsv, FakeRequest } from '../types'; import { createGenerateCsv } from './lib'; export const executeJobFactory: ExecuteJobFactory; - stored_fields: string[]; - } - | any; -} - -export interface SavedSearchGeneratorResult { - content: string; - maxSizeReached: boolean; - size: number; -} - -export interface CsvResultFromSearch { - type: string; - result: SavedSearchGeneratorResult; -} - -type EndpointCaller = (method: string, params: any) => Promise; -type FormatsMap = Map< - string, - { - id: string; - params: { - pattern: string; - }; - } ->; - -export interface GenerateCsvParams { - searchRequest: SearchRequest; - callEndpoint: EndpointCaller; - fields: string[]; - formatsMap: FormatsMap; - metaFields: string[]; // FIXME not sure what this is for - conflictedTypesFields: string[]; // FIXME not sure what this is for - cancellationToken: CancellationToken; - settings: { - separator: string; - quoteValues: boolean; - timezone: string | null; - maxSizeBytes: number; - scroll: { duration: string; size: number }; - }; -} - /* * These filter types are stub types to help ensure things get passed to * non-Typescript functions in the right order. An actual structure is not diff --git a/x-pack/legacy/plugins/reporting/server/lib/create_queue.ts b/x-pack/legacy/plugins/reporting/server/lib/create_queue.ts index 5cf760250ec0e3..4a9b0c7cd2ebb3 100644 --- a/x-pack/legacy/plugins/reporting/server/lib/create_queue.ts +++ b/x-pack/legacy/plugins/reporting/server/lib/create_queue.ts @@ -15,7 +15,6 @@ import { import { Esqueue } from './esqueue'; import { createWorkerFactory } from './create_worker'; import { LevelLogger } from './level_logger'; -// @ts-ignore import { createTaggedLogger } from './create_tagged_logger'; // TODO remove createTaggedLogger once esqueue is removed interface CreateQueueFactoryOpts { diff --git a/x-pack/legacy/plugins/reporting/server/lib/create_tagged_logger.js b/x-pack/legacy/plugins/reporting/server/lib/create_tagged_logger.ts similarity index 79% rename from x-pack/legacy/plugins/reporting/server/lib/create_tagged_logger.js rename to x-pack/legacy/plugins/reporting/server/lib/create_tagged_logger.ts index 838024f801b676..40a1cd8203d2fe 100644 --- a/x-pack/legacy/plugins/reporting/server/lib/create_tagged_logger.js +++ b/x-pack/legacy/plugins/reporting/server/lib/create_tagged_logger.ts @@ -4,6 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ +import { ServerFacade } from '../../types'; + /** * @function taggedLogger * @param {string} message @@ -17,8 +19,8 @@ * @param {string[]} tags - tags to always be passed into the `logger` function * @returns taggedLogger */ -export function createTaggedLogger(server, tags) { - return (msg, additionalTags = []) => { +export function createTaggedLogger(server: ServerFacade, tags: string[]) { + return (msg: string, additionalTags = []) => { server.log([...tags, ...additionalTags], msg); }; } diff --git a/x-pack/legacy/plugins/reporting/server/lib/jobs_query.js b/x-pack/legacy/plugins/reporting/server/lib/jobs_query.ts similarity index 70% rename from x-pack/legacy/plugins/reporting/server/lib/jobs_query.js rename to x-pack/legacy/plugins/reporting/server/lib/jobs_query.ts index 2162ecedb8371f..0c16f780c34acd 100644 --- a/x-pack/legacy/plugins/reporting/server/lib/jobs_query.js +++ b/x-pack/legacy/plugins/reporting/server/lib/jobs_query.ts @@ -5,21 +5,48 @@ */ import { get } from 'lodash'; +import { ServerFacade, JobSource } from '../../types'; const defaultSize = 10; -export function jobsQueryFactory(server) { +interface QueryBody { + size?: number; + from?: number; + _source?: { + excludes: string[]; + }; + query: { + constant_score: { + filter: { + bool: { + must: Array>; + }; + }; + }; + }; +} + +interface GetOpts { + includeContent?: boolean; +} + +interface CountAggResult { + count: number; +} + +export function jobsQueryFactory(server: ServerFacade) { const index = server.config().get('xpack.reporting.index'); + // @ts-ignore `errors` does not exist on type Cluster const { callWithInternalUser, errors: esErrors } = server.plugins.elasticsearch.getCluster( 'admin' ); - function getUsername(user) { + function getUsername(user: any) { return get(user, 'username', false); } - function execQuery(queryType, body) { - const defaultBody = { + function execQuery(queryType: string, body: QueryBody) { + const defaultBody: Record = { search: { _source: { excludes: ['output.content'], @@ -42,15 +69,17 @@ export function jobsQueryFactory(server) { }); } - function getHits(query) { + type Result = number; + + function getHits(query: Promise) { return query.then(res => get(res, 'hits.hits', [])); } return { - list(jobTypes, user, page = 0, size = defaultSize, jobIds) { + list(jobTypes: string[], user: any, page = 0, size = defaultSize, jobIds: string[] | null) { const username = getUsername(user); - const body = { + const body: QueryBody = { size, from: size * page, query: { @@ -73,10 +102,10 @@ export function jobsQueryFactory(server) { return getHits(execQuery('search', body)); }, - count(jobTypes, user) { + count(jobTypes: string[], user: any) { const username = getUsername(user); - const body = { + const body: QueryBody = { query: { constant_score: { filter: { @@ -88,18 +117,18 @@ export function jobsQueryFactory(server) { }, }; - return execQuery('count', body).then(doc => { + return execQuery('count', body).then((doc: CountAggResult) => { if (!doc) return 0; return doc.count; }); }, - get(user, id, opts = {}) { + get(user: any, id: string, opts: GetOpts = {}): Promise | void> { if (!id) return Promise.resolve(); const username = getUsername(user); - const body = { + const body: QueryBody = { query: { constant_score: { filter: { diff --git a/x-pack/legacy/plugins/reporting/server/routes/jobs.ts b/x-pack/legacy/plugins/reporting/server/routes/jobs.ts index a0be15d60f3164..6084ca613d10ed 100644 --- a/x-pack/legacy/plugins/reporting/server/routes/jobs.ts +++ b/x-pack/legacy/plugins/reporting/server/routes/jobs.ts @@ -82,17 +82,19 @@ export function registerJobInfoRoutes( const { docId } = request.params; return jobsQuery.get(request.pre.user, docId, { includeContent: true }).then( - ({ _source: job }: JobSource): JobDocOutput => { - if (!job) { + (result): JobDocOutput => { + if (!result) { throw boom.notFound(); } + const { + _source: { jobtype: jobType, output: jobOutput }, + } = result; - const { jobtype: jobType } = job; if (!request.pre.management.jobTypes.includes(jobType)) { throw boom.unauthorized(`Sorry, you are not authorized to download ${jobType} reports`); } - return job.output; + return jobOutput; } ); }, @@ -107,26 +109,25 @@ export function registerJobInfoRoutes( const request = makeRequestFacade(legacyRequest); const { docId } = request.params; - return jobsQuery - .get(request.pre.user, docId) - .then(({ _source: job }: JobSource): JobSource['_source'] => { - if (!job) { - throw boom.notFound(); - } + return jobsQuery.get(request.pre.user, docId).then((result): JobSource['_source'] => { + if (!result) { + throw boom.notFound(); + } - const { jobtype: jobType, payload } = job; - if (!request.pre.management.jobTypes.includes(jobType)) { - throw boom.unauthorized(`Sorry, you are not authorized to view ${jobType} info`); - } + const { _source: job } = result; + const { jobtype: jobType, payload: jobPayload } = job; + if (!request.pre.management.jobTypes.includes(jobType)) { + throw boom.unauthorized(`Sorry, you are not authorized to view ${jobType} info`); + } - return { - ...job, - payload: { - ...payload, - headers: undefined, - }, - }; - }); + return { + ...job, + payload: { + ...jobPayload, + headers: undefined, + }, + }; + }); }, }); diff --git a/x-pack/legacy/plugins/reporting/server/routes/lib/authorized_user_pre_routing.js b/x-pack/legacy/plugins/reporting/server/routes/lib/authorized_user_pre_routing.ts similarity index 60% rename from x-pack/legacy/plugins/reporting/server/routes/lib/authorized_user_pre_routing.js rename to x-pack/legacy/plugins/reporting/server/routes/lib/authorized_user_pre_routing.ts index 79a5f1a4f6f5fe..eb473e0bc76d45 100644 --- a/x-pack/legacy/plugins/reporting/server/routes/lib/authorized_user_pre_routing.js +++ b/x-pack/legacy/plugins/reporting/server/routes/lib/authorized_user_pre_routing.ts @@ -4,16 +4,25 @@ * you may not use this file except in compliance with the Elastic License. */ -import boom from 'boom'; +import Boom from 'boom'; +import { Legacy } from 'kibana'; +import { AuthenticatedUser } from '../../../../../../plugins/security/server'; import { getUserFactory } from '../../lib/get_user'; +import { ServerFacade } from '../../../types'; const superuserRole = 'superuser'; -export const authorizedUserPreRoutingFactory = function authorizedUserPreRoutingFn(server) { +export type PreRoutingFunction = ( + request: Legacy.Request +) => Promise | AuthenticatedUser | null>; + +export const authorizedUserPreRoutingFactory = function authorizedUserPreRoutingFn( + server: ServerFacade +) { const getUser = getUserFactory(server); const config = server.config(); - return async function authorizedUserPreRouting(request) { + return async function authorizedUserPreRouting(request: Legacy.Request) { const xpackInfo = server.plugins.xpack_main.info; if (!xpackInfo || !xpackInfo.isAvailable()) { @@ -21,7 +30,7 @@ export const authorizedUserPreRoutingFactory = function authorizedUserPreRouting ['reporting', 'authorizedUserPreRouting', 'debug'], 'Unable to authorize user before xpack info is available.' ); - return boom.notFound(); + return Boom.notFound(); } const security = xpackInfo.feature('security'); @@ -32,12 +41,15 @@ export const authorizedUserPreRoutingFactory = function authorizedUserPreRouting const user = await getUser(request); if (!user) { - return boom.unauthorized(`Sorry, you aren't authenticated`); + return Boom.unauthorized(`Sorry, you aren't authenticated`); } - const authorizedRoles = [superuserRole, ...config.get('xpack.reporting.roles.allow')]; + const authorizedRoles = [ + superuserRole, + ...(config.get('xpack.reporting.roles.allow') as string[]), + ]; if (!user.roles.find(role => authorizedRoles.includes(role))) { - return boom.forbidden(`Sorry, you don't have access to Reporting`); + return Boom.forbidden(`Sorry, you don't have access to Reporting`); } return user; diff --git a/x-pack/legacy/plugins/reporting/server/routes/lib/reporting_feature_pre_routing.js b/x-pack/legacy/plugins/reporting/server/routes/lib/reporting_feature_pre_routing.ts similarity index 76% rename from x-pack/legacy/plugins/reporting/server/routes/lib/reporting_feature_pre_routing.js rename to x-pack/legacy/plugins/reporting/server/routes/lib/reporting_feature_pre_routing.ts index 92973e3d0b4220..6efac818981efa 100644 --- a/x-pack/legacy/plugins/reporting/server/routes/lib/reporting_feature_pre_routing.js +++ b/x-pack/legacy/plugins/reporting/server/routes/lib/reporting_feature_pre_routing.ts @@ -5,14 +5,20 @@ */ import Boom from 'boom'; +import { Legacy } from 'kibana'; +import { ServerFacade } from '../../../types'; -export const reportingFeaturePreRoutingFactory = function reportingFeaturePreRoutingFn(server) { +export type GetReportingFeatureIdFn = (request: Legacy.Request) => string; + +export const reportingFeaturePreRoutingFactory = function reportingFeaturePreRoutingFn( + server: ServerFacade +) { const xpackMainPlugin = server.plugins.xpack_main; const pluginId = 'reporting'; // License checking and enable/disable logic - return function reportingFeaturePreRouting(getReportingFeatureId) { - return function licensePreRouting(request) { + return function reportingFeaturePreRouting(getReportingFeatureId: GetReportingFeatureIdFn) { + return function licensePreRouting(request: Legacy.Request) { const licenseCheckResults = xpackMainPlugin.info.feature(pluginId).getLicenseCheckResults(); const reportingFeatureId = getReportingFeatureId(request); const reportingFeature = licenseCheckResults[reportingFeatureId]; diff --git a/x-pack/legacy/plugins/reporting/server/routes/lib/route_config_factories.ts b/x-pack/legacy/plugins/reporting/server/routes/lib/route_config_factories.ts index 29ded68d403c58..caf24bf64f6023 100644 --- a/x-pack/legacy/plugins/reporting/server/routes/lib/route_config_factories.ts +++ b/x-pack/legacy/plugins/reporting/server/routes/lib/route_config_factories.ts @@ -6,11 +6,10 @@ import Joi from 'joi'; import { CSV_FROM_SAVEDOBJECT_JOB_TYPE } from '../../../common/constants'; -import { ServerFacade, RequestFacade } from '../../../types'; -// @ts-ignore +import { ServerFacade } from '../../../types'; import { authorizedUserPreRoutingFactory } from './authorized_user_pre_routing'; -// @ts-ignore import { reportingFeaturePreRoutingFactory } from './reporting_feature_pre_routing'; +import { GetReportingFeatureIdFn } from './reporting_feature_pre_routing'; const API_TAG = 'api'; @@ -22,19 +21,16 @@ export interface RouteConfigFactory { }; } -type GetFeatureFunction = (request: RequestFacade) => any; -type PreRoutingFunction = (getFeatureId?: GetFeatureFunction) => any; - export type GetRouteConfigFactoryFn = ( - getFeatureId?: GetFeatureFunction | undefined + getFeatureId?: GetReportingFeatureIdFn ) => RouteConfigFactory; export function getRouteConfigFactoryReportingPre(server: ServerFacade): GetRouteConfigFactoryFn { - const authorizedUserPreRouting: PreRoutingFunction = authorizedUserPreRoutingFactory(server); - const reportingFeaturePreRouting: PreRoutingFunction = reportingFeaturePreRoutingFactory(server); + const authorizedUserPreRouting = authorizedUserPreRoutingFactory(server); + const reportingFeaturePreRouting = reportingFeaturePreRoutingFactory(server); - return (getFeatureId?: GetFeatureFunction): RouteConfigFactory => { - const preRouting = [{ method: authorizedUserPreRouting, assign: 'user' }]; + return (getFeatureId?: GetReportingFeatureIdFn): RouteConfigFactory => { + const preRouting: any[] = [{ method: authorizedUserPreRouting, assign: 'user' }]; if (getFeatureId) { preRouting.push(reportingFeaturePreRouting(getFeatureId)); } diff --git a/x-pack/legacy/plugins/reporting/types.d.ts b/x-pack/legacy/plugins/reporting/types.d.ts index 9fae60afee4e82..47f384250dd537 100644 --- a/x-pack/legacy/plugins/reporting/types.d.ts +++ b/x-pack/legacy/plugins/reporting/types.d.ts @@ -355,3 +355,9 @@ export interface InterceptedRequest { frameId: string; resourceType: string; } + +export interface FieldFormats { + getConfig: number; + getInstance: (config: any) => any; + getDefaultInstance: (key: string) => any; +}