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.HttpClient
open Axial.PlatformService
open Axial.Process
open Axial.State
open Axial.Telemetry
open Axial.Telemetry.JavaScriptNode Hosting
Axial.Hosting.Node is a JavaScript-only Fable package for Node processes.
dotnet add package Axial.Hosting.Node
The NuGet package uses a .NET target asset because Fable consumes F# projects through MSBuild. It is not a .NET
runtime implementation: calling its entry points without Fable JavaScript fails immediately. Calling it in a browser
also fails because the Node process object is required.
Root Application
Keep Node mechanics outside the application workflow:
type StartupInputs =
{ Arguments: string list
EnvironmentVariables: IEnvironmentVariables }
let inputs =
{ Arguments = NodeApp.arguments()
EnvironmentVariables = NodeEnvironment.live }
let application : Flow<StartupInputs, AppError, unit> =
program
|> Layer.provide Live.appLayerRun and Exit
At the Fable entry point:
open Axial.Hosting.Node
NodeApp.run AppError.describe inputs application
|> Async.StartImmediate- subscribes to
SIGINTandSIGTERM; - requests coordinated
App.Stop()on either signal; - removes both handlers after completion;
- writes typed failures and defects through
console.error; - sets
process.exitCodeonly after the root scope closes.
It does not call process.exit(), because doing so would terminate the event loop before asynchronous finalizers can
finish.
The exit-code mapping is success 0, typed failure 1, defect 2, SIGINT 130, and SIGTERM 143. An interruption
not caused by an installed signal uses 130. A cleanup defect takes precedence over the interruption code.
Use NodeApp.start when another Node module needs the AppHandle:
let running = NodeApp.start AppError.describe inputs application
async {
let! exit = running.Completion
reportCompletion exit
}
|> Async.StartImmediateSupply Node logging as an explicit ILog implementation in the application environment. For tracing, install
Axial.Telemetry.JavaScript with the host's @opentelemetry/api object before starting the application. Hosting
does not choose an SDK, exporter, or context manager.
Build Shape
A minimal project uses Fable and an ES module package:
{
"type": "module",
"scripts": {
"build": "dotnet fable --outDir dist",
"start": "node dist/Program.fs.js"
}
}
The application and layers remain normal F# source. Only Program.fs needs Node hosting calls.

