Files
rea/src/cliJsonInput.ts
T
Rudy Mizrahi Celekli 22acb0d5d7 fix(cli): reject invalid UTF-8 JSON file bytes (#613)
* fix(cli): reject invalid UTF-8 JSON file bytes

Signed-off-by: Rudy Celekli <47457359+rudycelekli@users.noreply.github.com>

* test(browser): preserve unknown with-scope loader bindings

Signed-off-by: Rudy Celekli <47457359+rudycelekli@users.noreply.github.com>

---------

Signed-off-by: Rudy Celekli <47457359+rudycelekli@users.noreply.github.com>
2026-10-06 02:10:11 +08:00

72 lines
2.0 KiB
TypeScript

import { readFile } from "node:fs/promises";
import { AnalysisInputError, projectAnalysisError } from "./domain/errors.js";
import type { JsonValue } from "./domain/jsonValue.js";
/** Parse inline JSON or one local JSON file for a CLI workflow. */
export const parseCliJsonInput = async (
value: string,
operation: string,
): Promise<
| { readonly ok: true; readonly value: unknown }
| { readonly ok: false; readonly error: JsonValue }
> => {
const inline = parseJson(value);
if (inline !== undefined) return { ok: true, value: inline };
if (["{", "["].includes(value.trimStart()[0] ?? ""))
return { ok: false, error: inputError(operation) };
try {
const parsed = parseJson(await readFile(value));
return parsed === undefined
? jsonFileError(value, operation, "invalid-json")
: { ok: true, value: parsed };
} catch {
return jsonFileError(value, operation, "read-failed");
}
};
const parseJson = (value: string | Uint8Array): unknown => {
try {
return JSON.parse(
typeof value === "string"
? value
: new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(
value,
),
);
} catch {
return undefined;
}
};
const inputError = (operation: string): JsonValue => ({
error: "Application workflow failed",
...projectAnalysisError(
new AnalysisInputError(operation, undefined, [
{ path: [], reason: "invalid_format", expected: "JSON" },
]),
),
});
const jsonFileError = (
path: string | undefined,
operation: string,
reason: "invalid-json" | "read-failed",
) => ({
ok: false as const,
error: {
error: "Application workflow failed",
...projectAnalysisError(
new AnalysisInputError(
operation,
undefined,
reason === "invalid-json"
? [{ path: [], reason: "invalid_format", expected: "JSON" }]
: [],
),
),
...(path === undefined ? {} : { input_path: path }),
input_reason: reason,
},
});