@motiadev/workbench 0.8.2-beta.140-628177 → 0.8.2-beta.140-027880
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/components.json +1 -1
- package/dist/index.d.ts +7 -7
- package/dist/index.js +5 -5
- package/dist/middleware.d.ts +1 -1
- package/dist/middleware.js +3 -3
- package/dist/motia-plugin/__tests__/generator.test.js +97 -0
- package/dist/motia-plugin/__tests__/resolver.test.d.ts +1 -0
- package/dist/motia-plugin/__tests__/resolver.test.js +64 -0
- package/dist/motia-plugin/__tests__/validator.test.d.ts +1 -0
- package/dist/motia-plugin/__tests__/validator.test.js +59 -0
- package/dist/motia-plugin/generator.d.ts +78 -0
- package/dist/motia-plugin/generator.js +128 -0
- package/dist/motia-plugin/hmr.d.ts +22 -0
- package/dist/motia-plugin/hmr.js +116 -0
- package/dist/motia-plugin/index.d.ts +3 -0
- package/dist/motia-plugin/index.js +152 -0
- package/dist/motia-plugin/resolver.d.ts +63 -0
- package/dist/motia-plugin/resolver.js +92 -0
- package/dist/motia-plugin/types.d.ts +169 -0
- package/dist/motia-plugin/types.js +36 -0
- package/dist/motia-plugin/utils.d.ts +57 -0
- package/dist/motia-plugin/utils.js +75 -0
- package/dist/motia-plugin/validator.d.ts +19 -0
- package/dist/motia-plugin/validator.js +163 -0
- package/dist/postcss.config.mjs +1 -1
- package/dist/src/App.d.ts +1 -1
- package/dist/src/App.js +1 -18
- package/dist/src/components/flow/base-edge.d.ts +2 -2
- package/dist/src/components/flow/base-edge.js +1 -1
- package/dist/src/components/flow/flow-page.js +2 -2
- package/dist/src/components/flow/flow-tab-menu-item.js +2 -2
- package/dist/src/components/flow/flow-view.d.ts +3 -3
- package/dist/src/components/flow/hooks/use-get-flow-state.d.ts +2 -2
- package/dist/src/components/flow/hooks/use-get-flow-state.js +0 -4
- package/dist/src/components/flow/hooks/use-save-workflow-config.d.ts +1 -1
- package/dist/src/components/flow/node-organizer.d.ts +3 -3
- package/dist/src/components/flow/nodes/api-flow-node.d.ts +1 -1
- package/dist/src/components/flow/nodes/cron-flow-node.d.ts +1 -1
- package/dist/src/components/flow/nodes/event-flow-node.d.ts +1 -1
- package/dist/src/components/flow/nodes/noop-flow-node.d.ts +1 -1
- package/dist/src/components/header/deploy-button.js +2 -2
- package/dist/src/components/header/header.d.ts +1 -1
- package/dist/src/components/header/header.js +2 -2
- package/dist/src/components/root-motia.d.ts +2 -1
- package/dist/src/components/tutorial/engine/tutorial-engine.d.ts +1 -1
- package/dist/src/components/tutorial/hooks/use-tutorial-engine.d.ts +1 -1
- package/dist/src/components/tutorial/hooks/use-tutorial.d.ts +1 -1
- package/dist/src/components/tutorial/tutorial-button.d.ts +1 -1
- package/dist/src/components/tutorial/tutorial-button.js +1 -1
- package/dist/src/components/tutorial/tutorial-step.d.ts +2 -2
- package/dist/src/components/tutorial/tutorial-step.js +1 -1
- package/dist/src/components/tutorial/tutorial.css +8 -8
- package/dist/src/components/ui/json-editor.d.ts +1 -1
- package/dist/src/components/ui/json-editor.js +1 -1
- package/dist/src/components/ui/table.js +1 -1
- package/dist/src/components/ui/theme-toggle.d.ts +1 -1
- package/dist/src/components/ui/tooltip.d.ts +1 -1
- package/dist/src/hooks/use-fetch-flows.js +1 -1
- package/dist/src/hooks/use-update-handle-positions.d.ts +1 -1
- package/dist/src/index.css +5 -5
- package/dist/src/lib/plugins.js +3 -3
- package/dist/src/main.js +2 -3
- package/dist/src/project-view-mode.js +1 -1
- package/dist/src/publicComponents/api-node.d.ts +2 -2
- package/dist/src/publicComponents/base-node/base-handle.d.ts +3 -2
- package/dist/src/publicComponents/base-node/base-node.d.ts +3 -2
- package/dist/src/publicComponents/base-node/base-node.js +1 -1
- package/dist/src/publicComponents/base-node/code-display.d.ts +2 -2
- package/dist/src/publicComponents/base-node/code-display.js +1 -1
- package/dist/src/publicComponents/base-node/emits.d.ts +2 -2
- package/dist/src/publicComponents/base-node/feature-card.d.ts +2 -2
- package/dist/src/publicComponents/base-node/language-indicator.d.ts +2 -2
- package/dist/src/publicComponents/base-node/node-header.d.ts +3 -2
- package/dist/src/publicComponents/base-node/node-sidebar.d.ts +2 -2
- package/dist/src/publicComponents/base-node/subscribe.d.ts +1 -1
- package/dist/src/publicComponents/cron-node.d.ts +3 -2
- package/dist/src/publicComponents/event-node.d.ts +3 -2
- package/dist/src/publicComponents/node-props.d.ts +1 -1
- package/dist/src/publicComponents/noop-node.d.ts +3 -2
- package/dist/src/stores/use-global-store.d.ts +0 -6
- package/dist/src/stores/use-global-store.js +0 -6
- package/dist/src/types/flow.d.ts +1 -1
- package/dist/tsconfig.app.tsbuildinfo +1 -1
- package/dist/tsconfig.node.tsbuildinfo +1 -1
- package/motia-plugin/__tests__/generator.test.ts +129 -0
- package/motia-plugin/__tests__/resolver.test.ts +82 -0
- package/motia-plugin/__tests__/validator.test.ts +71 -0
- package/motia-plugin/generator.ts +130 -0
- package/motia-plugin/hmr.ts +140 -0
- package/motia-plugin/index.ts +182 -0
- package/motia-plugin/resolver.ts +96 -0
- package/motia-plugin/types.ts +198 -0
- package/motia-plugin/utils.ts +70 -0
- package/motia-plugin/validator.ts +197 -0
- package/package.json +9 -9
- package/postcss.config.mjs +1 -1
- package/dist/src/components/observability/events/code/function-call.d.ts +0 -13
- package/dist/src/components/observability/events/code/function-call.js +0 -16
- package/dist/src/components/observability/events/event-icon.d.ts +0 -7
- package/dist/src/components/observability/events/event-icon.js +0 -16
- package/dist/src/components/observability/events/trace-emit-event.d.ts +0 -5
- package/dist/src/components/observability/events/trace-emit-event.js +0 -5
- package/dist/src/components/observability/events/trace-event.d.ts +0 -5
- package/dist/src/components/observability/events/trace-event.js +0 -20
- package/dist/src/components/observability/events/trace-log-event.d.ts +0 -5
- package/dist/src/components/observability/events/trace-log-event.js +0 -5
- package/dist/src/components/observability/events/trace-state-event.d.ts +0 -5
- package/dist/src/components/observability/events/trace-state-event.js +0 -5
- package/dist/src/components/observability/events/trace-stream-event.d.ts +0 -5
- package/dist/src/components/observability/events/trace-stream-event.js +0 -5
- package/dist/src/components/observability/hooks/use-get-endtime.d.ts +0 -2
- package/dist/src/components/observability/hooks/use-get-endtime.js +0 -15
- package/dist/src/components/observability/trace-item/trace-item-detail.d.ts +0 -8
- package/dist/src/components/observability/trace-item/trace-item-detail.js +0 -10
- package/dist/src/components/observability/trace-item/trace-item.d.ts +0 -10
- package/dist/src/components/observability/trace-item/trace-item.js +0 -14
- package/dist/src/components/observability/trace-status.d.ts +0 -8
- package/dist/src/components/observability/trace-status.js +0 -18
- package/dist/src/components/observability/trace-tab-label.d.ts +0 -1
- package/dist/src/components/observability/trace-tab-label.js +0 -5
- package/dist/src/components/observability/trace-timeline.d.ts +0 -6
- package/dist/src/components/observability/trace-timeline.js +0 -30
- package/dist/src/components/observability/traces-groups.d.ts +0 -9
- package/dist/src/components/observability/traces-groups.js +0 -9
- package/dist/src/components/observability/traces-page.d.ts +0 -1
- package/dist/src/components/observability/traces-page.js +0 -33
- package/dist/src/components/states/hooks/states-hooks.d.ts +0 -13
- package/dist/src/components/states/hooks/states-hooks.js +0 -26
- package/dist/src/components/states/state-details.d.ts +0 -7
- package/dist/src/components/states/state-details.js +0 -3
- package/dist/src/components/states/state-editor.d.ts +0 -7
- package/dist/src/components/states/state-editor.js +0 -71
- package/dist/src/components/states/state-sidebar.d.ts +0 -8
- package/dist/src/components/states/state-sidebar.js +0 -17
- package/dist/src/components/states/state-tab-label.d.ts +0 -1
- package/dist/src/components/states/state-tab-label.js +0 -5
- package/dist/src/components/states/states-page.d.ts +0 -1
- package/dist/src/components/states/states-page.js +0 -56
- package/dist/src/types/observability.d.ts +0 -78
- package/dist/vite-plugin-motia-plugins.d.ts +0 -9
- package/dist/vite-plugin-motia-plugins.js +0 -69
- /package/dist/{src/types/observability.js → motia-plugin/__tests__/generator.test.d.ts} +0 -0
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import { Sidebar, Badge } from '@motiadev/ui';
|
|
3
|
-
import { formatDuration } from '@/lib/utils';
|
|
4
|
-
import { X } from 'lucide-react';
|
|
5
|
-
import { memo } from 'react';
|
|
6
|
-
import { EventIcon } from '../events/event-icon';
|
|
7
|
-
import { TraceEvent } from '../events/trace-event';
|
|
8
|
-
export const TraceItemDetail = memo(({ trace, onClose }) => {
|
|
9
|
-
return (_jsxs(Sidebar, { onClose: onClose, title: "Trace Details", subtitle: `Viewing details from step ${trace.name}`, actions: [{ icon: _jsx(X, {}), onClick: onClose, label: 'Close' }], children: [_jsxs("div", { className: "px-2 w-[800px] overflow-auto", children: [_jsxs("div", { className: "flex items-center gap-4 text-sm text-muted-foreground mb-4", children: [trace.endTime && _jsxs("span", { children: ["Duration: ", formatDuration(trace.endTime - trace.startTime)] }), _jsx("div", { className: "bg-blue-500 font-bold text-xs px-[4px] py-[2px] rounded-sm text-blue-100", children: trace.entryPoint.type }), trace.correlationId && _jsxs(Badge, { variant: "outline", children: ["Correlated: ", trace.correlationId] })] }), _jsx("div", { className: "pl-6 border-l-1 border-gray-500/40 font-mono text-xs flex flex-col gap-3", children: trace.events.map((event, index) => (_jsxs("div", { className: "relative", children: [_jsx("div", { className: "absolute -left-[26px] top-[8px] w-1 h-1 rounded-full bg-emerald-500 outline outline-2 outline-emerald-500/50" }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(EventIcon, { event: event }), _jsxs("span", { className: "text-sm font-mono text-muted-foreground", children: ["+", formatDuration(Math.floor(event.timestamp - trace.startTime))] }), _jsx(TraceEvent, { event: event })] })] }, index))) })] }), trace.error && (_jsxs("div", { className: "p-4 bg-red-800/10", children: [_jsx("div", { className: "text-sm text-red-800 dark:text-red-400 font-semibold", children: trace.error.message }), _jsx("div", { className: "text-sm text-red-800 dark:text-red-400 pl-4", children: trace.error.stack })] }))] }));
|
|
10
|
-
});
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { Trace, TraceGroup } from '@/types/observability';
|
|
2
|
-
import React from 'react';
|
|
3
|
-
type Props = {
|
|
4
|
-
trace: Trace;
|
|
5
|
-
group: TraceGroup;
|
|
6
|
-
groupEndTime: number;
|
|
7
|
-
onExpand: (traceId: string) => void;
|
|
8
|
-
};
|
|
9
|
-
export declare const TraceItem: React.FC<Props>;
|
|
10
|
-
export {};
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { cn } from '@motiadev/ui';
|
|
3
|
-
export const TraceItem = ({ trace, group, groupEndTime, onExpand }) => {
|
|
4
|
-
return (_jsxs("div", { className: "flex hover:bg-muted-foreground/10 relative cursor-pointer", onClick: () => onExpand(trace.id), "data-testid": "trace-timeline-item", children: [_jsx("div", { className: "flex items-center min-w-[200px] max-w-[200px] h-[32px] max-h-[32px] py-4 px-2 text-sm font-semibold text-foreground truncate sticky left-0 bg-card z-9", children: trace.name }), _jsx("div", { className: "flex w-full flex-row items-center hover:bg-muted/50 rounded-md", children: _jsx("div", { className: "relative w-full h-[32px] flex items-center", children: _jsx("div", { className: cn('h-[24px] rounded-[4px] hover:opacity-80 transition-all duration-200', {
|
|
5
|
-
'bg-[repeating-linear-gradient(140deg,#BEFE29,#BEFE29_8px,#ABE625_8px,#ABE625_16px)]': trace.status === 'running',
|
|
6
|
-
'bg-[repeating-linear-gradient(140deg,#2862FE,#2862FE_8px,#2358E5_8px,#2358E5_16px)]': trace.status === 'completed',
|
|
7
|
-
'bg-[repeating-linear-gradient(140deg,#EA2069,#EA2069_8px,#D41E60_8px,#D41E60_16px)]': trace.status === 'failed',
|
|
8
|
-
}), style: {
|
|
9
|
-
marginLeft: `${((trace.startTime - group.startTime) / (groupEndTime - group.startTime)) * 100}%`,
|
|
10
|
-
width: trace.endTime
|
|
11
|
-
? `${((trace.endTime - trace.startTime) / (groupEndTime - group.startTime)) * 100}%`
|
|
12
|
-
: `${((Date.now() - trace.startTime) / (groupEndTime - group.startTime)) * 100}%`,
|
|
13
|
-
} }) }) })] }));
|
|
14
|
-
};
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import { Badge } from '@motiadev/ui';
|
|
3
|
-
import { useMemo } from 'react';
|
|
4
|
-
export const TraceStatusBadge = ({ status, duration }) => {
|
|
5
|
-
const variant = useMemo(() => {
|
|
6
|
-
if (status === 'running') {
|
|
7
|
-
return 'info';
|
|
8
|
-
}
|
|
9
|
-
if (status === 'completed') {
|
|
10
|
-
return 'success';
|
|
11
|
-
}
|
|
12
|
-
if (status === 'failed') {
|
|
13
|
-
return 'error';
|
|
14
|
-
}
|
|
15
|
-
return 'default';
|
|
16
|
-
}, [status]);
|
|
17
|
-
return _jsx(Badge, { variant: variant, children: duration && status !== 'failed' ? duration : status });
|
|
18
|
-
};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare const TracingTabLabel: import("react").MemoExoticComponent<() => import("react/jsx-runtime").JSX.Element>;
|
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { GanttChart } from 'lucide-react';
|
|
3
|
-
import { memo } from 'react';
|
|
4
|
-
export const TracingTabLabel = memo(() => (_jsxs(_Fragment, { children: [_jsx(GanttChart, { "aria-hidden": "true" }), _jsx("span", { children: "Tracing" })] })));
|
|
5
|
-
TracingTabLabel.displayName = 'TracingTabLabel';
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
-
import { useGlobalStore } from '@/stores/use-global-store';
|
|
3
|
-
import { formatDuration } from '@/lib/utils';
|
|
4
|
-
import { useStreamGroup, useStreamItem } from '@motiadev/stream-client-react';
|
|
5
|
-
import { Button } from '@motiadev/ui';
|
|
6
|
-
import { Minus, Plus } from 'lucide-react';
|
|
7
|
-
import { memo, useMemo, useState } from 'react';
|
|
8
|
-
import { useGetEndTime } from './hooks/use-get-endtime';
|
|
9
|
-
import { TraceItem } from './trace-item/trace-item';
|
|
10
|
-
import { TraceItemDetail } from './trace-item/trace-item-detail';
|
|
11
|
-
export const TraceTimeline = memo(({ groupId }) => {
|
|
12
|
-
const { data: group } = useStreamItem({
|
|
13
|
-
streamName: 'motia-trace-group',
|
|
14
|
-
groupId: 'default',
|
|
15
|
-
id: groupId,
|
|
16
|
-
});
|
|
17
|
-
const { data } = useStreamGroup({ streamName: 'motia-trace', groupId });
|
|
18
|
-
const endTime = useGetEndTime(group);
|
|
19
|
-
const [zoom, setZoom] = useState(1);
|
|
20
|
-
const selectedTraceId = useGlobalStore((state) => state.selectedTraceId);
|
|
21
|
-
const selectTraceId = useGlobalStore((state) => state.selectTraceId);
|
|
22
|
-
const selectedTrace = useMemo(() => data?.find((trace) => trace.id === selectedTraceId), [data, selectedTraceId]);
|
|
23
|
-
const zoomMinus = () => {
|
|
24
|
-
if (zoom > 0.5)
|
|
25
|
-
setZoom(zoom - 0.1);
|
|
26
|
-
};
|
|
27
|
-
if (!group)
|
|
28
|
-
return null;
|
|
29
|
-
return (_jsxs(_Fragment, { children: [_jsx("div", { className: "flex flex-col flex-1 overflow-x-auto h-full relative", children: _jsxs("div", { className: "flex flex-col items-center min-w-full sticky top-0", style: { width: `${zoom * 1000}px` }, children: [_jsxs("div", { className: "flex flex-1 w-full sticky top-0 bg-background z-10", children: [_jsxs("div", { className: "w-full min-h-[37px] h-[37px] min-w-[200px] max-w-[200px] flex items-center justify-center gap-2 sticky left-0 top-0 bg-card backdrop-blur-[4px] backdrop-filter", children: [_jsx(Button, { variant: "icon", size: "sm", className: "px-2", onClick: zoomMinus, children: _jsx(Minus, { className: "w-4 h-4 cursor-pointer" }) }), _jsxs("span", { className: "text-sm font-bold text-muted-foreground", children: [Math.floor(zoom * 100), "%"] }), _jsx(Button, { variant: "icon", size: "sm", className: "px-2", onClick: () => setZoom(zoom + 0.1), children: _jsx(Plus, { className: "w-4 h-4 cursor-pointer" }) })] }), _jsxs("div", { className: "flex justify-between font-mono p-2 w-full text-xs text-muted-foreground bg-card", children: [_jsx("span", { children: formatDuration(0) }), _jsx("span", { children: formatDuration(Math.floor((endTime - group.startTime) * 0.25)) }), _jsx("span", { children: formatDuration(Math.floor((endTime - group.startTime) * 0.5)) }), _jsx("span", { children: formatDuration(Math.floor((endTime - group.startTime) * 0.75)) }), _jsx("span", { children: formatDuration(Math.floor(endTime - group.startTime)) }), _jsxs("div", { className: "absolute bottom-[-4px] w-full flex justify-between", children: [_jsx("span", { className: "w-[1px] h-full bg-blue-500" }), _jsx("span", { className: "w-[1px] h-full bg-blue-500" }), _jsx("span", { className: "w-[1px] h-full bg-blue-500" }), _jsx("span", { className: "w-[1px] h-full bg-blue-500" }), _jsx("span", { className: "w-[1px] h-full bg-blue-500" })] })] })] }), _jsx("div", { className: "flex flex-col w-full h-full", children: data?.map((trace) => (_jsx(TraceItem, { trace: trace, group: group, groupEndTime: endTime, onExpand: selectTraceId }, trace.id))) })] }) }), selectedTrace && _jsx(TraceItemDetail, { trace: selectedTrace, onClose: () => selectTraceId(undefined) })] }));
|
|
30
|
-
});
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { TraceGroup } from '@/types/observability';
|
|
2
|
-
import React from 'react';
|
|
3
|
-
interface Props {
|
|
4
|
-
groups: TraceGroup[];
|
|
5
|
-
selectedGroupId?: string;
|
|
6
|
-
onGroupSelect: (group: TraceGroup) => void;
|
|
7
|
-
}
|
|
8
|
-
export declare const TracesGroups: React.FC<Props>;
|
|
9
|
-
export {};
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { formatDuration } from '@/lib/utils';
|
|
3
|
-
import { cn } from '@motiadev/ui';
|
|
4
|
-
import { formatDistanceToNow } from 'date-fns';
|
|
5
|
-
import { memo } from 'react';
|
|
6
|
-
import { TraceStatusBadge } from './trace-status';
|
|
7
|
-
export const TracesGroups = memo(({ groups, selectedGroupId, onGroupSelect }) => {
|
|
8
|
-
return (_jsx("div", { className: "overflow-auto", children: groups.length > 0 && (_jsx("div", { children: [...groups].reverse().map((group) => (_jsx("div", { "data-testid": `trace-${group.id}`, className: cn('motia-trace-group cursor-pointer transition-colors', selectedGroupId === group.id ? 'bg-muted-foreground/10' : 'hover:bg-muted/70'), onClick: () => onGroupSelect(group), children: _jsxs("div", { className: "p-3 flex flex-col gap-1", children: [_jsxs("div", { className: "flex flex-row justify-between items-center gap-2", children: [_jsx("span", { className: "font-semibold text-lg", children: group.name }), _jsx(TraceStatusBadge, { status: group.status, duration: group.endTime ? formatDuration(group.endTime - group.startTime) : undefined })] }), _jsxs("div", { className: "text-xs text-muted-foreground space-y-1", children: [_jsxs("div", { className: "flex justify-between", children: [_jsx("div", { "data-testid": "trace-id", className: "text-xs text-muted-foreground font-mono tracking-[1px]", children: group.id }), _jsxs("span", { children: [group.metadata.totalSteps, " steps"] })] }), _jsxs("div", { className: "flex justify-between", children: [formatDistanceToNow(group.startTime), " ago"] }), group.metadata.activeSteps > 0 && (_jsxs("div", { className: "text-blue-600", children: [group.metadata.activeSteps, " active"] }))] })] }) }, group.id))) })) }));
|
|
9
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare const TracesPage: () => import("react/jsx-runtime").JSX.Element;
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { TraceTimeline } from '@/components/observability/trace-timeline';
|
|
3
|
-
import { useStreamGroup } from '@motiadev/stream-client-react';
|
|
4
|
-
import { TracesGroups } from '@/components/observability/traces-groups';
|
|
5
|
-
import { useGlobalStore } from '../../stores/use-global-store';
|
|
6
|
-
import { useEffect, useMemo, useState } from 'react';
|
|
7
|
-
import { Button, cn, Input } from '@motiadev/ui';
|
|
8
|
-
import { Search, Trash, X } from 'lucide-react';
|
|
9
|
-
export const TracesPage = () => {
|
|
10
|
-
const selectedGroupId = useGlobalStore((state) => state.selectedTraceGroupId);
|
|
11
|
-
const selectTraceGroupId = useGlobalStore((state) => state.selectTraceGroupId);
|
|
12
|
-
const { data } = useStreamGroup({ streamName: 'motia-trace-group', groupId: 'default' });
|
|
13
|
-
const handleGroupSelect = (group) => selectTraceGroupId(group.id);
|
|
14
|
-
const [search, setSearch] = useState('');
|
|
15
|
-
const clearTraces = () => fetch('/__motia/trace/clear', { method: 'POST' });
|
|
16
|
-
const traceGroups = useMemo(() => data?.filter((group) => group.name.toLowerCase().includes(search.toLowerCase()) ||
|
|
17
|
-
group.id.toLowerCase().includes(search.toLowerCase())), [data, search]);
|
|
18
|
-
useEffect(() => {
|
|
19
|
-
if (traceGroups && traceGroups.length > 0) {
|
|
20
|
-
const group = traceGroups[traceGroups.length - 1];
|
|
21
|
-
if (group && group.status === 'running' && group.id !== selectedGroupId) {
|
|
22
|
-
selectTraceGroupId(group.id);
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
else if (selectedGroupId) {
|
|
26
|
-
selectTraceGroupId(undefined);
|
|
27
|
-
}
|
|
28
|
-
}, [traceGroups]);
|
|
29
|
-
return (_jsxs("div", { className: "grid grid-rows-[auto_1fr] h-full", children: [_jsxs("div", { className: "flex p-2 border-b gap-2", "data-testid": "logs-search-container", children: [_jsxs("div", { className: "flex-1 relative", children: [_jsx(Input, { variant: "shade", value: search, onChange: (e) => setSearch(e.target.value), className: "px-9 font-medium", placeholder: "Search by Trace ID or Step Name" }), _jsx(Search, { className: "absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-muted-foreground/50" }), _jsx(X, { className: cn('cursor-pointer absolute right-3 top-1/2 -translate-y-1/2 w-4 h-4 text-muted-foreground/50 hover:text-muted-foreground', {
|
|
30
|
-
visible: search !== '',
|
|
31
|
-
invisible: search === '',
|
|
32
|
-
}), onClick: () => setSearch('') })] }), _jsxs(Button, { variant: "default", onClick: clearTraces, className: "h-[34px]", children: [_jsx(Trash, {}), " Clear"] })] }), _jsxs("div", { className: "grid grid-cols-[300px_1fr] overflow-hidden", children: [_jsx("div", { className: "w-[300px] border-r border-border overflow-auto h-full", "data-testid": "traces-container", children: _jsx(TracesGroups, { groups: traceGroups, selectedGroupId: selectedGroupId, onGroupSelect: handleGroupSelect }) }), _jsxs("div", { className: "overflow-auto", "data-testid": "trace-details", children: [selectedGroupId && _jsx(TraceTimeline, { groupId: selectedGroupId }), !selectedGroupId && (_jsx("div", { className: "flex items-center justify-center h-full text-muted-foreground", children: "Select a trace or trace group to view the timeline" }))] })] })] }));
|
|
33
|
-
};
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
export interface StateItem {
|
|
2
|
-
groupId: string;
|
|
3
|
-
key: string;
|
|
4
|
-
type: 'string' | 'number' | 'boolean' | 'object' | 'array' | 'null';
|
|
5
|
-
value: string | number | boolean | object | unknown[] | null;
|
|
6
|
-
}
|
|
7
|
-
type Output = {
|
|
8
|
-
items: StateItem[];
|
|
9
|
-
deleteItems: (ids: string[]) => void;
|
|
10
|
-
refetch: () => void;
|
|
11
|
-
};
|
|
12
|
-
export declare const useGetStateItems: () => Output;
|
|
13
|
-
export {};
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { useEffect, useState, useCallback } from 'react';
|
|
2
|
-
export const useGetStateItems = () => {
|
|
3
|
-
const [items, setItems] = useState([]);
|
|
4
|
-
const refetch = useCallback(() => {
|
|
5
|
-
fetch('/__motia/state')
|
|
6
|
-
.then(async (res) => {
|
|
7
|
-
if (res.ok) {
|
|
8
|
-
return res.json();
|
|
9
|
-
}
|
|
10
|
-
else {
|
|
11
|
-
throw await res.json();
|
|
12
|
-
}
|
|
13
|
-
})
|
|
14
|
-
.then(setItems)
|
|
15
|
-
.catch((err) => console.error(err));
|
|
16
|
-
}, []);
|
|
17
|
-
const deleteItems = (ids) => {
|
|
18
|
-
fetch('/__motia/state/delete', {
|
|
19
|
-
method: 'POST',
|
|
20
|
-
headers: { 'Content-Type': 'application/json' },
|
|
21
|
-
body: JSON.stringify({ ids }),
|
|
22
|
-
}).then(() => refetch());
|
|
23
|
-
};
|
|
24
|
-
useEffect(refetch, [refetch]);
|
|
25
|
-
return { items, deleteItems, refetch };
|
|
26
|
-
};
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
-
import { Button } from '@motiadev/ui';
|
|
3
|
-
import { AlertCircle, Check, Loader2, Save } from 'lucide-react';
|
|
4
|
-
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
5
|
-
import { JsonEditor } from '../ui/json-editor';
|
|
6
|
-
export const StateEditor = ({ state }) => {
|
|
7
|
-
const [isRequestLoading, setIsRequestLoading] = useState(false);
|
|
8
|
-
const [isValid, setIsValid] = useState(true);
|
|
9
|
-
const [jsonValue, setJsonValue] = useState(JSON.stringify(state.value, null, 2));
|
|
10
|
-
const [hasChanges, setHasChanges] = useState(false);
|
|
11
|
-
const [saveStatus, setSaveStatus] = useState('idle');
|
|
12
|
-
const lastSavedValue = useRef(JSON.stringify(state.value, null, 2));
|
|
13
|
-
useEffect(() => {
|
|
14
|
-
setJsonValue(JSON.stringify(state.value, null, 2));
|
|
15
|
-
}, [state.value]);
|
|
16
|
-
const handleJsonChange = useCallback((value) => {
|
|
17
|
-
setHasChanges(value !== lastSavedValue.current);
|
|
18
|
-
setJsonValue(value);
|
|
19
|
-
setSaveStatus('idle');
|
|
20
|
-
}, []);
|
|
21
|
-
const handleSave = async () => {
|
|
22
|
-
if (!isValid || !hasChanges)
|
|
23
|
-
return;
|
|
24
|
-
try {
|
|
25
|
-
setIsRequestLoading(true);
|
|
26
|
-
setSaveStatus('idle');
|
|
27
|
-
const response = await fetch('/__motia/state', {
|
|
28
|
-
method: 'POST',
|
|
29
|
-
headers: {
|
|
30
|
-
'Content-Type': 'application/json',
|
|
31
|
-
},
|
|
32
|
-
body: JSON.stringify({
|
|
33
|
-
key: state.key,
|
|
34
|
-
groupId: state.groupId,
|
|
35
|
-
value: JSON.parse(jsonValue),
|
|
36
|
-
}),
|
|
37
|
-
});
|
|
38
|
-
if (!response.ok) {
|
|
39
|
-
throw new Error(`HTTP error! status: ${response.status}`);
|
|
40
|
-
}
|
|
41
|
-
lastSavedValue.current = jsonValue;
|
|
42
|
-
setSaveStatus('success');
|
|
43
|
-
setHasChanges(false);
|
|
44
|
-
setTimeout(() => {
|
|
45
|
-
setSaveStatus('idle');
|
|
46
|
-
}, 3000);
|
|
47
|
-
}
|
|
48
|
-
catch (error) {
|
|
49
|
-
console.error('Failed to save state:', error);
|
|
50
|
-
setSaveStatus('error');
|
|
51
|
-
}
|
|
52
|
-
finally {
|
|
53
|
-
setIsRequestLoading(false);
|
|
54
|
-
}
|
|
55
|
-
};
|
|
56
|
-
const resetChanges = useCallback(() => {
|
|
57
|
-
setJsonValue(JSON.stringify(state.value, null, 2));
|
|
58
|
-
setHasChanges(false);
|
|
59
|
-
setSaveStatus('idle');
|
|
60
|
-
}, [state.value]);
|
|
61
|
-
const statusView = useMemo(() => {
|
|
62
|
-
if (saveStatus === 'success') {
|
|
63
|
-
return (_jsx("div", { className: "bg-green-50 dark:bg-green-950/20 border border-green-200 dark:border-green-800 rounded-lg p-2", children: _jsxs("div", { className: "flex items-center gap-2 text-green-700 dark:text-green-400 text-sm", children: [_jsx(Check, { className: "w-4 h-4" }), "State saved successfully!"] }) }));
|
|
64
|
-
}
|
|
65
|
-
if (saveStatus === 'error') {
|
|
66
|
-
return (_jsx("div", { className: "bg-red-50 dark:bg-red-950/20 border border-red-200 dark:border-red-800 rounded-lg p-2", children: _jsxs("div", { className: "flex items-center gap-2 text-red-700 dark:text-red-400 text-sm", children: [_jsx(AlertCircle, { className: "w-4 h-4" }), "Failed to save state. Please try again."] }) }));
|
|
67
|
-
}
|
|
68
|
-
return (_jsx("div", { className: "text-xs text-muted-foreground", children: hasChanges ? (_jsxs("span", { className: "flex items-center gap-1", children: [_jsx("div", { className: "w-2 h-2 bg-orange-500 rounded-full" }), "Unsaved changes"] })) : (_jsxs("span", { className: "flex items-center gap-1", children: [_jsx("div", { className: "w-2 h-2 bg-green-500 rounded-full" }), "Up to date"] })) }));
|
|
69
|
-
}, [saveStatus, hasChanges]);
|
|
70
|
-
return (_jsxs("div", { className: "flex flex-col gap-2 h-full", children: [_jsx("p", { className: "text-xs text-muted-foreground", children: "Modify the state value using the JSON editor below." }), _jsx("div", { className: "space-y-3 pt-2 flex flex-col", children: _jsxs("div", { className: "relative flex-1", children: [_jsx(JsonEditor, { value: jsonValue, onChange: handleJsonChange, onValidate: setIsValid, height: 'calc(100vh - 300px)' }), !isValid && (_jsxs("div", { className: "absolute top-2 right-2 bg-destructive/90 text-destructive-foreground px-2 py-1 rounded text-xs flex items-center gap-1", children: [_jsx(AlertCircle, { className: "w-3 h-3" }), "Invalid JSON"] }))] }) }), _jsxs("div", { className: "flex items-center justify-between pt-2", children: [statusView, _jsxs("div", { className: "flex items-center gap-2", children: [hasChanges && (_jsx(Button, { variant: "secondary", onClick: resetChanges, disabled: isRequestLoading, children: "Reset" })), _jsx(Button, { onClick: handleSave, variant: "accent", disabled: isRequestLoading || !isValid || !hasChanges, "data-testid": "state-save-button", children: isRequestLoading ? (_jsxs(_Fragment, { children: [_jsx(Loader2, { className: "w-3 h-3 animate-spin mr-1" }), "Saving..."] })) : (_jsxs(_Fragment, { children: [_jsx(Save, { className: "w-3 h-3 mr-1" }), "Save Changes"] })) })] })] })] }));
|
|
71
|
-
};
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import { Sidebar } from '@motiadev/ui';
|
|
3
|
-
import { X } from 'lucide-react';
|
|
4
|
-
import { StateDetails } from './state-details';
|
|
5
|
-
import { StateEditor } from './state-editor';
|
|
6
|
-
export const StateSidebar = ({ state, onClose }) => {
|
|
7
|
-
return (_jsx(Sidebar, { onClose: onClose, title: "State Details", initialWidth: 500, tabs: [
|
|
8
|
-
{
|
|
9
|
-
label: 'Overview',
|
|
10
|
-
content: _jsx(StateDetails, { state: state }),
|
|
11
|
-
},
|
|
12
|
-
{
|
|
13
|
-
label: 'Editor',
|
|
14
|
-
content: _jsx(StateEditor, { state: state }),
|
|
15
|
-
},
|
|
16
|
-
], actions: [{ icon: _jsx(X, {}), onClick: onClose, label: 'Close' }] }));
|
|
17
|
-
};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare const StatesTabLabel: import("react").MemoExoticComponent<() => import("react/jsx-runtime").JSX.Element>;
|
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { memo } from 'react';
|
|
3
|
-
import { File } from 'lucide-react';
|
|
4
|
-
export const StatesTabLabel = memo(() => (_jsxs(_Fragment, { children: [_jsx(File, { "aria-hidden": "true" }), _jsx("span", { children: "States" })] })));
|
|
5
|
-
StatesTabLabel.displayName = 'StatesTabLabel';
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare const StatesPage: () => import("react/jsx-runtime").JSX.Element;
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
-
import { useGlobalStore } from '@/stores/use-global-store';
|
|
3
|
-
import { Checkbox, Button, cn, Input } from '@motiadev/ui';
|
|
4
|
-
import { RefreshCw, Search, Trash, X } from 'lucide-react';
|
|
5
|
-
import { useMemo, useState } from 'react';
|
|
6
|
-
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '../ui/table';
|
|
7
|
-
import { useGetStateItems } from './hooks/states-hooks';
|
|
8
|
-
import { StateSidebar } from './state-sidebar';
|
|
9
|
-
export const StatesPage = () => {
|
|
10
|
-
const selectedStateId = useGlobalStore((state) => state.selectedStateId);
|
|
11
|
-
const selectStateId = useGlobalStore((state) => state.selectStateId);
|
|
12
|
-
const { items, deleteItems, refetch } = useGetStateItems();
|
|
13
|
-
const [search, setSearch] = useState('');
|
|
14
|
-
const filteredItems = useMemo(() => {
|
|
15
|
-
return items.filter((item) => {
|
|
16
|
-
return (item.groupId.toLowerCase().includes(search.toLowerCase()) ||
|
|
17
|
-
item.key.toLowerCase().includes(search.toLowerCase()));
|
|
18
|
-
});
|
|
19
|
-
}, [items, search]);
|
|
20
|
-
const selectedItem = useMemo(() => (selectedStateId ? filteredItems.find((item) => `${item.groupId}:${item.key}` === selectedStateId) : null), [filteredItems, selectedStateId]);
|
|
21
|
-
const [checkedItems, setCheckedItems] = useState(new Set());
|
|
22
|
-
const handleRowClick = (item) => selectStateId(`${item.groupId}:${item.key}`);
|
|
23
|
-
const onClose = () => selectStateId(undefined);
|
|
24
|
-
const deleteStates = () => {
|
|
25
|
-
deleteItems(Array.from(checkedItems));
|
|
26
|
-
setCheckedItems(new Set());
|
|
27
|
-
};
|
|
28
|
-
const handleCheckboxChange = (item) => {
|
|
29
|
-
const isChecked = checkedItems.has(`${item.groupId}:${item.key}`);
|
|
30
|
-
setCheckedItems((prev) => {
|
|
31
|
-
const newSet = new Set(prev);
|
|
32
|
-
if (isChecked) {
|
|
33
|
-
newSet.delete(`${item.groupId}:${item.key}`);
|
|
34
|
-
}
|
|
35
|
-
else {
|
|
36
|
-
newSet.add(`${item.groupId}:${item.key}`);
|
|
37
|
-
}
|
|
38
|
-
return newSet;
|
|
39
|
-
});
|
|
40
|
-
};
|
|
41
|
-
const toggleSelectAll = (checked) => {
|
|
42
|
-
setCheckedItems((prev) => {
|
|
43
|
-
const newSet = new Set(prev);
|
|
44
|
-
if (checked) {
|
|
45
|
-
filteredItems.forEach((item) => newSet.add(`${item.groupId}:${item.key}`));
|
|
46
|
-
}
|
|
47
|
-
else {
|
|
48
|
-
filteredItems.forEach((item) => newSet.delete(`${item.groupId}:${item.key}`));
|
|
49
|
-
}
|
|
50
|
-
return newSet;
|
|
51
|
-
});
|
|
52
|
-
};
|
|
53
|
-
return (_jsxs(_Fragment, { children: [selectedItem && _jsx(StateSidebar, { state: selectedItem, onClose: onClose }), _jsxs("div", { className: "grid grid-rows-[auto_1fr] h-full", "data-testid": "states-container", children: [_jsxs("div", { className: "flex p-2 border-b gap-2", "data-testid": "logs-search-container", children: [_jsxs("div", { className: "flex-1 relative", children: [_jsx(Input, { variant: "shade", value: search, onChange: (e) => setSearch(e.target.value), className: "px-9 font-medium", placeholder: "Search by Group ID or Key" }), _jsx(Search, { className: "absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-muted-foreground/50" }), _jsx(X, { className: "cursor-pointer absolute right-3 top-1/2 -translate-y-1/2 w-4 h-4 text-muted-foreground/50 hover:text-muted-foreground", onClick: () => setSearch('') })] }), _jsxs(Button, { variant: "default", className: "h-[34px]", disabled: checkedItems.size === 0, onClick: deleteStates, children: [_jsx(Trash, {}), " Delete"] }), _jsx(Button, { variant: "default", className: "h-[34px]", onClick: refetch, children: _jsx(RefreshCw, { className: "w-4 h-4 text-muted-foreground" }) })] }), _jsxs(Table, { children: [_jsx(TableHeader, { className: "sticky top-0 bg-background/20 backdrop-blur-sm", children: _jsxs(TableRow, { children: [_jsx(TableHead, { children: _jsx(Checkbox, { onClick: (evt) => evt.stopPropagation(), onCheckedChange: toggleSelectAll }) }), _jsx(TableHead, { className: "rounded-0", children: "Group ID" }), _jsx(TableHead, { children: "Key" }), _jsx(TableHead, { children: "Type" })] }) }), _jsx(TableBody, { children: filteredItems.map((item) => (_jsxs(TableRow, { "data-testid": `item-${item}`, onClick: () => handleRowClick(item), className: cn('font-mono font-semibold cursor-pointer border-0', selectedItem === item
|
|
54
|
-
? 'bg-muted-foreground/10 hover:bg-muted-foreground/20'
|
|
55
|
-
: 'hover:bg-muted-foreground/10'), children: [_jsx(TableCell, { onClick: (evt) => evt.stopPropagation(), children: _jsx(Checkbox, { checked: checkedItems.has(`${item.groupId}:${item.key}`), onClick: () => handleCheckboxChange(item) }) }), _jsx(TableCell, { className: "hover:bg-transparent", children: item.groupId }), _jsx(TableCell, { className: "hover:bg-transparent", children: item.key }), _jsx(TableCell, { className: "hover:bg-transparent", children: item.type })] }, `${item.groupId}:${item.key}`))) })] })] })] }));
|
|
56
|
-
};
|
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
export interface TraceGroup {
|
|
2
|
-
id: string;
|
|
3
|
-
correlationId: string | undefined;
|
|
4
|
-
name: string;
|
|
5
|
-
status: 'running' | 'completed' | 'failed';
|
|
6
|
-
startTime: number;
|
|
7
|
-
endTime?: number;
|
|
8
|
-
lastActivity: number;
|
|
9
|
-
metadata: {
|
|
10
|
-
completedSteps: number;
|
|
11
|
-
activeSteps: number;
|
|
12
|
-
totalSteps: number;
|
|
13
|
-
};
|
|
14
|
-
}
|
|
15
|
-
export interface Trace {
|
|
16
|
-
id: string;
|
|
17
|
-
name: string;
|
|
18
|
-
correlationId?: string;
|
|
19
|
-
parentTraceId?: string;
|
|
20
|
-
status: 'running' | 'completed' | 'failed';
|
|
21
|
-
startTime: number;
|
|
22
|
-
endTime?: number;
|
|
23
|
-
entryPoint: {
|
|
24
|
-
type: 'api' | 'event' | 'cron';
|
|
25
|
-
stepName: string;
|
|
26
|
-
};
|
|
27
|
-
events: TraceEvent[];
|
|
28
|
-
error?: TraceError;
|
|
29
|
-
}
|
|
30
|
-
export type TraceError = {
|
|
31
|
-
message: string;
|
|
32
|
-
code?: string | number;
|
|
33
|
-
stack?: string;
|
|
34
|
-
};
|
|
35
|
-
export type TraceEvent = StateEvent | EmitEvent | StreamEvent | LogEntry;
|
|
36
|
-
export type StateOperation = 'get' | 'getGroup' | 'set' | 'delete' | 'clear';
|
|
37
|
-
export type StreamOperation = 'get' | 'getGroup' | 'set' | 'delete' | 'clear' | 'send';
|
|
38
|
-
export interface StateEvent {
|
|
39
|
-
type: 'state';
|
|
40
|
-
timestamp: number;
|
|
41
|
-
operation: 'get' | 'getGroup' | 'set' | 'delete' | 'clear';
|
|
42
|
-
key?: string;
|
|
43
|
-
duration?: number;
|
|
44
|
-
data: any;
|
|
45
|
-
}
|
|
46
|
-
export interface EmitEvent {
|
|
47
|
-
type: 'emit';
|
|
48
|
-
timestamp: number;
|
|
49
|
-
topic: string;
|
|
50
|
-
success: boolean;
|
|
51
|
-
data: unknown;
|
|
52
|
-
}
|
|
53
|
-
export interface StreamEvent {
|
|
54
|
-
type: 'stream';
|
|
55
|
-
timestamp: number;
|
|
56
|
-
operation: StreamOperation;
|
|
57
|
-
streamName: string;
|
|
58
|
-
duration?: number;
|
|
59
|
-
data: {
|
|
60
|
-
groupId: string;
|
|
61
|
-
id: string;
|
|
62
|
-
data?: unknown;
|
|
63
|
-
};
|
|
64
|
-
calls: number;
|
|
65
|
-
}
|
|
66
|
-
export interface LogEntry {
|
|
67
|
-
type: 'log';
|
|
68
|
-
timestamp: number;
|
|
69
|
-
level: string;
|
|
70
|
-
message: string;
|
|
71
|
-
metadata?: unknown;
|
|
72
|
-
}
|
|
73
|
-
export interface ObservabilityStats {
|
|
74
|
-
total: number;
|
|
75
|
-
running: number;
|
|
76
|
-
completed: number;
|
|
77
|
-
failed: number;
|
|
78
|
-
}
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import type { Plugin } from 'vite';
|
|
2
|
-
export interface WorkbenchPlugin {
|
|
3
|
-
packageName: string;
|
|
4
|
-
componentName?: string;
|
|
5
|
-
position?: 'top' | 'bottom';
|
|
6
|
-
label?: string;
|
|
7
|
-
props?: Record<string, any>;
|
|
8
|
-
}
|
|
9
|
-
export default function motiaPluginsPlugin(plugins: WorkbenchPlugin[]): Plugin;
|
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.default = motiaPluginsPlugin;
|
|
7
|
-
const path_1 = __importDefault(require("path"));
|
|
8
|
-
const VIRTUAL_MODULE_ID = 'virtual:motia-plugins';
|
|
9
|
-
const RESOLVED_VIRTUAL_MODULE_ID = '\0' + VIRTUAL_MODULE_ID;
|
|
10
|
-
function motiaPluginsPlugin(plugins) {
|
|
11
|
-
const packages = Array.from(new Set(plugins.map(({ packageName }) => packageName)));
|
|
12
|
-
const alias = packages
|
|
13
|
-
.filter((packageName) => !packageName.includes('@motiadev/'))
|
|
14
|
-
.reduce((acc, packageName) => ({
|
|
15
|
-
...acc,
|
|
16
|
-
[packageName]: path_1.default.join(process.cwd(), './node_modules', packageName),
|
|
17
|
-
}), {});
|
|
18
|
-
const generatePluginCode = () => {
|
|
19
|
-
if (!packages.length) {
|
|
20
|
-
return '';
|
|
21
|
-
}
|
|
22
|
-
const imports = packages.map((packageName, index) => `import * as plugin_${index} from '${packageName}'`).join('\n');
|
|
23
|
-
const importsMap = packages.map((packageName, index) => `'${packageName}': plugin_${index}`);
|
|
24
|
-
return `
|
|
25
|
-
${imports}
|
|
26
|
-
const packageMap = {${importsMap}}
|
|
27
|
-
|
|
28
|
-
const motiaPlugins = ${JSON.stringify(plugins)}
|
|
29
|
-
|
|
30
|
-
export const plugins = motiaPlugins.map((plugin) => {
|
|
31
|
-
const component = packageMap[plugin.packageName]
|
|
32
|
-
const config = component.config || {}
|
|
33
|
-
const componentName = config.componentName || plugin.componentName
|
|
34
|
-
|
|
35
|
-
return {
|
|
36
|
-
label: plugin.label || config.label || 'Plugin label',
|
|
37
|
-
labelIcon: plugin.labelIcon || config.labelIcon || 'toy-brick',
|
|
38
|
-
position: plugin.position || config.position || 'top',
|
|
39
|
-
props: plugin.props || config.props || {},
|
|
40
|
-
component: componentName ? component[componentName] : component.default,
|
|
41
|
-
}
|
|
42
|
-
})
|
|
43
|
-
`;
|
|
44
|
-
};
|
|
45
|
-
return {
|
|
46
|
-
name: 'vite-plugin-motia-plugins',
|
|
47
|
-
config: () => ({
|
|
48
|
-
resolve: {
|
|
49
|
-
alias,
|
|
50
|
-
},
|
|
51
|
-
}),
|
|
52
|
-
resolveId(id) {
|
|
53
|
-
if (id === VIRTUAL_MODULE_ID) {
|
|
54
|
-
return RESOLVED_VIRTUAL_MODULE_ID;
|
|
55
|
-
}
|
|
56
|
-
},
|
|
57
|
-
load(id) {
|
|
58
|
-
if (id === RESOLVED_VIRTUAL_MODULE_ID) {
|
|
59
|
-
console.log(`[motia-plugins] Loading plugins`);
|
|
60
|
-
const code = generatePluginCode();
|
|
61
|
-
if (!code) {
|
|
62
|
-
console.log('[motia-plugins] No plugins found');
|
|
63
|
-
return '';
|
|
64
|
-
}
|
|
65
|
-
return code;
|
|
66
|
-
}
|
|
67
|
-
},
|
|
68
|
-
};
|
|
69
|
-
}
|
|
File without changes
|