Files
camino-package-runtime/dist/queries.js
T

58 lines
2.3 KiB
JavaScript

import { decodeQxValue } from "./bindings.js";
export function decodeQuerySnapshot(response, output, runId, sequence) {
if (response.preparationToken || response.residualWindows.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 }),
};
}