Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/Process-PSModule.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,6 @@ permissions:

jobs:
Process-PSModule:
uses: PSModule/Process-PSModule/.github/workflows/workflow.yml@fb1bdb8fefd243292f779d2a856a38db6fe6daf4 # v6.1.13
uses: PSModule/Process-PSModule/.github/workflows/workflow.yml@11117919e65242d3388727819a751f74ad24ea9e # v5.5.0
secrets:
APIKEY: ${{ secrets.APIKEY }}
File renamed without changes.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

# PSModule framework outputs folder
outputs/*
output/

# .Net build output
bin/
Expand Down
124 changes: 114 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,31 +1,135 @@
# Toml

Toml is a PowerShell module for reading TOML file content from disk so scripts can load and process configuration text.
PowerShell module for reading and writing [TOML](https://toml.io) data, with full TOML 1.0.0 specification support.

## Prerequisites

- PowerShell 7.6 LTS
- The [PSModule framework](https://github.com/PSModule/Process-PSModule) for building, testing and publishing the module.

## Installation

Install the module from the PowerShell Gallery:
To install the module from the PowerShell Gallery, you can use the following command:

```powershell
Install-PSResource -Name Toml
Import-Module -Name Toml
```

## Capabilities
## Usage

Use this command to read TOML content from a file path:
### Parse a TOML string

```powershell
Get-Toml -Path '.\settings.toml'
$doc = ConvertFrom-Toml -InputObject @'
[database]
host = "localhost"
port = 5432
enabled = true
'@

$doc.Data.database.host # "localhost"
$doc.Data.database.port # 5432 [long]
$doc.Data.database.enabled # $true
```

## Documentation
### Import from a TOML file

```powershell
$doc = Import-Toml -Path './config.toml'
$doc.FilePath # absolute path to the file
$doc.Data # OrderedDictionary of all top-level keys
```

### Serialize an object to TOML

```powershell
$toml = ConvertTo-Toml -InputObject ([ordered]@{
title = 'My App'
version = 1
server = [ordered]@{
host = 'localhost'
port = 8080
}
})
# title = "My App"
# version = 1
#
# [server]
# host = "localhost"
# port = 8080
```

### Export to a TOML file

```powershell
$config = [ordered]@{
name = 'example'
enabled = $true
}
Export-Toml -InputObject $config -Path './output.toml'
```

### Round-trip: file β†’ modify β†’ file

```powershell
$doc = Import-Toml -Path './config.toml'
$doc.Data['version'] = 2
Export-Toml -InputObject $doc -Path './config.toml'
```

## TOML type mapping

| TOML type | PowerShell type |
|----------------------|----------------------------|
| String | `[string]` |
| Integer | `[long]` |
| Float | `[double]` |
| Boolean | `[bool]` |
| Offset date-time | `[System.DateTimeOffset]` |
| Local date-time | `[System.DateTime]` |
| Local date | `[System.DateTime]` |
| Local time | `[System.TimeSpan]` |
| Array | `[object[]]` |
| Table / Inline table | `[ordered]` hashtable |
| Array of tables | `[object[]]` of hashtables |

## Commands

Documentation is published at [psmodule.io/Toml](https://psmodule.io/Toml/).
| Command | Description |
|-------------------|------------------------------------------|
| `ConvertFrom-Toml` | Parse TOML text β†’ `TomlDocument` |
| `ConvertTo-Toml` | Serialize object β†’ TOML text |
| `Import-Toml` | Read TOML file β†’ `TomlDocument` |
| `Export-Toml` | Write object or `TomlDocument` to file |

Use PowerShell help and command discovery for details:
## Implementation notes

- Pure PowerShell parser and serializer β€” no external TOML runtime dependency.
- Duplicate keys and table redefinition are rejected per the TOML 1.0.0 spec.
- Files are written as UTF-8 without BOM.

## More examples

See the [examples](examples) folder for runnable scripts. Use PowerShell help for per-command examples:

```powershell
Get-Command -Module Toml
Get-Help -Name Get-Toml -Examples
Get-Help ConvertFrom-Toml -Examples
Get-Help Import-Toml -Examples
```

## Documentation

Full documentation is available at [psmodule.io/Toml](https://psmodule.io/Toml).

## Contributing

Coder or not, you can contribute to the project! We welcome all contributions.

### For Users

If you experience unexpected behavior, errors, or missing functionality, please open an issue on the [issues tab](https://github.com/PSModule/Toml/issues).

### For Developers

Please read the [Contribution guidelines](CONTRIBUTING.md) and pick up an existing issue or submit a new one.
94 changes: 94 additions & 0 deletions build.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
#!/usr/bin/env pwsh
#Requires -Version 7.0
<#
.SYNOPSIS
Builds the Toml module from source into ./output/Toml/.

.DESCRIPTION
Assembles all source files (classes, init, private functions, public functions)
into a single psm1 and creates a manifest, so tests can be run locally without
the PSModule CI pipeline.
#>
[CmdletBinding()]
param(
# Version to stamp into the manifest.
[string] $ModuleVersion = '0.0.1'
)

$ErrorActionPreference = 'Stop'
$moduleName = 'Toml'
$srcPath = Join-Path $PSScriptRoot 'src'
$outputPath = Join-Path $PSScriptRoot 'output' $moduleName

# ── clean / create output directory ─────────────────────────────────────────
if (Test-Path $outputPath) {
Remove-Item $outputPath -Recurse -Force
}
$null = New-Item -ItemType Directory -Path $outputPath -Force

# ── build psm1 ───────────────────────────────────────────────────────────────
$psm1Path = Join-Path $outputPath "$moduleName.psm1"
$sb = [System.Text.StringBuilder]::new()

# header
$headerPath = Join-Path $srcPath 'header.ps1'
if (Test-Path $headerPath) {
$null = $sb.AppendLine((Get-Content $headerPath -Raw))
} else {
$null = $sb.AppendLine('$ErrorActionPreference = ''Stop''')
$null = $sb.AppendLine()
}

# init
foreach ($f in (Get-ChildItem (Join-Path $srcPath 'init') -Filter '*.ps1' -ErrorAction SilentlyContinue)) {
$null = $sb.AppendLine((Get-Content $f.FullName -Raw))
}

# classes private then public
foreach ($visibility in @('private', 'public')) {
$classPath = Join-Path $srcPath "classes/$visibility"
foreach ($f in (Get-ChildItem $classPath -Filter '*.ps1' -Recurse -ErrorAction SilentlyContinue)) {
$null = $sb.AppendLine((Get-Content $f.FullName -Raw))
}
}

# private functions
foreach ($f in (Get-ChildItem (Join-Path $srcPath 'functions/private') -Filter '*.ps1' -Recurse -ErrorAction SilentlyContinue)) {
$null = $sb.AppendLine((Get-Content $f.FullName -Raw))
}

# public functions
$publicFunctions = [System.Collections.Generic.List[string]]::new()
foreach ($f in (Get-ChildItem (Join-Path $srcPath 'functions/public') -Filter '*.ps1' -Recurse -ErrorAction SilentlyContinue)) {
$null = $sb.AppendLine((Get-Content $f.FullName -Raw))
$publicFunctions.Add([System.IO.Path]::GetFileNameWithoutExtension($f.Name))
}

# finally
$finallyPath = Join-Path $srcPath 'finally.ps1'
if (Test-Path $finallyPath) {
$null = $sb.AppendLine((Get-Content $finallyPath -Raw))
}

# Export-ModuleMember
$null = $sb.AppendLine("Export-ModuleMember -Function @($($publicFunctions | ForEach-Object { "'$_'" } | Join-String -Separator ', '))")

[System.IO.File]::WriteAllText($psm1Path, $sb.ToString(), [System.Text.UTF8Encoding]::new($false))

# ── write manifest ────────────────────────────────────────────────────────────
$psd1Path = Join-Path $outputPath "$moduleName.psd1"
$manifest = @{
Path = $psd1Path
ModuleVersion = $ModuleVersion
RootModule = "$moduleName.psm1"
FunctionsToExport = $publicFunctions.ToArray()
PowerShellVersion = '7.6'
Description = 'PowerShell module for reading and writing TOML data.'
Author = 'PSModule'
CompanyName = 'PSModule'
GUID = '6f1b6f8d-1234-4321-abcd-ef0123456789'
}
New-ModuleManifest @manifest

Write-Host "Built $moduleName $ModuleVersion -> $outputPath"
Write-Host "Public functions: $($publicFunctions -join ', ')"
76 changes: 76 additions & 0 deletions examples/General.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
ο»Ώ<#
.SYNOPSIS
General usage examples for the Toml module.
#>

# Import the module
Import-Module -Name 'Toml'

# ── Parse TOML string ──────────────────────────────────────────────────────
$doc = ConvertFrom-Toml -InputObject @'
[database]
host = "localhost"
port = 5432
enabled = true
tags = ["production", "primary"]

[database.credentials]
user = "admin"
'@

$doc.Data.database.host # "localhost"
$doc.Data.database.port # 5432
$doc.Data.database.enabled # True
$doc.Data.database.tags # @("production", "primary")
$doc.Data.database.credentials.user # "admin"

# ── Serialize to TOML ──────────────────────────────────────────────────────
$toml = ConvertTo-Toml -InputObject ([ordered]@{
title = 'My Application'
version = 2
debug = $false
server = [ordered]@{
host = '0.0.0.0'
port = 8080
}
features = @('auth', 'logging', 'metrics')
})
Write-Host $toml

# ── Import from file ───────────────────────────────────────────────────────
# $doc = Import-Toml -Path './config.toml'
# $doc.FilePath # absolute path to the source file
# $doc.Data # [ordered] hashtable of all top-level keys

# ── Export to file ─────────────────────────────────────────────────────────
# Export-Toml -InputObject ([ordered]@{ key = 'value' }) -Path './config.toml'

# ── Round-trip: file β†’ edit β†’ file ────────────────────────────────────────
# $doc = Import-Toml -Path './config.toml'
# $doc.Data['version'] = 3
# Export-Toml -InputObject $doc -Path './config.toml'

# ── Pipeline usage ─────────────────────────────────────────────────────────
# '[server]
# host = "localhost"' | ConvertFrom-Toml | ConvertTo-Toml

# ── All TOML scalar types ──────────────────────────────────────────────────
$types = ConvertFrom-Toml -InputObject @'
a_string = "hello"
an_integer = 42
a_float = 3.14
a_bool = true
an_offset_dt = 1979-05-27T07:32:00Z
a_local_dt = 1979-05-27T07:32:00
a_local_date = 1979-05-27
a_local_time = 07:32:00
'@

$types.Data.a_string # [string]
$types.Data.an_integer # [long]
$types.Data.a_float # [double]
$types.Data.a_bool # [bool]
$types.Data.an_offset_dt # [System.DateTimeOffset]
$types.Data.a_local_dt # [System.DateTime] (Kind=Unspecified)
$types.Data.a_local_date # [System.DateTime] (00:00:00)
$types.Data.a_local_time # [System.TimeSpan]
Loading
Loading