mirror of
https://github.com/morluto/rea
synced 2026-10-26 14:25:49 -04:00
5d2c8c2b78
* feat(cli): add JSON Lines output for row-oriented results (#5487) - Support opt-in JSON Lines format (--format jsonl) for row-oriented results and collection views with clear record boundaries - Preserve stable source identities and stream records deterministically line-by-line - Emit final coverage and limitation metadata as a distinct line with https://rea.dev/schemas/jsonl-coverage-v1.json to prevent confusion with data rows - Distinguish error outputs with https://rea.dev/schemas/jsonl-error-v1.json - Reject non-row-oriented results that lack record boundaries with an unreadable_output error - Document JSON Lines streaming conventions in docs/cli.md - Add boundary tests covering empty results, multiline strings, partial coverage, large fields, and non-row rejection * fix(cli): preserve diagnostics, provenance, and nested collections in JSONL * fix(cli): frame classified failures and reject unrepresented JSONL facets --------- Co-authored-by: gensokyo-dev <342580529+gensokyo-dev@users.noreply.github.com>
104 lines
3.6 KiB
TypeScript
104 lines
3.6 KiB
TypeScript
import { readFile } from "node:fs/promises";
|
|
import { randomUUID } from "node:crypto";
|
|
import { mkdir } from "node:fs/promises";
|
|
import { join } from "node:path";
|
|
|
|
import { expect } from "vitest";
|
|
import { z } from "zod";
|
|
|
|
import { versionReportSchema } from "../../../src/domain/versionReport.js";
|
|
import { SUPPORTED_NODE_VERSION_RANGE } from "../../../src/domain/runtimeVersion.js";
|
|
import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js";
|
|
import { cliTest } from "../../support/cli/cliFixture.js";
|
|
|
|
const packageSchema = z.object({ name: z.string(), version: z.string() });
|
|
|
|
cliTest(
|
|
"reports version and runtime as a document only when a format is selected",
|
|
async ({ cli }) => {
|
|
const { name, version } = packageSchema.parse(
|
|
JSON.parse(await readFile("package.json", "utf8")),
|
|
);
|
|
// Unique private values: the report must carry none of them. Literal
|
|
// report values such as "node" or "linux" cannot collide with these.
|
|
const marker = `rea-private-${randomUUID()}`;
|
|
const cwd = await createTestTempDirectory(`${marker}-cwd-`);
|
|
const home = join(cwd, `${marker}-home`);
|
|
await mkdir(home);
|
|
const environment = {
|
|
HOME: home,
|
|
USERPROFILE: home,
|
|
REA_VERSION_REPORT_PRIVATE_MARKER: marker,
|
|
};
|
|
|
|
const json = await cli.run({
|
|
arguments: ["--version", "--json"],
|
|
cwd,
|
|
environment,
|
|
});
|
|
expect(json.exitCode, json.stderr).toBe(0);
|
|
// Piped JSON is one compact document.
|
|
expect(json.stdout.trimEnd().split("\n")).toHaveLength(1);
|
|
const report = versionReportSchema.parse(JSON.parse(json.stdout));
|
|
expect(report).toEqual({
|
|
name,
|
|
version,
|
|
runtime: { id: "node", version: process.versions.node },
|
|
platform: process.platform,
|
|
architecture: process.arch,
|
|
supported_runtime: {
|
|
range: SUPPORTED_NODE_VERSION_RANGE,
|
|
satisfied: true,
|
|
},
|
|
});
|
|
expect(json.stdout).not.toContain(marker);
|
|
|
|
const jsonl = await cli.run({
|
|
arguments: ["--version", "--format", "jsonl"],
|
|
cwd,
|
|
environment,
|
|
});
|
|
expect(jsonl.exitCode, jsonl.stderr).toBe(0);
|
|
expect(jsonl.stdout.trimEnd().split("\n")).toHaveLength(1);
|
|
expect(versionReportSchema.parse(JSON.parse(jsonl.stdout))).toEqual(report);
|
|
|
|
const yaml = await cli.run({
|
|
arguments: ["--version", "--format=yaml"],
|
|
cwd,
|
|
});
|
|
expect(yaml.exitCode, yaml.stderr).toBe(0);
|
|
expect(yaml.stdout).toContain(`version: ${version}`);
|
|
expect(yaml.stdout).toContain(`architecture: ${process.arch}`);
|
|
|
|
// Plain --version keeps the bare version string.
|
|
const plain = await cli.run({ arguments: ["--version"], cwd });
|
|
expect(plain.exitCode, plain.stderr).toBe(0);
|
|
expect(plain.stdout).toBe(`${version}\n`);
|
|
|
|
// Valid other output controls keep the plain version; invalid
|
|
// combinations keep their existing output-flag error.
|
|
const filtered = await cli.run({
|
|
arguments: ["--version", "--json", "--filter-output", "version"],
|
|
cwd,
|
|
});
|
|
expect(filtered.exitCode, filtered.stderr).toBe(0);
|
|
expect(filtered.stdout).toBe(`${version}\n`);
|
|
const windowed = await cli.run({
|
|
arguments: ["--version", "--json", "--token-limit", "5"],
|
|
cwd,
|
|
});
|
|
expect(windowed.exitCode).toBe(1);
|
|
expect(windowed.json).toMatchObject({
|
|
error: { code: "UNSUPPORTED_OUTPUT_COMBINATION" },
|
|
});
|
|
|
|
// Help keeps precedence over --version.
|
|
const help = await cli.run({
|
|
arguments: ["--version", "--json", "--help"],
|
|
cwd,
|
|
});
|
|
expect(help.exitCode, help.stderr).toBe(0);
|
|
expect(help.stdout).toContain("Usage: rea");
|
|
},
|
|
);
|