@firfi/quint-connect
Version:
Model-based testing framework connecting Quint specifications to TypeScript implementations
72 lines • 3.12 kB
JavaScript
import { transformITFValue } from "@firfi/itf-trace-parser";
import { Effect, Schema } from "effect";
import { ItfOption } from "./schema.js";
const assumeNoSchemaRequirements = (schema) =>
// ItfOption preserves the action pick schema requirements, but extraction widens R.
schema;
export const buildEffectPicksDecoder = (picksShape) => (rawPicks) => Effect.gen(function* () {
if (typeof rawPicks !== "object" || rawPicks === null) {
return yield* Schema.decodeUnknown(Schema.Struct({}))(rawPicks);
}
const record = rawPicks;
const decoded = {};
for (const [key, fieldSchema] of Object.entries(picksShape.fields)) {
const schema = assumeNoSchemaRequirements(Schema.asSchema(fieldSchema));
const raw = record[key];
if (raw === undefined) {
decoded[key] = yield* Schema.decodeUnknown(schema)(undefined);
continue;
}
const value = yield* Schema.decodeUnknown(ItfOption(schema))(raw);
if (value === undefined) {
decoded[key] = yield* Schema.decodeUnknown(schema)(undefined);
continue;
}
decoded[key] = value;
}
return decoded;
});
const formatIssues = (issues) => issues.map((issue) => issue.message).join(", ");
const decodeStandardPickValueSync = (rawValue, key, schema) => {
const result = schema["~standard"].validate(transformITFValue(rawValue));
if (result instanceof Promise) {
throw new Error("pickFrom does not support async schemas");
}
if (result.issues) {
throw new Error(`pickFrom "${key}" validation failed: ${formatIssues(result.issues)}`);
}
return result.value;
};
const decodeStandardPickValue = async (rawValue, key, schema) => {
const result = await schema["~standard"].validate(transformITFValue(rawValue));
if (result.issues) {
throw new Error(`Pick "${key}" validation failed: ${formatIssues(result.issues)}`);
}
return result.value;
};
export const decodeStandardPicks = async (rawPicks, picksSchema) => {
const decoded = await Promise.all(Object.entries(picksSchema).map(async ([key, schema]) => [
key,
await decodeStandardPickValue(rawPicks[key], key, schema)
]));
return Object.fromEntries(decoded);
};
const unwrapQuintOptionPick = (raw, key) => {
if (raw === undefined)
return undefined;
if (typeof raw !== "object" || raw === null || !("tag" in raw)) {
throw new Error(`pickFrom "${key}": expected Quint Option (Some/None), got: ${JSON.stringify(raw)}`);
}
const variant = raw;
if (variant.tag === "None")
return { present: false };
if (variant.tag !== "Some") {
throw new Error(`pickFrom "${key}": expected Option tag "Some" or "None", got: "${variant.tag}"`);
}
return { present: true, value: variant.value };
};
export const pickFrom = (nondetPicks, key, schema) => {
const pick = unwrapQuintOptionPick(nondetPicks.get(key), key);
return pick === undefined || !pick.present ? undefined : decodeStandardPickValueSync(pick.value, key, schema);
};
//# sourceMappingURL=picks.js.map