From fbd8dab25869c0bd794057ff4b9cf6cc8e26523d Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Mon, 12 Oct 2026 08:40:49 +0200 Subject: [PATCH] thing-contract-ts: domain codecs hand the checked value back from encode Co-Authored-By: Claude Sonnet 5.5 --- packages/thing-contract/src/domain.ts | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/packages/thing-contract/src/domain.ts b/packages/thing-contract/src/domain.ts index c375f72..ee53892 100644 --- a/packages/thing-contract/src/domain.ts +++ b/packages/thing-contract/src/domain.ts @@ -4,10 +4,16 @@ import { codecs } from "@gamecult/cultcache-ts"; import type { Codec } from "@gamecult/cultcache-ts"; +// A domain's wire form is its value, so its encode hands the checked value back: a caller that holds a number from +// outside (a factory argument, a key part) passes it through `encode` and keeps what comes out. +export interface Domain extends Codec { + encode(value: TValue): TValue; +} + function bounded( leaf: Codec, refusal: (value: TValue) => string | null, -): Codec { +): Domain { const hold = (value: TValue): TValue => { const refused = refusal(value); if (refused !== null) throw new Error(refused); @@ -34,7 +40,7 @@ export const count = bounded(codecs.int32, (value) => (value >= 0 ? null : "Coun * A name the contract joins into a record key: non-empty, no '.'. A domain admits no nil, and the library refuses a nil * in a value slot, so it is declared one. */ -export const segment: Codec = { +export const segment: Domain = { ...bounded(codecs.string, (value) => value === "" ? "Segment must be non-empty" : value.includes(".") ? "Segment must be free of '.'" : null, ),