Repository F# setup
open System
open System.IO
open System.Threading
open System.Threading.Tasks
open Axial
open Axial.Layers
open Axial.Console
open Axial.FileSystem
open Axial.Hosting
open Axial.Hosting.Browser
open Axial.Hosting.Node
open Axial.PlatformService
open Axial.State
open Axial.Telemetry
open Axial.Telemetry.JavaScriptA missing environment variable can surface as null, and a malformed value can throw a parse exception later. Axial.PlatformService
splits this into two modules: one for raw access, and one for typed reads with a failure channel.
Show page setup
// Setup for the checked examples on this page.
open System
open Axial
open Axial.PlatformService
/// Fails the docs test when an example's result differs from the value shown.
let shouldEqual expected actual =
if actual <> expected then failwithf "Expected %A but got %A" expected actualopen System
open Axial
open Axial.PlatformService
SystemAxialPlatformServiceRaw access
EnvironmentVariables provides raw access without requiring values:
| Function | Result |
|---|---|
EnvironmentVariables.tryGet name |
string option |
EnvironmentVariables.getAll |
IReadOnlyDictionary<string, string> |
EnvironmentVariables.set name value |
Sets a variable |
EnvironmentVariables.clear name |
Removes a variable |
EnvironmentVariables.expand text |
Expands %VAR% references |
EnvironmentVariables.fromPairs builds an in-memory set for tests:
> open Axial.PlatformService;;
> let runtime () = { BaseRuntime.liveValue with EnvironmentVariables = EnvironmentVariables.fromPairs [ "REGION", "eu" ] };;
> (EnvironmentVariables.tryGet "REGION" : Flow<BaseRuntime, Never, string option>) |> Flow.run (runtime ());;
> (EnvironmentVariables.tryGet "MISSING" : Flow<BaseRuntime, Never, string option>) |> Flow.run (runtime ());;val it: Exit<string option,Never> = Success (Some "eu")
val it: Exit<string option,Never> = Success NoneAxialPlatformServiceruntime: unit -> BaseRuntimeAxial.PlatformService.BaseRuntimeGroups the standard operational services commonly used by workflow hosts.
Axial.PlatformService.BaseRuntimeModuleHelpers for constructing the standard explicit service bundle used by workflow hosts.
liveValue: BaseRuntimeCreates the standard live base runtime as an explicit service bundle.
EnvironmentVariables: IEnvironmentVariablesAxial.PlatformService.EnvironmentVariablesHelpers for the environment-variable service.
tryGet: string -> Flow<'env,'error,string option>Reads a raw environment-variable value from an explicit environment-variable service.
Axial.Flow`3Axial.NeverRepresents an error channel that cannot occur.
stringAn abbreviation for the CLI type . Basic Types
optionThe type of optional values. When used from other CLI languages the empty option is the null value. Use the constructors Some and None to create values of this type. Use the values in the Option module to manipulate values of this type, or pattern match against the values directly. 'None' values will appear as the value null to other CLI languages. Instance methods on this type will appear as static methods to other CLI languages due to the use of null as a value representation. Options
(|>): 'T1 -> ('T1 -> 'U) -> 'UApply a function to a value, the value being on the left, the function on the right The argument. The function. The function result. let doubleIt x = x * 2 3 |> doubleIt // Evaluates to 6
Axial.Flowrun: 'env -> Flow<'env,'error,'value> -> Exit<'value,'error>Runs the workflow and blocks until the final exit is available. The environment used by the workflow. The workflow to run. The final workflow exit. let exit = workflow |> Flow.run environment
These never fail; an absent variable is None.
Typed reads
EnvironmentVariable reads a variable, requires it, and parses it, failing with EnvironmentVariableError:
let readPort : Flow<BaseRuntime, EnvironmentVariableError, int> =
EnvironmentVariable.getInt "PORT"
readPort: Flow<BaseRuntime,EnvironmentVariableError,int>Axial.Flow`3Axial.PlatformService.BaseRuntimeGroups the standard operational services commonly used by workflow hosts.
Axial.PlatformService.EnvironmentVariableErrorintAn abbreviation for the CLI type . Basic Types
Axial.PlatformService.EnvironmentVariableHelpers for reading and parsing environment variables through an explicit service.
getInt: string -> Flow<'env,EnvironmentVariableError,int>Reads an integer environment variable through an explicit service.
Requires & types
Requires: open Axial; open Axial.PlatformService (packages: Axial, Axial.PlatformService)val readPort: Flow<BaseRuntime,EnvironmentVariableError,int>The environment is named concretely here rather than written as #IHasEnvironmentVariables, because a flow bound
to a plain value hits F#'s value restriction while its environment is still generic: a value cannot be generalised
over a type variable.
Adding a parameter removes the restriction, because a function can be. A unit parameter is enough, and the result
stays usable in any environment supplying the service:
let readPortIn () : Flow<#IHasEnvironmentVariables, EnvironmentVariableError, int> =
EnvironmentVariable.getInt "PORT"
readPortIn: unit -> Flow<'a,EnvironmentVariableError,int>Axial.Flow`3Axial.PlatformService.IHasEnvironmentVariablesDeclares that an environment supplies the environment-variable service.
Axial.PlatformService.EnvironmentVariableErrorintAn abbreviation for the CLI type . Basic Types
Axial.PlatformService.EnvironmentVariableHelpers for reading and parsing environment variables through an explicit service.
getInt: string -> Flow<'env,EnvironmentVariableError,int>Reads an integer environment variable through an explicit service.
Requires & types
Requires: open Axial; open Axial.PlatformService (packages: Axial, Axial.PlatformService)val readPortIn: unit -> Flow<'a,EnvironmentVariableError,int>Prefer naming the environment when a workflow belongs to one application, and the parameterised form when a helper is genuinely shared across environment shapes.
| Function | Result |
|---|---|
get |
string, failing when absent |
tryGet |
string option, never failing |
getInt, getInt64 |
Integers |
getDouble, getDecimal |
Numbers |
getBool |
Booleans |
getGuid |
GUIDs |
getUri |
URIs |
getTimeSpan |
Durations |
Numeric parsing uses the invariant culture, so a variable set on a machine with a comma decimal separator reads the same everywhere.
EnvironmentVariableError has two cases:
MissingVariable name: the variable was not set.InvalidVariable (name, value, expected): it was set but did not parse, with what was expected.
EnvironmentVariableErrors.describe formats either into a sentence such as Environment variable 'PORT' had value 'eighty' but expected an integer.
Validating configuration at startup
Typed reads compose into a workflow that produces settings or fails with EnvironmentVariableError:
type Settings = { Port: int; Endpoint: Uri; Timeout: TimeSpan }
let readSettings : Flow<BaseRuntime, EnvironmentVariableError, Settings> =
flow {
let! port = EnvironmentVariable.getInt "PORT"
let! endpoint = EnvironmentVariable.getUri "API_ENDPOINT"
let! timeout = EnvironmentVariable.getTimeSpan "API_TIMEOUT"
return { Port = port; Endpoint = endpoint; Timeout = timeout }
}
let withVariables pairs =
{ BaseRuntime.liveValue with EnvironmentVariables = EnvironmentVariables.fromPairs pairs }
FsLiveDocsGeneratedPage2_F9357565CFEE.SettingsPort: intintAn abbreviation for the CLI type . Basic Types
Endpoint: UriSystem.UriProvides an object representation of a uniform resource identifier (URI) and easy access to the parts of the URI.
Timeout: TimeSpanSystem.TimeSpanRepresents a time interval.
readSettings: Flow<BaseRuntime,EnvironmentVariableError,Settings>Axial.Flow`3Axial.PlatformService.BaseRuntimeGroups the standard operational services commonly used by workflow hosts.
Axial.PlatformService.EnvironmentVariableErrorflow: FlowBuilderThe universal flow { } computation expression.
port: intAxial.PlatformService.EnvironmentVariableHelpers for reading and parsing environment variables through an explicit service.
getInt: string -> Flow<'env,EnvironmentVariableError,int>Reads an integer environment variable through an explicit service.
endpoint: UrigetUri: string -> Flow<'env,EnvironmentVariableError,Uri>Reads a URI environment variable through an explicit service.
timeout: TimeSpangetTimeSpan: string -> Flow<'env,EnvironmentVariableError,TimeSpan>Reads a time span environment variable through an explicit service.
withVariables: (string * string) seq -> BaseRuntimepairs: (string * string) seqAxial.PlatformService.BaseRuntimeModuleHelpers for constructing the standard explicit service bundle used by workflow hosts.
liveValue: BaseRuntimeCreates the standard live base runtime as an explicit service bundle.
EnvironmentVariables: IEnvironmentVariablesRequires & types
Requires: open Axial; open Axial.PlatformService; open System (packages: Axial, Axial.PlatformService)val readSettings: Flow<BaseRuntime,EnvironmentVariableError,Settings>val withVariables: (string * string) seq -> BaseRuntimereadSettings
|> Flow.run (withVariables [ "PORT", "8080"; "API_ENDPOINT", "https://api.example.com"; "API_TIMEOUT", "00:00:30" ])
|> shouldEqual (Exit.Success { Port = 8080; Endpoint = Uri "https://api.example.com"; Timeout = TimeSpan.FromSeconds 30.0 })
readSettings
|> Flow.run (withVariables [ "PORT", "eighty" ])
|> shouldEqual (Exit.Failure(Cause.Fail(EnvironmentVariableError.InvalidVariable("PORT", "eighty", "an integer"))))
readSettings: Flow<BaseRuntime,EnvironmentVariableError,Settings>(|>): 'T1 -> ('T1 -> 'U) -> 'UApply a function to a value, the value being on the left, the function on the right The argument. The function. The function result. let doubleIt x = x * 2 3 |> doubleIt // Evaluates to 6
Axial.Flowrun: 'env -> Flow<'env,'error,'value> -> Exit<'value,'error>Runs the workflow and blocks until the final exit is available. The environment used by the workflow. The workflow to run. The final workflow exit. let exit = workflow |> Flow.run environment
withVariables: (string * string) seq -> BaseRuntimeshouldEqual: 'a -> 'a -> unitAxial.Exit`2Represents the final outcome of a workflow execution. The type of the success value. The type of the domain-specific failure value.
SuccessThe workflow completed successfully.
Port: intEndpoint: Uri``.ctor``: string -> unitInitializes a new instance of the class with the specified URI. A string that identifies the resource to be represented by the instance. Note that an IPv6 address in string form must be enclosed within brackets. For example, "http://[2607:f8b0:400d:c06::69]". is . In the .NET for Windows Store apps or the Portable Class Library, catch the base class exception, , instead. is empty. -or- The scheme specified in is not correctly formed. See . -or- contains too many slashes. -or- The password specified in is not valid. -or- The host name specified in is not valid. -or- The file name specified in is not valid. -or- The user name specified in is not valid. -or- The host or authority name specified in cannot be terminated by backslashes. -or- The port number specified in is not valid or cannot be parsed. -or- The length of exceeds 65519 characters. -or- The length of the scheme specified in exceeds 1023 characters. -or- There is an invalid character sequence in . -or- The MS-DOS path specified in must start with c:\\.
Timeout: TimeSpanSystem.TimeSpanRepresents a time interval.
FromSeconds: float -> TimeSpanReturns a that represents a specified number of seconds, where the specification is accurate to the nearest millisecond. A number of seconds, accurate to the nearest millisecond. An object that represents . is less than or greater than . -or- is . -or- is . is equal to .
FailureThe workflow failed due to a specific cause.
Axial.Cause`1Represents the cause of a failed workflow. The type of the domain-specific failure value.
FailAn expected domain-specific failure.
Axial.PlatformService.EnvironmentVariableErrorInvalidVariableRequires & types
Requires: open Axial; open Axial.PlatformService; open System (packages: Axial, Axial.PlatformService)This binds sequentially, so it stops at the first problem. Run it as a layer during startup and the application cannot reach its first request with unparsed configuration; see layers for provisioning failure.
Supplying the service
EnvironmentVariables.live reads the current process environment. EnvironmentVariables.fromPairs builds a fixed
provider, which is how tests avoid mutating global process state:
let environment =
EnvironmentVariables.fromPairs
[ "PORT", "8080"
"API_ENDPOINT", "https://api.example.com" ]
environment: IEnvironmentVariablesAxial.PlatformService.EnvironmentVariablesHelpers for the environment-variable service.
fromPairs: (string * string) seq -> IEnvironmentVariablesCreates a deterministic provider from a fixed set of name/value pairs.
Requires & types
Requires: open Axial.PlatformService (packages: Axial.PlatformService)val environment: IEnvironmentVariablesPrefer fromPairs over setting real variables in a test. Process environment state is shared across a test run, so
mutating it makes tests order-dependent.

