Axial is a set of F# libraries for two common application problems:
- turning untrusted input into domain values without constructing a failed model;
- composing async work while keeping dependencies and expected failures visible.
Use either part on its own.
Warning
Axial 0.7.0 is the first planned release under the Axial name. It replaces the former monolithic FsFlow package with smaller packages. The public surface is still pre-1.0 and may change.
A schema describes fields, parsing, constraints, and construction in one value:
open Axial.Schema
type Signup =
{ Email: string
Age: int }
let signupSchema =
Schema.recordFor<Signup, _> (fun email age -> { Email = email; Age = age })
|> Schema.field "email" _.Email
(Schema.text
|> Schema.constrainAll [ Constraint.required; Constraint.email ])
|> Schema.field "age" _.Age
(Schema.int |> Schema.constrain (Constraint.atLeast 13))
|> Schema.build
match (Schema.parse signupSchema rawInput).Result with
| Ok signup -> register signup
| Error diagnostics -> display diagnosticsSchema.parse either returns the model or path-aware diagnostics. The same declaration can drive checking, JSON
Schema, compiled codecs, form redisplay, test-data generation, and versioned wire contracts.
A schema only controls values produced through the schema. When every value of a type must satisfy an invariant, use a private representation and expose a fallible constructor or named domain operations.
Start here:
- Schema overview
- Getting started with Schema
- Construction guarantees
- Recommended Schema patterns
- Versioned wire contracts
Install the core package:
dotnet add package Axial.SchemaFlow<'env, 'error, 'value> describes async work, its dependencies, and its expected failure type:
open Axial.Flow
type RegistrationError =
| UserNotFound
| SaveFailed of string
type RegistrationEnv =
{ LoadUser: int -> Task<Result<User, RegistrationError>>
SaveUser: User -> Task<Result<unit, RegistrationError>> }
let register userId : Flow<RegistrationEnv, RegistrationError, unit> =
flow {
let! loadUser = Flow.read _.LoadUser
let! saveUser = Flow.read _.SaveUser
let! user = loadUser userId
return! saveUser user
}Tests supply a small record of fakes. The application host supplies live implementations. Cancellation, resource scopes, retries, and child fibers stay within the workflow runtime.
Start here:
Install Flow:
dotnet add package Axial.FlowSmall functions do not need schemas or workflows. Axial.ErrorHandling adds reusable checks and focused helpers while
keeping ordinary Result<'value, 'error> in your interfaces.
open Axial.ErrorHandling
let requireName value =
value
|> Check.String.present
|> Result.orError NameMissingThe authored schema and workflow paths avoid runtime reflection. The core packages support NativeAOT, trimming, and Fable; individual host and service packages document their supported targets.