Copilot commented on code in PR #3607:
URL:
https://github.com/apache/incubator-kie-tools/pull/3607#discussion_r3325173799
##########
packages/bpmn-editor-envelope/src/BpmnEditorChannelApi.ts:
##########
@@ -19,4 +19,22 @@
import { KogitoEditorChannelApi } from "@kie-tools-core/editor/dist/api";
-export interface BpmnEditorChannelApi extends KogitoEditorChannelApi {}
+export interface RestTaskTestRequest {
+ url: string;
+ method: string;
+ headers: Record<string, string>;
+ body?: string;
+ useCorsProxy: boolean;
+}
+
+export interface RestTaskTestResponse {
+ status: number;
+ data: string;
+ headers?: Record<string, string>;
+}
Review Comment:
`RestTaskTestResponse.data` is typed as `string`, but both the online editor
and VS Code implementations parse JSON responses with `response.json()` and
return an object/array via `data: any` (see
`packages/online-editor/src/editor/EditorPage.tsx` lines 363-366 and
`packages/bpmn-vscode-extension/src/channelApi/BpmnEditorChannelApiImpl.ts`
lines 52-56). The panel itself also handles non-string data by serializing with
`JSON.stringify(testResult.data, null, 2)`. The type should be `string |
unknown` (or `any`/`unknown`) to match the actual contract; otherwise callers
relying on this type may pass it directly into string contexts and break.
##########
packages/bpmn-vscode-extension/src/channelApi/BpmnEditorChannelApiImpl.ts:
##########
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { DefaultVsCodeKieEditorChannelApiImpl } from
"@kie-tools-core/vscode-extension/dist/DefaultVsCodeKieEditorChannelApiImpl";
+import {
+ BpmnEditorChannelApi,
+ RestTaskTestRequest,
+ RestTaskTestResponse,
+} from "@kie-tools/bpmn-editor-envelope/dist/BpmnEditorChannelApi";
+
+export class BpmnEditorChannelApiImpl extends
DefaultVsCodeKieEditorChannelApiImpl implements BpmnEditorChannelApi {
+ constructor(
+ protected readonly editor: any,
+ protected readonly resourceContentService: any,
+ protected readonly vscodeWorkspace: any,
+ protected readonly vscodeNotifications: any,
+ protected readonly javaCodeCompletionApi: any,
+ protected readonly viewType: string,
+ protected readonly i18n: any
+ ) {
+ super(editor, resourceContentService, vscodeWorkspace,
vscodeNotifications, javaCodeCompletionApi, viewType, i18n);
+ }
Review Comment:
All constructor parameters are typed as `any`, losing type safety provided
by `VsCodeKieEditorChannelApiProducer.get` (see
`packages/vscode-extension/src/VsCodeKieEditorChannelApiProducer.ts:34-53`).
Because this class extends `DefaultVsCodeKieEditorChannelApiImpl`, you can drop
the explicit constructor entirely and let TypeScript infer the parent's
signature, or import the proper types (`VsCodeKieEditorController`,
`ResourceContentService`, `VsCodeWorkspaceChannelApiImpl`,
`VsCodeNotificationsChannelApiImpl`, `JavaCodeCompletionApi`,
`I18n<VsCodeI18n>`).
##########
packages/online-editor/src/editor/EditorPage.tsx:
##########
@@ -91,8 +95,14 @@ export function EditorPage() {
const [_, setEditorPageError] = useState(false);
const lastContent = useRef<string>();
const workspaceFilePromise = useWorkspaceFilePromise(workspaceId,
fileRelativePath);
+ const [isReady, setReady] = useState(false);
Review Comment:
`isReady` is lifted to parent state but is never reset to `false` when the
active file changes. `<EmbeddedEditor key={uniqueFileId} ...>` remounts on file
switch, but the parent's `isReady` stays `true` from the previous file, so
`EmbeddedEditor` reports `isReady: true` (via `props.isReady ?? isReady`)
before the newly mounted editor has actually signaled `kogitoEditor_ready`.
Consumers relying on `isReady` will act on a stale value. Consider resetting
`setReady(false)` in an effect keyed on `uniqueFileId`/`embeddedEditorFile`, or
only resolve `kogitoEditor_ready` after a corresponding reset on file change.
##########
packages/bpmn-editor-envelope/src/BpmnEditorChannelApi.ts:
##########
@@ -19,4 +19,22 @@
import { KogitoEditorChannelApi } from "@kie-tools-core/editor/dist/api";
-export interface BpmnEditorChannelApi extends KogitoEditorChannelApi {}
+export interface RestTaskTestRequest {
+ url: string;
+ method: string;
+ headers: Record<string, string>;
+ body?: string;
+ useCorsProxy: boolean;
+}
+
+export interface RestTaskTestResponse {
+ status: number;
+ data: string;
+ headers?: Record<string, string>;
+}
+
+export interface BpmnServiceApi extends KogitoEditorChannelApi {
+ bpmnEditor_restTaskTest?(request: RestTaskTestRequest):
Promise<RestTaskTestResponse>;
+}
+
+export interface BpmnEditorChannelApi extends KogitoEditorChannelApi,
BpmnServiceApi {}
Review Comment:
`BpmnServiceApi` already extends `KogitoEditorChannelApi`, so
`BpmnEditorChannelApi extends KogitoEditorChannelApi, BpmnServiceApi` is
redundant (`BpmnEditorChannelApi` is structurally identical to
`BpmnServiceApi`). Either drop `BpmnServiceApi` and put
`bpmnEditor_restTaskTest` directly on `BpmnEditorChannelApi`, or have
`BpmnServiceApi` not extend `KogitoEditorChannelApi` and keep the composition
on `BpmnEditorChannelApi` only.
##########
packages/online-editor/src/editor/EditorPage.tsx:
##########
@@ -327,11 +337,90 @@ export function EditorPage() {
[workspaceFilePromise, workspaces, navigate, routes]
);
+ const handleRestTaskTest = useCallback(
+ async (request: {
+ url: string;
+ method: string;
+ headers: Record<string, string>;
+ body?: string;
+ useCorsProxy: boolean;
+ }): Promise<{ status: number; data: string; headers?: Record<string,
string> }> => {
+ try {
+ const targetUrl =
+ request.useCorsProxy && env.KIE_SANDBOX_CORS_PROXY_URL
+ ?
`${env.KIE_SANDBOX_CORS_PROXY_URL}/${request.url.replace(/^https?:\/\//, "")}`
+ : request.url;
+
+ const response = await fetch(targetUrl, {
+ method: request.method,
+ headers: request.headers,
+ body: request.body,
+ });
+
+ const contentType = response.headers.get("content-type");
+ let data: any;
+
+ if (contentType?.includes("application/json")) {
+ data = await response.json();
+ } else {
+ data = await response.text();
+ }
+
+ const responseHeaders: Record<string, string> = {};
+ response.headers.forEach((value, key) => {
+ responseHeaders[key] = value;
+ });
+
+ return {
+ status: response.status,
+ data,
+ headers: responseHeaders,
+ };
+ } catch (error) {
+ console.error("REST task test request failed:", error);
+ throw error;
+ }
+ },
+ [env.KIE_SANDBOX_CORS_PROXY_URL]
+ );
+
const handleSetContentError = useCallback(() => {
setFileBroken(true);
setContentErrorAlert.show();
}, [setContentErrorAlert]);
+ const kieSandboxEditorChannelApiImpl = useMemo<BpmnEditorChannelApi |
undefined>(() => {
+ if (!embeddedEditorFile) {
+ return undefined;
+ }
+ const defaultApi = new EmbeddedEditorChannelApiImpl(stateControl,
embeddedEditorFile, locale, {});
+ return {
+ kogitoWorkspace_newEdit: (...args) =>
defaultApi.kogitoWorkspace_newEdit(...args),
+ kogitoEditor_stateControlCommandUpdate: (...args) =>
defaultApi.kogitoEditor_stateControlCommandUpdate(...args),
+ kogitoEditor_contentRequest: (...args) =>
defaultApi.kogitoEditor_contentRequest(...args),
+ kogitoWorkspace_resourceContentRequest: handleResourceContentRequest,
+ kogitoWorkspace_resourceListRequest: handleResourceListRequest,
+ kogitoWorkspace_openFile: handleOpenFile,
+ kogitoEditor_ready: () => setReady(true),
+ kogitoEditor_setContentError: handleSetContentError,
+ kogitoEditor_theme: (...args) => defaultApi.kogitoEditor_theme(...args),
+ kogitoI18n_getLocale: (...args) =>
defaultApi.kogitoI18n_getLocale(...args),
+ kogitoNotifications_createNotification: (...args) =>
defaultApi.kogitoNotifications_createNotification(...args),
+ kogitoNotifications_setNotifications: (...args) =>
defaultApi.kogitoNotifications_setNotifications(...args),
+ kogitoNotifications_removeNotifications: (...args) =>
defaultApi.kogitoNotifications_removeNotifications(...args),
+ bpmnEditor_restTaskTest: handleRestTaskTest,
+ };
+ }, [
+ embeddedEditorFile,
+ stateControl,
+ locale,
+ handleResourceContentRequest,
+ handleResourceListRequest,
+ handleOpenFile,
+ handleSetContentError,
+ handleRestTaskTest,
+ ]);
Review Comment:
When the active file changes, `kieSandboxEditorChannelApiImpl` is rebuilt
and a new `EmbeddedEditorChannelApiImpl` is constructed inside `useMemo`. The
dependency list contains `stateControl`, `locale` and the various handlers, but
the `defaultApi` instance captures `embeddedEditorFile` (via `getFileContents`)
only at construction time. Any change to `embeddedEditorFile` that does not
also change its identity (e.g. an updated `getFileContents` closure on the same
object) will leave the `EmbeddedEditorChannelApiImpl` referencing stale file
content for `kogitoEditor_contentRequest`. Consider adding
`embeddedEditorFile.getFileContents` (or the whole `embeddedEditorFile`)
explicitly so this stays consistent with how `EmbeddedEditor` itself rebuilds
its default channel.
##########
packages/bpmn-editor-envelope/src/customTasks/RestServiceTaskConstants.tsx:
##########
@@ -0,0 +1,104 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import * as React from "react";
+import { DEFAULT_DATA_TYPES } from
"@kie-tools/bpmn-editor/dist/mutations/addOrGetItemDefinitions";
+
+export enum RestProperties {
+ Method = "Method",
+ Url = "Url",
+ Protocol = "Protocol",
+ Host = "Host",
+ Port = "Port",
+ ContentData = "ContentData",
+ RequestTimeout = "RequestTimeout",
+ AccessTokenAcquisitionStrategy = "AccessTokenAcquisitionStrategy",
+ RestServiceCallTaskId = "RestServiceCallTaskId",
+}
+
+export enum HttpMethod {
+ GET = "GET",
+ POST = "POST",
+ PUT = "PUT",
+ PATCH = "PATCH",
+ DELETE = "DELETE",
+}
+
+export enum AuthStrategy {
+ PROPAGATED = "propagated",
+ CONFIGURED = "configured",
+ NONE = "none",
+}
+
+export const HTTP_METHODS_OPTIONS = [
+ { value: HttpMethod.GET, labelKey: "httpMethodGet" },
+ { value: HttpMethod.POST, labelKey: "httpMethodPost" },
+ { value: HttpMethod.PUT, labelKey: "httpMethodPut" },
+ { value: HttpMethod.PATCH, labelKey: "httpMethodPatch" },
+ { value: HttpMethod.DELETE, labelKey: "httpMethodDelete" },
+] as const;
+
+export const AUTH_STRATEGIES_OPTIONS = [
+ { value: AuthStrategy.PROPAGATED, labelKey: "authStrategyPropagated" },
+ { value: AuthStrategy.CONFIGURED, labelKey: "authStrategyConfigured" },
+ { value: AuthStrategy.NONE, labelKey: "authStrategyNone" },
+] as const;
+
+export const REST_PROPERTIES_KEYS = [
+ RestProperties.Method,
+ RestProperties.Url,
+ RestProperties.Protocol,
+ RestProperties.Host,
+ RestProperties.Port,
+ RestProperties.ContentData,
+ RestProperties.RequestTimeout,
+ RestProperties.AccessTokenAcquisitionStrategy,
+ RestProperties.RestServiceCallTaskId,
+] as const;
+
+export const REST_TASK_ICON = (
+ <svg
+ width="30"
+ height="30"
+ viewBox="0 0 30 30"
+ xmlns="http://www.w3.org/2000/svg"
+ fill="none"
+ stroke="black"
+ strokeWidth="1"
+ >
+ <text x="15" y="25" textAnchor="middle" fontSize="24" fontFamily="Arial"
fontWeight={"light"}>
+ 🌐
+ </text>
+ </svg>
+);
Review Comment:
The REST task icon is a Unicode emoji (🌐) inside an SVG `<text>` element.
Emoji glyphs render very differently across operating systems and Monaco-style
sandboxes, and may not appear at all if the system font lacks an emoji glyph,
leading to an empty task icon. Other built-in tasks (e.g. `MilestoneTask`) ship
with a proper vector icon — consider using a real SVG path/icon or a PatternFly
icon to ensure consistent rendering in VS Code, online editor, and standalone.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]