Skip to content

Commit

Permalink
[1.x] Added automatic Vite versioning (#34)
Browse files Browse the repository at this point in the history
* added automatic vite versioning

* Minor changes

---------

Co-authored-by: kapi2289 <[email protected]>
  • Loading branch information
adrum and kapi2289 authored Feb 23, 2025
1 parent 3ab22e2 commit 1c6c064
Show file tree
Hide file tree
Showing 6 changed files with 91 additions and 11 deletions.
6 changes: 5 additions & 1 deletion InertiaCore/Extensions/Configure.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,11 @@ public static IApplicationBuilder UseInertia(this IApplicationBuilder app)
Inertia.UseFactory(factory);

var viteBuilder = app.ApplicationServices.GetService<IViteBuilder>();
if (viteBuilder != null) Vite.UseBuilder(viteBuilder);
if (viteBuilder != null)
{
Vite.UseBuilder(viteBuilder);
Inertia.Version(Vite.GetManifestHash);
}

app.Use(async (context, next) =>
{
Expand Down
14 changes: 14 additions & 0 deletions InertiaCore/Extensions/InertiaExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Extensions;
using Microsoft.AspNetCore.Mvc;
using System.Text;

namespace InertiaCore.Extensions;

Expand Down Expand Up @@ -49,4 +50,17 @@ internal static bool Override<TKey, TValue>(this IDictionary<TKey, TValue> dicti

return result?.GetValue(task);
}

internal static string MD5(this string s)
{
using var md5 = System.Security.Cryptography.MD5.Create();
var inputBytes = Encoding.UTF8.GetBytes(s);
var hashBytes = md5.ComputeHash(inputBytes);

var sb = new StringBuilder();
foreach (var t in hashBytes)
sb.Append(t.ToString("x2"));

return sb.ToString();
}
}
8 changes: 5 additions & 3 deletions InertiaCore/Inertia.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ public static class Inertia

public static Task<IHtmlContent> Html(dynamic model) => _factory.Html(model);

public static void Version(object? version) => _factory.Version(version);
public static void Version(string? version) => _factory.Version(version);

public static void Version(Func<string?> version) => _factory.Version(version);

public static string? GetVersion() => _factory.GetVersion();

Expand All @@ -29,9 +31,9 @@ public static class Inertia

public static void Share(IDictionary<string, object?> data) => _factory.Share(data);

public static AlwaysProp Always(object? value) => _factory.Always(value);
public static AlwaysProp Always(string value) => _factory.Always(value);

public static AlwaysProp Always(Func<object?> callback) => _factory.Always(callback);
public static AlwaysProp Always(Func<string> callback) => _factory.Always(callback);

public static AlwaysProp Always(Func<Task<object?>> callback) => _factory.Always(callback);

Expand Down
7 changes: 5 additions & 2 deletions InertiaCore/ResponseFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ internal interface IResponseFactory
public Response Render(string component, object? props = null);
public Task<IHtmlContent> Head(dynamic model);
public Task<IHtmlContent> Html(dynamic model);
public void Version(object? version);
public void Version(string? version);
public void Version(Func<string?> version);
public string? GetVersion();
public LocationResult Location(string url);
public void Share(string key, object? value);
Expand Down Expand Up @@ -95,7 +96,9 @@ public async Task<IHtmlContent> Html(dynamic model)
return new HtmlString($"<div id=\"app\" data-page=\"{encoded}\"></div>");
}

public void Version(object? version) => _version = version;
public void Version(string? version) => _version = version;

public void Version(Func<string?> version) => _version = version;

public string? GetVersion() => _version switch
{
Expand Down
17 changes: 15 additions & 2 deletions InertiaCore/Utils/Vite.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,15 @@
using System.IO.Abstractions;
using InertiaCore.Models;
using Microsoft.Extensions.Options;
using InertiaCore.Extensions;

namespace InertiaCore.Utils;

public interface IViteBuilder
{
HtmlString ReactRefresh();
HtmlString Input(string path);
string? GetManifest();
}

internal class ViteBuilder : IViteBuilder
Expand Down Expand Up @@ -65,12 +67,11 @@ public HtmlString Input(string path)
throw new Exception("Vite Manifest is invalid. Run `npm run build` and try again.");
}

if (!manifestJson.ContainsKey(path))
if (!manifestJson.TryGetValue(path, out var obj))
{
throw new Exception("Asset not found in manifest: " + path);
}

var obj = manifestJson[path];
var filePath = obj.GetProperty("file");

if (IsCssPath(filePath.ToString()))
Expand Down Expand Up @@ -205,6 +206,13 @@ private static string GetString(IHtmlContent content)
content.WriteTo(writer, HtmlEncoder.Default);
return writer.ToString();
}

public string? GetManifest()
{
return _fileSystem.File.Exists(GetPublicPathForFile(_options.Value.ManifestFilename))
? _fileSystem.File.ReadAllText(GetPublicPathForFile(_options.Value.ManifestFilename))
: null;
}
}

public static class Vite
Expand All @@ -222,4 +230,9 @@ public static class Vite
/// Generate React refresh runtime script.
/// </summary>
public static HtmlString ReactRefresh() => _instance.ReactRefresh();

/// <summary>
/// Generate the Manifest hash.
/// </summary>
public static string? GetManifestHash() => _instance.GetManifest()?.MD5();
}
50 changes: 47 additions & 3 deletions InertiaCoreTests/UnitTestVite.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
using InertiaCore.Models;
using InertiaCore.Utils;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using Moq;

Expand All @@ -14,8 +16,6 @@ public partial class Tests
[Description("Test if the Vite configuration registers properly the service.")]
public void TestViteConfiguration()
{
Assert.Throws<NullReferenceException>(() => Vite.ReactRefresh());

var builder = WebApplication.CreateBuilder();
builder.Services.AddInertia();

Expand Down Expand Up @@ -72,7 +72,8 @@ public void TestNotHot()
}

[Test]
[Description("Test if the Vite Helper handles generating HTML tags for both JS and CSS from HMR and the manifest properly.")]
[Description(
"Test if the Vite Helper handles generating HTML tags for both JS and CSS from HMR and the manifest properly.")]
public void TestViteInput()
{
var fileSystem = new MockFileSystem(new Dictionary<string, MockFileData>());
Expand Down Expand Up @@ -209,4 +210,47 @@ public void TestViteFacade()
"<script src=\"http://127.0.0.1:5174/@vite/client\" type=\"module\"></script>\n\t" +
"<script src=\"http://127.0.0.1:5174/index.scss\" type=\"module\"></script>\n\t"));
}

[Test]
[Description("Test if the vite version is read properly.")]
public async Task TestViteVersion()
{
var fileSystem = new MockFileSystem(new Dictionary<string, MockFileData>());
var options = new Mock<IOptions<ViteOptions>>();
options.SetupGet(x => x.Value).Returns(new ViteOptions());

var mock = new Mock<ViteBuilder>(options.Object);
mock.Object.UseFileSystem(fileSystem);
Vite.UseBuilder(mock.Object);

fileSystem.AddFile(@"/wwwroot/build/manifest.json",
new MockFileData("{\"app.tsx\": {\"file\": \"assets/main-19038c6a.js\"}}"));

_factory.Version(Vite.GetManifestHash);

var response = _factory.Render("Test/Page", new
{
Test = "Test"
});

var headers = new HeaderDictionary
{
{ "X-Inertia", "true" }
};

var context = PrepareContext(headers);

response.SetContext(context);
await response.ProcessResponse();

var result = response.GetResult();

Assert.Multiple(() =>
{
Assert.That(result, Is.InstanceOf<JsonResult>());

var json = (result as JsonResult)?.Value;
Assert.That((json as Page)?.Version, Is.EqualTo("bba1afd1066309f4a69430e0c446ba8d"));
});
}
}

0 comments on commit 1c6c064

Please sign in to comment.