diff --git a/.github/workflows/powershell.yml b/.github/workflows/powershell.yml
new file mode 100644
index 0000000..6acbcbb
--- /dev/null
+++ b/.github/workflows/powershell.yml
@@ -0,0 +1,112 @@
+name: PowerShell
+
+on:
+ push:
+ branches: [ "main" ]
+ paths-ignore:
+ - 'docs/**'
+ - 'Changelog.md'
+ - 'README.md'
+ - src/internal/Export-HelpToMd.ps1
+ pull_request:
+ branches: [ "main" ]
+
+permissions:
+ contents: read
+
+jobs:
+ build:
+ permissions:
+ contents: read # for actions/checkout to fetch code
+ security-events: write # for github/codeql-action/upload-sarif to upload SARIF results
+ actions: read # only required for a private repository by github/codeql-action/upload-sarif to get the Action run status
+ name: Build
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v4
+ with:
+ fetch-depth: 0 # avoid shallow clone so nbgv can do its work.
+
+ - name: Run PSScriptAnalyzer
+ uses: microsoft/psscriptanalyzer-action@6b2948b1944407914a58661c49941824d149734f
+ with:
+ # Check https://github.com/microsoft/action-psscriptanalyzer for more info about the options.
+ # The below set up runs PSScriptAnalyzer to your entire repository and runs some basic security rules.
+ path: .\src
+ recurse: true
+ # Include your own basic security rules. Removing this option will run all the rules
+ includeRule: '"PSAvoidGlobalAliases", "PSAvoidUsingConvertToSecureStringWithPlainText"'
+ output: results.sarif
+
+ # Upload the SARIF file generated in the previous step
+ - name: Upload SARIF results file
+ uses: github/codeql-action/upload-sarif@v2
+ with:
+ sarif_file: results.sarif
+
+ - uses: dotnet/nbgv@1801854259a50d987aaa03b99b28cebf49faa779
+ id: nbgv
+
+ - name: Build
+ shell: pwsh
+ run: ./build.ps1 build ${{ steps.nbgv.outputs.VersionMajor }} ${{ steps.nbgv.outputs.VersionMinor }} ${{ steps.nbgv.outputs.BuildNumber }} ${{ steps.nbgv.outputs.VersionRevision }} ${{ steps.nbgv.outputs.PrereleaseVersionNoLeadingHyphen }}
+
+ - name: Store build output
+ uses: actions/upload-artifact@v3
+ with:
+ name: build
+ path: |
+ publish
+ retention-days: 1
+
+ test:
+ permissions:
+ contents: read # for actions/checkout to fetch code
+ actions: read # only required for a private repository by github/codeql-action/upload-sarif to get the Action run status
+ name: Test
+ needs: Build
+ runs-on: ubuntu-latest
+ container:
+ image: mcr.microsoft.com/powershell:${{ matrix.pwshv }}-ubuntu-22.04
+ strategy:
+ matrix:
+ pwshv: ['7.3','7.4']
+
+ steps:
+ - uses: actions/checkout@v4
+
+ - name: Download build output
+ uses: actions/download-artifact@v3
+ with:
+ name: build
+ path: publish
+
+ - name: Test
+ shell: pwsh
+ run: ./build.ps1 test
+
+ publish:
+ permissions:
+ contents: read # for actions/checkout to fetch code
+ actions: read # only required for a private repository by github/codeql-action/upload-sarif to get the Action run status
+ name: Publish
+ needs: Test
+ runs-on: ubuntu-latest
+ container:
+ image: mcr.microsoft.com/dotnet/sdk:8.0
+ if: github.ref == 'refs/heads/main'
+ steps:
+ - uses: actions/checkout@v4
+
+ - name: Download build output
+ uses: actions/download-artifact@v3
+ with:
+ name: build
+ path: publish
+
+ - name: Publish
+ shell: pwsh
+ run: ./build.ps1 publish
+ env:
+ PSPublishApiKey: ${{ secrets.NUGETAPIKEY }}
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..95deb82
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,399 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Ww][Ii][Nn]32/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+build/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# ASP.NET Scaffolding
+ScaffoldingReadMe.txt
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.tlog
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Coverlet is a free, cross platform Code Coverage Tool
+coverage*.json
+coverage*.xml
+coverage*.info
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio 6 auto-generated project file (contains which files were open etc.)
+*.vbp
+
+# Visual Studio 6 workspace and project file (working project files containing files to include in project)
+*.dsw
+*.dsp
+
+# Visual Studio 6 technical files
+*.ncb
+*.aps
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# Visual Studio History (VSHistory) files
+.vshistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
+
+# Fody - auto-generated XML schema
+FodyWeavers.xsd
+
+# VS Code files for those working on multiple tools
+.vscode/*
+!.vscode/settings.json
+!.vscode/tasks.json
+!.vscode/launch.json
+!.vscode/extensions.json
+*.code-workspace
+
+# Local History for Visual Studio Code
+.history/
+
+# Windows Installer files from build outputs
+*.cab
+*.msi
+*.msix
+*.msm
+*.msp
+
+# JetBrains Rider
+*.sln.iml
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..261eeb9
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/README.md b/README.md
index 87c9758..3fa68a7 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,24 @@
# Import-ConfigData
Load configuration data from multiple file types.
+
+## Docs
+
+[Full Docs](docs)
+
+### Getting Started
+
+Return an object representing the contents of a PowerShell Data File.
+
+```powershell
+#config.psd1
+@{
+ DriveName = "data"
+}
+```
+
+```powershell
+$config = Import-ConfigData -Path config.psd1
+$config.DriveName
+data
+```
diff --git a/build.ps1 b/build.ps1
new file mode 100644
index 0000000..ac4d9a8
--- /dev/null
+++ b/build.ps1
@@ -0,0 +1,214 @@
+#! /usr/bin/pwsh
+
+[CmdletBinding()]
+param (
+ [Parameter(Position = 0)]
+ [ValidateSet('clean', 'build', 'test', 'changelog', 'publish', 'docs')]
+ [string[]]
+ $Task,
+
+ [Parameter(Position = 1)]
+ [int]
+ $Major,
+
+ [Parameter(Position = 2)]
+ [int]
+ $Minor,
+
+ [Parameter(Position = 3)]
+ [int]
+ $Build,
+
+ [Parameter(Position = 4)]
+ [int]
+ $Revision,
+
+ [Parameter(Position = 5)]
+ [string]
+ $Prerelease
+)
+
+if ( (Get-Command 'nbgv' -CommandType Application -ErrorAction SilentlyContinue) ) {
+ if (!$PSBoundParameters.ContainsKey('Major')) { $Major = $(nbgv get-version -v VersionMajor) }
+ if (!$PSBoundParameters.ContainsKey('Minor')) { $Minor = $(nbgv get-version -v VersionMinor) }
+ if (!$PSBoundParameters.ContainsKey('Build')) { $Build = $(nbgv get-version -v BuildNumber) }
+ if (!$PSBoundParameters.ContainsKey('Revision')) { $Revision = $(nbgv get-version -v VersionRevision) }
+}
+
+$parent = $PSScriptRoot
+$parent = [string]::IsNullOrEmpty($parent) ? $pwd.Path : $parent
+$src = Join-Path $parent -ChildPath "src"
+$docs = Join-Path $parent -ChildPath "docs"
+$publish = Join-Path $parent -ChildPath "publish" -AdditionalChildPath 'Import-ConfigData'
+$csproj = Join-Path -Path $src -ChildPath "dotnet" -AdditionalChildPath "dependencies.csproj"
+$bin = Join-Path -Path $src -ChildPath "dotnet" -AdditionalChildPath "bin"
+$obj = Join-Path -Path $src -ChildPath "dotnet" -AdditionalChildPath "obj"
+$lib = Join-Path -Path $publish -ChildPath "lib"
+
+Write-Host "src: $src"
+Write-Host "docs: $docs"
+Write-Host "publish: $publish"
+Write-Host "lib: $lib"
+Write-Host "dotnet: $([Environment]::Version)"
+Write-Host "ps: $($PSVersionTable.PSVersion)"
+
+$manifest = @{
+ Path = Join-Path -Path $publish -ChildPath 'Import-ConfigData.psd1'
+ Author = 'Chris Hunt'
+ CompanyName = 'Chris Hunt'
+ Copyright = 'Chris Hunt'
+ CompatiblePSEditions = @("Desktop", "Core")
+ Description = 'Load configuration data from multiple file types.'
+ LicenseUri = 'https://github.com/cdhunt/Import-ConfigData/blob/main/LICENSE'
+ FunctionsToExport = @()
+ ModuleVersion = [version]::new($Major, $Minor, $Build, $Revision)
+ PowerShellVersion = '5.1'
+ #ProjectUri = 'https://github.com/cdhunt/Import-ConfigData'
+ RootModule = 'Import-ConfigData.psm1'
+ Tags = @('development', 'configuration', 'settings', 'storage', 'yaml', 'toml')
+ RequiredModules = @( @{ModuleName = 'powershell-yaml'; ModuleVersion = '0.4.7' } )
+}
+
+function Clean {
+ param ()
+
+ if (Test-Path $publish) {
+ Remove-Item -Path $publish -Recurse -Force
+ }
+}
+
+function Build {
+ param ()
+
+ New-Item -Path $publish -ItemType Directory -ErrorAction SilentlyContinue | Out-Null
+
+ dotnet publish $csproj -o $lib
+ Get-ChildItem -Path $lib -filter "*.json" | Remove-Item -Force -ErrorAction SilentlyContinue
+ Get-ChildItem -Path $lib -filter "*.pdb" | Remove-Item -Force -ErrorAction SilentlyContinue
+ Get-ChildItem -Path $lib -filter "System.Management.Automation.dll" | Remove-Item -Force -ErrorAction SilentlyContinue
+ Get-ChildItem -Path $lib -filter "dependencies.dll" | Remove-Item -Force -ErrorAction SilentlyContinue
+
+ Copy-Item -Path "$src/Import-ConfigData.psm1" -Destination $publish
+ Copy-Item -Path @("$parent/LICENSE", "$parent/README.md") -Destination $publish -ErrorAction SilentlyContinue
+
+ $internalFunctions = Get-ChildItem -Path "$src/internal/Add-PackageTypes.ps1"
+ $publicFunctions = Get-ChildItem -Path "$src/public/*.ps1"
+ $privateFunctions = Get-ChildItem -Path "$src/private/*.ps1" -ErrorAction SilentlyContinue
+
+ New-Item -Path "$publish/internal" -ItemType Directory -ErrorAction SilentlyContinue | Out-Null
+ foreach ($function in $internalFunctions) {
+ Copy-Item -Path $function.FullName -Destination "$publish/internal/$($function.Name)"
+ }
+
+ New-Item -Path "$publish/public" -ItemType Directory -ErrorAction SilentlyContinue | Out-Null
+ foreach ($function in $publicFunctions) {
+ Copy-Item -Path $function.FullName -Destination "$publish/public/$($function.Name)"
+ '. "$PSSCriptRoot/public/{0}"' -f $function.Name | Add-Content "$publish/Import-ConfigData.psm1"
+ $manifest.FunctionsToExport += $function.BaseName
+ }
+
+ New-Item -Path "$publish/private" -ItemType Directory -ErrorAction SilentlyContinue | Out-Null
+ foreach ($function in $privateFunctions) {
+ Copy-Item -Path $function.FullName -Destination "$publish/private/$($function.Name)"
+ '. "$PSSCriptRoot/private/{0}"' -f $function.Name | Add-Content "$publish/Import-ConfigData.psm1"
+ }
+
+ if ($PSBoundParameters.ContainsKey('Prerelease')) {
+ $manifest.Add('Prerelease', $PreRelease)
+ }
+
+ New-ModuleManifest @manifest
+
+}
+
+function Test {
+ param ()
+
+ if ($null -eq (Get-Module Pester -ListAvailable)) {
+ Install-Module -Name Pester -Confirm:$false -Force
+ }
+
+ Invoke-Pester -Path test -Output detailed
+}
+
+
+function ChangeLog {
+ param ()
+
+}
+
+function Commit {
+ param ()
+
+ git rev-parse --short HEAD
+}
+
+function Publish {
+ param ()
+
+ <# Disabled for now
+ $docChanges = git status docs -s
+
+ if ($docChanges.count -gt 0) {
+ Write-Warning "There are pending Docs change. Run './build.ps1 docs', review and commit updated docs."
+ }
+ #>
+
+ $repo = if ($env:PSPublishRepo) { $env:PSPublishRepo } else { 'PSGallery' }
+
+ $notes = ChangeLog
+ Publish-Module -Path $publish -Repository $repo -NuGetApiKey $env:PSPublishApiKey -ReleaseNotes $notes
+}
+
+function Docs {
+ param ()
+
+ Import-Module $publish -Force
+
+ $commands = Get-Command -Module Import-ConfigData
+ $HelpToMd = Join-Path -Path $src -ChildPath 'internal' -AdditionalChildPath 'Export-HelpToMd.ps1'
+ . $HelpToMd
+
+ @('# Import-ConfigData', [System.Environment]::NewLine) | Set-Content -Path "$docs/README.md"
+ $($manifest.Description) | Add-Content -Path "$docs/README.md"
+ @('## Cmdlets', [System.Environment]::NewLine) | Add-Content -Path "$docs/README.md"
+
+ foreach ($command in $Commands | Sort-Object -Property Verb) {
+ $name = $command.Name
+ $docPath = Join-Path -Path $docs -ChildPath "$name.md"
+ $help = Get-Help -Name $name
+
+ Export-HelpToMd $help | Set-Content -Path $docPath
+
+ "- [$name]($name.md) $($help.Synopsis)" | Add-Content -Path "$docs/README.md"
+ }
+
+ ChangeLog | Set-Content -Path "$parent/Changelog.md"
+}
+
+switch ($Task) {
+ { $_ -contains 'clean' } {
+ Clean
+ }
+ { $_ -contains 'build' } {
+ Clean
+ Build
+ }
+ { $_ -contains 'test' } {
+ Test
+ }
+ { $_ -contains 'changelog' } {
+ ChangeLog
+ }
+ { $_ -contains 'publish' } {
+ Docs
+ Publish
+ }
+ { $_ -contains 'docs' } {
+ Docs
+ }
+ Default {
+ Clean
+ Build
+ }
+}
\ No newline at end of file
diff --git a/docs/Import-ConfigData.md b/docs/Import-ConfigData.md
new file mode 100644
index 0000000..823bec2
--- /dev/null
+++ b/docs/Import-ConfigData.md
@@ -0,0 +1,61 @@
+# Import-ConfigData
+
+
+Load configuration data from multiple file types. The returned object should look the same regardless of the source format.
+## Parameters
+
+
+### Parameter Set 1
+
+
+- `[String]` **Path** _Specifies a path to a configuration file with an extention of psd1, toml, yaml, or yml._ Mandatory, ValueFromPipeline
+
+
+## Examples
+
+
+### Example 1
+
+
+Return an object representing the contents of a PowerShell Data File.
+
+
+```powershell
+$config = Import-ConfigData -Path config.psd1
+$config.DriveName
+data
+```
+
+
+### Example 2
+
+
+Return an object representing the contents of a TOML File.
+
+
+```powershell
+$config = Import-ConfigData -Path config.toml
+$config.DriveName
+data
+```
+
+
+### Example 3
+
+
+Return an object representing the contents of a YAML File.
+
+
+```powershell
+$config = Import-ConfigData -Path config.yaml
+$config.DriveName
+data
+```
+
+
+## Links
+
+
+- [https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_data_files?view=powershell-7.4](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_data_files?view=powershell-7.4)
+- [https://toml.io/](https://toml.io/)
+- [https://yaml.org/](https://yaml.org/)
diff --git a/docs/README.md b/docs/README.md
new file mode 100644
index 0000000..cb8942e
--- /dev/null
+++ b/docs/README.md
@@ -0,0 +1,8 @@
+# Import-ConfigData
+
+
+Load configuration data from multiple file types.
+## Cmdlets
+
+
+- [Import-ConfigData](Import-ConfigData.md) Load configuration data from multiple file types.
diff --git a/src/Import-ConfigData.psm1 b/src/Import-ConfigData.psm1
new file mode 100644
index 0000000..d916aa5
--- /dev/null
+++ b/src/Import-ConfigData.psm1
@@ -0,0 +1,3 @@
+# Load all package dlls
+. "$PSScriptRoot/internal/Add-PackageTypes.ps1"
+Add-PackageTypes -LibsDirectory "$PSScriptRoot/lib"
diff --git a/src/dotnet/dependencies.csproj b/src/dotnet/dependencies.csproj
new file mode 100644
index 0000000..314d715
--- /dev/null
+++ b/src/dotnet/dependencies.csproj
@@ -0,0 +1,12 @@
+
+
+
+ netstandard2.0
+ 1.0.0
+
+
+
+
+
+
+
diff --git a/src/internal/Add-PackageTypes.ps1 b/src/internal/Add-PackageTypes.ps1
new file mode 100644
index 0000000..8d28dfa
--- /dev/null
+++ b/src/internal/Add-PackageTypes.ps1
@@ -0,0 +1,12 @@
+function Add-PackageTypes {
+ param(
+ [Parameter(Mandatory = $true)]
+ [string]$LibsDirectory
+ )
+
+ process {
+ foreach ($path in (Get-ChildItem $LibsDirectory | Where-Object { $_.Name -like '*.dll' -and $_.BaseName -ne "grpc_csharp_ext.x64" } | Select-Object -ExpandProperty FullName)) {
+ Add-Type -Path $path
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/internal/Export-HelpToMd.ps1 b/src/internal/Export-HelpToMd.ps1
new file mode 100644
index 0000000..f943d60
--- /dev/null
+++ b/src/internal/Export-HelpToMd.ps1
@@ -0,0 +1,148 @@
+function Export-HelpToMd {
+ [CmdletBinding()]
+ param (
+ [Parameter(Mandatory, Position = 0, ValueFromPipeline)]
+ [PSCustomObject]
+ $HelpInfo
+ )
+
+ begin {
+ function GetText {
+ param ([string]$text, [string]$default)
+
+ $text = $text.Trim()
+ if ([string]::IsNullOrEmpty($text)) {
+ if ([string]::IsNullOrEmpty($default)) {
+ $default = 'No description'
+ }
+ return $default
+ }
+ return $text
+ }
+
+ function GetName ([PSCustomObject]$help) {
+ $lines = @()
+ $lines += '# {0}' -f $help.Name
+ $lines += [System.Environment]::NewLine
+ return $lines
+ }
+
+ function GetDescription {
+ param ($description, [string]$noDesc)
+
+ $description = $description.Description.Text | Out-String
+ $line = '{0}' -f (GetText $description $noDesc)
+
+ return $line
+ }
+
+ function GetParameterSet ([PSCustomObject]$help) {
+ $lines = @()
+ $setNum = 1
+
+ $lines += '## Parameters'
+
+ foreach ($set in $help.syntax.syntaxItem) {
+ $lines += [System.Environment]::NewLine
+ $lines += '### Parameter Set {0}' -f $setNum
+ $lines += [System.Environment]::NewLine
+
+ foreach ($param in $set.Parameter) {
+ $paramStringParts = @()
+
+ $paramStringParts += '- `[{0}]`' -f (GetText $param.parameterValue 'switch')
+
+ $paramStringParts += '**{0}**' -f $param.Name
+
+ $paramStringParts += '_{0}_ ' -f (GetDescription -description $param -noDesc 'Parameter help description')
+
+ $attributes = @()
+ if ($param.required -eq 'true') { $attributes += 'Mandatory' }
+ if ($param.pipelineInput -like '*ByValue*') { $attributes += 'ValueFromPipeline' }
+
+ $paramStringParts += $attributes -join ', '
+
+ $lines += $paramStringParts -join ' '
+ }
+
+ $setNum++
+ }
+
+ return $lines
+ }
+
+ function GetExample ([PSCustomObject]$help) {
+ $lines = @()
+ $exNum = 1
+
+ $lines += [System.Environment]::NewLine
+ $lines += '## Examples'
+
+ foreach ($exampleList in $help.examples.example) {
+ foreach ($example in $exampleList) {
+ $lines += [System.Environment]::NewLine
+ $lines += '### Example {0}' -f $exNum
+ $lines += [System.Environment]::NewLine
+
+ $lines += $example.remarks.Text.Where({ ![string]::IsNullOrEmpty($_) })
+ $lines += [System.Environment]::NewLine
+
+ $lines += '```powershell'
+ $lines += $example.code.Trim("`t")
+ $lines += '```'
+
+ }
+ $exNum++
+ }
+
+ return $lines
+ }
+
+ function GetLink ([PSCustomObject]$help, $Commands) {
+ if ($help.relatedLinks.count -gt 0) {
+ $lines = @()
+
+ $lines += [System.Environment]::NewLine
+ $lines += '## Links'
+ $lines += [System.Environment]::NewLine
+
+ foreach ($link in $help.relatedLinks) {
+
+ foreach ($text in $link.navigationLink.linkText) {
+
+ if ($text -match '\w{3,}-\w{3,}') {
+ $uri = $text
+ $lines += '- [{0}]({0}.md)' -f $uri
+ }
+
+ if ($text -match 'images\/.+\.png') {
+ $uri = $text
+ $lines += '- [{0}]({0})' -f $uri
+ }
+
+ }
+ foreach ($uri in $link.navigationLink.uri) {
+ if (![string]::IsNullOrEmpty($uri)) {
+ $lines += '- [{0}]({0})' -f $uri
+ }
+ }
+ }
+
+ return $lines
+ }
+ }
+ }
+
+ process {
+
+ GetName $HelpInfo
+ GetDescription $HelpInfo $HelpInfo.Synopsis
+ GetParameterSet $HelpInfo
+ GetExample $HelpInfo
+ GetLink $HelpInfo
+ }
+
+ end {
+
+ }
+}
diff --git a/src/private/Import-TomlConfigData.ps1 b/src/private/Import-TomlConfigData.ps1
new file mode 100644
index 0000000..95fe42a
--- /dev/null
+++ b/src/private/Import-TomlConfigData.ps1
@@ -0,0 +1,38 @@
+function Import-TomlConfigData {
+ [CmdletBinding()]
+ param (
+ [Parameter(Mandatory,
+ Position = 0,
+ ValueFromPipeline,
+ ValueFromPipelineByPropertyName)]
+ [Alias("PSPath")]
+ [ValidateNotNullOrEmpty()]
+ [string]
+ $Path
+ )
+
+ $content = Get-Content -Path $Path -Raw
+
+ $tomlModel = [Tomlyn.Toml]::ToModel($content)
+
+ foreach ($key in $tomlModel.Keys) {
+ if ($tomlModel[$key].GetType().IsValueType -or $tomlModel[$key].GetType().Name -eq 'String') {
+ $top = @{$key = $tomlModel[$key] }
+ break;
+ }
+ else {
+ $top = @{$key = [Collections.Generic.List[Object]]::new() }
+ foreach ($prop in $tomlModel[$key]) {
+
+ $next = @{}
+ foreach ($pk in $prop.Keys) {
+ $next.Add($pk, $prop[$pk])
+ }
+
+ $top[$key].Add($next)
+ }
+ }
+ }
+
+ $top | Write-Output
+}
\ No newline at end of file
diff --git a/src/private/Import-YamlConfigData.ps1 b/src/private/Import-YamlConfigData.ps1
new file mode 100644
index 0000000..37879ed
--- /dev/null
+++ b/src/private/Import-YamlConfigData.ps1
@@ -0,0 +1,29 @@
+function Import-YamlConfigData {
+ [CmdletBinding()]
+ param (
+ [Parameter(Mandatory,
+ Position = 0,
+ ValueFromPipeline,
+ ValueFromPipelineByPropertyName)]
+ [Alias("PSPath")]
+ [ValidateNotNullOrEmpty()]
+ [string]
+ $Path
+ )
+
+ begin {
+
+ }
+
+ process {
+
+ $content = Get-Content -Path $Path -Raw
+
+ ConvertFrom-Yaml -Yaml $content
+
+ }
+
+ end {
+
+ }
+}
\ No newline at end of file
diff --git a/src/public/Import-ConfigData.ps1 b/src/public/Import-ConfigData.ps1
new file mode 100644
index 0000000..56df97d
--- /dev/null
+++ b/src/public/Import-ConfigData.ps1
@@ -0,0 +1,64 @@
+function Import-ConfigData {
+ <#
+.SYNOPSIS
+ Load configuration data from multiple file types.
+.DESCRIPTION
+ Load configuration data from multiple file types. The returned object should look the same regardless of the source format.
+.PARAMETER Path
+ Specifies a path to a configuration file with an extention of psd1, toml, yaml, or yml.
+.LINK
+ https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_data_files?view=powershell-7.4
+.LINK
+ https://toml.io/
+.LINK
+ https://yaml.org/
+.EXAMPLE
+ $config = Import-ConfigData -Path config.psd1
+ $config.DriveName
+ data
+
+ Return an object representing the contents of a PowerShell Data File.
+.EXAMPLE
+ $config = Import-ConfigData -Path config.toml
+ $config.DriveName
+ data
+
+ Return an object representing the contents of a TOML File.
+.EXAMPLE
+ $config = Import-ConfigData -Path config.yaml
+ $config.DriveName
+ data
+
+ Return an object representing the contents of a YAML File.
+#>
+ [CmdletBinding()]
+ param (
+ [Parameter(Mandatory,
+ Position = 0,
+ ValueFromPipeline,
+ ValueFromPipelineByPropertyName)]
+ [Alias("PSPath")]
+ [ValidateNotNullOrEmpty()]
+ [string]
+ $Path
+ )
+
+ begin {
+
+ }
+
+ process {
+ $file = Get-Item -Path $Path -ErrorAction Stop
+
+ switch ($file.Extension) {
+ '.psd1' { Import-PowerShellDataFile -Path $Path; break }
+ '.toml' { Import-TomlConfigData -Path $Path; break }
+ '.yaml' { Import-YamlConfigData -Path $Path; break }
+ '.yml' { Import-YamlConfigData -Path $Path; break }
+ }
+ }
+
+ end {
+
+ }
+}
\ No newline at end of file
diff --git a/test/Import-ConfigData.Tests.ps1 b/test/Import-ConfigData.Tests.ps1
new file mode 100644
index 0000000..d8cbbe7
--- /dev/null
+++ b/test/Import-ConfigData.Tests.ps1
@@ -0,0 +1,49 @@
+BeforeAll {
+ Import-Module "$PSScriptRoot/../publish/Import-ConfigData" -Force
+
+}
+
+Describe 'Import-ConfigData' {
+ Context 'Simple Object' {
+ It 'Should import a file' -ForEach @(
+ @{ config = "$PSScriptRoot/test1/TestConfig.psd1"; type = 'PSD1' }
+ @{ config = "$PSScriptRoot/test1/TestConfig.toml"; type = 'TOML' }
+ @{ config = "$PSScriptRoot/test1/TestConfig.yml"; type = 'YAML' }
+ ) {
+ $results = Import-ConfigData -Path $config
+
+ $results.DriveName | Should -BeExactly 'data'
+ $results | Should -BeOfType 'Hashtable'
+ }
+ }
+ Context 'ObjectArray' {
+
+ It 'Should import a file' -ForEach @(
+ @{ config = "$PSScriptRoot/test2/TestConfig.psd1"; type = 'PSD1' }
+ @{ config = "$PSScriptRoot/test2/TestConfig.toml"; type = 'TOML' }
+ @{ config = "$PSScriptRoot/test2/TestConfig.yml"; type = 'YAML' }
+ ) {
+ $results = Import-ConfigData -Path $config
+
+ $results.ObjectArray.Count | Should -Be 2
+ $results.ObjectArray[0].PropertyString | Should -BeExactly 'test_value'
+ $results.ObjectArray[0].PropertyInt | Should -Be 1
+ $results.ObjectArray[0].PropertyBool | Should -Be $true
+ $results.ObjectArray[0].PropertyList.Count | Should -Be 3
+ $results.ObjectArray[0].PropertyList[0] | Should -Be 4
+ $results.ObjectArray[0].PropertyList[1] | Should -Be 5
+ $results.ObjectArray[0].PropertyList[2] | Should -Be 6
+
+ $results.ObjectArray[1].PropertyString | Should -BeExactly 'test_value_2'
+ $results.ObjectArray[1].PropertyInt | Should -Be 2
+ $results.ObjectArray[1].PropertyBool | Should -Be $false
+ $results.ObjectArray[1].PropertyList.Count | Should -Be 2
+ $results.ObjectArray[1].PropertyList[0] | Should -Be "one"
+ $results.ObjectArray[1].PropertyList[1] | Should -Be "two"
+ }
+ }
+}
+
+AfterAll {
+ Remove-Module Import-ConfigData
+}
\ No newline at end of file
diff --git a/test/test1/TestConfig.psd1 b/test/test1/TestConfig.psd1
new file mode 100644
index 0000000..ace0d03
--- /dev/null
+++ b/test/test1/TestConfig.psd1
@@ -0,0 +1,3 @@
+@{
+ DriveName = "data"
+}
\ No newline at end of file
diff --git a/test/test1/TestConfig.toml b/test/test1/TestConfig.toml
new file mode 100644
index 0000000..05cef0f
--- /dev/null
+++ b/test/test1/TestConfig.toml
@@ -0,0 +1 @@
+DriveName = "data"
diff --git a/test/test1/TestConfig.yml b/test/test1/TestConfig.yml
new file mode 100644
index 0000000..d70b18a
--- /dev/null
+++ b/test/test1/TestConfig.yml
@@ -0,0 +1 @@
+DriveName: data
diff --git a/test/test2/TestConfig.psd1 b/test/test2/TestConfig.psd1
new file mode 100644
index 0000000..51644bd
--- /dev/null
+++ b/test/test2/TestConfig.psd1
@@ -0,0 +1,16 @@
+@{
+ ObjectArray = @(
+ @{
+ PropertyString = 'test_value'
+ PropertyInt = 1
+ PropertyBool = $true
+ PropertyList = @(4, 5, 6)
+ }
+ @{
+ PropertyString = 'test_value_2'
+ PropertyInt = 2
+ PropertyBool = $false
+ PropertyList = @("one", "two")
+ }
+ )
+}
\ No newline at end of file
diff --git a/test/test2/TestConfig.toml b/test/test2/TestConfig.toml
new file mode 100644
index 0000000..f8b9e79
--- /dev/null
+++ b/test/test2/TestConfig.toml
@@ -0,0 +1,11 @@
+[[ObjectArray]]
+ PropertyString = "test_value"
+ PropertyInt = 1
+ PropertyBool = true
+ PropertyList = [4, 5, 6]
+
+[[ObjectArray]]
+ PropertyString = "test_value_2"
+ PropertyInt = 2
+ PropertyBool = false
+ PropertyList = ["one","two"]
\ No newline at end of file
diff --git a/test/test2/TestConfig.yml b/test/test2/TestConfig.yml
new file mode 100644
index 0000000..2806f72
--- /dev/null
+++ b/test/test2/TestConfig.yml
@@ -0,0 +1,9 @@
+ObjectArray:
+ - PropertyString: "test_value"
+ PropertyInt: 1
+ PropertyBool: true
+ PropertyList: [4, 5, 6]
+ - PropertyString: "test_value_2"
+ PropertyInt: 2
+ PropertyBool: false
+ PropertyList: ["one", "two"]
diff --git a/version.json b/version.json
new file mode 100644
index 0000000..50ea6af
--- /dev/null
+++ b/version.json
@@ -0,0 +1,9 @@
+{
+ "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/main/src/NerdBank.GitVersioning/version.schema.json",
+ "version": "0.1",
+ "cloudBuild": {
+ "buildNumber": {
+ "enabled": true
+ }
+ }
+}
\ No newline at end of file