@zhin.js/http 1.0.4 → 1.0.6

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/index.js CHANGED
@@ -1,35 +1,43 @@
1
- import { register, useApp, useDatabase } from '@zhin.js/core';
2
- import { createServer } from 'http';
3
- import os from 'node:os';
4
- import Koa from 'koa';
5
- import auth from 'koa-basic-auth';
6
- import KoaBodyParser from 'koa-bodyparser';
7
- import { Router } from './router.js';
8
- import * as process from 'process';
9
- export * from './router.js';
1
+ import { register, defineSchema, Schema, usePlugin, useApp, useDatabase, } from "@zhin.js/core";
2
+ import { createServer } from "http";
3
+ import os from "node:os";
4
+ import Koa from "koa";
5
+ import auth from "koa-basic-auth";
6
+ import KoaBodyParser from "koa-bodyparser";
7
+ import { Router } from "./router.js";
8
+ import * as process from "process";
9
+ export * from "./router.js";
10
+ const plugin = usePlugin();
11
+ const schema = defineSchema(Schema.object({
12
+ port: Schema.number("port").default(8086).description("HTTP 服务端口"),
13
+ username: Schema.string("username").description("HTTP 基本认证用户名, 默认为当前系统用户名"),
14
+ password: Schema.string("password").description("HTTP 基本认证密码, 默认为随机生成的6位字符串"),
15
+ base: Schema.string("base")
16
+ .default("/api")
17
+ .description("HTTP 路由前缀, 默认为 /api"),
18
+ }));
10
19
  const koa = new Koa();
11
20
  const server = createServer(koa.callback());
12
- const router = new Router(server, { prefix: process.env.routerPrefix || '' });
21
+ const router = new Router(server, { prefix: process.env.routerPrefix || "" });
13
22
  // 获取当前计算机登录用户名
14
23
  const getCurrentUsername = () => {
15
24
  try {
16
25
  return os.userInfo().username;
17
26
  }
18
27
  catch {
19
- return 'admin'; // 如果获取失败,使用默认用户名
28
+ return "admin"; // 如果获取失败,使用默认用户名
20
29
  }
21
30
  };
22
31
  // 生成6位随机密码
23
32
  const generateRandomPassword = () => {
24
- const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
25
- let result = '';
33
+ const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
34
+ let result = "";
26
35
  for (let i = 0; i < 6; i++) {
27
36
  result += chars.charAt(Math.floor(Math.random() * chars.length));
28
37
  }
29
38
  return result;
30
39
  };
31
- const username = process.env.username || getCurrentUsername();
32
- const password = process.env.password || generateRandomPassword();
40
+ const { port = 8086, username = getCurrentUsername(), password = generateRandomPassword(), base = "/api", } = schema(plugin.config, "http");
33
41
  const app = useApp();
34
42
  koa.use(auth({
35
43
  name: username,
@@ -39,7 +47,7 @@ koa.use(auth({
39
47
  // API 路由
40
48
  // ============================================================================
41
49
  // 系统状态 API
42
- router.get('/api/system/status', async (ctx) => {
50
+ router.get(`${base}/system/status`, async (ctx) => {
43
51
  try {
44
52
  ctx.body = {
45
53
  success: true,
@@ -50,8 +58,8 @@ router.get('/api/system/status', async (ctx) => {
50
58
  platform: process.platform,
51
59
  nodeVersion: process.version,
52
60
  pid: process.pid,
53
- timestamp: new Date().toISOString()
54
- }
61
+ timestamp: new Date().toISOString(),
62
+ },
55
63
  };
56
64
  }
57
65
  catch (error) {
@@ -60,25 +68,25 @@ router.get('/api/system/status', async (ctx) => {
60
68
  }
61
69
  });
62
70
  // 健康检查 API
63
- router.get('/api/health', async (ctx) => {
71
+ router.get(`${base}/health`, async (ctx) => {
64
72
  ctx.body = {
65
73
  success: true,
66
- status: 'ok',
67
- timestamp: new Date().toISOString()
74
+ status: "ok",
75
+ timestamp: new Date().toISOString(),
68
76
  };
69
77
  });
70
78
  // 统计信息 API
71
- router.get('/api/stats', async (ctx) => {
79
+ router.get(`${base}/stats`, async (ctx) => {
72
80
  try {
73
81
  // 统计插件数量
74
82
  const pluginCount = app.dependencyList.length;
75
- const activePluginCount = app.dependencyList.filter(dep => dep.mounted).length;
83
+ const activePluginCount = app.dependencyList.filter((dep) => dep.mounted).length;
76
84
  // 统计机器人数量
77
85
  let botCount = 0;
78
86
  let onlineBotCount = 0;
79
87
  for (const context of app.contextList) {
80
88
  const adapter = app.getContext(context.name);
81
- if (adapter && typeof adapter === 'object' && 'bots' in adapter) {
89
+ if (adapter && typeof adapter === "object" && "bots" in adapter) {
82
90
  const adapterBots = adapter.bots;
83
91
  if (adapterBots && adapterBots instanceof Map) {
84
92
  botCount += adapterBots.size;
@@ -105,7 +113,7 @@ router.get('/api/stats', async (ctx) => {
105
113
  components: componentCount,
106
114
  uptime: process.uptime(),
107
115
  memory: process.memoryUsage().heapUsed / 1024 / 1024, // MB
108
- }
116
+ },
109
117
  };
110
118
  }
111
119
  catch (error) {
@@ -114,18 +122,18 @@ router.get('/api/stats', async (ctx) => {
114
122
  }
115
123
  });
116
124
  // 插件管理 API
117
- router.get('/api/plugins', async (ctx) => {
125
+ router.get(`${base}/plugins`, async (ctx) => {
118
126
  try {
119
127
  // 获取详细的插件数据
120
- const plugins = app.dependencyList.map(dep => {
128
+ const plugins = app.dependencyList.map((dep) => {
121
129
  return {
122
130
  name: dep.name,
123
- status: dep.mounted ? 'active' : 'inactive',
131
+ status: dep.mounted ? "active" : "inactive",
124
132
  commandCount: dep.commands.length,
125
133
  componentCount: dep.components.size,
126
134
  middlewareCount: dep.middlewares.length,
127
135
  contextCount: dep.contexts.size,
128
- description: dep.description || '无描述',
136
+ description: dep.description || "无描述",
129
137
  };
130
138
  });
131
139
  ctx.body = { success: true, data: plugins, total: plugins.length };
@@ -136,68 +144,68 @@ router.get('/api/plugins', async (ctx) => {
136
144
  }
137
145
  });
138
146
  // 插件详情 API
139
- router.get('/api/plugins/:name', async (ctx) => {
147
+ router.get("/api/plugins/:name", async (ctx) => {
140
148
  try {
141
149
  const pluginName = ctx.params.name;
142
- const plugin = app.dependencyList.find(dep => dep.name === pluginName);
150
+ const plugin = app.dependencyList.find((dep) => dep.name === pluginName);
143
151
  if (!plugin) {
144
152
  ctx.status = 404;
145
- ctx.body = { success: false, error: '插件不存在' };
153
+ ctx.body = { success: false, error: "插件不存在" };
146
154
  return;
147
155
  }
148
156
  // 获取命令详情
149
- const commands = plugin.commands.map(cmd => ({
150
- name: cmd.pattern
157
+ const commands = plugin.commands.map((cmd) => ({
158
+ name: cmd.pattern,
151
159
  }));
152
160
  // 获取组件详情
153
161
  const components = Array.from(plugin.components.entries()).map(([name, comp]) => ({
154
162
  name,
155
163
  props: comp.props || {},
156
- type: typeof comp
164
+ type: typeof comp,
157
165
  }));
158
166
  // 获取中间件详情
159
167
  const middlewares = plugin.middlewares.map((_, index) => ({
160
168
  id: `middleware-${index}`,
161
- type: 'function'
169
+ type: "function",
162
170
  }));
163
171
  // 获取上下文详情
164
172
  const contexts = Array.from(plugin.contexts.entries()).map(([name, ctx]) => ({
165
173
  name,
166
- description: ctx.description || '无描述'
174
+ description: ctx.description || "无描述",
167
175
  }));
168
176
  // 获取定时任务详情
169
177
  const crons = plugin.crons.map((cron, index) => ({
170
178
  id: `cron-${index}`,
171
- pattern: cron.pattern || 'unknown',
172
- running: cron.running || false
179
+ pattern: cron.pattern || "unknown",
180
+ running: cron.running || false,
173
181
  }));
174
182
  // 获取数据模型详情
175
- const schemas = Array.from(plugin.schemas.entries()).map(([name, schema]) => ({
183
+ const definitions = Array.from(plugin.definitions.entries()).map(([name, definition]) => ({
176
184
  name,
177
- fields: Object.keys(schema.fields || {})
185
+ fields: Object.keys(definition),
178
186
  }));
179
187
  ctx.body = {
180
188
  success: true,
181
189
  data: {
182
190
  name: plugin.name,
183
191
  filename: plugin.filename,
184
- status: plugin.mounted ? 'active' : 'inactive',
185
- description: plugin.description || '无描述',
192
+ status: plugin.mounted ? "active" : "inactive",
193
+ description: plugin.description || "无描述",
186
194
  commands,
187
195
  components,
188
196
  middlewares,
189
197
  contexts,
190
198
  crons,
191
- schemas,
199
+ definitions,
192
200
  statistics: {
193
201
  commandCount: commands.length,
194
202
  componentCount: components.length,
195
203
  middlewareCount: middlewares.length,
196
204
  contextCount: contexts.length,
197
205
  cronCount: crons.length,
198
- schemaCount: schemas.length
199
- }
200
- }
206
+ definitionCount: definitions.length,
207
+ },
208
+ },
201
209
  };
202
210
  }
203
211
  catch (error) {
@@ -206,13 +214,13 @@ router.get('/api/plugins/:name', async (ctx) => {
206
214
  }
207
215
  });
208
216
  // 适配器和机器人状态 API
209
- router.get('/api/bots', async (ctx) => {
217
+ router.get(`${base}/bots`, async (ctx) => {
210
218
  try {
211
219
  const bots = [];
212
220
  // 遍历所有上下文,查找适配器
213
221
  for (const context of app.contextList) {
214
222
  const adapter = app.getContext(context.name);
215
- if (adapter && typeof adapter === 'object' && 'bots' in adapter) {
223
+ if (adapter && typeof adapter === "object" && "bots" in adapter) {
216
224
  const adapterBots = adapter.bots;
217
225
  if (adapterBots && adapterBots instanceof Map) {
218
226
  for (const [botName, bot] of adapterBots.entries()) {
@@ -220,7 +228,7 @@ router.get('/api/bots', async (ctx) => {
220
228
  name: botName,
221
229
  adapter: context.name,
222
230
  connected: bot.$connected || false,
223
- status: bot.$connected ? 'online' : 'offline'
231
+ status: bot.$connected ? "online" : "offline",
224
232
  // 移除 config 字段以保护隐私
225
233
  });
226
234
  }
@@ -235,7 +243,7 @@ router.get('/api/bots', async (ctx) => {
235
243
  }
236
244
  });
237
245
  // 框架配置信息 API
238
- router.get('/api/config', async (ctx) => {
246
+ router.get(`${base}/config`, async (ctx) => {
239
247
  try {
240
248
  const config = app.getConfig();
241
249
  ctx.body = { success: true, data: config };
@@ -245,8 +253,126 @@ router.get('/api/config', async (ctx) => {
245
253
  ctx.body = { success: false, error: error.message };
246
254
  }
247
255
  });
256
+ // 获取所有插件的 Schema API
257
+ router.get(`${base}/schemas`, async (ctx) => {
258
+ try {
259
+ const schemas = {};
260
+ // 获取 App 的 Schema
261
+ const appSchema = app.schema.toJSON();
262
+ if (appSchema) {
263
+ schemas["app"] = appSchema;
264
+ }
265
+ // 获取所有插件的 Schema
266
+ for (const plugin of app.dependencyList) {
267
+ const schema = plugin.schema.toJSON();
268
+ if (schema) {
269
+ schemas[plugin.name] = schema;
270
+ }
271
+ }
272
+ ctx.body = {
273
+ success: true,
274
+ data: schemas,
275
+ total: Object.keys(schemas).length,
276
+ };
277
+ }
278
+ catch (error) {
279
+ ctx.status = 500;
280
+ ctx.body = { success: false, error: error.message };
281
+ }
282
+ });
283
+ // 获取单个插件的 Schema API
284
+ router.get(`${base}/schemas/:name`, async (ctx) => {
285
+ try {
286
+ const { name } = ctx.params;
287
+ if (name === "app") {
288
+ const schema = app.schema?.toJSON();
289
+ if (!schema) {
290
+ ctx.status = 404;
291
+ ctx.body = { success: false, error: "App schema not found" };
292
+ return;
293
+ }
294
+ ctx.body = { success: true, data: schema };
295
+ return;
296
+ }
297
+ const plugin = app.findPluginByName(name);
298
+ if (!plugin) {
299
+ ctx.status = 404;
300
+ ctx.body = { success: false, error: `Plugin ${name} not found` };
301
+ return;
302
+ }
303
+ const schema = plugin.schema.toJSON();
304
+ if (!schema) {
305
+ ctx.status = 404;
306
+ ctx.body = {
307
+ success: false,
308
+ error: `Schema for plugin ${name} not found`,
309
+ };
310
+ return;
311
+ }
312
+ ctx.body = { success: true, data: schema };
313
+ }
314
+ catch (error) {
315
+ ctx.status = 500;
316
+ ctx.body = { success: false, error: error.message };
317
+ }
318
+ });
319
+ // 获取插件配置 API
320
+ router.get(`${base}/config/:name`, async (ctx) => {
321
+ try {
322
+ const { name } = ctx.params;
323
+ if (name === "app") {
324
+ const config = app.getConfig();
325
+ ctx.body = { success: true, data: config };
326
+ return;
327
+ }
328
+ const plugin = app.findPluginByName(name);
329
+ if (!plugin) {
330
+ ctx.status = 404;
331
+ ctx.body = { success: false, error: `Plugin ${name} not found` };
332
+ return;
333
+ }
334
+ const config = plugin.config;
335
+ ctx.body = { success: true, data: config };
336
+ }
337
+ catch (error) {
338
+ ctx.status = 500;
339
+ ctx.body = { success: false, error: error.message };
340
+ }
341
+ });
342
+ // 更新插件配置 API
343
+ router.post(`${base}/config/:name`, async (ctx) => {
344
+ try {
345
+ const { name } = ctx.params;
346
+ const newConfig = ctx.request.body;
347
+ if (name === "app") {
348
+ app.config = newConfig;
349
+ ctx.body = {
350
+ success: true,
351
+ message: "App configuration updated successfully",
352
+ data: app.getConfig(),
353
+ };
354
+ return;
355
+ }
356
+ const plugin = app.findPluginByName(name);
357
+ if (!plugin) {
358
+ ctx.status = 404;
359
+ ctx.body = { success: false, error: `Plugin ${name} not found` };
360
+ return;
361
+ }
362
+ plugin.config = newConfig;
363
+ ctx.body = {
364
+ success: true,
365
+ message: `Plugin ${name} configuration updated successfully`,
366
+ data: plugin.config,
367
+ };
368
+ }
369
+ catch (error) {
370
+ ctx.status = 500;
371
+ ctx.body = { success: false, error: error.message };
372
+ }
373
+ });
248
374
  // 消息发送 API
249
- router.post('/api/message/send', async (ctx) => {
375
+ router.post(`${base}/message/send`, async (ctx) => {
250
376
  try {
251
377
  const body = ctx.request.body;
252
378
  const { context, bot, id, type, content } = body;
@@ -254,7 +380,7 @@ router.post('/api/message/send', async (ctx) => {
254
380
  ctx.status = 400;
255
381
  ctx.body = {
256
382
  success: false,
257
- error: 'Missing required fields: context, bot, id, type, content'
383
+ error: "Missing required fields: context, bot, id, type, content",
258
384
  };
259
385
  return;
260
386
  }
@@ -262,8 +388,15 @@ router.post('/api/message/send', async (ctx) => {
262
388
  // console.log 已替换为注释
263
389
  ctx.body = {
264
390
  success: true,
265
- message: 'Message sent successfully',
266
- data: { context, bot, id, type, content, timestamp: new Date().toISOString() }
391
+ message: "Message sent successfully",
392
+ data: {
393
+ context,
394
+ bot,
395
+ id,
396
+ type,
397
+ content,
398
+ timestamp: new Date().toISOString(),
399
+ },
267
400
  };
268
401
  }
269
402
  catch (error) {
@@ -272,43 +405,45 @@ router.post('/api/message/send', async (ctx) => {
272
405
  }
273
406
  });
274
407
  // 日志 API - 获取日志
275
- router.get('/api/logs', async (ctx) => {
408
+ router.get(`${base}/logs`, async (ctx) => {
276
409
  try {
277
410
  const database = useDatabase();
278
411
  if (!database) {
279
412
  ctx.status = 503;
280
- ctx.body = { success: false, error: 'Database not available' };
413
+ ctx.body = { success: false, error: "Database not available" };
281
414
  return;
282
415
  }
283
416
  // 获取查询参数
284
417
  const limit = parseInt(ctx.query.limit) || 100;
285
418
  const level = ctx.query.level;
286
- const LogModel = database.model('SystemLog');
419
+ const LogModel = database.model("SystemLog");
287
420
  if (!LogModel) {
288
421
  ctx.status = 500;
289
- ctx.body = { success: false, error: 'SystemLog model not found' };
422
+ ctx.body = { success: false, error: "SystemLog model not found" };
290
423
  return;
291
424
  }
292
425
  // 查询日志
293
426
  let selection = LogModel.select();
294
427
  // 按级别过滤
295
- if (level && level !== 'all') {
428
+ if (level && level !== "all") {
296
429
  selection = selection.where({ level });
297
430
  }
298
431
  // 按时间倒序,限制数量
299
- const logs = await selection.orderBy('timestamp', 'DESC').limit(limit);
432
+ const logs = await selection.orderBy("timestamp", "DESC").limit(limit);
300
433
  // 格式化返回数据
301
434
  const formattedLogs = logs.map((log) => ({
302
435
  level: log.level,
303
436
  name: log.name,
304
437
  message: log.message,
305
438
  source: log.source,
306
- timestamp: log.timestamp instanceof Date ? log.timestamp.toISOString() : log.timestamp
439
+ timestamp: log.timestamp instanceof Date
440
+ ? log.timestamp.toISOString()
441
+ : log.timestamp,
307
442
  }));
308
443
  ctx.body = {
309
444
  success: true,
310
445
  data: formattedLogs,
311
- total: formattedLogs.length
446
+ total: formattedLogs.length,
312
447
  };
313
448
  }
314
449
  catch (error) {
@@ -317,25 +452,25 @@ router.get('/api/logs', async (ctx) => {
317
452
  }
318
453
  });
319
454
  // 日志 API - 清空日志
320
- router.delete('/api/logs', async (ctx) => {
455
+ router.delete(`${base}/logs`, async (ctx) => {
321
456
  try {
322
457
  const database = useDatabase();
323
458
  if (!database) {
324
459
  ctx.status = 503;
325
- ctx.body = { success: false, error: 'Database not available' };
460
+ ctx.body = { success: false, error: "Database not available" };
326
461
  return;
327
462
  }
328
- const LogModel = database.model('SystemLog');
463
+ const LogModel = database.model("SystemLog");
329
464
  if (!LogModel) {
330
465
  ctx.status = 500;
331
- ctx.body = { success: false, error: 'SystemLog model not found' };
466
+ ctx.body = { success: false, error: "SystemLog model not found" };
332
467
  return;
333
468
  }
334
469
  // 删除所有日志
335
470
  await LogModel.delete({});
336
471
  ctx.body = {
337
472
  success: true,
338
- message: '日志已清空'
473
+ message: "日志已清空",
339
474
  };
340
475
  }
341
476
  catch (error) {
@@ -344,49 +479,46 @@ router.delete('/api/logs', async (ctx) => {
344
479
  }
345
480
  });
346
481
  // 日志 API - 获取日志统计
347
- router.get('/api/logs/stats', async (ctx) => {
482
+ router.get(`${base}/logs/stats`, async (ctx) => {
348
483
  try {
349
484
  const database = useDatabase();
350
485
  if (!database) {
351
486
  ctx.status = 503;
352
- ctx.body = { success: false, error: 'Database not available' };
487
+ ctx.body = { success: false, error: "Database not available" };
353
488
  return;
354
489
  }
355
- const LogModel = database.model('SystemLog');
490
+ const LogModel = database.model("SystemLog");
356
491
  if (!LogModel) {
357
492
  ctx.status = 500;
358
- ctx.body = { success: false, error: 'SystemLog model not found' };
493
+ ctx.body = { success: false, error: "SystemLog model not found" };
359
494
  return;
360
495
  }
361
496
  // 获取总日志数
362
497
  const total = await LogModel.select();
363
498
  const totalCount = total.length;
364
499
  // 获取各级别日志数
365
- const levels = ['info', 'warn', 'error'];
500
+ const levels = ["info", "warn", "error"];
366
501
  const levelCounts = {};
367
502
  for (const level of levels) {
368
- const count = await LogModel
369
- .select()
370
- .where({ level });
503
+ const count = await LogModel.select().where({ level });
371
504
  levelCounts[level] = count.length;
372
505
  }
373
506
  // 获取最旧日志时间
374
- const oldestLog = await LogModel
375
- .select('timestamp')
376
- .orderBy('timestamp', 'ASC')
507
+ const oldestLog = await LogModel.select("timestamp")
508
+ .orderBy("timestamp", "ASC")
377
509
  .limit(1);
378
510
  const oldestTimestamp = oldestLog.length > 0
379
- ? (oldestLog[0].timestamp instanceof Date
511
+ ? oldestLog[0].timestamp instanceof Date
380
512
  ? oldestLog[0].timestamp.toISOString()
381
- : oldestLog[0].timestamp)
513
+ : oldestLog[0].timestamp
382
514
  : null;
383
515
  ctx.body = {
384
516
  success: true,
385
517
  data: {
386
518
  total: totalCount,
387
519
  byLevel: levelCounts,
388
- oldestTimestamp
389
- }
520
+ oldestTimestamp,
521
+ },
390
522
  };
391
523
  }
392
524
  catch (error) {
@@ -395,38 +527,36 @@ router.get('/api/logs/stats', async (ctx) => {
395
527
  }
396
528
  });
397
529
  // 日志 API - 清理旧日志(手动触发)
398
- router.post('/api/logs/cleanup', async (ctx) => {
530
+ router.post(`${base}/logs/cleanup`, async (ctx) => {
399
531
  try {
400
532
  const database = useDatabase();
401
533
  if (!database) {
402
534
  ctx.status = 503;
403
- ctx.body = { success: false, error: 'Database not available' };
535
+ ctx.body = { success: false, error: "Database not available" };
404
536
  return;
405
537
  }
406
- const LogModel = database.model('SystemLog');
538
+ const LogModel = database.model("SystemLog");
407
539
  if (!LogModel) {
408
540
  ctx.status = 500;
409
- ctx.body = { success: false, error: 'SystemLog model not found' };
541
+ ctx.body = { success: false, error: "SystemLog model not found" };
410
542
  return;
411
543
  }
412
544
  const { days, maxRecords } = ctx.request.body || {};
413
545
  let deletedCount = 0;
414
546
  // 按天数清理
415
- if (days && typeof days === 'number' && days > 0) {
547
+ if (days && typeof days === "number" && days > 0) {
416
548
  const cutoffDate = new Date();
417
549
  cutoffDate.setDate(cutoffDate.getDate() - days);
418
- const deleted = await LogModel
419
- .delete({ timestamp: { $lt: cutoffDate } });
550
+ const deleted = await LogModel.delete({ timestamp: { $lt: cutoffDate } });
420
551
  deletedCount += deleted || 0;
421
552
  }
422
553
  // 按数量清理
423
- if (maxRecords && typeof maxRecords === 'number' && maxRecords > 0) {
554
+ if (maxRecords && typeof maxRecords === "number" && maxRecords > 0) {
424
555
  const totalCount = await LogModel.select();
425
556
  if (totalCount.length > maxRecords) {
426
557
  const excessCount = totalCount - maxRecords;
427
- const oldestLogs = await LogModel
428
- .select('id', 'timestamp')
429
- .orderBy('timestamp', 'ASC')
558
+ const oldestLogs = await LogModel.select("id", "timestamp")
559
+ .orderBy("timestamp", "ASC")
430
560
  .limit(excessCount);
431
561
  const idsToDelete = oldestLogs.map((log) => log.id);
432
562
  if (idsToDelete.length > 0) {
@@ -440,7 +570,7 @@ router.post('/api/logs/cleanup', async (ctx) => {
440
570
  ctx.body = {
441
571
  success: true,
442
572
  message: `已清理 ${deletedCount} 条日志`,
443
- deletedCount
573
+ deletedCount,
444
574
  };
445
575
  }
446
576
  catch (error) {
@@ -452,38 +582,40 @@ router.post('/api/logs/cleanup', async (ctx) => {
452
582
  // 上下文注册
453
583
  // ============================================================================
454
584
  register({
455
- name: 'server',
585
+ name: "server",
456
586
  description: "http server",
457
587
  mounted(p) {
458
588
  return new Promise((resolve) => {
459
589
  server.listen({
460
- host: '0.0.0.0',
461
- port: Number((process.env.port ||= '8086')),
590
+ host: "0.0.0.0",
591
+ port: port,
462
592
  }, () => {
463
593
  const address = server.address();
464
594
  if (!address)
465
595
  return;
466
- const visitAddress = typeof address === 'string' ? address : `${address.address}:${address.port}`;
596
+ const visitAddress = typeof address === "string"
597
+ ? address
598
+ : `${address.address}:${address.port}`;
467
599
  p.logger.info(`server is running at http://${visitAddress}`);
468
- p.logger.info('your username is:', username);
469
- p.logger.info('your password is:', password);
600
+ p.logger.info("your username is:", username);
601
+ p.logger.info("your password is:", password);
470
602
  resolve(server);
471
603
  });
472
604
  });
473
605
  },
474
606
  dispose(s) {
475
607
  s.close();
476
- }
608
+ },
477
609
  });
478
610
  register({
479
611
  name: "koa",
480
612
  description: "koa instance",
481
- value: koa
613
+ value: koa,
482
614
  });
483
615
  register({
484
- name: 'router',
616
+ name: "router",
485
617
  description: "koa router",
486
- value: router
618
+ value: router,
487
619
  });
488
620
  koa.use(KoaBodyParser()).use(router.routes()).use(router.allowedMethods());
489
621
  //# sourceMappingURL=index.js.map