[Console] Clean up use of any (#95065)

* cleaned up autocomplete.ts and get_endpoint_from_postition.ts of anys

* general clean up of lowering hanging fruit

* cleaned up remaining anys, still need to test

* fix remaining TS compilation issues

* also tidy up use of "as any" and some more ": any"

* addressed type issues and introduced the default editor settings object

* clean up @ts-ignore

* added comments to interface

Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
Jean-Louis Leysens 2021-03-24 14:05:08 +01:00 committed by GitHub
parent 6295ae71b5
commit edfdb78957
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
52 changed files with 402 additions and 219 deletions

View file

@ -16,7 +16,7 @@ import { i18n } from '@kbn/i18n';
interface Props {
getCurl: () => Promise<string>;
getDocumentation: () => Promise<string | null>;
autoIndent: (ev?: React.MouseEvent) => void;
autoIndent: (ev: React.MouseEvent) => void;
addNotification?: (opts: { title: string }) => void;
}
@ -84,8 +84,7 @@ export class ConsoleMenu extends Component<Props, State> {
window.open(documentation, '_blank');
};
// Using `any` here per this issue: https://github.com/elastic/eui/issues/2265
autoIndent: any = (event: React.MouseEvent) => {
autoIndent = (event: React.MouseEvent) => {
this.closePopover();
this.props.autoIndent(event);
};

View file

@ -32,7 +32,7 @@ export type AutocompleteOptions = 'fields' | 'indices' | 'templates';
interface Props {
onSaveSettings: (newSettings: DevToolsSettings) => void;
onClose: () => void;
refreshAutocompleteSettings: (selectedSettings: any) => void;
refreshAutocompleteSettings: (selectedSettings: DevToolsSettings['autocomplete']) => void;
settings: DevToolsSettings;
}
@ -233,7 +233,7 @@ export function DevToolsSettingsModal(props: Props) {
return rest;
})}
idToSelectedMap={checkboxIdToSelectedMap}
onChange={(e: any) => {
onChange={(e: unknown) => {
onAutocompleteChange(e as AutocompleteOptions);
}}
/>

View file

@ -53,7 +53,7 @@ export function ConsoleHistory({ close }: Props) {
const selectedReq = useRef<any>(null);
const describeReq = useMemo(() => {
const _describeReq = (req: any) => {
const _describeReq = (req: { endpoint: string; time: string }) => {
const endpoint = req.endpoint;
const date = moment(req.time);

View file

@ -20,7 +20,7 @@ import { applyCurrentSettings } from '../editor/legacy/console_editor/apply_edit
interface Props {
settings: DevToolsSettings;
req: any | null;
req: { method: string; endpoint: string; data: string; time: string } | null;
}
export function HistoryViewer({ settings, req }: Props) {

View file

@ -14,7 +14,7 @@ export function applyCurrentSettings(
editor: CoreEditor | CustomAceEditor,
settings: DevToolsSettings
) {
if ((editor as any).setStyles) {
if ((editor as { setStyles?: Function }).setStyles) {
(editor as CoreEditor).setStyles({
wrapLines: settings.wrapMode,
fontSize: settings.fontSize + 'px',

View file

@ -27,7 +27,7 @@ import {
// Mocked functions
import { sendRequestToES } from '../../../../hooks/use_send_current_request_to_es/send_request_to_es';
import { getEndpointFromPosition } from '../../../../../lib/autocomplete/get_endpoint_from_position';
import type { DevToolsSettings } from '../../../../../services';
import * as consoleMenuActions from '../console_menu_actions';
import { Editor } from './editor';
@ -40,7 +40,7 @@ describe('Legacy (Ace) Console Editor Component Smoke Test', () => {
<I18nProvider>
<ServicesContextProvider value={mockedAppContextValue}>
<RequestContextProvider>
<EditorContextProvider settings={{} as any}>
<EditorContextProvider settings={({} as unknown) as DevToolsSettings}>
<Editor initialTextValue="" />
</EditorContextProvider>
</RequestContextProvider>

View file

@ -229,7 +229,7 @@ function EditorUI({ initialTextValue }: EditorProps) {
getDocumentation={() => {
return getDocumentation(editorInstanceRef.current!, docLinkVersion);
}}
autoIndent={(event: any) => {
autoIndent={(event) => {
autoIndent(editorInstanceRef.current!, event);
}}
addNotification={({ title }) => notifications.toasts.add({ title })}

View file

@ -9,7 +9,7 @@
import { getEndpointFromPosition } from '../../../../lib/autocomplete/get_endpoint_from_position';
import { SenseEditor } from '../../../models/sense_editor';
export async function autoIndent(editor: SenseEditor, event: Event) {
export async function autoIndent(editor: SenseEditor, event: React.MouseEvent) {
event.preventDefault();
await editor.autoIndent();
editor.getCoreEditor().getContainer().focus();

View file

@ -15,14 +15,20 @@ import { retrieveAutoCompleteInfo } from '../../lib/mappings/mappings';
import { useServicesContext, useEditorActionContext } from '../contexts';
import { DevToolsSettings, Settings as SettingsService } from '../../services';
const getAutocompleteDiff = (newSettings: DevToolsSettings, prevSettings: DevToolsSettings) => {
const getAutocompleteDiff = (
newSettings: DevToolsSettings,
prevSettings: DevToolsSettings
): AutocompleteOptions[] => {
return Object.keys(newSettings.autocomplete).filter((key) => {
// @ts-ignore
return prevSettings.autocomplete[key] !== newSettings.autocomplete[key];
});
}) as AutocompleteOptions[];
};
const refreshAutocompleteSettings = (settings: SettingsService, selectedSettings: any) => {
const refreshAutocompleteSettings = (
settings: SettingsService,
selectedSettings: DevToolsSettings['autocomplete']
) => {
retrieveAutoCompleteInfo(settings, selectedSettings);
};
@ -44,12 +50,12 @@ const fetchAutocompleteSettingsIfNeeded = (
if (isSettingsChanged) {
// If the user has changed one of the autocomplete settings, then we'll fetch just the
// ones which have changed.
const changedSettings: any = autocompleteDiff.reduce(
(changedSettingsAccum: any, setting: string): any => {
changedSettingsAccum[setting] = newSettings.autocomplete[setting as AutocompleteOptions];
const changedSettings: DevToolsSettings['autocomplete'] = autocompleteDiff.reduce(
(changedSettingsAccum, setting) => {
changedSettingsAccum[setting] = newSettings.autocomplete[setting];
return changedSettingsAccum;
},
{}
{} as DevToolsSettings['autocomplete']
);
retrieveAutoCompleteInfo(settings, changedSettings);
} else if (isPollingChanged && newSettings.polling) {
@ -89,7 +95,7 @@ export function Settings({ onClose }: Props) {
<DevToolsSettingsModal
onClose={onClose}
onSaveSettings={onSaveSettings}
refreshAutocompleteSettings={(selectedSettings: any) =>
refreshAutocompleteSettings={(selectedSettings) =>
refreshAutocompleteSettings(settings, selectedSettings)
}
settings={settings.toJSON()}

View file

@ -11,11 +11,11 @@ import * as editor from '../../stores/editor';
import { DevToolsSettings } from '../../../services';
import { createUseContext } from '../create_use_context';
const EditorReadContext = createContext<editor.Store>(null as any);
const EditorActionContext = createContext<Dispatch<editor.Action>>(null as any);
const EditorReadContext = createContext<editor.Store>(editor.initialValue);
const EditorActionContext = createContext<Dispatch<editor.Action>>(() => {});
export interface EditorContextArgs {
children: any;
children: JSX.Element;
settings: DevToolsSettings;
}
@ -25,7 +25,7 @@ export function EditorContextProvider({ children, settings }: EditorContextArgs)
settings,
}));
return (
<EditorReadContext.Provider value={state as any}>
<EditorReadContext.Provider value={state}>
<EditorActionContext.Provider value={dispatch}>{children}</EditorActionContext.Provider>
</EditorReadContext.Provider>
);

View file

@ -10,8 +10,8 @@ import React, { createContext, useReducer, Dispatch } from 'react';
import { createUseContext } from './create_use_context';
import * as store from '../stores/request';
const RequestReadContext = createContext<store.Store>(null as any);
const RequestActionContext = createContext<Dispatch<store.Actions>>(null as any);
const RequestReadContext = createContext<store.Store>(store.initialValue);
const RequestActionContext = createContext<Dispatch<store.Actions>>(() => {});
export function RequestContextProvider({ children }: { children: React.ReactNode }) {
const [state, dispatch] = useReducer(store.reducer, store.initialValue);

View file

@ -9,6 +9,7 @@
import { notificationServiceMock } from '../../../../../core/public/mocks';
import { httpServiceMock } from '../../../../../core/public/mocks';
import type { ObjectStorageClient } from '../../../common/types';
import { HistoryMock } from '../../services/history.mock';
import { SettingsMock } from '../../services/settings.mock';
import { StorageMock } from '../../services/storage.mock';
@ -18,7 +19,7 @@ import { ContextValue } from './services_context';
export const serviceContextMock = {
create: (): ContextValue => {
const storage = new StorageMock({} as any, 'test');
const storage = new StorageMock(({} as unknown) as Storage, 'test');
const http = httpServiceMock.createSetupContract();
const api = createApi({ http });
const esHostService = createEsHostService({ api });
@ -31,7 +32,7 @@ export const serviceContextMock = {
settings: new SettingsMock(storage),
history: new HistoryMock(storage),
notifications: notificationServiceMock.createSetupContract(),
objectStorageClient: {} as any,
objectStorageClient: ({} as unknown) as ObjectStorageClient,
},
docLinkVersion: 'NA',
};

View file

@ -30,10 +30,10 @@ export interface ContextValue {
interface ContextProps {
value: ContextValue;
children: any;
children: JSX.Element;
}
const ServicesContext = createContext<ContextValue>(null as any);
const ServicesContext = createContext<ContextValue | null>(null);
export function ServicesContextProvider({ children, value }: ContextProps) {
useEffect(() => {
@ -46,8 +46,8 @@ export function ServicesContextProvider({ children, value }: ContextProps) {
export const useServicesContext = () => {
const context = useContext(ServicesContext);
if (context === undefined) {
if (context == null) {
throw new Error('useServicesContext must be used inside the ServicesContextProvider.');
}
return context;
return context!;
};

View file

@ -7,12 +7,10 @@
*/
import RowParser from '../../../lib/row_parser';
import { ESRequest } from '../../../types';
import { SenseEditor } from '../../models/sense_editor';
/**
* This function is considered legacy and should not be changed or updated before we have editor
* interfaces in place (it's using a customized version of Ace directly).
*/
export function restoreRequestFromHistory(editor: SenseEditor, req: any) {
export function restoreRequestFromHistory(editor: SenseEditor, req: ESRequest) {
const coreEditor = editor.getCoreEditor();
let pos = coreEditor.getCurrentPosition();
let prefix = '';

View file

@ -8,10 +8,11 @@
import { useCallback } from 'react';
import { instance as registry } from '../../contexts/editor_context/editor_registry';
import { ESRequest } from '../../../types';
import { restoreRequestFromHistory } from './restore_request_from_history';
export const useRestoreRequestFromHistory = () => {
return useCallback((req: any) => {
return useCallback((req: ESRequest) => {
const editor = registry.getInputEditor();
restoreRequestFromHistory(editor, req);
}, []);

View file

@ -8,19 +8,14 @@
import { extractWarningMessages } from '../../../lib/utils';
import { XJson } from '../../../../../es_ui_shared/public';
const { collapseLiteralStrings } = XJson;
// @ts-ignore
import * as es from '../../../lib/es/es';
import { BaseResponseType } from '../../../types';
export interface EsRequestArgs {
requests: any;
}
const { collapseLiteralStrings } = XJson;
export interface ESRequestObject {
path: string;
data: any;
method: string;
export interface EsRequestArgs {
requests: Array<{ url: string; method: string; data: string[] }>;
}
export interface ESResponseObject<V = unknown> {
@ -32,7 +27,7 @@ export interface ESResponseObject<V = unknown> {
}
export interface ESRequestResult<V = unknown> {
request: ESRequestObject;
request: { data: string; method: string; path: string };
response: ESResponseObject<V>;
}
@ -61,7 +56,7 @@ export function sendRequestToES(args: EsRequestArgs): Promise<ESRequestResult[]>
resolve(results);
return;
}
const req = requests.shift();
const req = requests.shift()!;
const esPath = req.url;
const esMethod = req.method;
let esData = collapseLiteralStrings(req.data.join('\n'));
@ -71,7 +66,7 @@ export function sendRequestToES(args: EsRequestArgs): Promise<ESRequestResult[]>
const startTime = Date.now();
es.send(esMethod, esPath, esData).always(
(dataOrjqXHR: any, textStatus: string, jqXhrORerrorThrown: any) => {
(dataOrjqXHR, textStatus: string, jqXhrORerrorThrown) => {
if (reqId !== CURRENT_REQ_ID) {
return;
}

View file

@ -10,7 +10,11 @@ import { SenseEditor } from '../../models/sense_editor';
import { getEndpointFromPosition } from '../../../lib/autocomplete/get_endpoint_from_position';
import { MetricsTracker } from '../../../types';
export const track = (requests: any[], editor: SenseEditor, trackUiMetric: MetricsTracker) => {
export const track = (
requests: Array<{ method: string }>,
editor: SenseEditor,
trackUiMetric: MetricsTracker
) => {
const coreEditor = editor.getCoreEditor();
// `getEndpointFromPosition` gets values from the server-side generated JSON files which
// are a combination of JS, automatically generated JSON and manual overrides. That means

View file

@ -26,8 +26,8 @@ import { useSendCurrentRequestToES } from './use_send_current_request_to_es';
describe('useSendCurrentRequestToES', () => {
let mockContextValue: ContextValue;
let dispatch: (...args: any[]) => void;
const contexts = ({ children }: { children?: any }) => (
let dispatch: (...args: unknown[]) => void;
const contexts = ({ children }: { children: JSX.Element }) => (
<ServicesContextProvider value={mockContextValue}>{children}</ServicesContextProvider>
);

View file

@ -9,12 +9,13 @@
import { useCallback } from 'react';
import { useEditorActionContext } from '../contexts/editor_context';
import { instance as registry } from '../contexts/editor_context/editor_registry';
import { SenseEditor } from '../models';
export const useSetInputEditor = () => {
const dispatch = useEditorActionContext();
return useCallback(
(editor: any) => {
(editor: SenseEditor) => {
dispatch({ type: 'setInputEditor', payload: editor });
registry.setInputEditor(editor);
},

View file

@ -8,7 +8,7 @@
import React from 'react';
import { render, unmountComponentAtNode } from 'react-dom';
import { HttpSetup, NotificationsSetup } from 'src/core/public';
import { HttpSetup, NotificationsSetup, I18nStart } from 'src/core/public';
import { ServicesContextProvider, EditorContextProvider, RequestContextProvider } from './contexts';
import { Main } from './containers';
import { createStorage, createHistory, createSettings } from '../services';
@ -20,7 +20,7 @@ import { createApi, createEsHostService } from './lib';
export interface BootDependencies {
http: HttpSetup;
docLinkVersion: string;
I18nContext: any;
I18nContext: I18nStart['Context'];
notifications: NotificationsSetup;
usageCollection?: UsageCollectionSetup;
element: HTMLElement;

View file

@ -13,7 +13,7 @@ import * as OutputMode from './mode/output';
import smartResize from './smart_resize';
export interface CustomAceEditor extends ace.Editor {
update: (text: string, mode?: any, cb?: () => void) => void;
update: (text: string, mode?: unknown, cb?: () => void) => void;
append: (text: string, foldPrevious?: boolean, cb?: () => void) => void;
}
@ -28,9 +28,9 @@ export function createReadOnlyAceEditor(element: HTMLElement): CustomAceEditor {
output.$blockScrolling = Infinity;
output.resize = smartResize(output);
output.update = (val: string, mode?: any, cb?: () => void) => {
output.update = (val: string, mode?: unknown, cb?: () => void) => {
if (typeof mode === 'function') {
cb = mode;
cb = mode as () => void;
mode = void 0;
}
@ -65,7 +65,7 @@ export function createReadOnlyAceEditor(element: HTMLElement): CustomAceEditor {
(function setupSession(session) {
session.setMode('ace/mode/text');
(session as any).setFoldStyle('markbeginend');
((session as unknown) as { setFoldStyle: (v: string) => void }).setFoldStyle('markbeginend');
session.setTabSize(2);
session.setUseWrapMode(true);
})(output.getSession());

View file

@ -13,7 +13,7 @@ jest.mock('./mode/worker', () => {
// @ts-ignore
window.Worker = function () {
this.postMessage = () => {};
(this as any).terminate = () => {};
((this as unknown) as { terminate: () => void }).terminate = () => {};
};
// @ts-ignore

View file

@ -31,8 +31,8 @@ const rangeToAceRange = ({ start, end }: Range) =>
new _AceRange(start.lineNumber - 1, start.column - 1, end.lineNumber - 1, end.column - 1);
export class LegacyCoreEditor implements CoreEditor {
private _aceOnPaste: any;
$actions: any;
private _aceOnPaste: Function;
$actions: JQuery<HTMLElement>;
resize: () => void;
constructor(private readonly editor: IAceEditor, actions: HTMLElement) {
@ -41,7 +41,9 @@ export class LegacyCoreEditor implements CoreEditor {
const session = this.editor.getSession();
session.setMode(new InputMode.Mode());
(session as any).setFoldStyle('markbeginend');
((session as unknown) as { setFoldStyle: (style: string) => void }).setFoldStyle(
'markbeginend'
);
session.setTabSize(2);
session.setUseWrapMode(true);
@ -72,7 +74,7 @@ export class LegacyCoreEditor implements CoreEditor {
// torn down, e.g. by closing the History tab, and we don't need to do anything further.
if (session.bgTokenizer) {
// Wait until the bgTokenizer is done running before executing the callback.
if ((session.bgTokenizer as any).running) {
if (((session.bgTokenizer as unknown) as { running: boolean }).running) {
setTimeout(check, checkInterval);
} else {
resolve();
@ -197,7 +199,7 @@ export class LegacyCoreEditor implements CoreEditor {
.addMarker(rangeToAceRange(range), 'ace_snippet-marker', 'fullLine', false);
}
removeMarker(ref: any) {
removeMarker(ref: number) {
this.editor.getSession().removeMarker(ref);
}
@ -222,8 +224,10 @@ export class LegacyCoreEditor implements CoreEditor {
}
isCompleterActive() {
// Secrets of the arcane here.
return Boolean((this.editor as any).completer && (this.editor as any).completer.activated);
return Boolean(
((this.editor as unknown) as { completer: { activated: unknown } }).completer &&
((this.editor as unknown) as { completer: { activated: unknown } }).completer.activated
);
}
private forceRetokenize() {
@ -250,7 +254,7 @@ export class LegacyCoreEditor implements CoreEditor {
this._aceOnPaste.call(this.editor, text);
}
private setActionsBar = (value?: any, topOrBottom: 'top' | 'bottom' = 'top') => {
private setActionsBar = (value: number | null, topOrBottom: 'top' | 'bottom' = 'top') => {
if (value === null) {
this.$actions.css('visibility', 'hidden');
} else {
@ -271,7 +275,7 @@ export class LegacyCoreEditor implements CoreEditor {
};
private hideActionsBar = () => {
this.setActionsBar();
this.setActionsBar(null);
};
execCommand(cmd: string) {
@ -295,7 +299,7 @@ export class LegacyCoreEditor implements CoreEditor {
});
}
legacyUpdateUI(range: any) {
legacyUpdateUI(range: Range) {
if (!this.$actions) {
return;
}
@ -360,14 +364,19 @@ export class LegacyCoreEditor implements CoreEditor {
ace.define(
'ace/autocomplete/text_completer',
['require', 'exports', 'module'],
function (require: any, exports: any) {
exports.getCompletions = function (
innerEditor: any,
session: any,
pos: any,
prefix: any,
callback: any
) {
function (
require: unknown,
exports: {
getCompletions: (
innerEditor: unknown,
session: unknown,
pos: unknown,
prefix: unknown,
callback: (e: null | Error, values: string[]) => void
) => void;
}
) {
exports.getCompletions = function (innerEditor, session, pos, prefix, callback) {
callback(null, []);
};
}
@ -387,7 +396,7 @@ export class LegacyCoreEditor implements CoreEditor {
DO_NOT_USE_2: IAceEditSession,
pos: { row: number; column: number },
prefix: string,
callback: (...args: any[]) => void
callback: (...args: unknown[]) => void
) => {
const position: Position = {
lineNumber: pos.row + 1,

View file

@ -7,9 +7,10 @@
*/
import { get, throttle } from 'lodash';
import type { Editor } from 'brace';
// eslint-disable-next-line import/no-default-export
export default function (editor: any) {
export default function (editor: Editor) {
const resize = editor.resize;
const throttledResize = throttle(() => {

View file

@ -25,7 +25,7 @@ export function detectCURL(text: string) {
export function parseCURL(text: string) {
let state = 'NONE';
const out = [];
let body: any[] = [];
let body: string[] = [];
let line = '';
const lines = text.trim().split('\n');
let matches;
@ -62,7 +62,7 @@ export function parseCURL(text: string) {
}
function unescapeLastBodyEl() {
const str = body.pop().replace(/\\([\\"'])/g, '$1');
const str = body.pop()!.replace(/\\([\\"'])/g, '$1');
body.push(str);
}

View file

@ -7,8 +7,10 @@
*/
import _ from 'lodash';
import RowParser from '../../../lib/row_parser';
import { XJson } from '../../../../../es_ui_shared/public';
import RowParser from '../../../lib/row_parser';
import * as utils from '../../../lib/utils';
// @ts-ignore
@ -16,22 +18,20 @@ import * as es from '../../../lib/es/es';
import { CoreEditor, Position, Range } from '../../../types';
import { createTokenIterator } from '../../factories';
import Autocomplete from '../../../lib/autocomplete/autocomplete';
import createAutocompleter from '../../../lib/autocomplete/autocomplete';
const { collapseLiteralStrings } = XJson;
export class SenseEditor {
currentReqRange: (Range & { markerRef: any }) | null;
parser: any;
currentReqRange: (Range & { markerRef: unknown }) | null;
parser: RowParser;
// @ts-ignore
private readonly autocomplete: any;
private readonly autocomplete: ReturnType<typeof createAutocompleter>;
constructor(private readonly coreEditor: CoreEditor) {
this.currentReqRange = null;
this.parser = new RowParser(this.coreEditor);
this.autocomplete = new (Autocomplete as any)({
this.autocomplete = createAutocompleter({
coreEditor,
parser: this.parser,
});
@ -114,7 +114,10 @@ export class SenseEditor {
return this.coreEditor.setValue(data, reTokenizeAll);
};
replaceRequestRange = (newRequest: any, requestRange: Range) => {
replaceRequestRange = (
newRequest: { method: string; url: string; data: string | string[] },
requestRange: Range
) => {
const text = utils.textFromRequest(newRequest);
if (requestRange) {
this.coreEditor.replaceRange(requestRange, text);
@ -207,12 +210,12 @@ export class SenseEditor {
const request: {
method: string;
data: string[];
url: string | null;
url: string;
range: Range;
} = {
method: '',
data: [],
url: null,
url: '',
range,
};
@ -284,7 +287,7 @@ export class SenseEditor {
return [];
}
const requests: any = [];
const requests: unknown[] = [];
let rangeStartCursor = expandedRange.start.lineNumber;
const endLineNumber = expandedRange.end.lineNumber;

View file

@ -9,8 +9,9 @@
import { Reducer } from 'react';
import { produce } from 'immer';
import { identity } from 'fp-ts/lib/function';
import { DevToolsSettings } from '../../services';
import { DevToolsSettings, DEFAULT_SETTINGS } from '../../services';
import { TextObject } from '../../../common/text_object';
import { SenseEditor } from '../models';
export interface Store {
ready: boolean;
@ -21,15 +22,15 @@ export interface Store {
export const initialValue: Store = produce<Store>(
{
ready: false,
settings: null as any,
settings: DEFAULT_SETTINGS,
currentTextObject: null,
},
identity
);
export type Action =
| { type: 'setInputEditor'; payload: any }
| { type: 'setCurrentTextObject'; payload: any }
| { type: 'setInputEditor'; payload: SenseEditor }
| { type: 'setCurrentTextObject'; payload: TextObject }
| { type: 'updateSettings'; payload: DevToolsSettings };
export const reducer: Reducer<Store, Action> = (state, action) =>

View file

@ -63,7 +63,7 @@ export class AceTokensProvider implements TokensProvider {
return null;
}
const tokens: TokenInfo[] = this.session.getTokens(lineNumber - 1) as any;
const tokens = (this.session.getTokens(lineNumber - 1) as unknown) as TokenInfo[];
if (!tokens || !tokens.length) {
// We are inside of the document but have no tokens for this line. Return an empty
// array to represent this empty line.
@ -74,7 +74,7 @@ export class AceTokensProvider implements TokensProvider {
}
getTokenAt(pos: Position): Token | null {
const tokens: TokenInfo[] = this.session.getTokens(pos.lineNumber - 1) as any;
const tokens = (this.session.getTokens(pos.lineNumber - 1) as unknown) as TokenInfo[];
if (tokens) {
return extractTokenFromAceTokenRow(pos.lineNumber, pos.column, tokens);
}

View file

@ -18,19 +18,21 @@ import {
// @ts-ignore
} from '../kb/kb';
import { createTokenIterator } from '../../application/factories';
import { Position, Token, Range, CoreEditor } from '../../types';
import type RowParser from '../row_parser';
import * as utils from '../utils';
// @ts-ignore
import { populateContext } from './engine';
import { AutoCompleteContext, ResultTerm } from './types';
// @ts-ignore
import { URL_PATH_END_MARKER } from './components/index';
import { createTokenIterator } from '../../application/factories';
import { Position, Token, Range, CoreEditor } from '../../types';
let lastEvaluatedToken: Token | null = null;
let lastEvaluatedToken: any = null;
function isUrlParamsToken(token: any) {
function isUrlParamsToken(token: { type: string } | null) {
switch ((token || {}).type) {
case 'url.param':
case 'url.equal':
@ -54,7 +56,7 @@ function isUrlParamsToken(token: any) {
export function getCurrentMethodAndTokenPaths(
editor: CoreEditor,
pos: Position,
parser: any,
parser: RowParser,
forceEndOfUrl?: boolean /* Flag for indicating whether we want to avoid early escape optimization. */
) {
const tokenIter = createTokenIterator({
@ -62,8 +64,8 @@ export function getCurrentMethodAndTokenPaths(
position: pos,
});
const startPos = pos;
let bodyTokenPath: any = [];
const ret: any = {};
let bodyTokenPath: string[] | null = [];
const ret: AutoCompleteContext = {};
const STATES = {
looking_for_key: 0, // looking for a key but without jumping over anything but white space and colon.
@ -210,7 +212,12 @@ export function getCurrentMethodAndTokenPaths(
ret.urlParamsTokenPath = null;
ret.requestStartRow = tokenIter.getCurrentPosition().lineNumber;
let curUrlPart: any;
let curUrlPart:
| null
| string
| Array<string | Record<string, unknown>>
| undefined
| Record<string, unknown>;
while (t && isUrlParamsToken(t)) {
switch (t.type) {
@ -240,7 +247,7 @@ export function getCurrentMethodAndTokenPaths(
if (!ret.urlParamsTokenPath) {
ret.urlParamsTokenPath = [];
}
ret.urlParamsTokenPath.unshift(curUrlPart || {});
ret.urlParamsTokenPath.unshift((curUrlPart as Record<string, string>) || {});
curUrlPart = null;
break;
}
@ -268,7 +275,7 @@ export function getCurrentMethodAndTokenPaths(
break;
case 'url.slash':
if (curUrlPart) {
ret.urlTokenPath.unshift(curUrlPart);
ret.urlTokenPath.unshift(curUrlPart as string);
curUrlPart = null;
}
break;
@ -277,7 +284,7 @@ export function getCurrentMethodAndTokenPaths(
}
if (curUrlPart) {
ret.urlTokenPath.unshift(curUrlPart);
ret.urlTokenPath.unshift(curUrlPart as string);
}
if (!ret.bodyTokenPath && !ret.urlParamsTokenPath) {
@ -297,9 +304,15 @@ export function getCurrentMethodAndTokenPaths(
}
// eslint-disable-next-line
export default function ({ coreEditor: editor, parser }: { coreEditor: CoreEditor; parser: any }) {
export default function ({
coreEditor: editor,
parser,
}: {
coreEditor: CoreEditor;
parser: RowParser;
}) {
function isUrlPathToken(token: Token | null) {
switch ((token || ({} as any)).type) {
switch ((token || ({} as Token)).type) {
case 'url.slash':
case 'url.comma':
case 'url.part':
@ -309,8 +322,12 @@ export default function ({ coreEditor: editor, parser }: { coreEditor: CoreEdito
}
}
function addMetaToTermsList(list: any, meta: any, template?: string) {
return _.map(list, function (t: any) {
function addMetaToTermsList(
list: unknown[],
meta: unknown,
template?: string
): Array<{ meta: unknown; template: unknown; name?: string }> {
return _.map(list, function (t) {
if (typeof t !== 'object') {
t = { name: t };
}
@ -318,8 +335,13 @@ export default function ({ coreEditor: editor, parser }: { coreEditor: CoreEdito
});
}
function applyTerm(term: any) {
const context = term.context;
function applyTerm(term: {
value?: string;
context?: AutoCompleteContext;
template?: { __raw: boolean; value: string };
insertValue?: string;
}) {
const context = term.context!;
// make sure we get up to date replacement info.
addReplacementInfoToContext(context, editor.getCurrentPosition(), term.insertValue);
@ -346,7 +368,7 @@ export default function ({ coreEditor: editor, parser }: { coreEditor: CoreEdito
} else {
indentedTemplateLines = utils.jsonToString(term.template, true).split('\n');
}
let currentIndentation = editor.getLineValue(context.rangeToReplace.start.lineNumber);
let currentIndentation = editor.getLineValue(context.rangeToReplace!.start.lineNumber);
currentIndentation = currentIndentation.match(/^\s*/)![0];
for (
let i = 1;
@ -374,8 +396,8 @@ export default function ({ coreEditor: editor, parser }: { coreEditor: CoreEdito
// disable listening to the changes we are making.
editor.off('changeSelection', editorChangeListener);
if (context.rangeToReplace.start.column !== context.rangeToReplace.end.column) {
editor.replace(context.rangeToReplace, valueToInsert);
if (context.rangeToReplace!.start.column !== context.rangeToReplace!.end.column) {
editor.replace(context.rangeToReplace!, valueToInsert);
} else {
editor.insert(valueToInsert);
}
@ -384,12 +406,12 @@ export default function ({ coreEditor: editor, parser }: { coreEditor: CoreEdito
// go back to see whether we have one of ( : { & [ do not require a comma. All the rest do.
let newPos = {
lineNumber: context.rangeToReplace.start.lineNumber,
lineNumber: context.rangeToReplace!.start.lineNumber,
column:
context.rangeToReplace.start.column +
context.rangeToReplace!.start.column +
termAsString.length +
context.prefixToAdd.length +
(templateInserted ? 0 : context.suffixToAdd.length),
context.prefixToAdd!.length +
(templateInserted ? 0 : context.suffixToAdd!.length),
};
const tokenIter = createTokenIterator({
@ -406,7 +428,7 @@ export default function ({ coreEditor: editor, parser }: { coreEditor: CoreEdito
break;
case 'punctuation.colon':
nonEmptyToken = parser.nextNonEmptyToken(tokenIter);
if ((nonEmptyToken || ({} as any)).type === 'paren.lparen') {
if ((nonEmptyToken || ({} as Token)).type === 'paren.lparen') {
nonEmptyToken = parser.nextNonEmptyToken(tokenIter);
newPos = tokenIter.getCurrentPosition();
if (nonEmptyToken && nonEmptyToken.value.indexOf('"') === 0) {
@ -429,7 +451,7 @@ export default function ({ coreEditor: editor, parser }: { coreEditor: CoreEdito
function getAutoCompleteContext(ctxEditor: CoreEditor, pos: Position) {
// deduces all the parameters need to position and insert the auto complete
const context: any = {
const context: AutoCompleteContext = {
autoCompleteSet: null, // instructions for what can be here
endpoint: null,
urlPath: null,
@ -501,7 +523,7 @@ export default function ({ coreEditor: editor, parser }: { coreEditor: CoreEdito
case 'whitespace':
t = parser.prevNonEmptyToken(tokenIter);
switch ((t || ({} as any)).type) {
switch ((t || ({} as Token)).type) {
case 'method':
// we moved one back
return 'path';
@ -552,7 +574,11 @@ export default function ({ coreEditor: editor, parser }: { coreEditor: CoreEdito
return null;
}
function addReplacementInfoToContext(context: any, pos: Position, replacingTerm?: any) {
function addReplacementInfoToContext(
context: AutoCompleteContext,
pos: Position,
replacingTerm?: unknown
) {
// extract the initial value, rangeToReplace & textBoxPosition
// Scenarios for current token:
@ -605,7 +631,7 @@ export default function ({ coreEditor: editor, parser }: { coreEditor: CoreEdito
default:
if (replacingTerm && context.updatedForToken.value === replacingTerm) {
context.rangeToReplace = {
start: { lineNumber: pos.lineNumber, column: anchorToken.column },
start: { lineNumber: pos.lineNumber, column: anchorToken.position.column },
end: {
lineNumber: pos.lineNumber,
column:
@ -645,7 +671,7 @@ export default function ({ coreEditor: editor, parser }: { coreEditor: CoreEdito
}
}
function addBodyPrefixSuffixToContext(context: any) {
function addBodyPrefixSuffixToContext(context: AutoCompleteContext) {
// Figure out what happens next to the token to see whether it needs trailing commas etc.
// Templates will be used if not destroying existing structure.
@ -680,9 +706,9 @@ export default function ({ coreEditor: editor, parser }: { coreEditor: CoreEdito
}
context.addTemplate = true;
// extend range to replace to include all up to token
context.rangeToReplace.end.lineNumber = tokenIter.getCurrentTokenLineNumber();
context.rangeToReplace.end.column =
tokenIter.getCurrentTokenColumn() + nonEmptyToken.value.length;
context.rangeToReplace!.end.lineNumber = tokenIter.getCurrentTokenLineNumber() as number;
context.rangeToReplace!.end.column =
(tokenIter.getCurrentTokenColumn() as number) + nonEmptyToken.value.length;
// move one more time to check if we need a trailing comma
nonEmptyToken = parser.nextNonEmptyToken(tokenIter);
@ -711,11 +737,11 @@ export default function ({ coreEditor: editor, parser }: { coreEditor: CoreEdito
insertingRelativeToToken = 0;
} else {
const pos = editor.getCurrentPosition();
if (pos.column === context.updatedForToken.position.column) {
if (pos.column === context.updatedForToken!.position.column) {
insertingRelativeToToken = -1;
} else if (
pos.column <
context.updatedForToken.position.column + context.updatedForToken.value.length
context.updatedForToken!.position.column + context.updatedForToken!.value.length
) {
insertingRelativeToToken = 0;
} else {
@ -743,12 +769,12 @@ export default function ({ coreEditor: editor, parser }: { coreEditor: CoreEdito
return context;
}
function addUrlParamsPrefixSuffixToContext(context: any) {
function addUrlParamsPrefixSuffixToContext(context: AutoCompleteContext) {
context.prefixToAdd = '';
context.suffixToAdd = '';
}
function addMethodPrefixSuffixToContext(context: any) {
function addMethodPrefixSuffixToContext(context: AutoCompleteContext) {
context.prefixToAdd = '';
context.suffixToAdd = '';
const tokenIter = createTokenIterator({ editor, position: editor.getCurrentPosition() });
@ -761,12 +787,12 @@ export default function ({ coreEditor: editor, parser }: { coreEditor: CoreEdito
}
}
function addPathPrefixSuffixToContext(context: any) {
function addPathPrefixSuffixToContext(context: AutoCompleteContext) {
context.prefixToAdd = '';
context.suffixToAdd = '';
}
function addMethodAutoCompleteSetToContext(context: any) {
function addMethodAutoCompleteSetToContext(context: AutoCompleteContext) {
context.autoCompleteSet = ['GET', 'PUT', 'POST', 'DELETE', 'HEAD'].map((m, i) => ({
name: m,
score: -i,
@ -774,7 +800,7 @@ export default function ({ coreEditor: editor, parser }: { coreEditor: CoreEdito
}));
}
function addPathAutoCompleteSetToContext(context: any, pos: Position) {
function addPathAutoCompleteSetToContext(context: AutoCompleteContext, pos: Position) {
const ret = getCurrentMethodAndTokenPaths(editor, pos, parser);
context.method = ret.method;
context.token = ret.token;
@ -783,10 +809,10 @@ export default function ({ coreEditor: editor, parser }: { coreEditor: CoreEdito
const components = getTopLevelUrlCompleteComponents(context.method);
populateContext(ret.urlTokenPath, context, editor, true, components);
context.autoCompleteSet = addMetaToTermsList(context.autoCompleteSet, 'endpoint');
context.autoCompleteSet = addMetaToTermsList(context.autoCompleteSet!, 'endpoint');
}
function addUrlParamsAutoCompleteSetToContext(context: any, pos: Position) {
function addUrlParamsAutoCompleteSetToContext(context: AutoCompleteContext, pos: Position) {
const ret = getCurrentMethodAndTokenPaths(editor, pos, parser);
context.method = ret.method;
context.otherTokenValues = ret.otherTokenValues;
@ -813,7 +839,7 @@ export default function ({ coreEditor: editor, parser }: { coreEditor: CoreEdito
// zero length tokenPath is true
return context;
}
let tokenPath: any[] = [];
let tokenPath: string[] = [];
const currentParam = ret.urlParamsTokenPath.pop();
if (currentParam) {
tokenPath = Object.keys(currentParam); // single key object
@ -830,7 +856,7 @@ export default function ({ coreEditor: editor, parser }: { coreEditor: CoreEdito
return context;
}
function addBodyAutoCompleteSetToContext(context: any, pos: Position) {
function addBodyAutoCompleteSetToContext(context: AutoCompleteContext, pos: Position) {
const ret = getCurrentMethodAndTokenPaths(editor, pos, parser);
context.method = ret.method;
context.otherTokenValues = ret.otherTokenValues;
@ -859,7 +885,7 @@ export default function ({ coreEditor: editor, parser }: { coreEditor: CoreEdito
// needed for scope linking + global term resolving
context.endpointComponentResolver = getEndpointBodyCompleteComponents;
context.globalComponentResolver = getGlobalAutocompleteComponents;
let components;
let components: unknown;
if (context.endpoint) {
components = context.endpoint.bodyAutocompleteRootComponents;
} else {
@ -935,15 +961,19 @@ export default function ({ coreEditor: editor, parser }: { coreEditor: CoreEdito
}
}
function getCompletions(position: Position, prefix: string, callback: (...args: any[]) => void) {
function getCompletions(
position: Position,
prefix: string,
callback: (e: Error | null, result: ResultTerm[] | null) => void
) {
try {
const context = getAutoCompleteContext(editor, position);
if (!context) {
callback(null, []);
} else {
const terms = _.map(
context.autoCompleteSet.filter((term: any) => Boolean(term) && term.name != null),
function (term: any) {
context.autoCompleteSet!.filter((term) => Boolean(term) && term.name != null),
function (term) {
if (typeof term !== 'object') {
term = {
name: term,
@ -951,7 +981,13 @@ export default function ({ coreEditor: editor, parser }: { coreEditor: CoreEdito
} else {
term = _.clone(term);
}
const defaults: any = {
const defaults: {
value?: string;
meta: string;
score: number;
context: AutoCompleteContext;
completer?: { insertMatch: (v: unknown) => void };
} = {
value: term.name,
meta: 'API',
score: 0,
@ -969,7 +1005,10 @@ export default function ({ coreEditor: editor, parser }: { coreEditor: CoreEdito
}
);
terms.sort(function (t1: any, t2: any) {
terms.sort(function (
t1: { score: number; name?: string },
t2: { score: number; name?: string }
) {
/* score sorts from high to low */
if (t1.score > t2.score) {
return -1;
@ -978,7 +1017,7 @@ export default function ({ coreEditor: editor, parser }: { coreEditor: CoreEdito
return 1;
}
/* names sort from low to high */
if (t1.name < t2.name) {
if (t1.name! < t2.name!) {
return -1;
}
if (t1.name === t2.name) {
@ -989,7 +1028,7 @@ export default function ({ coreEditor: editor, parser }: { coreEditor: CoreEdito
callback(
null,
_.map(terms, function (t: any, i: any) {
_.map(terms, function (t, i) {
t.insertValue = t.insertValue || t.value;
t.value = '' + t.value; // normalize to strings
t.score = -i;
@ -1010,8 +1049,13 @@ export default function ({ coreEditor: editor, parser }: { coreEditor: CoreEdito
getCompletions,
// TODO: This needs to be cleaned up
_test: {
getCompletions: (_editor: any, _editSession: any, pos: any, prefix: any, callback: any) =>
getCompletions(pos, prefix, callback),
getCompletions: (
_editor: unknown,
_editSession: unknown,
pos: Position,
prefix: string,
callback: (e: Error | null, result: ResultTerm[] | null) => void
) => getCompletions(pos, prefix, callback),
addReplacementInfoToContext,
addChangeListener: () => editor.on('changeSelection', editorChangeListener),
removeChangeListener: () => editor.off('changeSelection', editorChangeListener),

View file

@ -11,7 +11,7 @@ import { ConstantComponent } from './constant_component';
export class FullRequestComponent extends ConstantComponent {
private readonly name: string;
constructor(name: string, parent: any, private readonly template: string) {
constructor(name: string, parent: unknown, private readonly template: string) {
super(name, parent);
this.name = name;
}

View file

@ -8,13 +8,14 @@
import { CoreEditor, Position } from '../../types';
import { getCurrentMethodAndTokenPaths } from './autocomplete';
import type RowParser from '../row_parser';
// @ts-ignore
import { getTopLevelUrlCompleteComponents } from '../kb/kb';
// @ts-ignore
import { populateContext } from './engine';
export function getEndpointFromPosition(editor: CoreEditor, pos: Position, parser: any) {
export function getEndpointFromPosition(editor: CoreEditor, pos: Position, parser: RowParser) {
const lineValue = editor.getLineValue(pos.lineNumber);
const context = {
...getCurrentMethodAndTokenPaths(

View file

@ -0,0 +1,61 @@
/*
* 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 { CoreEditor, Range, Token } from '../../types';
export interface ResultTerm {
context?: AutoCompleteContext;
insertValue?: string;
name?: string;
value?: string;
}
export interface AutoCompleteContext {
autoCompleteSet?: null | ResultTerm[];
endpoint?: null | {
paramsAutocomplete: {
getTopLevelComponents: (method?: string | null) => unknown;
};
bodyAutocompleteRootComponents: unknown;
id?: string;
documentation?: string;
};
urlPath?: null | unknown;
urlParamsTokenPath?: Array<Record<string, string>> | null;
method?: string | null;
token?: Token;
activeScheme?: unknown;
replacingToken?: boolean;
rangeToReplace?: Range;
autoCompleteType?: null | string;
editor?: CoreEditor;
/**
* The tokenized user input that prompted the current autocomplete at the cursor. This can be out of sync with
* the input that is currently being displayed in the editor.
*/
createdWithToken?: Token | null;
/**
* The tokenized user input that is currently being displayed at the cursor in the editor when the user accepted
* the autocomplete suggestion.
*/
updatedForToken?: Token | null;
addTemplate?: unknown;
prefixToAdd?: string;
suffixToAdd?: string;
textBoxPosition?: { lineNumber: number; column: number };
urlTokenPath?: string[];
otherTokenValues?: string;
requestStartRow?: number | null;
bodyTokenPath?: string[] | null;
endpointComponentResolver?: unknown;
globalComponentResolver?: unknown;
documentation?: string;
}

View file

@ -19,7 +19,7 @@ export function getVersion() {
return esVersion;
}
export function getContentType(body: any) {
export function getContentType(body: unknown) {
if (!body) return;
return 'application/json';
}
@ -27,7 +27,7 @@ export function getContentType(body: any) {
export function send(
method: string,
path: string,
data: any,
data: string | object,
{ asSystemRequest }: SendOptions = {}
) {
const wrappedDfd = $.Deferred();
@ -47,10 +47,10 @@ export function send(
};
$.ajax(options).then(
(responseData: any, textStatus: string, jqXHR: any) => {
(responseData, textStatus: string, jqXHR: unknown) => {
wrappedDfd.resolveWith({}, [responseData, textStatus, jqXHR]);
},
((jqXHR: any, textStatus: string, errorThrown: Error) => {
((jqXHR: { status: number; responseText: string }, textStatus: string, errorThrown: Error) => {
if (jqXHR.status === 0) {
jqXHR.responseText =
"\n\nFailed to connect to Console's backend.\nPlease check the Kibana server is up and running";

View file

@ -75,7 +75,7 @@ export default class RowParser {
return MODE.REQUEST_START;
}
rowPredicate(lineNumber: number | undefined, editor: CoreEditor, value: any) {
rowPredicate(lineNumber: number | undefined, editor: CoreEditor, value: number) {
const mode = this.getRowParseMode(lineNumber);
// eslint-disable-next-line no-bitwise
return (mode & value) > 0;

View file

@ -15,7 +15,7 @@ const mockTokensProviderFactory = (tokenMtx: Token[][]): TokensProvider => {
return tokenMtx[lineNumber - 1] || null;
},
getTokenAt(pos: Position): Token | null {
return null as any;
return null;
},
};
};

View file

@ -11,7 +11,7 @@ import { XJson } from '../../../../es_ui_shared/public';
const { collapseLiteralStrings, expandLiteralStrings } = XJson;
export function textFromRequest(request: any) {
export function textFromRequest(request: { method: string; url: string; data: string | string[] }) {
let data = request.data;
if (typeof data !== 'string') {
data = data.join('\n');
@ -19,7 +19,7 @@ export function textFromRequest(request: any) {
return request.method + ' ' + request.url + '\n' + data;
}
export function jsonToString(data: any, indent: boolean) {
export function jsonToString(data: object, indent: boolean) {
return JSON.stringify(data, null, indent ? 2 : 0);
}

View file

@ -35,12 +35,12 @@ export class History {
// be triggered from different places in the app. The alternative would be to store
// this in state so that we hook into the React model, but it would require loading history
// every time the application starts even if a user is not going to view history.
change(listener: (reqs: any[]) => void) {
change(listener: (reqs: unknown[]) => void) {
const subscription = this.changeEmitter.subscribe(listener);
return () => subscription.unsubscribe();
}
addToHistory(endpoint: string, method: string, data: any) {
addToHistory(endpoint: string, method: string, data?: string) {
const keys = this.getHistoryKeys();
keys.splice(0, MAX_NUMBER_OF_HISTORY_ITEMS); // only maintain most recent X;
keys.forEach((key) => {
@ -59,7 +59,7 @@ export class History {
this.changeEmitter.next(this.getHistory());
}
updateCurrentState(content: any) {
updateCurrentState(content: string) {
const timestamp = new Date().getTime();
this.storage.set('editor_state', {
time: timestamp,

View file

@ -8,4 +8,4 @@
export { createHistory, History } from './history';
export { createStorage, Storage, StorageKeys } from './storage';
export { createSettings, Settings, DevToolsSettings } from './settings';
export { createSettings, Settings, DevToolsSettings, DEFAULT_SETTINGS } from './settings';

View file

@ -8,6 +8,14 @@
import { Storage } from './index';
export const DEFAULT_SETTINGS = Object.freeze({
fontSize: 14,
polling: true,
tripleQuotes: true,
wrapMode: true,
autocomplete: Object.freeze({ fields: true, indices: true, templates: true }),
});
export interface DevToolsSettings {
fontSize: number;
wrapMode: boolean;
@ -24,50 +32,46 @@ export class Settings {
constructor(private readonly storage: Storage) {}
getFontSize() {
return this.storage.get('font_size', 14);
return this.storage.get('font_size', DEFAULT_SETTINGS.fontSize);
}
setFontSize(size: any) {
setFontSize(size: number) {
this.storage.set('font_size', size);
return true;
}
getWrapMode() {
return this.storage.get('wrap_mode', true);
return this.storage.get('wrap_mode', DEFAULT_SETTINGS.wrapMode);
}
setWrapMode(mode: any) {
setWrapMode(mode: boolean) {
this.storage.set('wrap_mode', mode);
return true;
}
setTripleQuotes(tripleQuotes: any) {
setTripleQuotes(tripleQuotes: boolean) {
this.storage.set('triple_quotes', tripleQuotes);
return true;
}
getTripleQuotes() {
return this.storage.get('triple_quotes', true);
return this.storage.get('triple_quotes', DEFAULT_SETTINGS.tripleQuotes);
}
getAutocomplete() {
return this.storage.get('autocomplete_settings', {
fields: true,
indices: true,
templates: true,
});
return this.storage.get('autocomplete_settings', DEFAULT_SETTINGS.autocomplete);
}
setAutocomplete(settings: any) {
setAutocomplete(settings: object) {
this.storage.set('autocomplete_settings', settings);
return true;
}
getPolling() {
return this.storage.get('console_polling', true);
return this.storage.get('console_polling', DEFAULT_SETTINGS.polling);
}
setPolling(polling: any) {
setPolling(polling: boolean) {
this.storage.set('console_polling', polling);
return true;
}

View file

@ -17,11 +17,11 @@ export enum StorageKeys {
export class Storage {
constructor(private readonly engine: IStorageEngine, private readonly prefix: string) {}
encode(val: any) {
encode(val: unknown) {
return JSON.stringify(val);
}
decode(val: any) {
decode(val: string | null) {
if (typeof val === 'string') {
return JSON.parse(val);
}
@ -37,7 +37,7 @@ export class Storage {
}
}
set(key: string, val: any) {
set(key: string, val: unknown) {
this.engine.setItem(this.encodeKey(key), this.encode(val));
return val;
}

View file

@ -11,6 +11,12 @@ export interface MetricsTracker {
load: (eventName: string) => void;
}
export interface ESRequest {
method: string;
endpoint: string;
data?: string;
}
export type BaseResponseType =
| 'application/json'
| 'text/csv'

View file

@ -21,7 +21,7 @@ export type EditorEvent =
export type AutoCompleterFunction = (
pos: Position,
prefix: string,
callback: (...args: any[]) => void
callback: (...args: unknown[]) => void
) => void;
export interface Position {
@ -235,7 +235,7 @@ export interface CoreEditor {
* have this backdoor to update UI in response to request range changes, for example, as the user
* moves the cursor around
*/
legacyUpdateUI(opts: any): void;
legacyUpdateUI(opts: unknown): void;
/**
* A method to for the editor to resize, useful when, for instance, window size changes.
@ -250,7 +250,11 @@ export interface CoreEditor {
/**
* Register a keyboard shortcut and provide a function to be called.
*/
registerKeyboardShortcut(opts: { keys: any; fn: () => void; name: string }): void;
registerKeyboardShortcut(opts: {
keys: string | { win?: string; mac?: string };
fn: () => void;
name: string;
}): void;
/**
* Register a completions function that will be called when the editor

View file

@ -14,7 +14,7 @@ import url from 'url';
import { ESConfigForProxy } from '../types';
const createAgent = (legacyConfig: ESConfigForProxy) => {
const target = url.parse(_.head(legacyConfig.hosts) as any);
const target = url.parse(_.head(legacyConfig.hosts)!);
if (!/^https/.test(target.protocol || '')) return new http.Agent();
const agentOptions: https.AgentOptions = {};
@ -28,7 +28,7 @@ const createAgent = (legacyConfig: ESConfigForProxy) => {
agentOptions.rejectUnauthorized = true;
// by default, NodeJS is checking the server identify
agentOptions.checkServerIdentity = _.noop as any;
agentOptions.checkServerIdentity = (_.noop as unknown) as https.AgentOptions['checkServerIdentity'];
break;
case 'full':
agentOptions.rejectUnauthorized = true;

View file

@ -12,6 +12,17 @@ import { Agent as HttpsAgent, AgentOptions } from 'https';
import { WildcardMatcher } from './wildcard_matcher';
interface Config {
match: {
protocol: string;
host: string;
port: string;
path: string;
};
ssl?: { verify?: boolean; ca?: string; cert?: string; key?: string };
timeout: number;
}
export class ProxyConfig {
// @ts-ignore
private id: string;
@ -26,9 +37,9 @@ export class ProxyConfig {
private readonly sslAgent?: HttpsAgent;
private verifySsl: any;
private verifySsl: undefined | boolean;
constructor(config: { match: any; timeout: number }) {
constructor(config: Config) {
config = {
...config,
};
@ -61,8 +72,8 @@ export class ProxyConfig {
this.sslAgent = this._makeSslAgent(config);
}
_makeSslAgent(config: any) {
const ssl = config.ssl || {};
_makeSslAgent(config: Config) {
const ssl: Config['ssl'] = config.ssl || {};
this.verifySsl = ssl.verify;
const sslAgentOpts: AgentOptions = {

View file

@ -6,6 +6,7 @@
* Side Public License, v 1.
*/
import type { Agent } from 'http';
import { defaultsDeep } from 'lodash';
import { parse as parseUrl } from 'url';
@ -14,7 +15,12 @@ import { ProxyConfig } from './proxy_config';
export class ProxyConfigCollection {
private configs: ProxyConfig[];
constructor(configs: Array<{ match: any; timeout: number }> = []) {
constructor(
configs: Array<{
match: { protocol: string; host: string; port: string; path: string };
timeout: number;
}> = []
) {
this.configs = configs.map((settings) => new ProxyConfig(settings));
}
@ -22,7 +28,7 @@ export class ProxyConfigCollection {
return Boolean(this.configs.length);
}
configForUri(uri: string): object {
configForUri(uri: string): { agent: Agent; timeout: number } {
const parsedUri = parseUrl(uri);
const settings = this.configs.map((config) => config.getForParsedUri(parsedUri as any));
return defaultsDeep({}, ...settings);

View file

@ -55,7 +55,7 @@ describe(`Console's send request`, () => {
fakeRequest = {
abort: sinon.stub(),
on() {},
once(event: string, fn: any) {
once(event: string, fn: (v: string) => void) {
if (event === 'response') {
return fn('done');
}

View file

@ -46,9 +46,9 @@ export const proxyRequest = ({
const client = uri.protocol === 'https:' ? https : http;
let resolved = false;
let resolve: any;
let reject: any;
const reqPromise = new Promise<http.ServerResponse>((res, rej) => {
let resolve: (res: http.IncomingMessage) => void;
let reject: (res: unknown) => void;
const reqPromise = new Promise<http.IncomingMessage>((res, rej) => {
resolve = res;
reject = rej;
});

View file

@ -5,7 +5,7 @@
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import { IKibanaResponse } from 'src/core/server';
import { getProxyRouteHandlerDeps } from './mocks';
import { Readable } from 'stream';
@ -16,10 +16,14 @@ import * as requestModule from '../../../../lib/proxy_request';
import { createResponseStub } from './stubs';
describe('Console Proxy Route', () => {
let request: any;
let request: (
method: string,
path: string,
response?: string
) => Promise<IKibanaResponse> | IKibanaResponse;
beforeEach(() => {
request = (method: string, path: string, response: string) => {
request = (method, path, response) => {
(requestModule.proxyRequest as jest.Mock).mockResolvedValue(createResponseStub(response));
const handler = createHandler(getProxyRouteHandlerDeps({}));

View file

@ -41,7 +41,7 @@ function toURL(base: string, path: string) {
}
function filterHeaders(originalHeaders: object, headersToKeep: string[]): object {
const normalizeHeader = function (header: any) {
const normalizeHeader = function (header: string) {
if (!header) {
return '';
}
@ -68,7 +68,7 @@ function getRequestConfig(
return {
...proxyConfigCollection.configForUri(uri),
headers: newHeaders,
} as any;
};
}
return {
@ -81,7 +81,7 @@ function getProxyHeaders(req: KibanaRequest) {
const headers = Object.create(null);
// Scope this proto-unsafe functionality to where it is being used.
function extendCommaList(obj: Record<string, any>, property: string, value: any) {
function extendCommaList(obj: Record<string, any>, property: string, value: string) {
obj[property] = (obj[property] ? obj[property] + ',' : '') + value;
}
@ -142,7 +142,7 @@ export const createHandler = ({
};
esIncomingMessage = await proxyRequest({
method: method.toLowerCase() as any,
method: method.toLowerCase() as 'get' | 'post' | 'put' | 'delete' | 'patch' | 'head',
headers: requestHeaders,
uri,
timeout,

View file

@ -6,6 +6,7 @@
* Side Public License, v 1.
*/
import type { IKibanaResponse } from 'src/core/server';
import { kibanaResponseFactory } from '../../../../../../../core/server';
import { getProxyRouteHandlerDeps } from './mocks';
import { createResponseStub } from './stubs';
@ -14,7 +15,7 @@ import * as requestModule from '../../../../lib/proxy_request';
import { createHandler } from './create_handler';
describe('Console Proxy Route', () => {
let request: any;
let request: (method: string, path: string) => Promise<IKibanaResponse> | IKibanaResponse;
beforeEach(() => {
(requestModule.proxyRequest as jest.Mock).mockResolvedValue(createResponseStub('foo'));

View file

@ -9,8 +9,12 @@
import { IncomingMessage } from 'http';
import { Readable } from 'stream';
export function createResponseStub(response: any) {
const resp: any = new Readable({
export function createResponseStub(response?: string) {
const resp: Readable & {
statusCode?: number;
statusMessage?: string;
headers?: Record<string, unknown>;
} = new Readable({
read() {
if (response) {
this.push(response);

View file

@ -15,6 +15,15 @@ import { jsSpecLoaders } from '../lib';
const PATH_TO_OSS_JSON_SPEC = resolve(__dirname, '../lib/spec_definitions/json');
interface EndpointDescription {
methods?: string[];
patterns?: string | string[];
url_params?: Record<string, unknown>;
data_autocomplete_rules?: Record<string, unknown>;
url_components?: Record<string, unknown>;
priority?: number;
}
export class SpecDefinitionsService {
private readonly name = 'es';
@ -24,16 +33,23 @@ export class SpecDefinitionsService {
private hasLoadedSpec = false;
public addGlobalAutocompleteRules(parentNode: string, rules: any) {
public addGlobalAutocompleteRules(parentNode: string, rules: unknown) {
this.globalRules[parentNode] = rules;
}
public addEndpointDescription(endpoint: string, description: any = {}) {
let copiedDescription: any = {};
public addEndpointDescription(endpoint: string, description: EndpointDescription = {}) {
let copiedDescription: { patterns?: string; url_params?: Record<string, unknown> } = {};
if (this.endpoints[endpoint]) {
copiedDescription = { ...this.endpoints[endpoint] };
}
let urlParamsDef: any;
let urlParamsDef:
| {
ignore_unavailable?: string;
allow_no_indices?: string;
expand_wildcards?: string[];
}
| undefined;
_.each(description.patterns || [], function (p) {
if (p.indexOf('{indices}') >= 0) {
urlParamsDef = urlParamsDef || {};
@ -70,7 +86,7 @@ export class SpecDefinitionsService {
this.extensionSpecFilePaths.push(path);
}
public addProcessorDefinition(processor: any) {
public addProcessorDefinition(processor: unknown) {
if (!this.hasLoadedSpec) {
throw new Error(
'Cannot add a processor definition because spec definitions have not loaded!'
@ -104,11 +120,13 @@ export class SpecDefinitionsService {
return generatedFiles.reduce((acc, file) => {
const overrideFile = overrideFiles.find((f) => basename(f) === basename(file));
const loadedSpec = JSON.parse(readFileSync(file, 'utf8'));
const loadedSpec: Record<string, EndpointDescription> = JSON.parse(
readFileSync(file, 'utf8')
);
if (overrideFile) {
merge(loadedSpec, JSON.parse(readFileSync(overrideFile, 'utf8')));
}
const spec: any = {};
const spec: Record<string, EndpointDescription> = {};
Object.entries(loadedSpec).forEach(([key, value]) => {
if (acc[key]) {
// add time to remove key collision
@ -119,7 +137,7 @@ export class SpecDefinitionsService {
});
return { ...acc, ...spec };
}, {} as any);
}, {} as Record<string, EndpointDescription>);
}
private loadJsonSpec() {