@zhin.js/http 1.0.5 → 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.d.ts CHANGED
@@ -1,8 +1,8 @@
1
- import { Server } from 'http';
2
- import Koa from 'koa';
3
- import { Router } from './router.js';
4
- export * from './router.js';
5
- declare module '@zhin.js/types' {
1
+ import { Server } from "http";
2
+ import Koa from "koa";
3
+ import { Router } from "./router.js";
4
+ export * from "./router.js";
5
+ declare module "@zhin.js/types" {
6
6
  interface GlobalContext {
7
7
  koa: Koa;
8
8
  router: Router;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAgB,MAAM,EAAE,MAAM,MAAM,CAAC;AAE5C,OAAO,GAAG,MAAM,KAAK,CAAC;AAGtB,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAIrC,cAAc,aAAa,CAAC;AAE5B,OAAO,QAAQ,gBAAgB,CAAA;IAC7B,UAAU,aAAa;QACrB,GAAG,EAAE,GAAG,CAAC;QACT,MAAM,EAAE,MAAM,CAAC;QACf,MAAM,EAAE,MAAM,CAAA;KACf;CACF"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../app/index.ts"],"names":[],"mappings":"AASA,OAAO,EAAgB,MAAM,EAAE,MAAM,MAAM,CAAC;AAE5C,OAAO,GAAG,MAAM,KAAK,CAAC;AAGtB,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAIrC,cAAc,aAAa,CAAC;AAE5B,OAAO,QAAQ,gBAAgB,CAAC;IAC9B,UAAU,aAAa;QACrB,GAAG,EAAE,GAAG,CAAC;QACT,MAAM,EAAE,MAAM,CAAC;QACf,MAAM,EAAE,MAAM,CAAC;KAChB;CACF"}
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,53 +144,53 @@ 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
183
  const definitions = Array.from(plugin.definitions.entries()).map(([name, definition]) => ({
176
184
  name,
177
- fields: Object.keys(definition)
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,
@@ -195,9 +203,9 @@ router.get('/api/plugins/:name', async (ctx) => {
195
203
  middlewareCount: middlewares.length,
196
204
  contextCount: contexts.length,
197
205
  cronCount: crons.length,
198
- definitionCount: definitions.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 };
@@ -246,13 +254,13 @@ router.get('/api/config', async (ctx) => {
246
254
  }
247
255
  });
248
256
  // 获取所有插件的 Schema API
249
- router.get('/api/schemas', async (ctx) => {
257
+ router.get(`${base}/schemas`, async (ctx) => {
250
258
  try {
251
259
  const schemas = {};
252
260
  // 获取 App 的 Schema
253
261
  const appSchema = app.schema.toJSON();
254
262
  if (appSchema) {
255
- schemas['app'] = appSchema;
263
+ schemas["app"] = appSchema;
256
264
  }
257
265
  // 获取所有插件的 Schema
258
266
  for (const plugin of app.dependencyList) {
@@ -261,7 +269,11 @@ router.get('/api/schemas', async (ctx) => {
261
269
  schemas[plugin.name] = schema;
262
270
  }
263
271
  }
264
- ctx.body = { success: true, data: schemas, total: Object.keys(schemas).length };
272
+ ctx.body = {
273
+ success: true,
274
+ data: schemas,
275
+ total: Object.keys(schemas).length,
276
+ };
265
277
  }
266
278
  catch (error) {
267
279
  ctx.status = 500;
@@ -269,14 +281,14 @@ router.get('/api/schemas', async (ctx) => {
269
281
  }
270
282
  });
271
283
  // 获取单个插件的 Schema API
272
- router.get('/api/schemas/:name', async (ctx) => {
284
+ router.get(`${base}/schemas/:name`, async (ctx) => {
273
285
  try {
274
286
  const { name } = ctx.params;
275
- if (name === 'app') {
287
+ if (name === "app") {
276
288
  const schema = app.schema?.toJSON();
277
289
  if (!schema) {
278
290
  ctx.status = 404;
279
- ctx.body = { success: false, error: 'App schema not found' };
291
+ ctx.body = { success: false, error: "App schema not found" };
280
292
  return;
281
293
  }
282
294
  ctx.body = { success: true, data: schema };
@@ -291,7 +303,10 @@ router.get('/api/schemas/:name', async (ctx) => {
291
303
  const schema = plugin.schema.toJSON();
292
304
  if (!schema) {
293
305
  ctx.status = 404;
294
- ctx.body = { success: false, error: `Schema for plugin ${name} not found` };
306
+ ctx.body = {
307
+ success: false,
308
+ error: `Schema for plugin ${name} not found`,
309
+ };
295
310
  return;
296
311
  }
297
312
  ctx.body = { success: true, data: schema };
@@ -302,10 +317,10 @@ router.get('/api/schemas/:name', async (ctx) => {
302
317
  }
303
318
  });
304
319
  // 获取插件配置 API
305
- router.get('/api/config/:name', async (ctx) => {
320
+ router.get(`${base}/config/:name`, async (ctx) => {
306
321
  try {
307
322
  const { name } = ctx.params;
308
- if (name === 'app') {
323
+ if (name === "app") {
309
324
  const config = app.getConfig();
310
325
  ctx.body = { success: true, data: config };
311
326
  return;
@@ -325,16 +340,16 @@ router.get('/api/config/:name', async (ctx) => {
325
340
  }
326
341
  });
327
342
  // 更新插件配置 API
328
- router.post('/api/config/:name', async (ctx) => {
343
+ router.post(`${base}/config/:name`, async (ctx) => {
329
344
  try {
330
345
  const { name } = ctx.params;
331
346
  const newConfig = ctx.request.body;
332
- if (name === 'app') {
347
+ if (name === "app") {
333
348
  app.config = newConfig;
334
349
  ctx.body = {
335
350
  success: true,
336
- message: 'App configuration updated successfully',
337
- data: app.getConfig()
351
+ message: "App configuration updated successfully",
352
+ data: app.getConfig(),
338
353
  };
339
354
  return;
340
355
  }
@@ -348,7 +363,7 @@ router.post('/api/config/:name', async (ctx) => {
348
363
  ctx.body = {
349
364
  success: true,
350
365
  message: `Plugin ${name} configuration updated successfully`,
351
- data: plugin.config
366
+ data: plugin.config,
352
367
  };
353
368
  }
354
369
  catch (error) {
@@ -357,7 +372,7 @@ router.post('/api/config/:name', async (ctx) => {
357
372
  }
358
373
  });
359
374
  // 消息发送 API
360
- router.post('/api/message/send', async (ctx) => {
375
+ router.post(`${base}/message/send`, async (ctx) => {
361
376
  try {
362
377
  const body = ctx.request.body;
363
378
  const { context, bot, id, type, content } = body;
@@ -365,7 +380,7 @@ router.post('/api/message/send', async (ctx) => {
365
380
  ctx.status = 400;
366
381
  ctx.body = {
367
382
  success: false,
368
- error: 'Missing required fields: context, bot, id, type, content'
383
+ error: "Missing required fields: context, bot, id, type, content",
369
384
  };
370
385
  return;
371
386
  }
@@ -373,8 +388,15 @@ router.post('/api/message/send', async (ctx) => {
373
388
  // console.log 已替换为注释
374
389
  ctx.body = {
375
390
  success: true,
376
- message: 'Message sent successfully',
377
- 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
+ },
378
400
  };
379
401
  }
380
402
  catch (error) {
@@ -383,43 +405,45 @@ router.post('/api/message/send', async (ctx) => {
383
405
  }
384
406
  });
385
407
  // 日志 API - 获取日志
386
- router.get('/api/logs', async (ctx) => {
408
+ router.get(`${base}/logs`, async (ctx) => {
387
409
  try {
388
410
  const database = useDatabase();
389
411
  if (!database) {
390
412
  ctx.status = 503;
391
- ctx.body = { success: false, error: 'Database not available' };
413
+ ctx.body = { success: false, error: "Database not available" };
392
414
  return;
393
415
  }
394
416
  // 获取查询参数
395
417
  const limit = parseInt(ctx.query.limit) || 100;
396
418
  const level = ctx.query.level;
397
- const LogModel = database.model('SystemLog');
419
+ const LogModel = database.model("SystemLog");
398
420
  if (!LogModel) {
399
421
  ctx.status = 500;
400
- ctx.body = { success: false, error: 'SystemLog model not found' };
422
+ ctx.body = { success: false, error: "SystemLog model not found" };
401
423
  return;
402
424
  }
403
425
  // 查询日志
404
426
  let selection = LogModel.select();
405
427
  // 按级别过滤
406
- if (level && level !== 'all') {
428
+ if (level && level !== "all") {
407
429
  selection = selection.where({ level });
408
430
  }
409
431
  // 按时间倒序,限制数量
410
- const logs = await selection.orderBy('timestamp', 'DESC').limit(limit);
432
+ const logs = await selection.orderBy("timestamp", "DESC").limit(limit);
411
433
  // 格式化返回数据
412
434
  const formattedLogs = logs.map((log) => ({
413
435
  level: log.level,
414
436
  name: log.name,
415
437
  message: log.message,
416
438
  source: log.source,
417
- timestamp: log.timestamp instanceof Date ? log.timestamp.toISOString() : log.timestamp
439
+ timestamp: log.timestamp instanceof Date
440
+ ? log.timestamp.toISOString()
441
+ : log.timestamp,
418
442
  }));
419
443
  ctx.body = {
420
444
  success: true,
421
445
  data: formattedLogs,
422
- total: formattedLogs.length
446
+ total: formattedLogs.length,
423
447
  };
424
448
  }
425
449
  catch (error) {
@@ -428,25 +452,25 @@ router.get('/api/logs', async (ctx) => {
428
452
  }
429
453
  });
430
454
  // 日志 API - 清空日志
431
- router.delete('/api/logs', async (ctx) => {
455
+ router.delete(`${base}/logs`, async (ctx) => {
432
456
  try {
433
457
  const database = useDatabase();
434
458
  if (!database) {
435
459
  ctx.status = 503;
436
- ctx.body = { success: false, error: 'Database not available' };
460
+ ctx.body = { success: false, error: "Database not available" };
437
461
  return;
438
462
  }
439
- const LogModel = database.model('SystemLog');
463
+ const LogModel = database.model("SystemLog");
440
464
  if (!LogModel) {
441
465
  ctx.status = 500;
442
- ctx.body = { success: false, error: 'SystemLog model not found' };
466
+ ctx.body = { success: false, error: "SystemLog model not found" };
443
467
  return;
444
468
  }
445
469
  // 删除所有日志
446
470
  await LogModel.delete({});
447
471
  ctx.body = {
448
472
  success: true,
449
- message: '日志已清空'
473
+ message: "日志已清空",
450
474
  };
451
475
  }
452
476
  catch (error) {
@@ -455,49 +479,46 @@ router.delete('/api/logs', async (ctx) => {
455
479
  }
456
480
  });
457
481
  // 日志 API - 获取日志统计
458
- router.get('/api/logs/stats', async (ctx) => {
482
+ router.get(`${base}/logs/stats`, async (ctx) => {
459
483
  try {
460
484
  const database = useDatabase();
461
485
  if (!database) {
462
486
  ctx.status = 503;
463
- ctx.body = { success: false, error: 'Database not available' };
487
+ ctx.body = { success: false, error: "Database not available" };
464
488
  return;
465
489
  }
466
- const LogModel = database.model('SystemLog');
490
+ const LogModel = database.model("SystemLog");
467
491
  if (!LogModel) {
468
492
  ctx.status = 500;
469
- ctx.body = { success: false, error: 'SystemLog model not found' };
493
+ ctx.body = { success: false, error: "SystemLog model not found" };
470
494
  return;
471
495
  }
472
496
  // 获取总日志数
473
497
  const total = await LogModel.select();
474
498
  const totalCount = total.length;
475
499
  // 获取各级别日志数
476
- const levels = ['info', 'warn', 'error'];
500
+ const levels = ["info", "warn", "error"];
477
501
  const levelCounts = {};
478
502
  for (const level of levels) {
479
- const count = await LogModel
480
- .select()
481
- .where({ level });
503
+ const count = await LogModel.select().where({ level });
482
504
  levelCounts[level] = count.length;
483
505
  }
484
506
  // 获取最旧日志时间
485
- const oldestLog = await LogModel
486
- .select('timestamp')
487
- .orderBy('timestamp', 'ASC')
507
+ const oldestLog = await LogModel.select("timestamp")
508
+ .orderBy("timestamp", "ASC")
488
509
  .limit(1);
489
510
  const oldestTimestamp = oldestLog.length > 0
490
- ? (oldestLog[0].timestamp instanceof Date
511
+ ? oldestLog[0].timestamp instanceof Date
491
512
  ? oldestLog[0].timestamp.toISOString()
492
- : oldestLog[0].timestamp)
513
+ : oldestLog[0].timestamp
493
514
  : null;
494
515
  ctx.body = {
495
516
  success: true,
496
517
  data: {
497
518
  total: totalCount,
498
519
  byLevel: levelCounts,
499
- oldestTimestamp
500
- }
520
+ oldestTimestamp,
521
+ },
501
522
  };
502
523
  }
503
524
  catch (error) {
@@ -506,38 +527,36 @@ router.get('/api/logs/stats', async (ctx) => {
506
527
  }
507
528
  });
508
529
  // 日志 API - 清理旧日志(手动触发)
509
- router.post('/api/logs/cleanup', async (ctx) => {
530
+ router.post(`${base}/logs/cleanup`, async (ctx) => {
510
531
  try {
511
532
  const database = useDatabase();
512
533
  if (!database) {
513
534
  ctx.status = 503;
514
- ctx.body = { success: false, error: 'Database not available' };
535
+ ctx.body = { success: false, error: "Database not available" };
515
536
  return;
516
537
  }
517
- const LogModel = database.model('SystemLog');
538
+ const LogModel = database.model("SystemLog");
518
539
  if (!LogModel) {
519
540
  ctx.status = 500;
520
- ctx.body = { success: false, error: 'SystemLog model not found' };
541
+ ctx.body = { success: false, error: "SystemLog model not found" };
521
542
  return;
522
543
  }
523
544
  const { days, maxRecords } = ctx.request.body || {};
524
545
  let deletedCount = 0;
525
546
  // 按天数清理
526
- if (days && typeof days === 'number' && days > 0) {
547
+ if (days && typeof days === "number" && days > 0) {
527
548
  const cutoffDate = new Date();
528
549
  cutoffDate.setDate(cutoffDate.getDate() - days);
529
- const deleted = await LogModel
530
- .delete({ timestamp: { $lt: cutoffDate } });
550
+ const deleted = await LogModel.delete({ timestamp: { $lt: cutoffDate } });
531
551
  deletedCount += deleted || 0;
532
552
  }
533
553
  // 按数量清理
534
- if (maxRecords && typeof maxRecords === 'number' && maxRecords > 0) {
554
+ if (maxRecords && typeof maxRecords === "number" && maxRecords > 0) {
535
555
  const totalCount = await LogModel.select();
536
556
  if (totalCount.length > maxRecords) {
537
557
  const excessCount = totalCount - maxRecords;
538
- const oldestLogs = await LogModel
539
- .select('id', 'timestamp')
540
- .orderBy('timestamp', 'ASC')
558
+ const oldestLogs = await LogModel.select("id", "timestamp")
559
+ .orderBy("timestamp", "ASC")
541
560
  .limit(excessCount);
542
561
  const idsToDelete = oldestLogs.map((log) => log.id);
543
562
  if (idsToDelete.length > 0) {
@@ -551,7 +570,7 @@ router.post('/api/logs/cleanup', async (ctx) => {
551
570
  ctx.body = {
552
571
  success: true,
553
572
  message: `已清理 ${deletedCount} 条日志`,
554
- deletedCount
573
+ deletedCount,
555
574
  };
556
575
  }
557
576
  catch (error) {
@@ -563,38 +582,40 @@ router.post('/api/logs/cleanup', async (ctx) => {
563
582
  // 上下文注册
564
583
  // ============================================================================
565
584
  register({
566
- name: 'server',
585
+ name: "server",
567
586
  description: "http server",
568
587
  mounted(p) {
569
588
  return new Promise((resolve) => {
570
589
  server.listen({
571
- host: '0.0.0.0',
572
- port: Number((process.env.port ||= '8086')),
590
+ host: "0.0.0.0",
591
+ port: port,
573
592
  }, () => {
574
593
  const address = server.address();
575
594
  if (!address)
576
595
  return;
577
- const visitAddress = typeof address === 'string' ? address : `${address.address}:${address.port}`;
596
+ const visitAddress = typeof address === "string"
597
+ ? address
598
+ : `${address.address}:${address.port}`;
578
599
  p.logger.info(`server is running at http://${visitAddress}`);
579
- p.logger.info('your username is:', username);
580
- p.logger.info('your password is:', password);
600
+ p.logger.info("your username is:", username);
601
+ p.logger.info("your password is:", password);
581
602
  resolve(server);
582
603
  });
583
604
  });
584
605
  },
585
606
  dispose(s) {
586
607
  s.close();
587
- }
608
+ },
588
609
  });
589
610
  register({
590
611
  name: "koa",
591
612
  description: "koa instance",
592
- value: koa
613
+ value: koa,
593
614
  });
594
615
  register({
595
- name: 'router',
616
+ name: "router",
596
617
  description: "koa router",
597
- value: router
618
+ value: router,
598
619
  });
599
620
  koa.use(KoaBodyParser()).use(router.routes()).use(router.allowedMethods());
600
621
  //# sourceMappingURL=index.js.map