Etymon.Core 0.1.0-preview.7

This is a prerelease version of Etymon.Core.
dotnet add package Etymon.Core --version 0.1.0-preview.7
                    
NuGet\Install-Package Etymon.Core -Version 0.1.0-preview.7
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Etymon.Core" Version="0.1.0-preview.7" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Etymon.Core" Version="0.1.0-preview.7" />
                    
Directory.Packages.props
<PackageReference Include="Etymon.Core" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Etymon.Core --version 0.1.0-preview.7
                    
#r "nuget: Etymon.Core, 0.1.0-preview.7"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Etymon.Core@0.1.0-preview.7
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Etymon.Core&version=0.1.0-preview.7&prerelease
                    
Install as a Cake Addin
#tool nuget:?package=Etymon.Core&version=0.1.0-preview.7&prerelease
                    
Install as a Cake Tool

Etymon.Core

The foundation of the Etymon suite.

Depends on nothing but FSharp.Core. It trims to roughly 85 KB when the refinement and error model are used, so it can sit in a Blazor WebAssembly domain layer rather than stopping at a server boundary. That figure is measured, not estimated: eng/trim-size.sh publishes a trimmed application that uses the package and prints what the assembly actually weighs.

Take this package alone if you want smart constructors and a proper validation error model, and nothing else. In particular, the error vocabulary deliberately does not depend on Etymon.Schema: if you hand-write your JSON codecs — because the bytes already in your database are a contract you cannot let a rename change — you can adopt Path and ValidationErrors and keep those codecs exactly as they are.

What it gives you

Errors that accumulate, and know where they came from

open Etymon

validation {
    let! name = NonEmpty.create raw.Name |> Validation.underField "name"
    and! age = Age.create raw.Age |> Validation.underField "age"
    and! zip = Zip.create raw.Zip |> Validation.underField "address" 
    return { Name = name; Age = age; Zip = zip }
}
// Error, all at once:
//   name: must be at least 1 character
//   age: must be between 0 and 130
//   address: must be exactly 5 characters

Validation<'T> is an abbreviation for Result<'T, ValidationErrors>, not a new type, so it pattern-matches as Ok / Error and interoperates with everything that already understands Result. Use and! to collect every error; a plain sequence of let! uses bind and stops at the first, because a dependent step has no value to work with.

Constrained types in a few lines

type Email = private Email of string

module Email =
    let refinement =
        Refine.ofString "Email"
        |> Refine.trimmed
        |> Refine.lowercased
        |> Refine.length (Some 3) (Some 254)
        |> Refine.format Format.Email
        |> Refine.wrap Email (fun (Email s) -> s)

    let create (s: string) = Refine.create refinement s
    let value (Email s) = s

Every rule runs, so a value that breaks three of them reports three errors. Normalisation (trimmed, lowercased) always happens before any rule, so " " trims to "" and is then correctly rejected as empty.

Constraints as data

Email.refinement.Constraints
// [ Length(Some 3, Some 254); HasFormat Email ]

This list is the point of the whole suite. Etymon.Schema.OpenApi turns it into JSON Schema keywords, Etymon.Schema.Sql into SQL constraints, Etymon.Invariants.FsCheck into generators — all reading the same rules rather than restating them. A rule Etymon cannot inspect is Opaque: enforced and documented, but never half-derived into something that looks right and is not.

Secrets that stay secret

let settings = { Host = "db.internal"; Password = Secret.create "hunter2" }
printfn "%A" settings
// { Host = "db.internal"; Password = <redacted> }

Redaction lives on the type, so ToString, %O, %A, string and most structured loggers are all covered — including when the secret is nested inside the record somebody actually logs. Getting the value back is Secret.reveal, which is one greppable token, so auditing where secrets escape is a search rather than an audit.

Licence

MIT.

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (16)

Showing the top 5 NuGet packages that depend on Etymon.Core:

Package Downloads
Etymon.Schema

A combinator-based schema type for F#: one value that describes how a type is encoded, decoded, validated and documented. JSON via System.Text.Json, decode errors that accumulate and carry field paths, and an untyped description that OpenAPI, SQL and test generators all read.

Etymon.Migrations

A relational model derived from an Etymon schema, snapshot diffing, and SQL migration scripts for PostgreSQL and SQLite. Generates SQL text and executes nothing, so it carries no database driver. Ambiguous mappings are errors rather than guesses, and destructive changes are flagged rather than emitted silently.

Etymon.Api.Client

Calls an Etymon.Api endpoint over HTTP. The declaration is enough to build the URL, encode the body and decode the response, so a console application calling an Etymon-described API needs no web framework and no server.

Etymon.Config

Configuration loaded through an Etymon schema, from environment variables, JSON files or a source of your own. Reports every missing or invalid setting at once, each with what was expected and which source supplied it. Sensitive settings are redacted wherever Etymon prints them.

Etymon.Schema.Compatibility

Event shapes derived from an Etymon Schema, committed as a snapshot and compared for compatibility in both directions: can new code read events already written, and can already-deployed code read events written by new code. Pure and driver-free. It never emits SQL, never opens a connection, and never proposes rewriting an event, because the events already written are the one irreplaceable thing in the system.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.1.0-preview.7 0 9/21/2026
0.1.0-preview.6 0 9/21/2026
0.1.0-preview.5 0 9/21/2026
0.1.0-preview.4 31 9/21/2026
0.1.0-preview.3 33 9/21/2026
0.1.0-preview.2 38 9/20/2026
0.1.0-preview.1 48 9/20/2026