@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.
Files changed (42) hide show
  1. package/LICENSE +17 -0
  2. package/dist/formatter/index.d.ts +3 -0
  3. package/dist/formatter/index.d.ts.map +1 -0
  4. package/dist/formatter/index.js +5 -0
  5. package/dist/formatter/index.js.map +1 -0
  6. package/dist/formatter/json.d.ts +5 -0
  7. package/dist/formatter/json.d.ts.map +1 -0
  8. package/dist/formatter/json.js +29 -0
  9. package/dist/formatter/json.js.map +1 -0
  10. package/dist/formatter/pretty.d.ts +5 -0
  11. package/dist/formatter/pretty.d.ts.map +1 -0
  12. package/dist/formatter/pretty.js +35 -0
  13. package/dist/formatter/pretty.js.map +1 -0
  14. package/dist/index.d.ts +9 -0
  15. package/dist/index.d.ts.map +1 -0
  16. package/dist/index.js +13 -0
  17. package/dist/index.js.map +1 -0
  18. package/dist/logger.d.ts +27 -0
  19. package/dist/logger.d.ts.map +1 -0
  20. package/dist/logger.js +103 -0
  21. package/dist/logger.js.map +1 -0
  22. package/dist/transport/console.d.ts +6 -0
  23. package/dist/transport/console.d.ts.map +1 -0
  24. package/dist/transport/console.js +16 -0
  25. package/dist/transport/console.js.map +1 -0
  26. package/dist/transport/file.d.ts +22 -0
  27. package/dist/transport/file.d.ts.map +1 -0
  28. package/dist/transport/file.js +67 -0
  29. package/dist/transport/file.js.map +1 -0
  30. package/dist/transport/index.d.ts +6 -0
  31. package/dist/transport/index.d.ts.map +1 -0
  32. package/dist/transport/index.js +6 -0
  33. package/dist/transport/index.js.map +1 -0
  34. package/dist/transport/remote.d.ts +24 -0
  35. package/dist/transport/remote.d.ts.map +1 -0
  36. package/dist/transport/remote.js +54 -0
  37. package/dist/transport/remote.js.map +1 -0
  38. package/dist/types.d.ts +44 -0
  39. package/dist/types.d.ts.map +1 -0
  40. package/dist/types.js +11 -0
  41. package/dist/types.js.map +1 -0
  42. 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,3 @@
1
+ export { JsonFormatter } from './json.js';
2
+ export { PrettyFormatter } from './pretty.js';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -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,5 @@
1
+ // Copyright 2026 CodePedia Labs. Licensed under Apache-2.0.
2
+ // @airmcp-dev/logger — formatter/index.ts
3
+ export { JsonFormatter } from './json.js';
4
+ export { PrettyFormatter } from './pretty.js';
5
+ //# sourceMappingURL=index.js.map
@@ -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,5 @@
1
+ import type { LogEntry, LogFormatter } from '../types.js';
2
+ export declare class JsonFormatter implements LogFormatter {
3
+ format(entry: LogEntry): string;
4
+ }
5
+ //# sourceMappingURL=json.d.ts.map
@@ -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,5 @@
1
+ import type { LogEntry, LogFormatter } from '../types.js';
2
+ export declare class PrettyFormatter implements LogFormatter {
3
+ format(entry: LogEntry): string;
4
+ }
5
+ //# sourceMappingURL=pretty.d.ts.map
@@ -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"}
@@ -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"}
@@ -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":"AAAA,4DAA4D;AAC5D,iCAAiC;AACjC,EAAE;AACF,6BAA6B;AAC7B,iCAAiC;AACjC,EAAE;AACF,WAAW;AACX,0EAA0E;AAC1E,mDAAmD;AACnD,4DAA4D;AAG5D,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAE1D,MAAM,OAAO,SAAS;IACZ,KAAK,CAAW;IAChB,SAAS,CAAe;IACxB,UAAU,CAAiB;IAC3B,MAAM,CAAU;IAExB,YAAY,MAAqB;QAC/B,IAAI,CAAC,KAAK,GAAG,MAAM,EAAE,KAAK,IAAI,MAAM,CAAC;QACrC,IAAI,CAAC,MAAM,GAAG,MAAM,EAAE,MAAM,CAAC;QAE7B,SAAS;QACT,IAAI,CAAC,MAAM,EAAE,SAAS,IAAI,MAAM,CAAC,SAAS,KAAK,MAAM,EAAE,CAAC;YACtD,IAAI,CAAC,SAAS,GAAG,IAAI,aAAa,EAAE,CAAC;QACvC,CAAC;aAAM,IAAI,MAAM,CAAC,SAAS,KAAK,QAAQ,EAAE,CAAC;YACzC,IAAI,CAAC,SAAS,GAAG,IAAI,eAAe,EAAE,CAAC;QACzC,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,SAAS,GAAG,MAAM,CAAC,SAAS,CAAC;QACpC,CAAC;QAED,sBAAsB;QACtB,IAAI,CAAC,UAAU,GAAG,MAAM,EAAE,UAAU,IAAI,CAAC,IAAI,gBAAgB,EAAE,CAAC,CAAC;IACnE,CAAC;IAED,KAAK,CAAC,OAAe,EAAE,IAA0B;QAC/C,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;IACnC,CAAC;IAED,IAAI,CAAC,OAAe,EAAE,IAA0B;QAC9C,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;IAClC,CAAC;IAED,IAAI,CAAC,OAAe,EAAE,IAA0B;QAC9C,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;IAClC,CAAC;IAED,KAAK,CAAC,OAAe,EAAE,IAA0B,EAAE,GAAW;QAC5D,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC;IACxC,CAAC;IAED,KAAK,CAAC,OAAe,EAAE,IAA0B,EAAE,GAAW;QAC5D,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC;IACxC,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,MAAc;QAClB,MAAM,KAAK,GAAG,IAAI,SAAS,CAAC;YAC1B,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,MAAM;YACN,UAAU,EAAE,IAAI,CAAC,UAAU;SAC5B,CAAC,CAAC;QACH,SAAS;QACR,KAAa,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC;QAC1C,OAAO,KAAK,CAAC;IACf,CAAC;IAED;;OAEG;IACH,YAAY,CAAC,SAAuB;QAClC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAClC,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,KAAK;QACT,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YAChC,IAAI,CAAC,CAAC,KAAK;gBAAE,MAAM,CAAC,CAAC,KAAK,EAAE,CAAC;QAC/B,CAAC;IACH,CAAC;IAEO,GAAG,CAAC,KAAe,EAAE,OAAe,EAAE,IAA0B,EAAE,GAAW;QACnF,SAAS;QACT,IAAI,kBAAkB,CAAC,KAAK,CAAC,GAAG,kBAAkB,CAAC,IAAI,CAAC,KAAK,CAAC;YAAE,OAAO;QAEvE,MAAM,KAAK,GAAa;YACtB,KAAK;YACL,OAAO;YACP,SAAS,EAAE,IAAI,IAAI,EAAE;YACrB,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,IAAI;SACL,CAAC;QAEF,IAAI,GAAG,EAAE,CAAC;YACR,KAAK,CAAC,KAAK,GAAG;gBACZ,IAAI,EAAE,GAAG,CAAC,IAAI;gBACd,OAAO,EAAE,GAAG,CAAC,OAAO;gBACpB,KAAK,EAAE,GAAG,CAAC,KAAK;aACjB,CAAC;QACJ,CAAC;QAED,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAE/C,KAAK,MAAM,SAAS,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACxC,SAAS,CAAC,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;QACpC,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,6 @@
1
+ import type { LogEntry, LogTransport } from '../types.js';
2
+ export declare class ConsoleTransport implements LogTransport {
3
+ name: string;
4
+ write(formatted: string, entry: LogEntry): void;
5
+ }
6
+ //# sourceMappingURL=console.d.ts.map
@@ -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"}
@@ -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
+ }