headlamp 0.1.33 → 0.1.35

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.
@@ -1,193 +0,0 @@
1
- /* eslint-disable global-require */
2
- /* eslint-disable @typescript-eslint/no-require-imports */
3
- /* eslint-disable import/no-dynamic-require */
4
-
5
- const fs = require('node:fs');
6
- const path = require('node:path');
7
-
8
- const print = (payload) => {
9
- try {
10
- const line = `[JEST-BRIDGE-EVENT] ${JSON.stringify(payload)}`;
11
- (process.stderr || process.stdout).write(`${line}\n`);
12
- } catch {}
13
- };
14
-
15
- const isObject = (v) => typeof v === 'object' && v !== null;
16
- const sanitizeError = (err) => {
17
- if (!isObject(err)) return err;
18
- const out = {};
19
- const name = err.name || (err.constructor && err.constructor.name) || undefined;
20
- if (name) out.name = String(name);
21
- if (typeof err.message === 'string') out.message = err.message;
22
- if (typeof err.stack === 'string') out.stack = err.stack;
23
- if (err.code !== undefined) out.code = err.code;
24
- if (err.expected !== undefined) out.expected = err.expected;
25
- if (err.received !== undefined) out.received = err.received;
26
- if (err.matcherResult && isObject(err.matcherResult)) {
27
- const mr = err.matcherResult;
28
- let messageText;
29
- try {
30
- messageText =
31
- typeof mr.message === 'function'
32
- ? String(mr.message())
33
- : typeof mr.message === 'string'
34
- ? mr.message
35
- : undefined;
36
- } catch {}
37
- out.matcherResult = {
38
- matcherName: typeof mr.matcherName === 'string' ? mr.matcherName : undefined,
39
- message: messageText,
40
- stack: typeof mr.stack === 'string' ? mr.stack : undefined,
41
- expected: mr.expected,
42
- received: mr.received,
43
- actual: mr.actual,
44
- pass: typeof mr.pass === 'boolean' ? mr.pass : undefined,
45
- };
46
- }
47
- if (err.cause) {
48
- out.cause = sanitizeError(err.cause);
49
- }
50
- // Copy own enumerable props to preserve custom data
51
- try {
52
- for (const key of Object.keys(err)) {
53
- if (!(key in out)) out[key] = err[key];
54
- }
55
- } catch {}
56
- return out;
57
- };
58
- const sanitizeDetail = (d) => {
59
- if (typeof d === 'string') return d;
60
- if (!isObject(d)) return d;
61
- // Common Jest detail shapes
62
- const out = {};
63
- if (d.message) out.message = d.message;
64
- if (d.stack) out.stack = d.stack;
65
- if (d.error) out.error = sanitizeError(d.error);
66
- if (d.matcherResult) {
67
- out.matcherResult = sanitizeError({ matcherResult: d.matcherResult }).matcherResult;
68
- }
69
- if (d.expected !== undefined) out.expected = d.expected;
70
- if (d.received !== undefined) out.received = d.received;
71
- // Copy the rest
72
- try {
73
- for (const key of Object.keys(d)) {
74
- if (!(key in out)) out[key] = d[key];
75
- }
76
- } catch {}
77
- return out;
78
- };
79
-
80
- class BridgeReporter {
81
- constructor(globalConfig, options) {
82
- this.out =
83
- process.env.JEST_BRIDGE_OUT ||
84
- (options && options.outFile) ||
85
- path.join(process.cwd(), 'coverage', 'jest-run.json');
86
- this.buf = { startTime: Date.now(), testResults: [], aggregated: null };
87
- }
88
-
89
- onRunStart() {
90
- this.buf.startTime = Date.now();
91
- }
92
-
93
- onTestResult(_test, tr) {
94
- const mapAssertion = (a) => ({
95
- title: a.title,
96
- fullName: a.fullName || [...(a.ancestorTitles || []), a.title].join(' '),
97
- status: a.status,
98
- timedOut: Boolean(
99
- a.status === 'failed' &&
100
- String(a.failureMessages || '')
101
- .toLowerCase()
102
- .includes('timed out'),
103
- ),
104
- duration: a.duration || 0,
105
- location: a.location || null,
106
- failureMessages: (a.failureMessages || []).map(String),
107
- failureDetails: (a.failureDetails || []).map(sanitizeDetail),
108
- });
109
- this.buf.testResults.push({
110
- testFilePath: tr.testFilePath,
111
- // Consider suite-level errors as failures even when no individual assertions failed
112
- status:
113
- (tr && typeof tr.numFailingTests === 'number' && tr.numFailingTests > 0) ||
114
- Boolean(tr.testExecError) ||
115
- Boolean(tr.failureMessage)
116
- ? 'failed'
117
- : 'passed',
118
- timedOut: Boolean(
119
- (tr.testExecError &&
120
- /timed out/i.test(
121
- String(tr.testExecError && (tr.testExecError.message || tr.testExecError)),
122
- )) ||
123
- /timed out/i.test(String(tr.failureMessage || '')),
124
- ),
125
- failureMessage: tr.failureMessage || '',
126
- failureDetails: (tr.failureDetails || []).map(sanitizeDetail),
127
- testExecError: tr.testExecError ? sanitizeError(tr.testExecError) : null,
128
- console: tr.console || null,
129
- perfStats: tr.perfStats || {},
130
- testResults: (tr.testResults || []).map(mapAssertion),
131
- });
132
- try {
133
- print({
134
- type: 'suiteComplete',
135
- testPath: tr.testFilePath,
136
- numPassingTests: tr.numPassingTests,
137
- numFailingTests: tr.numFailingTests,
138
- });
139
- } catch {}
140
- }
141
-
142
- onRunComplete(_contexts, agg) {
143
- // Compute timed out counts heuristically from test results & errors
144
- const suiteTimedOut = (r) =>
145
- Boolean(
146
- (r.testExecError &&
147
- /timed out/i.test(
148
- String(r.testExecError && (r.testExecError.message || r.testExecError)),
149
- )) ||
150
- /timed out/i.test(String(r.failureMessage || '')),
151
- );
152
- const fileTimeouts = this.buf.testResults.filter(suiteTimedOut);
153
- const testTimeouts = this.buf.testResults
154
- .flatMap((r) => r.testResults || [])
155
- .filter((a) => a && a.timedOut);
156
- // Recompute suite pass/fail counts to include suite-level errors/timeouts
157
- const totalSuites = typeof agg.numTotalTestSuites === 'number' ? agg.numTotalTestSuites : 0;
158
- const failedSuites = this.buf.testResults.filter(
159
- (r) => r.status === 'failed' || r.testExecError || r.failureMessage,
160
- ).length;
161
- const passedSuites = Math.max(0, totalSuites - failedSuites);
162
- const failedAssertions = typeof agg.numFailedTests === 'number' ? agg.numFailedTests : 0;
163
- const suiteOnlyFailures = Math.max(0, failedSuites - failedAssertions);
164
- const failedTestsInclSuiteErrors = failedAssertions + suiteOnlyFailures;
165
-
166
- this.buf.aggregated = {
167
- numTotalTestSuites: totalSuites,
168
- numPassedTestSuites: passedSuites,
169
- numFailedTestSuites: failedSuites,
170
- numTotalTests: agg.numTotalTests,
171
- numPassedTests: agg.numPassedTests,
172
- numFailedTests: failedTestsInclSuiteErrors,
173
- numPendingTests: agg.numPendingTests,
174
- numTodoTests: agg.numTodoTests,
175
- numTimedOutTests: testTimeouts.length,
176
- numTimedOutTestSuites: fileTimeouts.length,
177
- startTime: agg.startTime,
178
- success:
179
- Boolean(agg.success) &&
180
- failedSuites === 0 &&
181
- failedTestsInclSuiteErrors === 0 &&
182
- fileTimeouts.length === 0,
183
- runTimeMs: agg.testResults.reduce(
184
- (t, r) => t + Math.max(0, (r.perfStats?.end || 0) - (r.perfStats?.start || 0)),
185
- 0,
186
- ),
187
- };
188
- fs.mkdirSync(path.dirname(this.out), { recursive: true });
189
- fs.writeFileSync(this.out, JSON.stringify(this.buf), 'utf8');
190
- }
191
- }
192
-
193
- module.exports = BridgeReporter;
@@ -1,201 +0,0 @@
1
- /* eslint-disable global-require */
2
- /* eslint-disable @typescript-eslint/no-require-imports */
3
- /* eslint-disable import/no-dynamic-require */
4
-
5
- (function setupBridge() {
6
- try {
7
- const print = (payload) => {
8
- try {
9
- const line = `[JEST-BRIDGE-EVENT] ${JSON.stringify(payload)}`;
10
- (process.stderr || process.stdout).write(`${line}\n`);
11
- } catch {}
12
- };
13
-
14
- const toErr = (x) => {
15
- try {
16
- return x instanceof Error ? x : new Error(String(x));
17
- } catch {
18
- return new Error('unknown');
19
- }
20
- };
21
-
22
- const getCtx = () => {
23
- try {
24
- const st =
25
- global.expect && typeof global.expect.getState === 'function'
26
- ? global.expect.getState()
27
- : {};
28
- return { testPath: st.testPath, currentTestName: st.currentTestName };
29
- } catch {
30
- return {};
31
- }
32
- };
33
-
34
- // Capture console output during tests
35
- try {
36
- const g = global;
37
- const levels = ['log', 'info', 'warn', 'error'];
38
- const originals = {};
39
- const maxEntries = 200;
40
- const toText = (args) => {
41
- try {
42
- return args.map((v) => (typeof v === 'string' ? v : JSON.stringify(v))).join(' ');
43
- } catch {
44
- return args.map(String).join(' ');
45
- }
46
- };
47
- if (!g.__JEST_CONSOLE_BUFFER__) g.__JEST_CONSOLE_BUFFER__ = [];
48
- for (const lvl of levels) {
49
- try {
50
- originals[lvl] =
51
- g.console[lvl] && g.console[lvl].bind ? g.console[lvl].bind(g.console) : g.console[lvl];
52
- g.console[lvl] = (...args) => {
53
- try {
54
- const buf = Array.isArray(g.__JEST_CONSOLE_BUFFER__)
55
- ? g.__JEST_CONSOLE_BUFFER__
56
- : (g.__JEST_CONSOLE_BUFFER__ = []);
57
- const msg = toText(args);
58
- buf.push({ type: lvl, message: msg, ts: Date.now() });
59
- if (buf.length > maxEntries) buf.splice(0, buf.length - maxEntries);
60
- const ctx = getCtx();
61
- print({ type: 'console', level: lvl, message: msg, ...ctx });
62
- } catch {}
63
- try {
64
- return originals[lvl](...args);
65
- } catch {
66
- return undefined;
67
- }
68
- };
69
- } catch {}
70
- }
71
- } catch {}
72
-
73
- // Process-level error hooks
74
- try {
75
- const onRej = (reason) => {
76
- const e = toErr(reason);
77
- const c = getCtx();
78
- print({
79
- type: 'unhandledRejection',
80
- name: e.name,
81
- message: e.message,
82
- stack: e.stack,
83
- code: e.code ?? undefined,
84
- ...c,
85
- });
86
- };
87
- const onExc = (error) => {
88
- const e = toErr(error);
89
- const c = getCtx();
90
- print({
91
- type: 'uncaughtException',
92
- name: e.name,
93
- message: e.message,
94
- stack: e.stack,
95
- code: e.code ?? undefined,
96
- ...c,
97
- });
98
- };
99
- process.on('unhandledRejection', onRej);
100
- process.on('uncaughtException', onExc);
101
- } catch {}
102
-
103
- // HTTP response patch
104
- try {
105
- const http = require('node:http');
106
- const PATCH_FLAG = Symbol.for('jestBridgePatched');
107
- const ORIGINAL_KEY = Symbol.for('jestBridgeOriginalEmit');
108
- const originalEmit =
109
- http &&
110
- http.Server &&
111
- http.Server.prototype &&
112
- typeof http.Server.prototype.emit === 'function'
113
- ? http.Server.prototype.emit
114
- : null;
115
- if (originalEmit && !http.Server.prototype.emit[PATCH_FLAG]) {
116
- const MAX = 64 * 1024;
117
- const asString = (x) => {
118
- try {
119
- if (typeof x === 'string') return x;
120
- if (Buffer.isBuffer(x)) return x.toString('utf8');
121
- return String(x);
122
- } catch {
123
- return '';
124
- }
125
- };
126
- const patched = function (eventName, req, res) {
127
- try {
128
- if (
129
- eventName === 'request' &&
130
- req &&
131
- res &&
132
- typeof res.write === 'function' &&
133
- typeof res.end === 'function'
134
- ) {
135
- const startAt = Date.now();
136
- const chunks = [];
137
- const write = res.write.bind(res);
138
- const end = res.end.bind(res);
139
- const method = req.method ? String(req.method) : undefined;
140
- const url =
141
- req.originalUrl || req.url ? String(req.originalUrl || req.url) : undefined;
142
- res.write = function (chunk, enc, cb) {
143
- try {
144
- const s = asString(chunk);
145
- if (s) chunks.push(s);
146
- } catch {}
147
- return write(chunk, enc, cb);
148
- };
149
- res.end = function (chunk, enc, cb) {
150
- try {
151
- const s = asString(chunk);
152
- if (s) chunks.push(s);
153
- } catch {}
154
- try {
155
- const preview = chunks.join('').slice(0, MAX);
156
- const statusCode =
157
- typeof res.statusCode === 'number' ? res.statusCode : undefined;
158
- const ctx = getCtx();
159
- print({
160
- type: 'httpResponse',
161
- timestampMs: Date.now(),
162
- durationMs: Math.max(0, Date.now() - startAt),
163
- method,
164
- url,
165
- statusCode,
166
- bodyPreview: preview,
167
- ...ctx,
168
- });
169
- } catch {}
170
- return end(chunk, enc, cb);
171
- };
172
- try {
173
- res.on('close', () => {
174
- try {
175
- const ended =
176
- typeof res.writableEnded === 'boolean' ? res.writableEnded : false;
177
- if (!ended) {
178
- const ctx = getCtx();
179
- print({
180
- type: 'httpAbort',
181
- timestampMs: Date.now(),
182
- durationMs: Math.max(0, Date.now() - startAt),
183
- method,
184
- url,
185
- ...ctx,
186
- });
187
- }
188
- } catch {}
189
- });
190
- } catch {}
191
- }
192
- } catch {}
193
- return originalEmit.apply(this, arguments);
194
- };
195
- patched[PATCH_FLAG] = true;
196
- patched[ORIGINAL_KEY] = originalEmit;
197
- http.Server.prototype.emit = patched;
198
- }
199
- } catch {}
200
- } catch {}
201
- })();
package/scripts/build.mjs DELETED
@@ -1,123 +0,0 @@
1
- import { rm, mkdir, writeFile, chmod, cp } from 'node:fs/promises';
2
- import { resolve } from 'node:path';
3
-
4
- // eslint-disable-next-line import/no-extraneous-dependencies
5
- import { build } from 'esbuild';
6
-
7
- const root = resolve(new URL('.', import.meta.url).pathname, '..');
8
- const src = resolve(root, 'src');
9
- const dist = resolve(root, 'dist');
10
-
11
- await rm(dist, { recursive: true, force: true });
12
- await mkdir(dist, { recursive: true });
13
-
14
- // Build ESM library output (index.js)
15
- await build({
16
- entryPoints: [resolve(src, 'index.ts')],
17
- outdir: dist,
18
- format: 'esm',
19
- platform: 'node',
20
- target: ['node18'],
21
- bundle: true,
22
- sourcemap: true,
23
- external: [
24
- 'fs',
25
- 'path',
26
- 'os',
27
- 'crypto',
28
- 'stream',
29
- 'util',
30
- 'events',
31
- 'assert',
32
- 'buffer',
33
- 'querystring',
34
- 'url',
35
- 'http',
36
- 'https',
37
- 'zlib',
38
- 'child_process',
39
- 'cluster',
40
- 'dgram',
41
- 'dns',
42
- 'domain',
43
- 'http2',
44
- 'net',
45
- 'perf_hooks',
46
- 'process',
47
- 'punycode',
48
- 'readline',
49
- 'repl',
50
- 'string_decoder',
51
- 'tls',
52
- 'tty',
53
- 'v8',
54
- 'vm',
55
- 'worker_threads',
56
- // Keep Istanbul libs external to avoid bundling CJS that requires('fs')
57
- // which breaks in ESM bundles on Node 20+ with dynamic require shim
58
- 'istanbul-lib-coverage',
59
- 'istanbul-lib-report',
60
- 'istanbul-reports',
61
- ],
62
- });
63
-
64
- // Build CJS CLI output (cli.cjs) to support CJS-only deps and dynamic require
65
- await build({
66
- entryPoints: [resolve(src, 'cli.ts')],
67
- outfile: resolve(dist, 'cli.cjs'),
68
- format: 'cjs',
69
- platform: 'node',
70
- target: ['node18'],
71
- bundle: true,
72
- sourcemap: true,
73
- external: [
74
- // keep Node core externals trivial
75
- 'fs',
76
- 'path',
77
- 'os',
78
- 'crypto',
79
- 'stream',
80
- 'util',
81
- 'events',
82
- 'assert',
83
- 'buffer',
84
- 'querystring',
85
- 'url',
86
- 'http',
87
- 'https',
88
- 'zlib',
89
- 'child_process',
90
- 'cluster',
91
- 'dgram',
92
- 'dns',
93
- 'domain',
94
- 'http2',
95
- 'net',
96
- 'perf_hooks',
97
- 'process',
98
- 'punycode',
99
- 'readline',
100
- 'repl',
101
- 'string_decoder',
102
- 'tls',
103
- 'tty',
104
- 'v8',
105
- 'vm',
106
- 'worker_threads',
107
- // Externalize Istanbul + picomatch so their internal dynamic requires resolve correctly
108
- 'istanbul-lib-coverage',
109
- 'istanbul-lib-report',
110
- 'istanbul-reports',
111
- 'picomatch',
112
- ],
113
- });
114
-
115
- // Create a Node shebang for the CLI
116
- const cliPath = resolve(dist, 'cli.cjs');
117
- const cliContent = await (await import('node:fs/promises')).readFile(cliPath, 'utf8');
118
- await writeFile(cliPath, `#!/usr/bin/env node\n${cliContent}`);
119
- await chmod(cliPath, 0o755);
120
-
121
- // Copy Jest runtime assets (reporter/setup) to dist so Jest can require them by absolute path
122
- await mkdir(resolve(dist, 'jest'), { recursive: true });
123
- await cp(resolve(src, 'jest'), resolve(dist, 'jest'), { recursive: true });
@@ -1,13 +0,0 @@
1
- import { chmod } from 'node:fs/promises';
2
- import { resolve } from 'node:path';
3
-
4
- const EXECUTABLE_MODE = 0o755;
5
-
6
- (async () => {
7
- try {
8
- const cli = resolve(new URL('.', import.meta.url).pathname, '..', 'dist', 'cli.cjs');
9
- await chmod(cli, EXECUTABLE_MODE);
10
- } catch {
11
- // ignore (best-effort)
12
- }
13
- })();
@@ -1,29 +0,0 @@
1
- import { readFile } from 'node:fs/promises';
2
- import { resolve, dirname } from 'node:path';
3
- import { fileURLToPath } from 'node:url';
4
-
5
- const __dirname = dirname(fileURLToPath(import.meta.url));
6
- const rootDir = resolve(__dirname, '..');
7
-
8
- const pkgJsonPath = resolve(rootDir, 'package.json');
9
- const pkgRaw = await readFile(pkgJsonPath, 'utf8');
10
- const pkg = JSON.parse(pkgRaw);
11
-
12
- const date = new Date();
13
- // Detect the user's/system timezone; fall back to TZ env or UTC if unavailable
14
- const tz = Intl.DateTimeFormat().resolvedOptions().timeZone ?? process.env.TZ ?? 'UTC';
15
- // Friendly: "5:58 PM" (narrow no-break space before AM/PM to prevent wrapping)
16
- const ts = new Intl.DateTimeFormat('en-US', {
17
- hour: 'numeric',
18
- minute: '2-digit',
19
- hour12: true,
20
- timeZone: tz,
21
- // If you want "CDT"/"CST", uncomment:
22
- // timeZoneName: 'short',
23
- })
24
- .format(date)
25
- .replace(' AM', '\u202FAM')
26
- .replace(' PM', '\u202FPM');
27
-
28
- // eslint-disable-next-line no-console
29
- console.log(`[${ts}] ${pkg.name}@${pkg.version} published in store.`);