fix(cli): project nested array slices

This commit is contained in:
morluto committed 2026-10-27 12:06:29 +08:00
1 parent 2f27d3ac92
commit 47a8000cce
3 files changed
+82 -1

No files matched your search

+9 -1
View File
@@ -552,6 +552,11 @@ type FilterPath = FilterPaths[number];
/** Apply Incur's parsed path grammar while merging sibling array selections. */
const applyCliOutputFilter = (value: unknown, paths: FilterPaths): unknown => {
if (paths.length === 0) return value;
if (
Array.isArray(value) &&
paths.some((path) => path[0] !== undefined && "start" in path[0])
)
return projectArraySlices(value, paths);
if (Array.isArray(value))
return value.map((item) => applyCliOutputFilter(item, paths));
if (
@@ -638,7 +643,10 @@ const projectArraySlices = (
const siblings = selected.get(index)!;
const item = source[index];
if (siblings.some((path) => path.length === 0)) return item;
return projectObjectPaths(item, siblings);
return Array.isArray(item) &&
siblings.some((path) => path[0] !== undefined && "start" in path[0])
? projectArraySlices(item, siblings)
: projectObjectPaths(item, siblings);
});
};
@@ -34,6 +34,42 @@ import { cliTest, runFileCli } from "../support/cli/cliFixture.js";
const digest = (bytes: Buffer): string =>
createHash("sha256").update(bytes).digest("hex");
cliTest(
"projects selected SQLite matrix cells through consecutive output slices",
async ({ cli }) => {
const root = await createTestTempDirectory("rea-sqlite-matrix-filter-");
const path = join(root, "selected.db");
const database = new DatabaseSync(path);
try {
database.exec(
"CREATE TABLE selected (first TEXT, second TEXT); INSERT INTO selected VALUES ('left', 'right')",
);
} finally {
database.close();
}
const result = await cli.run({
arguments: [
"inspect-sqlite-database",
path,
"--table",
"selected",
"--column",
"second",
"--column",
"first",
"--json",
"--filter-output",
"normalized_result.rows.values[0,1][0,1].value",
],
environment: { REA_LOG_LEVEL: "silent" },
});
expect(result.exitCode, result.stdout + result.stderr).toBe(0);
expect(result.json).toEqual({
normalized_result: { rows: { values: [[{ value: "right" }]] } },
});
},
);
for (const expectedErrno of ["ELOOP", "ENAMETOOLONG"] as const) {
cliTest.skipIf(expectedErrno === "ELOOP" && process.platform === "win32")(
`reports an initial ${expectedErrno} path failure through CLI and MCP`,
@@ -322,6 +322,43 @@ const overlappingPaths = [
"rows[1,4].right,rows[0,3].left",
] as const;
it("projects consecutive slices through nested root arrays and merges cell fields", async () => {
const value = freezeRecursively([
[
{ left: 1, right: 2 },
{ left: 3, right: 4 },
],
[{ left: 5, right: 6 }],
]);
const output = await runFilteredCli(
value,
"json",
"[0,2][0,1].left,[0,1][0,2].right",
);
expect(JSON.parse(output)).toEqual([
[{ left: 1, right: 2 }, { right: 4 }],
[{ left: 5 }],
]);
});
it.each([
["rows[0,2][-2,-1]", { rows: [[1], [3]] }],
["rows[0,2][1,1]", { rows: [[], []] }],
["rows[0,2][invalid,1]", { rows: [[1], [3]] }],
] as const)("retains parsed slice bounds for %s", async (filter, expected) => {
const output = await runFilteredCli(
{
rows: [
[1, 2],
[3, 4],
],
},
"json",
filter,
);
expect(JSON.parse(output)).toEqual(expected);
});
it.each(["json", "jsonl", "yaml", "toon", "md"] as const)(
"unions overlapping sibling slices independent of path order in %s",
async (format) => {