How the Variable Validation System Works in Hyperframes Runtime
The Hyperframes runtime validates composition variables through a deterministic schema-based check that ensures type safety, required field presence, and enum constraints before rendering.
The heygen-com/hyperframes repository implements a strict variable validation system to prevent runtime errors in dynamic compositions. When a composition loads, the runtime executes the validation helper to compare supplied values against a declared schema extracted from the composition's metadata. This process ensures that rendering pipelines receive only well-typed, expected data, eliminating crashes caused by type mismatches or missing required fields.
Schema Declaration and Variable Types
Variables in Hyperframes are declared using a <script type="application/hyperframes-variables"> block within the composition HTML or via a standalone JSON configuration file. The schema defines each variable's type, whether it is required, allowed enum values, and optional default values. The parser in packages/core/src/parsers/htmlParser.ts extracts these declarations into a VariableDeclarationMap that serves as the validation contract.
Supported types include:
- string: Plain text values
- number: Numeric values rejecting
NaNandInfinity - boolean: Boolean values or string coercion of
"true"and"false" - enum: Values constrained to a specific set of allowed literals
- custom formats: Built-in patterns such as hex color strings
The Validation Pipeline
The core validation logic resides in packages/core/src/runtime/validateVariables.ts. The validateVariables function accepts a Record<string, unknown> of user-supplied values and a VariableDeclarationMap, returning an array of VariableValidationIssue objects.
Required Field Verification
The validator first iterates through the declaration map to identify missing required variables. If a required key is absent from the supplied data, the system pushes an issue with type "missing" containing the variable name.
Type-Specific Validation
For each supplied variable, the system performs strict type checking according to the schema definition:
- String validation: Verifies
typeof value === "string" - Number validation: Confirms
typeof value === "number"and explicitly rejectsNaNorInfinity - Boolean coercion: Accepts native booleans or the exact strings
"true"and"false"; other values generate an"invalid-boolean"issue - Enum constraints: Validates that the value exists within the declared
decl.valuesarray; mismatches produce"invalid-enum-value"issues listing the allowed options - Format validation: Applies regex patterns for declared formats, flagging failures as
"invalid-format"issues
Extra Field Detection
Any key present in the user-supplied object but missing from the declaration map is flagged as an "extra-field" issue. This strict matching prevents typos and undefined behavior in compositions.
Core Implementation
The following implementation from packages/core/src/runtime/validateVariables.ts illustrates the validation logic:
export function validateVariables(
vars: Record<string, unknown>,
decls: VariableDeclarationMap,
): VariableValidationIssue[] {
const issues: VariableValidationIssue[] = [];
// Check required variables
for (const [name, decl] of Object.entries(decls)) {
if (decl.required && !(name in vars)) {
issues.push({ type: "missing", name });
}
}
// Validate each supplied variable
for (const [name, value] of Object.entries(vars)) {
const decl = decls[name];
if (!decl) {
issues.push({ type: "extra-field", name });
continue;
}
// Type-specific checks
switch (decl.type) {
case "string":
if (typeof value !== "string") {
issues.push({ type: "type-mismatch", name, expected: "string" });
}
break;
case "number":
if (typeof value !== "number" || Number.isNaN(value)) {
issues.push({ type: "invalid-number", name });
}
break;
case "boolean":
if (typeof value !== "boolean" && !(value === "true" || value === "false")) {
issues.push({ type: "invalid-boolean", name });
}
break;
case "enum":
if (!decl.values?.includes(value as string)) {
issues.push({ type: "invalid-enum-value", name, allowed: decl.values! });
}
break;
// Add more custom format checks here
}
}
return issues;
}
Test Suite Examples
The test file packages/core/src/runtime/validateVariables.test.ts demonstrates expected behavior:
const DECLS = {
title: { type: "string", required: true },
count: { type: "number" },
active: { type: "boolean" },
theme: { type: "enum", values: ["midnight", "sunrise"] },
};
// Valid case
expect(validateVariables({ title: "Demo" }, DECLS)).toEqual([]);
// Missing required
expect(validateVariables({ }, DECLS)).toEqual([{type:"missing",name:"title"}]);
// Type mismatch
expect(validateVariables({ count: "three" }, DECLS)).toEqual([
{type:"type-mismatch",name:"count",expected:"number"}
]);
// Invalid enum
expect(validateVariables({ theme: "neon" }, DECLS)).toEqual([
{type:"invalid-enum-value",name:"theme",allowed:["midnight","sunrise"]}
]);
CLI and Programmatic Usage
Command-Line Interface
When using the Hyperframes CLI, developers pass variables via --var flags:
hyperframes render my-composition.html \
--var title="My Video" \
--var count=5 \
--var active=true \
--var theme=midnight
The CLI implementation in packages/cli/src/commands/render.ts parses these flags into an object and invokes validateVariables before executing the render pipeline.
Programmatic Integration
Custom plugins can import the validator directly:
import { validateVariables } from "hyperframes/core/runtime";
export function myPlugin(context) {
const vars = context.getCompositionVariables();
const schema = context.getVariableSchema();
const problems = validateVariables(vars, schema);
if (problems.length) {
throw new Error(`Invalid variables: ${problems.map(i => i.name).join(", ")}`);
}
// Variables validated - safe to proceed with rendering
}
Summary
- The variable validation system in Hyperframes runtime enforces type safety through a declarative schema extracted from composition metadata in
packages/core/src/parsers/htmlParser.ts. - The
validateVariablesfunction inpackages/core/src/runtime/validateVariables.tsperforms deterministic checks for required fields, type mismatches, enum constraints, and extra fields. - The system rejects
NaNandInfinityfor numeric types and coerces boolean strings while rejecting invalid formats. - Validation returns an array of
VariableValidationIssueobjects; an empty array indicates success and permits rendering to proceed. - Both CLI tools and programmatic APIs expose this validation layer to ensure deterministic composition rendering across all execution contexts.
Frequently Asked Questions
What happens if I pass an undefined variable to a Hyperframes composition?
The validator flags undefined values as type mismatches for non-optional fields. If the variable is declared as required in the schema, the system generates a "missing" issue. If the variable is optional but provided as undefined, it typically fails the type check for the declared type, resulting in a type-mismatch error.
Does Hyperframes support custom validation rules beyond the built-in types?
The current implementation supports custom format validation through regex patterns, such as hex color validation. However, complex custom validation logic requires manual implementation outside the validateVariables function. Developers can pre-validate variables programmatically using the exposed API before passing them to the runtime.
How does the runtime handle boolean values passed as strings?
The validation system accepts both native JavaScript booleans and the string literals "true" and "false", coercing them to proper boolean values. Any other string value generates an "invalid-boolean" validation issue, preventing ambiguous truthy or falsy interpretations that could cause rendering inconsistencies.
Where is the variable schema defined in a Hyperframes project?
The schema is declared within a <script type="application/hyperframes-variables"> block inside your composition HTML file, or alternatively via a separate JSON configuration. The parser in packages/core/src/parsers/htmlParser.ts extracts these declarations during the loading phase to create the VariableDeclarationMap used by the validator.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →