Schema Metadata
JavaScript schema metadata is declared with Type.* builders or TypeScript decorators. Metadata
defines type identity, field types, nullability, reference tracking, dynamic fields, and per-struct
schema evolution behavior.
Type Identity
Structs and enums can use a numeric ID or a namespace/name pair. Pick one identity strategy for a type and use it consistently in every runtime that reads or writes the payload.
import { Type } from "@apache-fory/core";
const byId = Type.struct(
{ typeId: 1001 },
{
id: Type.int64(),
name: Type.string(),
},
);
const byName = Type.struct(
{ namespace: "example", typeName: "user" },
{
id: Type.int64(),
name: Type.string(),
},
);
Decorator Metadata
Decorators keep the schema next to a TypeScript class declaration:
@Type.struct({ typeName: "example.user" })
class User {
@Type.int64()
id!: bigint;
@Type.string()
name!: string;
}
The decorator metadata is equivalent to the builder metadata registered with fory.register(...).
Field Types
Use explicit scalar builders for stable contracts:
Type.int8();
Type.int16();
Type.int32();
Type.int64(); // JavaScript value is bigint
Type.uint32();
Type.uint64(); // JavaScript value is bigint
Type.float16();
Type.bfloat16();
Type.float32();
Type.float64();
Type.string();
Type.binary();
Use collection builders for nested values:
Type.list(Type.string());
Type.map(Type.string(), Type.int32());
Type.set(Type.string());
Type.int32Array();
Type.float64Array();
Nullability
Fields are non-nullable unless the schema says otherwise:
const userType = Type.struct("example.user", {
name: Type.string(),
email: Type.string().setNullable(true),
});
Passing null to a non-nullable field throws.
Reference Tracking
When the same object instance can appear in multiple fields, or when an object graph can be circular, enable global reference tracking and mark reference-tracked fields:
import Fory, { Type } from "@apache-fory/core";
const fory = new Fory({ ref: true });
const nodeType = Type.struct("example.node", {
next: Type.struct("example.node").setNullable(true).setTrackingRef(true),
});
Field-level reference metadata has no effect unless new Fory({ ref: true }) is also set.
Dynamic Fields
Use Type.any() when a field can hold different Fory values at runtime:
const eventType = Type.struct("example.event", {
kind: Type.string(),
payload: Type.any(),
});
For a struct field with a declared type, .setDynamic(Dynamic.FALSE) always treats values as the
declared type and .setDynamic(Dynamic.TRUE) always writes the runtime type. The default
Dynamic.AUTO is appropriate for most fields.
Per-Struct Schema Evolution
JavaScript uses compatible schema evolution by default. For a stable struct that should omit
evolution metadata, set evolving: false:
const fixedType = Type.struct(
{ typeId: 1002, evolving: false },
{
name: Type.string(),
},
);
Both writer and reader must agree on evolving: false.