@airmcp-dev/logger 0.1.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/LICENSE +17 -0
- package/dist/formatter/index.d.ts +3 -0
- package/dist/formatter/index.d.ts.map +1 -0
- package/dist/formatter/index.js +5 -0
- package/dist/formatter/index.js.map +1 -0
- package/dist/formatter/json.d.ts +5 -0
- package/dist/formatter/json.d.ts.map +1 -0
- package/dist/formatter/json.js +29 -0
- package/dist/formatter/json.js.map +1 -0
- package/dist/formatter/pretty.d.ts +5 -0
- package/dist/formatter/pretty.d.ts.map +1 -0
- package/dist/formatter/pretty.js +35 -0
- package/dist/formatter/pretty.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -0
- package/dist/logger.d.ts +27 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +103 -0
- package/dist/logger.js.map +1 -0
- package/dist/transport/console.d.ts +6 -0
- package/dist/transport/console.d.ts.map +1 -0
- package/dist/transport/console.js +16 -0
- package/dist/transport/console.js.map +1 -0
- package/dist/transport/file.d.ts +22 -0
- package/dist/transport/file.d.ts.map +1 -0
- package/dist/transport/file.js +67 -0
- package/dist/transport/file.js.map +1 -0
- package/dist/transport/index.d.ts +6 -0
- package/dist/transport/index.d.ts.map +1 -0
- package/dist/transport/index.js +6 -0
- package/dist/transport/index.js.map +1 -0
- package/dist/transport/remote.d.ts +24 -0
- package/dist/transport/remote.d.ts.map +1 -0
- package/dist/transport/remote.js +54 -0
- package/dist/transport/remote.js.map +1 -0
- package/dist/types.d.ts +44 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +11 -0
- package/dist/types.js.map +1 -0
- package/package.json +31 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
Apache License
|
|
2
|
+
Version 2.0, January 2004
|
|
3
|
+
http://www.apache.org/licenses/
|
|
4
|
+
|
|
5
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
you may not use this file except in compliance with the License.
|
|
7
|
+
You may obtain a copy of the License at
|
|
8
|
+
|
|
9
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
|
|
11
|
+
Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
See the License for the specific language governing permissions and
|
|
15
|
+
limitations under the License.
|
|
16
|
+
|
|
17
|
+
Copyright 2026 CodePedia Labs (labs@codepedia.kr)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/formatter/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/formatter/index.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,0CAA0C;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json.d.ts","sourceRoot":"","sources":["../../src/formatter/json.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE1D,qBAAa,aAAc,YAAW,YAAY;IAChD,MAAM,CAAC,KAAK,EAAE,QAAQ,GAAG,MAAM;CAoBhC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// Copyright 2026 CodePedia Labs. Licensed under Apache-2.0.
|
|
2
|
+
// @airmcp-dev/logger — formatter/json.ts
|
|
3
|
+
//
|
|
4
|
+
// 구조화 JSON 포맷. 파일 저장, 원격 전송, 파이프라인 처리용.
|
|
5
|
+
// 한 줄 한 엔트리 (NDJSON).
|
|
6
|
+
export class JsonFormatter {
|
|
7
|
+
format(entry) {
|
|
8
|
+
const obj = {
|
|
9
|
+
level: entry.level,
|
|
10
|
+
msg: entry.message,
|
|
11
|
+
ts: entry.timestamp.toISOString(),
|
|
12
|
+
};
|
|
13
|
+
if (entry.source)
|
|
14
|
+
obj.source = entry.source;
|
|
15
|
+
if (entry.requestId)
|
|
16
|
+
obj.reqId = entry.requestId;
|
|
17
|
+
if (entry.data)
|
|
18
|
+
obj.data = entry.data;
|
|
19
|
+
if (entry.error) {
|
|
20
|
+
obj.err = {
|
|
21
|
+
name: entry.error.name,
|
|
22
|
+
message: entry.error.message,
|
|
23
|
+
...(entry.error.stack ? { stack: entry.error.stack } : {}),
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
return JSON.stringify(obj);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=json.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json.js","sourceRoot":"","sources":["../../src/formatter/json.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yCAAyC;AACzC,EAAE;AACF,wCAAwC;AACxC,sBAAsB;AAItB,MAAM,OAAO,aAAa;IACxB,MAAM,CAAC,KAAe;QACpB,MAAM,GAAG,GAAwB;YAC/B,KAAK,EAAE,KAAK,CAAC,KAAK;YAClB,GAAG,EAAE,KAAK,CAAC,OAAO;YAClB,EAAE,EAAE,KAAK,CAAC,SAAS,CAAC,WAAW,EAAE;SAClC,CAAC;QAEF,IAAI,KAAK,CAAC,MAAM;YAAE,GAAG,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;QAC5C,IAAI,KAAK,CAAC,SAAS;YAAE,GAAG,CAAC,KAAK,GAAG,KAAK,CAAC,SAAS,CAAC;QACjD,IAAI,KAAK,CAAC,IAAI;YAAE,GAAG,CAAC,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC;QACtC,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;YAChB,GAAG,CAAC,GAAG,GAAG;gBACR,IAAI,EAAE,KAAK,CAAC,KAAK,CAAC,IAAI;gBACtB,OAAO,EAAE,KAAK,CAAC,KAAK,CAAC,OAAO;gBAC5B,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aAC3D,CAAC;QACJ,CAAC;QAED,OAAO,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;IAC7B,CAAC;CACF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pretty.d.ts","sourceRoot":"","sources":["../../src/formatter/pretty.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAa1D,qBAAa,eAAgB,YAAW,YAAY;IAClD,MAAM,CAAC,KAAK,EAAE,QAAQ,GAAG,MAAM;CAsBhC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
// Copyright 2026 CodePedia Labs. Licensed under Apache-2.0.
|
|
2
|
+
// @airmcp-dev/logger — formatter/pretty.ts
|
|
3
|
+
//
|
|
4
|
+
// 사람이 읽기 좋은 컬러 포맷. 개발 모드용.
|
|
5
|
+
// 예: 14:32:05 INFO [my-tool] Server started on port 3000
|
|
6
|
+
const LEVEL_COLORS = {
|
|
7
|
+
debug: '\x1b[90m', // gray
|
|
8
|
+
info: '\x1b[36m', // cyan
|
|
9
|
+
warn: '\x1b[33m', // yellow
|
|
10
|
+
error: '\x1b[31m', // red
|
|
11
|
+
fatal: '\x1b[35m', // magenta
|
|
12
|
+
};
|
|
13
|
+
const RESET = '\x1b[0m';
|
|
14
|
+
const DIM = '\x1b[2m';
|
|
15
|
+
export class PrettyFormatter {
|
|
16
|
+
format(entry) {
|
|
17
|
+
const time = entry.timestamp.toTimeString().slice(0, 8);
|
|
18
|
+
const level = entry.level.toUpperCase().padEnd(5);
|
|
19
|
+
const color = LEVEL_COLORS[entry.level] || '';
|
|
20
|
+
const source = entry.source ? `${DIM}[${entry.source}]${RESET} ` : '';
|
|
21
|
+
let line = `${DIM}${time}${RESET} ${color}${level}${RESET} ${source}${entry.message}`;
|
|
22
|
+
if (entry.data && Object.keys(entry.data).length > 0) {
|
|
23
|
+
line += ` ${DIM}${JSON.stringify(entry.data)}${RESET}`;
|
|
24
|
+
}
|
|
25
|
+
if (entry.error) {
|
|
26
|
+
line += `\n ${color}${entry.error.name}: ${entry.error.message}${RESET}`;
|
|
27
|
+
if (entry.error.stack) {
|
|
28
|
+
const stackLines = entry.error.stack.split('\n').slice(1, 4);
|
|
29
|
+
line += `\n${DIM}${stackLines.join('\n')}${RESET}`;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return line;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=pretty.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pretty.js","sourceRoot":"","sources":["../../src/formatter/pretty.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,2CAA2C;AAC3C,EAAE;AACF,2BAA2B;AAC3B,0DAA0D;AAI1D,MAAM,YAAY,GAA2B;IAC3C,KAAK,EAAE,UAAU,EAAE,OAAO;IAC1B,IAAI,EAAE,UAAU,EAAE,OAAO;IACzB,IAAI,EAAE,UAAU,EAAE,SAAS;IAC3B,KAAK,EAAE,UAAU,EAAE,MAAM;IACzB,KAAK,EAAE,UAAU,EAAE,UAAU;CAC9B,CAAC;AAEF,MAAM,KAAK,GAAG,SAAS,CAAC;AACxB,MAAM,GAAG,GAAG,SAAS,CAAC;AAEtB,MAAM,OAAO,eAAe;IAC1B,MAAM,CAAC,KAAe;QACpB,MAAM,IAAI,GAAG,KAAK,CAAC,SAAS,CAAC,YAAY,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QACxD,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QAClD,MAAM,KAAK,GAAG,YAAY,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;QAC9C,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,GAAG,IAAI,KAAK,CAAC,MAAM,IAAI,KAAK,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;QAEtE,IAAI,IAAI,GAAG,GAAG,GAAG,GAAG,IAAI,GAAG,KAAK,IAAI,KAAK,GAAG,KAAK,GAAG,KAAK,IAAI,MAAM,GAAG,KAAK,CAAC,OAAO,EAAE,CAAC;QAEtF,IAAI,KAAK,CAAC,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACrD,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,KAAK,EAAE,CAAC;QACzD,CAAC;QAED,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;YAChB,IAAI,IAAI,OAAO,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,KAAK,KAAK,CAAC,KAAK,CAAC,OAAO,GAAG,KAAK,EAAE,CAAC;YAC1E,IAAI,KAAK,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;gBACtB,MAAM,UAAU,GAAG,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;gBAC7D,IAAI,IAAI,KAAK,GAAG,GAAG,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,KAAK,EAAE,CAAC;YACrD,CAAC;QACH,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;CACF"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export { AirLogger } from './logger.js';
|
|
2
|
+
export { JsonFormatter } from './formatter/index.js';
|
|
3
|
+
export { PrettyFormatter } from './formatter/index.js';
|
|
4
|
+
export { ConsoleTransport } from './transport/index.js';
|
|
5
|
+
export { FileTransport } from './transport/index.js';
|
|
6
|
+
export { RemoteTransport } from './transport/index.js';
|
|
7
|
+
export type { LogLevel, LogEntry, LogFormatter, LogTransport, LoggerConfig } from './types.js';
|
|
8
|
+
export { LOG_LEVEL_PRIORITY } from './types.js';
|
|
9
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAGxC,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAGvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAGvD,YAAY,EAAE,QAAQ,EAAE,QAAQ,EAAE,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC/F,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// Copyright 2026 CodePedia Labs. Licensed under Apache-2.0.
|
|
2
|
+
// @airmcp-dev/logger — index.ts
|
|
3
|
+
// re-export only. 로직 없음.
|
|
4
|
+
export { AirLogger } from './logger.js';
|
|
5
|
+
// ── Formatter ──
|
|
6
|
+
export { JsonFormatter } from './formatter/index.js';
|
|
7
|
+
export { PrettyFormatter } from './formatter/index.js';
|
|
8
|
+
// ── Transport ──
|
|
9
|
+
export { ConsoleTransport } from './transport/index.js';
|
|
10
|
+
export { FileTransport } from './transport/index.js';
|
|
11
|
+
export { RemoteTransport } from './transport/index.js';
|
|
12
|
+
export { LOG_LEVEL_PRIORITY } from './types.js';
|
|
13
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,gCAAgC;AAChC,yBAAyB;AAEzB,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAExC,kBAAkB;AAClB,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAEvD,kBAAkB;AAClB,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAIvD,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC"}
|
package/dist/logger.d.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { LogTransport, LoggerConfig } from './types.js';
|
|
2
|
+
export declare class AirLogger {
|
|
3
|
+
private level;
|
|
4
|
+
private formatter;
|
|
5
|
+
private transports;
|
|
6
|
+
private source?;
|
|
7
|
+
constructor(config?: LoggerConfig);
|
|
8
|
+
debug(message: string, data?: Record<string, any>): void;
|
|
9
|
+
info(message: string, data?: Record<string, any>): void;
|
|
10
|
+
warn(message: string, data?: Record<string, any>): void;
|
|
11
|
+
error(message: string, data?: Record<string, any>, err?: Error): void;
|
|
12
|
+
fatal(message: string, data?: Record<string, any>, err?: Error): void;
|
|
13
|
+
/**
|
|
14
|
+
* 자식 로거를 생성한다. source를 오버라이드.
|
|
15
|
+
*/
|
|
16
|
+
child(source: string): AirLogger;
|
|
17
|
+
/**
|
|
18
|
+
* 트랜스포트를 추가한다.
|
|
19
|
+
*/
|
|
20
|
+
addTransport(transport: LogTransport): void;
|
|
21
|
+
/**
|
|
22
|
+
* 모든 트랜스포트를 정리한다.
|
|
23
|
+
*/
|
|
24
|
+
close(): Promise<void>;
|
|
25
|
+
private log;
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=logger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAoC,YAAY,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAM/F,qBAAa,SAAS;IACpB,OAAO,CAAC,KAAK,CAAW;IACxB,OAAO,CAAC,SAAS,CAAe;IAChC,OAAO,CAAC,UAAU,CAAiB;IACnC,OAAO,CAAC,MAAM,CAAC,CAAS;gBAEZ,MAAM,CAAC,EAAE,YAAY;IAiBjC,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI;IAIxD,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI;IAIvD,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI;IAIvD,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,GAAG,CAAC,EAAE,KAAK,GAAG,IAAI;IAIrE,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,GAAG,CAAC,EAAE,KAAK,GAAG,IAAI;IAIrE;;OAEG;IACH,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS;IAWhC;;OAEG;IACH,YAAY,CAAC,SAAS,EAAE,YAAY,GAAG,IAAI;IAI3C;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAM5B,OAAO,CAAC,GAAG;CA0BZ"}
|
package/dist/logger.js
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
// Copyright 2026 CodePedia Labs. Licensed under Apache-2.0.
|
|
2
|
+
// @airmcp-dev/logger — logger.ts
|
|
3
|
+
//
|
|
4
|
+
// AirLogger — 구조화 로깅 메인 클래스.
|
|
5
|
+
// formatter + transport 조합으로 출력.
|
|
6
|
+
//
|
|
7
|
+
// @example
|
|
8
|
+
// const logger = new AirLogger({ level: 'info', formatter: 'pretty' });
|
|
9
|
+
// logger.info('Server started', { port: 3000 });
|
|
10
|
+
// logger.error('Connection failed', { host: 'db' }, err);
|
|
11
|
+
import { LOG_LEVEL_PRIORITY } from './types.js';
|
|
12
|
+
import { JsonFormatter } from './formatter/json.js';
|
|
13
|
+
import { PrettyFormatter } from './formatter/pretty.js';
|
|
14
|
+
import { ConsoleTransport } from './transport/console.js';
|
|
15
|
+
export class AirLogger {
|
|
16
|
+
level;
|
|
17
|
+
formatter;
|
|
18
|
+
transports;
|
|
19
|
+
source;
|
|
20
|
+
constructor(config) {
|
|
21
|
+
this.level = config?.level ?? 'info';
|
|
22
|
+
this.source = config?.source;
|
|
23
|
+
// 포매터 결정
|
|
24
|
+
if (!config?.formatter || config.formatter === 'json') {
|
|
25
|
+
this.formatter = new JsonFormatter();
|
|
26
|
+
}
|
|
27
|
+
else if (config.formatter === 'pretty') {
|
|
28
|
+
this.formatter = new PrettyFormatter();
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
this.formatter = config.formatter;
|
|
32
|
+
}
|
|
33
|
+
// 트랜스포트 (기본: console)
|
|
34
|
+
this.transports = config?.transports ?? [new ConsoleTransport()];
|
|
35
|
+
}
|
|
36
|
+
debug(message, data) {
|
|
37
|
+
this.log('debug', message, data);
|
|
38
|
+
}
|
|
39
|
+
info(message, data) {
|
|
40
|
+
this.log('info', message, data);
|
|
41
|
+
}
|
|
42
|
+
warn(message, data) {
|
|
43
|
+
this.log('warn', message, data);
|
|
44
|
+
}
|
|
45
|
+
error(message, data, err) {
|
|
46
|
+
this.log('error', message, data, err);
|
|
47
|
+
}
|
|
48
|
+
fatal(message, data, err) {
|
|
49
|
+
this.log('fatal', message, data, err);
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* 자식 로거를 생성한다. source를 오버라이드.
|
|
53
|
+
*/
|
|
54
|
+
child(source) {
|
|
55
|
+
const child = new AirLogger({
|
|
56
|
+
level: this.level,
|
|
57
|
+
source,
|
|
58
|
+
transports: this.transports,
|
|
59
|
+
});
|
|
60
|
+
// 포매터 공유
|
|
61
|
+
child.formatter = this.formatter;
|
|
62
|
+
return child;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* 트랜스포트를 추가한다.
|
|
66
|
+
*/
|
|
67
|
+
addTransport(transport) {
|
|
68
|
+
this.transports.push(transport);
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* 모든 트랜스포트를 정리한다.
|
|
72
|
+
*/
|
|
73
|
+
async close() {
|
|
74
|
+
for (const t of this.transports) {
|
|
75
|
+
if (t.close)
|
|
76
|
+
await t.close();
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
log(level, message, data, err) {
|
|
80
|
+
// 레벨 필터링
|
|
81
|
+
if (LOG_LEVEL_PRIORITY[level] < LOG_LEVEL_PRIORITY[this.level])
|
|
82
|
+
return;
|
|
83
|
+
const entry = {
|
|
84
|
+
level,
|
|
85
|
+
message,
|
|
86
|
+
timestamp: new Date(),
|
|
87
|
+
source: this.source,
|
|
88
|
+
data,
|
|
89
|
+
};
|
|
90
|
+
if (err) {
|
|
91
|
+
entry.error = {
|
|
92
|
+
name: err.name,
|
|
93
|
+
message: err.message,
|
|
94
|
+
stack: err.stack,
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
const formatted = this.formatter.format(entry);
|
|
98
|
+
for (const transport of this.transports) {
|
|
99
|
+
transport.write(formatted, entry);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"console.d.ts","sourceRoot":"","sources":["../../src/transport/console.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE1D,qBAAa,gBAAiB,YAAW,YAAY;IACnD,IAAI,SAAa;IAEjB,KAAK,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,GAAG,IAAI;CAOhD"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// Copyright 2026 CodePedia Labs. Licensed under Apache-2.0.
|
|
2
|
+
// @airmcp-dev/logger — transport/console.ts
|
|
3
|
+
//
|
|
4
|
+
// stdout/stderr 출력 트랜스포트. 기본값.
|
|
5
|
+
export class ConsoleTransport {
|
|
6
|
+
name = 'console';
|
|
7
|
+
write(formatted, entry) {
|
|
8
|
+
if (entry.level === 'error' || entry.level === 'fatal') {
|
|
9
|
+
process.stderr.write(formatted + '\n');
|
|
10
|
+
}
|
|
11
|
+
else {
|
|
12
|
+
process.stdout.write(formatted + '\n');
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=console.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"console.js","sourceRoot":"","sources":["../../src/transport/console.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,4CAA4C;AAC5C,EAAE;AACF,+BAA+B;AAI/B,MAAM,OAAO,gBAAgB;IAC3B,IAAI,GAAG,SAAS,CAAC;IAEjB,KAAK,CAAC,SAAiB,EAAE,KAAe;QACtC,IAAI,KAAK,CAAC,KAAK,KAAK,OAAO,IAAI,KAAK,CAAC,KAAK,KAAK,OAAO,EAAE,CAAC;YACvD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,SAAS,GAAG,IAAI,CAAC,CAAC;QACzC,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,SAAS,GAAG,IAAI,CAAC,CAAC;QACzC,CAAC;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { LogEntry, LogTransport } from '../types.js';
|
|
2
|
+
export interface FileTransportOptions {
|
|
3
|
+
/** 로그 파일 경로 */
|
|
4
|
+
path: string;
|
|
5
|
+
/** 최대 파일 크기 (bytes, 기본 10MB) */
|
|
6
|
+
maxSize?: number;
|
|
7
|
+
/** 보관할 로테이션 파일 수 (기본 5) */
|
|
8
|
+
maxFiles?: number;
|
|
9
|
+
}
|
|
10
|
+
export declare class FileTransport implements LogTransport {
|
|
11
|
+
name: string;
|
|
12
|
+
private stream;
|
|
13
|
+
private currentSize;
|
|
14
|
+
private filePath;
|
|
15
|
+
private maxSize;
|
|
16
|
+
private maxFiles;
|
|
17
|
+
constructor(opts: FileTransportOptions);
|
|
18
|
+
write(formatted: string, _entry: LogEntry): void;
|
|
19
|
+
close(): Promise<void>;
|
|
20
|
+
private rotate;
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=file.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file.d.ts","sourceRoot":"","sources":["../../src/transport/file.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE1D,MAAM,WAAW,oBAAoB;IACnC,eAAe;IACf,IAAI,EAAE,MAAM,CAAC;IACb,gCAAgC;IAChC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,2BAA2B;IAC3B,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,qBAAa,aAAc,YAAW,YAAY;IAChD,IAAI,SAAU;IACd,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,WAAW,CAAK;IACxB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,QAAQ,CAAS;gBAEb,IAAI,EAAE,oBAAoB;IAkBtC,KAAK,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,GAAG,IAAI;IAU1C,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAM5B,OAAO,CAAC,MAAM;CAuBf"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
// Copyright 2026 CodePedia Labs. Licensed under Apache-2.0.
|
|
2
|
+
// @airmcp-dev/logger — transport/file.ts
|
|
3
|
+
//
|
|
4
|
+
// 파일 로테이션 트랜스포트.
|
|
5
|
+
// 지정 크기 초과 시 자동 로테이션 (.1, .2, ...).
|
|
6
|
+
import { createWriteStream, statSync, renameSync } from 'node:fs';
|
|
7
|
+
import { mkdirSync } from 'node:fs';
|
|
8
|
+
import { dirname } from 'node:path';
|
|
9
|
+
export class FileTransport {
|
|
10
|
+
name = 'file';
|
|
11
|
+
stream;
|
|
12
|
+
currentSize = 0;
|
|
13
|
+
filePath;
|
|
14
|
+
maxSize;
|
|
15
|
+
maxFiles;
|
|
16
|
+
constructor(opts) {
|
|
17
|
+
this.filePath = opts.path;
|
|
18
|
+
this.maxSize = opts.maxSize ?? 10 * 1024 * 1024;
|
|
19
|
+
this.maxFiles = opts.maxFiles ?? 5;
|
|
20
|
+
// 디렉토리 생성
|
|
21
|
+
mkdirSync(dirname(this.filePath), { recursive: true });
|
|
22
|
+
// 기존 파일 크기 확인
|
|
23
|
+
try {
|
|
24
|
+
this.currentSize = statSync(this.filePath).size;
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
this.currentSize = 0;
|
|
28
|
+
}
|
|
29
|
+
this.stream = createWriteStream(this.filePath, { flags: 'a' });
|
|
30
|
+
}
|
|
31
|
+
write(formatted, _entry) {
|
|
32
|
+
const line = formatted + '\n';
|
|
33
|
+
this.stream.write(line);
|
|
34
|
+
this.currentSize += Buffer.byteLength(line);
|
|
35
|
+
if (this.currentSize >= this.maxSize) {
|
|
36
|
+
this.rotate();
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
async close() {
|
|
40
|
+
return new Promise((resolve) => {
|
|
41
|
+
this.stream.end(resolve);
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
rotate() {
|
|
45
|
+
this.stream.end();
|
|
46
|
+
// .5 → 삭제, .4 → .5, ... .1 → .2, 현재 → .1
|
|
47
|
+
for (let i = this.maxFiles - 1; i >= 1; i--) {
|
|
48
|
+
const from = i === 1 ? this.filePath : `${this.filePath}.${i}`;
|
|
49
|
+
const to = `${this.filePath}.${i + 1}`;
|
|
50
|
+
try {
|
|
51
|
+
renameSync(from, to);
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
/* 없으면 무시 */
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
try {
|
|
58
|
+
renameSync(this.filePath, `${this.filePath}.1`);
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
/* ignore */
|
|
62
|
+
}
|
|
63
|
+
this.stream = createWriteStream(this.filePath, { flags: 'a' });
|
|
64
|
+
this.currentSize = 0;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=file.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file.js","sourceRoot":"","sources":["../../src/transport/file.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { ConsoleTransport } from './console.js';
|
|
2
|
+
export { FileTransport } from './file.js';
|
|
3
|
+
export type { FileTransportOptions } from './file.js';
|
|
4
|
+
export { RemoteTransport } from './remote.js';
|
|
5
|
+
export type { RemoteTransportOptions } from './remote.js';
|
|
6
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/transport/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAC1C,YAAY,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,YAAY,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
// Copyright 2026 CodePedia Labs. Licensed under Apache-2.0.
|
|
2
|
+
// @airmcp-dev/logger — transport/index.ts
|
|
3
|
+
export { ConsoleTransport } from './console.js';
|
|
4
|
+
export { FileTransport } from './file.js';
|
|
5
|
+
export { RemoteTransport } from './remote.js';
|
|
6
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/transport/index.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,0CAA0C;AAC1C,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAE1C,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { LogEntry, LogTransport } from '../types.js';
|
|
2
|
+
export interface RemoteTransportOptions {
|
|
3
|
+
/** 전송 대상 URL */
|
|
4
|
+
url: string;
|
|
5
|
+
/** HTTP 헤더 (인증 등) */
|
|
6
|
+
headers?: Record<string, string>;
|
|
7
|
+
/** 배치 크기 (기본 50) */
|
|
8
|
+
batchSize?: number;
|
|
9
|
+
/** 플러시 간격 (ms, 기본 5000) */
|
|
10
|
+
flushInterval?: number;
|
|
11
|
+
}
|
|
12
|
+
export declare class RemoteTransport implements LogTransport {
|
|
13
|
+
name: string;
|
|
14
|
+
private buffer;
|
|
15
|
+
private url;
|
|
16
|
+
private headers;
|
|
17
|
+
private batchSize;
|
|
18
|
+
private timer;
|
|
19
|
+
constructor(opts: RemoteTransportOptions);
|
|
20
|
+
write(formatted: string, _entry: LogEntry): void;
|
|
21
|
+
close(): Promise<void>;
|
|
22
|
+
private flush;
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=remote.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"remote.d.ts","sourceRoot":"","sources":["../../src/transport/remote.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE1D,MAAM,WAAW,sBAAsB;IACrC,gBAAgB;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,qBAAqB;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,oBAAoB;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,2BAA2B;IAC3B,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,qBAAa,eAAgB,YAAW,YAAY;IAClD,IAAI,SAAY;IAChB,OAAO,CAAC,MAAM,CAAgB;IAC9B,OAAO,CAAC,GAAG,CAAS;IACpB,OAAO,CAAC,OAAO,CAAyB;IACxC,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,KAAK,CAAwC;gBAEzC,IAAI,EAAE,sBAAsB;IAYxC,KAAK,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,GAAG,IAAI;IAQ1C,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;YAQd,KAAK;CAiBpB"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
// Copyright 2026 CodePedia Labs. Licensed under Apache-2.0.
|
|
2
|
+
// @airmcp-dev/logger — transport/remote.ts
|
|
3
|
+
//
|
|
4
|
+
// HTTP로 로그를 외부 서비스에 전송하는 트랜스포트.
|
|
5
|
+
// 배치 모드: 일정 개수 또는 시간 간격마다 묶어서 전송.
|
|
6
|
+
export class RemoteTransport {
|
|
7
|
+
name = 'remote';
|
|
8
|
+
buffer = [];
|
|
9
|
+
url;
|
|
10
|
+
headers;
|
|
11
|
+
batchSize;
|
|
12
|
+
timer;
|
|
13
|
+
constructor(opts) {
|
|
14
|
+
this.url = opts.url;
|
|
15
|
+
this.headers = {
|
|
16
|
+
'Content-Type': 'application/json',
|
|
17
|
+
...opts.headers,
|
|
18
|
+
};
|
|
19
|
+
this.batchSize = opts.batchSize ?? 50;
|
|
20
|
+
const interval = opts.flushInterval ?? 5000;
|
|
21
|
+
this.timer = setInterval(() => this.flush(), interval);
|
|
22
|
+
}
|
|
23
|
+
write(formatted, _entry) {
|
|
24
|
+
this.buffer.push(formatted);
|
|
25
|
+
if (this.buffer.length >= this.batchSize) {
|
|
26
|
+
this.flush();
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
async close() {
|
|
30
|
+
if (this.timer) {
|
|
31
|
+
clearInterval(this.timer);
|
|
32
|
+
this.timer = null;
|
|
33
|
+
}
|
|
34
|
+
await this.flush();
|
|
35
|
+
}
|
|
36
|
+
async flush() {
|
|
37
|
+
if (this.buffer.length === 0)
|
|
38
|
+
return;
|
|
39
|
+
const batch = this.buffer.splice(0);
|
|
40
|
+
const body = JSON.stringify({ logs: batch });
|
|
41
|
+
try {
|
|
42
|
+
await fetch(this.url, {
|
|
43
|
+
method: 'POST',
|
|
44
|
+
headers: this.headers,
|
|
45
|
+
body,
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
// 전송 실패 시 버퍼에 되돌리지 않음 (유실 허용)
|
|
50
|
+
// 프로덕션에서는 재시도 큐 추가 가능
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=remote.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"remote.js","sourceRoot":"","sources":["../../src/transport/remote.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,2CAA2C;AAC3C,EAAE;AACF,gCAAgC;AAChC,kCAAkC;AAelC,MAAM,OAAO,eAAe;IAC1B,IAAI,GAAG,QAAQ,CAAC;IACR,MAAM,GAAa,EAAE,CAAC;IACtB,GAAG,CAAS;IACZ,OAAO,CAAyB;IAChC,SAAS,CAAS;IAClB,KAAK,CAAwC;IAErD,YAAY,IAA4B;QACtC,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC;QACpB,IAAI,CAAC,OAAO,GAAG;YACb,cAAc,EAAE,kBAAkB;YAClC,GAAG,IAAI,CAAC,OAAO;SAChB,CAAC;QACF,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,IAAI,EAAE,CAAC;QAEtC,MAAM,QAAQ,GAAG,IAAI,CAAC,aAAa,IAAI,IAAI,CAAC;QAC5C,IAAI,CAAC,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,QAAQ,CAAC,CAAC;IACzD,CAAC;IAED,KAAK,CAAC,SAAiB,EAAE,MAAgB;QACvC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAE5B,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACzC,IAAI,CAAC,KAAK,EAAE,CAAC;QACf,CAAC;IACH,CAAC;IAED,KAAK,CAAC,KAAK;QACT,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACf,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAC1B,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;QACpB,CAAC;QACD,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC;IACrB,CAAC;IAEO,KAAK,CAAC,KAAK;QACjB,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO;QAErC,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QACpC,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QAE7C,IAAI,CAAC;YACH,MAAM,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE;gBACpB,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE,IAAI,CAAC,OAAO;gBACrB,IAAI;aACL,CAAC,CAAC;QACL,CAAC;QAAC,MAAM,CAAC;YACP,8BAA8B;YAC9B,sBAAsB;QACxB,CAAC;IACH,CAAC;CACF"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/** 로그 레벨 */
|
|
2
|
+
export type LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'fatal';
|
|
3
|
+
/** 로그 엔트리 */
|
|
4
|
+
export interface LogEntry {
|
|
5
|
+
level: LogLevel;
|
|
6
|
+
message: string;
|
|
7
|
+
timestamp: Date;
|
|
8
|
+
/** 도구/서버 이름 */
|
|
9
|
+
source?: string;
|
|
10
|
+
/** 요청 ID (추적용) */
|
|
11
|
+
requestId?: string;
|
|
12
|
+
/** 추가 데이터 */
|
|
13
|
+
data?: Record<string, any>;
|
|
14
|
+
/** 에러 객체 */
|
|
15
|
+
error?: {
|
|
16
|
+
name: string;
|
|
17
|
+
message: string;
|
|
18
|
+
stack?: string;
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
/** 포매터 인터페이스 */
|
|
22
|
+
export interface LogFormatter {
|
|
23
|
+
format(entry: LogEntry): string;
|
|
24
|
+
}
|
|
25
|
+
/** 트랜스포트 인터페이스 */
|
|
26
|
+
export interface LogTransport {
|
|
27
|
+
name: string;
|
|
28
|
+
write(formatted: string, entry: LogEntry): void | Promise<void>;
|
|
29
|
+
close?(): void | Promise<void>;
|
|
30
|
+
}
|
|
31
|
+
/** 로거 설정 */
|
|
32
|
+
export interface LoggerConfig {
|
|
33
|
+
/** 최소 출력 레벨 */
|
|
34
|
+
level?: LogLevel;
|
|
35
|
+
/** 포매터 ('json' | 'pretty' | 커스텀) */
|
|
36
|
+
formatter?: 'json' | 'pretty' | LogFormatter;
|
|
37
|
+
/** 트랜스포트 목록 */
|
|
38
|
+
transports?: LogTransport[];
|
|
39
|
+
/** 소스 이름 (도구/서버 식별) */
|
|
40
|
+
source?: string;
|
|
41
|
+
}
|
|
42
|
+
/** 레벨 우선순위 (숫자가 높을수록 심각) */
|
|
43
|
+
export declare const LOG_LEVEL_PRIORITY: Record<LogLevel, number>;
|
|
44
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAGA,YAAY;AACZ,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,CAAC;AAErE,aAAa;AACb,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,QAAQ,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,IAAI,CAAC;IAChB,eAAe;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,kBAAkB;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa;IACb,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC3B,YAAY;IACZ,KAAK,CAAC,EAAE;QACN,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,CAAC;QAChB,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,CAAC;CACH;AAED,gBAAgB;AAChB,MAAM,WAAW,YAAY;IAC3B,MAAM,CAAC,KAAK,EAAE,QAAQ,GAAG,MAAM,CAAC;CACjC;AAED,kBAAkB;AAClB,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAChE,KAAK,CAAC,IAAI,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAChC;AAED,YAAY;AACZ,MAAM,WAAW,YAAY;IAC3B,eAAe;IACf,KAAK,CAAC,EAAE,QAAQ,CAAC;IACjB,oCAAoC;IACpC,SAAS,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,YAAY,CAAC;IAC7C,eAAe;IACf,UAAU,CAAC,EAAE,YAAY,EAAE,CAAC;IAC5B,uBAAuB;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,4BAA4B;AAC5B,eAAO,MAAM,kBAAkB,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,CAMvD,CAAC"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// Copyright 2026 CodePedia Labs. Licensed under Apache-2.0.
|
|
2
|
+
// @airmcp-dev/logger — types.ts
|
|
3
|
+
/** 레벨 우선순위 (숫자가 높을수록 심각) */
|
|
4
|
+
export const LOG_LEVEL_PRIORITY = {
|
|
5
|
+
debug: 0,
|
|
6
|
+
info: 1,
|
|
7
|
+
warn: 2,
|
|
8
|
+
error: 3,
|
|
9
|
+
fatal: 4,
|
|
10
|
+
};
|
|
11
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,gCAAgC;AAgDhC,4BAA4B;AAC5B,MAAM,CAAC,MAAM,kBAAkB,GAA6B;IAC1D,KAAK,EAAE,CAAC;IACR,IAAI,EAAE,CAAC;IACP,IAAI,EAAE,CAAC;IACP,KAAK,EAAE,CAAC;IACR,KAAK,EAAE,CAAC;CACT,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@airmcp-dev/logger",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Structured logging for MCP servers — JSON, pretty, file, remote transport",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"files": ["dist", "README.md", "LICENSE"],
|
|
7
|
+
"main": "dist/index.js",
|
|
8
|
+
"types": "dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": "./dist/index.js"
|
|
11
|
+
},
|
|
12
|
+
"scripts": {
|
|
13
|
+
"build": "tsc",
|
|
14
|
+
"test": "vitest run",
|
|
15
|
+
"lint": "tsc --noEmit"
|
|
16
|
+
},
|
|
17
|
+
"dependencies": {
|
|
18
|
+
"@airmcp-dev/core": "^0.1.0"
|
|
19
|
+
},
|
|
20
|
+
"devDependencies": {
|
|
21
|
+
"typescript": "^5.5.0",
|
|
22
|
+
"vitest": "^2.0.0",
|
|
23
|
+
"@types/node": "^20.0.0"
|
|
24
|
+
},
|
|
25
|
+
"author": "CodePedia Labs",
|
|
26
|
+
"homepage": "https://airmcp.dev",
|
|
27
|
+
"bugs": { "url": "https://github.com/airmcp-dev/air/issues" },
|
|
28
|
+
"repository": { "type": "git", "url": "https://github.com/airmcp-dev/air", "directory": "packages/logger" },
|
|
29
|
+
"keywords": ["mcp", "ai", "agent", "air"],
|
|
30
|
+
"license": "Apache-2.0"
|
|
31
|
+
}
|