@zhin.js/console 1.0.13 → 1.0.15

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/lib/dev.js CHANGED
@@ -1,74 +1,87 @@
1
- import react from '@vitejs/plugin-react';
2
- import tailwindcss from '@tailwindcss/vite';
3
1
  import path from 'path';
4
2
  import fs from 'fs';
5
3
 
6
4
  // src/dev.ts
7
5
  async function createViteDevServer(options) {
8
6
  const { root, base = "/vite/", enableTailwind = true } = options;
9
- const { createServer, searchForWorkspaceRoot } = await import('vite');
10
- const plugins = [react()];
11
- if (enableTailwind) {
12
- plugins.push(tailwindcss());
13
- }
14
- const clientPath = path.resolve(process.cwd(), "node_modules/@zhin.js/client/client");
15
- if (!fs.existsSync(clientPath)) {
16
- throw new Error("@zhin.js/client not found");
17
- }
18
- return await await createServer({
19
- root,
20
- base,
21
- plugins: [react(), tailwindcss()],
22
- server: {
23
- middlewareMode: true,
24
- allowedHosts: true,
25
- fs: {
26
- strict: false,
27
- // 添加文件访问过滤,避免访问特殊文件
28
- allow: [
29
- // 允许访问的目录
30
- root,
31
- searchForWorkspaceRoot(root),
32
- path.resolve(process.cwd(), "node_modules"),
33
- path.resolve(process.cwd(), "client"),
34
- path.resolve(process.cwd(), "src")
7
+ try {
8
+ const [
9
+ { createServer, searchForWorkspaceRoot },
10
+ { default: react },
11
+ { default: tailwindcss }
12
+ ] = await Promise.all([
13
+ import('vite'),
14
+ import('@vitejs/plugin-react'),
15
+ import('@tailwindcss/vite')
16
+ ]);
17
+ const plugins = [react()];
18
+ if (enableTailwind) {
19
+ plugins.push(tailwindcss());
20
+ }
21
+ const clientPath = path.resolve(process.cwd(), "node_modules/@zhin.js/client/client");
22
+ if (!fs.existsSync(clientPath)) {
23
+ throw new Error("@zhin.js/client not found");
24
+ }
25
+ return await createServer({
26
+ root,
27
+ base,
28
+ plugins: [react(), tailwindcss()],
29
+ server: {
30
+ middlewareMode: true,
31
+ allowedHosts: true,
32
+ fs: {
33
+ strict: false,
34
+ // 添加文件访问过滤,避免访问特殊文件
35
+ allow: [
36
+ // 允许访问的目录
37
+ root,
38
+ searchForWorkspaceRoot(root),
39
+ path.resolve(process.cwd(), "node_modules"),
40
+ path.resolve(process.cwd(), "client"),
41
+ path.resolve(process.cwd(), "src")
42
+ ],
43
+ // 拒绝访问某些文件模式
44
+ deny: [
45
+ "**/.git/**",
46
+ "**/node_modules/.cache/**",
47
+ "**/*.socket",
48
+ "**/*.pipe",
49
+ "**/Dockerfile*",
50
+ "**/.env*"
51
+ ]
52
+ }
53
+ },
54
+ resolve: {
55
+ dedupe: [
56
+ "react",
57
+ "react-dom",
58
+ "clsx",
59
+ "tailwind-merge",
60
+ "@reduxjs/toolkit",
61
+ "react-router",
62
+ "react-redux",
63
+ "redux-persist"
35
64
  ],
36
- // 拒绝访问某些文件模式
37
- deny: [
38
- "**/.git/**",
39
- "**/node_modules/.cache/**",
40
- "**/*.socket",
41
- "**/*.pipe",
42
- "**/Dockerfile*",
43
- "**/.env*"
44
- ]
65
+ alias: {
66
+ "@zhin.js/client": path.resolve(process.cwd(), "node_modules/@zhin.js/client/client"),
67
+ "@": path.resolve(root, "../client/src")
68
+ }
69
+ },
70
+ optimizeDeps: {
71
+ include: ["react", "react-dom"]
72
+ },
73
+ build: {
74
+ rollupOptions: {
75
+ input: root + "/index.html"
76
+ }
45
77
  }
46
- },
47
- resolve: {
48
- dedupe: [
49
- "react",
50
- "react-dom",
51
- "clsx",
52
- "tailwind-merge",
53
- "@reduxjs/toolkit",
54
- "react-router",
55
- "react-redux",
56
- "redux-persist"
57
- ],
58
- alias: {
59
- "@zhin.js/client": path.resolve(process.cwd(), "node_modules/@zhin.js/client/client"),
60
- "@": path.resolve(root, "../client/src")
61
- }
62
- },
63
- optimizeDeps: {
64
- include: ["react", "react-dom"]
65
- },
66
- build: {
67
- rollupOptions: {
68
- input: root + "/index.html"
69
- }
70
- }
71
- });
78
+ });
79
+ } catch (error) {
80
+ throw new Error(
81
+ `Failed to create Vite dev server. Make sure all development dependencies are installed: vite, @vitejs/plugin-react, @tailwindcss/vite. Run: pnpm install --include=optional
82
+ Original error: ${error.message}`
83
+ );
84
+ }
72
85
  }
73
86
 
74
87
  export { createViteDevServer };
package/lib/index.d.ts CHANGED
@@ -1,20 +1,31 @@
1
+ import * as _zhin_js_http from '@zhin.js/http';
1
2
  import { WebSocketServer } from 'ws';
2
3
  import { ViteDevServer } from 'vite';
3
4
 
4
- declare module "@zhin.js/types" {
5
- interface GlobalContext {
6
- web: WebServer;
7
- }
5
+ interface ConsoleConfig {
6
+ /** 是否启用控制台插件,默认 true */
7
+ enabled?: boolean;
8
+ /** 是否延迟加载 Vite(开发模式),默认 true */
9
+ /** 端口号(继承自 http 配置) */
10
+ port?: number;
8
11
  }
9
12
  type WebEntry = string | {
10
13
  production: string;
11
14
  development: string;
12
15
  };
13
- type WebServer = {
16
+ interface WebServer {
14
17
  vite?: ViteDevServer;
15
18
  addEntry(entry: WebEntry): () => void;
16
19
  entries: Record<string, string>;
17
20
  ws: WebSocketServer;
18
- };
21
+ }
22
+ declare module "@zhin.js/core" {
23
+ namespace Plugin {
24
+ interface Contexts {
25
+ web: WebServer;
26
+ router: _zhin_js_http.Router;
27
+ }
28
+ }
29
+ }
19
30
 
20
- export type { WebEntry, WebServer };
31
+ export type { ConsoleConfig, WebEntry, WebServer };
package/lib/index.js CHANGED
@@ -1,10 +1,112 @@
1
- import { useLogger, useContext, register } from '@zhin.js/core';
1
+ import * as path2 from 'path';
2
+ import path2__default from 'path';
3
+ import * as fs2 from 'fs';
4
+ import fs2__default from 'fs';
5
+ import { usePlugin } from '@zhin.js/core';
2
6
  import mime from 'mime';
3
- import * as fs from 'fs';
4
- import * as path from 'path';
5
7
  import WebSocket from 'ws';
6
8
 
7
- // src/index.ts
9
+ var __defProp = Object.defineProperty;
10
+ var __getOwnPropNames = Object.getOwnPropertyNames;
11
+ var __esm = (fn, res) => function __init() {
12
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
13
+ };
14
+ var __export = (target, all) => {
15
+ for (var name in all)
16
+ __defProp(target, name, { get: all[name], enumerable: true });
17
+ };
18
+
19
+ // src/dev.ts
20
+ var dev_exports = {};
21
+ __export(dev_exports, {
22
+ createViteDevServer: () => createViteDevServer
23
+ });
24
+ async function createViteDevServer(options) {
25
+ const { root: root3, base = "/vite/", enableTailwind = true } = options;
26
+ try {
27
+ const [
28
+ { createServer, searchForWorkspaceRoot },
29
+ { default: react },
30
+ { default: tailwindcss }
31
+ ] = await Promise.all([
32
+ import('vite'),
33
+ import('@vitejs/plugin-react'),
34
+ import('@tailwindcss/vite')
35
+ ]);
36
+ const plugins = [react()];
37
+ if (enableTailwind) {
38
+ plugins.push(tailwindcss());
39
+ }
40
+ const clientPath = path2__default.resolve(process.cwd(), "node_modules/@zhin.js/client/client");
41
+ if (!fs2__default.existsSync(clientPath)) {
42
+ throw new Error("@zhin.js/client not found");
43
+ }
44
+ return await createServer({
45
+ root: root3,
46
+ base,
47
+ plugins: [react(), tailwindcss()],
48
+ server: {
49
+ middlewareMode: true,
50
+ allowedHosts: true,
51
+ fs: {
52
+ strict: false,
53
+ // 添加文件访问过滤,避免访问特殊文件
54
+ allow: [
55
+ // 允许访问的目录
56
+ root3,
57
+ searchForWorkspaceRoot(root3),
58
+ path2__default.resolve(process.cwd(), "node_modules"),
59
+ path2__default.resolve(process.cwd(), "client"),
60
+ path2__default.resolve(process.cwd(), "src")
61
+ ],
62
+ // 拒绝访问某些文件模式
63
+ deny: [
64
+ "**/.git/**",
65
+ "**/node_modules/.cache/**",
66
+ "**/*.socket",
67
+ "**/*.pipe",
68
+ "**/Dockerfile*",
69
+ "**/.env*"
70
+ ]
71
+ }
72
+ },
73
+ resolve: {
74
+ dedupe: [
75
+ "react",
76
+ "react-dom",
77
+ "clsx",
78
+ "tailwind-merge",
79
+ "@reduxjs/toolkit",
80
+ "react-router",
81
+ "react-redux",
82
+ "redux-persist"
83
+ ],
84
+ alias: {
85
+ "@zhin.js/client": path2__default.resolve(process.cwd(), "node_modules/@zhin.js/client/client"),
86
+ "@": path2__default.resolve(root3, "../client/src")
87
+ }
88
+ },
89
+ optimizeDeps: {
90
+ include: ["react", "react-dom"]
91
+ },
92
+ build: {
93
+ rollupOptions: {
94
+ input: root3 + "/index.html"
95
+ }
96
+ }
97
+ });
98
+ } catch (error) {
99
+ throw new Error(
100
+ `Failed to create Vite dev server. Make sure all development dependencies are installed: vite, @vitejs/plugin-react, @tailwindcss/vite. Run: pnpm install --include=optional
101
+ Original error: ${error.message}`
102
+ );
103
+ }
104
+ }
105
+ var init_dev = __esm({
106
+ "src/dev.ts"() {
107
+ }
108
+ });
109
+ var { root, logger } = usePlugin();
8
110
  function setupWebSocket(webServer) {
9
111
  webServer.ws.on("connection", (ws) => {
10
112
  ws.send(
@@ -43,7 +145,7 @@ function setupWebSocket(webServer) {
43
145
  });
44
146
  }
45
147
  async function handleWebSocketMessage(ws, message, webServer) {
46
- const { type, requestId } = message;
148
+ const { type, requestId, pluginName } = message;
47
149
  switch (type) {
48
150
  case "ping":
49
151
  ws.send(JSON.stringify({ type: "pong", requestId }));
@@ -56,6 +158,72 @@ async function handleWebSocketMessage(ws, message, webServer) {
56
158
  })
57
159
  );
58
160
  break;
161
+ case "config:get":
162
+ try {
163
+ const configService2 = root.inject("config");
164
+ const appConfig2 = configService2.get("zhin.config.yml");
165
+ const config = pluginName ? appConfig2[pluginName] || {} : appConfig2;
166
+ ws.send(JSON.stringify({ requestId, data: config }));
167
+ } catch (error) {
168
+ ws.send(JSON.stringify({ requestId, error: `Failed to get config: ${error.message}` }));
169
+ }
170
+ break;
171
+ case "config:get-all":
172
+ try {
173
+ const configService2 = root.inject("config");
174
+ const appConfig2 = configService2.get("zhin.config.yml");
175
+ ws.send(JSON.stringify({ requestId, data: appConfig2 }));
176
+ } catch (error) {
177
+ ws.send(JSON.stringify({ requestId, error: `Failed to get all configs: ${error.message}` }));
178
+ }
179
+ break;
180
+ case "config:set":
181
+ try {
182
+ const { data } = message;
183
+ if (!pluginName) {
184
+ ws.send(JSON.stringify({ requestId, error: "Plugin name is required" }));
185
+ break;
186
+ }
187
+ const configService2 = root.inject("config");
188
+ const appConfig2 = configService2.get("zhin.config.yml");
189
+ appConfig2[pluginName] = data;
190
+ configService2.set("zhin.config.yml", appConfig2);
191
+ ws.send(JSON.stringify({ requestId, success: true }));
192
+ broadcastToAll(webServer, {
193
+ type: "config:updated",
194
+ data: { pluginName, config: data }
195
+ });
196
+ } catch (error) {
197
+ ws.send(JSON.stringify({ requestId, error: `Failed to set config: ${error.message}` }));
198
+ }
199
+ break;
200
+ case "schema:get":
201
+ try {
202
+ const schemaService = root.inject("schema");
203
+ const schema = pluginName && schemaService ? schemaService.get(pluginName) : null;
204
+ if (schema) {
205
+ ws.send(JSON.stringify({ requestId, data: schema.toJSON() }));
206
+ } else {
207
+ ws.send(JSON.stringify({ requestId, data: null }));
208
+ }
209
+ } catch (error) {
210
+ ws.send(JSON.stringify({ requestId, error: `Failed to get schema: ${error.message}` }));
211
+ }
212
+ break;
213
+ case "schema:get-all":
214
+ try {
215
+ const schemaService = root.inject("schema");
216
+ const schemas = {};
217
+ if (schemaService) {
218
+ for (const [name, schema] of schemaService.items.entries()) {
219
+ schemas[name] = schema.toJSON();
220
+ }
221
+ }
222
+ ws.send(JSON.stringify({ requestId, data: schemas }));
223
+ } catch (error) {
224
+ ws.send(JSON.stringify({ requestId, error: `Failed to get all schemas: ${error.message}` }));
225
+ }
226
+ break;
59
227
  default:
60
228
  ws.send(
61
229
  JSON.stringify({
@@ -78,113 +246,180 @@ function notifyDataUpdate(webServer) {
78
246
  timestamp: Date.now()
79
247
  });
80
248
  }
81
- useLogger();
82
- var createAddMsg = (key, value) => {
83
- return {
249
+
250
+ // src/index.ts
251
+ async function loadDevDependencies() {
252
+ try {
253
+ const devModule = await Promise.resolve().then(() => (init_dev(), dev_exports));
254
+ const koaConnectModule = await import('koa-connect');
255
+ return {
256
+ createViteDevServer: devModule.createViteDevServer,
257
+ connect: koaConnectModule.default
258
+ };
259
+ } catch {
260
+ return null;
261
+ }
262
+ }
263
+ var { provide, root: root2, useContext, logger: logger2, inject, onDispose } = usePlugin();
264
+ var configService = inject("config");
265
+ var appConfig = configService?.get("zhin.config.yml") || {};
266
+ var consoleConfig = appConfig.plugins?.console || {};
267
+ var {
268
+ enabled = true
269
+ // 默认不延迟加载,避免 addEntry 等功能不可用
270
+ } = consoleConfig;
271
+ if (enabled) {
272
+ const createAddMsg = (key, value) => ({
84
273
  type: "add",
85
- data: {
86
- key,
87
- value
88
- }
89
- };
90
- };
91
- var createDeleteMsg = (key, value) => {
92
- return {
274
+ data: { key, value }
275
+ });
276
+ const createDeleteMsg = (key, value) => ({
93
277
  type: "delete",
94
- data: {
95
- key,
96
- value
97
- }
98
- };
99
- };
100
- useContext("router", async (router) => {
101
- const base = "/vite/";
102
- const webServer = {
103
- entries: {},
104
- addEntry(entry) {
105
- const hash = Date.now().toString(16) + Math.random().toString(16).slice(2, 8);
106
- const entryFile = typeof entry === "string" ? entry : entry["production"];
107
- this.entries[hash] = `/vite/@fs/${entryFile}`;
108
- for (const ws of this.ws.clients || []) {
109
- ws.send(JSON.stringify(createAddMsg("entries", this.entries[hash])));
110
- }
111
- return () => {
112
- for (const ws of this.ws.clients || []) {
113
- ws.send(
114
- JSON.stringify(createDeleteMsg("entries", this.entries[hash]))
115
- );
278
+ data: { key, value }
279
+ });
280
+ useContext("router", async (router) => {
281
+ const base = "/vite/";
282
+ const isDev = process.env.NODE_ENV === "development";
283
+ const rootDir = isDev ? path2.join(import.meta.dirname, "../client") : path2.join(import.meta.dirname, "../dist");
284
+ let viteStarting = false;
285
+ let viteStarted = false;
286
+ let devDeps = null;
287
+ const webServer = {
288
+ entries: {},
289
+ addEntry(entry) {
290
+ const hash = Date.now().toString(16) + Math.random().toString(16).slice(2, 8);
291
+ const entryFile = typeof entry === "string" ? entry : entry[process.env.NODE_ENV || "development"];
292
+ this.entries[hash] = `/vite/@fs/${entryFile}`;
293
+ if (this.ws) {
294
+ for (const ws of this.ws.clients || []) {
295
+ ws.send(JSON.stringify(createAddMsg("entries", this.entries[hash])));
296
+ }
116
297
  }
117
- delete this.entries[hash];
118
- };
119
- },
120
- ws: router.ws("/server")
121
- };
122
- const root = path.join(import.meta.dirname, "../dist");
123
- {
124
- router.use((ctx, next) => {
125
- if (ctx.request.originalUrl.startsWith("/api")) return next();
126
- if (!ctx.path.startsWith("/vite/@fs/")) return next();
127
- const filename = ctx.path.replace(`/vite/@fs/`, "");
128
- if (!fs.existsSync(filename)) return next();
129
- ctx.type = mime.getType(filename) || path.extname(filename);
130
- ctx.body = fs.createReadStream(filename);
131
- });
132
- }
133
- router.all("*all", async (ctx, next) => {
134
- ctx.request.originalUrl.replace(base, "");
135
- const name = ctx.path.slice(1);
136
- const sendFile = (filename2) => {
298
+ return () => {
299
+ if (this.ws) {
300
+ for (const ws of this.ws.clients || []) {
301
+ ws.send(JSON.stringify(createDeleteMsg("entries", this.entries[hash])));
302
+ }
303
+ }
304
+ delete this.entries[hash];
305
+ };
306
+ },
307
+ ws: router.ws("/server")
308
+ };
309
+ const ensureViteStarted = async () => {
310
+ if (viteStarted || viteStarting || !isDev) return;
311
+ viteStarting = true;
137
312
  try {
138
- const stat = fs.statSync(filename2);
139
- if (!stat.isFile()) {
140
- ctx.status = 404;
141
- return;
313
+ logger2.info("\u{1F504} \u68C0\u6D4B\u5230\u63A7\u5236\u53F0\u8BBF\u95EE\uFF0C\u6B63\u5728\u542F\u52A8 Vite \u5F00\u53D1\u670D\u52A1\u5668...");
314
+ devDeps = await loadDevDependencies();
315
+ if (devDeps) {
316
+ webServer.vite = await devDeps.createViteDevServer({
317
+ root: rootDir,
318
+ base,
319
+ enableTailwind: true
320
+ });
321
+ viteStarted = true;
322
+ logger2.info("\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557");
323
+ logger2.info("\u2551 Web \u63A7\u5236\u53F0\u5DF2\u542F\u52A8 (\u6309\u9700\u52A0\u8F7D) \u2551");
324
+ logger2.info("\u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563");
325
+ logger2.info("\u2551 \u5730\u5740: http://localhost:8086/ \u2551");
326
+ logger2.info("\u2551 \u6A21\u5F0F: \u5F00\u53D1\u6A21\u5F0F (Vite HMR) \u2551");
327
+ logger2.info("\u2551 \u5185\u5B58: \u5DF2\u52A0\u8F7D (~23MB) \u2551");
328
+ logger2.info("\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D");
142
329
  }
143
330
  } catch (error) {
144
- ctx.status = 404;
145
- return;
331
+ logger2.error("Vite \u542F\u52A8\u5931\u8D25:", error);
332
+ } finally {
333
+ viteStarting = false;
146
334
  }
147
- ctx.type = path.extname(filename2);
148
- ctx.type = mime.getType(filename2) || ctx.type;
149
- return ctx.body = fs.createReadStream(filename2);
150
335
  };
151
- if (Object.keys(webServer.entries).includes(name)) {
152
- return sendFile(path.resolve(process.cwd(), webServer.entries[name]));
336
+ if (isDev) {
337
+ await ensureViteStarted();
338
+ router.use(async (ctx, next) => {
339
+ if (ctx.request.originalUrl.startsWith("/api")) return next();
340
+ if (webServer.vite && devDeps) {
341
+ return devDeps.connect(webServer.vite.middlewares)(ctx, next);
342
+ }
343
+ return next();
344
+ });
345
+ } else {
346
+ router.use((ctx, next) => {
347
+ if (ctx.request.originalUrl.startsWith("/api")) return next();
348
+ if (!ctx.path.startsWith("/vite/@fs/")) return next();
349
+ const filename = ctx.path.replace(`/vite/@fs/`, "");
350
+ if (!fs2.existsSync(filename)) return next();
351
+ ctx.type = mime.getType(filename) || path2.extname(filename);
352
+ ctx.body = fs2.createReadStream(filename);
353
+ });
354
+ logger2.info("\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557");
355
+ logger2.info("\u2551 Web \u63A7\u5236\u53F0\u5DF2\u542F\u52A8 \u2551");
356
+ logger2.info("\u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563");
357
+ logger2.info("\u2551 \u5730\u5740: http://localhost:8086/ \u2551");
358
+ logger2.info("\u2551 \u6A21\u5F0F: \u751F\u4EA7\u6A21\u5F0F (\u9759\u6001\u6587\u4EF6) \u2551");
359
+ logger2.info("\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D");
153
360
  }
154
- const filename = path.resolve(root, name);
155
- if (filename.startsWith(root) || filename.includes("node_modules")) {
156
- try {
157
- if (fs.existsSync(filename)) {
158
- const fileState = fs.statSync(filename);
159
- if (fileState.isFile() && !fileState.isSocket() && !fileState.isFIFO()) {
160
- return sendFile(filename);
361
+ router.all("*all", async (ctx, next) => {
362
+ const url = ctx.request.originalUrl.replace(base, "");
363
+ const name = ctx.path.slice(1);
364
+ const sendFile = (filename2) => {
365
+ try {
366
+ const stat = fs2.statSync(filename2);
367
+ if (!stat.isFile()) {
368
+ ctx.status = 404;
369
+ return;
161
370
  }
371
+ } catch (error) {
372
+ ctx.status = 404;
373
+ return;
162
374
  }
163
- } catch (error) {
164
- console.warn(`\u6587\u4EF6\u8BBF\u95EE\u9519\u8BEF: ${filename}`, error.message);
375
+ ctx.type = path2.extname(filename2);
376
+ ctx.type = mime.getType(filename2) || ctx.type;
377
+ return ctx.body = fs2.createReadStream(filename2);
378
+ };
379
+ if (Object.keys(webServer.entries).includes(name)) {
380
+ return sendFile(path2.resolve(process.cwd(), webServer.entries[name]));
165
381
  }
166
- } else {
167
- return ctx.status = 403;
168
- }
169
- const indexFile = path.resolve(root, "index.html");
170
- return sendFile(indexFile);
171
- });
172
- const dataUpdateInterval = setInterval(() => {
173
- notifyDataUpdate(webServer);
174
- }, 5e3);
175
- setupWebSocket(webServer);
176
- process.on("exit", () => {
177
- clearInterval(dataUpdateInterval);
178
- });
179
- register({
180
- name: "web",
181
- description: "web\u670D\u52A1",
182
- async mounted() {
183
- return webServer;
184
- },
185
- async dispose(server) {
186
- await server.vite?.close();
187
- server.ws.close();
188
- }
382
+ const filename = path2.resolve(rootDir, name);
383
+ if (filename.startsWith(rootDir) || filename.includes("node_modules")) {
384
+ try {
385
+ if (fs2.existsSync(filename)) {
386
+ const fileState = fs2.statSync(filename);
387
+ if (fileState.isFile() && !fileState.isSocket() && !fileState.isFIFO()) {
388
+ return sendFile(filename);
389
+ }
390
+ }
391
+ } catch (error) {
392
+ logger2.warn(`\u6587\u4EF6\u8BBF\u95EE\u9519\u8BEF: ${filename}`, error.message);
393
+ }
394
+ } else {
395
+ return ctx.status = 403;
396
+ }
397
+ const indexFile = path2.resolve(rootDir, "index.html");
398
+ if (!isDev) return sendFile(indexFile);
399
+ const template = fs2.readFileSync(indexFile, "utf8");
400
+ ctx.type = "html";
401
+ ctx.body = await webServer.vite?.transformIndexHtml(url, template) || template;
402
+ });
403
+ webServer.ws;
404
+ const dataUpdateInterval = setInterval(() => {
405
+ notifyDataUpdate(webServer);
406
+ }, 5e3);
407
+ setupWebSocket(webServer);
408
+ onDispose(() => {
409
+ clearInterval(dataUpdateInterval);
410
+ });
411
+ provide({
412
+ name: "web",
413
+ description: "web\u670D\u52A1",
414
+ value: webServer,
415
+ dispose(server) {
416
+ return Promise.all([
417
+ server.vite?.close(),
418
+ new Promise((resolve2) => {
419
+ server.ws.close(() => resolve2());
420
+ })
421
+ ]);
422
+ }
423
+ });
189
424
  });
190
- });
425
+ }
@@ -1,4 +1,5 @@
1
1
  import { WebServer } from './index.js';
2
+ import '@zhin.js/http';
2
3
  import 'ws';
3
4
  import 'vite';
4
5