How To Model A Versioned Contract
Use this pattern for config files or messages that evolve over time and need an explicit version marker in the wire shape.
open CodecMapper.Schema
type SettingsV2 = {
Version: int
Mode: string
Region: string option
}
let makeSettingsV2 version mode region =
{ Version = version; Mode = mode; Region = region }
let settingsV2Schema =
define<SettingsV2>
|> construct makeSettingsV2
|> fieldWith "version" _.Version (
int
|> tryMap
(fun value ->
if value > 0 then Ok value
else Error "version must be positive")
id
)
|> field "mode" _.Mode
|> field "region" _.Region
|> build
Keep the version field explicit so contract evolution stays visible in one authored schema. If you also need omission policies or defaults, compose those helpers directly at the field boundary.
type SettingsV2 =
{
Version: int
Mode: string
Region: string option
}
Multiple items
val int: value: 'T -> int (requires member op_Explicit)
--------------------
type int = int32
--------------------
type int<'Measure> = int
val int: value: 'T -> int (requires member op_Explicit)
--------------------
type int = int32
--------------------
type int<'Measure> = int
Multiple items
val string: value: 'T -> string
--------------------
type string = System.String
val string: value: 'T -> string
--------------------
type string = System.String
type 'T option = Option<'T>
val makeSettingsV2: version: int -> mode: string -> region: string option -> SettingsV2
val version: int
val mode: string
val region: string option
val settingsV2Schema: obj
union case Result.Ok: ResultValue: 'T -> Result<'T,'TError>
union case Result.Error: ErrorValue: 'TError -> Result<'T,'TError>
val id: x: 'T -> 'T
CodecMapper