@enactprotocol/shared 1.2.13 → 2.0.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/README.md +44 -0
- package/package.json +16 -58
- package/src/config.ts +476 -0
- package/src/constants.ts +36 -0
- package/src/execution/command.ts +314 -0
- package/src/execution/index.ts +73 -0
- package/src/execution/runtime.ts +308 -0
- package/src/execution/types.ts +379 -0
- package/src/execution/validation.ts +508 -0
- package/src/index.ts +237 -30
- package/src/manifest/index.ts +36 -0
- package/src/manifest/loader.ts +187 -0
- package/src/manifest/parser.ts +173 -0
- package/src/manifest/validator.ts +309 -0
- package/src/paths.ts +108 -0
- package/src/registry.ts +219 -0
- package/src/resolver.ts +345 -0
- package/src/types/index.ts +30 -0
- package/src/types/manifest.ts +255 -0
- package/src/types.ts +5 -188
- package/src/utils/fs.ts +281 -0
- package/src/utils/logger.ts +270 -59
- package/src/utils/version.ts +304 -36
- package/tests/config.test.ts +515 -0
- package/tests/execution/command.test.ts +317 -0
- package/tests/execution/validation.test.ts +384 -0
- package/tests/fixtures/invalid-tool.yaml +4 -0
- package/tests/fixtures/valid-tool.md +62 -0
- package/tests/fixtures/valid-tool.yaml +40 -0
- package/tests/index.test.ts +8 -0
- package/tests/manifest/loader.test.ts +291 -0
- package/tests/manifest/parser.test.ts +345 -0
- package/tests/manifest/validator.test.ts +394 -0
- package/tests/manifest-types.test.ts +358 -0
- package/tests/paths.test.ts +153 -0
- package/tests/registry.test.ts +231 -0
- package/tests/resolver.test.ts +272 -0
- package/tests/utils/fs.test.ts +388 -0
- package/tests/utils/logger.test.ts +480 -0
- package/tests/utils/version.test.ts +390 -0
- package/tsconfig.json +12 -0
- package/tsconfig.tsbuildinfo +1 -0
- package/dist/LocalToolResolver.d.ts +0 -84
- package/dist/LocalToolResolver.js +0 -353
- package/dist/api/enact-api.d.ts +0 -130
- package/dist/api/enact-api.js +0 -428
- package/dist/api/index.d.ts +0 -2
- package/dist/api/index.js +0 -2
- package/dist/api/types.d.ts +0 -103
- package/dist/api/types.js +0 -1
- package/dist/constants.d.ts +0 -7
- package/dist/constants.js +0 -10
- package/dist/core/DaggerExecutionProvider.d.ts +0 -169
- package/dist/core/DaggerExecutionProvider.js +0 -1029
- package/dist/core/DirectExecutionProvider.d.ts +0 -23
- package/dist/core/DirectExecutionProvider.js +0 -406
- package/dist/core/EnactCore.d.ts +0 -162
- package/dist/core/EnactCore.js +0 -597
- package/dist/core/NativeExecutionProvider.d.ts +0 -9
- package/dist/core/NativeExecutionProvider.js +0 -16
- package/dist/core/index.d.ts +0 -3
- package/dist/core/index.js +0 -3
- package/dist/exec/index.d.ts +0 -3
- package/dist/exec/index.js +0 -3
- package/dist/exec/logger.d.ts +0 -11
- package/dist/exec/logger.js +0 -57
- package/dist/exec/validate.d.ts +0 -5
- package/dist/exec/validate.js +0 -167
- package/dist/index.d.ts +0 -21
- package/dist/index.js +0 -25
- package/dist/lib/enact-direct.d.ts +0 -150
- package/dist/lib/enact-direct.js +0 -159
- package/dist/lib/index.d.ts +0 -1
- package/dist/lib/index.js +0 -1
- package/dist/security/index.d.ts +0 -3
- package/dist/security/index.js +0 -3
- package/dist/security/security.d.ts +0 -23
- package/dist/security/security.js +0 -137
- package/dist/security/sign.d.ts +0 -103
- package/dist/security/sign.js +0 -666
- package/dist/security/verification-enforcer.d.ts +0 -53
- package/dist/security/verification-enforcer.js +0 -204
- package/dist/services/McpCoreService.d.ts +0 -98
- package/dist/services/McpCoreService.js +0 -124
- package/dist/services/index.d.ts +0 -1
- package/dist/services/index.js +0 -1
- package/dist/types.d.ts +0 -132
- package/dist/types.js +0 -3
- package/dist/utils/config.d.ts +0 -111
- package/dist/utils/config.js +0 -342
- package/dist/utils/env-loader.d.ts +0 -54
- package/dist/utils/env-loader.js +0 -270
- package/dist/utils/help.d.ts +0 -36
- package/dist/utils/help.js +0 -248
- package/dist/utils/index.d.ts +0 -7
- package/dist/utils/index.js +0 -7
- package/dist/utils/logger.d.ts +0 -35
- package/dist/utils/logger.js +0 -75
- package/dist/utils/silent-monitor.d.ts +0 -67
- package/dist/utils/silent-monitor.js +0 -242
- package/dist/utils/timeout.d.ts +0 -5
- package/dist/utils/timeout.js +0 -23
- package/dist/utils/version.d.ts +0 -4
- package/dist/utils/version.js +0 -35
- package/dist/web/env-manager-server.d.ts +0 -29
- package/dist/web/env-manager-server.js +0 -367
- package/dist/web/index.d.ts +0 -1
- package/dist/web/index.js +0 -1
- package/src/LocalToolResolver.ts +0 -424
- package/src/api/enact-api.ts +0 -604
- package/src/api/index.ts +0 -2
- package/src/api/types.ts +0 -114
- package/src/core/DaggerExecutionProvider.ts +0 -1357
- package/src/core/DirectExecutionProvider.ts +0 -484
- package/src/core/EnactCore.ts +0 -847
- package/src/core/index.ts +0 -3
- package/src/exec/index.ts +0 -3
- package/src/exec/logger.ts +0 -63
- package/src/exec/validate.ts +0 -238
- package/src/lib/enact-direct.ts +0 -254
- package/src/lib/index.ts +0 -1
- package/src/services/McpCoreService.ts +0 -201
- package/src/services/index.ts +0 -1
- package/src/utils/config.ts +0 -438
- package/src/utils/env-loader.ts +0 -370
- package/src/utils/help.ts +0 -257
- package/src/utils/index.ts +0 -7
- package/src/utils/silent-monitor.ts +0 -328
- package/src/utils/timeout.ts +0 -26
- package/src/web/env-manager-server.ts +0 -465
- package/src/web/index.ts +0 -1
- package/src/web/static/app.js +0 -663
- package/src/web/static/index.html +0 -117
- package/src/web/static/style.css +0 -291
|
@@ -0,0 +1,480 @@
|
|
|
1
|
+
import { describe, expect, test } from "bun:test";
|
|
2
|
+
import { Logger, configureLogger, createLogger, getLogger } from "../../src/utils/logger";
|
|
3
|
+
|
|
4
|
+
/** Helper to parse JSON from output array */
|
|
5
|
+
function parseOutput(output: string[], index: number): Record<string, unknown> {
|
|
6
|
+
const item = output[index];
|
|
7
|
+
if (item === undefined) {
|
|
8
|
+
throw new Error(`No output at index ${index}`);
|
|
9
|
+
}
|
|
10
|
+
return JSON.parse(item) as Record<string, unknown>;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/** Helper to get output at index */
|
|
14
|
+
function getOutput(output: string[], index: number): string {
|
|
15
|
+
const item = output[index];
|
|
16
|
+
if (item === undefined) {
|
|
17
|
+
throw new Error(`No output at index ${index}`);
|
|
18
|
+
}
|
|
19
|
+
return item;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
describe("Logger", () => {
|
|
23
|
+
describe("constructor and options", () => {
|
|
24
|
+
test("creates logger with default options", () => {
|
|
25
|
+
const logger = new Logger();
|
|
26
|
+
expect(logger.getLevel()).toBe("info");
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
test("creates logger with custom level", () => {
|
|
30
|
+
const logger = new Logger({ level: "debug" });
|
|
31
|
+
expect(logger.getLevel()).toBe("debug");
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
test("creates logger with custom format", () => {
|
|
35
|
+
const output: string[] = [];
|
|
36
|
+
const logger = new Logger({
|
|
37
|
+
format: "json",
|
|
38
|
+
output: (text) => output.push(text),
|
|
39
|
+
});
|
|
40
|
+
logger.info("test");
|
|
41
|
+
expect(output.length).toBe(1);
|
|
42
|
+
const parsed = parseOutput(output, 0);
|
|
43
|
+
expect(parsed.level).toBe("info");
|
|
44
|
+
expect(parsed.message).toBe("test");
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
test("creates logger with prefix", () => {
|
|
48
|
+
const output: string[] = [];
|
|
49
|
+
const logger = new Logger({
|
|
50
|
+
prefix: "MyModule",
|
|
51
|
+
format: "json",
|
|
52
|
+
output: (text) => output.push(text),
|
|
53
|
+
});
|
|
54
|
+
logger.info("test");
|
|
55
|
+
const parsed = parseOutput(output, 0);
|
|
56
|
+
expect(parsed.message).toBe("[MyModule] test");
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
describe("level filtering", () => {
|
|
61
|
+
test("logs messages at or above current level", () => {
|
|
62
|
+
const output: string[] = [];
|
|
63
|
+
const logger = new Logger({
|
|
64
|
+
level: "warn",
|
|
65
|
+
format: "json",
|
|
66
|
+
output: (text) => output.push(text),
|
|
67
|
+
errorOutput: (text) => output.push(text),
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
logger.debug("debug msg");
|
|
71
|
+
logger.info("info msg");
|
|
72
|
+
logger.warn("warn msg");
|
|
73
|
+
logger.error("error msg");
|
|
74
|
+
|
|
75
|
+
expect(output.length).toBe(2); // only warn and error
|
|
76
|
+
expect(getOutput(output, 0)).toContain("warn msg");
|
|
77
|
+
expect(getOutput(output, 1)).toContain("error msg");
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
test("silent level suppresses all output", () => {
|
|
81
|
+
const output: string[] = [];
|
|
82
|
+
const logger = new Logger({
|
|
83
|
+
level: "silent",
|
|
84
|
+
output: (text) => output.push(text),
|
|
85
|
+
errorOutput: (text) => output.push(text),
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
logger.debug("debug");
|
|
89
|
+
logger.info("info");
|
|
90
|
+
logger.warn("warn");
|
|
91
|
+
logger.error("error");
|
|
92
|
+
|
|
93
|
+
expect(output.length).toBe(0);
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
test("debug level logs everything", () => {
|
|
97
|
+
const output: string[] = [];
|
|
98
|
+
const logger = new Logger({
|
|
99
|
+
level: "debug",
|
|
100
|
+
format: "json",
|
|
101
|
+
output: (text) => output.push(text),
|
|
102
|
+
errorOutput: (text) => output.push(text),
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
logger.debug("debug");
|
|
106
|
+
logger.info("info");
|
|
107
|
+
logger.warn("warn");
|
|
108
|
+
logger.error("error");
|
|
109
|
+
|
|
110
|
+
expect(output.length).toBe(4);
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
test("setLevel changes filtering", () => {
|
|
114
|
+
const output: string[] = [];
|
|
115
|
+
const logger = new Logger({
|
|
116
|
+
level: "info",
|
|
117
|
+
format: "json",
|
|
118
|
+
output: (text) => output.push(text),
|
|
119
|
+
errorOutput: (text) => output.push(text),
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
logger.debug("should not appear");
|
|
123
|
+
expect(output.length).toBe(0);
|
|
124
|
+
|
|
125
|
+
logger.setLevel("debug");
|
|
126
|
+
logger.debug("should appear");
|
|
127
|
+
expect(output.length).toBe(1);
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
test("shouldLog returns correct boolean", () => {
|
|
131
|
+
const logger = new Logger({ level: "warn" });
|
|
132
|
+
expect(logger.shouldLog("debug")).toBe(false);
|
|
133
|
+
expect(logger.shouldLog("info")).toBe(false);
|
|
134
|
+
expect(logger.shouldLog("warn")).toBe(true);
|
|
135
|
+
expect(logger.shouldLog("error")).toBe(true);
|
|
136
|
+
});
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
describe("output formats", () => {
|
|
140
|
+
test("JSON format outputs valid JSON", () => {
|
|
141
|
+
const output: string[] = [];
|
|
142
|
+
const logger = new Logger({
|
|
143
|
+
format: "json",
|
|
144
|
+
output: (text) => output.push(text),
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
logger.info("test message");
|
|
148
|
+
|
|
149
|
+
const parsed = parseOutput(output, 0);
|
|
150
|
+
expect(parsed.level).toBe("info");
|
|
151
|
+
expect(parsed.message).toBe("test message");
|
|
152
|
+
expect(parsed.timestamp).toBeDefined();
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
test("JSON format includes context", () => {
|
|
156
|
+
const output: string[] = [];
|
|
157
|
+
const logger = new Logger({
|
|
158
|
+
format: "json",
|
|
159
|
+
output: (text) => output.push(text),
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
logger.info("test", { userId: 123, action: "login" });
|
|
163
|
+
|
|
164
|
+
const parsed = parseOutput(output, 0);
|
|
165
|
+
expect(parsed.context).toEqual({ userId: 123, action: "login" });
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
test("JSON format omits empty context", () => {
|
|
169
|
+
const output: string[] = [];
|
|
170
|
+
const logger = new Logger({
|
|
171
|
+
format: "json",
|
|
172
|
+
output: (text) => output.push(text),
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
logger.info("test");
|
|
176
|
+
|
|
177
|
+
const parsed = parseOutput(output, 0);
|
|
178
|
+
expect(parsed.context).toBeUndefined();
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
test("console format includes timestamp and level", () => {
|
|
182
|
+
const output: string[] = [];
|
|
183
|
+
const logger = new Logger({
|
|
184
|
+
format: "console",
|
|
185
|
+
colors: false,
|
|
186
|
+
output: (text) => output.push(text),
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
logger.info("test message");
|
|
190
|
+
|
|
191
|
+
const out = getOutput(output, 0);
|
|
192
|
+
expect(out).toContain("INFO");
|
|
193
|
+
expect(out).toContain("test message");
|
|
194
|
+
// Should have ISO timestamp
|
|
195
|
+
expect(out).toMatch(/\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/);
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
test("console format with colors includes ANSI codes", () => {
|
|
199
|
+
const output: string[] = [];
|
|
200
|
+
const logger = new Logger({
|
|
201
|
+
format: "console",
|
|
202
|
+
colors: true,
|
|
203
|
+
output: (text) => output.push(text),
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
logger.info("test");
|
|
207
|
+
|
|
208
|
+
// Should contain ANSI escape codes
|
|
209
|
+
expect(getOutput(output, 0)).toContain("\x1b[");
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
test("console format without colors has no ANSI codes", () => {
|
|
213
|
+
const output: string[] = [];
|
|
214
|
+
const logger = new Logger({
|
|
215
|
+
format: "console",
|
|
216
|
+
colors: false,
|
|
217
|
+
output: (text) => output.push(text),
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
logger.info("test");
|
|
221
|
+
|
|
222
|
+
expect(getOutput(output, 0)).not.toContain("\x1b[");
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
test("setFormat changes output format", () => {
|
|
226
|
+
const output: string[] = [];
|
|
227
|
+
const logger = new Logger({
|
|
228
|
+
format: "console",
|
|
229
|
+
colors: false,
|
|
230
|
+
output: (text) => output.push(text),
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
logger.info("console");
|
|
234
|
+
logger.setFormat("json");
|
|
235
|
+
logger.info("json");
|
|
236
|
+
|
|
237
|
+
// First message is console format (not valid JSON)
|
|
238
|
+
expect(() => JSON.parse(getOutput(output, 0))).toThrow();
|
|
239
|
+
// Second message is JSON
|
|
240
|
+
expect(parseOutput(output, 1).message).toBe("json");
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
test("setColors enables/disables colors", () => {
|
|
244
|
+
const output: string[] = [];
|
|
245
|
+
const logger = new Logger({
|
|
246
|
+
format: "console",
|
|
247
|
+
colors: true,
|
|
248
|
+
output: (text) => output.push(text),
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
logger.info("with colors");
|
|
252
|
+
logger.setColors(false);
|
|
253
|
+
logger.info("no colors");
|
|
254
|
+
|
|
255
|
+
expect(getOutput(output, 0)).toContain("\x1b[");
|
|
256
|
+
expect(getOutput(output, 1)).not.toContain("\x1b[");
|
|
257
|
+
});
|
|
258
|
+
});
|
|
259
|
+
|
|
260
|
+
describe("error output routing", () => {
|
|
261
|
+
test("warn and error use errorOutput", () => {
|
|
262
|
+
const stdout: string[] = [];
|
|
263
|
+
const stderr: string[] = [];
|
|
264
|
+
const logger = new Logger({
|
|
265
|
+
level: "debug",
|
|
266
|
+
format: "json",
|
|
267
|
+
output: (text) => stdout.push(text),
|
|
268
|
+
errorOutput: (text) => stderr.push(text),
|
|
269
|
+
});
|
|
270
|
+
|
|
271
|
+
logger.debug("debug");
|
|
272
|
+
logger.info("info");
|
|
273
|
+
logger.warn("warn");
|
|
274
|
+
logger.error("error");
|
|
275
|
+
|
|
276
|
+
expect(stdout.length).toBe(2); // debug, info
|
|
277
|
+
expect(stderr.length).toBe(2); // warn, error
|
|
278
|
+
});
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
describe("child loggers", () => {
|
|
282
|
+
test("child logger inherits settings", () => {
|
|
283
|
+
const output: string[] = [];
|
|
284
|
+
const parent = new Logger({
|
|
285
|
+
level: "debug",
|
|
286
|
+
format: "json",
|
|
287
|
+
output: (text) => output.push(text),
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
const child = parent.child("SubModule");
|
|
291
|
+
child.info("test");
|
|
292
|
+
|
|
293
|
+
const parsed = parseOutput(output, 0);
|
|
294
|
+
expect(parsed.message).toBe("[SubModule] test");
|
|
295
|
+
});
|
|
296
|
+
|
|
297
|
+
test("child logger chains prefixes", () => {
|
|
298
|
+
const output: string[] = [];
|
|
299
|
+
const parent = new Logger({
|
|
300
|
+
level: "debug",
|
|
301
|
+
format: "json",
|
|
302
|
+
prefix: "Parent",
|
|
303
|
+
output: (text) => output.push(text),
|
|
304
|
+
});
|
|
305
|
+
|
|
306
|
+
const child = parent.child("Child");
|
|
307
|
+
child.info("test");
|
|
308
|
+
|
|
309
|
+
const parsed = parseOutput(output, 0);
|
|
310
|
+
expect(parsed.message).toBe("[Parent:Child] test");
|
|
311
|
+
});
|
|
312
|
+
|
|
313
|
+
test("setPrefix changes prefix", () => {
|
|
314
|
+
const output: string[] = [];
|
|
315
|
+
const logger = new Logger({
|
|
316
|
+
format: "json",
|
|
317
|
+
output: (text) => output.push(text),
|
|
318
|
+
});
|
|
319
|
+
|
|
320
|
+
logger.info("no prefix");
|
|
321
|
+
logger.setPrefix("NewPrefix");
|
|
322
|
+
logger.info("with prefix");
|
|
323
|
+
|
|
324
|
+
const msg1 = parseOutput(output, 0).message;
|
|
325
|
+
const msg2 = parseOutput(output, 1).message;
|
|
326
|
+
expect(msg1).toBe("no prefix");
|
|
327
|
+
expect(msg2).toBe("[NewPrefix] with prefix");
|
|
328
|
+
});
|
|
329
|
+
});
|
|
330
|
+
|
|
331
|
+
describe("structured context", () => {
|
|
332
|
+
test("context is included in JSON output", () => {
|
|
333
|
+
const output: string[] = [];
|
|
334
|
+
const logger = new Logger({
|
|
335
|
+
format: "json",
|
|
336
|
+
output: (text) => output.push(text),
|
|
337
|
+
});
|
|
338
|
+
|
|
339
|
+
logger.info("user action", {
|
|
340
|
+
userId: "u123",
|
|
341
|
+
action: "login",
|
|
342
|
+
success: true,
|
|
343
|
+
duration: 150,
|
|
344
|
+
});
|
|
345
|
+
|
|
346
|
+
const parsed = parseOutput(output, 0);
|
|
347
|
+
expect(parsed.context).toEqual({
|
|
348
|
+
userId: "u123",
|
|
349
|
+
action: "login",
|
|
350
|
+
success: true,
|
|
351
|
+
duration: 150,
|
|
352
|
+
});
|
|
353
|
+
});
|
|
354
|
+
|
|
355
|
+
test("context is included in console output", () => {
|
|
356
|
+
const output: string[] = [];
|
|
357
|
+
const logger = new Logger({
|
|
358
|
+
format: "console",
|
|
359
|
+
colors: false,
|
|
360
|
+
output: (text) => output.push(text),
|
|
361
|
+
});
|
|
362
|
+
|
|
363
|
+
logger.info("test", { key: "value" });
|
|
364
|
+
|
|
365
|
+
expect(getOutput(output, 0)).toContain('{"key":"value"}');
|
|
366
|
+
});
|
|
367
|
+
|
|
368
|
+
test("nested context is supported", () => {
|
|
369
|
+
const output: string[] = [];
|
|
370
|
+
const logger = new Logger({
|
|
371
|
+
format: "json",
|
|
372
|
+
output: (text) => output.push(text),
|
|
373
|
+
});
|
|
374
|
+
|
|
375
|
+
logger.info("nested", {
|
|
376
|
+
user: { id: 1, name: "test" },
|
|
377
|
+
tags: ["a", "b"],
|
|
378
|
+
});
|
|
379
|
+
|
|
380
|
+
const parsed = parseOutput(output, 0);
|
|
381
|
+
const context = parsed.context as Record<string, unknown>;
|
|
382
|
+
expect(context.user).toEqual({ id: 1, name: "test" });
|
|
383
|
+
expect(context.tags).toEqual(["a", "b"]);
|
|
384
|
+
});
|
|
385
|
+
});
|
|
386
|
+
|
|
387
|
+
describe("convenience functions", () => {
|
|
388
|
+
test("createLogger creates new instance", () => {
|
|
389
|
+
const logger = createLogger({ level: "debug" });
|
|
390
|
+
expect(logger).toBeInstanceOf(Logger);
|
|
391
|
+
expect(logger.getLevel()).toBe("debug");
|
|
392
|
+
});
|
|
393
|
+
|
|
394
|
+
test("getLogger returns singleton", () => {
|
|
395
|
+
const logger1 = getLogger();
|
|
396
|
+
const logger2 = getLogger();
|
|
397
|
+
expect(logger1).toBe(logger2);
|
|
398
|
+
});
|
|
399
|
+
|
|
400
|
+
test("configureLogger updates singleton", () => {
|
|
401
|
+
configureLogger({ level: "error" });
|
|
402
|
+
const newLogger = getLogger();
|
|
403
|
+
expect(newLogger.getLevel()).toBe("error");
|
|
404
|
+
// Restore to info for other tests
|
|
405
|
+
configureLogger({ level: "info" });
|
|
406
|
+
});
|
|
407
|
+
});
|
|
408
|
+
|
|
409
|
+
describe("level-specific methods", () => {
|
|
410
|
+
test("debug method logs at debug level", () => {
|
|
411
|
+
const output: string[] = [];
|
|
412
|
+
const logger = new Logger({
|
|
413
|
+
level: "debug",
|
|
414
|
+
format: "json",
|
|
415
|
+
output: (text) => output.push(text),
|
|
416
|
+
});
|
|
417
|
+
|
|
418
|
+
logger.debug("debug message");
|
|
419
|
+
const parsed = parseOutput(output, 0);
|
|
420
|
+
expect(parsed.level).toBe("debug");
|
|
421
|
+
});
|
|
422
|
+
|
|
423
|
+
test("info method logs at info level", () => {
|
|
424
|
+
const output: string[] = [];
|
|
425
|
+
const logger = new Logger({
|
|
426
|
+
level: "debug",
|
|
427
|
+
format: "json",
|
|
428
|
+
output: (text) => output.push(text),
|
|
429
|
+
});
|
|
430
|
+
|
|
431
|
+
logger.info("info message");
|
|
432
|
+
const parsed = parseOutput(output, 0);
|
|
433
|
+
expect(parsed.level).toBe("info");
|
|
434
|
+
});
|
|
435
|
+
|
|
436
|
+
test("warn method logs at warn level", () => {
|
|
437
|
+
const output: string[] = [];
|
|
438
|
+
const logger = new Logger({
|
|
439
|
+
level: "debug",
|
|
440
|
+
format: "json",
|
|
441
|
+
errorOutput: (text) => output.push(text),
|
|
442
|
+
});
|
|
443
|
+
|
|
444
|
+
logger.warn("warn message");
|
|
445
|
+
const parsed = parseOutput(output, 0);
|
|
446
|
+
expect(parsed.level).toBe("warn");
|
|
447
|
+
});
|
|
448
|
+
|
|
449
|
+
test("error method logs at error level", () => {
|
|
450
|
+
const output: string[] = [];
|
|
451
|
+
const logger = new Logger({
|
|
452
|
+
level: "debug",
|
|
453
|
+
format: "json",
|
|
454
|
+
errorOutput: (text) => output.push(text),
|
|
455
|
+
});
|
|
456
|
+
|
|
457
|
+
logger.error("error message");
|
|
458
|
+
const parsed = parseOutput(output, 0);
|
|
459
|
+
expect(parsed.level).toBe("error");
|
|
460
|
+
});
|
|
461
|
+
});
|
|
462
|
+
|
|
463
|
+
describe("timestamp format", () => {
|
|
464
|
+
test("timestamp is ISO 8601 format", () => {
|
|
465
|
+
const output: string[] = [];
|
|
466
|
+
const logger = new Logger({
|
|
467
|
+
format: "json",
|
|
468
|
+
output: (text) => output.push(text),
|
|
469
|
+
});
|
|
470
|
+
|
|
471
|
+
logger.info("test");
|
|
472
|
+
const parsed = parseOutput(output, 0);
|
|
473
|
+
|
|
474
|
+
// Should be valid ISO 8601
|
|
475
|
+
const timestamp = parsed.timestamp as string;
|
|
476
|
+
const date = new Date(timestamp);
|
|
477
|
+
expect(date.toISOString()).toBe(timestamp);
|
|
478
|
+
});
|
|
479
|
+
});
|
|
480
|
+
});
|