UNPKG

@firfi/quint-connect

Version:

Model-based testing framework connecting Quint specifications to TypeScript implementations

76 lines • 3.38 kB
import { transformITFValue } from "@firfi/itf-trace-parser"; import { Effect, Option, Predicate, Schema } from "effect"; import { ItfOption } from "./schema.js"; export const buildEffectPicksDecoder = (picksShape) => (rawPicks) => Effect.gen(function* () { if (!Predicate.isObject(rawPicks)) { return yield* Schema.decodeUnknownEffect(picksShape)(rawPicks); } const decoded = {}; for (const [key, fieldSchema] of Object.entries(picksShape.fields)) { const raw = rawPicks[key]; if (raw === undefined) { decoded[key] = yield* Schema.decodeUnknownEffect(fieldSchema)(undefined); continue; } const value = yield* Schema.decodeUnknownEffect(ItfOption(fieldSchema))(raw); decoded[key] = value === undefined ? yield* Schema.decodeUnknownEffect(fieldSchema)(undefined) : value; } return yield* Schema.decodeUnknownEffect(Schema.toType(picksShape))(decoded); }); const formatIssues = (issues) => issues.map((issue) => issue.message).join(", "); const QuintSomePick = Schema.Struct({ tag: Schema.Literal("Some"), value: Schema.Unknown }); const QuintNonePick = Schema.Struct({ tag: Schema.Literal("None"), value: Schema.optional(Schema.Unknown) }); const QuintOptionPick = Schema.Union([QuintSomePick, QuintNonePick]); const QuintOptionTag = Schema.Struct({ tag: Schema.String }); 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; const decoded = Schema.decodeUnknownOption(QuintOptionPick)(raw); if (Option.isSome(decoded)) { return decoded.value.tag === "None" ? { present: false } : { present: true, value: decoded.value.value }; } const decodedTag = Schema.decodeUnknownOption(QuintOptionTag)(raw); if (Option.isSome(decodedTag)) { throw new Error(`pickFrom "${key}": expected Option tag "Some" or "None", got: "${decodedTag.value.tag}"`); } throw new Error(`pickFrom "${key}": expected Quint Option (Some/None), got: ${JSON.stringify(raw)}`); }; 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