Codecs
Type-safe serialization with Zod, Valibot, or ArkType
Codecs combine serialization with schema validation. Your schema tells fatline exactly where extended types live, so decoding is faster and type-safe.
Creating Codecs
import { createCodec } from 'fatline/codec'
import { z } from 'zod'
const UserCodec = createCodec(z.object({
id: z.string(),
email: z.string().email(),
createdAt: z.date(),
preferences: z.map(z.string(), z.unknown()),
}))
// Encode
const json = UserCodec.encode(user)
// Decode (deserialize + validate)
const user = UserCodec.decode(json)
// ^? { id: string, email: string, createdAt: Date, preferences: Map<string, unknown> }Decode Modes
// Standard: validates, throws on error
const user = UserCodec.decode(json)
// Unsafe: skip validation (for trusted sources)
const user = UserCodec.decodeUnsafe(json)
// Safe: returns Result, never throws
const result = UserCodec.safeDecode(json)
// { success: true, data: User } | { success: false, error: FatlineError }
// Lenient: partial success with field-level errors
const { data, errors } = UserCodec.decodeLenient(json)Schema Fingerprinting
Each codec has a content-based hash:
UserCodec.hash // "a3f2c1b8"Same schema, same hash—regardless of when or where it was compiled. This lets client and server verify they're speaking the same language.
// packages/schemas/user.ts (shared)
export const UserSchema = z.object({
id: z.string(),
createdAt: z.date(),
})
// Server
import { createCodec } from 'fatline/codec'
const ServerCodec = createCodec(UserSchema)
ServerCodec.hash // "a3f2c1b8"
// Client
import { createCodec } from 'fatline/codec'
const ClientCodec = createCodec(UserSchema)
ClientCodec.hash // "a3f2c1b8"When hashes match, you can skip validation entirely with decodeUnsafe.
Schema Registry
For managing multiple schemas:
import { createRegistry } from 'fatline/codec'
const registry = createRegistry()
const UserCodec = registry.register('User', UserSchema)
const PostCodec = registry.register('Post', PostSchema)
// Retrieve by name
const codec = registry.get('User')
// Verify schema version
registry.verify('User', 'a3f2c1b8') // boolean