modestbench 0.6.0 → 0.8.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 (139) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/README.md +6 -2
  3. package/dist/cli/commands/run.cjs +100 -54
  4. package/dist/cli/commands/run.cjs.map +1 -1
  5. package/dist/cli/commands/run.d.cts.map +1 -1
  6. package/dist/cli/commands/run.d.ts.map +1 -1
  7. package/dist/cli/commands/run.js +93 -47
  8. package/dist/cli/commands/run.js.map +1 -1
  9. package/dist/cli/commands/test.cjs +14 -15
  10. package/dist/cli/commands/test.cjs.map +1 -1
  11. package/dist/cli/commands/test.d.cts.map +1 -1
  12. package/dist/cli/commands/test.d.ts.map +1 -1
  13. package/dist/cli/commands/test.js +2 -3
  14. package/dist/cli/commands/test.js.map +1 -1
  15. package/dist/cli/index.cjs +3 -0
  16. package/dist/cli/index.cjs.map +1 -1
  17. package/dist/cli/index.d.cts.map +1 -1
  18. package/dist/cli/index.d.ts.map +1 -1
  19. package/dist/cli/index.js +4 -1
  20. package/dist/cli/index.js.map +1 -1
  21. package/dist/constants.cjs +3 -0
  22. package/dist/constants.cjs.map +1 -1
  23. package/dist/constants.d.cts +3 -0
  24. package/dist/constants.d.cts.map +1 -1
  25. package/dist/constants.d.ts +3 -0
  26. package/dist/constants.d.ts.map +1 -1
  27. package/dist/constants.js +3 -0
  28. package/dist/constants.js.map +1 -1
  29. package/dist/errors/index.cjs +3 -1
  30. package/dist/errors/index.cjs.map +1 -1
  31. package/dist/errors/index.d.cts +1 -1
  32. package/dist/errors/index.d.cts.map +1 -1
  33. package/dist/errors/index.d.ts +1 -1
  34. package/dist/errors/index.d.ts.map +1 -1
  35. package/dist/errors/index.js +1 -1
  36. package/dist/errors/index.js.map +1 -1
  37. package/dist/errors/reporter.cjs +45 -1
  38. package/dist/errors/reporter.cjs.map +1 -1
  39. package/dist/errors/reporter.d.cts +32 -0
  40. package/dist/errors/reporter.d.cts.map +1 -1
  41. package/dist/errors/reporter.d.ts +32 -0
  42. package/dist/errors/reporter.d.ts.map +1 -1
  43. package/dist/errors/reporter.js +42 -0
  44. package/dist/errors/reporter.js.map +1 -1
  45. package/dist/index.cjs +19 -1
  46. package/dist/index.cjs.map +1 -1
  47. package/dist/index.d.cts +4 -1
  48. package/dist/index.d.cts.map +1 -1
  49. package/dist/index.d.ts +4 -1
  50. package/dist/index.d.ts.map +1 -1
  51. package/dist/index.js +7 -1
  52. package/dist/index.js.map +1 -1
  53. package/dist/reporters/index.cjs +3 -1
  54. package/dist/reporters/index.cjs.map +1 -1
  55. package/dist/reporters/index.d.cts +1 -0
  56. package/dist/reporters/index.d.cts.map +1 -1
  57. package/dist/reporters/index.d.ts +1 -0
  58. package/dist/reporters/index.d.ts.map +1 -1
  59. package/dist/reporters/index.js +1 -0
  60. package/dist/reporters/index.js.map +1 -1
  61. package/dist/reporters/nyan.cjs +318 -0
  62. package/dist/reporters/nyan.cjs.map +1 -0
  63. package/dist/reporters/nyan.d.cts +118 -0
  64. package/dist/reporters/nyan.d.cts.map +1 -0
  65. package/dist/reporters/nyan.d.ts +118 -0
  66. package/dist/reporters/nyan.d.ts.map +1 -0
  67. package/dist/reporters/nyan.js +314 -0
  68. package/dist/reporters/nyan.js.map +1 -0
  69. package/dist/services/reporter-loader.cjs +281 -0
  70. package/dist/services/reporter-loader.cjs.map +1 -0
  71. package/dist/services/reporter-loader.d.cts +67 -0
  72. package/dist/services/reporter-loader.d.cts.map +1 -0
  73. package/dist/services/reporter-loader.d.ts +67 -0
  74. package/dist/services/reporter-loader.d.ts.map +1 -0
  75. package/dist/services/reporter-loader.js +241 -0
  76. package/dist/services/reporter-loader.js.map +1 -0
  77. package/dist/types/core.cjs.map +1 -1
  78. package/dist/types/core.d.cts +13 -12
  79. package/dist/types/core.d.cts.map +1 -1
  80. package/dist/types/core.d.ts +13 -12
  81. package/dist/types/core.d.ts.map +1 -1
  82. package/dist/types/core.js.map +1 -1
  83. package/dist/types/index.cjs +0 -2
  84. package/dist/types/index.cjs.map +1 -1
  85. package/dist/types/index.d.cts +1 -1
  86. package/dist/types/index.d.cts.map +1 -1
  87. package/dist/types/index.d.ts +1 -1
  88. package/dist/types/index.d.ts.map +1 -1
  89. package/dist/types/index.js +0 -2
  90. package/dist/types/index.js.map +1 -1
  91. package/dist/types/plugin.cjs +9 -0
  92. package/dist/types/plugin.cjs.map +1 -0
  93. package/dist/types/plugin.d.cts +179 -0
  94. package/dist/types/plugin.d.cts.map +1 -0
  95. package/dist/types/plugin.d.ts +179 -0
  96. package/dist/types/plugin.d.ts.map +1 -0
  97. package/dist/types/plugin.js +8 -0
  98. package/dist/types/plugin.js.map +1 -0
  99. package/dist/utils/package.cjs +66 -5
  100. package/dist/utils/package.cjs.map +1 -1
  101. package/dist/utils/package.d.cts +6 -0
  102. package/dist/utils/package.d.cts.map +1 -1
  103. package/dist/utils/package.d.ts +6 -0
  104. package/dist/utils/package.d.ts.map +1 -1
  105. package/dist/utils/package.js +31 -1
  106. package/dist/utils/package.js.map +1 -1
  107. package/dist/utils/reporter-utils.cjs +90 -0
  108. package/dist/utils/reporter-utils.cjs.map +1 -0
  109. package/dist/utils/reporter-utils.d.cts +42 -0
  110. package/dist/utils/reporter-utils.d.cts.map +1 -0
  111. package/dist/utils/reporter-utils.d.ts +42 -0
  112. package/dist/utils/reporter-utils.d.ts.map +1 -0
  113. package/dist/utils/reporter-utils.js +83 -0
  114. package/dist/utils/reporter-utils.js.map +1 -0
  115. package/package.json +6 -6
  116. package/src/cli/commands/run.ts +130 -64
  117. package/src/cli/commands/test.ts +2 -3
  118. package/src/cli/index.ts +8 -0
  119. package/src/constants.ts +4 -1
  120. package/src/errors/index.ts +2 -0
  121. package/src/errors/reporter.ts +55 -0
  122. package/src/index.ts +22 -1
  123. package/src/reporters/index.ts +1 -0
  124. package/src/reporters/nyan.ts +409 -0
  125. package/src/services/reporter-loader.ts +323 -0
  126. package/src/types/core.ts +16 -14
  127. package/src/types/index.ts +3 -3
  128. package/src/types/plugin.ts +197 -0
  129. package/src/utils/package.ts +32 -1
  130. package/src/utils/reporter-utils.ts +85 -0
  131. package/dist/types/cli.cjs +0 -12
  132. package/dist/types/cli.cjs.map +0 -1
  133. package/dist/types/cli.d.cts +0 -75
  134. package/dist/types/cli.d.cts.map +0 -1
  135. package/dist/types/cli.d.ts +0 -75
  136. package/dist/types/cli.d.ts.map +0 -1
  137. package/dist/types/cli.js +0 -9
  138. package/dist/types/cli.js.map +0 -1
  139. package/src/types/cli.ts +0 -82
@@ -0,0 +1,314 @@
1
+ /**
2
+ * ModestBench Nyan Cat Reporter
3
+ *
4
+ * Because benchmarking should be more colorful. Displays an animated nyan cat
5
+ * flying through a rainbow trail as benchmarks complete.
6
+ *
7
+ * Based on Mocha's legendary nyan reporter, adapted for the glory of
8
+ * performance measurement.
9
+ *
10
+ * @packageDocumentation
11
+ */
12
+ import { BaseReporter } from "../services/reporter-registry.js";
13
+ import { colors } from "../utils/ansi.js";
14
+ /**
15
+ * Nyan Cat reporter - because your benchmarks deserve rainbow power
16
+ */
17
+ export class NyanReporter extends BaseReporter {
18
+ /** Index into rainbow colors for cycling */
19
+ colorIndex = 0;
20
+ /** Current file being processed */
21
+ currentFile = '';
22
+ /** Current suite being processed */
23
+ currentSuite = '';
24
+ /** Total failed tasks */
25
+ failed = 0;
26
+ /** Collected failures for summary */
27
+ failures = [];
28
+ /** Number of lines the cat occupies */
29
+ numberOfLines = 4;
30
+ /** Total passed tasks */
31
+ passed = 0;
32
+ /** Whether the display is active */
33
+ progressActive = false;
34
+ /** Quiet mode - suppress output */
35
+ quiet;
36
+ /** Generated rainbow color palette */
37
+ rainbowColors = [];
38
+ /** Width of scoreboard */
39
+ scoreboardWidth = 5;
40
+ /** Start time for duration calculation */
41
+ startTime = 0;
42
+ /** Animation tick (alternates between frames) */
43
+ tick = false;
44
+ /** Rainbow trail storage - one trajectory per cat line */
45
+ trajectories = [[], [], [], []];
46
+ /** Maximum width of the rainbow trail */
47
+ trajectoryWidthMax = 0;
48
+ /** Whether to use colors */
49
+ useColor;
50
+ constructor(options = {}) {
51
+ super('nyan', options);
52
+ this.quiet = options.quiet ?? false;
53
+ // Auto-detect color support if not explicitly set
54
+ this.useColor =
55
+ options.color ??
56
+ (process.stdout.isTTY &&
57
+ process.env.FORCE_COLOR !== '0' &&
58
+ process.env.NO_COLOR == null);
59
+ // Generate the rainbow colors on construction
60
+ this.rainbowColors = this.generateColors();
61
+ // Calculate trajectory width based on terminal width
62
+ // Leave room for scoreboard (5) + cat (11) + some padding
63
+ const termWidth = process.stdout.columns || 80;
64
+ const nyanCatWidth = 11;
65
+ this.trajectoryWidthMax = Math.floor(termWidth * 0.75) - nyanCatWidth;
66
+ }
67
+ onEnd(run) {
68
+ if (this.quiet) {
69
+ return;
70
+ }
71
+ // Show cursor and move past the cat
72
+ this.showCursor();
73
+ for (let i = 0; i < this.numberOfLines; i++) {
74
+ process.stdout.write('\n');
75
+ }
76
+ // Print summary
77
+ this.printEpilogue(run);
78
+ }
79
+ onError(error) {
80
+ if (this.quiet) {
81
+ return;
82
+ }
83
+ // Make sure cursor is visible
84
+ this.showCursor();
85
+ console.error(`\n${colors.red}Error: ${error.message}${colors.reset}`);
86
+ }
87
+ onFileEnd(_result) {
88
+ // Just keep flying
89
+ }
90
+ onFileStart(file) {
91
+ this.currentFile = file;
92
+ }
93
+ onStart(_run) {
94
+ this.startTime = Date.now();
95
+ this.passed = 0;
96
+ this.failed = 0;
97
+ this.failures = [];
98
+ this.colorIndex = 0;
99
+ this.tick = false;
100
+ this.trajectories = [[], [], [], []];
101
+ if (this.quiet) {
102
+ return;
103
+ }
104
+ // Hide cursor for cleaner animation
105
+ this.hideCursor();
106
+ // Initial draw
107
+ this.draw();
108
+ this.progressActive = true;
109
+ }
110
+ onSuiteEnd(_result) {
111
+ // Keep flying
112
+ }
113
+ onSuiteStart(suite) {
114
+ this.currentSuite = suite;
115
+ }
116
+ onTaskResult(result) {
117
+ if (result.error) {
118
+ this.failed++;
119
+ this.failures.push({
120
+ error: result.error.message || String(result.error),
121
+ file: this.currentFile,
122
+ suite: this.currentSuite,
123
+ task: result.name,
124
+ });
125
+ }
126
+ else if (!result.aborted) {
127
+ this.passed++;
128
+ }
129
+ if (this.quiet) {
130
+ return;
131
+ }
132
+ this.draw();
133
+ }
134
+ onTaskStart(_task) {
135
+ // The cat flies on results, not starts
136
+ }
137
+ /**
138
+ * Append a segment to the rainbow trail
139
+ */
140
+ appendRainbow() {
141
+ const segment = this.tick ? '_' : '-';
142
+ const rainbowified = this.rainbowify(segment);
143
+ for (let index = 0; index < this.numberOfLines; index++) {
144
+ const trajectory = this.trajectories[index];
145
+ if (trajectory.length >= this.trajectoryWidthMax) {
146
+ trajectory.shift();
147
+ }
148
+ trajectory.push(rainbowified);
149
+ }
150
+ }
151
+ /**
152
+ * Move cursor down n lines
153
+ */
154
+ cursorDown(n) {
155
+ process.stdout.write(`\x1b[${n}B`);
156
+ }
157
+ /**
158
+ * Move cursor up n lines
159
+ */
160
+ cursorUp(n) {
161
+ process.stdout.write(`\x1b[${n}A`);
162
+ }
163
+ /**
164
+ * Draw the complete nyan cat scene
165
+ */
166
+ draw() {
167
+ this.appendRainbow();
168
+ this.drawScoreboard();
169
+ this.drawRainbow();
170
+ this.drawNyanCat();
171
+ this.tick = !this.tick;
172
+ }
173
+ /**
174
+ * Draw the nyan cat ASCII art
175
+ */
176
+ drawNyanCat() {
177
+ const startWidth = this.scoreboardWidth + this.trajectories[0].length;
178
+ const dist = `\x1b[${startWidth}C`;
179
+ process.stdout.write(dist);
180
+ process.stdout.write('_,------,');
181
+ process.stdout.write('\n');
182
+ process.stdout.write(dist);
183
+ const padding1 = this.tick ? ' ' : ' ';
184
+ process.stdout.write(`_|${padding1}/\\_/\\ `);
185
+ process.stdout.write('\n');
186
+ process.stdout.write(dist);
187
+ const padding2 = this.tick ? '_' : '__';
188
+ const tail = this.tick ? '~' : '^';
189
+ process.stdout.write(`${tail}|${padding2}${this.face()} `);
190
+ process.stdout.write('\n');
191
+ process.stdout.write(dist);
192
+ const padding3 = this.tick ? ' ' : ' ';
193
+ process.stdout.write(`${padding3}"" "" `);
194
+ process.stdout.write('\n');
195
+ this.cursorUp(this.numberOfLines);
196
+ }
197
+ /**
198
+ * Draw the rainbow trail
199
+ */
200
+ drawRainbow() {
201
+ for (const line of this.trajectories) {
202
+ process.stdout.write(`\x1b[${this.scoreboardWidth}C`);
203
+ process.stdout.write(line.join(''));
204
+ process.stdout.write('\n');
205
+ }
206
+ this.cursorUp(this.numberOfLines);
207
+ }
208
+ /**
209
+ * Draw the scoreboard showing pass/fail counts
210
+ */
211
+ drawScoreboard() {
212
+ const draw = (type, n) => {
213
+ process.stdout.write(' ');
214
+ if (this.useColor) {
215
+ process.stdout.write(`${colors[type]}${n}${colors.reset}`);
216
+ }
217
+ else {
218
+ process.stdout.write(String(n));
219
+ }
220
+ process.stdout.write('\n');
221
+ };
222
+ draw('green', this.passed);
223
+ draw('red', this.failed);
224
+ process.stdout.write('\n');
225
+ process.stdout.write('\n');
226
+ this.cursorUp(this.numberOfLines);
227
+ }
228
+ /**
229
+ * Get the nyan cat's face based on current state
230
+ */
231
+ face() {
232
+ if (this.failed > 0) {
233
+ return '( x .x)';
234
+ }
235
+ else if (this.passed > 0) {
236
+ return '( ^ .^)';
237
+ }
238
+ return '( - .-)';
239
+ }
240
+ /**
241
+ * Generate rainbow colors using sine wave color cycling
242
+ *
243
+ * Uses 256-color palette (colors 16-231 are a 6x6x6 color cube)
244
+ */
245
+ generateColors() {
246
+ const colorList = [];
247
+ // Generate 42 colors (6 * 7) cycling through the spectrum
248
+ for (let i = 0; i < 6 * 7; i++) {
249
+ const pi3 = Math.floor(Math.PI / 3);
250
+ const n = i * (1.0 / 6);
251
+ const r = Math.floor(3 * Math.sin(n) + 3);
252
+ const g = Math.floor(3 * Math.sin(n + 2 * pi3) + 3);
253
+ const b = Math.floor(3 * Math.sin(n + 4 * pi3) + 3);
254
+ // Calculate 256-color code from RGB values (16 + 36*r + 6*g + b)
255
+ colorList.push(36 * r + 6 * g + b + 16);
256
+ }
257
+ return colorList;
258
+ }
259
+ /**
260
+ * Hide the cursor
261
+ */
262
+ hideCursor() {
263
+ if (process.stdout.isTTY) {
264
+ process.stdout.write('\x1b[?25l');
265
+ }
266
+ }
267
+ /**
268
+ * Print the epilogue summary after the run
269
+ */
270
+ printEpilogue(run) {
271
+ const duration = Date.now() - this.startTime;
272
+ const durationStr = BaseReporter.formatDuration(duration * 1000000);
273
+ console.log();
274
+ console.log(` ${this.useColor ? colors.green : ''}${this.passed} passing${this.useColor ? colors.reset : ''} ${this.useColor ? colors.gray : ''}(${durationStr})${this.useColor ? colors.reset : ''}`);
275
+ if (this.failed > 0) {
276
+ console.log(` ${this.useColor ? colors.red : ''}${this.failed} failing${this.useColor ? colors.reset : ''}`);
277
+ console.log();
278
+ // Print failure details
279
+ for (let i = 0; i < this.failures.length; i++) {
280
+ const failure = this.failures[i];
281
+ console.log(` ${i + 1}) ${failure.suite === 'default' ? '' : failure.suite + ' > '}${failure.task}`);
282
+ console.log(` ${this.useColor ? colors.red : ''}${failure.error}${this.useColor ? colors.reset : ''}`);
283
+ console.log();
284
+ }
285
+ }
286
+ // Show total files/suites for context
287
+ let totalSuites = 0;
288
+ for (const file of run.files) {
289
+ totalSuites += file.suites.length;
290
+ }
291
+ console.log();
292
+ console.log(` ${this.useColor ? colors.gray : ''}Files: ${run.files.length} | Suites: ${totalSuites} | Tasks: ${this.passed + this.failed}${this.useColor ? colors.reset : ''}`);
293
+ }
294
+ /**
295
+ * Apply rainbow coloring to a string
296
+ */
297
+ rainbowify(str) {
298
+ if (!this.useColor) {
299
+ return str;
300
+ }
301
+ const color = this.rainbowColors[this.colorIndex % this.rainbowColors.length];
302
+ this.colorIndex += 1;
303
+ return `\x1b[38;5;${color}m${str}\x1b[0m`;
304
+ }
305
+ /**
306
+ * Show the cursor
307
+ */
308
+ showCursor() {
309
+ if (process.stdout.isTTY) {
310
+ process.stdout.write('\x1b[?25h');
311
+ }
312
+ }
313
+ }
314
+ //# sourceMappingURL=nyan.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nyan.js","sourceRoot":"","sources":["../../src/reporters/nyan.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,281 @@
1
+ "use strict";
2
+ /**
3
+ * ModestBench Reporter Loader
4
+ *
5
+ * Service for loading third-party reporter plugins from file paths or npm
6
+ * packages. Supports multiple export patterns: plain objects, classes, and
7
+ * factory functions (sync or async).
8
+ */
9
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ var desc = Object.getOwnPropertyDescriptor(m, k);
12
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
13
+ desc = { enumerable: true, get: function() { return m[k]; } };
14
+ }
15
+ Object.defineProperty(o, k2, desc);
16
+ }) : (function(o, m, k, k2) {
17
+ if (k2 === undefined) k2 = k;
18
+ o[k2] = m[k];
19
+ }));
20
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
21
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
22
+ }) : function(o, v) {
23
+ o["default"] = v;
24
+ });
25
+ var __importStar = (this && this.__importStar) || (function () {
26
+ var ownKeys = function(o) {
27
+ ownKeys = Object.getOwnPropertyNames || function (o) {
28
+ var ar = [];
29
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
30
+ return ar;
31
+ };
32
+ return ownKeys(o);
33
+ };
34
+ return function (mod) {
35
+ if (mod && mod.__esModule) return mod;
36
+ var result = {};
37
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
38
+ __setModuleDefault(result, mod);
39
+ return result;
40
+ };
41
+ })();
42
+ var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExtension) || function (path, preserveJsx) {
43
+ if (typeof path === "string" && /^\.\.?\//.test(path)) {
44
+ return path.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) {
45
+ return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : (d + ext + "." + cm.toLowerCase() + "js");
46
+ });
47
+ }
48
+ return path;
49
+ };
50
+ Object.defineProperty(exports, "__esModule", { value: true });
51
+ exports.loadReporter = exports.isFilePath = exports.isBuiltInReporter = exports.createReporterContext = exports.PLUGIN_API_VERSION = void 0;
52
+ const node_path_1 = require("node:path");
53
+ const node_url_1 = require("node:url");
54
+ const constants_js_1 = require("../constants.cjs");
55
+ const reporter_js_1 = require("../errors/reporter.cjs");
56
+ const package_js_1 = require("../utils/package.cjs");
57
+ const reporter_utils_js_1 = require("../utils/reporter-utils.cjs");
58
+ /**
59
+ * Current plugin API version
60
+ *
61
+ * Increment this when making breaking changes to the plugin API.
62
+ */
63
+ exports.PLUGIN_API_VERSION = 1;
64
+ /**
65
+ * Set of built-in reporter names
66
+ */
67
+ const BUILT_IN_REPORTERS = new Set(Object.values(constants_js_1.Reporters));
68
+ /**
69
+ * Required methods that all reporters must implement
70
+ */
71
+ const REQUIRED_REPORTER_METHODS = [
72
+ 'onStart',
73
+ 'onEnd',
74
+ 'onError',
75
+ 'onTaskResult',
76
+ ];
77
+ /**
78
+ * Default logger implementation using console
79
+ *
80
+ * This provides a simple console-based logger for reporter plugins.
81
+ */
82
+ const defaultLogger = {
83
+ debug: (message, ...args) => console.debug(message, ...args),
84
+ error: (message, ...args) => console.error(message, ...args),
85
+ info: (message, ...args) => console.info(message, ...args),
86
+ trace: (message, ...args) => console.trace(message, ...args),
87
+ warn: (message, ...args) => console.warn(message, ...args),
88
+ };
89
+ /**
90
+ * Create a ReporterContext for passing to plugins
91
+ *
92
+ * @param logger - Optional logger to use (defaults to console-based logger)
93
+ * @returns ReporterContext with version info and utilities
94
+ */
95
+ const createReporterContext = (logger) => {
96
+ return {
97
+ logger: logger ?? defaultLogger,
98
+ pluginApiVersion: exports.PLUGIN_API_VERSION,
99
+ utils: reporter_utils_js_1.reporterUtils,
100
+ version: (0, package_js_1.getPackageVersion)(),
101
+ };
102
+ };
103
+ exports.createReporterContext = createReporterContext;
104
+ /**
105
+ * Get the list of missing required methods from a reporter object
106
+ *
107
+ * @param obj - Object to check
108
+ * @returns Array of missing method names
109
+ */
110
+ const getMissingMethods = (obj) => {
111
+ if (typeof obj !== 'object' || obj === null) {
112
+ return [...REQUIRED_REPORTER_METHODS];
113
+ }
114
+ return REQUIRED_REPORTER_METHODS.filter((method) => typeof obj[method] !== 'function');
115
+ };
116
+ /**
117
+ * Check if a specifier refers to a built-in reporter
118
+ *
119
+ * @param specifier - Reporter name or path
120
+ * @returns True if the specifier is a built-in reporter name
121
+ */
122
+ const isBuiltInReporter = (specifier) => {
123
+ return BUILT_IN_REPORTERS.has(specifier);
124
+ };
125
+ exports.isBuiltInReporter = isBuiltInReporter;
126
+ /**
127
+ * Check if a function is a class constructor
128
+ *
129
+ * Uses heuristics to distinguish classes from regular functions:
130
+ *
131
+ * - Classes have a non-writable prototype property
132
+ * - Class syntax produces different toString() output
133
+ *
134
+ * @param func - Function to check
135
+ * @returns True if the function appears to be a class constructor
136
+ */
137
+ const isClass = (func) => {
138
+ if (typeof func !== 'function') {
139
+ return false;
140
+ }
141
+ // Classes have a non-writable prototype
142
+ const protoDescriptor = Object.getOwnPropertyDescriptor(func, 'prototype');
143
+ if (!protoDescriptor || protoDescriptor.writable) {
144
+ return false;
145
+ }
146
+ // Check if it uses class syntax (handles both 'class Foo' and 'class{')
147
+ const funcStr = func.toString();
148
+ return /^class\b/.test(funcStr);
149
+ };
150
+ /**
151
+ * Check if a specifier looks like a file path
152
+ *
153
+ * @param specifier - Reporter name or path
154
+ * @returns True if the specifier appears to be a file path
155
+ */
156
+ const isFilePath = (specifier) => {
157
+ return (specifier.startsWith('.') ||
158
+ specifier.startsWith('/') ||
159
+ // isAbsolute handles Windows paths like 'C:\path\to\file.js'
160
+ (0, node_path_1.isAbsolute)(specifier));
161
+ };
162
+ exports.isFilePath = isFilePath;
163
+ /**
164
+ * Check if an object implements the Reporter interface
165
+ *
166
+ * Validates that all required methods are present and are functions.
167
+ *
168
+ * @param obj - Object to validate
169
+ * @returns True if the object has all required reporter methods
170
+ */
171
+ const isReporterObject = (obj) => {
172
+ if (typeof obj !== 'object' || obj === null) {
173
+ return false;
174
+ }
175
+ return REQUIRED_REPORTER_METHODS.every((method) => typeof obj[method] === 'function');
176
+ };
177
+ /**
178
+ * Load a reporter from a file path or npm package name
179
+ *
180
+ * Supports multiple export patterns:
181
+ *
182
+ * 1. Plain Reporter object (simplest, no options support)
183
+ * 2. Class constructor (instantiated with options and context)
184
+ * 3. Factory function (called with options and context, can be async)
185
+ *
186
+ * @example
187
+ *
188
+ * ```typescript
189
+ * // Load from file path
190
+ * const reporter = await loadReporter('./my-reporter.js', {
191
+ * verbose: true,
192
+ * });
193
+ *
194
+ * // Load from npm package
195
+ * const reporter = await loadReporter('@company/custom-reporter', {
196
+ * apiKey: 'xxx',
197
+ * });
198
+ * ```
199
+ *
200
+ * @param specifier - File path (relative or absolute) or npm package name
201
+ * @param options - Options to pass to the reporter factory/constructor
202
+ * @param cwd - Current working directory for resolving relative paths
203
+ * @returns Loaded reporter instance
204
+ * @throws ReporterLoadError if the module cannot be loaded
205
+ * @throws ReporterValidationError if the module doesn't implement Reporter
206
+ */
207
+ const loadReporter = async (specifier, options = {}, cwd = process.cwd()) => {
208
+ const context = (0, exports.createReporterContext)();
209
+ const resolvedSpecifier = resolveSpecifier(specifier, cwd);
210
+ let module;
211
+ try {
212
+ module = await Promise.resolve(`${__rewriteRelativeImportExtension(resolvedSpecifier)}`).then(s => __importStar(require(s)));
213
+ }
214
+ catch (error) {
215
+ const message = error instanceof Error ? error.message : String(error);
216
+ throw new reporter_js_1.ReporterLoadError(message, specifier, { cause: error });
217
+ }
218
+ // Handle ESM/CJS interop - get default export if present
219
+ const exported = module.default ?? module;
220
+ // Case 1: Already a Reporter object (plain object export)
221
+ if (isReporterObject(exported)) {
222
+ return exported;
223
+ }
224
+ // Case 2: Class constructor
225
+ if (isClass(exported)) {
226
+ let instance;
227
+ try {
228
+ instance = new exported(options, context);
229
+ }
230
+ catch (error) {
231
+ const message = error instanceof Error ? error.message : String(error);
232
+ throw new reporter_js_1.ReporterLoadError(`Constructor threw error: ${message}`, specifier, { cause: error });
233
+ }
234
+ validateReporter(instance, specifier);
235
+ return instance;
236
+ }
237
+ // Case 3: Factory function (sync or async)
238
+ if (typeof exported === 'function') {
239
+ let result;
240
+ try {
241
+ result = await exported(options, context);
242
+ }
243
+ catch (error) {
244
+ const message = error instanceof Error ? error.message : String(error);
245
+ throw new reporter_js_1.ReporterLoadError(`Factory function threw error: ${message}`, specifier, { cause: error });
246
+ }
247
+ validateReporter(result, specifier);
248
+ return result;
249
+ }
250
+ // None of the above - could be an object with missing methods or invalid type
251
+ if (typeof exported === 'object' && exported !== null) {
252
+ // It's an object but missing required methods
253
+ const missing = getMissingMethods(exported);
254
+ throw new reporter_js_1.ReporterValidationError('Module does not implement Reporter interface.', specifier, missing);
255
+ }
256
+ // Completely invalid export type
257
+ throw new reporter_js_1.ReporterValidationError('Module must export a Reporter object, class, or factory function.', specifier);
258
+ };
259
+ exports.loadReporter = loadReporter;
260
+ /**
261
+ * Resolve a specifier to an importable URL or module name
262
+ *
263
+ * @param specifier - File path or npm package name
264
+ * @param cwd - Current working directory for resolving relative paths
265
+ * @returns Resolved module specifier
266
+ */
267
+ const resolveSpecifier = (specifier, cwd) => {
268
+ if ((0, exports.isFilePath)(specifier)) {
269
+ const absolutePath = (0, node_path_1.resolve)(cwd, specifier);
270
+ return (0, node_url_1.pathToFileURL)(absolutePath).href;
271
+ }
272
+ // npm package name - return as-is for dynamic import
273
+ return specifier;
274
+ };
275
+ const validateReporter = (obj, specifier) => {
276
+ const missing = getMissingMethods(obj);
277
+ if (missing.length > 0) {
278
+ throw new reporter_js_1.ReporterValidationError('Module does not implement Reporter interface.', specifier, missing);
279
+ }
280
+ };
281
+ //# sourceMappingURL=reporter-loader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reporter-loader.js","sourceRoot":"","sources":["../../src/services/reporter-loader.ts"],"names":[],"mappings":"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"}