@faapi/faapi 6.9.0 → 6.10.0
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/dist/cli/index.js +45 -35
- package/dist/cli/index.js.map +1 -1
- package/dist/index.d.ts +54 -21
- package/dist/index.js +49 -35
- package/dist/index.js.map +1 -1
- package/dist/{routeTypes-CuGMDCGB.d.ts → routeTypes-m9wZHWyo.d.ts} +9 -34
- package/dist/testing.d.ts +2 -4
- package/dist/testing.js +35 -33
- package/dist/testing.js.map +1 -1
- package/package.json +1 -1
|
@@ -306,24 +306,27 @@ interface CreateLoggerOptions {
|
|
|
306
306
|
/**
|
|
307
307
|
* `config.log` 的对象形状(config 侧另接受 boolean:false 全静默、true 默认)
|
|
308
308
|
*
|
|
309
|
-
*
|
|
310
|
-
*
|
|
309
|
+
* 参考 egg.js 的单管道模型:一条日志管道、两个输出出口(文件/sink 与 console),
|
|
310
|
+
* 各有独立阈值——`level` 管管道出口(不配不过滤),`consoleLevel` 管 console 出口
|
|
311
|
+
* (不配 `'info'`)。非法级别值启动报错。`sink` 与 `dir` 互斥,同时配置启动报错。
|
|
311
312
|
*/
|
|
312
313
|
interface LogConfig {
|
|
313
|
-
/**
|
|
314
|
+
/** 管道阈值(文件/sink 收到的条目;不配不过滤,LOG_LEVEL env 同源) */
|
|
314
315
|
level?: LogLevel;
|
|
316
|
+
/** console 出口阈值(不配 `'info'`;`false` 关闭 console 输出) */
|
|
317
|
+
consoleLevel?: LogLevel | false;
|
|
315
318
|
/** 自定义输出管道(整体接管,与 `dir` 互斥) */
|
|
316
319
|
sink?: LogSink;
|
|
317
320
|
/**
|
|
318
321
|
* 文件日志目录(egg 风格):配置即启用内置文件管道——默认 `app.log` 全量 +
|
|
319
|
-
* `error.log` 仅 error(dup
|
|
322
|
+
* `error.log` 仅 error(dup 语义);请求日志自动并入
|
|
320
323
|
*/
|
|
321
324
|
dir?: string;
|
|
322
325
|
/** true 时按级别四文件 `debug.log`/`info.log`/`warn.log`/`error.log`(各只含对应级别) */
|
|
323
326
|
splitByLevel?: boolean;
|
|
324
327
|
/** 文件模式下是否保留 console 双写(默认 true;false 纯文件) */
|
|
325
328
|
stdout?: boolean;
|
|
326
|
-
/**
|
|
329
|
+
/** 请求日志是否并入管道(默认 true;false 关闭请求日志,不输出) */
|
|
327
330
|
accessLog?: boolean;
|
|
328
331
|
}
|
|
329
332
|
|
|
@@ -1125,34 +1128,6 @@ interface CorsOptions {
|
|
|
1125
1128
|
*/
|
|
1126
1129
|
declare function cors(options?: CorsOptions): FaapiMiddleware;
|
|
1127
1130
|
|
|
1128
|
-
type LoggerFn = (messageOrObj: string | Record<string, unknown>, message?: string) => void;
|
|
1129
|
-
interface LoggerOptions {
|
|
1130
|
-
/**
|
|
1131
|
-
* 自定义日志函数
|
|
1132
|
-
*
|
|
1133
|
-
* - 传入 `console.log`(默认):纯文本格式 `GET /api/users 200 12ms`
|
|
1134
|
-
* - 传入 pino logger:结构化日志 `logger.info({ method, path, status, durationMs }, 'request completed')`
|
|
1135
|
-
* - 传入 winston logger:`logger.info('GET /api/users 200 12ms', { method, path })`
|
|
1136
|
-
*/
|
|
1137
|
-
log?: LoggerFn;
|
|
1138
|
-
}
|
|
1139
|
-
/**
|
|
1140
|
-
* 创建请求日志中间件(洋葱模型)
|
|
1141
|
-
*
|
|
1142
|
-
* 日志格式(文本模式):GET /api/users 200 12ms
|
|
1143
|
-
* 错误格式(文本模式):POST /api/users 400 45ms - Error: ...
|
|
1144
|
-
*
|
|
1145
|
-
* 结构化模式:传入 pino/winston 等 logger 实例时,会自动传递结构化字段。
|
|
1146
|
-
*
|
|
1147
|
-
* before/after 一体,闭包变量共享开始时间,无需污染 ctx。
|
|
1148
|
-
* 错误用 try/catch 捕获,记录后重新抛出(让上层处理)。
|
|
1149
|
-
* 成功时从 next() 返回的 Response 读取状态码。
|
|
1150
|
-
*
|
|
1151
|
-
* log 函数每次请求时读取(options.log ?? defaultLog),运行时替换 console.log 或
|
|
1152
|
-
* 切换全局日志配置均会生效。
|
|
1153
|
-
*/
|
|
1154
|
-
declare function logger(options?: LoggerOptions): FaapiMiddleware;
|
|
1155
|
-
|
|
1156
1131
|
interface HelmetOptions {
|
|
1157
1132
|
contentSecurityPolicy?: string | false;
|
|
1158
1133
|
xFrameOptions?: 'DENY' | 'SAMEORIGIN' | false;
|
|
@@ -1256,4 +1231,4 @@ interface RouteInfo {
|
|
|
1256
1231
|
output: RouteOutputSchema | null;
|
|
1257
1232
|
}
|
|
1258
1233
|
|
|
1259
|
-
export { type
|
|
1234
|
+
export { type ToolRegistry as $, type AppRegistries as A, type RouteOutputSchema as B, type CorsOptions as C, type RouteParamSchema as D, type SseEvent as E, type FaapiMiddleware as F, type SseWriter as G, type HelmetOptions as H, type InjectorMap as I, type TaskContext as J, type TaskDriverJob as K, type LogConfig as L, type TaskDriverProcess as M, type TaskDriverRecord as N, type TaskFailedInfo as O, type TaskJob as P, type TaskJobStatus as Q, type RouteManifest as R, type SkillRegistry as S, type TaskClient as T, type TaskMetadata as U, type TaskModule as V, type WsRouteManifest as W, type TaskRegistriesSnapshot as X, type TaskRegistriesView as Y, type ToolCore as Z, type ToolPathMeta as _, type FaapiContext as a, cors as a0, createAppRegistries as a1, createTaskRegistriesView as a2, createTaskRegistry as a3, helmet as a4, type TaskFailedHandler as b, type TaskQueueDeps as c, type TaskQueue as d, type TaskDriver as e, type TaskRegistry as f, type TaskManifest as g, type ToolMetadata as h, type AgentCore as i, type AgentMetadata as j, type CreateLoggerOptions as k, type Logger as l, type AgentHandleFactory as m, type AgentHandleStore as n, type AgentPathMeta as o, type AgentRegistry as p, type AgentToolDescriptor as q, type FaapiContextConfig as r, type FaapiTaskMeta as s, type FailOptions as t, type Injector as u, type LogEntry as v, type LogLevel as w, type LogSink as x, type RouteInfo as y, type RouteInputSchema as z };
|
package/dist/testing.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { a as FaapiContext, F as FaapiMiddleware, I as InjectorMap, R as RouteManifest, W as WsRouteManifest, C as CorsOptions, H as HelmetOptions } from './routeTypes-m9wZHWyo.js';
|
|
2
2
|
import { Server } from 'node:http';
|
|
3
3
|
import { WebSocket } from 'ws';
|
|
4
4
|
|
|
@@ -76,8 +76,6 @@ interface TestServerOptions {
|
|
|
76
76
|
cors?: CorsOptions | boolean;
|
|
77
77
|
/** 安全头配置,默认 false */
|
|
78
78
|
helmet?: HelmetOptions | boolean;
|
|
79
|
-
/** 请求日志配置,默认 false(避免污染测试输出) */
|
|
80
|
-
logger?: LoggerOptions | boolean;
|
|
81
79
|
/** 全局中间件(外层洋葱) */
|
|
82
80
|
middlewares?: FaapiMiddleware[];
|
|
83
81
|
/** 全局注入器 */
|
|
@@ -126,7 +124,7 @@ interface TestServer {
|
|
|
126
124
|
* 2. sortRoutes 排序
|
|
127
125
|
* 3. mkdtemp 创建临时 schema 目录(或用传入的 dist)
|
|
128
126
|
* 4. generateSchemaFiles 生成 zod.js
|
|
129
|
-
* 5. createServer 创建 server(默认禁用 CORS/Helmet
|
|
127
|
+
* 5. createServer 创建 server(默认禁用 CORS/Helmet,避免污染断言)
|
|
130
128
|
* 6. server.listen(0) 随机端口
|
|
131
129
|
* 7. 返回 TestServer
|
|
132
130
|
*
|
package/dist/testing.js
CHANGED
|
@@ -271,50 +271,60 @@ function formatEntry(entry) {
|
|
|
271
271
|
|
|
272
272
|
// src/logger/logger.ts
|
|
273
273
|
var LEVEL_RANK = { debug: 0, info: 1, warn: 2, error: 3 };
|
|
274
|
-
var globalState = {
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
274
|
+
var globalState = {
|
|
275
|
+
level: null,
|
|
276
|
+
consoleLevel: null,
|
|
277
|
+
sink: null,
|
|
278
|
+
fileSink: null,
|
|
279
|
+
stdout: true,
|
|
280
|
+
accessLog: true,
|
|
281
|
+
disabled: false
|
|
282
|
+
};
|
|
283
|
+
function pipelineThreshold() {
|
|
284
|
+
return globalState.level ?? void 0;
|
|
285
|
+
}
|
|
286
|
+
function consoleThreshold() {
|
|
287
|
+
return globalState.consoleLevel ?? "info";
|
|
279
288
|
}
|
|
280
289
|
function belowThreshold(level, threshold) {
|
|
281
290
|
return threshold !== void 0 && LEVEL_RANK[level] < LEVEL_RANK[threshold];
|
|
282
291
|
}
|
|
283
|
-
var consoleSink = (entry) => {
|
|
284
|
-
console[CONSOLE_METHOD[entry.level]](formatEntry(entry));
|
|
285
|
-
};
|
|
286
292
|
var CONSOLE_METHOD = {
|
|
287
293
|
debug: "debug",
|
|
288
294
|
info: "info",
|
|
289
295
|
warn: "warn",
|
|
290
296
|
error: "error"
|
|
291
297
|
};
|
|
298
|
+
function consoleDispatch(entry) {
|
|
299
|
+
const threshold = consoleThreshold();
|
|
300
|
+
if (threshold === false || belowThreshold(entry.level, threshold)) return;
|
|
301
|
+
console[CONSOLE_METHOD[entry.level]](formatEntry(entry));
|
|
302
|
+
}
|
|
292
303
|
function globalDispatch(entry) {
|
|
293
304
|
if (globalState.disabled) return;
|
|
305
|
+
const pipeThreshold = pipelineThreshold();
|
|
294
306
|
if (globalState.sink) {
|
|
295
|
-
globalState.sink(entry);
|
|
307
|
+
if (!belowThreshold(entry.level, pipeThreshold)) globalState.sink(entry);
|
|
296
308
|
return;
|
|
297
309
|
}
|
|
298
310
|
if (globalState.fileSink) {
|
|
299
|
-
globalState.fileSink.write(entry);
|
|
300
|
-
if (globalState.stdout)
|
|
311
|
+
if (!belowThreshold(entry.level, pipeThreshold)) globalState.fileSink.write(entry);
|
|
312
|
+
if (globalState.stdout) consoleDispatch(entry);
|
|
301
313
|
return;
|
|
302
314
|
}
|
|
303
|
-
|
|
315
|
+
consoleDispatch(entry);
|
|
304
316
|
}
|
|
305
317
|
function writeLogEntry(entry) {
|
|
306
|
-
if (belowThreshold(entry.level, globalThreshold())) return;
|
|
307
318
|
globalDispatch(entry);
|
|
308
319
|
}
|
|
309
|
-
function
|
|
320
|
+
function isAccessLogEnabled() {
|
|
310
321
|
return !globalState.disabled && globalState.accessLog;
|
|
311
322
|
}
|
|
312
323
|
function createLogger(scope, options) {
|
|
313
324
|
const baseScope = scope;
|
|
314
325
|
const baseFields = options?.fields;
|
|
315
326
|
const write = (level, message, callFields, scopeSuffix) => {
|
|
316
|
-
|
|
317
|
-
if (belowThreshold(level, threshold)) return;
|
|
327
|
+
if (belowThreshold(level, options?.level)) return;
|
|
318
328
|
const entry = {
|
|
319
329
|
level,
|
|
320
330
|
message,
|
|
@@ -4212,18 +4222,14 @@ function levelForStatus(status) {
|
|
|
4212
4222
|
return "info";
|
|
4213
4223
|
}
|
|
4214
4224
|
function defaultLog(entry, text) {
|
|
4215
|
-
if (
|
|
4216
|
-
|
|
4217
|
-
|
|
4218
|
-
|
|
4219
|
-
|
|
4220
|
-
|
|
4221
|
-
|
|
4222
|
-
|
|
4223
|
-
writeLogEntry(logEntry);
|
|
4224
|
-
return;
|
|
4225
|
-
}
|
|
4226
|
-
console.log(entry);
|
|
4225
|
+
if (!isAccessLogEnabled()) return;
|
|
4226
|
+
writeLogEntry({
|
|
4227
|
+
level: levelForStatus(entry.status),
|
|
4228
|
+
message: text,
|
|
4229
|
+
time: (/* @__PURE__ */ new Date()).toISOString(),
|
|
4230
|
+
scope: "access",
|
|
4231
|
+
fields: entry
|
|
4232
|
+
});
|
|
4227
4233
|
}
|
|
4228
4234
|
function logger(options = {}) {
|
|
4229
4235
|
return async (ctx, next) => {
|
|
@@ -4586,7 +4592,6 @@ function createServer(options) {
|
|
|
4586
4592
|
compression: compressionOption,
|
|
4587
4593
|
etag: etagOption,
|
|
4588
4594
|
registries,
|
|
4589
|
-
logger: loggerOption,
|
|
4590
4595
|
bodyLimit = DEFAULT_BODY_LIMIT,
|
|
4591
4596
|
http2: http2Option,
|
|
4592
4597
|
trustedProxy = false
|
|
@@ -4603,8 +4608,7 @@ function createServer(options) {
|
|
|
4603
4608
|
const helmOpts = typeof helmetOption === "object" ? helmetOption : {};
|
|
4604
4609
|
configMiddlewares.push(helmet(helmOpts));
|
|
4605
4610
|
}
|
|
4606
|
-
|
|
4607
|
-
if (loggerMiddlewareInst) configMiddlewares.push(loggerMiddlewareInst);
|
|
4611
|
+
configMiddlewares.push(logger());
|
|
4608
4612
|
if (etagOption) {
|
|
4609
4613
|
const etagOpts = typeof etagOption === "object" ? etagOption : {};
|
|
4610
4614
|
configMiddlewares.push(etag(etagOpts));
|
|
@@ -4787,7 +4791,6 @@ async function createTestServer(options) {
|
|
|
4787
4791
|
dist,
|
|
4788
4792
|
cors: cors2 = false,
|
|
4789
4793
|
helmet: helmet2 = false,
|
|
4790
|
-
logger: logger2 = false,
|
|
4791
4794
|
middlewares,
|
|
4792
4795
|
injectors,
|
|
4793
4796
|
onError,
|
|
@@ -4804,7 +4807,6 @@ async function createTestServer(options) {
|
|
|
4804
4807
|
dist: schemaDist,
|
|
4805
4808
|
cors: cors2,
|
|
4806
4809
|
helmet: helmet2,
|
|
4807
|
-
logger: logger2,
|
|
4808
4810
|
middlewares,
|
|
4809
4811
|
injectors,
|
|
4810
4812
|
onError,
|