Relish schema (RNull, RStruct, REnum, etc.)
Codec with typed encode/decode methods
Basic usage:
import { createCodec, RStruct, field, RString, RU8 } from '@grounds/schema';
import type { Static } from '@grounds/schema';
const UserSchema = RStruct({
name: field(0, RString()),
age: field(1, RU8())
});
type User = Static<typeof UserSchema>;
const codec = createCodec(UserSchema);
const user: User = { name: 'Alice', age: 25 };
codec.encode(user).match(
(bytes) => {
// bytes: Uint8Array ready for transmission
codec.decode(bytes).match(
(decoded) => console.log(decoded.name, decoded.age),
(error) => console.error('Decode error:', error.code)
);
},
(error) => console.error('Encode error:', error.message)
);
Type safety with Static:
import { createCodec, RArray, RU32, type Static } from '@grounds/schema';
const schema = RArray(RU32());
const codec = createCodec(schema);
type Numbers = Static<typeof schema>; // Array<number>
const valid: Numbers = [1, 2, 3];
codec.encode(valid); // OK
// TypeScript compile error:
// const invalid: Numbers = [1, 'two', 3];
Codec uses toRelish for encoding (JS value → bytes) and fromRelish for decoding (bytes → JS value). Both operations are truly symmetric per ADR 0001: encode produces bytes directly, decode consumes bytes directly.
Type inference via Static
Creates a type-safe codec from a Relish schema.
The codec provides encode/decode methods with full type inference, automatically validating values against the schema during encoding.