mirror of
https://github.com/elastic/kibana.git
synced 2025-04-25 02:09:32 -04:00
[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:
parent
6295ae71b5
commit
edfdb78957
52 changed files with 402 additions and 219 deletions
|
@ -16,7 +16,7 @@ import { i18n } from '@kbn/i18n';
|
||||||
interface Props {
|
interface Props {
|
||||||
getCurl: () => Promise<string>;
|
getCurl: () => Promise<string>;
|
||||||
getDocumentation: () => Promise<string | null>;
|
getDocumentation: () => Promise<string | null>;
|
||||||
autoIndent: (ev?: React.MouseEvent) => void;
|
autoIndent: (ev: React.MouseEvent) => void;
|
||||||
addNotification?: (opts: { title: string }) => void;
|
addNotification?: (opts: { title: string }) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,8 +84,7 @@ export class ConsoleMenu extends Component<Props, State> {
|
||||||
window.open(documentation, '_blank');
|
window.open(documentation, '_blank');
|
||||||
};
|
};
|
||||||
|
|
||||||
// Using `any` here per this issue: https://github.com/elastic/eui/issues/2265
|
autoIndent = (event: React.MouseEvent) => {
|
||||||
autoIndent: any = (event: React.MouseEvent) => {
|
|
||||||
this.closePopover();
|
this.closePopover();
|
||||||
this.props.autoIndent(event);
|
this.props.autoIndent(event);
|
||||||
};
|
};
|
||||||
|
|
|
@ -32,7 +32,7 @@ export type AutocompleteOptions = 'fields' | 'indices' | 'templates';
|
||||||
interface Props {
|
interface Props {
|
||||||
onSaveSettings: (newSettings: DevToolsSettings) => void;
|
onSaveSettings: (newSettings: DevToolsSettings) => void;
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
refreshAutocompleteSettings: (selectedSettings: any) => void;
|
refreshAutocompleteSettings: (selectedSettings: DevToolsSettings['autocomplete']) => void;
|
||||||
settings: DevToolsSettings;
|
settings: DevToolsSettings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -233,7 +233,7 @@ export function DevToolsSettingsModal(props: Props) {
|
||||||
return rest;
|
return rest;
|
||||||
})}
|
})}
|
||||||
idToSelectedMap={checkboxIdToSelectedMap}
|
idToSelectedMap={checkboxIdToSelectedMap}
|
||||||
onChange={(e: any) => {
|
onChange={(e: unknown) => {
|
||||||
onAutocompleteChange(e as AutocompleteOptions);
|
onAutocompleteChange(e as AutocompleteOptions);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -53,7 +53,7 @@ export function ConsoleHistory({ close }: Props) {
|
||||||
const selectedReq = useRef<any>(null);
|
const selectedReq = useRef<any>(null);
|
||||||
|
|
||||||
const describeReq = useMemo(() => {
|
const describeReq = useMemo(() => {
|
||||||
const _describeReq = (req: any) => {
|
const _describeReq = (req: { endpoint: string; time: string }) => {
|
||||||
const endpoint = req.endpoint;
|
const endpoint = req.endpoint;
|
||||||
const date = moment(req.time);
|
const date = moment(req.time);
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@ import { applyCurrentSettings } from '../editor/legacy/console_editor/apply_edit
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
settings: DevToolsSettings;
|
settings: DevToolsSettings;
|
||||||
req: any | null;
|
req: { method: string; endpoint: string; data: string; time: string } | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function HistoryViewer({ settings, req }: Props) {
|
export function HistoryViewer({ settings, req }: Props) {
|
||||||
|
|
|
@ -14,7 +14,7 @@ export function applyCurrentSettings(
|
||||||
editor: CoreEditor | CustomAceEditor,
|
editor: CoreEditor | CustomAceEditor,
|
||||||
settings: DevToolsSettings
|
settings: DevToolsSettings
|
||||||
) {
|
) {
|
||||||
if ((editor as any).setStyles) {
|
if ((editor as { setStyles?: Function }).setStyles) {
|
||||||
(editor as CoreEditor).setStyles({
|
(editor as CoreEditor).setStyles({
|
||||||
wrapLines: settings.wrapMode,
|
wrapLines: settings.wrapMode,
|
||||||
fontSize: settings.fontSize + 'px',
|
fontSize: settings.fontSize + 'px',
|
||||||
|
|
|
@ -27,7 +27,7 @@ import {
|
||||||
// Mocked functions
|
// Mocked functions
|
||||||
import { sendRequestToES } from '../../../../hooks/use_send_current_request_to_es/send_request_to_es';
|
import { sendRequestToES } from '../../../../hooks/use_send_current_request_to_es/send_request_to_es';
|
||||||
import { getEndpointFromPosition } from '../../../../../lib/autocomplete/get_endpoint_from_position';
|
import { getEndpointFromPosition } from '../../../../../lib/autocomplete/get_endpoint_from_position';
|
||||||
|
import type { DevToolsSettings } from '../../../../../services';
|
||||||
import * as consoleMenuActions from '../console_menu_actions';
|
import * as consoleMenuActions from '../console_menu_actions';
|
||||||
import { Editor } from './editor';
|
import { Editor } from './editor';
|
||||||
|
|
||||||
|
@ -40,7 +40,7 @@ describe('Legacy (Ace) Console Editor Component Smoke Test', () => {
|
||||||
<I18nProvider>
|
<I18nProvider>
|
||||||
<ServicesContextProvider value={mockedAppContextValue}>
|
<ServicesContextProvider value={mockedAppContextValue}>
|
||||||
<RequestContextProvider>
|
<RequestContextProvider>
|
||||||
<EditorContextProvider settings={{} as any}>
|
<EditorContextProvider settings={({} as unknown) as DevToolsSettings}>
|
||||||
<Editor initialTextValue="" />
|
<Editor initialTextValue="" />
|
||||||
</EditorContextProvider>
|
</EditorContextProvider>
|
||||||
</RequestContextProvider>
|
</RequestContextProvider>
|
||||||
|
|
|
@ -229,7 +229,7 @@ function EditorUI({ initialTextValue }: EditorProps) {
|
||||||
getDocumentation={() => {
|
getDocumentation={() => {
|
||||||
return getDocumentation(editorInstanceRef.current!, docLinkVersion);
|
return getDocumentation(editorInstanceRef.current!, docLinkVersion);
|
||||||
}}
|
}}
|
||||||
autoIndent={(event: any) => {
|
autoIndent={(event) => {
|
||||||
autoIndent(editorInstanceRef.current!, event);
|
autoIndent(editorInstanceRef.current!, event);
|
||||||
}}
|
}}
|
||||||
addNotification={({ title }) => notifications.toasts.add({ title })}
|
addNotification={({ title }) => notifications.toasts.add({ title })}
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
import { getEndpointFromPosition } from '../../../../lib/autocomplete/get_endpoint_from_position';
|
import { getEndpointFromPosition } from '../../../../lib/autocomplete/get_endpoint_from_position';
|
||||||
import { SenseEditor } from '../../../models/sense_editor';
|
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();
|
event.preventDefault();
|
||||||
await editor.autoIndent();
|
await editor.autoIndent();
|
||||||
editor.getCoreEditor().getContainer().focus();
|
editor.getCoreEditor().getContainer().focus();
|
||||||
|
|
|
@ -15,14 +15,20 @@ import { retrieveAutoCompleteInfo } from '../../lib/mappings/mappings';
|
||||||
import { useServicesContext, useEditorActionContext } from '../contexts';
|
import { useServicesContext, useEditorActionContext } from '../contexts';
|
||||||
import { DevToolsSettings, Settings as SettingsService } from '../../services';
|
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) => {
|
return Object.keys(newSettings.autocomplete).filter((key) => {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
return prevSettings.autocomplete[key] !== newSettings.autocomplete[key];
|
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);
|
retrieveAutoCompleteInfo(settings, selectedSettings);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -44,12 +50,12 @@ const fetchAutocompleteSettingsIfNeeded = (
|
||||||
if (isSettingsChanged) {
|
if (isSettingsChanged) {
|
||||||
// If the user has changed one of the autocomplete settings, then we'll fetch just the
|
// If the user has changed one of the autocomplete settings, then we'll fetch just the
|
||||||
// ones which have changed.
|
// ones which have changed.
|
||||||
const changedSettings: any = autocompleteDiff.reduce(
|
const changedSettings: DevToolsSettings['autocomplete'] = autocompleteDiff.reduce(
|
||||||
(changedSettingsAccum: any, setting: string): any => {
|
(changedSettingsAccum, setting) => {
|
||||||
changedSettingsAccum[setting] = newSettings.autocomplete[setting as AutocompleteOptions];
|
changedSettingsAccum[setting] = newSettings.autocomplete[setting];
|
||||||
return changedSettingsAccum;
|
return changedSettingsAccum;
|
||||||
},
|
},
|
||||||
{}
|
{} as DevToolsSettings['autocomplete']
|
||||||
);
|
);
|
||||||
retrieveAutoCompleteInfo(settings, changedSettings);
|
retrieveAutoCompleteInfo(settings, changedSettings);
|
||||||
} else if (isPollingChanged && newSettings.polling) {
|
} else if (isPollingChanged && newSettings.polling) {
|
||||||
|
@ -89,7 +95,7 @@ export function Settings({ onClose }: Props) {
|
||||||
<DevToolsSettingsModal
|
<DevToolsSettingsModal
|
||||||
onClose={onClose}
|
onClose={onClose}
|
||||||
onSaveSettings={onSaveSettings}
|
onSaveSettings={onSaveSettings}
|
||||||
refreshAutocompleteSettings={(selectedSettings: any) =>
|
refreshAutocompleteSettings={(selectedSettings) =>
|
||||||
refreshAutocompleteSettings(settings, selectedSettings)
|
refreshAutocompleteSettings(settings, selectedSettings)
|
||||||
}
|
}
|
||||||
settings={settings.toJSON()}
|
settings={settings.toJSON()}
|
||||||
|
|
|
@ -11,11 +11,11 @@ import * as editor from '../../stores/editor';
|
||||||
import { DevToolsSettings } from '../../../services';
|
import { DevToolsSettings } from '../../../services';
|
||||||
import { createUseContext } from '../create_use_context';
|
import { createUseContext } from '../create_use_context';
|
||||||
|
|
||||||
const EditorReadContext = createContext<editor.Store>(null as any);
|
const EditorReadContext = createContext<editor.Store>(editor.initialValue);
|
||||||
const EditorActionContext = createContext<Dispatch<editor.Action>>(null as any);
|
const EditorActionContext = createContext<Dispatch<editor.Action>>(() => {});
|
||||||
|
|
||||||
export interface EditorContextArgs {
|
export interface EditorContextArgs {
|
||||||
children: any;
|
children: JSX.Element;
|
||||||
settings: DevToolsSettings;
|
settings: DevToolsSettings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@ export function EditorContextProvider({ children, settings }: EditorContextArgs)
|
||||||
settings,
|
settings,
|
||||||
}));
|
}));
|
||||||
return (
|
return (
|
||||||
<EditorReadContext.Provider value={state as any}>
|
<EditorReadContext.Provider value={state}>
|
||||||
<EditorActionContext.Provider value={dispatch}>{children}</EditorActionContext.Provider>
|
<EditorActionContext.Provider value={dispatch}>{children}</EditorActionContext.Provider>
|
||||||
</EditorReadContext.Provider>
|
</EditorReadContext.Provider>
|
||||||
);
|
);
|
||||||
|
|
|
@ -10,8 +10,8 @@ import React, { createContext, useReducer, Dispatch } from 'react';
|
||||||
import { createUseContext } from './create_use_context';
|
import { createUseContext } from './create_use_context';
|
||||||
import * as store from '../stores/request';
|
import * as store from '../stores/request';
|
||||||
|
|
||||||
const RequestReadContext = createContext<store.Store>(null as any);
|
const RequestReadContext = createContext<store.Store>(store.initialValue);
|
||||||
const RequestActionContext = createContext<Dispatch<store.Actions>>(null as any);
|
const RequestActionContext = createContext<Dispatch<store.Actions>>(() => {});
|
||||||
|
|
||||||
export function RequestContextProvider({ children }: { children: React.ReactNode }) {
|
export function RequestContextProvider({ children }: { children: React.ReactNode }) {
|
||||||
const [state, dispatch] = useReducer(store.reducer, store.initialValue);
|
const [state, dispatch] = useReducer(store.reducer, store.initialValue);
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
import { notificationServiceMock } from '../../../../../core/public/mocks';
|
import { notificationServiceMock } from '../../../../../core/public/mocks';
|
||||||
import { httpServiceMock } from '../../../../../core/public/mocks';
|
import { httpServiceMock } from '../../../../../core/public/mocks';
|
||||||
|
|
||||||
|
import type { ObjectStorageClient } from '../../../common/types';
|
||||||
import { HistoryMock } from '../../services/history.mock';
|
import { HistoryMock } from '../../services/history.mock';
|
||||||
import { SettingsMock } from '../../services/settings.mock';
|
import { SettingsMock } from '../../services/settings.mock';
|
||||||
import { StorageMock } from '../../services/storage.mock';
|
import { StorageMock } from '../../services/storage.mock';
|
||||||
|
@ -18,7 +19,7 @@ import { ContextValue } from './services_context';
|
||||||
|
|
||||||
export const serviceContextMock = {
|
export const serviceContextMock = {
|
||||||
create: (): ContextValue => {
|
create: (): ContextValue => {
|
||||||
const storage = new StorageMock({} as any, 'test');
|
const storage = new StorageMock(({} as unknown) as Storage, 'test');
|
||||||
const http = httpServiceMock.createSetupContract();
|
const http = httpServiceMock.createSetupContract();
|
||||||
const api = createApi({ http });
|
const api = createApi({ http });
|
||||||
const esHostService = createEsHostService({ api });
|
const esHostService = createEsHostService({ api });
|
||||||
|
@ -31,7 +32,7 @@ export const serviceContextMock = {
|
||||||
settings: new SettingsMock(storage),
|
settings: new SettingsMock(storage),
|
||||||
history: new HistoryMock(storage),
|
history: new HistoryMock(storage),
|
||||||
notifications: notificationServiceMock.createSetupContract(),
|
notifications: notificationServiceMock.createSetupContract(),
|
||||||
objectStorageClient: {} as any,
|
objectStorageClient: ({} as unknown) as ObjectStorageClient,
|
||||||
},
|
},
|
||||||
docLinkVersion: 'NA',
|
docLinkVersion: 'NA',
|
||||||
};
|
};
|
||||||
|
|
|
@ -30,10 +30,10 @@ export interface ContextValue {
|
||||||
|
|
||||||
interface ContextProps {
|
interface ContextProps {
|
||||||
value: ContextValue;
|
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) {
|
export function ServicesContextProvider({ children, value }: ContextProps) {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -46,8 +46,8 @@ export function ServicesContextProvider({ children, value }: ContextProps) {
|
||||||
|
|
||||||
export const useServicesContext = () => {
|
export const useServicesContext = () => {
|
||||||
const context = useContext(ServicesContext);
|
const context = useContext(ServicesContext);
|
||||||
if (context === undefined) {
|
if (context == null) {
|
||||||
throw new Error('useServicesContext must be used inside the ServicesContextProvider.');
|
throw new Error('useServicesContext must be used inside the ServicesContextProvider.');
|
||||||
}
|
}
|
||||||
return context;
|
return context!;
|
||||||
};
|
};
|
||||||
|
|
|
@ -7,12 +7,10 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import RowParser from '../../../lib/row_parser';
|
import RowParser from '../../../lib/row_parser';
|
||||||
|
import { ESRequest } from '../../../types';
|
||||||
import { SenseEditor } from '../../models/sense_editor';
|
import { SenseEditor } from '../../models/sense_editor';
|
||||||
/**
|
|
||||||
* This function is considered legacy and should not be changed or updated before we have editor
|
export function restoreRequestFromHistory(editor: SenseEditor, req: ESRequest) {
|
||||||
* interfaces in place (it's using a customized version of Ace directly).
|
|
||||||
*/
|
|
||||||
export function restoreRequestFromHistory(editor: SenseEditor, req: any) {
|
|
||||||
const coreEditor = editor.getCoreEditor();
|
const coreEditor = editor.getCoreEditor();
|
||||||
let pos = coreEditor.getCurrentPosition();
|
let pos = coreEditor.getCurrentPosition();
|
||||||
let prefix = '';
|
let prefix = '';
|
||||||
|
|
|
@ -8,10 +8,11 @@
|
||||||
|
|
||||||
import { useCallback } from 'react';
|
import { useCallback } from 'react';
|
||||||
import { instance as registry } from '../../contexts/editor_context/editor_registry';
|
import { instance as registry } from '../../contexts/editor_context/editor_registry';
|
||||||
|
import { ESRequest } from '../../../types';
|
||||||
import { restoreRequestFromHistory } from './restore_request_from_history';
|
import { restoreRequestFromHistory } from './restore_request_from_history';
|
||||||
|
|
||||||
export const useRestoreRequestFromHistory = () => {
|
export const useRestoreRequestFromHistory = () => {
|
||||||
return useCallback((req: any) => {
|
return useCallback((req: ESRequest) => {
|
||||||
const editor = registry.getInputEditor();
|
const editor = registry.getInputEditor();
|
||||||
restoreRequestFromHistory(editor, req);
|
restoreRequestFromHistory(editor, req);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
|
@ -8,19 +8,14 @@
|
||||||
|
|
||||||
import { extractWarningMessages } from '../../../lib/utils';
|
import { extractWarningMessages } from '../../../lib/utils';
|
||||||
import { XJson } from '../../../../../es_ui_shared/public';
|
import { XJson } from '../../../../../es_ui_shared/public';
|
||||||
const { collapseLiteralStrings } = XJson;
|
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
import * as es from '../../../lib/es/es';
|
import * as es from '../../../lib/es/es';
|
||||||
import { BaseResponseType } from '../../../types';
|
import { BaseResponseType } from '../../../types';
|
||||||
|
|
||||||
export interface EsRequestArgs {
|
const { collapseLiteralStrings } = XJson;
|
||||||
requests: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ESRequestObject {
|
export interface EsRequestArgs {
|
||||||
path: string;
|
requests: Array<{ url: string; method: string; data: string[] }>;
|
||||||
data: any;
|
|
||||||
method: string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ESResponseObject<V = unknown> {
|
export interface ESResponseObject<V = unknown> {
|
||||||
|
@ -32,7 +27,7 @@ export interface ESResponseObject<V = unknown> {
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ESRequestResult<V = unknown> {
|
export interface ESRequestResult<V = unknown> {
|
||||||
request: ESRequestObject;
|
request: { data: string; method: string; path: string };
|
||||||
response: ESResponseObject<V>;
|
response: ESResponseObject<V>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,7 +56,7 @@ export function sendRequestToES(args: EsRequestArgs): Promise<ESRequestResult[]>
|
||||||
resolve(results);
|
resolve(results);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const req = requests.shift();
|
const req = requests.shift()!;
|
||||||
const esPath = req.url;
|
const esPath = req.url;
|
||||||
const esMethod = req.method;
|
const esMethod = req.method;
|
||||||
let esData = collapseLiteralStrings(req.data.join('\n'));
|
let esData = collapseLiteralStrings(req.data.join('\n'));
|
||||||
|
@ -71,7 +66,7 @@ export function sendRequestToES(args: EsRequestArgs): Promise<ESRequestResult[]>
|
||||||
|
|
||||||
const startTime = Date.now();
|
const startTime = Date.now();
|
||||||
es.send(esMethod, esPath, esData).always(
|
es.send(esMethod, esPath, esData).always(
|
||||||
(dataOrjqXHR: any, textStatus: string, jqXhrORerrorThrown: any) => {
|
(dataOrjqXHR, textStatus: string, jqXhrORerrorThrown) => {
|
||||||
if (reqId !== CURRENT_REQ_ID) {
|
if (reqId !== CURRENT_REQ_ID) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,11 @@ import { SenseEditor } from '../../models/sense_editor';
|
||||||
import { getEndpointFromPosition } from '../../../lib/autocomplete/get_endpoint_from_position';
|
import { getEndpointFromPosition } from '../../../lib/autocomplete/get_endpoint_from_position';
|
||||||
import { MetricsTracker } from '../../../types';
|
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();
|
const coreEditor = editor.getCoreEditor();
|
||||||
// `getEndpointFromPosition` gets values from the server-side generated JSON files which
|
// `getEndpointFromPosition` gets values from the server-side generated JSON files which
|
||||||
// are a combination of JS, automatically generated JSON and manual overrides. That means
|
// are a combination of JS, automatically generated JSON and manual overrides. That means
|
||||||
|
|
|
@ -26,8 +26,8 @@ import { useSendCurrentRequestToES } from './use_send_current_request_to_es';
|
||||||
|
|
||||||
describe('useSendCurrentRequestToES', () => {
|
describe('useSendCurrentRequestToES', () => {
|
||||||
let mockContextValue: ContextValue;
|
let mockContextValue: ContextValue;
|
||||||
let dispatch: (...args: any[]) => void;
|
let dispatch: (...args: unknown[]) => void;
|
||||||
const contexts = ({ children }: { children?: any }) => (
|
const contexts = ({ children }: { children: JSX.Element }) => (
|
||||||
<ServicesContextProvider value={mockContextValue}>{children}</ServicesContextProvider>
|
<ServicesContextProvider value={mockContextValue}>{children}</ServicesContextProvider>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -9,12 +9,13 @@
|
||||||
import { useCallback } from 'react';
|
import { useCallback } from 'react';
|
||||||
import { useEditorActionContext } from '../contexts/editor_context';
|
import { useEditorActionContext } from '../contexts/editor_context';
|
||||||
import { instance as registry } from '../contexts/editor_context/editor_registry';
|
import { instance as registry } from '../contexts/editor_context/editor_registry';
|
||||||
|
import { SenseEditor } from '../models';
|
||||||
|
|
||||||
export const useSetInputEditor = () => {
|
export const useSetInputEditor = () => {
|
||||||
const dispatch = useEditorActionContext();
|
const dispatch = useEditorActionContext();
|
||||||
|
|
||||||
return useCallback(
|
return useCallback(
|
||||||
(editor: any) => {
|
(editor: SenseEditor) => {
|
||||||
dispatch({ type: 'setInputEditor', payload: editor });
|
dispatch({ type: 'setInputEditor', payload: editor });
|
||||||
registry.setInputEditor(editor);
|
registry.setInputEditor(editor);
|
||||||
},
|
},
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { render, unmountComponentAtNode } from 'react-dom';
|
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 { ServicesContextProvider, EditorContextProvider, RequestContextProvider } from './contexts';
|
||||||
import { Main } from './containers';
|
import { Main } from './containers';
|
||||||
import { createStorage, createHistory, createSettings } from '../services';
|
import { createStorage, createHistory, createSettings } from '../services';
|
||||||
|
@ -20,7 +20,7 @@ import { createApi, createEsHostService } from './lib';
|
||||||
export interface BootDependencies {
|
export interface BootDependencies {
|
||||||
http: HttpSetup;
|
http: HttpSetup;
|
||||||
docLinkVersion: string;
|
docLinkVersion: string;
|
||||||
I18nContext: any;
|
I18nContext: I18nStart['Context'];
|
||||||
notifications: NotificationsSetup;
|
notifications: NotificationsSetup;
|
||||||
usageCollection?: UsageCollectionSetup;
|
usageCollection?: UsageCollectionSetup;
|
||||||
element: HTMLElement;
|
element: HTMLElement;
|
||||||
|
|
|
@ -13,7 +13,7 @@ import * as OutputMode from './mode/output';
|
||||||
import smartResize from './smart_resize';
|
import smartResize from './smart_resize';
|
||||||
|
|
||||||
export interface CustomAceEditor extends ace.Editor {
|
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;
|
append: (text: string, foldPrevious?: boolean, cb?: () => void) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,9 +28,9 @@ export function createReadOnlyAceEditor(element: HTMLElement): CustomAceEditor {
|
||||||
|
|
||||||
output.$blockScrolling = Infinity;
|
output.$blockScrolling = Infinity;
|
||||||
output.resize = smartResize(output);
|
output.resize = smartResize(output);
|
||||||
output.update = (val: string, mode?: any, cb?: () => void) => {
|
output.update = (val: string, mode?: unknown, cb?: () => void) => {
|
||||||
if (typeof mode === 'function') {
|
if (typeof mode === 'function') {
|
||||||
cb = mode;
|
cb = mode as () => void;
|
||||||
mode = void 0;
|
mode = void 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,7 +65,7 @@ export function createReadOnlyAceEditor(element: HTMLElement): CustomAceEditor {
|
||||||
|
|
||||||
(function setupSession(session) {
|
(function setupSession(session) {
|
||||||
session.setMode('ace/mode/text');
|
session.setMode('ace/mode/text');
|
||||||
(session as any).setFoldStyle('markbeginend');
|
((session as unknown) as { setFoldStyle: (v: string) => void }).setFoldStyle('markbeginend');
|
||||||
session.setTabSize(2);
|
session.setTabSize(2);
|
||||||
session.setUseWrapMode(true);
|
session.setUseWrapMode(true);
|
||||||
})(output.getSession());
|
})(output.getSession());
|
||||||
|
|
|
@ -13,7 +13,7 @@ jest.mock('./mode/worker', () => {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
window.Worker = function () {
|
window.Worker = function () {
|
||||||
this.postMessage = () => {};
|
this.postMessage = () => {};
|
||||||
(this as any).terminate = () => {};
|
((this as unknown) as { terminate: () => void }).terminate = () => {};
|
||||||
};
|
};
|
||||||
|
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
|
|
|
@ -31,8 +31,8 @@ const rangeToAceRange = ({ start, end }: Range) =>
|
||||||
new _AceRange(start.lineNumber - 1, start.column - 1, end.lineNumber - 1, end.column - 1);
|
new _AceRange(start.lineNumber - 1, start.column - 1, end.lineNumber - 1, end.column - 1);
|
||||||
|
|
||||||
export class LegacyCoreEditor implements CoreEditor {
|
export class LegacyCoreEditor implements CoreEditor {
|
||||||
private _aceOnPaste: any;
|
private _aceOnPaste: Function;
|
||||||
$actions: any;
|
$actions: JQuery<HTMLElement>;
|
||||||
resize: () => void;
|
resize: () => void;
|
||||||
|
|
||||||
constructor(private readonly editor: IAceEditor, actions: HTMLElement) {
|
constructor(private readonly editor: IAceEditor, actions: HTMLElement) {
|
||||||
|
@ -41,7 +41,9 @@ export class LegacyCoreEditor implements CoreEditor {
|
||||||
|
|
||||||
const session = this.editor.getSession();
|
const session = this.editor.getSession();
|
||||||
session.setMode(new InputMode.Mode());
|
session.setMode(new InputMode.Mode());
|
||||||
(session as any).setFoldStyle('markbeginend');
|
((session as unknown) as { setFoldStyle: (style: string) => void }).setFoldStyle(
|
||||||
|
'markbeginend'
|
||||||
|
);
|
||||||
session.setTabSize(2);
|
session.setTabSize(2);
|
||||||
session.setUseWrapMode(true);
|
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.
|
// torn down, e.g. by closing the History tab, and we don't need to do anything further.
|
||||||
if (session.bgTokenizer) {
|
if (session.bgTokenizer) {
|
||||||
// Wait until the bgTokenizer is done running before executing the callback.
|
// 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);
|
setTimeout(check, checkInterval);
|
||||||
} else {
|
} else {
|
||||||
resolve();
|
resolve();
|
||||||
|
@ -197,7 +199,7 @@ export class LegacyCoreEditor implements CoreEditor {
|
||||||
.addMarker(rangeToAceRange(range), 'ace_snippet-marker', 'fullLine', false);
|
.addMarker(rangeToAceRange(range), 'ace_snippet-marker', 'fullLine', false);
|
||||||
}
|
}
|
||||||
|
|
||||||
removeMarker(ref: any) {
|
removeMarker(ref: number) {
|
||||||
this.editor.getSession().removeMarker(ref);
|
this.editor.getSession().removeMarker(ref);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -222,8 +224,10 @@ export class LegacyCoreEditor implements CoreEditor {
|
||||||
}
|
}
|
||||||
|
|
||||||
isCompleterActive() {
|
isCompleterActive() {
|
||||||
// Secrets of the arcane here.
|
return Boolean(
|
||||||
return Boolean((this.editor as any).completer && (this.editor as any).completer.activated);
|
((this.editor as unknown) as { completer: { activated: unknown } }).completer &&
|
||||||
|
((this.editor as unknown) as { completer: { activated: unknown } }).completer.activated
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private forceRetokenize() {
|
private forceRetokenize() {
|
||||||
|
@ -250,7 +254,7 @@ export class LegacyCoreEditor implements CoreEditor {
|
||||||
this._aceOnPaste.call(this.editor, text);
|
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) {
|
if (value === null) {
|
||||||
this.$actions.css('visibility', 'hidden');
|
this.$actions.css('visibility', 'hidden');
|
||||||
} else {
|
} else {
|
||||||
|
@ -271,7 +275,7 @@ export class LegacyCoreEditor implements CoreEditor {
|
||||||
};
|
};
|
||||||
|
|
||||||
private hideActionsBar = () => {
|
private hideActionsBar = () => {
|
||||||
this.setActionsBar();
|
this.setActionsBar(null);
|
||||||
};
|
};
|
||||||
|
|
||||||
execCommand(cmd: string) {
|
execCommand(cmd: string) {
|
||||||
|
@ -295,7 +299,7 @@ export class LegacyCoreEditor implements CoreEditor {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
legacyUpdateUI(range: any) {
|
legacyUpdateUI(range: Range) {
|
||||||
if (!this.$actions) {
|
if (!this.$actions) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -360,14 +364,19 @@ export class LegacyCoreEditor implements CoreEditor {
|
||||||
ace.define(
|
ace.define(
|
||||||
'ace/autocomplete/text_completer',
|
'ace/autocomplete/text_completer',
|
||||||
['require', 'exports', 'module'],
|
['require', 'exports', 'module'],
|
||||||
function (require: any, exports: any) {
|
function (
|
||||||
exports.getCompletions = function (
|
require: unknown,
|
||||||
innerEditor: any,
|
exports: {
|
||||||
session: any,
|
getCompletions: (
|
||||||
pos: any,
|
innerEditor: unknown,
|
||||||
prefix: any,
|
session: unknown,
|
||||||
callback: any
|
pos: unknown,
|
||||||
|
prefix: unknown,
|
||||||
|
callback: (e: null | Error, values: string[]) => void
|
||||||
|
) => void;
|
||||||
|
}
|
||||||
) {
|
) {
|
||||||
|
exports.getCompletions = function (innerEditor, session, pos, prefix, callback) {
|
||||||
callback(null, []);
|
callback(null, []);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -387,7 +396,7 @@ export class LegacyCoreEditor implements CoreEditor {
|
||||||
DO_NOT_USE_2: IAceEditSession,
|
DO_NOT_USE_2: IAceEditSession,
|
||||||
pos: { row: number; column: number },
|
pos: { row: number; column: number },
|
||||||
prefix: string,
|
prefix: string,
|
||||||
callback: (...args: any[]) => void
|
callback: (...args: unknown[]) => void
|
||||||
) => {
|
) => {
|
||||||
const position: Position = {
|
const position: Position = {
|
||||||
lineNumber: pos.row + 1,
|
lineNumber: pos.row + 1,
|
||||||
|
|
|
@ -7,9 +7,10 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { get, throttle } from 'lodash';
|
import { get, throttle } from 'lodash';
|
||||||
|
import type { Editor } from 'brace';
|
||||||
|
|
||||||
// eslint-disable-next-line import/no-default-export
|
// eslint-disable-next-line import/no-default-export
|
||||||
export default function (editor: any) {
|
export default function (editor: Editor) {
|
||||||
const resize = editor.resize;
|
const resize = editor.resize;
|
||||||
|
|
||||||
const throttledResize = throttle(() => {
|
const throttledResize = throttle(() => {
|
||||||
|
|
|
@ -25,7 +25,7 @@ export function detectCURL(text: string) {
|
||||||
export function parseCURL(text: string) {
|
export function parseCURL(text: string) {
|
||||||
let state = 'NONE';
|
let state = 'NONE';
|
||||||
const out = [];
|
const out = [];
|
||||||
let body: any[] = [];
|
let body: string[] = [];
|
||||||
let line = '';
|
let line = '';
|
||||||
const lines = text.trim().split('\n');
|
const lines = text.trim().split('\n');
|
||||||
let matches;
|
let matches;
|
||||||
|
@ -62,7 +62,7 @@ export function parseCURL(text: string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function unescapeLastBodyEl() {
|
function unescapeLastBodyEl() {
|
||||||
const str = body.pop().replace(/\\([\\"'])/g, '$1');
|
const str = body.pop()!.replace(/\\([\\"'])/g, '$1');
|
||||||
body.push(str);
|
body.push(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,8 +7,10 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import RowParser from '../../../lib/row_parser';
|
|
||||||
import { XJson } from '../../../../../es_ui_shared/public';
|
import { XJson } from '../../../../../es_ui_shared/public';
|
||||||
|
|
||||||
|
import RowParser from '../../../lib/row_parser';
|
||||||
import * as utils from '../../../lib/utils';
|
import * as utils from '../../../lib/utils';
|
||||||
|
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
|
@ -16,22 +18,20 @@ import * as es from '../../../lib/es/es';
|
||||||
|
|
||||||
import { CoreEditor, Position, Range } from '../../../types';
|
import { CoreEditor, Position, Range } from '../../../types';
|
||||||
import { createTokenIterator } from '../../factories';
|
import { createTokenIterator } from '../../factories';
|
||||||
|
import createAutocompleter from '../../../lib/autocomplete/autocomplete';
|
||||||
import Autocomplete from '../../../lib/autocomplete/autocomplete';
|
|
||||||
|
|
||||||
const { collapseLiteralStrings } = XJson;
|
const { collapseLiteralStrings } = XJson;
|
||||||
|
|
||||||
export class SenseEditor {
|
export class SenseEditor {
|
||||||
currentReqRange: (Range & { markerRef: any }) | null;
|
currentReqRange: (Range & { markerRef: unknown }) | null;
|
||||||
parser: any;
|
parser: RowParser;
|
||||||
|
|
||||||
// @ts-ignore
|
private readonly autocomplete: ReturnType<typeof createAutocompleter>;
|
||||||
private readonly autocomplete: any;
|
|
||||||
|
|
||||||
constructor(private readonly coreEditor: CoreEditor) {
|
constructor(private readonly coreEditor: CoreEditor) {
|
||||||
this.currentReqRange = null;
|
this.currentReqRange = null;
|
||||||
this.parser = new RowParser(this.coreEditor);
|
this.parser = new RowParser(this.coreEditor);
|
||||||
this.autocomplete = new (Autocomplete as any)({
|
this.autocomplete = createAutocompleter({
|
||||||
coreEditor,
|
coreEditor,
|
||||||
parser: this.parser,
|
parser: this.parser,
|
||||||
});
|
});
|
||||||
|
@ -114,7 +114,10 @@ export class SenseEditor {
|
||||||
return this.coreEditor.setValue(data, reTokenizeAll);
|
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);
|
const text = utils.textFromRequest(newRequest);
|
||||||
if (requestRange) {
|
if (requestRange) {
|
||||||
this.coreEditor.replaceRange(requestRange, text);
|
this.coreEditor.replaceRange(requestRange, text);
|
||||||
|
@ -207,12 +210,12 @@ export class SenseEditor {
|
||||||
const request: {
|
const request: {
|
||||||
method: string;
|
method: string;
|
||||||
data: string[];
|
data: string[];
|
||||||
url: string | null;
|
url: string;
|
||||||
range: Range;
|
range: Range;
|
||||||
} = {
|
} = {
|
||||||
method: '',
|
method: '',
|
||||||
data: [],
|
data: [],
|
||||||
url: null,
|
url: '',
|
||||||
range,
|
range,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -284,7 +287,7 @@ export class SenseEditor {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
const requests: any = [];
|
const requests: unknown[] = [];
|
||||||
|
|
||||||
let rangeStartCursor = expandedRange.start.lineNumber;
|
let rangeStartCursor = expandedRange.start.lineNumber;
|
||||||
const endLineNumber = expandedRange.end.lineNumber;
|
const endLineNumber = expandedRange.end.lineNumber;
|
||||||
|
|
|
@ -9,8 +9,9 @@
|
||||||
import { Reducer } from 'react';
|
import { Reducer } from 'react';
|
||||||
import { produce } from 'immer';
|
import { produce } from 'immer';
|
||||||
import { identity } from 'fp-ts/lib/function';
|
import { identity } from 'fp-ts/lib/function';
|
||||||
import { DevToolsSettings } from '../../services';
|
import { DevToolsSettings, DEFAULT_SETTINGS } from '../../services';
|
||||||
import { TextObject } from '../../../common/text_object';
|
import { TextObject } from '../../../common/text_object';
|
||||||
|
import { SenseEditor } from '../models';
|
||||||
|
|
||||||
export interface Store {
|
export interface Store {
|
||||||
ready: boolean;
|
ready: boolean;
|
||||||
|
@ -21,15 +22,15 @@ export interface Store {
|
||||||
export const initialValue: Store = produce<Store>(
|
export const initialValue: Store = produce<Store>(
|
||||||
{
|
{
|
||||||
ready: false,
|
ready: false,
|
||||||
settings: null as any,
|
settings: DEFAULT_SETTINGS,
|
||||||
currentTextObject: null,
|
currentTextObject: null,
|
||||||
},
|
},
|
||||||
identity
|
identity
|
||||||
);
|
);
|
||||||
|
|
||||||
export type Action =
|
export type Action =
|
||||||
| { type: 'setInputEditor'; payload: any }
|
| { type: 'setInputEditor'; payload: SenseEditor }
|
||||||
| { type: 'setCurrentTextObject'; payload: any }
|
| { type: 'setCurrentTextObject'; payload: TextObject }
|
||||||
| { type: 'updateSettings'; payload: DevToolsSettings };
|
| { type: 'updateSettings'; payload: DevToolsSettings };
|
||||||
|
|
||||||
export const reducer: Reducer<Store, Action> = (state, action) =>
|
export const reducer: Reducer<Store, Action> = (state, action) =>
|
||||||
|
|
|
@ -63,7 +63,7 @@ export class AceTokensProvider implements TokensProvider {
|
||||||
return null;
|
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) {
|
if (!tokens || !tokens.length) {
|
||||||
// We are inside of the document but have no tokens for this line. Return an empty
|
// We are inside of the document but have no tokens for this line. Return an empty
|
||||||
// array to represent this empty line.
|
// array to represent this empty line.
|
||||||
|
@ -74,7 +74,7 @@ export class AceTokensProvider implements TokensProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
getTokenAt(pos: Position): Token | null {
|
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) {
|
if (tokens) {
|
||||||
return extractTokenFromAceTokenRow(pos.lineNumber, pos.column, tokens);
|
return extractTokenFromAceTokenRow(pos.lineNumber, pos.column, tokens);
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,19 +18,21 @@ import {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
} from '../kb/kb';
|
} 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';
|
import * as utils from '../utils';
|
||||||
|
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
import { populateContext } from './engine';
|
import { populateContext } from './engine';
|
||||||
|
import { AutoCompleteContext, ResultTerm } from './types';
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
import { URL_PATH_END_MARKER } from './components/index';
|
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: { type: string } | null) {
|
||||||
|
|
||||||
function isUrlParamsToken(token: any) {
|
|
||||||
switch ((token || {}).type) {
|
switch ((token || {}).type) {
|
||||||
case 'url.param':
|
case 'url.param':
|
||||||
case 'url.equal':
|
case 'url.equal':
|
||||||
|
@ -54,7 +56,7 @@ function isUrlParamsToken(token: any) {
|
||||||
export function getCurrentMethodAndTokenPaths(
|
export function getCurrentMethodAndTokenPaths(
|
||||||
editor: CoreEditor,
|
editor: CoreEditor,
|
||||||
pos: Position,
|
pos: Position,
|
||||||
parser: any,
|
parser: RowParser,
|
||||||
forceEndOfUrl?: boolean /* Flag for indicating whether we want to avoid early escape optimization. */
|
forceEndOfUrl?: boolean /* Flag for indicating whether we want to avoid early escape optimization. */
|
||||||
) {
|
) {
|
||||||
const tokenIter = createTokenIterator({
|
const tokenIter = createTokenIterator({
|
||||||
|
@ -62,8 +64,8 @@ export function getCurrentMethodAndTokenPaths(
|
||||||
position: pos,
|
position: pos,
|
||||||
});
|
});
|
||||||
const startPos = pos;
|
const startPos = pos;
|
||||||
let bodyTokenPath: any = [];
|
let bodyTokenPath: string[] | null = [];
|
||||||
const ret: any = {};
|
const ret: AutoCompleteContext = {};
|
||||||
|
|
||||||
const STATES = {
|
const STATES = {
|
||||||
looking_for_key: 0, // looking for a key but without jumping over anything but white space and colon.
|
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.urlParamsTokenPath = null;
|
||||||
ret.requestStartRow = tokenIter.getCurrentPosition().lineNumber;
|
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)) {
|
while (t && isUrlParamsToken(t)) {
|
||||||
switch (t.type) {
|
switch (t.type) {
|
||||||
|
@ -240,7 +247,7 @@ export function getCurrentMethodAndTokenPaths(
|
||||||
if (!ret.urlParamsTokenPath) {
|
if (!ret.urlParamsTokenPath) {
|
||||||
ret.urlParamsTokenPath = [];
|
ret.urlParamsTokenPath = [];
|
||||||
}
|
}
|
||||||
ret.urlParamsTokenPath.unshift(curUrlPart || {});
|
ret.urlParamsTokenPath.unshift((curUrlPart as Record<string, string>) || {});
|
||||||
curUrlPart = null;
|
curUrlPart = null;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -268,7 +275,7 @@ export function getCurrentMethodAndTokenPaths(
|
||||||
break;
|
break;
|
||||||
case 'url.slash':
|
case 'url.slash':
|
||||||
if (curUrlPart) {
|
if (curUrlPart) {
|
||||||
ret.urlTokenPath.unshift(curUrlPart);
|
ret.urlTokenPath.unshift(curUrlPart as string);
|
||||||
curUrlPart = null;
|
curUrlPart = null;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -277,7 +284,7 @@ export function getCurrentMethodAndTokenPaths(
|
||||||
}
|
}
|
||||||
|
|
||||||
if (curUrlPart) {
|
if (curUrlPart) {
|
||||||
ret.urlTokenPath.unshift(curUrlPart);
|
ret.urlTokenPath.unshift(curUrlPart as string);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ret.bodyTokenPath && !ret.urlParamsTokenPath) {
|
if (!ret.bodyTokenPath && !ret.urlParamsTokenPath) {
|
||||||
|
@ -297,9 +304,15 @@ export function getCurrentMethodAndTokenPaths(
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line
|
// 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) {
|
function isUrlPathToken(token: Token | null) {
|
||||||
switch ((token || ({} as any)).type) {
|
switch ((token || ({} as Token)).type) {
|
||||||
case 'url.slash':
|
case 'url.slash':
|
||||||
case 'url.comma':
|
case 'url.comma':
|
||||||
case 'url.part':
|
case 'url.part':
|
||||||
|
@ -309,8 +322,12 @@ export default function ({ coreEditor: editor, parser }: { coreEditor: CoreEdito
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function addMetaToTermsList(list: any, meta: any, template?: string) {
|
function addMetaToTermsList(
|
||||||
return _.map(list, function (t: any) {
|
list: unknown[],
|
||||||
|
meta: unknown,
|
||||||
|
template?: string
|
||||||
|
): Array<{ meta: unknown; template: unknown; name?: string }> {
|
||||||
|
return _.map(list, function (t) {
|
||||||
if (typeof t !== 'object') {
|
if (typeof t !== 'object') {
|
||||||
t = { name: t };
|
t = { name: t };
|
||||||
}
|
}
|
||||||
|
@ -318,8 +335,13 @@ export default function ({ coreEditor: editor, parser }: { coreEditor: CoreEdito
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function applyTerm(term: any) {
|
function applyTerm(term: {
|
||||||
const context = term.context;
|
value?: string;
|
||||||
|
context?: AutoCompleteContext;
|
||||||
|
template?: { __raw: boolean; value: string };
|
||||||
|
insertValue?: string;
|
||||||
|
}) {
|
||||||
|
const context = term.context!;
|
||||||
|
|
||||||
// make sure we get up to date replacement info.
|
// make sure we get up to date replacement info.
|
||||||
addReplacementInfoToContext(context, editor.getCurrentPosition(), term.insertValue);
|
addReplacementInfoToContext(context, editor.getCurrentPosition(), term.insertValue);
|
||||||
|
@ -346,7 +368,7 @@ export default function ({ coreEditor: editor, parser }: { coreEditor: CoreEdito
|
||||||
} else {
|
} else {
|
||||||
indentedTemplateLines = utils.jsonToString(term.template, true).split('\n');
|
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];
|
currentIndentation = currentIndentation.match(/^\s*/)![0];
|
||||||
for (
|
for (
|
||||||
let i = 1;
|
let i = 1;
|
||||||
|
@ -374,8 +396,8 @@ export default function ({ coreEditor: editor, parser }: { coreEditor: CoreEdito
|
||||||
// disable listening to the changes we are making.
|
// disable listening to the changes we are making.
|
||||||
editor.off('changeSelection', editorChangeListener);
|
editor.off('changeSelection', editorChangeListener);
|
||||||
|
|
||||||
if (context.rangeToReplace.start.column !== context.rangeToReplace.end.column) {
|
if (context.rangeToReplace!.start.column !== context.rangeToReplace!.end.column) {
|
||||||
editor.replace(context.rangeToReplace, valueToInsert);
|
editor.replace(context.rangeToReplace!, valueToInsert);
|
||||||
} else {
|
} else {
|
||||||
editor.insert(valueToInsert);
|
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.
|
// go back to see whether we have one of ( : { & [ do not require a comma. All the rest do.
|
||||||
let newPos = {
|
let newPos = {
|
||||||
lineNumber: context.rangeToReplace.start.lineNumber,
|
lineNumber: context.rangeToReplace!.start.lineNumber,
|
||||||
column:
|
column:
|
||||||
context.rangeToReplace.start.column +
|
context.rangeToReplace!.start.column +
|
||||||
termAsString.length +
|
termAsString.length +
|
||||||
context.prefixToAdd.length +
|
context.prefixToAdd!.length +
|
||||||
(templateInserted ? 0 : context.suffixToAdd.length),
|
(templateInserted ? 0 : context.suffixToAdd!.length),
|
||||||
};
|
};
|
||||||
|
|
||||||
const tokenIter = createTokenIterator({
|
const tokenIter = createTokenIterator({
|
||||||
|
@ -406,7 +428,7 @@ export default function ({ coreEditor: editor, parser }: { coreEditor: CoreEdito
|
||||||
break;
|
break;
|
||||||
case 'punctuation.colon':
|
case 'punctuation.colon':
|
||||||
nonEmptyToken = parser.nextNonEmptyToken(tokenIter);
|
nonEmptyToken = parser.nextNonEmptyToken(tokenIter);
|
||||||
if ((nonEmptyToken || ({} as any)).type === 'paren.lparen') {
|
if ((nonEmptyToken || ({} as Token)).type === 'paren.lparen') {
|
||||||
nonEmptyToken = parser.nextNonEmptyToken(tokenIter);
|
nonEmptyToken = parser.nextNonEmptyToken(tokenIter);
|
||||||
newPos = tokenIter.getCurrentPosition();
|
newPos = tokenIter.getCurrentPosition();
|
||||||
if (nonEmptyToken && nonEmptyToken.value.indexOf('"') === 0) {
|
if (nonEmptyToken && nonEmptyToken.value.indexOf('"') === 0) {
|
||||||
|
@ -429,7 +451,7 @@ export default function ({ coreEditor: editor, parser }: { coreEditor: CoreEdito
|
||||||
|
|
||||||
function getAutoCompleteContext(ctxEditor: CoreEditor, pos: Position) {
|
function getAutoCompleteContext(ctxEditor: CoreEditor, pos: Position) {
|
||||||
// deduces all the parameters need to position and insert the auto complete
|
// 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
|
autoCompleteSet: null, // instructions for what can be here
|
||||||
endpoint: null,
|
endpoint: null,
|
||||||
urlPath: null,
|
urlPath: null,
|
||||||
|
@ -501,7 +523,7 @@ export default function ({ coreEditor: editor, parser }: { coreEditor: CoreEdito
|
||||||
case 'whitespace':
|
case 'whitespace':
|
||||||
t = parser.prevNonEmptyToken(tokenIter);
|
t = parser.prevNonEmptyToken(tokenIter);
|
||||||
|
|
||||||
switch ((t || ({} as any)).type) {
|
switch ((t || ({} as Token)).type) {
|
||||||
case 'method':
|
case 'method':
|
||||||
// we moved one back
|
// we moved one back
|
||||||
return 'path';
|
return 'path';
|
||||||
|
@ -552,7 +574,11 @@ export default function ({ coreEditor: editor, parser }: { coreEditor: CoreEdito
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
function addReplacementInfoToContext(context: any, pos: Position, replacingTerm?: any) {
|
function addReplacementInfoToContext(
|
||||||
|
context: AutoCompleteContext,
|
||||||
|
pos: Position,
|
||||||
|
replacingTerm?: unknown
|
||||||
|
) {
|
||||||
// extract the initial value, rangeToReplace & textBoxPosition
|
// extract the initial value, rangeToReplace & textBoxPosition
|
||||||
|
|
||||||
// Scenarios for current token:
|
// Scenarios for current token:
|
||||||
|
@ -605,7 +631,7 @@ export default function ({ coreEditor: editor, parser }: { coreEditor: CoreEdito
|
||||||
default:
|
default:
|
||||||
if (replacingTerm && context.updatedForToken.value === replacingTerm) {
|
if (replacingTerm && context.updatedForToken.value === replacingTerm) {
|
||||||
context.rangeToReplace = {
|
context.rangeToReplace = {
|
||||||
start: { lineNumber: pos.lineNumber, column: anchorToken.column },
|
start: { lineNumber: pos.lineNumber, column: anchorToken.position.column },
|
||||||
end: {
|
end: {
|
||||||
lineNumber: pos.lineNumber,
|
lineNumber: pos.lineNumber,
|
||||||
column:
|
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.
|
// 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.
|
// Templates will be used if not destroying existing structure.
|
||||||
|
@ -680,9 +706,9 @@ export default function ({ coreEditor: editor, parser }: { coreEditor: CoreEdito
|
||||||
}
|
}
|
||||||
context.addTemplate = true;
|
context.addTemplate = true;
|
||||||
// extend range to replace to include all up to token
|
// extend range to replace to include all up to token
|
||||||
context.rangeToReplace.end.lineNumber = tokenIter.getCurrentTokenLineNumber();
|
context.rangeToReplace!.end.lineNumber = tokenIter.getCurrentTokenLineNumber() as number;
|
||||||
context.rangeToReplace.end.column =
|
context.rangeToReplace!.end.column =
|
||||||
tokenIter.getCurrentTokenColumn() + nonEmptyToken.value.length;
|
(tokenIter.getCurrentTokenColumn() as number) + nonEmptyToken.value.length;
|
||||||
|
|
||||||
// move one more time to check if we need a trailing comma
|
// move one more time to check if we need a trailing comma
|
||||||
nonEmptyToken = parser.nextNonEmptyToken(tokenIter);
|
nonEmptyToken = parser.nextNonEmptyToken(tokenIter);
|
||||||
|
@ -711,11 +737,11 @@ export default function ({ coreEditor: editor, parser }: { coreEditor: CoreEdito
|
||||||
insertingRelativeToToken = 0;
|
insertingRelativeToToken = 0;
|
||||||
} else {
|
} else {
|
||||||
const pos = editor.getCurrentPosition();
|
const pos = editor.getCurrentPosition();
|
||||||
if (pos.column === context.updatedForToken.position.column) {
|
if (pos.column === context.updatedForToken!.position.column) {
|
||||||
insertingRelativeToToken = -1;
|
insertingRelativeToToken = -1;
|
||||||
} else if (
|
} else if (
|
||||||
pos.column <
|
pos.column <
|
||||||
context.updatedForToken.position.column + context.updatedForToken.value.length
|
context.updatedForToken!.position.column + context.updatedForToken!.value.length
|
||||||
) {
|
) {
|
||||||
insertingRelativeToToken = 0;
|
insertingRelativeToToken = 0;
|
||||||
} else {
|
} else {
|
||||||
|
@ -743,12 +769,12 @@ export default function ({ coreEditor: editor, parser }: { coreEditor: CoreEdito
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
function addUrlParamsPrefixSuffixToContext(context: any) {
|
function addUrlParamsPrefixSuffixToContext(context: AutoCompleteContext) {
|
||||||
context.prefixToAdd = '';
|
context.prefixToAdd = '';
|
||||||
context.suffixToAdd = '';
|
context.suffixToAdd = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
function addMethodPrefixSuffixToContext(context: any) {
|
function addMethodPrefixSuffixToContext(context: AutoCompleteContext) {
|
||||||
context.prefixToAdd = '';
|
context.prefixToAdd = '';
|
||||||
context.suffixToAdd = '';
|
context.suffixToAdd = '';
|
||||||
const tokenIter = createTokenIterator({ editor, position: editor.getCurrentPosition() });
|
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.prefixToAdd = '';
|
||||||
context.suffixToAdd = '';
|
context.suffixToAdd = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
function addMethodAutoCompleteSetToContext(context: any) {
|
function addMethodAutoCompleteSetToContext(context: AutoCompleteContext) {
|
||||||
context.autoCompleteSet = ['GET', 'PUT', 'POST', 'DELETE', 'HEAD'].map((m, i) => ({
|
context.autoCompleteSet = ['GET', 'PUT', 'POST', 'DELETE', 'HEAD'].map((m, i) => ({
|
||||||
name: m,
|
name: m,
|
||||||
score: -i,
|
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);
|
const ret = getCurrentMethodAndTokenPaths(editor, pos, parser);
|
||||||
context.method = ret.method;
|
context.method = ret.method;
|
||||||
context.token = ret.token;
|
context.token = ret.token;
|
||||||
|
@ -783,10 +809,10 @@ export default function ({ coreEditor: editor, parser }: { coreEditor: CoreEdito
|
||||||
const components = getTopLevelUrlCompleteComponents(context.method);
|
const components = getTopLevelUrlCompleteComponents(context.method);
|
||||||
populateContext(ret.urlTokenPath, context, editor, true, components);
|
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);
|
const ret = getCurrentMethodAndTokenPaths(editor, pos, parser);
|
||||||
context.method = ret.method;
|
context.method = ret.method;
|
||||||
context.otherTokenValues = ret.otherTokenValues;
|
context.otherTokenValues = ret.otherTokenValues;
|
||||||
|
@ -813,7 +839,7 @@ export default function ({ coreEditor: editor, parser }: { coreEditor: CoreEdito
|
||||||
// zero length tokenPath is true
|
// zero length tokenPath is true
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
let tokenPath: any[] = [];
|
let tokenPath: string[] = [];
|
||||||
const currentParam = ret.urlParamsTokenPath.pop();
|
const currentParam = ret.urlParamsTokenPath.pop();
|
||||||
if (currentParam) {
|
if (currentParam) {
|
||||||
tokenPath = Object.keys(currentParam); // single key object
|
tokenPath = Object.keys(currentParam); // single key object
|
||||||
|
@ -830,7 +856,7 @@ export default function ({ coreEditor: editor, parser }: { coreEditor: CoreEdito
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
function addBodyAutoCompleteSetToContext(context: any, pos: Position) {
|
function addBodyAutoCompleteSetToContext(context: AutoCompleteContext, pos: Position) {
|
||||||
const ret = getCurrentMethodAndTokenPaths(editor, pos, parser);
|
const ret = getCurrentMethodAndTokenPaths(editor, pos, parser);
|
||||||
context.method = ret.method;
|
context.method = ret.method;
|
||||||
context.otherTokenValues = ret.otherTokenValues;
|
context.otherTokenValues = ret.otherTokenValues;
|
||||||
|
@ -859,7 +885,7 @@ export default function ({ coreEditor: editor, parser }: { coreEditor: CoreEdito
|
||||||
// needed for scope linking + global term resolving
|
// needed for scope linking + global term resolving
|
||||||
context.endpointComponentResolver = getEndpointBodyCompleteComponents;
|
context.endpointComponentResolver = getEndpointBodyCompleteComponents;
|
||||||
context.globalComponentResolver = getGlobalAutocompleteComponents;
|
context.globalComponentResolver = getGlobalAutocompleteComponents;
|
||||||
let components;
|
let components: unknown;
|
||||||
if (context.endpoint) {
|
if (context.endpoint) {
|
||||||
components = context.endpoint.bodyAutocompleteRootComponents;
|
components = context.endpoint.bodyAutocompleteRootComponents;
|
||||||
} else {
|
} 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 {
|
try {
|
||||||
const context = getAutoCompleteContext(editor, position);
|
const context = getAutoCompleteContext(editor, position);
|
||||||
if (!context) {
|
if (!context) {
|
||||||
callback(null, []);
|
callback(null, []);
|
||||||
} else {
|
} else {
|
||||||
const terms = _.map(
|
const terms = _.map(
|
||||||
context.autoCompleteSet.filter((term: any) => Boolean(term) && term.name != null),
|
context.autoCompleteSet!.filter((term) => Boolean(term) && term.name != null),
|
||||||
function (term: any) {
|
function (term) {
|
||||||
if (typeof term !== 'object') {
|
if (typeof term !== 'object') {
|
||||||
term = {
|
term = {
|
||||||
name: term,
|
name: term,
|
||||||
|
@ -951,7 +981,13 @@ export default function ({ coreEditor: editor, parser }: { coreEditor: CoreEdito
|
||||||
} else {
|
} else {
|
||||||
term = _.clone(term);
|
term = _.clone(term);
|
||||||
}
|
}
|
||||||
const defaults: any = {
|
const defaults: {
|
||||||
|
value?: string;
|
||||||
|
meta: string;
|
||||||
|
score: number;
|
||||||
|
context: AutoCompleteContext;
|
||||||
|
completer?: { insertMatch: (v: unknown) => void };
|
||||||
|
} = {
|
||||||
value: term.name,
|
value: term.name,
|
||||||
meta: 'API',
|
meta: 'API',
|
||||||
score: 0,
|
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 */
|
/* score sorts from high to low */
|
||||||
if (t1.score > t2.score) {
|
if (t1.score > t2.score) {
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -978,7 +1017,7 @@ export default function ({ coreEditor: editor, parser }: { coreEditor: CoreEdito
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
/* names sort from low to high */
|
/* names sort from low to high */
|
||||||
if (t1.name < t2.name) {
|
if (t1.name! < t2.name!) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (t1.name === t2.name) {
|
if (t1.name === t2.name) {
|
||||||
|
@ -989,7 +1028,7 @@ export default function ({ coreEditor: editor, parser }: { coreEditor: CoreEdito
|
||||||
|
|
||||||
callback(
|
callback(
|
||||||
null,
|
null,
|
||||||
_.map(terms, function (t: any, i: any) {
|
_.map(terms, function (t, i) {
|
||||||
t.insertValue = t.insertValue || t.value;
|
t.insertValue = t.insertValue || t.value;
|
||||||
t.value = '' + t.value; // normalize to strings
|
t.value = '' + t.value; // normalize to strings
|
||||||
t.score = -i;
|
t.score = -i;
|
||||||
|
@ -1010,8 +1049,13 @@ export default function ({ coreEditor: editor, parser }: { coreEditor: CoreEdito
|
||||||
getCompletions,
|
getCompletions,
|
||||||
// TODO: This needs to be cleaned up
|
// TODO: This needs to be cleaned up
|
||||||
_test: {
|
_test: {
|
||||||
getCompletions: (_editor: any, _editSession: any, pos: any, prefix: any, callback: any) =>
|
getCompletions: (
|
||||||
getCompletions(pos, prefix, callback),
|
_editor: unknown,
|
||||||
|
_editSession: unknown,
|
||||||
|
pos: Position,
|
||||||
|
prefix: string,
|
||||||
|
callback: (e: Error | null, result: ResultTerm[] | null) => void
|
||||||
|
) => getCompletions(pos, prefix, callback),
|
||||||
addReplacementInfoToContext,
|
addReplacementInfoToContext,
|
||||||
addChangeListener: () => editor.on('changeSelection', editorChangeListener),
|
addChangeListener: () => editor.on('changeSelection', editorChangeListener),
|
||||||
removeChangeListener: () => editor.off('changeSelection', editorChangeListener),
|
removeChangeListener: () => editor.off('changeSelection', editorChangeListener),
|
||||||
|
|
|
@ -11,7 +11,7 @@ import { ConstantComponent } from './constant_component';
|
||||||
|
|
||||||
export class FullRequestComponent extends ConstantComponent {
|
export class FullRequestComponent extends ConstantComponent {
|
||||||
private readonly name: string;
|
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);
|
super(name, parent);
|
||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,13 +8,14 @@
|
||||||
|
|
||||||
import { CoreEditor, Position } from '../../types';
|
import { CoreEditor, Position } from '../../types';
|
||||||
import { getCurrentMethodAndTokenPaths } from './autocomplete';
|
import { getCurrentMethodAndTokenPaths } from './autocomplete';
|
||||||
|
import type RowParser from '../row_parser';
|
||||||
|
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
import { getTopLevelUrlCompleteComponents } from '../kb/kb';
|
import { getTopLevelUrlCompleteComponents } from '../kb/kb';
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
import { populateContext } from './engine';
|
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 lineValue = editor.getLineValue(pos.lineNumber);
|
||||||
const context = {
|
const context = {
|
||||||
...getCurrentMethodAndTokenPaths(
|
...getCurrentMethodAndTokenPaths(
|
||||||
|
|
61
src/plugins/console/public/lib/autocomplete/types.ts
Normal file
61
src/plugins/console/public/lib/autocomplete/types.ts
Normal 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;
|
||||||
|
}
|
|
@ -19,7 +19,7 @@ export function getVersion() {
|
||||||
return esVersion;
|
return esVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getContentType(body: any) {
|
export function getContentType(body: unknown) {
|
||||||
if (!body) return;
|
if (!body) return;
|
||||||
return 'application/json';
|
return 'application/json';
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@ export function getContentType(body: any) {
|
||||||
export function send(
|
export function send(
|
||||||
method: string,
|
method: string,
|
||||||
path: string,
|
path: string,
|
||||||
data: any,
|
data: string | object,
|
||||||
{ asSystemRequest }: SendOptions = {}
|
{ asSystemRequest }: SendOptions = {}
|
||||||
) {
|
) {
|
||||||
const wrappedDfd = $.Deferred();
|
const wrappedDfd = $.Deferred();
|
||||||
|
@ -47,10 +47,10 @@ export function send(
|
||||||
};
|
};
|
||||||
|
|
||||||
$.ajax(options).then(
|
$.ajax(options).then(
|
||||||
(responseData: any, textStatus: string, jqXHR: any) => {
|
(responseData, textStatus: string, jqXHR: unknown) => {
|
||||||
wrappedDfd.resolveWith({}, [responseData, textStatus, jqXHR]);
|
wrappedDfd.resolveWith({}, [responseData, textStatus, jqXHR]);
|
||||||
},
|
},
|
||||||
((jqXHR: any, textStatus: string, errorThrown: Error) => {
|
((jqXHR: { status: number; responseText: string }, textStatus: string, errorThrown: Error) => {
|
||||||
if (jqXHR.status === 0) {
|
if (jqXHR.status === 0) {
|
||||||
jqXHR.responseText =
|
jqXHR.responseText =
|
||||||
"\n\nFailed to connect to Console's backend.\nPlease check the Kibana server is up and running";
|
"\n\nFailed to connect to Console's backend.\nPlease check the Kibana server is up and running";
|
||||||
|
|
|
@ -75,7 +75,7 @@ export default class RowParser {
|
||||||
return MODE.REQUEST_START;
|
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);
|
const mode = this.getRowParseMode(lineNumber);
|
||||||
// eslint-disable-next-line no-bitwise
|
// eslint-disable-next-line no-bitwise
|
||||||
return (mode & value) > 0;
|
return (mode & value) > 0;
|
||||||
|
|
|
@ -15,7 +15,7 @@ const mockTokensProviderFactory = (tokenMtx: Token[][]): TokensProvider => {
|
||||||
return tokenMtx[lineNumber - 1] || null;
|
return tokenMtx[lineNumber - 1] || null;
|
||||||
},
|
},
|
||||||
getTokenAt(pos: Position): Token | null {
|
getTokenAt(pos: Position): Token | null {
|
||||||
return null as any;
|
return null;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -11,7 +11,7 @@ import { XJson } from '../../../../es_ui_shared/public';
|
||||||
|
|
||||||
const { collapseLiteralStrings, expandLiteralStrings } = XJson;
|
const { collapseLiteralStrings, expandLiteralStrings } = XJson;
|
||||||
|
|
||||||
export function textFromRequest(request: any) {
|
export function textFromRequest(request: { method: string; url: string; data: string | string[] }) {
|
||||||
let data = request.data;
|
let data = request.data;
|
||||||
if (typeof data !== 'string') {
|
if (typeof data !== 'string') {
|
||||||
data = data.join('\n');
|
data = data.join('\n');
|
||||||
|
@ -19,7 +19,7 @@ export function textFromRequest(request: any) {
|
||||||
return request.method + ' ' + request.url + '\n' + data;
|
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);
|
return JSON.stringify(data, null, indent ? 2 : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,12 +35,12 @@ export class History {
|
||||||
// be triggered from different places in the app. The alternative would be to store
|
// 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
|
// 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.
|
// 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);
|
const subscription = this.changeEmitter.subscribe(listener);
|
||||||
return () => subscription.unsubscribe();
|
return () => subscription.unsubscribe();
|
||||||
}
|
}
|
||||||
|
|
||||||
addToHistory(endpoint: string, method: string, data: any) {
|
addToHistory(endpoint: string, method: string, data?: string) {
|
||||||
const keys = this.getHistoryKeys();
|
const keys = this.getHistoryKeys();
|
||||||
keys.splice(0, MAX_NUMBER_OF_HISTORY_ITEMS); // only maintain most recent X;
|
keys.splice(0, MAX_NUMBER_OF_HISTORY_ITEMS); // only maintain most recent X;
|
||||||
keys.forEach((key) => {
|
keys.forEach((key) => {
|
||||||
|
@ -59,7 +59,7 @@ export class History {
|
||||||
this.changeEmitter.next(this.getHistory());
|
this.changeEmitter.next(this.getHistory());
|
||||||
}
|
}
|
||||||
|
|
||||||
updateCurrentState(content: any) {
|
updateCurrentState(content: string) {
|
||||||
const timestamp = new Date().getTime();
|
const timestamp = new Date().getTime();
|
||||||
this.storage.set('editor_state', {
|
this.storage.set('editor_state', {
|
||||||
time: timestamp,
|
time: timestamp,
|
||||||
|
|
|
@ -8,4 +8,4 @@
|
||||||
|
|
||||||
export { createHistory, History } from './history';
|
export { createHistory, History } from './history';
|
||||||
export { createStorage, Storage, StorageKeys } from './storage';
|
export { createStorage, Storage, StorageKeys } from './storage';
|
||||||
export { createSettings, Settings, DevToolsSettings } from './settings';
|
export { createSettings, Settings, DevToolsSettings, DEFAULT_SETTINGS } from './settings';
|
||||||
|
|
|
@ -8,6 +8,14 @@
|
||||||
|
|
||||||
import { Storage } from './index';
|
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 {
|
export interface DevToolsSettings {
|
||||||
fontSize: number;
|
fontSize: number;
|
||||||
wrapMode: boolean;
|
wrapMode: boolean;
|
||||||
|
@ -24,50 +32,46 @@ export class Settings {
|
||||||
constructor(private readonly storage: Storage) {}
|
constructor(private readonly storage: Storage) {}
|
||||||
|
|
||||||
getFontSize() {
|
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);
|
this.storage.set('font_size', size);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
getWrapMode() {
|
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);
|
this.storage.set('wrap_mode', mode);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
setTripleQuotes(tripleQuotes: any) {
|
setTripleQuotes(tripleQuotes: boolean) {
|
||||||
this.storage.set('triple_quotes', tripleQuotes);
|
this.storage.set('triple_quotes', tripleQuotes);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
getTripleQuotes() {
|
getTripleQuotes() {
|
||||||
return this.storage.get('triple_quotes', true);
|
return this.storage.get('triple_quotes', DEFAULT_SETTINGS.tripleQuotes);
|
||||||
}
|
}
|
||||||
|
|
||||||
getAutocomplete() {
|
getAutocomplete() {
|
||||||
return this.storage.get('autocomplete_settings', {
|
return this.storage.get('autocomplete_settings', DEFAULT_SETTINGS.autocomplete);
|
||||||
fields: true,
|
|
||||||
indices: true,
|
|
||||||
templates: true,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setAutocomplete(settings: any) {
|
setAutocomplete(settings: object) {
|
||||||
this.storage.set('autocomplete_settings', settings);
|
this.storage.set('autocomplete_settings', settings);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
getPolling() {
|
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);
|
this.storage.set('console_polling', polling);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,11 +17,11 @@ export enum StorageKeys {
|
||||||
export class Storage {
|
export class Storage {
|
||||||
constructor(private readonly engine: IStorageEngine, private readonly prefix: string) {}
|
constructor(private readonly engine: IStorageEngine, private readonly prefix: string) {}
|
||||||
|
|
||||||
encode(val: any) {
|
encode(val: unknown) {
|
||||||
return JSON.stringify(val);
|
return JSON.stringify(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
decode(val: any) {
|
decode(val: string | null) {
|
||||||
if (typeof val === 'string') {
|
if (typeof val === 'string') {
|
||||||
return JSON.parse(val);
|
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));
|
this.engine.setItem(this.encodeKey(key), this.encode(val));
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,12 @@ export interface MetricsTracker {
|
||||||
load: (eventName: string) => void;
|
load: (eventName: string) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ESRequest {
|
||||||
|
method: string;
|
||||||
|
endpoint: string;
|
||||||
|
data?: string;
|
||||||
|
}
|
||||||
|
|
||||||
export type BaseResponseType =
|
export type BaseResponseType =
|
||||||
| 'application/json'
|
| 'application/json'
|
||||||
| 'text/csv'
|
| 'text/csv'
|
||||||
|
|
|
@ -21,7 +21,7 @@ export type EditorEvent =
|
||||||
export type AutoCompleterFunction = (
|
export type AutoCompleterFunction = (
|
||||||
pos: Position,
|
pos: Position,
|
||||||
prefix: string,
|
prefix: string,
|
||||||
callback: (...args: any[]) => void
|
callback: (...args: unknown[]) => void
|
||||||
) => void;
|
) => void;
|
||||||
|
|
||||||
export interface Position {
|
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
|
* have this backdoor to update UI in response to request range changes, for example, as the user
|
||||||
* moves the cursor around
|
* 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.
|
* 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.
|
* 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
|
* Register a completions function that will be called when the editor
|
||||||
|
|
|
@ -14,7 +14,7 @@ import url from 'url';
|
||||||
import { ESConfigForProxy } from '../types';
|
import { ESConfigForProxy } from '../types';
|
||||||
|
|
||||||
const createAgent = (legacyConfig: ESConfigForProxy) => {
|
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();
|
if (!/^https/.test(target.protocol || '')) return new http.Agent();
|
||||||
|
|
||||||
const agentOptions: https.AgentOptions = {};
|
const agentOptions: https.AgentOptions = {};
|
||||||
|
@ -28,7 +28,7 @@ const createAgent = (legacyConfig: ESConfigForProxy) => {
|
||||||
agentOptions.rejectUnauthorized = true;
|
agentOptions.rejectUnauthorized = true;
|
||||||
|
|
||||||
// by default, NodeJS is checking the server identify
|
// by default, NodeJS is checking the server identify
|
||||||
agentOptions.checkServerIdentity = _.noop as any;
|
agentOptions.checkServerIdentity = (_.noop as unknown) as https.AgentOptions['checkServerIdentity'];
|
||||||
break;
|
break;
|
||||||
case 'full':
|
case 'full':
|
||||||
agentOptions.rejectUnauthorized = true;
|
agentOptions.rejectUnauthorized = true;
|
||||||
|
|
|
@ -12,6 +12,17 @@ import { Agent as HttpsAgent, AgentOptions } from 'https';
|
||||||
|
|
||||||
import { WildcardMatcher } from './wildcard_matcher';
|
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 {
|
export class ProxyConfig {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
private id: string;
|
private id: string;
|
||||||
|
@ -26,9 +37,9 @@ export class ProxyConfig {
|
||||||
|
|
||||||
private readonly sslAgent?: HttpsAgent;
|
private readonly sslAgent?: HttpsAgent;
|
||||||
|
|
||||||
private verifySsl: any;
|
private verifySsl: undefined | boolean;
|
||||||
|
|
||||||
constructor(config: { match: any; timeout: number }) {
|
constructor(config: Config) {
|
||||||
config = {
|
config = {
|
||||||
...config,
|
...config,
|
||||||
};
|
};
|
||||||
|
@ -61,8 +72,8 @@ export class ProxyConfig {
|
||||||
this.sslAgent = this._makeSslAgent(config);
|
this.sslAgent = this._makeSslAgent(config);
|
||||||
}
|
}
|
||||||
|
|
||||||
_makeSslAgent(config: any) {
|
_makeSslAgent(config: Config) {
|
||||||
const ssl = config.ssl || {};
|
const ssl: Config['ssl'] = config.ssl || {};
|
||||||
this.verifySsl = ssl.verify;
|
this.verifySsl = ssl.verify;
|
||||||
|
|
||||||
const sslAgentOpts: AgentOptions = {
|
const sslAgentOpts: AgentOptions = {
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
* Side Public License, v 1.
|
* Side Public License, v 1.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import type { Agent } from 'http';
|
||||||
import { defaultsDeep } from 'lodash';
|
import { defaultsDeep } from 'lodash';
|
||||||
import { parse as parseUrl } from 'url';
|
import { parse as parseUrl } from 'url';
|
||||||
|
|
||||||
|
@ -14,7 +15,12 @@ import { ProxyConfig } from './proxy_config';
|
||||||
export class ProxyConfigCollection {
|
export class ProxyConfigCollection {
|
||||||
private configs: ProxyConfig[];
|
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));
|
this.configs = configs.map((settings) => new ProxyConfig(settings));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,7 +28,7 @@ export class ProxyConfigCollection {
|
||||||
return Boolean(this.configs.length);
|
return Boolean(this.configs.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
configForUri(uri: string): object {
|
configForUri(uri: string): { agent: Agent; timeout: number } {
|
||||||
const parsedUri = parseUrl(uri);
|
const parsedUri = parseUrl(uri);
|
||||||
const settings = this.configs.map((config) => config.getForParsedUri(parsedUri as any));
|
const settings = this.configs.map((config) => config.getForParsedUri(parsedUri as any));
|
||||||
return defaultsDeep({}, ...settings);
|
return defaultsDeep({}, ...settings);
|
||||||
|
|
|
@ -55,7 +55,7 @@ describe(`Console's send request`, () => {
|
||||||
fakeRequest = {
|
fakeRequest = {
|
||||||
abort: sinon.stub(),
|
abort: sinon.stub(),
|
||||||
on() {},
|
on() {},
|
||||||
once(event: string, fn: any) {
|
once(event: string, fn: (v: string) => void) {
|
||||||
if (event === 'response') {
|
if (event === 'response') {
|
||||||
return fn('done');
|
return fn('done');
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,9 +46,9 @@ export const proxyRequest = ({
|
||||||
const client = uri.protocol === 'https:' ? https : http;
|
const client = uri.protocol === 'https:' ? https : http;
|
||||||
let resolved = false;
|
let resolved = false;
|
||||||
|
|
||||||
let resolve: any;
|
let resolve: (res: http.IncomingMessage) => void;
|
||||||
let reject: any;
|
let reject: (res: unknown) => void;
|
||||||
const reqPromise = new Promise<http.ServerResponse>((res, rej) => {
|
const reqPromise = new Promise<http.IncomingMessage>((res, rej) => {
|
||||||
resolve = res;
|
resolve = res;
|
||||||
reject = rej;
|
reject = rej;
|
||||||
});
|
});
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||||
* Side Public License, v 1.
|
* Side Public License, v 1.
|
||||||
*/
|
*/
|
||||||
|
import { IKibanaResponse } from 'src/core/server';
|
||||||
import { getProxyRouteHandlerDeps } from './mocks';
|
import { getProxyRouteHandlerDeps } from './mocks';
|
||||||
|
|
||||||
import { Readable } from 'stream';
|
import { Readable } from 'stream';
|
||||||
|
@ -16,10 +16,14 @@ import * as requestModule from '../../../../lib/proxy_request';
|
||||||
import { createResponseStub } from './stubs';
|
import { createResponseStub } from './stubs';
|
||||||
|
|
||||||
describe('Console Proxy Route', () => {
|
describe('Console Proxy Route', () => {
|
||||||
let request: any;
|
let request: (
|
||||||
|
method: string,
|
||||||
|
path: string,
|
||||||
|
response?: string
|
||||||
|
) => Promise<IKibanaResponse> | IKibanaResponse;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
request = (method: string, path: string, response: string) => {
|
request = (method, path, response) => {
|
||||||
(requestModule.proxyRequest as jest.Mock).mockResolvedValue(createResponseStub(response));
|
(requestModule.proxyRequest as jest.Mock).mockResolvedValue(createResponseStub(response));
|
||||||
const handler = createHandler(getProxyRouteHandlerDeps({}));
|
const handler = createHandler(getProxyRouteHandlerDeps({}));
|
||||||
|
|
||||||
|
|
|
@ -41,7 +41,7 @@ function toURL(base: string, path: string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function filterHeaders(originalHeaders: object, headersToKeep: string[]): object {
|
function filterHeaders(originalHeaders: object, headersToKeep: string[]): object {
|
||||||
const normalizeHeader = function (header: any) {
|
const normalizeHeader = function (header: string) {
|
||||||
if (!header) {
|
if (!header) {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
@ -68,7 +68,7 @@ function getRequestConfig(
|
||||||
return {
|
return {
|
||||||
...proxyConfigCollection.configForUri(uri),
|
...proxyConfigCollection.configForUri(uri),
|
||||||
headers: newHeaders,
|
headers: newHeaders,
|
||||||
} as any;
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -81,7 +81,7 @@ function getProxyHeaders(req: KibanaRequest) {
|
||||||
const headers = Object.create(null);
|
const headers = Object.create(null);
|
||||||
|
|
||||||
// Scope this proto-unsafe functionality to where it is being used.
|
// 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;
|
obj[property] = (obj[property] ? obj[property] + ',' : '') + value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,7 +142,7 @@ export const createHandler = ({
|
||||||
};
|
};
|
||||||
|
|
||||||
esIncomingMessage = await proxyRequest({
|
esIncomingMessage = await proxyRequest({
|
||||||
method: method.toLowerCase() as any,
|
method: method.toLowerCase() as 'get' | 'post' | 'put' | 'delete' | 'patch' | 'head',
|
||||||
headers: requestHeaders,
|
headers: requestHeaders,
|
||||||
uri,
|
uri,
|
||||||
timeout,
|
timeout,
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
* Side Public License, v 1.
|
* Side Public License, v 1.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import type { IKibanaResponse } from 'src/core/server';
|
||||||
import { kibanaResponseFactory } from '../../../../../../../core/server';
|
import { kibanaResponseFactory } from '../../../../../../../core/server';
|
||||||
import { getProxyRouteHandlerDeps } from './mocks';
|
import { getProxyRouteHandlerDeps } from './mocks';
|
||||||
import { createResponseStub } from './stubs';
|
import { createResponseStub } from './stubs';
|
||||||
|
@ -14,7 +15,7 @@ import * as requestModule from '../../../../lib/proxy_request';
|
||||||
import { createHandler } from './create_handler';
|
import { createHandler } from './create_handler';
|
||||||
|
|
||||||
describe('Console Proxy Route', () => {
|
describe('Console Proxy Route', () => {
|
||||||
let request: any;
|
let request: (method: string, path: string) => Promise<IKibanaResponse> | IKibanaResponse;
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
(requestModule.proxyRequest as jest.Mock).mockResolvedValue(createResponseStub('foo'));
|
(requestModule.proxyRequest as jest.Mock).mockResolvedValue(createResponseStub('foo'));
|
||||||
|
|
||||||
|
|
|
@ -9,8 +9,12 @@
|
||||||
import { IncomingMessage } from 'http';
|
import { IncomingMessage } from 'http';
|
||||||
import { Readable } from 'stream';
|
import { Readable } from 'stream';
|
||||||
|
|
||||||
export function createResponseStub(response: any) {
|
export function createResponseStub(response?: string) {
|
||||||
const resp: any = new Readable({
|
const resp: Readable & {
|
||||||
|
statusCode?: number;
|
||||||
|
statusMessage?: string;
|
||||||
|
headers?: Record<string, unknown>;
|
||||||
|
} = new Readable({
|
||||||
read() {
|
read() {
|
||||||
if (response) {
|
if (response) {
|
||||||
this.push(response);
|
this.push(response);
|
||||||
|
|
|
@ -15,6 +15,15 @@ import { jsSpecLoaders } from '../lib';
|
||||||
|
|
||||||
const PATH_TO_OSS_JSON_SPEC = resolve(__dirname, '../lib/spec_definitions/json');
|
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 {
|
export class SpecDefinitionsService {
|
||||||
private readonly name = 'es';
|
private readonly name = 'es';
|
||||||
|
|
||||||
|
@ -24,16 +33,23 @@ export class SpecDefinitionsService {
|
||||||
|
|
||||||
private hasLoadedSpec = false;
|
private hasLoadedSpec = false;
|
||||||
|
|
||||||
public addGlobalAutocompleteRules(parentNode: string, rules: any) {
|
public addGlobalAutocompleteRules(parentNode: string, rules: unknown) {
|
||||||
this.globalRules[parentNode] = rules;
|
this.globalRules[parentNode] = rules;
|
||||||
}
|
}
|
||||||
|
|
||||||
public addEndpointDescription(endpoint: string, description: any = {}) {
|
public addEndpointDescription(endpoint: string, description: EndpointDescription = {}) {
|
||||||
let copiedDescription: any = {};
|
let copiedDescription: { patterns?: string; url_params?: Record<string, unknown> } = {};
|
||||||
if (this.endpoints[endpoint]) {
|
if (this.endpoints[endpoint]) {
|
||||||
copiedDescription = { ...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) {
|
_.each(description.patterns || [], function (p) {
|
||||||
if (p.indexOf('{indices}') >= 0) {
|
if (p.indexOf('{indices}') >= 0) {
|
||||||
urlParamsDef = urlParamsDef || {};
|
urlParamsDef = urlParamsDef || {};
|
||||||
|
@ -70,7 +86,7 @@ export class SpecDefinitionsService {
|
||||||
this.extensionSpecFilePaths.push(path);
|
this.extensionSpecFilePaths.push(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
public addProcessorDefinition(processor: any) {
|
public addProcessorDefinition(processor: unknown) {
|
||||||
if (!this.hasLoadedSpec) {
|
if (!this.hasLoadedSpec) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
'Cannot add a processor definition because spec definitions have not loaded!'
|
'Cannot add a processor definition because spec definitions have not loaded!'
|
||||||
|
@ -104,11 +120,13 @@ export class SpecDefinitionsService {
|
||||||
|
|
||||||
return generatedFiles.reduce((acc, file) => {
|
return generatedFiles.reduce((acc, file) => {
|
||||||
const overrideFile = overrideFiles.find((f) => basename(f) === basename(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) {
|
if (overrideFile) {
|
||||||
merge(loadedSpec, JSON.parse(readFileSync(overrideFile, 'utf8')));
|
merge(loadedSpec, JSON.parse(readFileSync(overrideFile, 'utf8')));
|
||||||
}
|
}
|
||||||
const spec: any = {};
|
const spec: Record<string, EndpointDescription> = {};
|
||||||
Object.entries(loadedSpec).forEach(([key, value]) => {
|
Object.entries(loadedSpec).forEach(([key, value]) => {
|
||||||
if (acc[key]) {
|
if (acc[key]) {
|
||||||
// add time to remove key collision
|
// add time to remove key collision
|
||||||
|
@ -119,7 +137,7 @@ export class SpecDefinitionsService {
|
||||||
});
|
});
|
||||||
|
|
||||||
return { ...acc, ...spec };
|
return { ...acc, ...spec };
|
||||||
}, {} as any);
|
}, {} as Record<string, EndpointDescription>);
|
||||||
}
|
}
|
||||||
|
|
||||||
private loadJsonSpec() {
|
private loadJsonSpec() {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue