@rozenite/vite-plugin 1.13.0 → 2.0.0
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/README.md +12 -0
- package/dist/bundle-dts.d.ts.map +1 -1
- package/dist/client-plugin.d.ts.map +1 -1
- package/dist/dev-config-module.d.ts.map +1 -1
- package/dist/dev-host/assets/index-DU3zXL2c.css +1 -0
- package/dist/dev-host/assets/index-Xsb6uYhI.js +13 -0
- package/dist/dev-host/index.html +3 -3
- package/dist/dev-host/manifest.json +2 -2
- package/dist/index.cjs +24 -8
- package/dist/index.d.ts +9 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +24 -8
- package/dist/react-native-plugin.d.ts.map +1 -1
- package/dist/sdk-plugin.d.ts.map +1 -1
- package/dist/server-plugin.d.ts.map +1 -1
- package/dist/tsconfig.lib.tsbuildinfo +1 -1
- package/package.json +9 -10
- package/src/bundle-dts.ts +7 -6
- package/src/client-plugin.ts +8 -6
- package/src/dev-config-module.ts +4 -1
- package/src/dev-host/App.tsx +219 -413
- package/src/dev-host/components/DispatchForm.tsx +108 -122
- package/src/dev-host/components/FlowList.tsx +81 -101
- package/src/dev-host/components/MessageDetailsPane.tsx +56 -83
- package/src/dev-host/components/MessageLogPane.tsx +84 -66
- package/src/dev-host/components/PanelTabs.tsx +29 -10
- package/src/dev-host/config.ts +6 -2
- package/src/dev-host/constants.ts +0 -19
- package/src/dev-host/flow-runtime.ts +33 -12
- package/src/dev-host/index.html +1 -1
- package/src/dev-host/main.tsx +1 -10
- package/src/dev-host/server.ts +9 -3
- package/src/dev-host/styles.css +162 -830
- package/src/dev-host/types.ts +5 -10
- package/src/dev-host/utils.ts +9 -6
- package/src/dev-host/vite.config.mts +2 -0
- package/src/index.ts +15 -5
- package/src/load-config.ts +4 -4
- package/src/package-json.ts +1 -1
- package/src/react-native-plugin.ts +3 -0
- package/src/sdk-plugin.ts +3 -0
- package/src/server-plugin.ts +3 -0
- package/src/utils.ts +1 -1
- package/dist/dev-host/assets/index-CkxvBMpp.css +0 -1
- package/dist/dev-host/assets/index-cNKHRwej.js +0 -11
- package/src/dev-host/components/MessagePayloadDetail.tsx +0 -32
- package/src/dev-host/components/ResizeHandle.tsx +0 -33
- package/src/dev-host/components/icons.tsx +0 -79
- package/src/dev-host/components/ui/Button.tsx +0 -91
- package/src/dev-host/components/ui/DropdownMenu.tsx +0 -84
- package/src/dev-host/components/ui/IconButton.tsx +0 -41
- package/src/dev-host/components/ui/Input.tsx +0 -73
- package/src/dev-host/components/ui/ScrollArea.tsx +0 -20
- package/src/dev-host/components/ui/Tabs.tsx +0 -166
- package/src/dev-host/components/ui/Textarea.tsx +0 -79
- package/src/dev-host/components/ui/ToggleGroup.tsx +0 -120
|
@@ -1,84 +1,102 @@
|
|
|
1
|
+
import { Button, DataTable, ScrollArea } from '@rozenite/ui';
|
|
2
|
+
import { Trash2 } from 'lucide-react';
|
|
3
|
+
import { useMemo } from 'react';
|
|
4
|
+
import type { DataTableColumn } from '@rozenite/ui';
|
|
1
5
|
import type { MessageEntry } from '../types.js';
|
|
2
|
-
import {
|
|
3
|
-
import { ClearIcon } from './icons.js';
|
|
4
|
-
import { ScrollArea } from './ui/ScrollArea.js';
|
|
5
|
-
import { IconButton } from './ui/IconButton.js';
|
|
6
|
+
import { formatMessageTableDate, formatPayloadPreview } from '../utils.js';
|
|
6
7
|
|
|
7
8
|
type MessageLogPaneProps = {
|
|
8
9
|
messages: MessageEntry[];
|
|
9
|
-
selectedMessageId: string | null;
|
|
10
10
|
onSelectMessage: (messageId: string) => void;
|
|
11
11
|
onClearMessages: () => void;
|
|
12
12
|
};
|
|
13
13
|
|
|
14
14
|
export const MessageLogPane = ({
|
|
15
15
|
messages,
|
|
16
|
-
selectedMessageId,
|
|
17
16
|
onSelectMessage,
|
|
18
17
|
onClearMessages,
|
|
19
18
|
}: MessageLogPaneProps) => {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
onClick={onClearMessages}
|
|
29
|
-
disabled={messages.length === 0}
|
|
30
|
-
aria-label="Clear message log"
|
|
31
|
-
title="Clear message log"
|
|
32
|
-
>
|
|
33
|
-
<ClearIcon />
|
|
34
|
-
</IconButton>
|
|
35
|
-
</div>
|
|
36
|
-
</div>
|
|
37
|
-
|
|
38
|
-
<ScrollArea className="rz-sidebar-scroll">
|
|
39
|
-
<div className="rz-message-list">
|
|
40
|
-
<div className="rz-message-list-header">
|
|
41
|
-
<div className="rz-message-header-cell">Dir</div>
|
|
42
|
-
<div className="rz-message-header-cell">Date</div>
|
|
43
|
-
<div className="rz-message-header-cell">Type</div>
|
|
44
|
-
<div className="rz-message-header-cell">Payload</div>
|
|
45
|
-
</div>
|
|
46
|
-
|
|
47
|
-
{messages.map((message) => (
|
|
48
|
-
<button
|
|
49
|
-
key={message.id}
|
|
50
|
-
type="button"
|
|
51
|
-
className="rz-message-row"
|
|
52
|
-
data-selected={message.id === selectedMessageId}
|
|
53
|
-
onClick={() => onSelectMessage(message.id)}
|
|
54
|
-
>
|
|
55
|
-
<div
|
|
56
|
-
className={cn(
|
|
57
|
-
'rz-message-cell rz-message-direction',
|
|
58
|
-
message.direction === 'in' ? 'rz-message-dir-in' : 'rz-message-dir-out',
|
|
59
|
-
)}
|
|
60
|
-
aria-label={message.direction === 'in' ? 'Sent message' : 'Received message'}
|
|
61
|
-
title={message.direction === 'in' ? 'Sent message' : 'Received message'}
|
|
62
|
-
>
|
|
63
|
-
<span className="rz-message-arrow" aria-hidden="true">
|
|
64
|
-
{message.direction === 'in' ? '↑' : '↓'}
|
|
65
|
-
</span>
|
|
66
|
-
</div>
|
|
19
|
+
const columns = useMemo<DataTableColumn<MessageEntry>[]>(
|
|
20
|
+
() => [
|
|
21
|
+
{
|
|
22
|
+
accessorKey: 'direction',
|
|
23
|
+
header: 'Dir',
|
|
24
|
+
cell: ({ getValue }) => {
|
|
25
|
+
const direction = getValue<MessageEntry['direction']>();
|
|
26
|
+
const isSent = direction === 'in';
|
|
67
27
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
28
|
+
return (
|
|
29
|
+
<span
|
|
30
|
+
className={
|
|
31
|
+
isSent ? 'dev-host-direction-in' : 'dev-host-direction-out'
|
|
32
|
+
}
|
|
33
|
+
aria-label={isSent ? 'Sent message' : 'Received message'}
|
|
34
|
+
title={isSent ? 'Sent message' : 'Received message'}
|
|
35
|
+
>
|
|
36
|
+
{isSent ? '↑' : '↓'}
|
|
37
|
+
</span>
|
|
38
|
+
);
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
accessorKey: 'date',
|
|
43
|
+
header: 'Date',
|
|
44
|
+
cell: ({ row }) => (
|
|
45
|
+
<span className="text-muted-foreground">
|
|
46
|
+
{formatMessageTableDate(row.original.date)}
|
|
47
|
+
</span>
|
|
48
|
+
),
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
accessorKey: 'type',
|
|
52
|
+
header: 'Type',
|
|
53
|
+
cell: ({ getValue }) => (
|
|
54
|
+
<span className="font-medium">{getValue<string>()}</span>
|
|
55
|
+
),
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
id: 'payload',
|
|
59
|
+
accessorFn: (message) => formatPayloadPreview(message.payload),
|
|
60
|
+
header: 'Payload',
|
|
61
|
+
cell: ({ getValue }) => (
|
|
62
|
+
<span className="block max-w-160 truncate font-mono text-xs text-muted-foreground">
|
|
63
|
+
{getValue<string>()}
|
|
64
|
+
</span>
|
|
65
|
+
),
|
|
66
|
+
},
|
|
67
|
+
],
|
|
68
|
+
[],
|
|
69
|
+
);
|
|
71
70
|
|
|
72
|
-
|
|
71
|
+
return (
|
|
72
|
+
<section className="dev-host-pane">
|
|
73
|
+
<header className="dev-host-pane-header">
|
|
74
|
+
<h2 className="dev-host-pane-title">Message Log</h2>
|
|
75
|
+
<Button
|
|
76
|
+
variant="ghost"
|
|
77
|
+
size="icon"
|
|
78
|
+
onClick={onClearMessages}
|
|
79
|
+
disabled={messages.length === 0}
|
|
80
|
+
aria-label="Clear message log"
|
|
81
|
+
title="Clear message log"
|
|
82
|
+
>
|
|
83
|
+
<Trash2 />
|
|
84
|
+
</Button>
|
|
85
|
+
</header>
|
|
73
86
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
87
|
+
<ScrollArea
|
|
88
|
+
className="dev-host-scroll"
|
|
89
|
+
viewportClassName="dev-host-scroll-viewport"
|
|
90
|
+
>
|
|
91
|
+
<DataTable
|
|
92
|
+
className="dev-host-message-table"
|
|
93
|
+
columns={columns}
|
|
94
|
+
data={messages}
|
|
95
|
+
emptyMessage="No messages yet."
|
|
96
|
+
getRowId={(message) => message.id}
|
|
97
|
+
onRowClick={(message) => onSelectMessage(message.id)}
|
|
98
|
+
/>
|
|
99
|
+
</ScrollArea>
|
|
100
|
+
</section>
|
|
83
101
|
);
|
|
84
102
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
import { Select } from '@rozenite/ui';
|
|
1
2
|
import type { DevHostPanelEntry } from '../types.js';
|
|
2
|
-
import { ToggleGroup } from './ui/ToggleGroup.js';
|
|
3
3
|
|
|
4
4
|
type PanelTabsProps = {
|
|
5
5
|
panels: DevHostPanelEntry[];
|
|
@@ -7,16 +7,35 @@ type PanelTabsProps = {
|
|
|
7
7
|
onValueChange: (value: string) => void;
|
|
8
8
|
};
|
|
9
9
|
|
|
10
|
-
export const PanelTabs = ({
|
|
10
|
+
export const PanelTabs = ({
|
|
11
|
+
panels,
|
|
12
|
+
activeSource,
|
|
13
|
+
onValueChange,
|
|
14
|
+
}: PanelTabsProps) => {
|
|
15
|
+
if (panels.length === 0) {
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const activePanel = panels.find((panel) => panel.source === activeSource);
|
|
20
|
+
|
|
11
21
|
return (
|
|
12
|
-
<
|
|
13
|
-
aria-label="Plugin panels"
|
|
22
|
+
<Select
|
|
14
23
|
value={activeSource}
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
24
|
+
onValueChange={(value) => onValueChange(String(value))}
|
|
25
|
+
>
|
|
26
|
+
<Select.Trigger
|
|
27
|
+
className="dev-host-panel-select"
|
|
28
|
+
aria-label="Plugin panel"
|
|
29
|
+
>
|
|
30
|
+
<Select.Value>{activePanel?.label}</Select.Value>
|
|
31
|
+
</Select.Trigger>
|
|
32
|
+
<Select.Content align="end">
|
|
33
|
+
{panels.map((panel) => (
|
|
34
|
+
<Select.Item key={panel.source} value={panel.source}>
|
|
35
|
+
{panel.label}
|
|
36
|
+
</Select.Item>
|
|
37
|
+
))}
|
|
38
|
+
</Select.Content>
|
|
39
|
+
</Select>
|
|
21
40
|
);
|
|
22
41
|
};
|
package/src/dev-host/config.ts
CHANGED
|
@@ -19,7 +19,9 @@ const getEntryDisplayName = (value: unknown, fallback: string) => {
|
|
|
19
19
|
};
|
|
20
20
|
|
|
21
21
|
const getDevHostConfig = () => {
|
|
22
|
-
const value = (window as unknown as Record<string, unknown>)[
|
|
22
|
+
const value = (window as unknown as Record<string, unknown>)[
|
|
23
|
+
DEV_HOST_CONFIG_GLOBAL_KEY
|
|
24
|
+
];
|
|
23
25
|
|
|
24
26
|
if (typeof value !== 'object' || value === null) {
|
|
25
27
|
return {} as { presets?: unknown; flows?: unknown };
|
|
@@ -28,7 +30,9 @@ const getDevHostConfig = () => {
|
|
|
28
30
|
return value as { presets?: unknown; flows?: unknown };
|
|
29
31
|
};
|
|
30
32
|
|
|
31
|
-
const isDevHostPresetSource = (
|
|
33
|
+
const isDevHostPresetSource = (
|
|
34
|
+
value: unknown,
|
|
35
|
+
): value is DevHostPresetSource => {
|
|
32
36
|
return (
|
|
33
37
|
typeof value === 'object' &&
|
|
34
38
|
value !== null &&
|
|
@@ -10,22 +10,3 @@ export const MIN_DETAILS_WIDTH = 280;
|
|
|
10
10
|
export const DEFAULT_COMMAND_WIDTH = 320;
|
|
11
11
|
export const MIN_COMMAND_WIDTH = 260;
|
|
12
12
|
export const SPLITTER_SIZE = 6;
|
|
13
|
-
|
|
14
|
-
export const jsonTreeTheme = {
|
|
15
|
-
base00: 'transparent',
|
|
16
|
-
base01: '#374151',
|
|
17
|
-
base02: '#4b5563',
|
|
18
|
-
base03: '#6b7280',
|
|
19
|
-
base04: '#9ca3af',
|
|
20
|
-
base05: '#d1d5db',
|
|
21
|
-
base06: '#e5e7eb',
|
|
22
|
-
base07: '#f9fafb',
|
|
23
|
-
base08: '#ef4444',
|
|
24
|
-
base09: '#f59e0b',
|
|
25
|
-
base0A: '#10b981',
|
|
26
|
-
base0B: '#3b82f6',
|
|
27
|
-
base0C: '#06b6d4',
|
|
28
|
-
base0D: '#8b5cf6',
|
|
29
|
-
base0E: '#ec4899',
|
|
30
|
-
base0F: '#f97316',
|
|
31
|
-
};
|
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
import { useEffect, useRef, useState } from 'react';
|
|
2
|
-
import type {
|
|
3
|
-
|
|
2
|
+
import type {
|
|
3
|
+
DevFlowContext,
|
|
4
|
+
DevFlowMessage,
|
|
5
|
+
DevFlowMessageMatcher,
|
|
6
|
+
} from '../load-config.js';
|
|
7
|
+
import type {
|
|
8
|
+
DevHostFlowEntry,
|
|
9
|
+
DevHostFlowRunState,
|
|
10
|
+
MessageEntry,
|
|
11
|
+
} from './types.js';
|
|
4
12
|
|
|
5
13
|
type FlowRunnerOptions = {
|
|
6
14
|
sendMessage: (type: string, payload: unknown) => void;
|
|
@@ -138,12 +146,12 @@ export const useFlowRunner = ({ sendMessage }: FlowRunnerOptions) => {
|
|
|
138
146
|
}
|
|
139
147
|
};
|
|
140
148
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
149
|
+
const cleanupRun = () => {
|
|
150
|
+
activeRun.cleanups.forEach((cleanup) => cleanup());
|
|
151
|
+
activeRun.cleanups.clear();
|
|
152
|
+
activeRun.listeners.clear();
|
|
153
|
+
activeRunsRef.current.delete(runId);
|
|
154
|
+
};
|
|
147
155
|
|
|
148
156
|
const onMessage: DevFlowContext['onMessage'] = (matcher, listener) => {
|
|
149
157
|
throwIfAborted();
|
|
@@ -203,13 +211,17 @@ export const useFlowRunner = ({ sendMessage }: FlowRunnerOptions) => {
|
|
|
203
211
|
resolve(message);
|
|
204
212
|
});
|
|
205
213
|
|
|
206
|
-
controller.signal.addEventListener('abort', handleAbort, {
|
|
214
|
+
controller.signal.addEventListener('abort', handleAbort, {
|
|
215
|
+
once: true,
|
|
216
|
+
});
|
|
207
217
|
|
|
208
218
|
if (options?.timeoutMs != null) {
|
|
209
219
|
timeoutId = window.setTimeout(() => {
|
|
210
220
|
cleanup();
|
|
211
221
|
reject(
|
|
212
|
-
new Error(
|
|
222
|
+
new Error(
|
|
223
|
+
`Timed out waiting for a matching message after ${options.timeoutMs}ms.`,
|
|
224
|
+
),
|
|
213
225
|
);
|
|
214
226
|
}, options.timeoutMs);
|
|
215
227
|
}
|
|
@@ -238,7 +250,14 @@ export const useFlowRunner = ({ sendMessage }: FlowRunnerOptions) => {
|
|
|
238
250
|
...current,
|
|
239
251
|
]);
|
|
240
252
|
|
|
241
|
-
const updateRunState = (
|
|
253
|
+
const updateRunState = (
|
|
254
|
+
nextState: Partial<
|
|
255
|
+
Omit<
|
|
256
|
+
DevHostFlowRunState,
|
|
257
|
+
'id' | 'flowName' | 'flowDisplayName' | 'autoRun'
|
|
258
|
+
>
|
|
259
|
+
>,
|
|
260
|
+
) => {
|
|
242
261
|
setFlowRuns((current) =>
|
|
243
262
|
current.map((run) =>
|
|
244
263
|
run.id === runId
|
|
@@ -283,7 +302,9 @@ export const useFlowRunner = ({ sendMessage }: FlowRunnerOptions) => {
|
|
|
283
302
|
};
|
|
284
303
|
|
|
285
304
|
const hasRunningFlow = (flowName: string) => {
|
|
286
|
-
return flowRuns.some(
|
|
305
|
+
return flowRuns.some(
|
|
306
|
+
(run) => run.flowName === flowName && run.status === 'running',
|
|
307
|
+
);
|
|
287
308
|
};
|
|
288
309
|
|
|
289
310
|
return {
|
package/src/dev-host/index.html
CHANGED
package/src/dev-host/main.tsx
CHANGED
|
@@ -1,15 +1,10 @@
|
|
|
1
1
|
import { StrictMode } from 'react';
|
|
2
2
|
import { createRoot } from 'react-dom/client';
|
|
3
|
-
import { BaseProvider, DarkTheme } from 'baseui';
|
|
4
|
-
import { Client as Styletron } from 'styletron-engine-monolithic';
|
|
5
|
-
import { Provider as StyletronProvider } from 'styletron-react';
|
|
6
3
|
import { App } from './App.js';
|
|
7
4
|
import { getDevHostFlows, getDevHostPresets } from './config.js';
|
|
8
5
|
import './styles.css';
|
|
9
6
|
import { readDevHostState } from './utils.js';
|
|
10
7
|
|
|
11
|
-
const styletron = new Styletron();
|
|
12
|
-
|
|
13
8
|
const rootElement = document.getElementById('root');
|
|
14
9
|
|
|
15
10
|
if (!rootElement) {
|
|
@@ -22,10 +17,6 @@ const presets = getDevHostPresets();
|
|
|
22
17
|
|
|
23
18
|
createRoot(rootElement).render(
|
|
24
19
|
<StrictMode>
|
|
25
|
-
<
|
|
26
|
-
<BaseProvider theme={DarkTheme}>
|
|
27
|
-
<App {...state} flows={flows} presets={presets} />
|
|
28
|
-
</BaseProvider>
|
|
29
|
-
</StyletronProvider>
|
|
20
|
+
<App {...state} flows={flows} presets={presets} />
|
|
30
21
|
</StrictMode>,
|
|
31
22
|
);
|
package/src/dev-host/server.ts
CHANGED
|
@@ -33,7 +33,9 @@ export const getDevHostSourceEntryFile = (packageDir: string) => {
|
|
|
33
33
|
return path.join(packageDir, 'src', 'dev-host', 'main.tsx');
|
|
34
34
|
};
|
|
35
35
|
|
|
36
|
-
export const getBuiltDevHostAssets = (
|
|
36
|
+
export const getBuiltDevHostAssets = (
|
|
37
|
+
packageDir: string,
|
|
38
|
+
): DevHostBuiltAssets | null => {
|
|
37
39
|
const devHostDistDir = path.join(packageDir, 'dist', 'dev-host');
|
|
38
40
|
const manifestPath = path.join(devHostDistDir, 'manifest.json');
|
|
39
41
|
|
|
@@ -41,11 +43,15 @@ export const getBuiltDevHostAssets = (packageDir: string): DevHostBuiltAssets |
|
|
|
41
43
|
return null;
|
|
42
44
|
}
|
|
43
45
|
|
|
44
|
-
const manifest = JSON.parse(
|
|
46
|
+
const manifest = JSON.parse(
|
|
47
|
+
fs.readFileSync(manifestPath, 'utf8'),
|
|
48
|
+
) as DevHostBuildManifest;
|
|
45
49
|
const entry = manifest[DEV_HOST_BUILD_ENTRY_KEY];
|
|
46
50
|
|
|
47
51
|
if (!entry?.file) {
|
|
48
|
-
throw new Error(
|
|
52
|
+
throw new Error(
|
|
53
|
+
`Missing ${DEV_HOST_BUILD_ENTRY_KEY} entry in dev host manifest.`,
|
|
54
|
+
);
|
|
49
55
|
}
|
|
50
56
|
|
|
51
57
|
return {
|