Skip to content

Commit 45f40ec

Browse files
Merge branch 'master' into kertal-pr-2019-12-09-np-saved-object-graph
2 parents f398e8f + 85aea35 commit 45f40ec

File tree

50 files changed

+1195
-314
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+1195
-314
lines changed

config/apm.js

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -42,19 +42,22 @@ const { join } = require('path');
4242
const { execSync } = require('child_process');
4343
const merge = require('lodash.merge');
4444

45-
module.exports = merge({
46-
active: false,
47-
serverUrl: 'https://f1542b814f674090afd914960583265f.apm.us-central1.gcp.cloud.es.io:443',
48-
// The secretToken below is intended to be hardcoded in this file even though
49-
// it makes it public. This is not a security/privacy issue. Normally we'd
50-
// instead disable the need for a secretToken in the APM Server config where
51-
// the data is transmitted to, but due to how it's being hosted, it's easier,
52-
// for now, to simply leave it in.
53-
secretToken: 'R0Gjg46pE9K9wGestd',
54-
globalLabels: {},
55-
centralConfig: false,
56-
logUncaughtExceptions: true
57-
}, devConfig());
45+
module.exports = merge(
46+
{
47+
active: false,
48+
serverUrl: 'https://f1542b814f674090afd914960583265f.apm.us-central1.gcp.cloud.es.io:443',
49+
// The secretToken below is intended to be hardcoded in this file even though
50+
// it makes it public. This is not a security/privacy issue. Normally we'd
51+
// instead disable the need for a secretToken in the APM Server config where
52+
// the data is transmitted to, but due to how it's being hosted, it's easier,
53+
// for now, to simply leave it in.
54+
secretToken: 'R0Gjg46pE9K9wGestd',
55+
globalLabels: {},
56+
centralConfig: false,
57+
logUncaughtExceptions: true,
58+
},
59+
devConfig()
60+
);
5861

5962
const rev = gitRev();
6063
if (rev !== null) module.exports.globalLabels.git_rev = rev;
@@ -66,7 +69,10 @@ try {
6669

6770
function gitRev() {
6871
try {
69-
return execSync('git rev-parse --short HEAD', { encoding: 'utf-8' }).trim();
72+
return execSync('git rev-parse --short HEAD', {
73+
encoding: 'utf-8',
74+
stdio: ['ignore', 'pipe', 'ignore'],
75+
}).trim();
7076
} catch (e) {
7177
return null;
7278
}

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -355,7 +355,7 @@
355355
"@types/semver": "^5.5.0",
356356
"@types/sinon": "^7.0.13",
357357
"@types/strip-ansi": "^3.0.0",
358-
"@types/styled-components": "^4.4.0",
358+
"@types/styled-components": "^4.4.1",
359359
"@types/supertest": "^2.0.5",
360360
"@types/supertest-as-promised": "^2.0.38",
361361
"@types/testing-library__react": "^9.1.2",

packages/kbn-babel-preset/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
"@babel/preset-typescript": "^7.3.3",
1515
"babel-plugin-add-module-exports": "^1.0.2",
1616
"babel-plugin-filter-imports": "^3.0.0",
17+
"babel-plugin-styled-components": "^1.10.6",
1718
"babel-plugin-transform-define": "^1.3.1",
1819
"babel-plugin-typescript-strip-namespaces": "^1.1.1"
1920
}

packages/kbn-babel-preset/webpack_preset.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,12 @@ module.exports = () => {
3333
plugins: [
3434
require.resolve('@babel/plugin-transform-modules-commonjs'),
3535
require.resolve('@babel/plugin-syntax-dynamic-import'),
36-
]
36+
[
37+
require.resolve('babel-plugin-styled-components'),
38+
{
39+
fileName: false,
40+
},
41+
],
42+
],
3743
};
3844
};

src/apm.js

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,13 @@ module.exports = function (serviceName = name) {
2525
if (process.env.kbnWorkerType === 'optmzr') return;
2626

2727
const conf = {
28-
serviceName: `${serviceName}-${version.replace(/\./g, '_')}`
28+
serviceName: `${serviceName}-${version.replace(/\./g, '_')}`,
2929
};
3030

31-
if (configFileExists()) conf.configFile = 'config/apm.js';
31+
const configFile = join(__dirname, '..', 'config', 'apm.js');
32+
33+
if (existsSync(configFile)) conf.configFile = configFile;
3234
else conf.active = false;
3335

3436
require('elastic-apm-node').start(conf);
3537
};
36-
37-
function configFileExists() {
38-
return existsSync(join(__dirname, '..', 'config', 'apm.js'));
39-
}

src/core/MIGRATION.md

Lines changed: 50 additions & 76 deletions
Large diffs are not rendered by default.

src/legacy/core_plugins/console/public/np_ready/application/containers/editor/legacy/console_editor/editor.tsx

Lines changed: 64 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,11 @@
2020
import React, { CSSProperties, useCallback, useEffect, useRef, useState } from 'react';
2121
import { EuiToolTip } from '@elastic/eui';
2222
import { i18n } from '@kbn/i18n';
23+
import { debounce } from 'lodash';
24+
25+
// Node v5 querystring for browser.
26+
// @ts-ignore
27+
import * as qs from 'querystring-browser';
2328

2429
import { EuiIcon, EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
2530
import { useServicesContext, useEditorReadContext } from '../../../../contexts';
@@ -80,17 +85,64 @@ function EditorUI() {
8085

8186
useEffect(() => {
8287
editorInstanceRef.current = senseEditor.create(editorRef.current!);
88+
const editor = editorInstanceRef.current;
89+
90+
const readQueryParams = () => {
91+
const [, queryString] = (window.location.hash || '').split('?');
92+
return qs.parse(queryString || '');
93+
};
94+
95+
const loadBufferFromRemote = (url: string) => {
96+
if (/^https?:\/\//.test(url)) {
97+
const loadFrom: Record<string, any> = {
98+
url,
99+
// Having dataType here is required as it doesn't allow jQuery to `eval` content
100+
// coming from the external source thereby preventing XSS attack.
101+
dataType: 'text',
102+
kbnXsrfToken: false,
103+
};
104+
105+
if (/https?:\/\/api\.github\.com/.test(url)) {
106+
loadFrom.headers = { Accept: 'application/vnd.github.v3.raw' };
107+
}
83108

84-
const { content: text } = history.getSavedEditorState() || {
85-
content: DEFAULT_INPUT_VALUE,
109+
// Fire and forget.
110+
$.ajax(loadFrom).done(async data => {
111+
const coreEditor = editor.getCoreEditor();
112+
await editor.update(data, true);
113+
editor.moveToNextRequestEdge(false);
114+
coreEditor.clearSelection();
115+
editor.highlightCurrentRequestsAndUpdateActionBar();
116+
coreEditor.getContainer().focus();
117+
});
118+
}
86119
};
87-
editorInstanceRef.current.update(text);
120+
121+
// Support for loading a console snippet from a remote source, like support docs.
122+
const onHashChange = debounce(() => {
123+
const { load_from: url } = readQueryParams();
124+
if (!url) {
125+
return;
126+
}
127+
loadBufferFromRemote(url);
128+
}, 200);
129+
window.addEventListener('hashchange', onHashChange);
130+
131+
const initialQueryParams = readQueryParams();
132+
if (initialQueryParams.load_from) {
133+
loadBufferFromRemote(initialQueryParams.load_from);
134+
} else {
135+
const { content: text } = history.getSavedEditorState() || {
136+
content: DEFAULT_INPUT_VALUE,
137+
};
138+
editor.update(text);
139+
}
88140

89141
function setupAutosave() {
90142
let timer: number;
91143
const saveDelay = 500;
92144

93-
editorInstanceRef.current!.getCoreEditor().on('change', () => {
145+
editor.getCoreEditor().on('change', () => {
94146
if (timer) {
95147
clearTimeout(timer);
96148
}
@@ -100,35 +152,34 @@ function EditorUI() {
100152

101153
function saveCurrentState() {
102154
try {
103-
const content = editorInstanceRef.current!.getCoreEditor().getValue();
155+
const content = editor.getCoreEditor().getValue();
104156
history.updateCurrentState(content);
105157
} catch (e) {
106158
// Ignoring saving error
107159
}
108160
}
109161

110-
setInputEditor(editorInstanceRef.current);
162+
setInputEditor(editor);
111163
setTextArea(editorRef.current!.querySelector('textarea'));
112164

113165
mappings.retrieveAutoCompleteInfo();
114166

115-
const unsubscribeResizer = subscribeResizeChecker(
116-
editorRef.current!,
117-
editorInstanceRef.current.getCoreEditor()
118-
);
167+
const unsubscribeResizer = subscribeResizeChecker(editorRef.current!, editor.getCoreEditor());
119168
setupAutosave();
120169

121170
return () => {
122171
unsubscribeResizer();
123172
mappings.clearSubscriptions();
173+
window.removeEventListener('hashchange', onHashChange);
124174
};
125175
}, [history, setInputEditor]);
126176

127177
useEffect(() => {
128-
applyCurrentSettings(editorInstanceRef.current!.getCoreEditor(), settings);
178+
const { current: editor } = editorInstanceRef;
179+
applyCurrentSettings(editor!.getCoreEditor(), settings);
129180
// Preserve legacy focus behavior after settings have updated.
130-
editorInstanceRef
131-
.current!.getCoreEditor()
181+
editor!
182+
.getCoreEditor()
132183
.getContainer()
133184
.focus();
134185
}, [settings]);

src/legacy/core_plugins/console/public/np_ready/application/hooks/use_set_input_editor.ts

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,18 @@
1616
* specific language governing permissions and limitations
1717
* under the License.
1818
*/
19-
19+
import { useCallback } from 'react';
2020
import { useEditorActionContext } from '../contexts/editor_context';
2121
import { instance as registry } from '../contexts/editor_context/editor_registry';
2222

2323
export const useSetInputEditor = () => {
2424
const dispatch = useEditorActionContext();
2525

26-
return (editor: any) => {
27-
dispatch({ type: 'setInputEditor', payload: editor });
28-
registry.setInputEditor(editor);
29-
};
26+
return useCallback(
27+
(editor: any) => {
28+
dispatch({ type: 'setInputEditor', payload: editor });
29+
registry.setInputEditor(editor);
30+
},
31+
[dispatch]
32+
);
3033
};

src/legacy/core_plugins/console/public/np_ready/application/models/legacy_core_editor/legacy_core_editor.ts

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -104,25 +104,12 @@ export class LegacyCoreEditor implements CoreEditor {
104104
return this.editor.getValue();
105105
}
106106

107-
setValue(text: string, forceRetokenize: boolean): Promise<void> {
107+
async setValue(text: string, forceRetokenize: boolean): Promise<void> {
108108
const session = this.editor.getSession();
109109
session.setValue(text);
110-
return new Promise(resolve => {
111-
if (!forceRetokenize) {
112-
// resolve immediately
113-
resolve();
114-
return;
115-
}
116-
117-
// force update of tokens, but not on this thread to allow for ace rendering.
118-
setTimeout(function() {
119-
let i;
120-
for (i = 0; i < session.getLength(); i++) {
121-
session.getTokens(i);
122-
}
123-
resolve();
124-
});
125-
});
110+
if (forceRetokenize) {
111+
await this.forceRetokenize();
112+
}
126113
}
127114

128115
getLineValue(lineNumber: number): string {
@@ -241,6 +228,20 @@ export class LegacyCoreEditor implements CoreEditor {
241228
return Boolean((this.editor as any).completer && (this.editor as any).completer.activated);
242229
}
243230

231+
private forceRetokenize() {
232+
const session = this.editor.getSession();
233+
return new Promise(resolve => {
234+
// force update of tokens, but not on this thread to allow for ace rendering.
235+
setTimeout(function() {
236+
let i;
237+
for (i = 0; i < session.getLength(); i++) {
238+
session.getTokens(i);
239+
}
240+
resolve();
241+
});
242+
});
243+
}
244+
244245
// eslint-disable-next-line @typescript-eslint/camelcase
245246
private DO_NOT_USE_onPaste(text: string) {
246247
if (text && curl.detectCURL(text)) {

src/legacy/core_plugins/interpreter/public/canvas/ajax_stream/ajax_stream.test.ts

Lines changed: 28 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ describe('ajaxStream', () => {
2626
it('pulls items from the stream and calls the handler', async () => {
2727
const handler = jest.fn(() => ({}));
2828
const { req, sendText, done } = mockRequest();
29-
const messages = ['{ "hello": "world" }\n', '{ "tis": "fate" }\n'].map(m => `${m.length}:${m}`);
29+
const messages = ['{ "hello": "world" }\n', '{ "tis": "fate" }\n'];
3030

3131
const promise = ajaxStream('', {}, req, {
3232
url: '/test/endpoint',
@@ -43,12 +43,34 @@ describe('ajaxStream', () => {
4343
expect(handler).toHaveBeenCalledWith({ tis: 'fate' });
4444
});
4545

46+
it('handles newlines in values', async () => {
47+
const handler = jest.fn(() => ({}));
48+
const { req, sendText, done } = mockRequest();
49+
const messages = [
50+
JSON.stringify({ hello: 'wo\nrld' }),
51+
'\n',
52+
JSON.stringify({ tis: 'fa\nte' }),
53+
'\n',
54+
];
55+
56+
const promise = ajaxStream('', {}, req, {
57+
url: '/test/endpoint',
58+
onResponse: handler,
59+
});
60+
61+
messages.forEach(sendText);
62+
done();
63+
64+
await promise;
65+
expect(handler).toHaveBeenCalledTimes(2);
66+
expect(handler).toHaveBeenCalledWith({ hello: 'wo\nrld' });
67+
expect(handler).toHaveBeenCalledWith({ tis: 'fa\nte' });
68+
});
69+
4670
it('handles partial messages', async () => {
4771
const handler = jest.fn(() => ({}));
4872
const { req, sendText, done } = mockRequest();
49-
const messages = ['{ "hello": "world" }\n', '{ "tis": "fate" }\n']
50-
.map(m => `${m.length}:${m}`)
51-
.join('');
73+
const messages = ['{ "hello": "world" }\n', '{ "tis": "fate" }\n'].join('');
5274

5375
const promise = ajaxStream('', {}, req, {
5476
url: '/test/endpoint',
@@ -117,7 +139,7 @@ describe('ajaxStream', () => {
117139
it('rejects if the payload contains invalid JSON', async () => {
118140
const handler = jest.fn(() => ({}));
119141
const { req, sendText, done } = mockRequest();
120-
const messages = ['{ waut? }\n'].map(m => `${m.length}:${m}`).join('');
142+
const messages = ['{ waut? }\n'].join('');
121143

122144
const promise = ajaxStream('', {}, req, {
123145
url: '/test/endpoint',
@@ -130,32 +152,12 @@ describe('ajaxStream', () => {
130152
expect(await promise.then(() => true).catch(() => false)).toBeFalsy();
131153
});
132154

133-
it('rejects if the delim is invalid', async () => {
134-
const handler = jest.fn(() => ({}));
135-
const { req, sendText, done } = mockRequest();
136-
const messages = '{ "hi": "there" }';
137-
138-
const promise = ajaxStream('', {}, req, {
139-
url: '/test/endpoint',
140-
onResponse: handler,
141-
});
142-
143-
sendText(messages);
144-
done();
145-
146-
expect(await promise.then(() => true).catch(({ message }) => message)).toMatch(
147-
/invalid stream response/i
148-
);
149-
});
150-
151155
it('rejects if the handler throws', async () => {
152156
const handler = jest.fn(() => {
153157
throw new Error('DOH!');
154158
});
155159
const { req, sendText, done } = mockRequest();
156-
const messages = ['{ "hello": "world" }\n', '{ "tis": "fate" }\n']
157-
.map(m => `${m.length}:${m}`)
158-
.join('');
160+
const messages = ['{ "hello": "world" }\n', '{ "tis": "fate" }\n'].join('');
159161

160162
const promise = ajaxStream('', {}, req, {
161163
url: '/test/endpoint',

0 commit comments

Comments
 (0)