@zhin.js/client 1.0.17 → 1.0.18
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/client/app.ts +228 -0
- package/client/index.ts +42 -14
- package/client/websocket/hooks.ts +218 -510
- package/client/websocket/index.ts +6 -43
- package/client/websocket/instance.ts +10 -32
- package/client/websocket/manager.ts +173 -390
- package/client/websocket/types.ts +58 -222
- package/dist/app.d.ts +95 -0
- package/dist/app.d.ts.map +1 -0
- package/dist/app.js +147 -0
- package/dist/app.js.map +1 -0
- package/dist/index.d.ts +7 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -14
- package/dist/index.js.map +1 -1
- package/dist/websocket/hooks.d.ts +35 -58
- package/dist/websocket/hooks.d.ts.map +1 -1
- package/dist/websocket/hooks.js +134 -410
- package/dist/websocket/hooks.js.map +1 -1
- package/dist/websocket/index.d.ts +5 -10
- package/dist/websocket/index.d.ts.map +1 -1
- package/dist/websocket/index.js +5 -25
- package/dist/websocket/index.js.map +1 -1
- package/dist/websocket/instance.d.ts +1 -14
- package/dist/websocket/instance.d.ts.map +1 -1
- package/dist/websocket/instance.js +2 -20
- package/dist/websocket/instance.js.map +1 -1
- package/dist/websocket/manager.d.ts +23 -93
- package/dist/websocket/manager.d.ts.map +1 -1
- package/dist/websocket/manager.js +87 -227
- package/dist/websocket/manager.js.map +1 -1
- package/dist/websocket/types.d.ts +35 -122
- package/dist/websocket/types.d.ts.map +1 -1
- package/dist/websocket/types.js +4 -13
- package/dist/websocket/types.js.map +1 -1
- package/package.json +12 -11
- package/client/router/index.tsx +0 -54
- package/client/store/index.ts +0 -132
- package/client/store/reducers/config.ts +0 -135
- package/client/store/reducers/index.ts +0 -19
- package/client/store/reducers/route.ts +0 -126
- package/client/store/reducers/script.ts +0 -109
- package/client/store/reducers/ui.ts +0 -31
- package/client/websocket/messageHandler.ts +0 -208
- package/dist/router/index.d.ts +0 -25
- package/dist/router/index.d.ts.map +0 -1
- package/dist/router/index.js +0 -48
- package/dist/router/index.js.map +0 -1
- package/dist/store/index.d.ts +0 -19
- package/dist/store/index.d.ts.map +0 -1
- package/dist/store/index.js +0 -67
- package/dist/store/index.js.map +0 -1
- package/dist/store/reducers/config.d.ts +0 -54
- package/dist/store/reducers/config.d.ts.map +0 -1
- package/dist/store/reducers/config.js +0 -78
- package/dist/store/reducers/config.js.map +0 -1
- package/dist/store/reducers/index.d.ts +0 -13
- package/dist/store/reducers/index.d.ts.map +0 -1
- package/dist/store/reducers/index.js +0 -11
- package/dist/store/reducers/index.js.map +0 -1
- package/dist/store/reducers/route.d.ts +0 -30
- package/dist/store/reducers/route.d.ts.map +0 -1
- package/dist/store/reducers/route.js +0 -85
- package/dist/store/reducers/route.js.map +0 -1
- package/dist/store/reducers/script.d.ts +0 -13
- package/dist/store/reducers/script.d.ts.map +0 -1
- package/dist/store/reducers/script.js +0 -78
- package/dist/store/reducers/script.js.map +0 -1
- package/dist/store/reducers/ui.d.ts +0 -8
- package/dist/store/reducers/ui.d.ts.map +0 -1
- package/dist/store/reducers/ui.js +0 -23
- package/dist/store/reducers/ui.js.map +0 -1
- package/dist/websocket/messageHandler.d.ts +0 -58
- package/dist/websocket/messageHandler.d.ts.map +0 -1
- package/dist/websocket/messageHandler.js +0 -174
- package/dist/websocket/messageHandler.js.map +0 -1
package/client/app.ts
ADDED
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
|
|
3
|
+
export type AddRouteInput = {
|
|
4
|
+
path: string;
|
|
5
|
+
name: string;
|
|
6
|
+
element: React.ReactNode;
|
|
7
|
+
parent?: string | null;
|
|
8
|
+
icon?: React.ReactNode | string;
|
|
9
|
+
requiredPermissions?: string[];
|
|
10
|
+
requiredRoles?: string[];
|
|
11
|
+
meta?: {
|
|
12
|
+
hideInMenu?: boolean;
|
|
13
|
+
order?: number;
|
|
14
|
+
group?: string;
|
|
15
|
+
fullWidth?: boolean;
|
|
16
|
+
};
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export type AddToolInput = {
|
|
20
|
+
id?: string;
|
|
21
|
+
name: string;
|
|
22
|
+
icon?: React.ReactNode;
|
|
23
|
+
parent?: string | null;
|
|
24
|
+
path?: string;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export type ConsoleRouteRecord = {
|
|
28
|
+
path: string;
|
|
29
|
+
name: string;
|
|
30
|
+
element: React.ReactNode;
|
|
31
|
+
parent: string | null;
|
|
32
|
+
icon?: React.ReactNode | string;
|
|
33
|
+
requiredPermissions?: string[];
|
|
34
|
+
requiredRoles?: string[];
|
|
35
|
+
meta?: {
|
|
36
|
+
hideInMenu?: boolean;
|
|
37
|
+
order?: number;
|
|
38
|
+
group?: string;
|
|
39
|
+
fullWidth?: boolean;
|
|
40
|
+
};
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
export type InternalToolRecord = {
|
|
44
|
+
id: string;
|
|
45
|
+
name: string;
|
|
46
|
+
icon?: React.ReactNode;
|
|
47
|
+
parent: string | null;
|
|
48
|
+
path?: string;
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
export type RouteTreeNode = ConsoleRouteRecord & { children: RouteTreeNode[] };
|
|
52
|
+
export type ToolTreeNode = InternalToolRecord & { children: ToolTreeNode[] };
|
|
53
|
+
|
|
54
|
+
type SidebarRenderer = (options: { routes: RouteTreeNode[] }) => React.ReactNode;
|
|
55
|
+
type ToolbarRenderer = (options: { tools: ToolTreeNode[] }) => React.ReactNode;
|
|
56
|
+
export type ConsoleRouteRenderer = (route: ConsoleRouteRecord) => React.ReactNode;
|
|
57
|
+
|
|
58
|
+
const listeners = new Set<() => void>();
|
|
59
|
+
let version = 0;
|
|
60
|
+
|
|
61
|
+
function bump() {
|
|
62
|
+
version++;
|
|
63
|
+
for (const l of listeners) l();
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function subscribe(listener: () => void) {
|
|
67
|
+
listeners.add(listener);
|
|
68
|
+
return () => listeners.delete(listener);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function getVersion() {
|
|
72
|
+
return version;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
let routes: ConsoleRouteRecord[] = [];
|
|
76
|
+
let tools: InternalToolRecord[] = [];
|
|
77
|
+
let sidebarRenderer: SidebarRenderer | null = null;
|
|
78
|
+
let toolbarRenderer: ToolbarRenderer | null = null;
|
|
79
|
+
let routeRenderer: ConsoleRouteRenderer | null = null;
|
|
80
|
+
|
|
81
|
+
function slugId(name: string) {
|
|
82
|
+
return (
|
|
83
|
+
name
|
|
84
|
+
.toLowerCase()
|
|
85
|
+
.replace(/[^a-z0-9]+/g, "-")
|
|
86
|
+
.replace(/^-|-$/g, "") || "tool"
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function buildRouteTree(flatRoutes: ConsoleRouteRecord[]): RouteTreeNode[] {
|
|
91
|
+
const nodes: RouteTreeNode[] = flatRoutes.map((r) => ({ ...r, children: [] }));
|
|
92
|
+
const roots: RouteTreeNode[] = [];
|
|
93
|
+
|
|
94
|
+
for (const node of nodes) {
|
|
95
|
+
if (!node.parent) {
|
|
96
|
+
roots.push(node);
|
|
97
|
+
} else {
|
|
98
|
+
const parent = nodes.find((n) => n.path === node.parent);
|
|
99
|
+
if (parent) {
|
|
100
|
+
parent.children.push(node);
|
|
101
|
+
} else {
|
|
102
|
+
roots.push(node);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const sortFn = (a: RouteTreeNode, b: RouteTreeNode) =>
|
|
108
|
+
(a.meta?.order ?? 999) - (b.meta?.order ?? 999);
|
|
109
|
+
roots.sort(sortFn);
|
|
110
|
+
for (const n of nodes) n.children.sort(sortFn);
|
|
111
|
+
|
|
112
|
+
return roots;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function buildToolTree(flatTools: InternalToolRecord[]): ToolTreeNode[] {
|
|
116
|
+
const nodes: ToolTreeNode[] = flatTools.map((t) => ({ ...t, children: [] }));
|
|
117
|
+
const roots: ToolTreeNode[] = [];
|
|
118
|
+
|
|
119
|
+
for (const node of nodes) {
|
|
120
|
+
if (!node.parent) {
|
|
121
|
+
roots.push(node);
|
|
122
|
+
} else {
|
|
123
|
+
const parent = nodes.find((n) => n.id === node.parent);
|
|
124
|
+
if (parent) {
|
|
125
|
+
parent.children.push(node);
|
|
126
|
+
} else {
|
|
127
|
+
roots.push(node);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
return roots;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
function renderRouteElement(route: ConsoleRouteRecord): React.ReactNode {
|
|
135
|
+
if (routeRenderer) return routeRenderer(route);
|
|
136
|
+
return route.element;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
function createConsoleApp() {
|
|
140
|
+
return {
|
|
141
|
+
subscribe,
|
|
142
|
+
getVersion,
|
|
143
|
+
|
|
144
|
+
defineSidebar(render: SidebarRenderer) {
|
|
145
|
+
sidebarRenderer = render;
|
|
146
|
+
bump();
|
|
147
|
+
},
|
|
148
|
+
|
|
149
|
+
defineToolbar(render: ToolbarRenderer) {
|
|
150
|
+
toolbarRenderer = render;
|
|
151
|
+
bump();
|
|
152
|
+
},
|
|
153
|
+
|
|
154
|
+
defineRouter(render: ConsoleRouteRenderer) {
|
|
155
|
+
routeRenderer = render;
|
|
156
|
+
bump();
|
|
157
|
+
},
|
|
158
|
+
|
|
159
|
+
addRoute(input: AddRouteInput) {
|
|
160
|
+
const next = routes.filter((r) => r.path !== input.path);
|
|
161
|
+
next.push({
|
|
162
|
+
path: input.path,
|
|
163
|
+
name: input.name,
|
|
164
|
+
element: input.element,
|
|
165
|
+
parent: input.parent ?? null,
|
|
166
|
+
icon: input.icon,
|
|
167
|
+
requiredPermissions: input.requiredPermissions,
|
|
168
|
+
requiredRoles: input.requiredRoles,
|
|
169
|
+
meta: input.meta,
|
|
170
|
+
});
|
|
171
|
+
routes = next;
|
|
172
|
+
bump();
|
|
173
|
+
},
|
|
174
|
+
|
|
175
|
+
removeRoute(path: string) {
|
|
176
|
+
routes = routes.filter((r) => r.path !== path);
|
|
177
|
+
bump();
|
|
178
|
+
},
|
|
179
|
+
|
|
180
|
+
addTool(input: AddToolInput): string {
|
|
181
|
+
const id =
|
|
182
|
+
input.id ?? `${slugId(input.name)}-${Math.random().toString(36).slice(2, 8)}`;
|
|
183
|
+
if (tools.some((t) => t.id === id)) {
|
|
184
|
+
throw new Error(`[zhin-console] addTool: id already exists: ${id}`);
|
|
185
|
+
}
|
|
186
|
+
tools = [
|
|
187
|
+
...tools,
|
|
188
|
+
{
|
|
189
|
+
id,
|
|
190
|
+
name: input.name,
|
|
191
|
+
icon: input.icon,
|
|
192
|
+
parent: input.parent ?? null,
|
|
193
|
+
path: input.path,
|
|
194
|
+
},
|
|
195
|
+
];
|
|
196
|
+
bump();
|
|
197
|
+
return id;
|
|
198
|
+
},
|
|
199
|
+
|
|
200
|
+
getRouteTree(): RouteTreeNode[] {
|
|
201
|
+
return buildRouteTree(routes);
|
|
202
|
+
},
|
|
203
|
+
|
|
204
|
+
getToolTree(): ToolTreeNode[] {
|
|
205
|
+
return buildToolTree(tools);
|
|
206
|
+
},
|
|
207
|
+
|
|
208
|
+
_getRoutes(): readonly ConsoleRouteRecord[] {
|
|
209
|
+
return routes;
|
|
210
|
+
},
|
|
211
|
+
|
|
212
|
+
_getSidebarRenderer(): SidebarRenderer | null {
|
|
213
|
+
return sidebarRenderer;
|
|
214
|
+
},
|
|
215
|
+
|
|
216
|
+
_getToolbarRenderer(): ToolbarRenderer | null {
|
|
217
|
+
return toolbarRenderer;
|
|
218
|
+
},
|
|
219
|
+
|
|
220
|
+
_renderRouteElement(route: ConsoleRouteRecord): React.ReactNode {
|
|
221
|
+
return renderRouteElement(route);
|
|
222
|
+
},
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
export type ConsoleApp = ReturnType<typeof createConsoleApp>;
|
|
227
|
+
|
|
228
|
+
export const app = createConsoleApp();
|
package/client/index.ts
CHANGED
|
@@ -1,20 +1,48 @@
|
|
|
1
|
-
import { type ClassValue, clsx } from 'clsx'
|
|
2
|
-
import { twMerge } from 'tailwind-merge'
|
|
3
1
|
// Types
|
|
4
|
-
export * from
|
|
2
|
+
export * from "./types";
|
|
5
3
|
|
|
6
|
-
//
|
|
7
|
-
export { resolveMediaSrc, pickMediaRawUrl, type MediaKind } from
|
|
4
|
+
// Media URL resolution
|
|
5
|
+
export { resolveMediaSrc, pickMediaRawUrl, type MediaKind } from "./mediaSrc";
|
|
8
6
|
|
|
9
|
-
//
|
|
10
|
-
export
|
|
7
|
+
// Console app singleton (page-manager style)
|
|
8
|
+
export {
|
|
9
|
+
app,
|
|
10
|
+
type ConsoleApp,
|
|
11
|
+
type AddRouteInput,
|
|
12
|
+
type AddToolInput,
|
|
13
|
+
type ConsoleRouteRecord,
|
|
14
|
+
type RouteTreeNode,
|
|
15
|
+
type ToolTreeNode,
|
|
16
|
+
type ConsoleRouteRenderer,
|
|
17
|
+
} from "./app";
|
|
11
18
|
|
|
12
|
-
//
|
|
13
|
-
export * from
|
|
19
|
+
// WebSocket (business data only)
|
|
20
|
+
export * from "./websocket";
|
|
14
21
|
|
|
15
|
-
//
|
|
16
|
-
export
|
|
22
|
+
// Re-export console-types
|
|
23
|
+
export type {
|
|
24
|
+
PluginRegisterHostApi,
|
|
25
|
+
PluginAddRouteInput,
|
|
26
|
+
PluginAddToolInput,
|
|
27
|
+
ConsolePluginRegister,
|
|
28
|
+
ConsoleClientEntry,
|
|
29
|
+
ConsoleEntriesResponse,
|
|
30
|
+
ConsoleEntry,
|
|
31
|
+
ConsoleFileAddEntryInput,
|
|
32
|
+
RuntimeEnv,
|
|
33
|
+
} from "@zhin.js/console-types";
|
|
17
34
|
|
|
18
|
-
export
|
|
19
|
-
|
|
20
|
-
|
|
35
|
+
export {
|
|
36
|
+
DEFAULT_CONSOLE_BASE_PATH,
|
|
37
|
+
CONSOLE_HOST_REACT_NAMESPACE_KEY,
|
|
38
|
+
} from "@zhin.js/console-types";
|
|
39
|
+
|
|
40
|
+
// Re-export console-core browser utilities
|
|
41
|
+
export {
|
|
42
|
+
createRegistryStore,
|
|
43
|
+
useRegistry,
|
|
44
|
+
type RegistryStore,
|
|
45
|
+
configureConsole,
|
|
46
|
+
getRuntimeEnv,
|
|
47
|
+
cn,
|
|
48
|
+
} from "@zhin.js/console-core/browser";
|