Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Console] Monaco migration: send request and copy as curl buttons #179808

Merged
merged 19 commits into from
Apr 16, 2024
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions packages/kbn-monaco/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,8 @@ export {
CONSOLE_OUTPUT_LANG_ID,
CONSOLE_THEME_ID,
CONSOLE_OUTPUT_THEME_ID,
getParsedRequestsProvider,
ConsoleParsedRequestsProvider,
} from './src/console';

export type { ParsedRequest } from './src/console';
56 changes: 56 additions & 0 deletions packages/kbn-monaco/src/console/console_errors_provider.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
* 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 { ConsoleWorkerProxyService } from './console_worker_proxy';
import { CONSOLE_LANG_ID } from './constants';
import { monaco } from '../monaco_imports';

export const setupConsoleErrorsProvider = (workerProxyService: ConsoleWorkerProxyService) => {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this file is copied from the previously used file packages/kbn-monaco/src/ace_migration/setup_worker.ts

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might be helpful to add some documentation here that explains what this function does.

const updateErrorMarkers = async (model: monaco.editor.IModel): Promise<void> => {
if (model.isDisposed()) {
return;
}
const parserResult = await workerProxyService.getParserResult(model.uri);

if (!parserResult) {
return;
}
const { errors } = parserResult;
monaco.editor.setModelMarkers(
model,
CONSOLE_LANG_ID,
errors.map(({ offset, text }) => {
const { column, lineNumber } = model.getPositionAt(offset);
return {
startLineNumber: lineNumber,
startColumn: column,
endLineNumber: lineNumber,
endColumn: column,
message: text,
severity: monaco.MarkerSeverity.Error,
};
})
);
};
const onModelAdd = (model: monaco.editor.IModel) => {
if (model.getLanguageId() !== CONSOLE_LANG_ID) {
return;
}

const { dispose } = model.onDidChangeContent(async () => {
await updateErrorMarkers(model);
});

model.onWillDispose(() => {
dispose();
});

updateErrorMarkers(model);
};
monaco.editor.onDidCreateModel(onModelAdd);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* 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 { ConsoleWorkerProxyService } from './console_worker_proxy';
import { ParsedRequest } from './types';
import { monaco } from '../monaco_imports';

export class ConsoleParsedRequestsProvider {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Documentation would be helpful here as well.

constructor(
private workerProxyService: ConsoleWorkerProxyService,
private model: monaco.editor.ITextModel | null
) {}
public async getRequests(): Promise<ParsedRequest[]> {
if (!this.model) {
return [];
}
const parserResult = await this.workerProxyService.getParserResult(this.model.uri);
return parserResult?.requests ?? [];
}
}
32 changes: 32 additions & 0 deletions packages/kbn-monaco/src/console/console_worker_proxy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* 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 { monaco } from '../monaco_imports';
import { CONSOLE_LANG_ID } from './constants';
import { ConsoleParserResult, ConsoleWorkerDefinition } from './types';

export class ConsoleWorkerProxyService {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this file is copied from the previously used file packages/kbn-monaco/src/ace_migration/worker_proxy.ts

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Documentation would be helpful here as well.

private worker: monaco.editor.MonacoWebWorker<ConsoleWorkerDefinition> | undefined;

public async getParserResult(modelUri: monaco.Uri): Promise<ConsoleParserResult | undefined> {
if (!this.worker) {
throw new Error('Worker Proxy Service has not been setup!');
}
await this.worker.withSyncedResources([modelUri]);
const parser = await this.worker.getProxy();
return parser.getParserResult(modelUri.toString());
}

public setup() {
this.worker = monaco.editor.createWebWorker({ label: CONSOLE_LANG_ID, moduleId: '' });
}

public stop() {
if (this.worker) this.worker.dispose();
}
}
4 changes: 4 additions & 0 deletions packages/kbn-monaco/src/console/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,7 @@ export const ConsoleOutputLang: LangModuleType = {
lexerRules: consoleOutputLexerRules,
languageConfiguration: consoleOutputLanguageConfiguration,
};

export type { ParsedRequest } from './types';
export { getParsedRequestsProvider } from './language';
export { ConsoleParsedRequestsProvider } from './console_parsed_requests_provider';
17 changes: 11 additions & 6 deletions packages/kbn-monaco/src/console/language.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,19 @@
* Side Public License, v 1.
*/

import { ConsoleWorker } from './worker';
import { WorkerProxyService } from '../ace_migration/worker_proxy';
import { setupConsoleErrorsProvider } from './console_errors_provider';
import { ConsoleWorkerProxyService } from './console_worker_proxy';
import { monaco } from '../monaco_imports';
import { CONSOLE_LANG_ID } from './constants';
import { setupWorker } from '../ace_migration/setup_worker';
import { ConsoleParsedRequestsProvider } from './console_parsed_requests_provider';

const workerProxyService = new ConsoleWorkerProxyService();

export const getParsedRequestsProvider = (model: monaco.editor.ITextModel | null) => {
return new ConsoleParsedRequestsProvider(workerProxyService, model);
};

const OWNER = 'CONSOLE_GRAMMAR_CHECKER';
const wps = new WorkerProxyService<ConsoleWorker>();
monaco.languages.onLanguage(CONSOLE_LANG_ID, async () => {
setupWorker(CONSOLE_LANG_ID, OWNER, wps);
workerProxyService.setup();
setupConsoleErrorsProvider(workerProxyService);
});
64 changes: 53 additions & 11 deletions packages/kbn-monaco/src/console/parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ export const createParser = () => {

let at, // The index of the current character
ch, // The current character
annos, // annotations
escapee = {
'"': '"',
'\\': '\\',
Expand All @@ -24,8 +23,44 @@ export const createParser = () => {
t: '\t',
},
text,
annotate = function (type, text) {
annos.push({ type: type, text: text, at: at });
errors,
addError = function (text) {
errors.push({ text: text, offset: at });
},
requests,
requestStartOffset,
requestEndOffset,
getLastRequest = function() {
return requests.length > 0 ? requests.pop() : {};
},
addRequestStart = function() {
requestStartOffset = at - 1;
requests.push({ startOffset: requestStartOffset });
},
addRequestMethod = function(method) {
const lastRequest = getLastRequest();
lastRequest.method = method;
requests.push(lastRequest);
requestEndOffset = at - 1;
},
addRequestUrl = function(url) {
const lastRequest = getLastRequest();
lastRequest.url = url;
requests.push(lastRequest);
requestEndOffset = at - 1;
},
addRequestData = function(data) {
const lastRequest = getLastRequest();
const dataArray = lastRequest.data || [];
dataArray.push(data);
lastRequest.data = dataArray;
requests.push(lastRequest);
requestEndOffset = at - 1;
},
addRequestEnd = function() {
const lastRequest = getLastRequest();
lastRequest.endOffset = requestEndOffset;
requests.push(lastRequest);
},
error = function (m) {
throw {
Expand Down Expand Up @@ -373,26 +408,32 @@ export const createParser = () => {
},
request = function () {
white();
method();
addRequestStart();
const parsedMethod = method();
addRequestMethod(parsedMethod);
strictWhite();
url();
const parsedUrl = url();
addRequestUrl(parsedUrl );
strictWhite(); // advance to one new line
newLine();
strictWhite();
if (ch == '{') {
object();
const parsedObject = object();
addRequestData(parsedObject);
}
// multi doc request
strictWhite(); // advance to one new line
newLine();
strictWhite();
while (ch == '{') {
// another object
object();
const parsedObject = object();
addRequestData(parsedObject);
strictWhite();
newLine();
strictWhite();
}
addRequestEnd();
},
comment = function () {
while (ch == '#') {
Expand All @@ -417,7 +458,7 @@ export const createParser = () => {
request();
white();
} catch (e) {
annotate('error', e.message);
addError(e.message);
// snap
const substring = text.substr(at);
const nextMatch = substring.search(/^POST|HEAD|GET|PUT|DELETE|PATCH/m);
Expand All @@ -432,15 +473,16 @@ export const createParser = () => {

text = source;
at = 0;
annos = [];
errors = [];
requests = [];
next();
multi_request();
white();
if (ch) {
annotate('error', 'Syntax error');
addError('Syntax error');
}

result = { annotations: annos };
result = { errors, requests };

return typeof reviver === 'function'
? (function walk(holder, key) {
Expand Down
29 changes: 29 additions & 0 deletions packages/kbn-monaco/src/console/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* 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.
*/

export interface ErrorAnnotation {
offset: number;
text: string;
}

export interface ParsedRequest {
startOffset: number;
endOffset: number;
method: string;
url: string;
data?: Array<Record<string, unknown>>;
}
export interface ConsoleParserResult {
errors: ErrorAnnotation[];
requests: ParsedRequest[];
}

export interface ConsoleWorkerDefinition {
getParserResult: (modelUri: string) => ConsoleParserResult | undefined;
}
export type ConsoleParser = (source: string) => ConsoleParserResult | undefined;
13 changes: 8 additions & 5 deletions packages/kbn-monaco/src/console/worker/console_worker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,23 @@

/* eslint-disable-next-line @kbn/eslint/module_migration */
import * as monaco from 'monaco-editor/esm/vs/editor/editor.api';
import { Parser, ParseResult } from '../../ace_migration/types';
import { ConsoleParserResult, ConsoleWorkerDefinition, ConsoleParser } from '../types';
import { createParser } from '../parser';

export class ConsoleWorker {
export class ConsoleWorker implements ConsoleWorkerDefinition {
private parser: ConsoleParser | undefined;
private parserResult: ConsoleParserResult | undefined;

constructor(private ctx: monaco.worker.IWorkerContext) {}
private parser: Parser | undefined;

async parse(modelUri: string): Promise<ParseResult | undefined> {
getParserResult(modelUri: string): ConsoleParserResult | undefined {
if (!this.parser) {
this.parser = createParser();
}
const model = this.ctx.getMirrorModels().find((m) => m.uri.toString() === modelUri);
if (model) {
return this.parser(model.getValue());
this.parserResult = this.parser(model.getValue());
}
return this.parserResult;
}
}
Loading