@vizij/value-json
v0.1.2
Published
Shared Value JSON helpers and types for Vizij wasm wrappers
Readme
@vizij/value-json
TypeScript definitions and helpers for Vizij’s Value/Shape ecosystem.
@vizij/value-json is the canonical TypeScript companion to vizij-api-core. It defines the normalised { type, data } value union, offers coercion utilities, and keeps every Vizij npm package (animation, node graph, orchestrator, renderer) speaking the same JSON dialect. Install it whenever your tooling, UI, or Node service needs to produce or consume Vizij values.
Table of Contents
- Overview
- Key Concepts
- Installation
- Key Types
- Utilities
- Usage Examples
- Development & Testing
- Related Packages
Overview
- Mirrors the canonical
{ type: "...", data: ... }envelope emitted by Vizij engines and WASM runtimes. - Accepts legacy
{ float: 1 },{ vec3: [...] }shapes for backwards compatibility while gently nudging you toward the normalised form. - Ships coercion helpers (
toValueJSON,valueAsNumber,valueAsTransform, etc.) that front-ends and tooling can rely on. - Ensures discriminants stay lowercase so string comparisons remain consistent across ecosystems.
Key Concepts
- ValueJSON – Union type that handles both canonical
{ type, data }payloads and legacy helpers ({ float: 1 },number[], primitives). - NormalizedValue – Strict
{ type, data }shape emitted by Vizij runtimes; useisNormalizedValueto detect it. - Shape Metadata – Optional
ShapeJSONstructures travel alongside values so tooling understands numeric layout (Vec3,Transform, etc.). - Coercion Helpers – Utilities (
toValueJSON,valueAsNumericArray,valueAsTransform, etc.) convert between loose JavaScript data and the strict Vizij schema.
Legacy conversion matrix
| Input form | toValueJSON output | Notes |
|------------|---------------------|-------|
| 42 | { type: "float", data: 42 } | Scalars normalise to floats. |
| true | { type: "bool", data: true } | Boolean primitives become tagged bools. |
| [0, 1, 2] | { type: "vec3", data: [0, 1, 2] } | Arrays of length 2/3/4 map to vec2/vec3/vec4; longer arrays become vector. |
| { vec3: [0, 1, 0] } | { type: "vec3", data: [0, 1, 0] } | Legacy objects are translated to canonical discriminants. |
| { transform: { translation: [0,0,0] } } | { type: "transform", data: { translation: [0,0,0], rotation: [0,0,0,1], scale: [1,1,1] } } | Missing axes are filled with defaults. |
| { enum: { tag: "State", value: { bool: true } } } | { type: "enum", data: ["State", { type: "bool", data: true }] } | Enum payloads normalise to [tag, value]. |
| { record: { a: { float: 1 }, b: { bool: false } } } | { type: "record", data: { a: { type: "float", data: 1 }, b: { type: "bool", data: false } } } | Nested structures recurse automatically. |
Anything that cannot be coerced throws, signalling that upstream JSON needs to be corrected.
Installation
pnpm add @vizij/value-json
# or npm install @vizij/value-jsonWithin the monorepo the package is built from vizij-rs/npm/@vizij/value-json.
Bundler Notes
- The published package ships both ESM (
dist/index.js) and CJS (dist/index.cjs) builds—Node and modern bundlers resolve the correct entry automatically viapackage.jsonexports. - Helpers are tree-shakeable; prefer
import { toValueJSON } from "@vizij/value-json"so unused utilities drop out of production builds. - Type definitions (
dist/index.d.ts) mirror the ESM entry and surface literal union types for discriminants, keeping TypeScript narrowing aligned with the Rust schema.
Key Types
type NormalizedValue =
| { type: "float"; data: number }
| { type: "vec3"; data: [number, number, number] }
| { type: "quat"; data: [number, number, number, number] }
| { type: "transform"; data: NormalizedTransform }
| { type: "vector"; data: number[] }
| { type: "enum"; data: [string, NormalizedValue] }
| { type: "record"; data: Record<string, NormalizedValue> }
| ...;
type ValueJSON = NormalizedValue | { float: number } | { vec3: number[] } | number | boolean | string | number[];NormalizedValue– canonical tagged union.ValueJSON– accepts both normalized values and legacy aliases/primitives for input convenience.ValueInput– alias forValueJSON | number[], used by staging helpers in other packages.NormalizedTransform–{ translation: [x,y,z], rotation: [x,y,z,w], scale: [x,y,z] }.
Working with ShapeJSON
- Shapes are optional metadata that mirror
vizij-api-core::Shape. When targeting Vizij runtimes, supply shapes for numeric types that benefit from validation (e.g.,Transform,Vectorof fixed length). - Helper
normalizeShape(exported alongside value helpers) converts{ id: "Vec3" }or legacy strings ("Vec3") into the canonical object. - When consuming data, rely on
value.shape ?? inferShape(value)—the helper returnsShapeJSONif provided; otherwise it infers from the value union.
Utilities
| Helper | Description |
|--------|-------------|
| toValueJSON(value: ValueInput): ValueJSON | Coerces primitives/arrays/legacy objects into the canonical union. |
| isNormalizedValue(value: ValueJSON): value is NormalizedValue | Type guard for lowercased { type, data } values. |
| valueAsNumber(value) | Extracts the first numeric component (floats, vectors, transforms, enums). |
| valueAsNumericArray(value, fallback = 0) | Flattens numeric payloads into an array. |
| valueAsVector(value) | Returns a numeric array or undefined if coercion fails. |
| valueAsTransform(value) | Returns a [translation, rotation, scale] tuple with defaults for missing components. |
| valueAsQuat, valueAsVec3, valueAsColorRgba, valueAsBool, valueAsText | Convenience accessors for common types. |
All readers return undefined when coercion fails, letting callers handle optional values explicitly.
Usage Examples
Normalising inputs before staging them into WASM bindings:
import { toValueJSON } from "@vizij/value-json";
import { Graph } from "@vizij/node-graph-wasm";
graph.stageInput("nodes.inputA.inputs.in", toValueJSON([1, 2, 3]));
graph.stageInput("nodes.mode.inputs.in", toValueJSON({ enum: { tag: "A", value: { float: 1 } } }));Reading values emitted by the animation engine:
import { valueAsNumber, valueAsTransform } from "@vizij/value-json";
const value = outputs.changes[0]?.value;
const scalar = valueAsNumber(value);
const transform = valueAsTransform(value);Type guard usage:
import { isNormalizedValue } from "@vizij/value-json";
if (isNormalizedValue(value)) {
console.log(value.type); // narrow to canonical discriminants
}Development & Testing
From the package directory:
pnpm install
pnpm testVitest covers coercion edge cases and regression scenarios. Add to the suite whenever you extend the helper surface.
Related Packages
vizij-api-core– Rust source of truth for Value/Shape types.@vizij/node-graph-wasm•@vizij/orchestrator-wasm•@vizij/animation-wasm– WASM packages that rely on these helpers.- React bindings (
@vizij/node-graph-react,@vizij/orchestrator-react,@vizij/animation-react) use the helpers to normalise staged inputs and render outputs.
Questions or improvements? Open an issue—aligned value handling keeps Vizij runtimes interoperable. 🔄
