MountAnything 0.2.1

There is a newer version of this package available.
See the version list below for details.
dotnet add package MountAnything --version 0.2.1
NuGet\Install-Package MountAnything -Version 0.2.1
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="MountAnything" Version="0.2.1" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add MountAnything --version 0.2.1
#r "nuget: MountAnything, 0.2.1"
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install MountAnything as a Cake Addin
#addin nuget:?package=MountAnything&version=0.2.1

// Install MountAnything as a Cake Tool
#tool nuget:?package=MountAnything&version=0.2.1

MountAnything

A framework for building powershell providers to make it easy to navigate arbitrary API's as a hierarchical virtual filesystem of objects.

Getting started

  1. Reference the MountAnything nuget package in your csproj project that will contain your powershell provider.
  2. Create a class that inherits from MountAnythingProvider.
  3. Implement the CreateRouter method. For information on creating a router, see the Router section below.

Key abstractions

There are three key abstractions that drive MountAnything. The Router, PathHandler's, and Item's:

Router

Every path in the virtual filesystem is processed by the Router to determine which PathHandler will process the command. The Router API composes a nested hierarchy of routes. Under the hood, routes are regex based, but you usually can use a more convenient extension method to avoid needing to actually deal with regex's. Here is an example of the routing api from the MountAws project:

router.MapRegex<RegionHandler>("(?<Region>[a-z0-9-]+)", region =>
{
    region.MapLiteral<EcsRootHandler>("ecs", ecs =>
    {
        ecs.MapLiteral<TaskDefinitionsHandler>("task-definitions", taskDefinitions =>
        {
            taskDefinitions.Map<TaskDefinitionHandler>();
        });
        ecs.MapLiteral<ClustersHandler>("clusters", clusters =>
        {
            clusters.Map<ClusterHandler,Cluster>(cluster =>
            {
                cluster.MapLiteral<ServicesHandler>("services", services =>
                {
                    services.Map<ServiceHandler>();
                });
            });
        });
    });
});

In the example, you can see a few different variations of Map methods used. All of them take a generic type argument that corresponds to the IPathHandler that will be invoked for matching routes. They are:

  • MapLiteral - This matches on the literal string (e.g. constant) passed into it. Only that literal string will match the route.
  • Map<THandler> - This matches any supported character (pretty much anything besides a /, which is used as the path separator) at this hierarchy level. You can optionally pass in a string as the first argument to this method if you would like to capture the value of the matched value. The captured value will be given the name that is passed as the argument. The captured value can be used for dependency injection into the PathHander of this or any child route.
  • Map<THandler,TCapture> - This is similar to the Map above, except it contains a second type parameter that is a TypedString whose value will be populated from the matched route value and can be injected into the constructor of this or any child PathHandler.
  • MapRegex - This is the lower level method that the above two methods call under the hood. Any regex is acceptable, so long as it does not contain the ^ or $ characters for declaring the beginning or end of a string. Those are implicitly added by the router as necessary. It is important to note that any regex you are adding is implicitly concatenated with the regex's built by parent and child routes when the router is matching. Named captures are allowed in the regex and those captured values can be used for dependency injection into the PathHandler of this or any child route.

PathHandler

The PathHandler is in charge of processing a command to the powershell provider. While there is an IPathHandler, it is expected that 99% of the time you will want to use the PathHandler abstract base class instead for convenience. It will automatically handle things like caching for you, which helps make things like tab completion as performant as possible.

The PathHandler base class has only two methods that you are required to implement:

  • GetItemImpl - This is called when the Get-Item command is called. It should return the IItem that corresponds to the path that this PathHandler is processing. If no item exists at this path, it should return null.
  • GetChildItemsImpl - This is called when the Get-ChildItems command. Its also used to support tab completion by default. It should return all of the child items of the item returned by the GetItemImpl method.

In addition, you can optionally override the following methods when helpful/necessary:

  • ExistsImpl - By default, existence is checked by calling GetItem and determining if it returned null or not. However, if you can provide a more performant/optimal implementation, you can override this method.
  • GetChildItems(string filter) - This method supports tab completion, as well as when the -Filter argument is used on the Get-ChildItems command. By default, the GetChildItemsImpl method is called and the filter as applied to entire set of items returned. However, if you can provide a more performant implementation that does not require fetching all items first, you are encouraged to do so by overriding this method.
  • CacheChildren - By default, the paths of the child items returned by GetChildItemsImpl are cached to help make things like tab completion faster. However, if there are potentially a very large number of child items for this handler, you may want to tell it not to do this by overriding this property and returning false.
  • GetItemCommandDefaultFreshness - This allows you to customize when the cache is used for Get-Item commands.
  • GetChildItemsCommandDefaultFreshness - This allows you to customize when the cache is used for Get-ChildItems commands.

Item

This represents the object/item that is returned to the console by Get-Item and Get-ChildItems commands. It is generally a wrapper class around an underlying object that will be sent to the console. There is a generic version of Item<T> where the type argument represents the .net type of the item that will be sent to the console. If you inherit from the non-generic Item, the underlying type will be a PSObject. Either way, all properties on the underlying type will be written to the powershell pipeline. The Item class has a couple methods that need to be implemented in the subclass to tell the powershell provider what the path of the item is:

  • ItemName - This identifies the virtual "filename" of the item. It should be something that naturally identifies the item. Prefer human friendly names if they are guaranteed to be unique.
  • IsContainer - This indicates whether this could have child items or not.

Here is an example of a simple Item implementation:

public class SecurityGroupItem : Item<SecurityGroup>
{
    public SecurityGroupItem(ItemPath parentPath, SecurityGroup securityGroup) : base(parentPath, securityGroup) {}

    public override string ItemName => UnderlyingObject.GroupId;
    
    public override bool IsContainer => false;
}
Product Compatible and additional computed target framework versions.
.NET net6.0 is compatible.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
0.7.0 368 1/28/2023
0.7.0-beta15 155 1/12/2023
0.7.0-beta14 126 1/12/2023
0.7.0-beta13 356 1/11/2023
0.7.0-beta12 156 1/11/2023
0.7.0-beta11 157 1/10/2023
0.7.0-beta10 144 1/10/2023
0.7.0-beta09 164 1/6/2023
0.7.0-beta08 133 1/5/2023
0.7.0-beta07 144 1/3/2023
0.7.0-beta06 154 12/3/2022
0.7.0-beta05 154 12/3/2022
0.7.0-beta04 186 11/7/2022
0.7.0-beta03 144 11/7/2022
0.7.0-beta02 148 11/7/2022
0.7.0-beta01 151 11/6/2022
0.6.0 504 9/17/2022
0.5.6 465 5/7/2022
0.5.5 434 5/7/2022
0.5.4 479 4/27/2022
0.5.3 447 4/27/2022
0.5.2 448 4/27/2022
0.5.1 447 4/26/2022
0.5.0 438 4/26/2022
0.4.0 557 2/2/2022
0.3.2 310 1/8/2022
0.3.1 276 1/7/2022
0.3.0 295 1/6/2022
0.2.1 294 1/4/2022
0.2.0 287 1/4/2022
0.1.4 299 1/3/2022
0.1.3 306 1/2/2022
0.1.2 296 1/2/2022
0.1.1 272 1/2/2022
0.1.0 310 1/2/2022
0.0.1-dev 192 1/2/2022

Store router and cache statics keyed by provider to ensure multiple providers using the same `MountAnythingProvider` base class have unique cache and router instances.