@enactprotocol/shared 1.2.11 → 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.
Files changed (134) hide show
  1. package/README.md +44 -0
  2. package/package.json +16 -58
  3. package/src/config.ts +476 -0
  4. package/src/constants.ts +36 -0
  5. package/src/execution/command.ts +314 -0
  6. package/src/execution/index.ts +73 -0
  7. package/src/execution/runtime.ts +308 -0
  8. package/src/execution/types.ts +379 -0
  9. package/src/execution/validation.ts +508 -0
  10. package/src/index.ts +237 -30
  11. package/src/manifest/index.ts +36 -0
  12. package/src/manifest/loader.ts +187 -0
  13. package/src/manifest/parser.ts +173 -0
  14. package/src/manifest/validator.ts +309 -0
  15. package/src/paths.ts +108 -0
  16. package/src/registry.ts +219 -0
  17. package/src/resolver.ts +345 -0
  18. package/src/types/index.ts +30 -0
  19. package/src/types/manifest.ts +255 -0
  20. package/src/types.ts +5 -188
  21. package/src/utils/fs.ts +281 -0
  22. package/src/utils/logger.ts +270 -59
  23. package/src/utils/version.ts +304 -36
  24. package/tests/config.test.ts +515 -0
  25. package/tests/execution/command.test.ts +317 -0
  26. package/tests/execution/validation.test.ts +384 -0
  27. package/tests/fixtures/invalid-tool.yaml +4 -0
  28. package/tests/fixtures/valid-tool.md +62 -0
  29. package/tests/fixtures/valid-tool.yaml +40 -0
  30. package/tests/index.test.ts +8 -0
  31. package/tests/manifest/loader.test.ts +291 -0
  32. package/tests/manifest/parser.test.ts +345 -0
  33. package/tests/manifest/validator.test.ts +394 -0
  34. package/tests/manifest-types.test.ts +358 -0
  35. package/tests/paths.test.ts +153 -0
  36. package/tests/registry.test.ts +231 -0
  37. package/tests/resolver.test.ts +272 -0
  38. package/tests/utils/fs.test.ts +388 -0
  39. package/tests/utils/logger.test.ts +480 -0
  40. package/tests/utils/version.test.ts +390 -0
  41. package/tsconfig.json +12 -0
  42. package/tsconfig.tsbuildinfo +1 -0
  43. package/dist/LocalToolResolver.d.ts +0 -84
  44. package/dist/LocalToolResolver.js +0 -353
  45. package/dist/api/enact-api.d.ts +0 -130
  46. package/dist/api/enact-api.js +0 -428
  47. package/dist/api/index.d.ts +0 -2
  48. package/dist/api/index.js +0 -2
  49. package/dist/api/types.d.ts +0 -103
  50. package/dist/api/types.js +0 -1
  51. package/dist/constants.d.ts +0 -7
  52. package/dist/constants.js +0 -10
  53. package/dist/core/DaggerExecutionProvider.d.ts +0 -169
  54. package/dist/core/DaggerExecutionProvider.js +0 -1029
  55. package/dist/core/DirectExecutionProvider.d.ts +0 -23
  56. package/dist/core/DirectExecutionProvider.js +0 -406
  57. package/dist/core/EnactCore.d.ts +0 -162
  58. package/dist/core/EnactCore.js +0 -597
  59. package/dist/core/NativeExecutionProvider.d.ts +0 -9
  60. package/dist/core/NativeExecutionProvider.js +0 -16
  61. package/dist/core/index.d.ts +0 -3
  62. package/dist/core/index.js +0 -3
  63. package/dist/exec/index.d.ts +0 -3
  64. package/dist/exec/index.js +0 -3
  65. package/dist/exec/logger.d.ts +0 -11
  66. package/dist/exec/logger.js +0 -57
  67. package/dist/exec/validate.d.ts +0 -5
  68. package/dist/exec/validate.js +0 -167
  69. package/dist/index.d.ts +0 -21
  70. package/dist/index.js +0 -25
  71. package/dist/lib/enact-direct.d.ts +0 -150
  72. package/dist/lib/enact-direct.js +0 -159
  73. package/dist/lib/index.d.ts +0 -1
  74. package/dist/lib/index.js +0 -1
  75. package/dist/security/index.d.ts +0 -3
  76. package/dist/security/index.js +0 -3
  77. package/dist/security/security.d.ts +0 -23
  78. package/dist/security/security.js +0 -137
  79. package/dist/security/sign.d.ts +0 -103
  80. package/dist/security/sign.js +0 -666
  81. package/dist/security/verification-enforcer.d.ts +0 -53
  82. package/dist/security/verification-enforcer.js +0 -204
  83. package/dist/services/McpCoreService.d.ts +0 -98
  84. package/dist/services/McpCoreService.js +0 -124
  85. package/dist/services/index.d.ts +0 -1
  86. package/dist/services/index.js +0 -1
  87. package/dist/types.d.ts +0 -132
  88. package/dist/types.js +0 -3
  89. package/dist/utils/config.d.ts +0 -111
  90. package/dist/utils/config.js +0 -342
  91. package/dist/utils/env-loader.d.ts +0 -54
  92. package/dist/utils/env-loader.js +0 -270
  93. package/dist/utils/help.d.ts +0 -36
  94. package/dist/utils/help.js +0 -248
  95. package/dist/utils/index.d.ts +0 -7
  96. package/dist/utils/index.js +0 -7
  97. package/dist/utils/logger.d.ts +0 -35
  98. package/dist/utils/logger.js +0 -75
  99. package/dist/utils/silent-monitor.d.ts +0 -67
  100. package/dist/utils/silent-monitor.js +0 -242
  101. package/dist/utils/timeout.d.ts +0 -5
  102. package/dist/utils/timeout.js +0 -23
  103. package/dist/utils/version.d.ts +0 -4
  104. package/dist/utils/version.js +0 -35
  105. package/dist/web/env-manager-server.d.ts +0 -29
  106. package/dist/web/env-manager-server.js +0 -367
  107. package/dist/web/index.d.ts +0 -1
  108. package/dist/web/index.js +0 -1
  109. package/src/LocalToolResolver.ts +0 -424
  110. package/src/api/enact-api.ts +0 -604
  111. package/src/api/index.ts +0 -2
  112. package/src/api/types.ts +0 -114
  113. package/src/core/DaggerExecutionProvider.ts +0 -1357
  114. package/src/core/DirectExecutionProvider.ts +0 -484
  115. package/src/core/EnactCore.ts +0 -847
  116. package/src/core/index.ts +0 -3
  117. package/src/exec/index.ts +0 -3
  118. package/src/exec/logger.ts +0 -63
  119. package/src/exec/validate.ts +0 -238
  120. package/src/lib/enact-direct.ts +0 -254
  121. package/src/lib/index.ts +0 -1
  122. package/src/services/McpCoreService.ts +0 -201
  123. package/src/services/index.ts +0 -1
  124. package/src/utils/config.ts +0 -438
  125. package/src/utils/env-loader.ts +0 -370
  126. package/src/utils/help.ts +0 -257
  127. package/src/utils/index.ts +0 -7
  128. package/src/utils/silent-monitor.ts +0 -328
  129. package/src/utils/timeout.ts +0 -26
  130. package/src/web/env-manager-server.ts +0 -465
  131. package/src/web/index.ts +0 -1
  132. package/src/web/static/app.js +0 -663
  133. package/src/web/static/index.html +0 -117
  134. 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
+ });