58 lines
2.4 KiB
JavaScript
58 lines
2.4 KiB
JavaScript
import { decodeQxValue } from "./bindings.js";
|
|
export function decodeQuerySnapshot(response, output, runId, sequence) {
|
|
if (response.preparationToken || response.residualWindows.length || response.relationalCaptures.length)
|
|
throw new Error("QUERY_RESULT_UNFINISHED: private preparation is not a query result");
|
|
const fields = [
|
|
...response.pending.map((field) => ({ path: field.path, status: "pending" })),
|
|
...response.errors.map((field) => ({ path: field.path, status: "error", error: field.error })),
|
|
].map((field) => ({
|
|
...field,
|
|
path: field.path.map((part) => {
|
|
if (part.part.case !== "field" && part.part.case !== "index")
|
|
throw new Error("QUERY_PATCH_INVALID");
|
|
return part.part.value;
|
|
}),
|
|
}));
|
|
// Pending/error values are absent, not successful nulls of a scalar type.
|
|
const shape = structuredClone(output);
|
|
for (const field of fields) {
|
|
let cursor = shape;
|
|
for (const [index, part] of field.path.entries()) {
|
|
while (cursor.kind === "optional")
|
|
cursor = cursor.value;
|
|
const last = index === field.path.length - 1;
|
|
if (typeof part === "string" && cursor.kind === "record" && cursor.fields[part]) {
|
|
if (last)
|
|
cursor.fields[part] = { kind: "optional", value: cursor.fields[part] };
|
|
else
|
|
cursor = cursor.fields[part];
|
|
}
|
|
else if (typeof part === "number" && cursor.kind === "list")
|
|
cursor = cursor.value;
|
|
else
|
|
throw new Error("QUERY_PATCH_INVALID");
|
|
}
|
|
}
|
|
const data = decodeQxValue(shape, response.value, {});
|
|
for (const field of fields) {
|
|
let cursor = data;
|
|
for (const [index, part] of field.path.entries()) {
|
|
if (!cursor || typeof cursor !== "object")
|
|
throw new Error("QUERY_PATCH_INVALID");
|
|
if (index === field.path.length - 1)
|
|
delete cursor[part];
|
|
else
|
|
cursor = cursor[part];
|
|
}
|
|
}
|
|
return {
|
|
runId,
|
|
sequence,
|
|
dataVersion: response.dataVersion,
|
|
bindingDigest: response.bindingDigest,
|
|
consistency: response.consistency,
|
|
fields,
|
|
...(fields.length ? { status: "partial", data } : { status: "ready", data }),
|
|
};
|
|
}
|