Skip to content

@zenfg/snapshot

@zenfg/snapshot owns the portable, versioned diagnostic contract used to move one compiled FrameGraph frame between producers and viewers. It provides the Snapshot 1.2 wire types, codec, validator, JSON Schema, fixtures, migration, and conformance corpus without depending on DOM, WebGPU, or a FrameGraph runtime.

Snapshot files contain graph structure and diagnostics, not GPU commands or resource contents, and cannot replay a frame. Snapshot wire-format versioning is independent from this package's beta API version.

Snapshot 1.1 inputs are validated before migration to 1.2; their CPU timing is marked not-collected. Writers and standalone validators accept canonical 1.2 only. Existing Legacy provenance and extensions are preserved.

Installation

sh
npm install @zenfg/snapshot@0.1.0

Quick start

Use an ESM TypeScript project targeting ES2022 or later. This package works without DOM or GPU objects. Call normalizeSnapshot(jsonText) with captured Snapshot JSON; a valid input returns formatted canonical JSON, and an invalid input reports its issues.

Use parseFrameGraphSnapshot() for untrusted JSON text. Supported legacy formats are migrated to a detached canonical Snapshot 1.2 value:

ts
import {
	parseFrameGraphSnapshot,
	stringifyFrameGraphSnapshot,
} from '@zenfg/snapshot';

export function normalizeSnapshot(jsonText: string): string {
	const decoded = parseFrameGraphSnapshot(jsonText);
	if (!decoded.ok) {
		throw new Error(decoded.issues.map((issue) => issue.message).join('\n'));
	}
	return stringifyFrameGraphSnapshot(decoded.snapshot, { pretty: true });
}

Decode and validation return structured issues for untrusted input instead of throwing native JSON or cloning failures. Serialization and producer finalization throw FrameGraphSnapshotValidationError when a caller attempts to write invalid canonical data.

Decoded, parsed, and finalized Snapshots use null-prototype objects throughout, including extension objects; arrays remain ordinary arrays. Inherited fields and getters are ignored. Use Object.hasOwn(object, key) instead of object.hasOwnProperty(key). This changes JavaScript object prototypes, not Snapshot fields or the JSON wire format.

Common tasks

TaskPublic API
Parse untrusted JSON textparseFrameGraphSnapshot()
Decode an already-parsed unknown valuedecodeFrameGraphSnapshot()
Validate canonical programmatic datavalidateFrameGraphSnapshot()
Finalize and detach a producer draftfinalizeFrameGraphSnapshot()
Serialize canonical Snapshot datastringifyFrameGraphSnapshot()
Handle producer-side validation failuresFrameGraphSnapshotValidationError
Read the canonical format and versionFRAME_GRAPH_SNAPSHOT_FORMAT, FRAME_GRAPH_SNAPSHOT_VERSION
Read the extension depth limitFRAME_GRAPH_SNAPSHOT_MAX_EXTENSION_DEPTH
Import the JSON Schema@zenfg/snapshot/schema/v1.json

Exact result unions, issue types, wire fields, defaults, and failure conditions are documented by the TSDoc preserved in the packaged source and declarations.

Consumer and producer boundaries

  • Consumers should use parseFrameGraphSnapshot() for text or decodeFrameGraphSnapshot() for unknown values. Both accept canonical 1.2 and supported historical formats, perform migration, and return a discriminated result.
  • Producers assembling an in-memory draft should use finalizeFrameGraphSnapshot(). It removes optional undefined properties, validates JSON safety and Snapshot semantics, and returns detached canonical data.
  • validateFrameGraphSnapshot() checks canonical data; it does not migrate historical input.
  • Unknown formats and versions are rejected until an explicit migration exists. Readers must not guess that another wire version is compatible.
  • Programmatic inputs are treated as read-only. Decode, migration, and finalization do not mutate caller-owned values.

The complete structural and cross-field contract is the SPEC.md specification. The JSON Schema is normative for structural constraints; the specification and conformance corpus define references, cross-field semantics, migration, and stable issue behavior.

Schema and fixtures

Import the published Draft 2020-12 Schema with an import attribute:

ts
import schema from '@zenfg/snapshot/schema/v1.json' with { type: 'json' };

Consumers need JSON module resolution and a module mode supporting import attributes. Published fixtures and conformance cases cover canonical documents, legacy migration, invalid structure, invalid semantics, stable keys, allocation, timing, and the extension-depth boundary.

Snapshot files conventionally use the .fgsnapshot.json extension. Entity IDs are type-prefixed strings; counts, sizes, and frame indices are non-negative JavaScript safe integers.

Common mistakes

SymptomFix
Parsed JSON is treated as trusted Snapshot dataPass it through parseFrameGraphSnapshot() or decodeFrameGraphSnapshot() first.
Legacy input fails canonical validationDecode it so the explicit migration runs; canonical validation alone does not migrate.
A producer writes undefined, non-finite numbers, or unsupported valuesFinalize the draft and handle FrameGraphSnapshotValidationError before serialization.
An unknown version appears to have compatible fieldsReject it until a reader implements and tests an explicit migration.
Reverse relationships are expected in the wire modelBuild consumer indices locally; the protocol stores canonical one-way references.
A Snapshot is expected to replay GPU workCapture commands or resource contents through an application-owned mechanism instead.

Further reading

Documentation and versions

This README describes @zenfg/snapshot 0.1.0. Registry badges show the current published channel, not your installed version.

Open source / MIT licensed