@faapi/faapi 6.8.0 → 6.9.1

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.
@@ -306,11 +306,25 @@ interface CreateLoggerOptions {
306
306
  /**
307
307
  * `config.log` 的对象形状(config 侧另接受 boolean:false 全静默、true 默认)
308
308
  *
309
- * level 解析顺序:显式值 > `LOG_LEVEL` 环境变量 > `'info'`(非法值启动报错)。
309
+ * level 解析顺序:显式值 > `LOG_LEVEL` 环境变量 > 模式默认(`dir` 文件模式不过滤,
310
+ * 其余模式 `'info'`;非法值启动报错)。`sink` 与 `dir` 互斥,同时配置启动报错。
310
311
  */
311
312
  interface LogConfig {
313
+ /** 实例级级别(覆盖全局 level) */
312
314
  level?: LogLevel;
315
+ /** 自定义输出管道(整体接管,与 `dir` 互斥) */
313
316
  sink?: LogSink;
317
+ /**
318
+ * 文件日志目录(egg 风格):配置即启用内置文件管道——默认 `app.log` 全量 +
319
+ * `error.log` 仅 error(dup 语义);请求日志自动并入(`accessLog` 缺省 true)
320
+ */
321
+ dir?: string;
322
+ /** true 时按级别四文件 `debug.log`/`info.log`/`warn.log`/`error.log`(各只含对应级别) */
323
+ splitByLevel?: boolean;
324
+ /** 文件模式下是否保留 console 双写(默认 true;false 纯文件) */
325
+ stdout?: boolean;
326
+ /** 请求日志是否并入统一管道;缺省 = `dir` 配置时 true(见 middleware/logger.md) */
327
+ accessLog?: boolean;
314
328
  }
315
329
 
316
330
  /**
@@ -347,10 +361,11 @@ interface TaskWorkerOptions {
347
361
  * 任务日志配置(纯数据,postMessage 传入,worker 内联重建日志器注入 taskCtx.log;
348
362
  * 缺省时 taskCtx.log 为 undefined):scope/fields 与进程内路径一致(`task:<name>`
349
363
  * + jobId/task/attempt),level 为宿主侧生效的全局级别(worker 侧预过滤,
350
- * 宿主 writeLogEntry 再次过滤)
364
+ * 宿主 writeLogEntry 再次过滤;undefined = 宿主未配置阈值——文件管道默认全量,
365
+ * worker 侧同样不过滤)
351
366
  */
352
367
  log?: {
353
- level: LogLevel;
368
+ level?: LogLevel;
354
369
  scope?: string;
355
370
  fields?: Record<string, unknown>;
356
371
  };
@@ -1133,7 +1148,8 @@ interface LoggerOptions {
1133
1148
  * 错误用 try/catch 捕获,记录后重新抛出(让上层处理)。
1134
1149
  * 成功时从 next() 返回的 Response 读取状态码。
1135
1150
  *
1136
- * log 函数每次请求时读取(options.log ?? console.log),运行时替换 console.log 会生效。
1151
+ * log 函数每次请求时读取(options.log ?? defaultLog),运行时替换 console.log 或
1152
+ * 切换全局日志配置均会生效。
1137
1153
  */
1138
1154
  declare function logger(options?: LoggerOptions): FaapiMiddleware;
1139
1155
 
package/dist/testing.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { F as FaapiContext, b as FaapiMiddleware, I as InjectorMap, R as RouteManifest, W as WsRouteManifest, C as CorsOptions, H as HelmetOptions, L as LoggerOptions } from './routeTypes-J5pPbjwR.js';
1
+ import { F as FaapiContext, b as FaapiMiddleware, I as InjectorMap, R as RouteManifest, W as WsRouteManifest, C as CorsOptions, H as HelmetOptions, L as LoggerOptions } from './routeTypes-CuGMDCGB.js';
2
2
  import { Server } from 'node:http';
3
3
  import { WebSocket } from 'ws';
4
4
 
package/dist/testing.js CHANGED
@@ -245,16 +245,7 @@ function formatErrorResponse(error, config) {
245
245
  return jsonOk(body, 500);
246
246
  }
247
247
 
248
- // src/logger/logger.ts
249
- var LEVEL_RANK = { debug: 0, info: 1, warn: 2, error: 3 };
250
- var globalState = {
251
- level: null,
252
- sink: null,
253
- disabled: false
254
- };
255
- function globalThreshold() {
256
- return globalState.level ?? "info";
257
- }
248
+ // src/logger/formatEntry.ts
258
249
  function serializeFieldValue(value) {
259
250
  if (value instanceof Error) {
260
251
  return { name: value.name, message: value.message, stack: value.stack };
@@ -277,25 +268,53 @@ function formatEntry(entry) {
277
268
  }
278
269
  return line;
279
270
  }
271
+
272
+ // src/logger/logger.ts
273
+ var LEVEL_RANK = { debug: 0, info: 1, warn: 2, error: 3 };
274
+ var globalState = { level: null, sink: null, fileSink: null, stdout: true, accessLog: false, disabled: false };
275
+ function globalThreshold() {
276
+ if (globalState.level) return globalState.level;
277
+ if (globalState.fileSink) return void 0;
278
+ return "info";
279
+ }
280
+ function belowThreshold(level, threshold) {
281
+ return threshold !== void 0 && LEVEL_RANK[level] < LEVEL_RANK[threshold];
282
+ }
283
+ var consoleSink = (entry) => {
284
+ console[CONSOLE_METHOD[entry.level]](formatEntry(entry));
285
+ };
280
286
  var CONSOLE_METHOD = {
281
287
  debug: "debug",
282
288
  info: "info",
283
289
  warn: "warn",
284
290
  error: "error"
285
291
  };
286
- var consoleSink = (entry) => {
287
- console[CONSOLE_METHOD[entry.level]](formatEntry(entry));
288
- };
289
292
  function globalDispatch(entry) {
290
293
  if (globalState.disabled) return;
291
- (globalState.sink ?? consoleSink)(entry);
294
+ if (globalState.sink) {
295
+ globalState.sink(entry);
296
+ return;
297
+ }
298
+ if (globalState.fileSink) {
299
+ globalState.fileSink.write(entry);
300
+ if (globalState.stdout) consoleSink(entry);
301
+ return;
302
+ }
303
+ consoleSink(entry);
304
+ }
305
+ function writeLogEntry(entry) {
306
+ if (belowThreshold(entry.level, globalThreshold())) return;
307
+ globalDispatch(entry);
308
+ }
309
+ function isAccessLogPiped() {
310
+ return !globalState.disabled && globalState.accessLog;
292
311
  }
293
312
  function createLogger(scope, options) {
294
313
  const baseScope = scope;
295
314
  const baseFields = options?.fields;
296
315
  const write = (level, message, callFields, scopeSuffix) => {
297
316
  const threshold = options?.level ?? globalThreshold();
298
- if (LEVEL_RANK[level] < LEVEL_RANK[threshold]) return;
317
+ if (belowThreshold(level, threshold)) return;
299
318
  const entry = {
300
319
  level,
301
320
  message,
@@ -4187,9 +4206,28 @@ function etag(options = {}) {
4187
4206
  }
4188
4207
 
4189
4208
  // src/middleware/logger.ts
4209
+ function levelForStatus(status) {
4210
+ if (status >= 500) return "error";
4211
+ if (status >= 400) return "warn";
4212
+ return "info";
4213
+ }
4214
+ function defaultLog(entry, text) {
4215
+ if (isAccessLogPiped()) {
4216
+ const logEntry = {
4217
+ level: levelForStatus(entry.status),
4218
+ message: text,
4219
+ time: (/* @__PURE__ */ new Date()).toISOString(),
4220
+ scope: "access",
4221
+ fields: entry
4222
+ };
4223
+ writeLogEntry(logEntry);
4224
+ return;
4225
+ }
4226
+ console.log(entry);
4227
+ }
4190
4228
  function logger(options = {}) {
4191
4229
  return async (ctx, next) => {
4192
- const log = options.log ?? console.log;
4230
+ const log = options.log ?? defaultLog;
4193
4231
  const start = Date.now();
4194
4232
  try {
4195
4233
  const response = await next();