2021-09-07 05:15:45 +00:00
|
|
|
using System;
|
|
|
|
using System.Collections.Generic;
|
|
|
|
using System.IO;
|
2022-06-05 18:44:51 +00:00
|
|
|
using System.Reflection;
|
2021-09-07 05:15:45 +00:00
|
|
|
using System.Threading.Tasks;
|
2022-06-05 18:44:51 +00:00
|
|
|
|
2021-09-07 05:15:45 +00:00
|
|
|
using Autofac;
|
2022-06-05 18:44:51 +00:00
|
|
|
|
|
|
|
using MfGames.ToolBuilder;
|
|
|
|
|
2021-09-07 05:15:45 +00:00
|
|
|
using Serilog;
|
2022-06-05 18:44:51 +00:00
|
|
|
|
2021-09-07 05:15:45 +00:00
|
|
|
using Zio;
|
|
|
|
using Zio.FileSystems;
|
|
|
|
|
2022-07-18 21:07:34 +00:00
|
|
|
using Module = Autofac.Module;
|
|
|
|
|
2022-09-06 05:53:22 +00:00
|
|
|
namespace MfGames.Nitride;
|
2022-06-05 18:44:51 +00:00
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// A class that implements a builder pattern for gathering all the
|
|
|
|
/// components of a static website. Once everything is build, then calling
|
|
|
|
/// `Build()` will generate the resulting website.
|
|
|
|
/// </summary>
|
|
|
|
public class NitrideBuilder
|
2021-09-07 05:15:45 +00:00
|
|
|
{
|
2022-06-05 18:44:51 +00:00
|
|
|
private readonly string[] arguments;
|
|
|
|
|
|
|
|
private readonly List<Action<ContainerBuilder>> configureContainerCallbacks;
|
|
|
|
|
2021-09-07 05:15:45 +00:00
|
|
|
/// <summary>
|
2022-06-05 18:44:51 +00:00
|
|
|
/// An event that is called after the container is built but before
|
|
|
|
/// the application runs.
|
2021-09-07 05:15:45 +00:00
|
|
|
/// </summary>
|
2023-01-15 00:19:42 +00:00
|
|
|
private readonly List<Action<NitrideBuilder, ILifetimeScope>>
|
|
|
|
configureSiteCallbacks;
|
2022-06-05 18:44:51 +00:00
|
|
|
|
|
|
|
private readonly NitrideModule nitrideModule;
|
|
|
|
|
|
|
|
public NitrideBuilder(string[] arguments)
|
2021-09-07 05:15:45 +00:00
|
|
|
{
|
2022-06-05 18:44:51 +00:00
|
|
|
this.arguments = arguments;
|
2023-01-15 00:19:42 +00:00
|
|
|
this.configureSiteCallbacks =
|
|
|
|
new List<Action<NitrideBuilder, ILifetimeScope>>();
|
2022-06-05 18:44:51 +00:00
|
|
|
this.configureContainerCallbacks = new List<Action<ContainerBuilder>>();
|
|
|
|
this.nitrideModule = new NitrideModule();
|
2022-07-09 04:52:10 +00:00
|
|
|
|
|
|
|
this.nitrideModule.ApplicationName = Assembly.GetExecutingAssembly()
|
|
|
|
.GetName()
|
|
|
|
.Name!;
|
2022-06-05 18:44:51 +00:00
|
|
|
}
|
2021-09-07 05:15:45 +00:00
|
|
|
|
2022-06-05 18:44:51 +00:00
|
|
|
/// <summary>
|
|
|
|
/// Gets or sets the input directory to automatically register as the
|
|
|
|
/// source of the files. If this is not set, then no Zio.IFileSystem
|
|
|
|
/// will be registered and it will have to be done manually.
|
|
|
|
/// </summary>
|
|
|
|
public DirectoryInfo? RootDirectory { get; set; }
|
2021-09-07 05:15:45 +00:00
|
|
|
|
2022-06-05 18:44:51 +00:00
|
|
|
/// <summary>
|
|
|
|
/// Allows for configuration of the Autofac container to register
|
|
|
|
/// additional types, pipelines, and modules.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="callback">The callback to configure the container.</param>
|
|
|
|
/// <returns>The builder to chain operations.</returns>
|
|
|
|
public NitrideBuilder ConfigureContainer(Action<ContainerBuilder> callback)
|
|
|
|
{
|
|
|
|
this.configureContainerCallbacks.Add(callback);
|
2022-07-09 04:52:10 +00:00
|
|
|
|
2022-06-05 18:44:51 +00:00
|
|
|
return this;
|
|
|
|
}
|
2021-09-07 05:15:45 +00:00
|
|
|
|
2022-06-05 18:44:51 +00:00
|
|
|
/// <summary>
|
|
|
|
/// Registers a callback to be called after the container is built but
|
|
|
|
/// before the application runs.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="callback">The callback to register.</param>
|
|
|
|
/// <returns>The builder for chaining.</returns>
|
2023-01-15 00:19:42 +00:00
|
|
|
public NitrideBuilder ConfigureSite(
|
|
|
|
Action<NitrideBuilder, ILifetimeScope> callback)
|
2022-06-05 18:44:51 +00:00
|
|
|
{
|
|
|
|
this.configureSiteCallbacks.Add(callback);
|
2022-07-09 04:52:10 +00:00
|
|
|
|
2022-06-05 18:44:51 +00:00
|
|
|
return this;
|
|
|
|
}
|
2021-09-07 05:15:45 +00:00
|
|
|
|
2022-06-05 18:44:51 +00:00
|
|
|
/// <summary>
|
|
|
|
/// Generates or builds the resulting website based on the given
|
|
|
|
/// command.
|
|
|
|
/// </summary>
|
|
|
|
/// <returns>The task once completed.</returns>
|
|
|
|
public async Task<int> RunAsync()
|
|
|
|
{
|
|
|
|
if (this.nitrideModule.ApplicationName == null)
|
2021-09-07 05:15:45 +00:00
|
|
|
{
|
2022-06-05 18:44:51 +00:00
|
|
|
throw new InvalidOperationException(
|
|
|
|
"Application name must be set, such as with the NitrideBuilder.WithApplicationName() to properly run.");
|
2021-09-07 05:15:45 +00:00
|
|
|
}
|
|
|
|
|
2022-07-10 00:24:55 +00:00
|
|
|
return await ToolBoxBuilder
|
|
|
|
.Create(this.nitrideModule.ApplicationName, this.arguments)
|
2022-06-05 18:44:51 +00:00
|
|
|
.ConfigureContainer(this.ConfigureContainer)
|
|
|
|
.Build()
|
|
|
|
.RunAsync();
|
|
|
|
}
|
2021-09-07 05:15:45 +00:00
|
|
|
|
2022-07-18 21:07:34 +00:00
|
|
|
/// <summary>
|
|
|
|
/// Initialize the builder with a given Autofac module.
|
|
|
|
/// </summary>
|
|
|
|
/// <typeparam name="TModule">The type of module to use.</typeparam>
|
|
|
|
/// <returns>The builder to chain operations.</returns>
|
|
|
|
public NitrideBuilder UseModule<TModule>()
|
|
|
|
where TModule : Module, new()
|
|
|
|
{
|
|
|
|
this.ConfigureContainer(x => x.RegisterModule<TModule>());
|
|
|
|
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Initialize the builder with a given Autofac module.
|
|
|
|
/// </summary>
|
|
|
|
/// <typeparam name="TModule">The type of module to use.</typeparam>
|
|
|
|
/// <returns>The builder to chain operations.</returns>
|
|
|
|
public NitrideBuilder UseModule(Module module)
|
|
|
|
{
|
|
|
|
this.ConfigureContainer(x => x.RegisterModule(module));
|
|
|
|
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
2022-06-05 18:44:51 +00:00
|
|
|
/// <summary>
|
|
|
|
/// Sets the description of the builder.
|
|
|
|
/// </summary>
|
|
|
|
public NitrideBuilder WithApplicationDescription(string value)
|
|
|
|
{
|
|
|
|
this.nitrideModule.Description = value;
|
2022-07-09 04:52:10 +00:00
|
|
|
|
2022-06-05 18:44:51 +00:00
|
|
|
return this;
|
|
|
|
}
|
2021-09-07 05:15:45 +00:00
|
|
|
|
2022-06-05 18:44:51 +00:00
|
|
|
/// <summary>
|
|
|
|
/// Sets the name of the application, which is displayed in the help screen.
|
|
|
|
/// </summary>
|
|
|
|
public NitrideBuilder WithApplicationName(string value)
|
|
|
|
{
|
|
|
|
this.nitrideModule.ApplicationName = value;
|
2022-07-09 04:52:10 +00:00
|
|
|
|
2022-06-05 18:44:51 +00:00
|
|
|
return this;
|
|
|
|
}
|
2021-09-07 05:15:45 +00:00
|
|
|
|
2022-06-05 18:44:51 +00:00
|
|
|
/// <summary>
|
|
|
|
/// Sets the root directory to a common value by creating a
|
|
|
|
/// IFileSystem (from Zio) of the root directory and registering it.
|
|
|
|
/// This will be used for both input and output.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="directory">
|
|
|
|
/// The path to the directory that represents "/" while
|
|
|
|
/// building.
|
|
|
|
/// </param>
|
|
|
|
/// <returns>The builder to chain calls.</returns>
|
|
|
|
public NitrideBuilder WithRootDirectory(DirectoryInfo directory)
|
|
|
|
{
|
|
|
|
this.RootDirectory = directory;
|
2022-07-09 04:52:10 +00:00
|
|
|
|
2022-06-05 18:44:51 +00:00
|
|
|
return this;
|
|
|
|
}
|
2021-09-07 05:15:45 +00:00
|
|
|
|
2022-06-05 18:44:51 +00:00
|
|
|
private void ConfigureContainer(ContainerBuilder builder)
|
|
|
|
{
|
|
|
|
// Hook up the rest of the modules.
|
|
|
|
builder.RegisterModule(this.nitrideModule);
|
2021-09-07 05:15:45 +00:00
|
|
|
|
2022-06-05 18:44:51 +00:00
|
|
|
// Set up our file system.
|
|
|
|
// TODO Wrong logger
|
|
|
|
this.RegisterRootDirectory(Log.Logger, builder);
|
2021-09-07 05:15:45 +00:00
|
|
|
|
2022-06-05 18:44:51 +00:00
|
|
|
// Finish up the registration by running our events.
|
2023-01-15 00:19:42 +00:00
|
|
|
foreach (Action<NitrideBuilder, ILifetimeScope>? callback in this
|
|
|
|
.configureSiteCallbacks)
|
2021-09-07 05:15:45 +00:00
|
|
|
{
|
2022-06-05 18:44:51 +00:00
|
|
|
builder.RegisterBuildCallback(scope => callback(this, scope));
|
2021-09-07 05:15:45 +00:00
|
|
|
}
|
|
|
|
|
2023-01-15 00:19:42 +00:00
|
|
|
foreach (Action<ContainerBuilder>? configureContainer in this
|
|
|
|
.configureContainerCallbacks)
|
2021-09-07 05:15:45 +00:00
|
|
|
{
|
2022-06-05 18:44:51 +00:00
|
|
|
configureContainer.Invoke(builder);
|
2021-09-07 05:15:45 +00:00
|
|
|
}
|
2022-06-05 18:44:51 +00:00
|
|
|
}
|
2021-09-07 05:15:45 +00:00
|
|
|
|
2022-07-09 04:52:10 +00:00
|
|
|
private void RegisterRootDirectory(
|
|
|
|
ILogger logger,
|
|
|
|
ContainerBuilder builder)
|
2022-06-05 18:44:51 +00:00
|
|
|
{
|
|
|
|
if (this.RootDirectory == null)
|
2021-09-07 05:15:45 +00:00
|
|
|
{
|
2022-06-05 18:44:51 +00:00
|
|
|
logger.Verbose("No root directory is registered");
|
2022-07-09 04:52:10 +00:00
|
|
|
|
2022-06-05 18:44:51 +00:00
|
|
|
return;
|
2021-09-07 05:15:45 +00:00
|
|
|
}
|
2022-06-05 18:44:51 +00:00
|
|
|
|
2023-01-15 00:19:42 +00:00
|
|
|
logger.Debug(
|
|
|
|
"Setting root directory to {Path}",
|
|
|
|
this.RootDirectory.FullName);
|
2022-06-05 18:44:51 +00:00
|
|
|
|
|
|
|
var rootFileSystem = new PhysicalFileSystem();
|
2023-01-15 00:19:42 +00:00
|
|
|
var subFileSystem = new SubFileSystem(
|
|
|
|
rootFileSystem,
|
|
|
|
this.RootDirectory.FullName);
|
2022-06-05 18:44:51 +00:00
|
|
|
|
2022-07-09 04:52:10 +00:00
|
|
|
builder.RegisterInstance(subFileSystem)
|
|
|
|
.As<IFileSystem>()
|
|
|
|
.SingleInstance();
|
2021-09-07 05:15:45 +00:00
|
|
|
}
|
|
|
|
}
|