@kraken-e2e/cli 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.
- package/LICENSE +674 -0
- package/bin/run.js +4 -0
- package/dist/commands/doctor.d.ts +11 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +24 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/init.d.ts +7 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +12 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/plugins/install.d.ts +13 -0
- package/dist/commands/plugins/install.d.ts.map +1 -0
- package/dist/commands/plugins/install.js +30 -0
- package/dist/commands/plugins/install.js.map +1 -0
- package/dist/commands/run.d.ts +13 -0
- package/dist/commands/run.d.ts.map +1 -0
- package/dist/commands/run.js +38 -0
- package/dist/commands/run.js.map +1 -0
- package/dist/commands/serve.d.ts +11 -0
- package/dist/commands/serve.d.ts.map +1 -0
- package/dist/commands/serve.js +31 -0
- package/dist/commands/serve.js.map +1 -0
- package/dist/doctor-report.d.ts +5 -0
- package/dist/doctor-report.d.ts.map +1 -0
- package/dist/doctor-report.js +54 -0
- package/dist/doctor-report.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -0
- package/dist/init-project.d.ts +9 -0
- package/dist/init-project.d.ts.map +1 -0
- package/dist/init-project.js +77 -0
- package/dist/init-project.js.map +1 -0
- package/dist/plugins-install.d.ts +17 -0
- package/dist/plugins-install.d.ts.map +1 -0
- package/dist/plugins-install.js +148 -0
- package/dist/plugins-install.js.map +1 -0
- package/dist/run-project.d.ts +17 -0
- package/dist/run-project.d.ts.map +1 -0
- package/dist/run-project.js +136 -0
- package/dist/run-project.js.map +1 -0
- package/dist/serve.d.ts +14 -0
- package/dist/serve.d.ts.map +1 -0
- package/dist/serve.js +182 -0
- package/dist/serve.js.map +1 -0
- package/package.json +57 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugins-install.js","sourceRoot":"","sources":["../src/plugins-install.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export interface RunProjectOptions {
|
|
2
|
+
readonly cwd?: string;
|
|
3
|
+
readonly configPath?: string;
|
|
4
|
+
readonly tags?: string;
|
|
5
|
+
readonly dryRun?: boolean;
|
|
6
|
+
/** Force the plain line renderer (default: Ink when TTY and not CI). */
|
|
7
|
+
readonly plain?: boolean;
|
|
8
|
+
/** All human-readable output flows through here (stdout discipline). */
|
|
9
|
+
readonly write: (line: string) => void;
|
|
10
|
+
}
|
|
11
|
+
export interface RunProjectResult {
|
|
12
|
+
readonly exitCode: number;
|
|
13
|
+
readonly runId?: string;
|
|
14
|
+
readonly eventsPath?: string;
|
|
15
|
+
}
|
|
16
|
+
export declare function runProject(options: RunProjectOptions): Promise<RunProjectResult>;
|
|
17
|
+
//# sourceMappingURL=run-project.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-project.d.ts","sourceRoot":"","sources":["../src/run-project.ts"],"names":[],"mappings":"AA6BA,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC;IAC1B,wEAAwE;IACxE,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;IACzB,wEAAwE;IACxE,QAAQ,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACxC;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;CAC9B;AA6BD,wBAAsB,UAAU,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAmHtF"}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `kraken run` pipeline, extracted from the oclif command so it is plain-
|
|
3
|
+
* function testable: load config → import the step registry → glob+compile
|
|
4
|
+
* features (dry-run analyzer) → build the driver registry → run on the
|
|
5
|
+
* orchestrator with Line+JSONL reporters.
|
|
6
|
+
*/
|
|
7
|
+
import { randomUUID } from 'node:crypto';
|
|
8
|
+
import { readFileSync } from 'node:fs';
|
|
9
|
+
import { isAbsolute, join, resolve } from 'node:path';
|
|
10
|
+
import { loadConfig } from '@kraken-e2e/config';
|
|
11
|
+
import { KrakenError } from '@kraken-e2e/contracts';
|
|
12
|
+
import { createHostContext, DriverRegistry, runScenarios, systemHostProbe, } from '@kraken-e2e/core';
|
|
13
|
+
import { compileFeatures, isStepRegistry } from '@kraken-e2e/gherkin';
|
|
14
|
+
import { createAllureReporter, createCtrfReporter, createJsonlReporter, createLineReporter, } from '@kraken-e2e/reporters';
|
|
15
|
+
import { InMemoryTransport, SignalBus } from '@kraken-e2e/signaling';
|
|
16
|
+
import { createJiti } from 'jiti';
|
|
17
|
+
import { glob } from 'tinyglobby';
|
|
18
|
+
async function importStepRegistry(projectRoot, stepsPath) {
|
|
19
|
+
const absolute = isAbsolute(stepsPath) ? stepsPath : resolve(projectRoot, stepsPath);
|
|
20
|
+
const jiti = createJiti(join(projectRoot, 'package.json'));
|
|
21
|
+
let moduleExports;
|
|
22
|
+
try {
|
|
23
|
+
moduleExports = (await jiti.import(absolute));
|
|
24
|
+
}
|
|
25
|
+
catch (cause) {
|
|
26
|
+
throw new KrakenError('KRK-CONFIG-INVALID', `Failed to load the steps module ${stepsPath}: ${cause instanceof Error ? cause.message : String(cause)}`, { cause, fix: 'Point config.steps at a module that exports your step `registry`.' });
|
|
27
|
+
}
|
|
28
|
+
const registry = moduleExports.registry;
|
|
29
|
+
// Brand check, not instanceof: jiti may load its own copy of @kraken-e2e/gherkin.
|
|
30
|
+
if (!isStepRegistry(registry)) {
|
|
31
|
+
throw new KrakenError('KRK-CONFIG-INVALID', `The steps module ${stepsPath} does not export a \`registry\` created by createStepRegistry().`, {
|
|
32
|
+
fix: 'export const { Given, When, Then, registry } = createStepRegistry(); — and import your step files from that module.',
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
return registry;
|
|
36
|
+
}
|
|
37
|
+
export async function runProject(options) {
|
|
38
|
+
const { write } = options;
|
|
39
|
+
const config = await loadConfig({
|
|
40
|
+
...(options.cwd !== undefined ? { cwd: options.cwd } : {}),
|
|
41
|
+
...(options.configPath !== undefined ? { configPath: options.configPath } : {}),
|
|
42
|
+
});
|
|
43
|
+
const registry = await importStepRegistry(config.projectRoot, config.steps ?? './steps/index.ts');
|
|
44
|
+
const featureFiles = await glob([...config.features], {
|
|
45
|
+
cwd: config.projectRoot,
|
|
46
|
+
absolute: true,
|
|
47
|
+
});
|
|
48
|
+
if (featureFiles.length === 0) {
|
|
49
|
+
write(`No feature files matched ${config.features.join(', ')} under ${config.projectRoot}.`);
|
|
50
|
+
return { exitCode: 1 };
|
|
51
|
+
}
|
|
52
|
+
const sources = featureFiles.sort().map((uri) => ({ uri, content: readFileSync(uri, 'utf8') }));
|
|
53
|
+
const actors = Object.entries(config.actors).map(([id, { platform, ...rest }]) => ({
|
|
54
|
+
id,
|
|
55
|
+
platform,
|
|
56
|
+
config: rest,
|
|
57
|
+
}));
|
|
58
|
+
// ── Dry-run analysis: ALWAYS runs; kraken refuses to start on errors ──
|
|
59
|
+
const compiled = compileFeatures({
|
|
60
|
+
sources,
|
|
61
|
+
registry,
|
|
62
|
+
actors,
|
|
63
|
+
...(options.tags !== undefined ? { tagFilter: options.tags } : {}),
|
|
64
|
+
});
|
|
65
|
+
for (const diagnostic of compiled.diagnostics) {
|
|
66
|
+
write(`${diagnostic.severity === 'error' ? '✗' : '!'} [${diagnostic.code}] ${diagnostic.uri}` +
|
|
67
|
+
`${diagnostic.scenario ? ` › ${diagnostic.scenario}` : ''}: ${diagnostic.message}`);
|
|
68
|
+
}
|
|
69
|
+
if (!compiled.ok) {
|
|
70
|
+
write('\nCompilation failed — nothing was executed (no sessions were booted).');
|
|
71
|
+
return { exitCode: 1 };
|
|
72
|
+
}
|
|
73
|
+
if (options.dryRun) {
|
|
74
|
+
write(`\nDry run OK: ${compiled.plans.length} scenario(s), ` +
|
|
75
|
+
`${compiled.plans.reduce((sum, plan) => sum + plan.nodes.length, 0)} step(s), ` +
|
|
76
|
+
`actors: ${[...new Set(compiled.plans.flatMap((plan) => plan.actors.map((actor) => actor.id)))].join(', ')}.`);
|
|
77
|
+
return { exitCode: 0 };
|
|
78
|
+
}
|
|
79
|
+
// ── Real execution ──
|
|
80
|
+
const host = systemHostProbe.detect();
|
|
81
|
+
const driverRegistry = await DriverRegistry.create({
|
|
82
|
+
registrations: config.drivers,
|
|
83
|
+
host,
|
|
84
|
+
projectRoot: config.projectRoot,
|
|
85
|
+
});
|
|
86
|
+
for (const status of driverRegistry.statuses()) {
|
|
87
|
+
if (status.state === 'unavailable-on-host') {
|
|
88
|
+
write(`! driver "${status.manifest.id}" disabled on this host: ${status.reason}`);
|
|
89
|
+
write(` fix: ${status.fix}`);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
const runId = randomUUID();
|
|
93
|
+
const artifactsDir = join(config.projectRoot, '.kraken', 'runs', runId);
|
|
94
|
+
const eventsPath = join(artifactsDir, 'events.jsonl');
|
|
95
|
+
// Renderer selection (ADR-0001 §5.11): Ink lanes on a TTY, plain lines
|
|
96
|
+
// otherwise — never Ink's final-frame CI mode for a long-running test run.
|
|
97
|
+
const live = options.plain !== true && process.stdout.isTTY === true && process.env['CI'] === undefined;
|
|
98
|
+
let finishInk;
|
|
99
|
+
let liveReporter = createLineReporter(write);
|
|
100
|
+
if (live) {
|
|
101
|
+
const { createInkReporter } = await import('@kraken-e2e/tui');
|
|
102
|
+
const handle = createInkReporter();
|
|
103
|
+
liveReporter = handle.reporter;
|
|
104
|
+
finishInk = handle.finish;
|
|
105
|
+
}
|
|
106
|
+
let result;
|
|
107
|
+
try {
|
|
108
|
+
result = await runScenarios({
|
|
109
|
+
plans: compiled.plans,
|
|
110
|
+
registry: driverRegistry,
|
|
111
|
+
signalBus: new SignalBus(new InMemoryTransport()),
|
|
112
|
+
hostContext: createHostContext(host, config.projectRoot),
|
|
113
|
+
reporters: [
|
|
114
|
+
liveReporter,
|
|
115
|
+
createJsonlReporter(eventsPath),
|
|
116
|
+
// ADR-0006 part B: Allure + CTRF are always-on projections (cheap).
|
|
117
|
+
createAllureReporter(join(artifactsDir, 'allure-results')),
|
|
118
|
+
createCtrfReporter(join(artifactsDir, 'ctrf-report.json')),
|
|
119
|
+
],
|
|
120
|
+
artifactsDir,
|
|
121
|
+
runId,
|
|
122
|
+
onReporterError: (reporterId, error) => write(`! reporter "${reporterId}" failed: ${error instanceof Error ? error.message : String(error)}`),
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
finally {
|
|
126
|
+
// The Ink instance MUST unmount on throw paths too (driver-start failures,
|
|
127
|
+
// host-disabled bindings) — a patched console with a frozen frame would
|
|
128
|
+
// swallow the error rendering otherwise.
|
|
129
|
+
await finishInk?.();
|
|
130
|
+
}
|
|
131
|
+
write(`\nEvent log: ${eventsPath}`);
|
|
132
|
+
write(`Allure results: ${join(artifactsDir, 'allure-results')} — html: npx allure generate <dir> -o <out>`);
|
|
133
|
+
write(`CTRF report: ${join(artifactsDir, 'ctrf-report.json')}`);
|
|
134
|
+
return { exitCode: result.status === 'passed' ? 0 : 1, runId, eventsPath };
|
|
135
|
+
}
|
|
136
|
+
//# sourceMappingURL=run-project.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-project.js","sourceRoot":"","sources":["../src/run-project.ts"],"names":[],"mappings":"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"}
|
package/dist/serve.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export interface ServeOptions {
|
|
2
|
+
/** The `.kraken/runs` directory to project. */
|
|
3
|
+
readonly runsDir: string;
|
|
4
|
+
readonly port?: number;
|
|
5
|
+
readonly host?: string;
|
|
6
|
+
readonly log?: (line: string) => void;
|
|
7
|
+
}
|
|
8
|
+
export interface ServeHandle {
|
|
9
|
+
readonly port: number;
|
|
10
|
+
readonly url: string;
|
|
11
|
+
close(): Promise<void>;
|
|
12
|
+
}
|
|
13
|
+
export declare function startServe(options: ServeOptions): Promise<ServeHandle>;
|
|
14
|
+
//# sourceMappingURL=serve.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serve.d.ts","sourceRoot":"","sources":["../src/serve.ts"],"names":[],"mappings":"AAoBA,MAAM,WAAW,YAAY;IAC3B,+CAA+C;IAC/C,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACvC;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAmED,wBAAsB,UAAU,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,WAAW,CAAC,CA2G5E"}
|
package/dist/serve.js
ADDED
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `kraken serve` (ADR-0001 §7 Phase 5): a GUI-ready projection server over
|
|
3
|
+
* the run artifacts on disk. BY CONSTRUCTION it needs zero core changes —
|
|
4
|
+
* it reads ONLY `.kraken/runs/<runId>/` (events.jsonl + artifacts), the same
|
|
5
|
+
* substrate every reporter projects from (ADR-0006 A3). Live runs stream
|
|
6
|
+
* through a WebSocket tail of the incrementally-written events.jsonl.
|
|
7
|
+
*
|
|
8
|
+
* Surface:
|
|
9
|
+
* GET / minimal built-in viewer (dependency-free HTML)
|
|
10
|
+
* GET /api/runs → run index (id, mtime, status)
|
|
11
|
+
* GET /api/runs/:id/events → full event log as JSON array
|
|
12
|
+
* GET /api/runs/:id/artifacts/<p> → artifact files (traversal-safe)
|
|
13
|
+
* WS /api/runs/:id/live → replay + live tail of events
|
|
14
|
+
*/
|
|
15
|
+
import { existsSync, readdirSync, readFileSync, statSync, watch } from 'node:fs';
|
|
16
|
+
import { createServer } from 'node:http';
|
|
17
|
+
import { join, normalize, resolve, sep } from 'node:path';
|
|
18
|
+
import { WebSocketServer } from 'ws';
|
|
19
|
+
function readEvents(runDir) {
|
|
20
|
+
const path = join(runDir, 'events.jsonl');
|
|
21
|
+
if (!existsSync(path))
|
|
22
|
+
return [];
|
|
23
|
+
return readFileSync(path, 'utf8')
|
|
24
|
+
.split('\n')
|
|
25
|
+
.filter((line) => line.trim().length > 0)
|
|
26
|
+
.map((line) => JSON.parse(line));
|
|
27
|
+
}
|
|
28
|
+
function summarize(runsDir, id) {
|
|
29
|
+
const dir = join(runsDir, id);
|
|
30
|
+
const events = readEvents(dir);
|
|
31
|
+
const last = [...events].reverse().find((event) => event['type'] === 'runFinished');
|
|
32
|
+
return {
|
|
33
|
+
id,
|
|
34
|
+
modifiedAt: statSync(dir).mtimeMs,
|
|
35
|
+
status: last
|
|
36
|
+
? last['status']
|
|
37
|
+
: events.length > 0
|
|
38
|
+
? 'running'
|
|
39
|
+
: 'unknown',
|
|
40
|
+
events: events.length,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
const VIEWER_HTML = `<!DOCTYPE html>
|
|
44
|
+
<html lang="en"><head><meta charset="utf-8"><title>Kraken serve</title>
|
|
45
|
+
<style>
|
|
46
|
+
body{font:14px ui-monospace,monospace;margin:2rem;background:#0d1117;color:#c9d1d9}
|
|
47
|
+
h1{color:#58a6ff} a{color:#58a6ff} .run{margin:.2rem 0}
|
|
48
|
+
#events{white-space:pre-wrap;border-top:1px solid #30363d;margin-top:1rem;padding-top:1rem}
|
|
49
|
+
.passed{color:#3fb950}.failed{color:#f85149}.running{color:#d29922}
|
|
50
|
+
</style></head><body>
|
|
51
|
+
<h1>🦑 kraken serve</h1>
|
|
52
|
+
<div id="runs">loading…</div><div id="events"></div>
|
|
53
|
+
<script>
|
|
54
|
+
const runsEl = document.getElementById('runs'), eventsEl = document.getElementById('events');
|
|
55
|
+
async function load() {
|
|
56
|
+
const runs = await (await fetch('/api/runs')).json();
|
|
57
|
+
runsEl.innerHTML = runs.length ? '' : 'no runs yet';
|
|
58
|
+
for (const run of runs) {
|
|
59
|
+
const div = document.createElement('div'); div.className = 'run';
|
|
60
|
+
div.innerHTML = '<span class="' + run.status + '">' + run.status + '</span> <a href="#" data-id="' +
|
|
61
|
+
run.id + '">' + run.id + '</a> (' + run.events + ' events)';
|
|
62
|
+
div.querySelector('a').onclick = (e) => { e.preventDefault(); tail(run.id); };
|
|
63
|
+
runsEl.appendChild(div);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
let socket;
|
|
67
|
+
function tail(id) {
|
|
68
|
+
socket?.close();
|
|
69
|
+
eventsEl.textContent = '── live: ' + id + '\\n';
|
|
70
|
+
socket = new WebSocket('ws://' + location.host + '/api/runs/' + id + '/live');
|
|
71
|
+
socket.onmessage = (message) => { eventsEl.textContent += message.data + '\\n'; };
|
|
72
|
+
}
|
|
73
|
+
load(); setInterval(load, 3000);
|
|
74
|
+
</script></body></html>`;
|
|
75
|
+
export async function startServe(options) {
|
|
76
|
+
const { runsDir } = options;
|
|
77
|
+
const log = options.log ?? (() => { });
|
|
78
|
+
const server = createServer((req, res) => {
|
|
79
|
+
const url = new URL(req.url ?? '/', 'http://localhost');
|
|
80
|
+
const parts = url.pathname.split('/').filter(Boolean);
|
|
81
|
+
try {
|
|
82
|
+
if (url.pathname === '/') {
|
|
83
|
+
res.writeHead(200, { 'content-type': 'text/html; charset=utf-8' });
|
|
84
|
+
res.end(VIEWER_HTML);
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
if (url.pathname === '/api/runs') {
|
|
88
|
+
const runs = existsSync(runsDir)
|
|
89
|
+
? readdirSync(runsDir)
|
|
90
|
+
.filter((entry) => statSync(join(runsDir, entry)).isDirectory())
|
|
91
|
+
.map((id) => summarize(runsDir, id))
|
|
92
|
+
.sort((a, b) => b.modifiedAt - a.modifiedAt)
|
|
93
|
+
: [];
|
|
94
|
+
res.writeHead(200, { 'content-type': 'application/json' });
|
|
95
|
+
res.end(JSON.stringify(runs));
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
if (parts[0] === 'api' && parts[1] === 'runs' && parts[3] === 'events' && parts[2]) {
|
|
99
|
+
res.writeHead(200, { 'content-type': 'application/json' });
|
|
100
|
+
res.end(JSON.stringify(readEvents(join(runsDir, parts[2]))));
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
if (parts[0] === 'api' && parts[1] === 'runs' && parts[3] === 'artifacts' && parts[2]) {
|
|
104
|
+
// Traversal-safe: the resolved path must stay inside the run dir.
|
|
105
|
+
const runDir = resolve(runsDir, parts[2]);
|
|
106
|
+
const target = normalize(resolve(runDir, parts.slice(4).join(sep)));
|
|
107
|
+
if (!target.startsWith(runDir + sep) || !existsSync(target) || !statSync(target).isFile()) {
|
|
108
|
+
res.writeHead(404);
|
|
109
|
+
res.end('not found');
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
const type = target.endsWith('.png')
|
|
113
|
+
? 'image/png'
|
|
114
|
+
: target.endsWith('.json') || target.endsWith('.jsonl')
|
|
115
|
+
? 'application/json'
|
|
116
|
+
: 'text/plain; charset=utf-8';
|
|
117
|
+
res.writeHead(200, { 'content-type': type });
|
|
118
|
+
res.end(readFileSync(target));
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
res.writeHead(404);
|
|
122
|
+
res.end('not found');
|
|
123
|
+
}
|
|
124
|
+
catch (cause) {
|
|
125
|
+
res.writeHead(500);
|
|
126
|
+
res.end(cause instanceof Error ? cause.message : 'internal error');
|
|
127
|
+
}
|
|
128
|
+
});
|
|
129
|
+
// WS live tail: replay everything written so far, then follow appends.
|
|
130
|
+
const wss = new WebSocketServer({ server });
|
|
131
|
+
wss.on('connection', (socket, req) => {
|
|
132
|
+
const match = /^\/api\/runs\/([^/]+)\/live$/.exec(req.url ?? '');
|
|
133
|
+
if (!match || match[1] === undefined) {
|
|
134
|
+
socket.close(4004, 'unknown endpoint');
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
const eventsPath = join(runsDir, match[1], 'events.jsonl');
|
|
138
|
+
let offset = 0;
|
|
139
|
+
const push = () => {
|
|
140
|
+
if (!existsSync(eventsPath))
|
|
141
|
+
return;
|
|
142
|
+
const content = readFileSync(eventsPath, 'utf8');
|
|
143
|
+
if (content.length <= offset)
|
|
144
|
+
return;
|
|
145
|
+
const fresh = content.slice(offset);
|
|
146
|
+
offset = content.length;
|
|
147
|
+
for (const line of fresh.split('\n')) {
|
|
148
|
+
if (line.trim().length > 0)
|
|
149
|
+
socket.send(line);
|
|
150
|
+
}
|
|
151
|
+
};
|
|
152
|
+
push();
|
|
153
|
+
const dir = join(runsDir, match[1]);
|
|
154
|
+
const watcher = existsSync(dir) ? watch(dir, () => push()) : undefined;
|
|
155
|
+
// fs.watch coalesces; a slow poll catches missed notifications.
|
|
156
|
+
const poll = setInterval(push, 500);
|
|
157
|
+
socket.on('close', () => {
|
|
158
|
+
watcher?.close();
|
|
159
|
+
clearInterval(poll);
|
|
160
|
+
});
|
|
161
|
+
});
|
|
162
|
+
await new Promise((resolvePromise) => server.listen(options.port ?? 0, options.host ?? '127.0.0.1', resolvePromise));
|
|
163
|
+
const address = server.address();
|
|
164
|
+
const port = address !== null && typeof address === 'object' ? address.port : 0;
|
|
165
|
+
const url = `http://${options.host ?? '127.0.0.1'}:${port}`;
|
|
166
|
+
log(`kraken serve listening on ${url} (runs: ${runsDir})`);
|
|
167
|
+
return {
|
|
168
|
+
port,
|
|
169
|
+
url,
|
|
170
|
+
close: async () => {
|
|
171
|
+
for (const client of wss.clients)
|
|
172
|
+
client.terminate();
|
|
173
|
+
await new Promise((resolvePromise, rejectPromise) => {
|
|
174
|
+
wss.close((error) => (error ? rejectPromise(error) : resolvePromise()));
|
|
175
|
+
});
|
|
176
|
+
await new Promise((resolvePromise, rejectPromise) => {
|
|
177
|
+
server.close((error) => (error ? rejectPromise(error) : resolvePromise()));
|
|
178
|
+
});
|
|
179
|
+
},
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
//# sourceMappingURL=serve.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serve.js","sourceRoot":"","sources":["../src/serve.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@kraken-e2e/cli",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "The kraken CLI (oclif): run, doctor, init, plugins — the composition layer wiring all packages together",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"exports": {
|
|
7
|
+
".": {
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"default": "./dist/index.js"
|
|
10
|
+
},
|
|
11
|
+
"./package.json": "./package.json"
|
|
12
|
+
},
|
|
13
|
+
"files": [
|
|
14
|
+
"bin",
|
|
15
|
+
"dist",
|
|
16
|
+
"LICENSE"
|
|
17
|
+
],
|
|
18
|
+
"sideEffects": false,
|
|
19
|
+
"engines": {
|
|
20
|
+
"node": ">=22.13.0"
|
|
21
|
+
},
|
|
22
|
+
"dependencies": {
|
|
23
|
+
"@oclif/core": "^4.11.0",
|
|
24
|
+
"jiti": "^2.7.0",
|
|
25
|
+
"tinyglobby": "^0.2.0",
|
|
26
|
+
"ws": "^8.18.0",
|
|
27
|
+
"@kraken-e2e/contracts": "0.1.0",
|
|
28
|
+
"@kraken-e2e/core": "0.1.0",
|
|
29
|
+
"@kraken-e2e/config": "0.1.0",
|
|
30
|
+
"@kraken-e2e/doctor": "0.1.0",
|
|
31
|
+
"@kraken-e2e/reporters": "1.0.0",
|
|
32
|
+
"@kraken-e2e/gherkin": "0.1.0",
|
|
33
|
+
"@kraken-e2e/tui": "0.1.0",
|
|
34
|
+
"@kraken-e2e/signaling": "0.1.0"
|
|
35
|
+
},
|
|
36
|
+
"devDependencies": {
|
|
37
|
+
"@types/node": "^22.15.0",
|
|
38
|
+
"typescript": "~6.0.3",
|
|
39
|
+
"vitest": "^4.1.9",
|
|
40
|
+
"@types/ws": "^8.18.0"
|
|
41
|
+
},
|
|
42
|
+
"bin": {
|
|
43
|
+
"kraken": "./bin/run.js"
|
|
44
|
+
},
|
|
45
|
+
"oclif": {
|
|
46
|
+
"bin": "kraken",
|
|
47
|
+
"dirname": "kraken",
|
|
48
|
+
"commands": "./dist/commands",
|
|
49
|
+
"topicSeparator": " "
|
|
50
|
+
},
|
|
51
|
+
"license": "GPL-3.0-only",
|
|
52
|
+
"scripts": {
|
|
53
|
+
"build": "tsc -p tsconfig.build.json",
|
|
54
|
+
"typecheck": "tsc --noEmit",
|
|
55
|
+
"test": "vitest run"
|
|
56
|
+
}
|
|
57
|
+
}
|