@motiadev/workbench 0.1.0-beta.9 → 0.2.0-beta.31
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.html +2 -1
- package/dist/src/components/app-sidebar.js +2 -2
- package/dist/src/components/endpoints/endpoint-badge.d.ts +10 -0
- package/dist/src/components/endpoints/endpoint-badge.js +22 -0
- package/dist/src/components/endpoints/endpoint-call.d.ts +8 -0
- package/dist/src/components/endpoints/endpoint-call.js +55 -0
- package/dist/src/components/endpoints/endpoints.d.ts +1 -0
- package/dist/src/components/endpoints/endpoints.js +34 -0
- package/dist/src/components/endpoints/hooks/use-get-endpoints.d.ts +15 -0
- package/dist/src/components/endpoints/hooks/use-get-endpoints.js +19 -0
- package/dist/src/components/endpoints/hooks/use-json-schema-to-json.d.ts +4 -0
- package/dist/src/components/endpoints/hooks/use-json-schema-to-json.js +11 -0
- package/dist/src/components/endpoints/hooks/use-path-params.d.ts +1 -0
- package/dist/src/components/endpoints/hooks/use-path-params.js +4 -0
- package/dist/src/components/endpoints/hooks/utils.d.ts +1 -0
- package/dist/src/components/endpoints/hooks/utils.js +29 -0
- package/dist/src/components/endpoints/response-body.d.ts +7 -0
- package/dist/src/components/endpoints/response-body.js +6 -0
- package/dist/src/components/endpoints/selected-endpoint.d.ts +7 -0
- package/dist/src/components/endpoints/selected-endpoint.js +7 -0
- package/dist/src/components/logs/log-level-dot.d.ts +4 -0
- package/dist/src/components/logs/log-level-dot.js +17 -0
- package/dist/src/components/logs/logs.js +3 -3
- package/dist/src/components/ui/sidebar.js +2 -2
- package/dist/src/components/ui/table.js +1 -1
- package/dist/src/index.css +75 -63
- package/dist/src/main.js +2 -1
- package/dist/src/publicComponents/api-node.js +1 -1
- package/dist/src/publicComponents/base-node.js +3 -3
- package/dist/src/publicComponents/event-node.js +1 -1
- package/dist/src/routes/endpoints-page.d.ts +1 -0
- package/dist/src/routes/endpoints-page.js +5 -0
- package/dist/src/routes/states-page.js +1 -1
- package/dist/src/views/flow/flow-view.js +2 -2
- package/dist/src/views/flow/hooks/use-get-flow-state.js +1 -1
- package/dist/src/views/flow/nodes/language-indicator.js +4 -4
- package/dist/tailwind.config.js +0 -14
- package/dist/tsconfig.app.tsbuildinfo +1 -1
- package/dist/tsconfig.node.tsbuildinfo +1 -1
- package/package.json +1 -1
package/dist/index.html
CHANGED
|
@@ -3,9 +3,10 @@
|
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="UTF-8" />
|
|
5
5
|
|
|
6
|
+
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
|
6
7
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
|
7
8
|
<link
|
|
8
|
-
href="https://fonts.googleapis.com/css2?family=
|
|
9
|
+
href="https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap"
|
|
9
10
|
rel="stylesheet"
|
|
10
11
|
/>
|
|
11
12
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useListFlows } from '@/hooks/use-list-flows';
|
|
3
|
-
import { File, Logs, Workflow } from 'lucide-react';
|
|
3
|
+
import { File, Link2, Logs, Workflow } from 'lucide-react';
|
|
4
4
|
import { Link, useLocation } from 'react-router';
|
|
5
5
|
import { Sidebar, SidebarButton, SidebarGroup } from './ui/sidebar';
|
|
6
6
|
import { Badge } from './ui/badge';
|
|
@@ -10,5 +10,5 @@ export const AppSidebar = () => {
|
|
|
10
10
|
const { pathname } = useLocation();
|
|
11
11
|
const isActive = (flowId) => pathname.includes(`/flow/${flowId}`);
|
|
12
12
|
const unreadLogsCount = useLogs((state) => state.unreadLogsCount);
|
|
13
|
-
return (_jsxs(Sidebar, { children: [_jsxs(SidebarGroup, { title: "Motia", children: [_jsx(Link, { to: "/logs", children: _jsxs(SidebarButton, { isActive: pathname === '/logs', icon: _jsx(Logs, { className: "w-4 h-4" }), children: ["Logs", pathname !== '/logs' && unreadLogsCount > 0 && _jsx(Badge, { variant: "red-rounded", children: unreadLogsCount })] }) }), _jsx(Link, { to: "/states", children: _jsx(SidebarButton, { isActive: pathname === '/states', icon: _jsx(File, { className: "w-4 h-4" }), children: "States" }) })] }), _jsx(SidebarGroup, { title: "Flows", children: flows.map((flow) => (_jsx(Link, { to: `/flow/${flow.id}`, children: _jsx(SidebarButton, { isActive: isActive(flow.id), icon: _jsx(Workflow, { className: "w-4 h-4" }), children: flow.name }) }, flow.id))) })] }));
|
|
13
|
+
return (_jsxs(Sidebar, { children: [_jsxs(SidebarGroup, { title: "Motia", children: [_jsx(Link, { to: "/logs", children: _jsxs(SidebarButton, { isActive: pathname === '/logs', icon: _jsx(Logs, { className: "w-4 h-4" }), children: ["Logs", pathname !== '/logs' && unreadLogsCount > 0 && _jsx(Badge, { variant: "red-rounded", children: unreadLogsCount })] }) }), _jsx(Link, { to: "/states", children: _jsx(SidebarButton, { isActive: pathname === '/states', icon: _jsx(File, { className: "w-4 h-4" }), children: "States" }) }), _jsx(Link, { to: "/endpoints", children: _jsx(SidebarButton, { isActive: pathname === '/endpoints', icon: _jsx(Link2, { className: "w-4 h-4" }), children: "Endpoints" }) })] }), _jsx(SidebarGroup, { title: "Flows", children: flows.map((flow) => (_jsx(Link, { to: `/flow/${flow.id}`, children: _jsx(SidebarButton, { isActive: isActive(flow.id), icon: _jsx(Workflow, { className: "w-4 h-4" }), children: flow.name }) }, flow.id))) })] }));
|
|
14
14
|
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { type VariantProps } from 'class-variance-authority';
|
|
3
|
+
declare const badgeVariants: (props?: ({
|
|
4
|
+
variant?: "POST" | "GET" | "PUT" | "DELETE" | "PATCH" | "HEAD" | "OPTIONS" | null | undefined;
|
|
5
|
+
defaultVariants?: "variant" | null | undefined;
|
|
6
|
+
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
7
|
+
interface BadgeProps extends React.HTMLAttributes<HTMLDivElement>, VariantProps<typeof badgeVariants> {
|
|
8
|
+
}
|
|
9
|
+
export declare function EndpointBadge({ className, variant, ...props }: BadgeProps): import("react/jsx-runtime").JSX.Element;
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { cva } from 'class-variance-authority';
|
|
3
|
+
import { cn } from '@/lib/utils';
|
|
4
|
+
const badgeVariants = cva('inline-flex items-center rounded-lg border px-2 py-1 text-xs font-bold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2', {
|
|
5
|
+
variants: {
|
|
6
|
+
variant: {
|
|
7
|
+
POST: 'bg-sky-500/50 text-sky-100',
|
|
8
|
+
GET: 'bg-lime-500/50 text-lime-100',
|
|
9
|
+
PUT: 'bg-yellow-500/50 text-yellow-100',
|
|
10
|
+
DELETE: 'bg-red-500/50 text-red-100',
|
|
11
|
+
PATCH: 'bg-yellow-500/50 text-yellow-100',
|
|
12
|
+
HEAD: 'bg-blue-500/50 text-blue-100',
|
|
13
|
+
OPTIONS: 'bg-purple-500/50 text-purple-100',
|
|
14
|
+
},
|
|
15
|
+
defaultVariants: {
|
|
16
|
+
variant: 'bg-blue-500/50 text-blue-100',
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
});
|
|
20
|
+
export function EndpointBadge({ className, variant, ...props }) {
|
|
21
|
+
return _jsx("div", { className: cn(badgeVariants({ variant }), className), ...props });
|
|
22
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useMemo, useState } from 'react';
|
|
3
|
+
import { Loader2, Play, X } from 'lucide-react';
|
|
4
|
+
import { Button } from '../ui/button';
|
|
5
|
+
import { Input } from '../ui/input';
|
|
6
|
+
import { Textarea } from '../ui/textarea';
|
|
7
|
+
import { EndpointBadge } from './endpoint-badge';
|
|
8
|
+
import { useJsonSchemaToJson } from './hooks/use-json-schema-to-json';
|
|
9
|
+
import { usePathParams } from './hooks/use-path-params';
|
|
10
|
+
export const EndpointCall = ({ endpoint, onClose }) => {
|
|
11
|
+
const shouldHaveBody = ['post', 'put', 'patch'].includes(endpoint.method.toLowerCase());
|
|
12
|
+
const [isRequestLoading, setIsRequestLoading] = useState(false);
|
|
13
|
+
const [responseCode, setResponseCode] = useState();
|
|
14
|
+
const [responseBody, setResponseBody] = useState();
|
|
15
|
+
const [executionTime, setExecutionTime] = useState();
|
|
16
|
+
const { body, setBody } = useJsonSchemaToJson(endpoint.bodySchema);
|
|
17
|
+
const pathParams = usePathParams(endpoint.path);
|
|
18
|
+
const [pathParamsValues, setPathParamsValues] = useState(pathParams?.reduce((acc, param) => ({ ...acc, [param]: '' }), {}));
|
|
19
|
+
const [queryParamsValues, setQueryParamsValues] = useState(endpoint.queryParams?.reduce((acc, param) => ({ ...acc, [param.name]: '' }), {}) ?? {});
|
|
20
|
+
const isPlayEnabled = useMemo(() => {
|
|
21
|
+
if (!pathParams)
|
|
22
|
+
return true;
|
|
23
|
+
return pathParams?.every((param) => pathParamsValues[param]);
|
|
24
|
+
}, [pathParams, pathParamsValues]);
|
|
25
|
+
const onPathParamChange = (param, value) => {
|
|
26
|
+
setPathParamsValues((prev) => ({ ...prev, [param]: value }));
|
|
27
|
+
};
|
|
28
|
+
const onQueryParamChange = (param, value) => {
|
|
29
|
+
setQueryParamsValues((prev) => ({ ...prev, [param]: value }));
|
|
30
|
+
};
|
|
31
|
+
const handleRequest = async () => {
|
|
32
|
+
setIsRequestLoading(true);
|
|
33
|
+
const startTime = Date.now();
|
|
34
|
+
const path = new URL(window.location.origin +
|
|
35
|
+
pathParams.reduce((acc, param) => {
|
|
36
|
+
return acc.replace(`:${param}`, pathParamsValues[param]);
|
|
37
|
+
}, endpoint.path));
|
|
38
|
+
for (const [key, value] of Object.entries(queryParamsValues)) {
|
|
39
|
+
path.searchParams.set(key, value);
|
|
40
|
+
}
|
|
41
|
+
const response = await fetch(path.toString(), {
|
|
42
|
+
method: endpoint.method,
|
|
43
|
+
headers: { 'Content-Type': 'application/json' },
|
|
44
|
+
body: endpoint.method === 'GET' ? null : body,
|
|
45
|
+
});
|
|
46
|
+
const endTime = Date.now();
|
|
47
|
+
const executionTime = endTime - startTime;
|
|
48
|
+
const json = await response.json();
|
|
49
|
+
setResponseCode(response.status);
|
|
50
|
+
setResponseBody(json);
|
|
51
|
+
setExecutionTime(executionTime);
|
|
52
|
+
setIsRequestLoading(false);
|
|
53
|
+
};
|
|
54
|
+
return (_jsxs("div", { className: "flex flex-col gap-2 overflow-y-auto", children: [_jsxs("div", { className: "text-xs flex flex-row gap-2 items-center justify-between w-full", children: [_jsx("span", { className: "font-bold", children: "Request" }), _jsx("div", { className: "flex flex-row gap-2 items-center hover:bg-white/10 rounded-md p-1", children: _jsx(X, { className: "cursor-pointer w-4 h-4", onClick: onClose }) })] }), _jsxs("div", { className: "flex flex-row gap-2 items-center", children: [_jsx(EndpointBadge, { variant: endpoint.method, children: endpoint.method.toUpperCase() }), _jsx("span", { className: "text-md font-bold", children: endpoint.path })] }), _jsx("span", { className: "text-xs text-muted-foreground", children: endpoint.description }), !!pathParams.length && (_jsxs("div", { className: "flex flex-col gap-2 p-4 rounded-lg bg-muted", children: [_jsx("span", { className: "text-xs font-bold", children: "Path Params" }), _jsx("div", { className: "flex flex-col gap-4", children: pathParams.map((param) => (_jsxs("div", { className: "text-xs", children: [_jsx("div", { className: "font-bold mb-2", children: param }), _jsx(Input, { className: "w-full", value: pathParamsValues[param], onChange: (e) => onPathParamChange(param, e.target.value) })] }, param))) })] })), !!endpoint.queryParams?.length && (_jsxs("div", { className: "flex flex-col gap-2 p-4 rounded-lg bg-muted", children: [_jsx("span", { className: "text-xs font-bold", children: "Query Params" }), _jsx("div", { className: "flex flex-col gap-4", children: endpoint.queryParams.map((param) => (_jsxs("div", { className: "text-xs", children: [_jsx("div", { className: "font-bold mb-2", children: param.name }), _jsx(Input, { className: "w-full", value: queryParamsValues[param.name], onChange: (e) => onQueryParamChange(param.name, e.target.value) })] }, param.name))) })] })), shouldHaveBody && (_jsxs("div", { className: "flex flex-col gap-2 p-4 rounded-lg bg-muted", children: [_jsx("span", { className: "text-xs font-bold", children: "Body" }), _jsx(Textarea, { className: "w-full font-mono font-medium min-h-[200px]", value: body, onChange: (e) => setBody(e.target.value) })] })), _jsxs(Button, { className: "w-fit", onClick: handleRequest, disabled: isRequestLoading || !isPlayEnabled, children: [isRequestLoading ? _jsx(Loader2, { className: "animate-spin" }) : _jsx(Play, {}), " Play"] }), responseCode !== undefined && (_jsxs("div", { className: "flex flex-col gap-2 p-4 rounded-lg bg-muted", children: [_jsxs("span", { className: "text-xs font-bold", children: [_jsx(EndpointBadge, { variant: responseCode >= 400 ? 'DELETE' : 'GET', children: responseCode }), " Execution time: ", _jsxs("span", { className: "text-muted-foreground", children: [executionTime, "ms"] })] }), _jsx("span", { className: "text-xs font-mono font-bold bg-black/50 p-2 rounded-lg whitespace-pre-wrap", children: JSON.stringify(responseBody, null, 2) })] }))] }));
|
|
55
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const Endpoints: () => import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { cva } from 'class-variance-authority';
|
|
3
|
+
import { useEffect, useState } from 'react';
|
|
4
|
+
import { EndpointBadge } from './endpoint-badge';
|
|
5
|
+
import { EndpointCall } from './endpoint-call';
|
|
6
|
+
import { useGetEndpoints } from './hooks/use-get-endpoints';
|
|
7
|
+
import { SelectedEndpoint } from './selected-endpoint';
|
|
8
|
+
const endpointVariants = cva('flex flex-col gap-2 font-mono p-2 rounded-lg cursor-pointer', {
|
|
9
|
+
variants: {
|
|
10
|
+
method: {
|
|
11
|
+
GET: 'bg-lime-500/20',
|
|
12
|
+
POST: 'bg-blue-500/20',
|
|
13
|
+
PUT: 'bg-yellow-500/20',
|
|
14
|
+
DELETE: 'bg-red-500/20',
|
|
15
|
+
PATCH: 'bg-yellow-500/20',
|
|
16
|
+
HEAD: 'bg-blue-500/20',
|
|
17
|
+
OPTIONS: 'bg-purple-500/20',
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
defaultVariants: { method: 'GET' },
|
|
21
|
+
});
|
|
22
|
+
export const Endpoints = () => {
|
|
23
|
+
const endpoints = useGetEndpoints();
|
|
24
|
+
const [selectedEndpoint, setSelectedEndpoint] = useState(null);
|
|
25
|
+
useEffect(() => {
|
|
26
|
+
setSelectedEndpoint((selected) => {
|
|
27
|
+
if (!selected)
|
|
28
|
+
return null;
|
|
29
|
+
const endpoint = endpoints.find((endpoint) => endpoint.method === selected.method && endpoint.path === selected.path);
|
|
30
|
+
return endpoint ?? null;
|
|
31
|
+
});
|
|
32
|
+
}, [endpoints]);
|
|
33
|
+
return (_jsxs("div", { className: "flex flex-row w-full h-screen", children: [_jsxs("div", { className: "flex flex-col gap-2 flex-1 m-4 mr-2 max-h-full overflow-y-auto", children: [_jsxs("header", { children: [_jsx("h1", { className: "text-2xl font-bold", children: "API Endpoints" }), _jsx("span", { className: "text-sm text-zinc-400", children: "Check all API endpoints" })] }), endpoints.map((endpoint) => (_jsxs("div", { className: endpointVariants({ method: endpoint.method }), onClick: () => setSelectedEndpoint(endpoint), children: [_jsxs("div", { className: "flex flex-row gap-2 items-center", children: [_jsx(EndpointBadge, { variant: endpoint.method, children: endpoint.method.toUpperCase() }), _jsx("span", { className: "text-md font-bold", children: endpoint.path }), !selectedEndpoint && _jsx("span", { className: "text-xs text-muted-foreground", children: endpoint.description })] }), selectedEndpoint && _jsx("span", { className: "text-xs text-muted-foreground", children: endpoint.description }), selectedEndpoint === endpoint && _jsx(SelectedEndpoint, { endpoint: selectedEndpoint })] }, `${endpoint.method} ${endpoint.path}`)))] }), selectedEndpoint && (_jsx("div", { className: "flex flex-col gap-2 flex-1 m-4 ml-2 p-4 rounded-lg bg-muted", children: _jsx(EndpointCall, { endpoint: selectedEndpoint, onClose: () => setSelectedEndpoint(null) }) }))] }));
|
|
34
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
type ApiRouteMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'OPTIONS' | 'HEAD';
|
|
2
|
+
type QueryParam = {
|
|
3
|
+
name: string;
|
|
4
|
+
description: string;
|
|
5
|
+
};
|
|
6
|
+
export type ApiEndpoint = {
|
|
7
|
+
method: ApiRouteMethod;
|
|
8
|
+
path: string;
|
|
9
|
+
description?: string;
|
|
10
|
+
queryParams?: QueryParam[];
|
|
11
|
+
responseSchema?: Record<string, any>;
|
|
12
|
+
bodySchema?: Record<string, Record<string, any>>;
|
|
13
|
+
};
|
|
14
|
+
export declare const useGetEndpoints: () => ApiEndpoint[];
|
|
15
|
+
export {};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { useCallback, useEffect, useState } from 'react';
|
|
2
|
+
import { useSocket } from '../../../hooks/use-socket';
|
|
3
|
+
export const useGetEndpoints = () => {
|
|
4
|
+
const { socket } = useSocket();
|
|
5
|
+
const [endpoints, setEndpoints] = useState([]);
|
|
6
|
+
const fetchEndpoints = useCallback(() => {
|
|
7
|
+
fetch(`/api-endpoints`)
|
|
8
|
+
.then((res) => res.json())
|
|
9
|
+
.then((endpoints) => setEndpoints(endpoints));
|
|
10
|
+
}, []);
|
|
11
|
+
useEffect(() => {
|
|
12
|
+
fetchEndpoints();
|
|
13
|
+
socket.on('api-endpoint-changed', fetchEndpoints);
|
|
14
|
+
return () => {
|
|
15
|
+
socket.off('api-endpoint-changed', fetchEndpoints);
|
|
16
|
+
};
|
|
17
|
+
}, [socket, fetchEndpoints]);
|
|
18
|
+
return endpoints;
|
|
19
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { useEffect, useState } from 'react';
|
|
2
|
+
import { convertJsonSchemaToJson } from './utils';
|
|
3
|
+
export const useJsonSchemaToJson = (schema) => {
|
|
4
|
+
const [body, setBody] = useState('');
|
|
5
|
+
useEffect(() => {
|
|
6
|
+
if (schema) {
|
|
7
|
+
setBody(JSON.stringify(convertJsonSchemaToJson(schema), null, 2));
|
|
8
|
+
}
|
|
9
|
+
}, [schema]);
|
|
10
|
+
return { body, setBody };
|
|
11
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const usePathParams: (path: string) => string[];
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const convertJsonSchemaToJson: (schema: Record<string, any>) => any;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export const convertJsonSchemaToJson = (schema) => {
|
|
2
|
+
if (!schema)
|
|
3
|
+
return {};
|
|
4
|
+
if (schema.type === 'object') {
|
|
5
|
+
const result = {};
|
|
6
|
+
if (schema.properties) {
|
|
7
|
+
Object.entries(schema.properties).forEach(([key, value]) => {
|
|
8
|
+
result[key] = convertJsonSchemaToJson(value);
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
return result;
|
|
12
|
+
}
|
|
13
|
+
switch (schema.type) {
|
|
14
|
+
case 'array':
|
|
15
|
+
return [convertJsonSchemaToJson(schema.items)];
|
|
16
|
+
case 'string':
|
|
17
|
+
return schema.description ?? 'string';
|
|
18
|
+
case 'number':
|
|
19
|
+
return schema.description ?? 0;
|
|
20
|
+
case 'integer':
|
|
21
|
+
return 0;
|
|
22
|
+
case 'boolean':
|
|
23
|
+
return schema.description ?? false;
|
|
24
|
+
case 'null':
|
|
25
|
+
return schema.description ?? null;
|
|
26
|
+
default:
|
|
27
|
+
return undefined;
|
|
28
|
+
}
|
|
29
|
+
};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useJsonSchemaToJson } from './hooks/use-json-schema-to-json';
|
|
3
|
+
export const ResponseBody = ({ status, body }) => {
|
|
4
|
+
const { body: responseBody } = useJsonSchemaToJson(body);
|
|
5
|
+
return (_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx("span", { className: "text-xs font-bold", children: status }), _jsx("span", { className: "text-xs font-mono bg-black/50 p-2 rounded-lg whitespace-pre-wrap", children: responseBody })] }));
|
|
6
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { useJsonSchemaToJson } from './hooks/use-json-schema-to-json';
|
|
3
|
+
import { ResponseBody } from './response-body';
|
|
4
|
+
export const SelectedEndpoint = ({ endpoint }) => {
|
|
5
|
+
const { body: requestBody } = useJsonSchemaToJson(endpoint.bodySchema);
|
|
6
|
+
return (_jsxs(_Fragment, { children: [endpoint.queryParams && (_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx("span", { className: "text-xs font-bold", children: "Query Params" }), _jsx("div", { className: "flex flex-col gap-2 flex-1 p-2 rounded-lg bg-muted table", children: endpoint.queryParams.map((param) => (_jsxs("span", { className: "text-xs table-row", children: [_jsx("span", { className: "font-bold table-cell", children: param.name }), _jsx("span", { className: "text-xs table-cell", children: param.description })] }, param.name))) })] })), requestBody && (_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx("span", { className: "text-xs font-bold", children: "Request Body" }), _jsx("span", { className: "text-xs font-mono bg-black/50 p-2 rounded-lg whitespace-pre-wrap", children: requestBody })] })), endpoint.responseSchema && (_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx("span", { className: "text-xs font-bold", children: "Response" }), Object.entries(endpoint.responseSchema).map(([status, schema]) => (_jsx(ResponseBody, { status: status, body: schema }, status)))] }))] }));
|
|
7
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { cva } from 'class-variance-authority';
|
|
3
|
+
const badgeVariants = cva('text-xs font-medium tracking-wide w-2 h-2 rounded-full mx-1', {
|
|
4
|
+
variants: {
|
|
5
|
+
variant: {
|
|
6
|
+
info: 'bg-sky-500',
|
|
7
|
+
trace: 'bg-sky-500',
|
|
8
|
+
debug: 'bg-sky-500',
|
|
9
|
+
error: 'bg-rose-500',
|
|
10
|
+
fatal: 'bg-rose-500',
|
|
11
|
+
warn: 'bg-amber-500',
|
|
12
|
+
},
|
|
13
|
+
},
|
|
14
|
+
});
|
|
15
|
+
export const LogLevelDot = ({ level }) => {
|
|
16
|
+
return _jsx("div", { className: badgeVariants({ variant: level }) });
|
|
17
|
+
};
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { Table, TableBody, TableCell,
|
|
2
|
+
import { Table, TableBody, TableCell, TableRow } from '@/components/ui/table';
|
|
3
3
|
import { useLogs } from '@/stores/use-logs';
|
|
4
|
-
import { LogLevelBadge } from './log-level-badge';
|
|
5
4
|
import { useState } from 'react';
|
|
6
5
|
import { LogDetail } from './log-detail';
|
|
6
|
+
import { LogLevelDot } from './log-level-dot';
|
|
7
7
|
const timestamp = (time) => {
|
|
8
8
|
const date = new Date(Number(time));
|
|
9
9
|
return `${date.toLocaleDateString()} ${date.toLocaleTimeString()}`;
|
|
@@ -14,5 +14,5 @@ export const Logs = () => {
|
|
|
14
14
|
const handleLogClick = (log) => {
|
|
15
15
|
setSelectedLog(log);
|
|
16
16
|
};
|
|
17
|
-
return (_jsxs("div", { className: "overflow-y-auto h-full text-bold p-4", children: [_jsx(LogDetail, { log: selectedLog, onClose: () => setSelectedLog(undefined) }),
|
|
17
|
+
return (_jsxs("div", { className: "overflow-y-auto h-full text-bold p-4", children: [_jsx(LogDetail, { log: selectedLog, onClose: () => setSelectedLog(undefined) }), _jsx(Table, { children: _jsx(TableBody, { className: "text-md font-mono", children: logs.map((log, index) => (_jsxs(TableRow, { className: "cursor-pointer even:bg-muted/50 border-0", onClick: () => handleLogClick(log), children: [_jsxs(TableCell, { className: "whitespace-nowrap flex items-center gap-2", children: [_jsx(LogLevelDot, { level: log.level }), timestamp(log.time)] }), _jsx(TableCell, { className: "whitespace-nowrap text-md font-mono cursor-pointer hover:text-primary text-muted-foreground text-xs font-mono", children: log.traceId }), _jsx(TableCell, { className: "whitespace-nowrap text-md font-mono", children: log.step }), _jsx(TableCell, { className: "whitespace-nowrap text-md font-mono max-w-[500px] truncate w-full", children: log.msg })] }, index))) }) })] }));
|
|
18
18
|
};
|
|
@@ -8,8 +8,8 @@ export const Sidebar = ({ children }) => {
|
|
|
8
8
|
return (_jsxs("div", { className: cn('max-h-screen overflow-y-auto transition-[width] duration-300 border-r border-zinc-800 border-solid', isCollapsed ? 'w-[50px]' : 'w-[250px]'), children: [_jsx("div", { className: "flex items-center justify-end gap-2 px-4 py-3", children: _jsx(Button, { variant: "ghost", size: "icon", onClick: () => setIsCollapsed(!isCollapsed), children: isCollapsed ? _jsx(PanelLeftOpen, { className: "w-4 h-4" }) : _jsx(PanelLeftClose, { className: "w-4 h-4" }) }) }), !isCollapsed && _jsx("div", { className: "overflow-y-auto w-[250px]", children: children })] }));
|
|
9
9
|
};
|
|
10
10
|
export const SidebarGroup = ({ children, title }) => {
|
|
11
|
-
return (_jsxs("div", { className: "flex flex-col", children: [_jsx("h2", { className: "text-
|
|
11
|
+
return (_jsxs("div", { className: "flex flex-col", children: [_jsx("h2", { className: "text-xs font-bold text-muted-foreground px-4 py-2 uppercase", children: title }), children] }));
|
|
12
12
|
};
|
|
13
13
|
export const SidebarButton = ({ children, isActive, icon }) => {
|
|
14
|
-
return (_jsxs("div", { className: cn('flex items-center gap-2 px-4 py-3 ', isActive && 'bg-
|
|
14
|
+
return (_jsxs("div", { className: cn('flex text-sm font-medium items-center gap-2 px-4 py-3 ', isActive && 'bg-muted'), children: [_jsx("div", { className: "text-muted-foreground", children: icon }), children] }));
|
|
15
15
|
};
|
|
@@ -11,7 +11,7 @@ const TableFooter = React.forwardRef(({ className, ...props }, ref) => (_jsx("tf
|
|
|
11
11
|
TableFooter.displayName = 'TableFooter';
|
|
12
12
|
const TableRow = React.forwardRef(({ className, ...props }, ref) => (_jsx("tr", { ref: ref, className: cn('border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted', className), ...props })));
|
|
13
13
|
TableRow.displayName = 'TableRow';
|
|
14
|
-
const TableHead = React.forwardRef(({ className, ...props }, ref) => (_jsx("th", { ref: ref, className: cn('h-10 px-2 text-left align-middle text-
|
|
14
|
+
const TableHead = React.forwardRef(({ className, ...props }, ref) => (_jsx("th", { ref: ref, className: cn('h-10 px-2 text-left align-middle text-md font-medium bg-muted text-muted-foreground first:rounded-l-lg last:rounded-r-lg [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]', className), ...props })));
|
|
15
15
|
TableHead.displayName = 'TableHead';
|
|
16
16
|
const TableCell = React.forwardRef(({ className, ...props }, ref) => (_jsx("td", { ref: ref, className: cn('p-2 align-middle [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]', className), ...props })));
|
|
17
17
|
TableCell.displayName = 'TableCell';
|
package/dist/src/index.css
CHANGED
|
@@ -133,9 +133,7 @@ table {
|
|
|
133
133
|
font-size: 16px;
|
|
134
134
|
|
|
135
135
|
color-scheme: light dark;
|
|
136
|
-
|
|
137
|
-
background-color: #242424;
|
|
138
|
-
|
|
136
|
+
font-family: var(--default-font-family, ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");
|
|
139
137
|
font-synthesis: none;
|
|
140
138
|
text-rendering: optimizeLegibility;
|
|
141
139
|
-webkit-font-smoothing: antialiased;
|
|
@@ -149,7 +147,7 @@ table {
|
|
|
149
147
|
text-rendering: optimizeLegibility;
|
|
150
148
|
-webkit-font-smoothing: antialiased;
|
|
151
149
|
-moz-osx-font-smoothing: grayscale;
|
|
152
|
-
font-family:
|
|
150
|
+
font-family: var(--default-font-family, ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");
|
|
153
151
|
font-optical-sizing: auto;
|
|
154
152
|
}
|
|
155
153
|
|
|
@@ -162,7 +160,7 @@ body {
|
|
|
162
160
|
|
|
163
161
|
button,
|
|
164
162
|
textarea {
|
|
165
|
-
font-family:
|
|
163
|
+
font-family: var(--default-font-family, ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");
|
|
166
164
|
}
|
|
167
165
|
|
|
168
166
|
strong {
|
|
@@ -182,72 +180,72 @@ body,
|
|
|
182
180
|
@layer base {
|
|
183
181
|
:root {
|
|
184
182
|
--background: 0 0% 100%;
|
|
185
|
-
--foreground:
|
|
183
|
+
--foreground: 0 0% 4%;
|
|
186
184
|
--card: 0 0% 100%;
|
|
187
|
-
--card-foreground:
|
|
185
|
+
--card-foreground: 0 0% 4%;
|
|
188
186
|
--popover: 0 0% 100%;
|
|
189
|
-
--popover-foreground:
|
|
190
|
-
--primary:
|
|
191
|
-
--primary-foreground:
|
|
192
|
-
--secondary:
|
|
193
|
-
--secondary-foreground:
|
|
194
|
-
--muted:
|
|
195
|
-
--muted-foreground:
|
|
196
|
-
--accent:
|
|
197
|
-
--accent-foreground:
|
|
198
|
-
--destructive: 0
|
|
199
|
-
--destructive-foreground:
|
|
200
|
-
--border:
|
|
201
|
-
--input:
|
|
202
|
-
--ring:
|
|
203
|
-
--chart-1:
|
|
204
|
-
--chart-2:
|
|
205
|
-
--chart-3:
|
|
206
|
-
--chart-4:
|
|
207
|
-
--chart-5:
|
|
187
|
+
--popover-foreground: 0 0% 4%;
|
|
188
|
+
--primary: 0 0% 11%;
|
|
189
|
+
--primary-foreground: 0 0% 98%;
|
|
190
|
+
--secondary: 0 0% 96%;
|
|
191
|
+
--secondary-foreground: 0 0% 11%;
|
|
192
|
+
--muted: 0 0% 96%;
|
|
193
|
+
--muted-foreground: 0 0% 46%;
|
|
194
|
+
--accent: 0 0% 96%;
|
|
195
|
+
--accent-foreground: 0 0% 11%;
|
|
196
|
+
--destructive: 0 0% 60%;
|
|
197
|
+
--destructive-foreground: 0 0% 98%;
|
|
198
|
+
--border: 0 0% 91%;
|
|
199
|
+
--input: 0 0% 91%;
|
|
200
|
+
--ring: 0 0% 4%;
|
|
201
|
+
--chart-1: 0 0% 70%;
|
|
202
|
+
--chart-2: 0 0% 55%;
|
|
203
|
+
--chart-3: 0 0% 40%;
|
|
204
|
+
--chart-4: 0 0% 25%;
|
|
205
|
+
--chart-5: 0 0% 10%;
|
|
208
206
|
--radius: 0.5rem;
|
|
209
207
|
--sidebar-background: 0 0% 98%;
|
|
210
|
-
--sidebar-foreground:
|
|
211
|
-
--sidebar-primary:
|
|
208
|
+
--sidebar-foreground: 0 0% 26%;
|
|
209
|
+
--sidebar-primary: 0 0% 10%;
|
|
212
210
|
--sidebar-primary-foreground: 0 0% 98%;
|
|
213
|
-
--sidebar-accent:
|
|
214
|
-
--sidebar-accent-foreground:
|
|
215
|
-
--sidebar-border:
|
|
216
|
-
--sidebar-ring:
|
|
211
|
+
--sidebar-accent: 0 0% 96%;
|
|
212
|
+
--sidebar-accent-foreground: 0 0% 10%;
|
|
213
|
+
--sidebar-border: 0 0% 91%;
|
|
214
|
+
--sidebar-ring: 0 0% 60%;
|
|
217
215
|
}
|
|
218
216
|
.dark {
|
|
219
|
-
--background:
|
|
220
|
-
--border:
|
|
221
|
-
--foreground:
|
|
222
|
-
--card:
|
|
223
|
-
--card-foreground:
|
|
224
|
-
--popover:
|
|
225
|
-
--popover-foreground:
|
|
226
|
-
--primary:
|
|
227
|
-
--primary-foreground:
|
|
228
|
-
--secondary:
|
|
229
|
-
--secondary-foreground:
|
|
230
|
-
--muted:
|
|
231
|
-
--muted-foreground:
|
|
232
|
-
--accent:
|
|
233
|
-
--accent-foreground:
|
|
234
|
-
--destructive: 0
|
|
235
|
-
--destructive-foreground:
|
|
236
|
-
--input:
|
|
237
|
-
--ring:
|
|
238
|
-
--chart-1:
|
|
239
|
-
--chart-2:
|
|
240
|
-
--chart-3:
|
|
241
|
-
--chart-4:
|
|
242
|
-
--chart-5:
|
|
243
|
-
--sidebar-background:
|
|
244
|
-
--sidebar-foreground:
|
|
245
|
-
--sidebar-primary:
|
|
217
|
+
--background: 0 0% 1%;
|
|
218
|
+
--border: 0 0% 18%;
|
|
219
|
+
--foreground: 0 0% 98%;
|
|
220
|
+
--card: 0 0% 4%;
|
|
221
|
+
--card-foreground: 0 0% 98%;
|
|
222
|
+
--popover: 0 0% 4%;
|
|
223
|
+
--popover-foreground: 0 0% 98%;
|
|
224
|
+
--primary: 0 0% 98%;
|
|
225
|
+
--primary-foreground: 0 0% 11%;
|
|
226
|
+
--secondary: 0 0% 17%;
|
|
227
|
+
--secondary-foreground: 0 0% 98%;
|
|
228
|
+
--muted: 0 0% 8%;
|
|
229
|
+
--muted-foreground: 0 0% 65%;
|
|
230
|
+
--accent: 0 0% 17%;
|
|
231
|
+
--accent-foreground: 0 0% 98%;
|
|
232
|
+
--destructive: 0 0% 31%;
|
|
233
|
+
--destructive-foreground: 0 0% 98%;
|
|
234
|
+
--input: 0 0% 17%;
|
|
235
|
+
--ring: 0 0% 84%;
|
|
236
|
+
--chart-1: 0 0% 80%;
|
|
237
|
+
--chart-2: 0 0% 65%;
|
|
238
|
+
--chart-3: 0 0% 50%;
|
|
239
|
+
--chart-4: 0 0% 35%;
|
|
240
|
+
--chart-5: 0 0% 20%;
|
|
241
|
+
--sidebar-background: 0 0% 10%;
|
|
242
|
+
--sidebar-foreground: 0 0% 96%;
|
|
243
|
+
--sidebar-primary: 0 0% 48%;
|
|
246
244
|
--sidebar-primary-foreground: 0 0% 100%;
|
|
247
|
-
--sidebar-accent:
|
|
248
|
-
--sidebar-accent-foreground:
|
|
249
|
-
--sidebar-border:
|
|
250
|
-
--sidebar-ring:
|
|
245
|
+
--sidebar-accent: 0 0% 16%;
|
|
246
|
+
--sidebar-accent-foreground: 0 0% 96%;
|
|
247
|
+
--sidebar-border: 0 0% 16%;
|
|
248
|
+
--sidebar-ring: 0 0% 60%;
|
|
251
249
|
}
|
|
252
250
|
|
|
253
251
|
.text-md {
|
|
@@ -294,3 +292,17 @@ body,
|
|
|
294
292
|
.resize-handle.dragging {
|
|
295
293
|
background-color: rgba(74, 222, 128, 0.4);
|
|
296
294
|
}
|
|
295
|
+
|
|
296
|
+
.bg-muted {
|
|
297
|
+
background-color: rgba(120, 120, 120, 0.10);
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
.text-muted {
|
|
301
|
+
color: rgba(120, 120, 120, 0.5);
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
.text-muted-foreground {
|
|
305
|
+
color: rgba(255, 255, 255, 0.8);
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
|
package/dist/src/main.js
CHANGED
|
@@ -9,9 +9,10 @@ import { RouteWrapper } from './route-wrapper';
|
|
|
9
9
|
import { LogsPage } from './routes/logs-page';
|
|
10
10
|
import { RootMotia } from './components/root-motia';
|
|
11
11
|
import { StatesPage } from './routes/states-page';
|
|
12
|
+
import { EndpointsPage } from './routes/endpoints-page';
|
|
12
13
|
// Render the app
|
|
13
14
|
const rootElement = document.getElementById('root');
|
|
14
15
|
if (!rootElement.innerHTML) {
|
|
15
16
|
const root = createRoot(rootElement);
|
|
16
|
-
root.render(_jsx(StrictMode, { children: _jsx(BrowserRouter, { children: _jsx(RootMotia, { children: _jsx(RouteWrapper, { children: _jsxs(Routes, { children: [_jsx(Route, { path: "/", element: _jsx(Index, {}) }), _jsx(Route, { path: "/flow/:id", element: _jsx(Flow, {}) }), _jsx(Route, { path: "/logs", element: _jsx(LogsPage, {}) }), _jsx(Route, { path: "/states", element: _jsx(StatesPage, {}) })] }) }) }) }) }));
|
|
17
|
+
root.render(_jsx(StrictMode, { children: _jsx(BrowserRouter, { children: _jsx(RootMotia, { children: _jsx(RouteWrapper, { children: _jsxs(Routes, { children: [_jsx(Route, { path: "/", element: _jsx(Index, {}) }), _jsx(Route, { path: "/flow/:id", element: _jsx(Flow, {}) }), _jsx(Route, { path: "/logs", element: _jsx(LogsPage, {}) }), _jsx(Route, { path: "/states", element: _jsx(StatesPage, {}) }), _jsx(Route, { path: "/endpoints", element: _jsx(EndpointsPage, {}) })] }) }) }) }) }));
|
|
17
18
|
}
|
|
@@ -3,5 +3,5 @@ import { Webhook } from 'lucide-react';
|
|
|
3
3
|
import { BaseNode } from './base-node';
|
|
4
4
|
import { DetailItem, NodeDetails } from './node-details';
|
|
5
5
|
export const ApiNode = ({ data, children }) => {
|
|
6
|
-
return (_jsxs(BaseNode, { variant: "api", title: data.name, language: data.language, disableSourceHandle: !data.emits?.length && !data.virtualEmits?.length, disableTargetHandle: !data.subscribes?.length && !data.virtualSubscribes?.length, children: [data.description && _jsx("div", { className: "text-sm text-
|
|
6
|
+
return (_jsxs(BaseNode, { variant: "api", title: data.name, language: data.language, disableSourceHandle: !data.emits?.length && !data.virtualEmits?.length, disableTargetHandle: !data.subscribes?.length && !data.virtualSubscribes?.length, children: [data.description && _jsx("div", { className: "text-sm text-muted-foreground", children: data.description }), children, data.webhookUrl && (_jsxs("div", { className: "flex gap-1 items-center text-xs text-muted-foreground", children: [_jsx(Webhook, { className: "w-3 h-3 text-muted-foreground/40" }), _jsx("div", { className: "font-mono", children: data.webhookUrl })] })), _jsx(NodeDetails, { type: "api", name: data.name, subscribes: data.subscribes, emits: data.emits, description: data.description, language: data.language, children: _jsx(DetailItem, { label: "Webhook URL", children: _jsxs("div", { className: "flex gap-1 items-center text-xs text-white/60", children: [_jsx(Webhook, { className: "w-3 h-3 text-white/40" }), _jsx("div", { className: "font-mono", children: data.webhookUrl })] }) }) })] }));
|
|
7
7
|
};
|
|
@@ -19,7 +19,7 @@ const Dot = ({ variant }) => (_jsx("div", { className: cn(baseDot({ variant }))
|
|
|
19
19
|
const HeaderBar = ({ text, variant, children, }) => (_jsxs("div", { className: "text-sm text-white flex justify-between items-center gap-4", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Dot, { variant: variant }), _jsx("span", { children: text })] }), children] }));
|
|
20
20
|
export const BaseNode = (props) => {
|
|
21
21
|
const { title, variant, children, disableSourceHandle, disableTargetHandle, language } = props;
|
|
22
|
-
return (_jsx("div", { className: "p-[1px] rounded-lg
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
return (_jsx("div", { className: "p-[1px] rounded-lg max-w-[350px] ", children: _jsx("div", { className: "rounded-lg bg-background p-4 border border-muted border-solid", style: {
|
|
23
|
+
borderColor: colorMap[variant],
|
|
24
|
+
}, children: _jsxs("div", { className: "group relative", children: [_jsx(HeaderBar, { text: title, variant: variant, children: _jsx(LanguageIndicator, { language: language }) }), _jsx("div", { className: "pt-4 space-y-3", children: children }), !disableTargetHandle && _jsx(BaseHandle, { type: "target", position: Position.Top, variant: variant }), !disableSourceHandle && _jsx(BaseHandle, { type: "source", position: Position.Bottom, variant: variant }), _jsx("div", { className: "absolute inset-0 -z-10 translate-y-1 translate-x-1 bg-background rounded-md border border-white/5" })] }) }) }));
|
|
25
25
|
};
|
|
@@ -3,5 +3,5 @@ import { BaseNode } from './base-node';
|
|
|
3
3
|
import { NodeDetails } from './node-details';
|
|
4
4
|
export const EventNode = (props) => {
|
|
5
5
|
const { data, children } = props;
|
|
6
|
-
return (_jsxs(BaseNode, { variant: "event", title: data.name, language: data.language, disableSourceHandle: !data.emits?.length && !data.virtualEmits?.length, disableTargetHandle: !data.subscribes?.length && !data.virtualSubscribes?.length, children: [children, _jsx(NodeDetails, { type: "event", name: data.name, subscribes: data.subscribes, emits: data.emits, description: data.description, language: data.language })] }));
|
|
6
|
+
return (_jsxs(BaseNode, { variant: "event", title: data.name, language: data.language, disableSourceHandle: !data.emits?.length && !data.virtualEmits?.length, disableTargetHandle: !data.subscribes?.length && !data.virtualSubscribes?.length, children: [_jsx("div", { className: "text-sm text-muted-foreground", children: data.description }), children, _jsx(NodeDetails, { type: "event", name: data.name, subscribes: data.subscribes, emits: data.emits, description: data.description, language: data.language })] }));
|
|
7
7
|
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const EndpointsPage: () => import("react/jsx-runtime").JSX.Element;
|