diff --git a/.github/workflows/default.yml b/.github/workflows/default.yml index 203fd44..3d9c4de 100644 --- a/.github/workflows/default.yml +++ b/.github/workflows/default.yml @@ -21,6 +21,8 @@ jobs: steps: - name: checkout uses: actions/checkout@v4 + with: + submodules: true - name: setup dotnet uses: actions/setup-dotnet@v4 @@ -30,7 +32,7 @@ jobs: global-json-file: global.json - name: restore - run: dotnet restore --locked-mode + run: dotnet workload restore && dotnet restore --locked-mode - name: build run: dotnet build --no-restore @@ -45,6 +47,7 @@ jobs: with: fetch-depth: 0 fetch-tags: true + submodules: true - name: setup dotnet uses: actions/setup-dotnet@v4 @@ -54,16 +57,16 @@ jobs: global-json-file: global.json - name: restore - run: dotnet restore --locked-mode + run: dotnet workload restore && dotnet restore --locked-mode - name: pack - run: dotnet pack src/Launcher/CS2Launcher.AspNetCore.Launcher.csproj -c Release -o .package --no-restore + run: dotnet pack -c Release -o .packages --no-restore - name: upload artifact uses: actions/upload-artifact@v4 with: - name: cs2-launcher - path: .package + name: cs2-launcher-packages + path: .packages publish: needs: [pack] @@ -83,7 +86,7 @@ jobs: - name: download artifact uses: actions/download-artifact@v4 with: - name: cs2-launcher + name: cs2-launcher-packages - name: push run: dotnet nuget push "*.nupkg" --api-key ${{ secrets.NUGET_API_KEY }} --source https://api.nuget.org/v3/index.json --skip-duplicate diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..f944b1b --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "modules/CoreRcon"] + path = modules/CoreRcon + url = https://github.com/cryptoc1/corercon diff --git a/.vscode/launch.json b/.vscode/launch.json index 935e5f4..18c1b04 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -2,17 +2,17 @@ "version": "0.2.0", "configurations": [ { - "name": "Sample Debug", + "name": "Debug Sample (Core)", "type": "coreclr", "request": "launch", - "program": "${workspaceFolder}/sample/bin/Debug/net8.0/CS2Launcher.Sample.dll", + "program": "${workspaceFolder}/sample/Launcher/bin/Debug/net8.0/CS2Launcher.Sample.Launcher.dll", "args": [ "environment=Development" ], "env": { "DOTNET_ENVIRONMENT": "Development" }, - "cwd": "${workspaceFolder}/sample", + "cwd": "${workspaceFolder}/sample/Launcher", "justMyCode": true, "preLaunchTask": "${defaultBuildTask}", "requireExactSource": true, @@ -30,6 +30,47 @@ } }, "stopAtEntry": false, + }, + { + "name": "Debug Sample (Blazor)", + "type": "blazorwasm", + "request": "launch", + "browser": "chrome", + "cwd": "${workspaceFolder}/sample/Launcher", + "dotNetConfig": { + "justMyCode": true, + "logging": { + "engineLogging": false, + "moduleLoad": false, + "threadExit": false, + }, + "requireExactSource": true, + "sourceFileMap": { + "/Views": "${workspaceFolder}/src/Launcher/Views" + }, + "sourceLinkOptions": { + "https://raw.githubusercontent.com/*": { + "enabled": true + }, + "*": { + "enabled": false + } + }, + "stopAtEntry": false, + }, + "env": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "hosted": true, + "preLaunchTask": "${defaultBuildTask}", + "program": "${workspaceFolder}/sample/Launcher/bin/Debug/net8.0/CS2Launcher.Sample.Launcher.dll", + "serverReadyAction": { + "action": "debugWithChrome", + "killOnServerStop": true, + "pattern": "\\bNow listening on:\\s+(https?://\\S+)", + }, + "url": "https://localhost:52750", + "webRoot": "${workspaceFolder}/sample/Launcher", } ] } \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index 8f45949..7067f45 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -26,6 +26,7 @@ "**/.git": true, "**/.svn": true, "**/.hg": true, + "**/.vs": true, "**/CVS": true, "**/.DS_Store": true, "**/Thumbs.db": true, diff --git a/.vscode/tasks.json b/.vscode/tasks.json index b187c80..cf44e38 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -1,25 +1,25 @@ { - "version": "2.0.0", - "tasks": [ - { - "label": "build", - "command": "dotnet", - "type": "process", - "args": [ - "build", - "${workspaceFolder}/cs2-launcher.sln", - "/property:GenerateFullPaths=true", - "/consoleloggerparameters:NoSummary" - ], - "runOptions": { - "instanceLimit": 1 - }, - "problemMatcher": "$msCompile", - "isBuildCommand": true, - "group": { - "kind": "build", - "isDefault": true - } - } - ] + "version": "2.0.0", + "tasks": [ + { + "label": "build", + "command": "dotnet", + "type": "process", + "args": [ + "build", + "${workspaceFolder}/cs2-launcher.sln", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary" + ], + "runOptions": { + "instanceLimit": 1 + }, + "problemMatcher": "$msCompile", + "isBuildCommand": true, + "group": { + "kind": "build", + "isDefault": true + } + } + ] } \ No newline at end of file diff --git a/cs2-launcher.sln b/cs2-launcher.sln index 1001fcc..84f894a 100644 --- a/cs2-launcher.sln +++ b/cs2-launcher.sln @@ -4,10 +4,20 @@ Microsoft Visual Studio Solution File, Format Version 12.00 VisualStudioVersion = 17.0.31903.59 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{5222FED7-6FE1-46CA-AA88-EA10FA14075C}" + ProjectSection(SolutionItems) = preProject + src\Directory.Build.props = src\Directory.Build.props + src\Directory.Build.targets = src\Directory.Build.targets + EndProjectSection EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CS2Launcher.AspNetCore.Launcher", "src\Launcher\CS2Launcher.AspNetCore.Launcher.csproj", "{115173BC-C8AD-4266-8759-3CA0A14374C2}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CS2Launcher.Sample", "sample\CS2Launcher.Sample.csproj", "{2ECAA280-96DA-4212-9857-6E3BAA4E2217}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CS2Launcher.AspNetCore.App", "src\App\CS2Launcher.AspNetCore.App.csproj", "{42BE4AA8-0386-474D-BFE2-0F4E68476B42}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "sample", "sample", "{170E8297-96FC-4172-B45C-2FCBCEFB9F4D}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CS2Launcher.Sample.Launcher", "sample\Launcher\CS2Launcher.Sample.Launcher.csproj", "{A415B696-7249-4A76-8423-6AC7163C8347}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CS2Launcher.Sample.App", "sample\App\CS2Launcher.Sample.App.csproj", "{55CFF728-1CC8-45A8-A4A8-1FC690065E3E}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -19,16 +29,27 @@ Global {115173BC-C8AD-4266-8759-3CA0A14374C2}.Debug|Any CPU.Build.0 = Debug|Any CPU {115173BC-C8AD-4266-8759-3CA0A14374C2}.Release|Any CPU.ActiveCfg = Release|Any CPU {115173BC-C8AD-4266-8759-3CA0A14374C2}.Release|Any CPU.Build.0 = Release|Any CPU - {2ECAA280-96DA-4212-9857-6E3BAA4E2217}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {2ECAA280-96DA-4212-9857-6E3BAA4E2217}.Debug|Any CPU.Build.0 = Debug|Any CPU - {2ECAA280-96DA-4212-9857-6E3BAA4E2217}.Release|Any CPU.ActiveCfg = Release|Any CPU - {2ECAA280-96DA-4212-9857-6E3BAA4E2217}.Release|Any CPU.Build.0 = Release|Any CPU + {42BE4AA8-0386-474D-BFE2-0F4E68476B42}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {42BE4AA8-0386-474D-BFE2-0F4E68476B42}.Debug|Any CPU.Build.0 = Debug|Any CPU + {42BE4AA8-0386-474D-BFE2-0F4E68476B42}.Release|Any CPU.ActiveCfg = Release|Any CPU + {42BE4AA8-0386-474D-BFE2-0F4E68476B42}.Release|Any CPU.Build.0 = Release|Any CPU + {A415B696-7249-4A76-8423-6AC7163C8347}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A415B696-7249-4A76-8423-6AC7163C8347}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A415B696-7249-4A76-8423-6AC7163C8347}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A415B696-7249-4A76-8423-6AC7163C8347}.Release|Any CPU.Build.0 = Release|Any CPU + {55CFF728-1CC8-45A8-A4A8-1FC690065E3E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {55CFF728-1CC8-45A8-A4A8-1FC690065E3E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {55CFF728-1CC8-45A8-A4A8-1FC690065E3E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {55CFF728-1CC8-45A8-A4A8-1FC690065E3E}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(NestedProjects) = preSolution {115173BC-C8AD-4266-8759-3CA0A14374C2} = {5222FED7-6FE1-46CA-AA88-EA10FA14075C} + {42BE4AA8-0386-474D-BFE2-0F4E68476B42} = {5222FED7-6FE1-46CA-AA88-EA10FA14075C} + {A415B696-7249-4A76-8423-6AC7163C8347} = {170E8297-96FC-4172-B45C-2FCBCEFB9F4D} + {55CFF728-1CC8-45A8-A4A8-1FC690065E3E} = {170E8297-96FC-4172-B45C-2FCBCEFB9F4D} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {56EB9027-8ADE-4B88-BDE0-E9BC3DD1ACF4} diff --git a/modules/CoreRcon b/modules/CoreRcon new file mode 160000 index 0000000..d8bca60 --- /dev/null +++ b/modules/CoreRcon @@ -0,0 +1 @@ +Subproject commit d8bca605b1ccdc877ace215e0cb4f7a18d0f11d6 diff --git a/sample/App/AppRoot.cs b/sample/App/AppRoot.cs new file mode 100644 index 0000000..cad74d2 --- /dev/null +++ b/sample/App/AppRoot.cs @@ -0,0 +1,5 @@ +using CS2Launcher.AspNetCore.App; + +namespace CS2Launcher.Sample.App; + +public sealed class AppRoot : RootComponent; \ No newline at end of file diff --git a/sample/App/CS2Launcher.Sample.App.csproj b/sample/App/CS2Launcher.Sample.App.csproj new file mode 100644 index 0000000..f61c6d5 --- /dev/null +++ b/sample/App/CS2Launcher.Sample.App.csproj @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/sample/App/Program.cs b/sample/App/Program.cs new file mode 100644 index 0000000..3819553 --- /dev/null +++ b/sample/App/Program.cs @@ -0,0 +1,9 @@ +using CS2Launcher.AspNetCore.App.Hosting; +using CS2Launcher.Sample.App; +using Microsoft.AspNetCore.Components.WebAssembly.Hosting; + +var builder = WebAssemblyHostBuilder.CreateDefault( args ); +builder.UseCS2Launcher(); + +await using var app = builder.Build(); +await app.RunAsync(); \ No newline at end of file diff --git a/sample/App/packages.lock.json b/sample/App/packages.lock.json new file mode 100644 index 0000000..172d2e4 --- /dev/null +++ b/sample/App/packages.lock.json @@ -0,0 +1,399 @@ +{ + "version": 1, + "dependencies": { + "net8.0": { + "Microsoft.AspNetCore.Components.WebAssembly": { + "type": "Direct", + "requested": "[8.0.4, )", + "resolved": "8.0.4", + "contentHash": "4mi1GyihE1R9BocAc5ZUeYZN/G2cFfoGibb6H+yQ7xXk3ec7cvqkjamdnXH2EwsikS+hX44pgirtiwUHDUw1uw==", + "dependencies": { + "Microsoft.AspNetCore.Components.Web": "8.0.4", + "Microsoft.Extensions.Configuration.Binder": "8.0.1", + "Microsoft.Extensions.Configuration.Json": "8.0.0", + "Microsoft.Extensions.Logging": "8.0.0", + "Microsoft.JSInterop.WebAssembly": "8.0.4" + } + }, + "Microsoft.NET.ILLink.Tasks": { + "type": "Direct", + "requested": "[8.0.4, )", + "resolved": "8.0.4", + "contentHash": "PZb5nfQ+U19nhnmnR9T1jw+LTmozhuG2eeuzuW5A7DqxD/UXW2ucjmNJqnqOuh8rdPzM3MQXoF8AfFCedJdCUw==" + }, + "Microsoft.NET.Sdk.WebAssembly.Pack": { + "type": "Direct", + "requested": "[8.0.4, )", + "resolved": "8.0.4", + "contentHash": "D4kK4zXW43HvIX0lG9rBGGVzNtY6WwbCGAHJEi6iChU5Dgw8VenJS7Jc1g9Yy8pq4mEQA5PCcZicA16hGTjRpw==" + }, + "MessagePack": { + "type": "Transitive", + "resolved": "2.5.108", + "contentHash": "kcVRbdWP3xNWLZmmpm4DFO+kuXf6mUR2mHZ27WoZIEFIv9hazuUd80injXhNrZnlq/FklAdCsLOil5M76I4Ndg==", + "dependencies": { + "MessagePack.Annotations": "2.5.108", + "Microsoft.NET.StringTools": "17.4.0", + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + }, + "MessagePack.Annotations": { + "type": "Transitive", + "resolved": "2.5.108", + "contentHash": "28aNCvfJClgwaKr26gf2S6LT+C1PNyPxiG+ihYpy8uCJsRLJEDoCt2I0Uk5hqOPQ8P8hI0ESy520oMkZkPmsOQ==" + }, + "Microsoft.AspNetCore.Authorization": { + "type": "Transitive", + "resolved": "8.0.4", + "contentHash": "dzYUHvqyavBiYVd5BZNAgV5rT+DC4HyIWPnbeYgxQNBYOFomvvwzPfidQf1Ld/HhkXhEj3tlzqNb4gy2P2ukUg==", + "dependencies": { + "Microsoft.AspNetCore.Metadata": "8.0.4", + "Microsoft.Extensions.Logging.Abstractions": "8.0.1", + "Microsoft.Extensions.Options": "8.0.2" + } + }, + "Microsoft.AspNetCore.Components": { + "type": "Transitive", + "resolved": "8.0.4", + "contentHash": "ExTJT1u3QCTKaq2LjazkoHMNVlz0Q93A4ei5Zqd38bj3hggpShi4A/U22zk1LOmT0eUE5WklOBMpKZMg+T6Veg==", + "dependencies": { + "Microsoft.AspNetCore.Authorization": "8.0.4", + "Microsoft.AspNetCore.Components.Analyzers": "8.0.4" + } + }, + "Microsoft.AspNetCore.Components.Analyzers": { + "type": "Transitive", + "resolved": "8.0.4", + "contentHash": "kEvEOOkgN8uLjP2PMR481yxSjUsyGLaehHSD3HWjboNsXA5++7Hxn83LRdVri9/0rlY2zS/dP9oGHZpgxYu2iQ==" + }, + "Microsoft.AspNetCore.Components.Forms": { + "type": "Transitive", + "resolved": "8.0.4", + "contentHash": "I/kttR/nmRZTc+bsetYnvbkVzHgsJXrWKxHo30vGvQV+dTeur9LV2g2TvyLerpWL9OFbNWgpTGBUwgX1IW/0Zw==", + "dependencies": { + "Microsoft.AspNetCore.Components": "8.0.4" + } + }, + "Microsoft.AspNetCore.Components.Web": { + "type": "Transitive", + "resolved": "8.0.4", + "contentHash": "K9zcUkciMHmPjYdaB417xlG9Srv2udLT5j7CIAN92H5KNLH1ItIGIEIIUMJT3r+2Ma3ZLZO0eddEbR+Z59MbOQ==", + "dependencies": { + "Microsoft.AspNetCore.Components": "8.0.4", + "Microsoft.AspNetCore.Components.Forms": "8.0.4", + "Microsoft.Extensions.DependencyInjection": "8.0.0", + "Microsoft.Extensions.Primitives": "8.0.0", + "Microsoft.JSInterop": "8.0.4", + "System.IO.Pipelines": "8.0.0" + } + }, + "Microsoft.AspNetCore.Connections.Abstractions": { + "type": "Transitive", + "resolved": "8.0.4", + "contentHash": "pvO0JgjrNOas+WzmHxqawTv64lwTy1zbGm4WQY7OOd/OfKMw8LaoNEtn9jsAfiKUkt3lYK8kOL8Uy9XyyTCUwg==", + "dependencies": { + "Microsoft.Extensions.Features": "8.0.4", + "System.IO.Pipelines": "8.0.0" + } + }, + "Microsoft.AspNetCore.Http.Connections.Client": { + "type": "Transitive", + "resolved": "8.0.4", + "contentHash": "Tl9Hf+ftWZeKDGJpQOMwDgev7EXiiqk71NvoGDNhAYhYJMpoyf4591aINACAPSZ3zWNs4cqKIm8YQ5eG1slf5Q==", + "dependencies": { + "Microsoft.AspNetCore.Http.Connections.Common": "8.0.4", + "Microsoft.Extensions.Logging.Abstractions": "8.0.1", + "Microsoft.Extensions.Options": "8.0.2" + } + }, + "Microsoft.AspNetCore.Http.Connections.Common": { + "type": "Transitive", + "resolved": "8.0.4", + "contentHash": "SG02A6/ZET3sCW/PiJumg3q4yZdBZeMetdy/ebS4ZcmFPr+yI9sSmLAw9MHZVNNxxBWM5VuLg463YwlXoxhJHQ==", + "dependencies": { + "Microsoft.AspNetCore.Connections.Abstractions": "8.0.4" + } + }, + "Microsoft.AspNetCore.Metadata": { + "type": "Transitive", + "resolved": "8.0.4", + "contentHash": "TG3JhI7dkDCIoxZ3TL/5yptLYLg56w1f4jE8GSYnZXSso1xY5JKKCxObK+xKQJU5kZir30+QUGX1WpbC1kDcow==" + }, + "Microsoft.AspNetCore.SignalR.Client": { + "type": "Transitive", + "resolved": "8.0.4", + "contentHash": "HPM5/ifdz4PvK6W3t7CNHgV69MPPrS75tLD9HUYFRlwGmvbVPYbsgES2b7wmnvZEsaGlEBNOdw//xU1jK4FM0w==", + "dependencies": { + "Microsoft.AspNetCore.Http.Connections.Client": "8.0.4", + "Microsoft.AspNetCore.SignalR.Client.Core": "8.0.4" + } + }, + "Microsoft.AspNetCore.SignalR.Client.Core": { + "type": "Transitive", + "resolved": "8.0.4", + "contentHash": "w8eaEHS6Qn0VALv3G7EuLg/i5WInxt2Jps4IbvB0u61l9GaTAOGw0Xx1G+0UJgWwd2RZoaJXqMr748TuSpxm6g==", + "dependencies": { + "Microsoft.AspNetCore.SignalR.Common": "8.0.4", + "Microsoft.AspNetCore.SignalR.Protocols.Json": "8.0.4", + "Microsoft.Extensions.DependencyInjection": "8.0.0", + "Microsoft.Extensions.Logging": "8.0.0", + "System.Threading.Channels": "8.0.0" + } + }, + "Microsoft.AspNetCore.SignalR.Common": { + "type": "Transitive", + "resolved": "8.0.4", + "contentHash": "vsoXzcAibrem3/qWSpZ9Q/Wc/4UpFdXtsNTBMAmltnQPGR07qa7Pzgrc7K9pT/gEkFR5DkFKkEOzgCkNBDUE+g==", + "dependencies": { + "Microsoft.AspNetCore.Connections.Abstractions": "8.0.4", + "Microsoft.Extensions.Options": "8.0.2" + } + }, + "Microsoft.AspNetCore.SignalR.Protocols.Json": { + "type": "Transitive", + "resolved": "8.0.4", + "contentHash": "9X4TnAZTGMVzH7DghV7AWXX5r8UO7RpSJAPxfd9lTu3GChEyUpppKIJMaOKpseplnlRxOedve8UPdjx5ks06vA==", + "dependencies": { + "Microsoft.AspNetCore.SignalR.Common": "8.0.4" + } + }, + "Microsoft.AspNetCore.SignalR.Protocols.MessagePack": { + "type": "Transitive", + "resolved": "8.0.4", + "contentHash": "Zr+ur9AHHLuKWbp1b2Tw/evvY41xt2Dar5zEmtfYg0vO/ztU4CBLCDdXvB01o9Dtb0bHoQ+25xwF11ur08/l1g==", + "dependencies": { + "MessagePack": "2.5.108", + "Microsoft.AspNetCore.SignalR.Common": "8.0.4" + } + }, + "Microsoft.Extensions.Configuration": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "0J/9YNXTMWSZP2p2+nvl8p71zpSwokZXZuJW+VjdErkegAnFdO1XlqtA62SJtgVYHdKu3uPxJHcMR/r35HwFBA==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "8.0.0", + "Microsoft.Extensions.Primitives": "8.0.0" + } + }, + "Microsoft.Extensions.Configuration.Abstractions": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "3lE/iLSutpgX1CC0NOW70FJoGARRHbyKmG7dc0klnUZ9Dd9hS6N/POPWhKhMLCEuNN5nXEY5agmlFtH562vqhQ==", + "dependencies": { + "Microsoft.Extensions.Primitives": "8.0.0" + } + }, + "Microsoft.Extensions.Configuration.Binder": { + "type": "Transitive", + "resolved": "8.0.1", + "contentHash": "2UKFJnLiBt7Od6nCnTqP9rTIUNhzmn9Hv1l2FchyKbz8xieB9ULwZTbQZMw+M24Qw3F5dzzH1U9PPleN0LNLOQ==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "8.0.0" + } + }, + "Microsoft.Extensions.Configuration.FileExtensions": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "McP+Lz/EKwvtCv48z0YImw+L1gi1gy5rHhNaNIY2CrjloV+XY8gydT8DjMR6zWeL13AFK+DioVpppwAuO1Gi1w==", + "dependencies": { + "Microsoft.Extensions.Configuration": "8.0.0", + "Microsoft.Extensions.Configuration.Abstractions": "8.0.0", + "Microsoft.Extensions.FileProviders.Abstractions": "8.0.0", + "Microsoft.Extensions.FileProviders.Physical": "8.0.0", + "Microsoft.Extensions.Primitives": "8.0.0" + } + }, + "Microsoft.Extensions.Configuration.Json": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "C2wqUoh9OmRL1akaCcKSTmRU8z0kckfImG7zLNI8uyi47Lp+zd5LWAD17waPQEqCz3ioWOCrFUo+JJuoeZLOBw==", + "dependencies": { + "Microsoft.Extensions.Configuration": "8.0.0", + "Microsoft.Extensions.Configuration.Abstractions": "8.0.0", + "Microsoft.Extensions.Configuration.FileExtensions": "8.0.0", + "Microsoft.Extensions.FileProviders.Abstractions": "8.0.0", + "System.Text.Json": "8.0.0" + } + }, + "Microsoft.Extensions.DependencyInjection": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "V8S3bsm50ig6JSyrbcJJ8bW2b9QLGouz+G1miK3UTaOWmMtFwNNNzUf4AleyDWUmTrWMLNnFSLEQtxmxgNQnNQ==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0" + } + }, + "Microsoft.Extensions.DependencyInjection.Abstractions": { + "type": "Transitive", + "resolved": "8.0.1", + "contentHash": "fGLiCRLMYd00JYpClraLjJTNKLmMJPnqxMaiRzEBIIvevlzxz33mXy39Lkd48hu1G+N21S7QpaO5ZzKsI6FRuA==" + }, + "Microsoft.Extensions.Features": { + "type": "Transitive", + "resolved": "8.0.4", + "contentHash": "ym56/tUtFHFHucqiyQq42Ha6n1CT3CkrSZmbb3Szfkl/KNEaNqotKXFQMWHlFk2WMvU4fepqUsW8VK5WEjMChA==" + }, + "Microsoft.Extensions.FileProviders.Abstractions": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "ZbaMlhJlpisjuWbvXr4LdAst/1XxH3vZ6A0BsgTphZ2L4PGuxRLz7Jr/S7mkAAnOn78Vu0fKhEgNF5JO3zfjqQ==", + "dependencies": { + "Microsoft.Extensions.Primitives": "8.0.0" + } + }, + "Microsoft.Extensions.FileProviders.Physical": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "UboiXxpPUpwulHvIAVE36Knq0VSHaAmfrFkegLyBZeaADuKezJ/AIXYAW8F5GBlGk/VaibN2k/Zn1ca8YAfVdA==", + "dependencies": { + "Microsoft.Extensions.FileProviders.Abstractions": "8.0.0", + "Microsoft.Extensions.FileSystemGlobbing": "8.0.0", + "Microsoft.Extensions.Primitives": "8.0.0" + } + }, + "Microsoft.Extensions.FileSystemGlobbing": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "OK+670i7esqlQrPjdIKRbsyMCe9g5kSLpRRQGSr4Q58AOYEe/hCnfLZprh7viNisSUUQZmMrbbuDaIrP+V1ebQ==" + }, + "Microsoft.Extensions.Logging": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "tvRkov9tAJ3xP51LCv3FJ2zINmv1P8Hi8lhhtcKGqM+ImiTCC84uOPEI4z8Cdq2C3o9e+Aa0Gw0rmrsJD77W+w==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection": "8.0.0", + "Microsoft.Extensions.Logging.Abstractions": "8.0.0", + "Microsoft.Extensions.Options": "8.0.0" + } + }, + "Microsoft.Extensions.Logging.Abstractions": { + "type": "Transitive", + "resolved": "8.0.1", + "contentHash": "RIFgaqoaINxkM2KTOw72dmilDmTrYA0ns2KW4lDz4gZ2+o6IQ894CzmdL3StM2oh7QQq44nCWiqKqc4qUI9Jmg==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.1" + } + }, + "Microsoft.Extensions.Options": { + "type": "Transitive", + "resolved": "8.0.2", + "contentHash": "dWGKvhFybsaZpGmzkGCbNNwBD1rVlWzrZKANLW/CcbFJpCEceMCGzT7zZwHOGBCbwM0SzBuceMj5HN1LKV1QqA==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0", + "Microsoft.Extensions.Primitives": "8.0.0" + } + }, + "Microsoft.Extensions.Primitives": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "bXJEZrW9ny8vjMF1JV253WeLhpEVzFo1lyaZu1vQ4ZxWUlVvknZ/+ftFgVheLubb4eZPSwwxBeqS1JkCOjxd8g==" + }, + "Microsoft.JSInterop": { + "type": "Transitive", + "resolved": "8.0.4", + "contentHash": "97XhCIlz57G74fuf9XsuItyeO/8e6etWYAPH8XuDmmIW7461Gu9WN3louVqjkh4BU0q3Nf5acvSIfkIuGzHVWw==" + }, + "Microsoft.JSInterop.WebAssembly": { + "type": "Transitive", + "resolved": "8.0.4", + "contentHash": "mG6XiYUmdLdrvowICG/nmGolx6oDZGt8xbkkI+7QvJL1aWuR/TTWPb6I6/N1ngQHMWzKpeRx1gWkmGV+dhJ58A==", + "dependencies": { + "Microsoft.JSInterop": "8.0.4" + } + }, + "Microsoft.NET.StringTools": { + "type": "Transitive", + "resolved": "17.4.0", + "contentHash": "06T6Hqfs3JDIaBvJaBRFFMIdU7oE0OMab5Xl8LKQjWPxBQr3BgVFKMQPTC+GsSEuYREWmK6g5eOd7Xqd9p1YCA==", + "dependencies": { + "System.Memory": "4.5.5", + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + }, + "Nito.AsyncEx.Coordination": { + "type": "Transitive", + "resolved": "5.1.2", + "contentHash": "QMyUfsaxov//0ZMbOHWr9hJaBFteZd66DV1ay4J5wRODDb8+K/uHC7+3VsOflo6SVw/29mu8OWZp8vMDSuzc0w==", + "dependencies": { + "Nito.AsyncEx.Tasks": "5.1.2", + "Nito.Collections.Deque": "1.1.1" + } + }, + "Nito.AsyncEx.Tasks": { + "type": "Transitive", + "resolved": "5.1.2", + "contentHash": "jEkCfR2/M26OK/U4G7SEN063EU/F4LiVA06TtpZILMdX/quIHCg+wn31Zerl2LC+u1cyFancjTY3cNAr2/89PA==", + "dependencies": { + "Nito.Disposables": "2.2.1" + } + }, + "Nito.Collections.Deque": { + "type": "Transitive", + "resolved": "1.1.1", + "contentHash": "CU0/Iuv5VDynK8I8pDLwkgF0rZhbQoZahtodfL0M3x2gFkpBRApKs8RyMyNlAi1mwExE4gsmqQXk4aFVvW9a4Q==" + }, + "Nito.Disposables": { + "type": "Transitive", + "resolved": "2.2.1", + "contentHash": "6sZ5uynQeAE9dPWBQGKebNmxbY4xsvcc5VplB5WkYEESUS7oy4AwnFp0FhqxTSKm/PaFrFqLrYr696CYN8cugg==", + "dependencies": { + "System.Collections.Immutable": "1.7.1" + } + }, + "System.Collections.Immutable": { + "type": "Transitive", + "resolved": "1.7.1", + "contentHash": "B43Zsz5EfMwyEbnObwRxW5u85fzJma3lrDeGcSAV1qkhSRTNY5uXAByTn9h9ddNdhM+4/YoLc/CI43umjwIl9Q==" + }, + "System.IO.Pipelines": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "FHNOatmUq0sqJOkTx+UF/9YK1f180cnW5FVqnQMvYUN0elp6wFzbtPSiqbo1/ru8ICp43JM1i7kKkk6GsNGHlA==" + }, + "System.Memory": { + "type": "Transitive", + "resolved": "4.5.5", + "contentHash": "XIWiDvKPXaTveaB7HVganDlOCRoj03l+jrwNvcge/t8vhGYKvqV+dMv6G4SAX2NoNmN0wZfVPTAlFwZcZvVOUw==" + }, + "System.Runtime.CompilerServices.Unsafe": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg==" + }, + "System.Text.Encodings.Web": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "yev/k9GHAEGx2Rg3/tU6MQh4HGBXJs70y7j1LaM1i/ER9po+6nnQ6RRqTJn1E7Xu0fbIFK80Nh5EoODxrbxwBQ==" + }, + "System.Text.Json": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "OdrZO2WjkiEG6ajEFRABTRCi/wuXQPxeV6g8xvUJqdxMvvuCCEk86zPla8UiIQJz3durtUEbNyY/3lIhS0yZvQ==", + "dependencies": { + "System.Text.Encodings.Web": "8.0.0" + } + }, + "System.Threading.Channels": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "CMaFr7v+57RW7uZfZkPExsPB6ljwzhjACWW1gfU35Y56rk72B/Wu+sTqxVmGSk4SFUlPc3cjeKND0zktziyjBA==" + }, + "cs2launcher.aspnetcore.app": { + "type": "Project", + "dependencies": { + "Microsoft.AspNetCore.Components.WebAssembly": "[8.0.4, )", + "Microsoft.AspNetCore.SignalR.Client": "[8.0.4, )", + "Microsoft.AspNetCore.SignalR.Protocols.MessagePack": "[8.0.4, )", + "Nito.AsyncEx.Coordination": "[5.1.2, )" + } + } + }, + "net8.0/browser-wasm": { + "System.Text.Encodings.Web": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "yev/k9GHAEGx2Rg3/tU6MQh4HGBXJs70y7j1LaM1i/ER9po+6nnQ6RRqTJn1E7Xu0fbIFK80Nh5EoODxrbxwBQ==" + } + } + } +} \ No newline at end of file diff --git a/sample/CS2Launcher.Sample.csproj b/sample/CS2Launcher.Sample.csproj deleted file mode 100644 index 3efc8b7..0000000 --- a/sample/CS2Launcher.Sample.csproj +++ /dev/null @@ -1,23 +0,0 @@ - - - - true - enable - true - latest - enable - Speed - true - true - linux-x64;win-x64 - true - net8.0 - partial - CS2LAUNCHER-SAMPLE-17947b4b-b2a8-4c6d-a8ae-8eea3c24f3c0 - - - - - - - \ No newline at end of file diff --git a/sample/Directory.Build.props b/sample/Directory.Build.props new file mode 100644 index 0000000..cc07614 --- /dev/null +++ b/sample/Directory.Build.props @@ -0,0 +1,14 @@ + + + + true + $(DefaultItemExcludesInProjectFolder);packages.lock.json;package.json;package-lock.json + enable + false + latest + enable + true + net8.0 + + + \ No newline at end of file diff --git a/sample/Launcher/CS2Launcher.Sample.Launcher.csproj b/sample/Launcher/CS2Launcher.Sample.Launcher.csproj new file mode 100644 index 0000000..aa6f09b --- /dev/null +++ b/sample/Launcher/CS2Launcher.Sample.Launcher.csproj @@ -0,0 +1,16 @@ + + + + true + Speed + linux-x64;win-x64 + partial + CS2LAUNCHER-SAMPLE-17947b4b-b2a8-4c6d-a8ae-8eea3c24f3c0 + + + + + + + + \ No newline at end of file diff --git a/sample/Launcher/Program.cs b/sample/Launcher/Program.cs new file mode 100644 index 0000000..380ef83 --- /dev/null +++ b/sample/Launcher/Program.cs @@ -0,0 +1,11 @@ +using CS2Launcher.AspNetCore.Launcher; +using CS2Launcher.AspNetCore.Launcher.Proc; +using CS2Launcher.Sample.App; + +var builder = CS2LauncherApplication.CreateBuilder( args ) + .WithLauncherApp(); + +builder.Services.Configure( options => options.Enabled = false ); + +await using var app = builder.Build(); +await app.RunAsync(); \ No newline at end of file diff --git a/sample/Properties/launchSettings.json b/sample/Launcher/Properties/launchSettings.json similarity index 100% rename from sample/Properties/launchSettings.json rename to sample/Launcher/Properties/launchSettings.json diff --git a/sample/appsettings.Development.json b/sample/Launcher/appsettings.Development.json similarity index 100% rename from sample/appsettings.Development.json rename to sample/Launcher/appsettings.Development.json diff --git a/sample/appsettings.json b/sample/Launcher/appsettings.json similarity index 100% rename from sample/appsettings.json rename to sample/Launcher/appsettings.json diff --git a/sample/Launcher/packages.lock.json b/sample/Launcher/packages.lock.json new file mode 100644 index 0000000..d3b2b18 --- /dev/null +++ b/sample/Launcher/packages.lock.json @@ -0,0 +1,509 @@ +{ + "version": 1, + "dependencies": { + "net8.0": { + "AngleSharp": { + "type": "Transitive", + "resolved": "1.0.6", + "contentHash": "OIU4pbC6KjSzYdQZOjV4nme1RgGfCd3TdZgx1/blDUpgagYc9Es1NcyLHNp6tTyHJBp1aU4cvxr9c679bWX0Rw==", + "dependencies": { + "System.Text.Encoding.CodePages": "7.0.0" + } + }, + "AspNet.Security.OpenId": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "QeBs3rnIPyc1DYl2b4Ukb078/n0QKBpPTVKdFOMEbC/2iMYwPDtflhlPe4ikwX6kV/Dhbj2rqArFA0SqeyzceA==", + "dependencies": { + "AngleSharp": "1.0.6", + "Microsoft.IdentityModel.Protocols": "7.0.3" + } + }, + "AspNet.Security.OpenId.Steam": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "7uJhN/asrC4h6EairBZiIyFL2wJtVe2FCmoKdWOebZISh+bhq+fkwMnWupL3iLONXuLRnGxk1m0kGwMmvsTV0g==", + "dependencies": { + "AspNet.Security.OpenId": "8.0.0" + } + }, + "MessagePack": { + "type": "Transitive", + "resolved": "2.5.108", + "contentHash": "kcVRbdWP3xNWLZmmpm4DFO+kuXf6mUR2mHZ27WoZIEFIv9hazuUd80injXhNrZnlq/FklAdCsLOil5M76I4Ndg==", + "dependencies": { + "MessagePack.Annotations": "2.5.108", + "Microsoft.NET.StringTools": "17.4.0", + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + }, + "MessagePack.Annotations": { + "type": "Transitive", + "resolved": "2.5.108", + "contentHash": "28aNCvfJClgwaKr26gf2S6LT+C1PNyPxiG+ihYpy8uCJsRLJEDoCt2I0Uk5hqOPQ8P8hI0ESy520oMkZkPmsOQ==" + }, + "Microsoft.AspNetCore.Authorization": { + "type": "Transitive", + "resolved": "8.0.4", + "contentHash": "dzYUHvqyavBiYVd5BZNAgV5rT+DC4HyIWPnbeYgxQNBYOFomvvwzPfidQf1Ld/HhkXhEj3tlzqNb4gy2P2ukUg==", + "dependencies": { + "Microsoft.AspNetCore.Metadata": "8.0.4", + "Microsoft.Extensions.Logging.Abstractions": "8.0.1", + "Microsoft.Extensions.Options": "8.0.2" + } + }, + "Microsoft.AspNetCore.Components": { + "type": "Transitive", + "resolved": "8.0.4", + "contentHash": "ExTJT1u3QCTKaq2LjazkoHMNVlz0Q93A4ei5Zqd38bj3hggpShi4A/U22zk1LOmT0eUE5WklOBMpKZMg+T6Veg==", + "dependencies": { + "Microsoft.AspNetCore.Authorization": "8.0.4", + "Microsoft.AspNetCore.Components.Analyzers": "8.0.4" + } + }, + "Microsoft.AspNetCore.Components.Analyzers": { + "type": "Transitive", + "resolved": "8.0.4", + "contentHash": "kEvEOOkgN8uLjP2PMR481yxSjUsyGLaehHSD3HWjboNsXA5++7Hxn83LRdVri9/0rlY2zS/dP9oGHZpgxYu2iQ==" + }, + "Microsoft.AspNetCore.Components.Forms": { + "type": "Transitive", + "resolved": "8.0.4", + "contentHash": "I/kttR/nmRZTc+bsetYnvbkVzHgsJXrWKxHo30vGvQV+dTeur9LV2g2TvyLerpWL9OFbNWgpTGBUwgX1IW/0Zw==", + "dependencies": { + "Microsoft.AspNetCore.Components": "8.0.4" + } + }, + "Microsoft.AspNetCore.Components.Web": { + "type": "Transitive", + "resolved": "8.0.4", + "contentHash": "K9zcUkciMHmPjYdaB417xlG9Srv2udLT5j7CIAN92H5KNLH1ItIGIEIIUMJT3r+2Ma3ZLZO0eddEbR+Z59MbOQ==", + "dependencies": { + "Microsoft.AspNetCore.Components": "8.0.4", + "Microsoft.AspNetCore.Components.Forms": "8.0.4", + "Microsoft.Extensions.DependencyInjection": "8.0.0", + "Microsoft.Extensions.Primitives": "8.0.0", + "Microsoft.JSInterop": "8.0.4", + "System.IO.Pipelines": "8.0.0" + } + }, + "Microsoft.AspNetCore.Components.WebAssembly": { + "type": "Transitive", + "resolved": "8.0.4", + "contentHash": "4mi1GyihE1R9BocAc5ZUeYZN/G2cFfoGibb6H+yQ7xXk3ec7cvqkjamdnXH2EwsikS+hX44pgirtiwUHDUw1uw==", + "dependencies": { + "Microsoft.AspNetCore.Components.Web": "8.0.4", + "Microsoft.Extensions.Configuration.Binder": "8.0.1", + "Microsoft.Extensions.Configuration.Json": "8.0.0", + "Microsoft.Extensions.Logging": "8.0.0", + "Microsoft.JSInterop.WebAssembly": "8.0.4" + } + }, + "Microsoft.AspNetCore.Components.WebAssembly.Server": { + "type": "Transitive", + "resolved": "8.0.4", + "contentHash": "oUax9BrdzlLdmRt1R39F/0PIUahHDI9AvysMmwqAZT7vgx+elAYLYdSXb/SA8DA+S14blLVkcTkY4ALtFqzGnw==" + }, + "Microsoft.AspNetCore.Connections.Abstractions": { + "type": "Transitive", + "resolved": "8.0.4", + "contentHash": "pvO0JgjrNOas+WzmHxqawTv64lwTy1zbGm4WQY7OOd/OfKMw8LaoNEtn9jsAfiKUkt3lYK8kOL8Uy9XyyTCUwg==", + "dependencies": { + "Microsoft.Extensions.Features": "8.0.4", + "System.IO.Pipelines": "8.0.0" + } + }, + "Microsoft.AspNetCore.Http.Connections.Client": { + "type": "Transitive", + "resolved": "8.0.4", + "contentHash": "Tl9Hf+ftWZeKDGJpQOMwDgev7EXiiqk71NvoGDNhAYhYJMpoyf4591aINACAPSZ3zWNs4cqKIm8YQ5eG1slf5Q==", + "dependencies": { + "Microsoft.AspNetCore.Http.Connections.Common": "8.0.4", + "Microsoft.Extensions.Logging.Abstractions": "8.0.1", + "Microsoft.Extensions.Options": "8.0.2" + } + }, + "Microsoft.AspNetCore.Http.Connections.Common": { + "type": "Transitive", + "resolved": "8.0.4", + "contentHash": "SG02A6/ZET3sCW/PiJumg3q4yZdBZeMetdy/ebS4ZcmFPr+yI9sSmLAw9MHZVNNxxBWM5VuLg463YwlXoxhJHQ==", + "dependencies": { + "Microsoft.AspNetCore.Connections.Abstractions": "8.0.4" + } + }, + "Microsoft.AspNetCore.Metadata": { + "type": "Transitive", + "resolved": "8.0.4", + "contentHash": "TG3JhI7dkDCIoxZ3TL/5yptLYLg56w1f4jE8GSYnZXSso1xY5JKKCxObK+xKQJU5kZir30+QUGX1WpbC1kDcow==" + }, + "Microsoft.AspNetCore.SignalR.Client": { + "type": "Transitive", + "resolved": "8.0.4", + "contentHash": "HPM5/ifdz4PvK6W3t7CNHgV69MPPrS75tLD9HUYFRlwGmvbVPYbsgES2b7wmnvZEsaGlEBNOdw//xU1jK4FM0w==", + "dependencies": { + "Microsoft.AspNetCore.Http.Connections.Client": "8.0.4", + "Microsoft.AspNetCore.SignalR.Client.Core": "8.0.4" + } + }, + "Microsoft.AspNetCore.SignalR.Client.Core": { + "type": "Transitive", + "resolved": "8.0.4", + "contentHash": "w8eaEHS6Qn0VALv3G7EuLg/i5WInxt2Jps4IbvB0u61l9GaTAOGw0Xx1G+0UJgWwd2RZoaJXqMr748TuSpxm6g==", + "dependencies": { + "Microsoft.AspNetCore.SignalR.Common": "8.0.4", + "Microsoft.AspNetCore.SignalR.Protocols.Json": "8.0.4", + "Microsoft.Extensions.DependencyInjection": "8.0.0", + "Microsoft.Extensions.Logging": "8.0.0", + "System.Threading.Channels": "8.0.0" + } + }, + "Microsoft.AspNetCore.SignalR.Common": { + "type": "Transitive", + "resolved": "8.0.4", + "contentHash": "vsoXzcAibrem3/qWSpZ9Q/Wc/4UpFdXtsNTBMAmltnQPGR07qa7Pzgrc7K9pT/gEkFR5DkFKkEOzgCkNBDUE+g==", + "dependencies": { + "Microsoft.AspNetCore.Connections.Abstractions": "8.0.4", + "Microsoft.Extensions.Options": "8.0.2" + } + }, + "Microsoft.AspNetCore.SignalR.Protocols.Json": { + "type": "Transitive", + "resolved": "8.0.4", + "contentHash": "9X4TnAZTGMVzH7DghV7AWXX5r8UO7RpSJAPxfd9lTu3GChEyUpppKIJMaOKpseplnlRxOedve8UPdjx5ks06vA==", + "dependencies": { + "Microsoft.AspNetCore.SignalR.Common": "8.0.4" + } + }, + "Microsoft.AspNetCore.SignalR.Protocols.MessagePack": { + "type": "Transitive", + "resolved": "8.0.4", + "contentHash": "Zr+ur9AHHLuKWbp1b2Tw/evvY41xt2Dar5zEmtfYg0vO/ztU4CBLCDdXvB01o9Dtb0bHoQ+25xwF11ur08/l1g==", + "dependencies": { + "MessagePack": "2.5.108", + "Microsoft.AspNetCore.SignalR.Common": "8.0.4" + } + }, + "Microsoft.Extensions.Configuration": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "0J/9YNXTMWSZP2p2+nvl8p71zpSwokZXZuJW+VjdErkegAnFdO1XlqtA62SJtgVYHdKu3uPxJHcMR/r35HwFBA==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "8.0.0", + "Microsoft.Extensions.Primitives": "8.0.0" + } + }, + "Microsoft.Extensions.Configuration.Abstractions": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "3lE/iLSutpgX1CC0NOW70FJoGARRHbyKmG7dc0klnUZ9Dd9hS6N/POPWhKhMLCEuNN5nXEY5agmlFtH562vqhQ==", + "dependencies": { + "Microsoft.Extensions.Primitives": "8.0.0" + } + }, + "Microsoft.Extensions.Configuration.Binder": { + "type": "Transitive", + "resolved": "8.0.1", + "contentHash": "2UKFJnLiBt7Od6nCnTqP9rTIUNhzmn9Hv1l2FchyKbz8xieB9ULwZTbQZMw+M24Qw3F5dzzH1U9PPleN0LNLOQ==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "8.0.0" + } + }, + "Microsoft.Extensions.Configuration.FileExtensions": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "McP+Lz/EKwvtCv48z0YImw+L1gi1gy5rHhNaNIY2CrjloV+XY8gydT8DjMR6zWeL13AFK+DioVpppwAuO1Gi1w==", + "dependencies": { + "Microsoft.Extensions.Configuration": "8.0.0", + "Microsoft.Extensions.Configuration.Abstractions": "8.0.0", + "Microsoft.Extensions.FileProviders.Abstractions": "8.0.0", + "Microsoft.Extensions.FileProviders.Physical": "8.0.0", + "Microsoft.Extensions.Primitives": "8.0.0" + } + }, + "Microsoft.Extensions.Configuration.Json": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "C2wqUoh9OmRL1akaCcKSTmRU8z0kckfImG7zLNI8uyi47Lp+zd5LWAD17waPQEqCz3ioWOCrFUo+JJuoeZLOBw==", + "dependencies": { + "Microsoft.Extensions.Configuration": "8.0.0", + "Microsoft.Extensions.Configuration.Abstractions": "8.0.0", + "Microsoft.Extensions.Configuration.FileExtensions": "8.0.0", + "Microsoft.Extensions.FileProviders.Abstractions": "8.0.0", + "System.Text.Json": "8.0.0" + } + }, + "Microsoft.Extensions.DependencyInjection": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "V8S3bsm50ig6JSyrbcJJ8bW2b9QLGouz+G1miK3UTaOWmMtFwNNNzUf4AleyDWUmTrWMLNnFSLEQtxmxgNQnNQ==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0" + } + }, + "Microsoft.Extensions.DependencyInjection.Abstractions": { + "type": "Transitive", + "resolved": "8.0.1", + "contentHash": "fGLiCRLMYd00JYpClraLjJTNKLmMJPnqxMaiRzEBIIvevlzxz33mXy39Lkd48hu1G+N21S7QpaO5ZzKsI6FRuA==" + }, + "Microsoft.Extensions.Features": { + "type": "Transitive", + "resolved": "8.0.4", + "contentHash": "ym56/tUtFHFHucqiyQq42Ha6n1CT3CkrSZmbb3Szfkl/KNEaNqotKXFQMWHlFk2WMvU4fepqUsW8VK5WEjMChA==" + }, + "Microsoft.Extensions.FileProviders.Abstractions": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "ZbaMlhJlpisjuWbvXr4LdAst/1XxH3vZ6A0BsgTphZ2L4PGuxRLz7Jr/S7mkAAnOn78Vu0fKhEgNF5JO3zfjqQ==", + "dependencies": { + "Microsoft.Extensions.Primitives": "8.0.0" + } + }, + "Microsoft.Extensions.FileProviders.Physical": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "UboiXxpPUpwulHvIAVE36Knq0VSHaAmfrFkegLyBZeaADuKezJ/AIXYAW8F5GBlGk/VaibN2k/Zn1ca8YAfVdA==", + "dependencies": { + "Microsoft.Extensions.FileProviders.Abstractions": "8.0.0", + "Microsoft.Extensions.FileSystemGlobbing": "8.0.0", + "Microsoft.Extensions.Primitives": "8.0.0" + } + }, + "Microsoft.Extensions.FileSystemGlobbing": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "OK+670i7esqlQrPjdIKRbsyMCe9g5kSLpRRQGSr4Q58AOYEe/hCnfLZprh7viNisSUUQZmMrbbuDaIrP+V1ebQ==" + }, + "Microsoft.Extensions.Logging": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "tvRkov9tAJ3xP51LCv3FJ2zINmv1P8Hi8lhhtcKGqM+ImiTCC84uOPEI4z8Cdq2C3o9e+Aa0Gw0rmrsJD77W+w==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection": "8.0.0", + "Microsoft.Extensions.Logging.Abstractions": "8.0.0", + "Microsoft.Extensions.Options": "8.0.0" + } + }, + "Microsoft.Extensions.Logging.Abstractions": { + "type": "Transitive", + "resolved": "8.0.1", + "contentHash": "RIFgaqoaINxkM2KTOw72dmilDmTrYA0ns2KW4lDz4gZ2+o6IQ894CzmdL3StM2oh7QQq44nCWiqKqc4qUI9Jmg==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.1" + } + }, + "Microsoft.Extensions.Options": { + "type": "Transitive", + "resolved": "8.0.2", + "contentHash": "dWGKvhFybsaZpGmzkGCbNNwBD1rVlWzrZKANLW/CcbFJpCEceMCGzT7zZwHOGBCbwM0SzBuceMj5HN1LKV1QqA==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0", + "Microsoft.Extensions.Primitives": "8.0.0" + } + }, + "Microsoft.Extensions.Primitives": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "bXJEZrW9ny8vjMF1JV253WeLhpEVzFo1lyaZu1vQ4ZxWUlVvknZ/+ftFgVheLubb4eZPSwwxBeqS1JkCOjxd8g==" + }, + "Microsoft.IdentityModel.Abstractions": { + "type": "Transitive", + "resolved": "7.0.3", + "contentHash": "cfPUWdjigLIRIJSKz3uaZxShgf86RVDXHC1VEEchj1gnY25akwPYpbrfSoIGDCqA9UmOMdlctq411+2pAViFow==" + }, + "Microsoft.IdentityModel.Logging": { + "type": "Transitive", + "resolved": "7.0.3", + "contentHash": "b6GbGO+2LOTBEccHhqoJsOsmemG4A/MY+8H0wK/ewRhiG+DCYwEnucog1cSArPIY55zcn+XdZl0YEiUHkpDISQ==", + "dependencies": { + "Microsoft.IdentityModel.Abstractions": "7.0.3" + } + }, + "Microsoft.IdentityModel.Protocols": { + "type": "Transitive", + "resolved": "7.0.3", + "contentHash": "BtwR+tctBYhPNygyZmt1Rnw74GFrJteW+1zcdIgyvBCjkek6cNwPPqRfdhzCv61i+lwyNomRi8+iI4QKd4YCKA==", + "dependencies": { + "Microsoft.IdentityModel.Logging": "7.0.3", + "Microsoft.IdentityModel.Tokens": "7.0.3" + } + }, + "Microsoft.IdentityModel.Tokens": { + "type": "Transitive", + "resolved": "7.0.3", + "contentHash": "wB+LlbDjhnJ98DULjmFepqf9eEMh/sDs6S6hFh68iNRHmwollwhxk+nbSSfpA5+j+FbRyNskoaY4JsY1iCOKCg==", + "dependencies": { + "Microsoft.IdentityModel.Logging": "7.0.3" + } + }, + "Microsoft.JSInterop": { + "type": "Transitive", + "resolved": "8.0.4", + "contentHash": "97XhCIlz57G74fuf9XsuItyeO/8e6etWYAPH8XuDmmIW7461Gu9WN3louVqjkh4BU0q3Nf5acvSIfkIuGzHVWw==" + }, + "Microsoft.JSInterop.WebAssembly": { + "type": "Transitive", + "resolved": "8.0.4", + "contentHash": "mG6XiYUmdLdrvowICG/nmGolx6oDZGt8xbkkI+7QvJL1aWuR/TTWPb6I6/N1ngQHMWzKpeRx1gWkmGV+dhJ58A==", + "dependencies": { + "Microsoft.JSInterop": "8.0.4" + } + }, + "Microsoft.NET.StringTools": { + "type": "Transitive", + "resolved": "17.4.0", + "contentHash": "06T6Hqfs3JDIaBvJaBRFFMIdU7oE0OMab5Xl8LKQjWPxBQr3BgVFKMQPTC+GsSEuYREWmK6g5eOd7Xqd9p1YCA==", + "dependencies": { + "System.Memory": "4.5.5", + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + }, + "Nito.AsyncEx.Coordination": { + "type": "Transitive", + "resolved": "5.1.2", + "contentHash": "QMyUfsaxov//0ZMbOHWr9hJaBFteZd66DV1ay4J5wRODDb8+K/uHC7+3VsOflo6SVw/29mu8OWZp8vMDSuzc0w==", + "dependencies": { + "Nito.AsyncEx.Tasks": "5.1.2", + "Nito.Collections.Deque": "1.1.1" + } + }, + "Nito.AsyncEx.Tasks": { + "type": "Transitive", + "resolved": "5.1.2", + "contentHash": "jEkCfR2/M26OK/U4G7SEN063EU/F4LiVA06TtpZILMdX/quIHCg+wn31Zerl2LC+u1cyFancjTY3cNAr2/89PA==", + "dependencies": { + "Nito.Disposables": "2.2.1" + } + }, + "Nito.Collections.Deque": { + "type": "Transitive", + "resolved": "1.1.1", + "contentHash": "CU0/Iuv5VDynK8I8pDLwkgF0rZhbQoZahtodfL0M3x2gFkpBRApKs8RyMyNlAi1mwExE4gsmqQXk4aFVvW9a4Q==" + }, + "Nito.Disposables": { + "type": "Transitive", + "resolved": "2.2.1", + "contentHash": "6sZ5uynQeAE9dPWBQGKebNmxbY4xsvcc5VplB5WkYEESUS7oy4AwnFp0FhqxTSKm/PaFrFqLrYr696CYN8cugg==", + "dependencies": { + "System.Collections.Immutable": "1.7.1" + } + }, + "System.Collections.Immutable": { + "type": "Transitive", + "resolved": "1.7.1", + "contentHash": "B43Zsz5EfMwyEbnObwRxW5u85fzJma3lrDeGcSAV1qkhSRTNY5uXAByTn9h9ddNdhM+4/YoLc/CI43umjwIl9Q==" + }, + "System.Diagnostics.DiagnosticSource": { + "type": "Transitive", + "resolved": "8.0.1", + "contentHash": "vaoWjvkG1aenR2XdjaVivlCV9fADfgyhW5bZtXT23qaEea0lWiUljdQuze4E31vKM7ZWJaSUsbYIKE3rnzfZUg==" + }, + "System.IO.Pipelines": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "FHNOatmUq0sqJOkTx+UF/9YK1f180cnW5FVqnQMvYUN0elp6wFzbtPSiqbo1/ru8ICp43JM1i7kKkk6GsNGHlA==" + }, + "System.Memory": { + "type": "Transitive", + "resolved": "4.5.5", + "contentHash": "XIWiDvKPXaTveaB7HVganDlOCRoj03l+jrwNvcge/t8vhGYKvqV+dMv6G4SAX2NoNmN0wZfVPTAlFwZcZvVOUw==" + }, + "System.Runtime.CompilerServices.Unsafe": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg==" + }, + "System.Text.Encoding.CodePages": { + "type": "Transitive", + "resolved": "7.0.0", + "contentHash": "LSyCblMpvOe0N3E+8e0skHcrIhgV2huaNcjUUEa8hRtgEAm36aGkRoC8Jxlb6Ra6GSfF29ftduPNywin8XolzQ==" + }, + "System.Text.Encodings.Web": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "yev/k9GHAEGx2Rg3/tU6MQh4HGBXJs70y7j1LaM1i/ER9po+6nnQ6RRqTJn1E7Xu0fbIFK80Nh5EoODxrbxwBQ==" + }, + "System.Text.Json": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "OdrZO2WjkiEG6ajEFRABTRCi/wuXQPxeV6g8xvUJqdxMvvuCCEk86zPla8UiIQJz3durtUEbNyY/3lIhS0yZvQ==", + "dependencies": { + "System.Text.Encodings.Web": "8.0.0" + } + }, + "System.Threading.Channels": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "CMaFr7v+57RW7uZfZkPExsPB6ljwzhjACWW1gfU35Y56rk72B/Wu+sTqxVmGSk4SFUlPc3cjeKND0zktziyjBA==" + }, + "corercon": { + "type": "Project", + "dependencies": { + "CoreRCON.Parsers": "[1.0.0, )", + "System.Diagnostics.DiagnosticSource": "[8.0.1, )", + "System.IO.Pipelines": "[8.0.0, )" + } + }, + "corercon.extensions.counterstrike": { + "type": "Project", + "dependencies": { + "CoreRCON": "[6.0.0, )" + } + }, + "corercon.parsers": { + "type": "Project", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "[6.0.0, )" + } + }, + "cs2launcher.aspnetcore.app": { + "type": "Project", + "dependencies": { + "Microsoft.AspNetCore.Components.WebAssembly": "[8.0.4, )", + "Microsoft.AspNetCore.SignalR.Client": "[8.0.4, )", + "Microsoft.AspNetCore.SignalR.Protocols.MessagePack": "[8.0.4, )", + "Nito.AsyncEx.Coordination": "[5.1.2, )" + } + }, + "cs2launcher.aspnetcore.launcher": { + "type": "Project", + "dependencies": { + "AspNet.Security.OpenId.Steam": "[8.0.0, )", + "CS2Launcher.AspNetCore.App": "[1.0.0, )", + "CoreRCON.Extensions.CounterStrike": "[1.0.0, )", + "Microsoft.AspNetCore.Components.WebAssembly.Server": "[8.0.4, )" + } + }, + "cs2launcher.sample.app": { + "type": "Project", + "dependencies": { + "CS2Launcher.AspNetCore.App": "[1.0.0, )", + "Microsoft.AspNetCore.Components.WebAssembly": "[8.0.4, )" + } + } + }, + "net8.0/linux-x64": { + "System.Text.Encoding.CodePages": { + "type": "Transitive", + "resolved": "7.0.0", + "contentHash": "LSyCblMpvOe0N3E+8e0skHcrIhgV2huaNcjUUEa8hRtgEAm36aGkRoC8Jxlb6Ra6GSfF29ftduPNywin8XolzQ==" + }, + "System.Text.Encodings.Web": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "yev/k9GHAEGx2Rg3/tU6MQh4HGBXJs70y7j1LaM1i/ER9po+6nnQ6RRqTJn1E7Xu0fbIFK80Nh5EoODxrbxwBQ==" + } + }, + "net8.0/win-x64": { + "System.Text.Encoding.CodePages": { + "type": "Transitive", + "resolved": "7.0.0", + "contentHash": "LSyCblMpvOe0N3E+8e0skHcrIhgV2huaNcjUUEa8hRtgEAm36aGkRoC8Jxlb6Ra6GSfF29ftduPNywin8XolzQ==" + }, + "System.Text.Encodings.Web": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "yev/k9GHAEGx2Rg3/tU6MQh4HGBXJs70y7j1LaM1i/ER9po+6nnQ6RRqTJn1E7Xu0fbIFK80Nh5EoODxrbxwBQ==" + } + } + } +} \ No newline at end of file diff --git a/sample/Program.cs b/sample/Program.cs deleted file mode 100644 index 4a5a6f8..0000000 --- a/sample/Program.cs +++ /dev/null @@ -1,6 +0,0 @@ -using CS2Launcher.AspNetCore.Launcher; - -var builder = CS2LauncherApplication.CreateBuilder( args ); - -await using var app = builder.Build(); -await app.RunAsync(); \ No newline at end of file diff --git a/sample/packages.lock.json b/sample/packages.lock.json deleted file mode 100644 index d451122..0000000 --- a/sample/packages.lock.json +++ /dev/null @@ -1,54 +0,0 @@ -{ - "version": 1, - "dependencies": { - "net8.0": { - "Microsoft.DotNet.ILCompiler": { - "type": "Direct", - "requested": "[8.0.4, )", - "resolved": "8.0.4", - "contentHash": "bVK6XD5E/BpkPmdrx99ZkloZZX3nOvTAcW+W6jW4cs8elWlLFAc9BXHk2esxSVHMiaCLiLdIJAyhUfhV50TW+Q==" - }, - "Microsoft.NET.ILLink.Tasks": { - "type": "Direct", - "requested": "[8.0.4, )", - "resolved": "8.0.4", - "contentHash": "PZb5nfQ+U19nhnmnR9T1jw+LTmozhuG2eeuzuW5A7DqxD/UXW2ucjmNJqnqOuh8rdPzM3MQXoF8AfFCedJdCUw==" - }, - "cs2launcher.aspnetcore.launcher": { - "type": "Project" - } - }, - "net8.0/linux-x64": { - "Microsoft.DotNet.ILCompiler": { - "type": "Direct", - "requested": "[8.0.4, )", - "resolved": "8.0.4", - "contentHash": "bVK6XD5E/BpkPmdrx99ZkloZZX3nOvTAcW+W6jW4cs8elWlLFAc9BXHk2esxSVHMiaCLiLdIJAyhUfhV50TW+Q==", - "dependencies": { - "runtime.linux-x64.Microsoft.DotNet.ILCompiler": "8.0.4" - } - }, - "runtime.linux-x64.Microsoft.DotNet.ILCompiler": { - "type": "Transitive", - "resolved": "8.0.4", - "contentHash": "SQ0McYt+iC6i5wMYIkW8hUlTGh5eFJgMiASG7HsOFyrv9DZnztUzIalN+MKwn8MdSoHE94bON4AC0VG8FjjqQA==" - } - }, - "net8.0/win-x64": { - "Microsoft.DotNet.ILCompiler": { - "type": "Direct", - "requested": "[8.0.4, )", - "resolved": "8.0.4", - "contentHash": "bVK6XD5E/BpkPmdrx99ZkloZZX3nOvTAcW+W6jW4cs8elWlLFAc9BXHk2esxSVHMiaCLiLdIJAyhUfhV50TW+Q==", - "dependencies": { - "runtime.win-x64.Microsoft.DotNet.ILCompiler": "8.0.4" - } - }, - "runtime.win-x64.Microsoft.DotNet.ILCompiler": { - "type": "Transitive", - "resolved": "8.0.4", - "contentHash": "jOBAHB9NiCdVUrNoJMkDjRPdNTLUxTVu87D5nXjoMPrgk12QDwVFGKCFCgQTxnfY12xSg6KlW4lMG0v+PfYGwQ==" - } - } - } -} \ No newline at end of file diff --git a/src/App/Abstractions/AppVersion.cs b/src/App/Abstractions/AppVersion.cs new file mode 100644 index 0000000..59dda4a --- /dev/null +++ b/src/App/Abstractions/AppVersion.cs @@ -0,0 +1,49 @@ +using System.Reflection; + +namespace CS2Launcher.AspNetCore.App.Abstractions; + +/// Represents the version of the CS2Launcher App. +public sealed class AppVersion +{ + /// A reference to the current version of the application. + public static readonly AppVersion Value = new(); + + /// The major version. + public int Major { get; } + + /// The minor version. + public int Minor { get; } + + /// The patch, or hotfix, version. + public int Patch { get; } + + /// Additional versioning metadata for tracking. + public string? Metadata { get; } + + private AppVersion( ) + { + var assembly = typeof( AppVersion ).Assembly; + + var version = assembly.GetName().Version!; + Major = version.Major; + Minor = version.Minor; + Patch = version.Build; + + var informational = assembly.GetCustomAttribute()?.InformationalVersion; + var index = informational?.IndexOf( '-' ) ?? -1; + if( index > 0 ) + { + Metadata = informational![ (index + 1)..(informational!.IndexOf( '+' ) + 8) ]; + } + } + + /// + public override string ToString( ) + { + var version = $"{Major}.{Minor}.{Patch}"; + return !string.IsNullOrEmpty( Metadata ) ? $"{version}-{Metadata}" : version; + } + + /// + public static implicit operator string( AppVersion version ) => version.ToString(); +} \ No newline at end of file diff --git a/src/App/Abstractions/ConsoleSignals.cs b/src/App/Abstractions/ConsoleSignals.cs new file mode 100644 index 0000000..15485a5 --- /dev/null +++ b/src/App/Abstractions/ConsoleSignals.cs @@ -0,0 +1,26 @@ +using CS2Launcher.AspNetCore.App.Abstractions.Signaling; + +namespace CS2Launcher.AspNetCore.App.Abstractions; + +/// Signals used by the 'Console' feature. +public static class ConsoleSignals +{ + /// Represents the 'Connected' signal. + /// The host that's been connected. + public sealed record Connected( string Host ) : Signal; + + /// Represents the 'ExecuteCommand' signal. + /// The command to be executed. + /// A unique identifier used for traking the signal. + public sealed record ExecuteCommand( string Command, long Token ) : Signal; + + /// Represents the 'ExecutedCommand' signal. + /// The result of executing a command. + /// A unique identifier used for traking the signal. + public sealed record ExecutedCommand( string Text, long Token ) : Signal; + + /// Represents the 'ExecuteCommandFailed' signal. + /// The result of executing a command. + /// A unique identifier used for traking the signal. + public sealed record ExecuteCommandFailed( string Error, long Token ) : Signal; +} \ No newline at end of file diff --git a/src/App/Abstractions/Signal{TSignal}.cs b/src/App/Abstractions/Signal{TSignal}.cs new file mode 100644 index 0000000..45a500d --- /dev/null +++ b/src/App/Abstractions/Signal{TSignal}.cs @@ -0,0 +1,5 @@ +namespace CS2Launcher.AspNetCore.App.Abstractions.Signaling; + +/// Defines a signal. +/// The type of signal being defined. +public abstract record Signal where TSignal : Signal; \ No newline at end of file diff --git a/src/App/AppServiceExtensions.cs b/src/App/AppServiceExtensions.cs new file mode 100644 index 0000000..c21a9b7 --- /dev/null +++ b/src/App/AppServiceExtensions.cs @@ -0,0 +1,20 @@ +using System.Diagnostics.CodeAnalysis; +using CS2Launcher.AspNetCore.App.Hosting; +using CS2Launcher.AspNetCore.App.Interop; +using Microsoft.Extensions.DependencyInjection; + +namespace CS2Launcher.AspNetCore.App; + +/// Extensions for registering services required by the CS2Launcher App. +public static class AppServiceExtensions +{ + /// Add services required by the CS2Launcher App. + /// The type of of the app. + public static IServiceCollection AddCS2LauncherApp<[DynamicallyAccessedMembers( DynamicallyAccessedMemberTypes.All )] TRoot>( this IServiceCollection services ) + where TRoot : RootComponent + { + ArgumentNullException.ThrowIfNull( services ); + return services.AddSingleton( new RootComponentDescriptor( typeof( TRoot ) ) ) + .AddScoped(); + } +} \ No newline at end of file diff --git a/src/App/CS2Launcher.AspNetCore.App.csproj b/src/App/CS2Launcher.AspNetCore.App.csproj new file mode 100644 index 0000000..112d174 --- /dev/null +++ b/src/App/CS2Launcher.AspNetCore.App.csproj @@ -0,0 +1,48 @@ + + + + Blazor Runtime Components for CS2 Launcher. + true + true + true + README.md + + + + + + + + + + + + + + + + + + + + + + + + + + + + <_ScopedCssBundle>$(ProjectDir)obj\$(ConfigurationName)\$(TargetFramework)\scopedcss\projectbundle\$(ProjectName).bundle.scp.css + + + <_CrossEnvArguments>MSBUILD_PROJECT_DIR='$(MSBuildProjectDirectory)' + + <_PostCssArguments>$(_ScopedCssBundle) -r --config . --verbose + <_PostCssArguments Condition=" '$(Configuration)' == 'Release' ">$(_PostCssArguments) --env production --no-map + + + + + + diff --git a/src/App/Hosting/RootComponentDescriptor.cs b/src/App/Hosting/RootComponentDescriptor.cs new file mode 100644 index 0000000..c4990dd --- /dev/null +++ b/src/App/Hosting/RootComponentDescriptor.cs @@ -0,0 +1,7 @@ +using System.Diagnostics.CodeAnalysis; + +namespace CS2Launcher.AspNetCore.App.Hosting; + +/// Represents metadata about the root component. +/// The type of . +public sealed record RootComponentDescriptor( [DynamicallyAccessedMembers( DynamicallyAccessedMemberTypes.All )] Type ComponentType ); \ No newline at end of file diff --git a/src/App/Hosting/WebAssemblyHostBuilderExtensions.cs b/src/App/Hosting/WebAssemblyHostBuilderExtensions.cs new file mode 100644 index 0000000..18e26bf --- /dev/null +++ b/src/App/Hosting/WebAssemblyHostBuilderExtensions.cs @@ -0,0 +1,24 @@ +using System.Diagnostics.CodeAnalysis; +using Microsoft.AspNetCore.Components.WebAssembly.Hosting; +using Microsoft.Extensions.Logging; + +namespace CS2Launcher.AspNetCore.App.Hosting; + +/// Extensions for configuring a CS2Launcher App in a Web Assembly Host. +public static class WebAssemblyHostBuilderExtensions +{ + /// Configure the Web Assembly Host to use the CS2Launcher App with the root component of type . + /// The type of . + public static WebAssemblyHostBuilder UseCS2Launcher<[DynamicallyAccessedMembers( DynamicallyAccessedMemberTypes.All )] TRoot>( this WebAssemblyHostBuilder builder ) + where TRoot : RootComponent + { + ArgumentNullException.ThrowIfNull( builder ); + + builder.Logging.SetMinimumLevel( builder.HostEnvironment.IsDevelopment() + ? LogLevel.Information + : LogLevel.Error ); + + builder.Services.AddCS2LauncherApp(); + return builder; + } +} \ No newline at end of file diff --git a/src/App/Infrastructure/ConsoleSignaler.cs b/src/App/Infrastructure/ConsoleSignaler.cs new file mode 100644 index 0000000..ac6972a --- /dev/null +++ b/src/App/Infrastructure/ConsoleSignaler.cs @@ -0,0 +1,5 @@ +using Microsoft.AspNetCore.Components; + +namespace CS2Launcher.AspNetCore.App.Infrastructure; + +internal sealed class ConsoleSignaler( NavigationManager navigation ) : Signaler( navigation, "/api/signals/console" ); \ No newline at end of file diff --git a/src/App/Infrastructure/PlatformGuard.cs b/src/App/Infrastructure/PlatformGuard.cs new file mode 100644 index 0000000..9218a31 --- /dev/null +++ b/src/App/Infrastructure/PlatformGuard.cs @@ -0,0 +1,12 @@ +namespace CS2Launcher.AspNetCore.App.Infrastructure; + +internal static class PlatformGuard +{ + public static void ThrowIfNotBrowser( string? message = null ) + { + if( !OperatingSystem.IsBrowser() ) + { + throw new PlatformNotSupportedException( message ); + } + } +} \ No newline at end of file diff --git a/src/App/Infrastructure/Signaler.cs b/src/App/Infrastructure/Signaler.cs new file mode 100644 index 0000000..62e1924 --- /dev/null +++ b/src/App/Infrastructure/Signaler.cs @@ -0,0 +1,67 @@ +using System.Diagnostics.CodeAnalysis; +using CS2Launcher.AspNetCore.App.Abstractions.Signaling; +using CS2Launcher.AspNetCore.App.Infrastructure; +using Microsoft.AspNetCore.Components; +using Microsoft.AspNetCore.SignalR.Client; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; + +internal abstract class Signaler( Action configure ) : IAsyncDisposable +{ + private readonly Lazy connection = new( ConnectionFactory( configure ) ); + protected HubConnection Connection => connection.Value; + + protected Signaler( NavigationManager navigation, string path ) + : this( connection => connection.WithUrl( navigation.ToAbsoluteUri( path ) ) ) + { + } + + private static Func ConnectionFactory( Action configure ) + => ( ) => + { + var builder = new HubConnectionBuilder() + .AddMessagePackProtocol() +#if DEBUG + .AddJsonProtocol() + .ConfigureLogging( logging => logging.SetMinimumLevel( LogLevel.Debug ) ) +#endif + .WithStatefulReconnect() + .WithAutomaticReconnect(); + + configure( builder ); + return builder.Build(); + }; + + public async ValueTask DisposeAsync( ) + { + if( connection.IsValueCreated ) + { + await connection.Value.DisposeAsync(); + } + + GC.SuppressFinalize( this ); + } + + public Task Connect( ) + { + PlatformGuard.ThrowIfNotBrowser( "Signaler cannot be initialized outside of a browser context." ); + if( Connection.State > HubConnectionState.Disconnected ) + { + return Task.CompletedTask; + } + + return Connection.StartAsync(); + } + + public IDisposable On<[DynamicallyAccessedMembers( DynamicallyAccessedMemberTypes.PublicProperties )] TSignal>( Func handler ) + where TSignal : Signal + => Connection.On( typeof( TSignal ).Name, handler ); + + public IDisposable On<[DynamicallyAccessedMembers( DynamicallyAccessedMemberTypes.PublicProperties )] TSignal>( Action handler ) + where TSignal : Signal + => Connection.On( typeof( TSignal ).Name, handler ); + + public Task Send<[DynamicallyAccessedMembers( DynamicallyAccessedMemberTypes.PublicProperties )] TSignal>( TSignal signal ) + where TSignal : Signal + => Connection.SendAsync( typeof( TSignal ).Name, signal ); +} \ No newline at end of file diff --git a/src/App/Interop/ElementInterop.cs b/src/App/Interop/ElementInterop.cs new file mode 100644 index 0000000..56afe66 --- /dev/null +++ b/src/App/Interop/ElementInterop.cs @@ -0,0 +1,9 @@ +using Microsoft.AspNetCore.Components; +using Microsoft.JSInterop; + +namespace CS2Launcher.AspNetCore.App.Interop; + +internal sealed class ElementInterop( IJSRuntime runtime ) : Interop( runtime, "Element" ) +{ + public ValueTask FocusAndSelectEnd( ElementReference element ) => Access( module => module.InvokeVoidAsync( "focusAndSelectEnd", element ) ); +} \ No newline at end of file diff --git a/src/App/Interop/Interop.cs b/src/App/Interop/Interop.cs new file mode 100644 index 0000000..dd9b52c --- /dev/null +++ b/src/App/Interop/Interop.cs @@ -0,0 +1,51 @@ +using Microsoft.JSInterop; +using CS2Launcher.AspNetCore.App.Infrastructure; +using Nito.AsyncEx; + +namespace CS2Launcher.AspNetCore.App.Interop; + +internal abstract class Interop( IJSRuntime runtime, string moduleName ) : IAsyncDisposable +{ + public string ModulePath => $"/_content/CS2Launcher.AspNetCore.App/Interop/{moduleName}.module.js"; + + private readonly AsyncLock moduleLock = new(); + + private IJSObjectReference? module; + protected IJSRuntime Runtime { get; } = runtime; + + protected async ValueTask Access( Func method ) + { + PlatformGuard.ThrowIfNotBrowser(); + + await EnsureModuleReference(); + await method( module! ); + } + + protected async ValueTask Access( Func> method ) + { + PlatformGuard.ThrowIfNotBrowser(); + + await EnsureModuleReference(); + return await method( module! ); + } + + public async ValueTask DisposeAsync( ) + { + if( module is not null ) + { + await module.DisposeAsync(); + } + + GC.SuppressFinalize( this ); + } + + private async ValueTask EnsureModuleReference( ) + { + if( module is not null ) return; + + using( await moduleLock.LockAsync() ) + { + module ??= await Runtime.InvokeAsync( "import", ModulePath ); + } + } +} \ No newline at end of file diff --git a/src/App/Pages/Console.razor b/src/App/Pages/Console.razor new file mode 100644 index 0000000..bde3b6d --- /dev/null +++ b/src/App/Pages/Console.razor @@ -0,0 +1,228 @@ +@page "/" + +@implements IAsyncDisposable + +@inject ElementInterop ElementInterop +@inject NavigationManager Navigation + +Console@(!string.IsNullOrEmpty(Host) ? $": {Host}" : "") + + + @if (!string.IsNullOrEmpty(Host)) + { + + + + + + + + @Host + + @entry.Value.Command + + + @if (entry.Value.IsExecuting) + { + + + + } + else + { + @entry.Value.Text + } + + + + + + + + + + @Host + + + + + + } + else + { + + } + + +@code { + + private InputText? commandInput; + private ConsoleSignaler signaler = default!; + private List? signals; + + private Dictionary Entries { get; set; } = []; + private ConsoleForm Form { get; set; } = new(); + private string Host { get; set; } + + protected override async Task OnAfterRenderAsync(bool firstRender) + { + await base.OnAfterRenderAsync(firstRender); + if (firstRender) + { + signals = [signaler.On(OnConnected), +signaler.On(OnExecutedCommand), +signaler.On(OnExecuteCommandFailed)]; + + await signaler.Connect(); + } + } + + private void OnCommandInputBlur() + { + Form.Offset = 0; + } + + private async Task OnCommandInputKeyDown(KeyboardEventArgs e) + { + var handled = await (e.Code switch + { + "ArrowDown" => OnArrowDown(), + "ArrowUp" => OnArrowUp(), + _ => Task.FromResult(false) + }); + + if (handled && string.IsNullOrEmpty(Form.Command)) + { + Form.Offset = 0; + } + + async Task OnArrowDown() + { + var offset = ((Entries.Count - 1) - Form.Offset) + 1; + if (offset >= 0 && offset < Entries.Count) + { + Form.Command = Entries.Values.ElementAt(offset).Command; + Form.Offset--; + await InvokeAsync(StateHasChanged); + + await Task.Delay(75); + await TryFocusCommandInput(); + return true; + } + + return false; + } + + async Task OnArrowUp() + { + var offset = (Entries.Count - 1) - Form.Offset; + if (offset >= 0) + { + Form.Command = Entries.Values.ElementAt(offset).Command; + Form.Offset++; + await InvokeAsync(StateHasChanged); + + await Task.Delay(75); + await TryFocusCommandInput(); + return true; + } + + return false; + } + } + + private Task OnExecutedCommand(ConsoleSignals.ExecutedCommand command) + { + if (Entries.TryGetValue(command.Token, out var entry)) + { + Entries[command.Token] = entry with + { + IsExecuting = false, + Text = command.Text + }; + + return InvokeAsync(StateHasChanged); + } + + return Task.CompletedTask; + } + + private Task OnExecuteCommandFailed(ConsoleSignals.ExecuteCommandFailed failure) + { + if (Entries.TryGetValue(failure.Token, out var entry)) + { + Entries[failure.Token] = entry with + { + IsExecuting = false, + IsError = true, + Text = failure.Error, + }; + + return InvokeAsync(StateHasChanged); + } + + return Task.CompletedTask; + } + + private async Task OnConnected(ConsoleSignals.Connected connected) + { + Host = connected.Host; + + await InvokeAsync(StateHasChanged); + await TryFocusCommandInput(); + } + + protected override void OnInitialized() + { + Form ??= new(); + signaler = new(Navigation); + } + + private async Task OnSubmit() + { + var signal = new ConsoleSignals.ExecuteCommand(Form.Command, DateTime.UtcNow.Ticks); + + Entries.Add(signal.Token, new(signal.Command)); + await signaler.Send(signal); + + Form = new(); + + await Task.Delay(75); + await TryFocusCommandInput(); + } + + public async ValueTask DisposeAsync() + { + signals?.ForEach(signal => signal.Dispose()); + signals?.Clear(); + + if (signaler is not null) + { + await signaler.DisposeAsync(); + } + } + + private ValueTask TryFocusCommandInput() + { + if (commandInput?.Element.HasValue is true) + { + return ElementInterop.FocusAndSelectEnd(commandInput.Element.Value); + } + + return ValueTask.CompletedTask; + } + + private sealed record CommandEntry(string Command, bool IsExecuting = true, string? Text = default) + { + public bool IsError { get; init; } + } + + public sealed class ConsoleForm + { + public int Offset { get; set; } + + [Required] + public string Command { get; set; } + } + +} \ No newline at end of file diff --git a/src/App/RootComponent.razor b/src/App/RootComponent.razor new file mode 100644 index 0000000..992b064 --- /dev/null +++ b/src/App/RootComponent.razor @@ -0,0 +1,25 @@ + + + + + + + + Not Found + Nothing to see here... + + + + +@code { + + protected override void OnAfterRender(bool firstRender) + { + base.OnAfterRender(firstRender); + if (firstRender) + { + Console.WriteLine($"CS2Launcher App v{AppVersion.Value}"); + } + } + +} \ No newline at end of file diff --git a/src/App/RootComponent.razor.cs b/src/App/RootComponent.razor.cs new file mode 100644 index 0000000..43482a0 --- /dev/null +++ b/src/App/RootComponent.razor.cs @@ -0,0 +1,6 @@ +using Microsoft.AspNetCore.Components; + +namespace CS2Launcher.AspNetCore.App; + +/// Describes the root component of a CS2Launcher App. +public abstract partial class RootComponent : ComponentBase; \ No newline at end of file diff --git a/src/App/Shared/ClassNames.cs b/src/App/Shared/ClassNames.cs new file mode 100644 index 0000000..7c77560 --- /dev/null +++ b/src/App/Shared/ClassNames.cs @@ -0,0 +1,19 @@ +namespace CS2Launcher.AspNetCore.App.Shared; + +/// Helpers for combining css class names. +public static class ClassNames +{ + /// Combine the given . + public static string Combine( params string[] classNames ) => string.Join( " ", classNames.Select( className => className.Trim() ) ).TrimEnd(); + + /// Combine the given with the class value in the given . + public static string Combine( IReadOnlyDictionary? attributes, params string[] classNames ) + { + if( attributes?.TryGetValue( "class", out var value ) is true && value is string @class ) + { + return Combine( [ .. classNames.Append( @class ) ] ); + } + + return Combine( classNames ); + } +} diff --git a/src/App/Shared/Icon.razor b/src/App/Shared/Icon.razor new file mode 100644 index 0000000..18d2885 --- /dev/null +++ b/src/App/Shared/Icon.razor @@ -0,0 +1,37 @@ +@Name + +@code { + + [Parameter(CaptureUnmatchedValues = true)] + public IReadOnlyDictionary? AdditionalAttributes { get; init; } + + [Parameter] + public bool Filled { get; init; } = true; + + [EditorRequired] + [Parameter] + public IconName Name { get; set; } = default!; + + [Parameter] + public IconSize Size { get; init; } = IconSize.Base; + + private static string ToCssClass(IconSize size) + => size switch + { + IconSize.ExtraSmall => "text-xs", + IconSize.Small => "text-sm", + IconSize.Base => "text-base", + IconSize.Large => "text-lg", + IconSize.ExtraLarge => "text-xl", + IconSize.ExtraLarge2 => "text-2xl", + IconSize.ExtraLarge3 => "text-3xl", + IconSize.ExtraLarge4 => "text-4xl", + IconSize.ExtraLarge5 => "text-5xl", + IconSize.ExtraLarge6 => "text-6xl", + IconSize.ExtraLarge7 => "text-7xl", + IconSize.ExtraLarge8 => "text-8xl", + IconSize.ExtraLarge9 => "text-9xl", + _ => "text-base" + }; + +} \ No newline at end of file diff --git a/src/App/Shared/Icon.razor.cs b/src/App/Shared/Icon.razor.cs new file mode 100644 index 0000000..99d8b14 --- /dev/null +++ b/src/App/Shared/Icon.razor.cs @@ -0,0 +1,34 @@ +namespace CS2Launcher.AspNetCore.App.Shared; + +/// Describes the name of icons. +/// The name of the icon. +public readonly struct IconName( string name ) +{ + public static readonly IconName ChevronRight = new( "chevron_right" ); + public static readonly IconName Circle = new( "circle" ); + public static readonly IconName CloudCircle = new( "cloud_circle" ); + public static readonly IconName Error = new( "error" ); + public static readonly IconName Pending = new( "pending" ); + public static readonly IconName ProgressActivity = new( "progress_activity" ); + + /// + public override string ToString( ) => name; +} + +/// Describes the desired size of an icon. +public enum IconSize +{ + ExtraSmall, + Small, + Base, + Large, + ExtraLarge, + ExtraLarge2, + ExtraLarge3, + ExtraLarge4, + ExtraLarge5, + ExtraLarge6, + ExtraLarge7, + ExtraLarge8, + ExtraLarge9, +} \ No newline at end of file diff --git a/src/App/Shared/Icon.razor.css b/src/App/Shared/Icon.razor.css new file mode 100644 index 0000000..1ce55b1 --- /dev/null +++ b/src/App/Shared/Icon.razor.css @@ -0,0 +1,31 @@ +@layer components { + @font-face { + font-family: 'Material Symbols Rounded'; + font-style: normal; + font-weight: 100 700; + src: url(https://fonts.gstatic.com/s/materialsymbolsrounded/v177/sykg-zNym6YjUruM-QrEh7-nyTnjDwKNJ_190Fjzag.woff2) format('woff2'); + } + + i { + font-family: 'Material Symbols Rounded'; + font-variation-settings: + 'FILL' 0, + 'wght' 400, + 'GRAD' 0, + 'opsz' 24; + } + + i.filled { + font-family: 'Material Symbols Rounded'; + font-variation-settings: + 'FILL' 1, + 'wght' 400, + 'GRAD' 0, + 'opsz' 24; + } + + i, + i.filled { + @apply antialiased font-normal inline-block leading-none normal-case not-italic select-none tracking-normal whitespace-nowrap; + } +} \ No newline at end of file diff --git a/src/App/Shared/Layout.razor b/src/App/Shared/Layout.razor new file mode 100644 index 0000000..d6b0b21 --- /dev/null +++ b/src/App/Shared/Layout.razor @@ -0,0 +1,5 @@ +@inherits LayoutComponentBase + + + @Body + diff --git a/src/App/Shared/Loading.razor b/src/App/Shared/Loading.razor new file mode 100644 index 0000000..8ae4677 --- /dev/null +++ b/src/App/Shared/Loading.razor @@ -0,0 +1,13 @@ + + + + + @Text + + +@code { + + [Parameter] + public string Text { get; set; } = "Loading..."; + +} \ No newline at end of file diff --git a/src/App/_Imports.razor b/src/App/_Imports.razor new file mode 100644 index 0000000..ee7d2e6 --- /dev/null +++ b/src/App/_Imports.razor @@ -0,0 +1,16 @@ +@using System.ComponentModel.DataAnnotations +@using System.Net.Http +@using System.Net.Http.Json + +@using Microsoft.AspNetCore.Components.Forms +@using Microsoft.AspNetCore.Components.Routing +@using Microsoft.AspNetCore.Components.Web +@using static Microsoft.AspNetCore.Components.Web.RenderMode +@using Microsoft.AspNetCore.Components.Web.Virtualization +@using Microsoft.JSInterop + +@using CS2Launcher.AspNetCore.App +@using CS2Launcher.AspNetCore.App.Abstractions +@using CS2Launcher.AspNetCore.App.Infrastructure +@using CS2Launcher.AspNetCore.App.Interop +@using CS2Launcher.AspNetCore.App.Shared diff --git a/src/App/_Imports.razor.css b/src/App/_Imports.razor.css new file mode 100644 index 0000000..5fc61e8 --- /dev/null +++ b/src/App/_Imports.razor.css @@ -0,0 +1,24 @@ +@tailwind base; + +@layer base { + ::deep body { + @apply caret-neutral-200/80 bg-gray-800 bg-gradient-to-tl from-gray-900/80 via-zinc-950/40 to-gray-900/80 font-sans text-base text-zinc-200; + } + + ::deep ::selection { + @apply backdrop-blur bg-slate-500/50 shadow text-neutral-50; + } + + ::deep code, + ::deep pre, + ::deep samp { + @apply font-mono; + } + + ::deep samp { + @apply whitespace-pre; + } +} + +@tailwind components; +@tailwind utilities; \ No newline at end of file diff --git a/src/App/build/CS2Launcher.AspNetCore.App.props b/src/App/build/CS2Launcher.AspNetCore.App.props new file mode 100644 index 0000000..679a09d --- /dev/null +++ b/src/App/build/CS2Launcher.AspNetCore.App.props @@ -0,0 +1,25 @@ + + + + true + true + false + true + true + true + Default + partial + true + true + + + + + + + + + + + + \ No newline at end of file diff --git a/src/App/package-lock.json b/src/App/package-lock.json new file mode 100644 index 0000000..5090635 --- /dev/null +++ b/src/App/package-lock.json @@ -0,0 +1,4502 @@ +{ + "name": "App", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "App", + "devDependencies": { + "@tailwindcss/forms": "^0.5.7", + "cross-env": "^7.0.3", + "cssnano": "^7.0.1", + "postcss": "^8.4.38", + "postcss-cli": "^11.0.0", + "postcss-preset-env": "^9.5.9", + "tailwindcss": "^3.4.3" + } + }, + "node_modules/@alloc/quick-lru": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", + "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@csstools/cascade-layer-name-parser": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@csstools/cascade-layer-name-parser/-/cascade-layer-name-parser-1.0.9.tgz", + "integrity": "sha512-RRqNjxTZDUhx7pxYOBG/AkCVmPS3zYzfE47GEhIGkFuWFTQGJBgWOUUkKNo5MfxIfjDz5/1L3F3rF1oIsYaIpw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "engines": { + "node": "^14 || ^16 || >=18" + }, + "peerDependencies": { + "@csstools/css-parser-algorithms": "^2.6.1", + "@csstools/css-tokenizer": "^2.2.4" + } + }, + "node_modules/@csstools/color-helpers": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-4.2.0.tgz", + "integrity": "sha512-hJJrSBzbfGxUsaR6X4Bzd/FLx0F1ulKnR5ljY9AiXCtsR+H+zSWQDFWlKES1BRaVZTDHLpIIHS9K2o0h+JLlrg==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "engines": { + "node": "^14 || ^16 || >=18" + } + }, + "node_modules/@csstools/css-calc": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@csstools/css-calc/-/css-calc-1.2.0.tgz", + "integrity": "sha512-iQqIW5vDPqQdLx07/atCuNKDprhIWjB0b8XRhUyXZWBZYUG+9mNyFwyu30rypX84WLevVo25NYW2ipxR8WyseQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "engines": { + "node": "^14 || ^16 || >=18" + }, + "peerDependencies": { + "@csstools/css-parser-algorithms": "^2.6.1", + "@csstools/css-tokenizer": "^2.2.4" + } + }, + "node_modules/@csstools/css-color-parser": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-2.0.0.tgz", + "integrity": "sha512-0/v6OPpcg+b8TJT2N1Rcp0oH5xEvVOU5K2qDkaR3IMHNXuJ7XfVCQLINt3Cuj8mr54DbilEoZ9uvAmHBoZ//Fw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "dependencies": { + "@csstools/color-helpers": "^4.2.0", + "@csstools/css-calc": "^1.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "peerDependencies": { + "@csstools/css-parser-algorithms": "^2.6.1", + "@csstools/css-tokenizer": "^2.2.4" + } + }, + "node_modules/@csstools/css-parser-algorithms": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-2.6.1.tgz", + "integrity": "sha512-ubEkAaTfVZa+WwGhs5jbo5Xfqpeaybr/RvWzvFxRs4jfq16wH8l8Ty/QEEpINxll4xhuGfdMbipRyz5QZh9+FA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "engines": { + "node": "^14 || ^16 || >=18" + }, + "peerDependencies": { + "@csstools/css-tokenizer": "^2.2.4" + } + }, + "node_modules/@csstools/css-tokenizer": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-2.2.4.tgz", + "integrity": "sha512-PuWRAewQLbDhGeTvFuq2oClaSCKPIBmHyIobCV39JHRYN0byDcUWJl5baPeNUcqrjtdMNqFooE0FGl31I3JOqw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "engines": { + "node": "^14 || ^16 || >=18" + } + }, + "node_modules/@csstools/media-query-list-parser": { + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/@csstools/media-query-list-parser/-/media-query-list-parser-2.1.9.tgz", + "integrity": "sha512-qqGuFfbn4rUmyOB0u8CVISIp5FfJ5GAR3mBrZ9/TKndHakdnm6pY0L/fbLcpPnrzwCyyTEZl1nUcXAYHEWneTA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "engines": { + "node": "^14 || ^16 || >=18" + }, + "peerDependencies": { + "@csstools/css-parser-algorithms": "^2.6.1", + "@csstools/css-tokenizer": "^2.2.4" + } + }, + "node_modules/@csstools/postcss-cascade-layers": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@csstools/postcss-cascade-layers/-/postcss-cascade-layers-4.0.4.tgz", + "integrity": "sha512-MKErv8lpEwVmAcAwidY1Kfd3oWrh2Q14kxHs9xn26XzjP/PrcdngWq63lJsZeMlBY7o+WlEOeE+FP6zPzeY2uw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "dependencies": { + "@csstools/selector-specificity": "^3.0.3", + "postcss-selector-parser": "^6.0.13" + }, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-color-function": { + "version": "3.0.14", + "resolved": "https://registry.npmjs.org/@csstools/postcss-color-function/-/postcss-color-function-3.0.14.tgz", + "integrity": "sha512-joGAf5bT3Jg1CpybupMJ4DwNg/VNjmLWZoWMDmX0MTy/ftHA1Qr4+CslqTT4AA1n6Dx4Wa+DSMGPrDLHtRP0jg==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "dependencies": { + "@csstools/css-color-parser": "^2.0.0", + "@csstools/css-parser-algorithms": "^2.6.1", + "@csstools/css-tokenizer": "^2.2.4", + "@csstools/postcss-progressive-custom-properties": "^3.2.0", + "@csstools/utilities": "^1.0.0" + }, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-color-mix-function": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/@csstools/postcss-color-mix-function/-/postcss-color-mix-function-2.0.14.tgz", + "integrity": "sha512-ZLbgtdhyuOoWoRo/W8jFv68q+IMgTJHOAI+WunRbrRPqI+vJ0K2rud/lS9Se5urzM/imVKs/kz0Uobm5Yj4HUg==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "dependencies": { + "@csstools/css-color-parser": "^2.0.0", + "@csstools/css-parser-algorithms": "^2.6.1", + "@csstools/css-tokenizer": "^2.2.4", + "@csstools/postcss-progressive-custom-properties": "^3.2.0", + "@csstools/utilities": "^1.0.0" + }, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-exponential-functions": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@csstools/postcss-exponential-functions/-/postcss-exponential-functions-1.0.5.tgz", + "integrity": "sha512-7S7I7KgwHWQYzJJAoIjRtUf7DQs1dxipeg1A6ikZr0PYapNJX7UHz0evlpE67SQqYj1xBs70gpG7xUv3uLp4PA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "dependencies": { + "@csstools/css-calc": "^1.2.0", + "@csstools/css-parser-algorithms": "^2.6.1", + "@csstools/css-tokenizer": "^2.2.4" + }, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-font-format-keywords": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@csstools/postcss-font-format-keywords/-/postcss-font-format-keywords-3.0.2.tgz", + "integrity": "sha512-E0xz2sjm4AMCkXLCFvI/lyl4XO6aN1NCSMMVEOngFDJ+k2rDwfr6NDjWljk1li42jiLNChVX+YFnmfGCigZKXw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "dependencies": { + "@csstools/utilities": "^1.0.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-gamut-mapping": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/@csstools/postcss-gamut-mapping/-/postcss-gamut-mapping-1.0.7.tgz", + "integrity": "sha512-vrsHsl5TN6NB5CT0rPG6JE9V2GLFftcmPtF/k4cWT4gyVMCsDyS9wEVl82sgvh/JQ32TaUo6bh8Ndl+XRJqGQw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "dependencies": { + "@csstools/css-color-parser": "^2.0.0", + "@csstools/css-parser-algorithms": "^2.6.1", + "@csstools/css-tokenizer": "^2.2.4" + }, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-gradients-interpolation-method": { + "version": "4.0.15", + "resolved": "https://registry.npmjs.org/@csstools/postcss-gradients-interpolation-method/-/postcss-gradients-interpolation-method-4.0.15.tgz", + "integrity": "sha512-0xQ5r4WU/6W2lDmnOTx9liC1Cq6RSnrkEzqX7d0cRA3fz5hjC276pA0nLMoAiY3vtAp0u71nTk/3TRdnCx/OUw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "dependencies": { + "@csstools/css-color-parser": "^2.0.0", + "@csstools/css-parser-algorithms": "^2.6.1", + "@csstools/css-tokenizer": "^2.2.4", + "@csstools/postcss-progressive-custom-properties": "^3.2.0", + "@csstools/utilities": "^1.0.0" + }, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-hwb-function": { + "version": "3.0.13", + "resolved": "https://registry.npmjs.org/@csstools/postcss-hwb-function/-/postcss-hwb-function-3.0.13.tgz", + "integrity": "sha512-f44tgkFSxJBGm8UjlkAfBP7xE2x2XFFdvNdedHl8jpx2pQcW8a50OT3yeMnM3NB9Y2Ynd7Wn8iXARiV/IHoKvw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "dependencies": { + "@csstools/css-color-parser": "^2.0.0", + "@csstools/css-parser-algorithms": "^2.6.1", + "@csstools/css-tokenizer": "^2.2.4", + "@csstools/postcss-progressive-custom-properties": "^3.2.0", + "@csstools/utilities": "^1.0.0" + }, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-ic-unit": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@csstools/postcss-ic-unit/-/postcss-ic-unit-3.0.6.tgz", + "integrity": "sha512-fHaU9C/sZPauXMrzPitZ/xbACbvxbkPpHoUgB9Kw5evtsBWdVkVrajOyiT9qX7/c+G1yjApoQjP1fQatldsy9w==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "dependencies": { + "@csstools/postcss-progressive-custom-properties": "^3.2.0", + "@csstools/utilities": "^1.0.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-initial": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-initial/-/postcss-initial-1.0.1.tgz", + "integrity": "sha512-wtb+IbUIrIf8CrN6MLQuFR7nlU5C7PwuebfeEXfjthUha1+XZj2RVi+5k/lukToA24sZkYAiSJfHM8uG/UZIdg==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "engines": { + "node": "^14 || ^16 || >=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-is-pseudo-class": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@csstools/postcss-is-pseudo-class/-/postcss-is-pseudo-class-4.0.6.tgz", + "integrity": "sha512-HilOhAsMpFheMYkuaREZx+CGa4hsG6kQdzwXSsuqKDFzYz2eIMP213+3dH/vUbPXaWrzqLKr8m3i0dgYPoh7vg==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "dependencies": { + "@csstools/selector-specificity": "^3.0.3", + "postcss-selector-parser": "^6.0.13" + }, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-light-dark-function": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@csstools/postcss-light-dark-function/-/postcss-light-dark-function-1.0.3.tgz", + "integrity": "sha512-izW8hvhOqJlarLcGXO5PSylW9pQS3fytmhRdx2/e1oZFi15vs7ZShOHcREHJ3FfGdYqDA10cP9uhH0A3hmm1Rw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "dependencies": { + "@csstools/css-parser-algorithms": "^2.6.1", + "@csstools/css-tokenizer": "^2.2.4", + "@csstools/postcss-progressive-custom-properties": "^3.2.0", + "@csstools/utilities": "^1.0.0" + }, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-logical-float-and-clear": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-logical-float-and-clear/-/postcss-logical-float-and-clear-2.0.1.tgz", + "integrity": "sha512-SsrWUNaXKr+e/Uo4R/uIsqJYt3DaggIh/jyZdhy/q8fECoJSKsSMr7nObSLdvoULB69Zb6Bs+sefEIoMG/YfOA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "engines": { + "node": "^14 || ^16 || >=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-logical-overflow": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-logical-overflow/-/postcss-logical-overflow-1.0.1.tgz", + "integrity": "sha512-Kl4lAbMg0iyztEzDhZuQw8Sj9r2uqFDcU1IPl+AAt2nue8K/f1i7ElvKtXkjhIAmKiy5h2EY8Gt/Cqg0pYFDCw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "engines": { + "node": "^14 || ^16 || >=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-logical-overscroll-behavior": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-logical-overscroll-behavior/-/postcss-logical-overscroll-behavior-1.0.1.tgz", + "integrity": "sha512-+kHamNxAnX8ojPCtV8WPcUP3XcqMFBSDuBuvT6MHgq7oX4IQxLIXKx64t7g9LiuJzE7vd06Q9qUYR6bh4YnGpQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "engines": { + "node": "^14 || ^16 || >=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-logical-resize": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-logical-resize/-/postcss-logical-resize-2.0.1.tgz", + "integrity": "sha512-W5Gtwz7oIuFcKa5SmBjQ2uxr8ZoL7M2bkoIf0T1WeNqljMkBrfw1DDA8/J83k57NQ1kcweJEjkJ04pUkmyee3A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-logical-viewport-units": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@csstools/postcss-logical-viewport-units/-/postcss-logical-viewport-units-2.0.7.tgz", + "integrity": "sha512-L4G3zsp/bnU0+WXUyysihCUH14LkfMgUJsS9vKz3vCYbVobOTqQRoNXnEPpyNp8WYyolLqAWbGGJhVu8J6u2OQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "dependencies": { + "@csstools/css-tokenizer": "^2.2.4", + "@csstools/utilities": "^1.0.0" + }, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-media-minmax": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@csstools/postcss-media-minmax/-/postcss-media-minmax-1.1.4.tgz", + "integrity": "sha512-xl/PIO3TUbXO1ZA4SA6HCw+Q9UGe2cgeRKx3lHCzoNig2D4bT5vfVCOrwhxjUb09oHihc9eI3I0iIfVPiXaN1A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "dependencies": { + "@csstools/css-calc": "^1.2.0", + "@csstools/css-parser-algorithms": "^2.6.1", + "@csstools/css-tokenizer": "^2.2.4", + "@csstools/media-query-list-parser": "^2.1.9" + }, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-media-queries-aspect-ratio-number-values": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@csstools/postcss-media-queries-aspect-ratio-number-values/-/postcss-media-queries-aspect-ratio-number-values-2.0.7.tgz", + "integrity": "sha512-HBDAQw1K0NilcHGMUHv8jzf2mpOtcWTVKtuY3AeZ5TS1uyWWNVi5/yuA/tREPLU9WifNdqHQ+rfbsV/8zTIkTg==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "dependencies": { + "@csstools/css-parser-algorithms": "^2.6.1", + "@csstools/css-tokenizer": "^2.2.4", + "@csstools/media-query-list-parser": "^2.1.9" + }, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-nested-calc": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@csstools/postcss-nested-calc/-/postcss-nested-calc-3.0.2.tgz", + "integrity": "sha512-ySUmPyawiHSmBW/VI44+IObcKH0v88LqFe0d09Sb3w4B1qjkaROc6d5IA3ll9kjD46IIX/dbO5bwFN/swyoyZA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "dependencies": { + "@csstools/utilities": "^1.0.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-normalize-display-values": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@csstools/postcss-normalize-display-values/-/postcss-normalize-display-values-3.0.2.tgz", + "integrity": "sha512-fCapyyT/dUdyPtrelQSIV+d5HqtTgnNP/BEG9IuhgXHt93Wc4CfC1bQ55GzKAjWrZbgakMQ7MLfCXEf3rlZJOw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-oklab-function": { + "version": "3.0.14", + "resolved": "https://registry.npmjs.org/@csstools/postcss-oklab-function/-/postcss-oklab-function-3.0.14.tgz", + "integrity": "sha512-92xdpcfc2wB3z4+GftPA0PXMuGI/tRLw9Tc0+HzpaAHHxyLK6aCJtoQIcw0Ox/PthXtqXZn/3wWT/Idfe8I7Wg==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "dependencies": { + "@csstools/css-color-parser": "^2.0.0", + "@csstools/css-parser-algorithms": "^2.6.1", + "@csstools/css-tokenizer": "^2.2.4", + "@csstools/postcss-progressive-custom-properties": "^3.2.0", + "@csstools/utilities": "^1.0.0" + }, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-progressive-custom-properties": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-progressive-custom-properties/-/postcss-progressive-custom-properties-3.2.0.tgz", + "integrity": "sha512-BZlirVxCRgKlE7yVme+Xvif72eTn1MYXj8oZ4Knb+jwaH4u3AN1DjbhM7j86RP5vvuAOexJ4JwfifYYKWMN/QQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-relative-color-syntax": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/@csstools/postcss-relative-color-syntax/-/postcss-relative-color-syntax-2.0.14.tgz", + "integrity": "sha512-NlxgLjAjVCTUVGiWk8WNj3dKvux9eC6O5aLM3BmdA8UXEwBHYI9r4IqlanxG9PlcXnzhTUX6eZsqgmxwt4FPow==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "dependencies": { + "@csstools/css-color-parser": "^2.0.0", + "@csstools/css-parser-algorithms": "^2.6.1", + "@csstools/css-tokenizer": "^2.2.4", + "@csstools/postcss-progressive-custom-properties": "^3.2.0", + "@csstools/utilities": "^1.0.0" + }, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-scope-pseudo-class": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-scope-pseudo-class/-/postcss-scope-pseudo-class-3.0.1.tgz", + "integrity": "sha512-3ZFonK2gfgqg29gUJ2w7xVw2wFJ1eNWVDONjbzGkm73gJHVCYK5fnCqlLr+N+KbEfv2XbWAO0AaOJCFB6Fer6A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "dependencies": { + "postcss-selector-parser": "^6.0.13" + }, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-stepped-value-functions": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@csstools/postcss-stepped-value-functions/-/postcss-stepped-value-functions-3.0.6.tgz", + "integrity": "sha512-rnyp8tWRuBXERTHVdB5hjUlif5dQgPcyN+BX55wUnYpZ3LN9QPfK2Z3/HUZymwyou8Gg6vhd6X2W+g1pLq1jYg==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "dependencies": { + "@csstools/css-calc": "^1.2.0", + "@csstools/css-parser-algorithms": "^2.6.1", + "@csstools/css-tokenizer": "^2.2.4" + }, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-text-decoration-shorthand": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@csstools/postcss-text-decoration-shorthand/-/postcss-text-decoration-shorthand-3.0.6.tgz", + "integrity": "sha512-Q8HEu4AEiwNVZBD6+DpQ8M9SajpMow4+WtmndWIAv8qxDtDYL4JK1xXWkhOGk28PrcJawOvkrEZ8Ri59UN1TJw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "dependencies": { + "@csstools/color-helpers": "^4.2.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-trigonometric-functions": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@csstools/postcss-trigonometric-functions/-/postcss-trigonometric-functions-3.0.6.tgz", + "integrity": "sha512-i5Zd0bMJooZAn+ZcDmPij2WCkcOJJJ6opzK+QeDjxbMrYmoGQl0CY8FDHdeQyBF1Nly+Q0Fq3S7QfdNLKBBaCg==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "dependencies": { + "@csstools/css-calc": "^1.2.0", + "@csstools/css-parser-algorithms": "^2.6.1", + "@csstools/css-tokenizer": "^2.2.4" + }, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-unset-value": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-unset-value/-/postcss-unset-value-3.0.1.tgz", + "integrity": "sha512-dbDnZ2ja2U8mbPP0Hvmt2RMEGBiF1H7oY6HYSpjteXJGihYwgxgTr6KRbbJ/V6c+4wd51M+9980qG4gKVn5ttg==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "engines": { + "node": "^14 || ^16 || >=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/selector-resolve-nested": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@csstools/selector-resolve-nested/-/selector-resolve-nested-1.1.0.tgz", + "integrity": "sha512-uWvSaeRcHyeNenKg8tp17EVDRkpflmdyvbE0DHo6D/GdBb6PDnCYYU6gRpXhtICMGMcahQmj2zGxwFM/WC8hCg==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "engines": { + "node": "^14 || ^16 || >=18" + }, + "peerDependencies": { + "postcss-selector-parser": "^6.0.13" + } + }, + "node_modules/@csstools/selector-specificity": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-3.0.3.tgz", + "integrity": "sha512-KEPNw4+WW5AVEIyzC80rTbWEUatTW2lXpN8+8ILC8PiPeWPjwUzrPZDIOZ2wwqDmeqOYTdSGyL3+vE5GC3FB3Q==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "engines": { + "node": "^14 || ^16 || >=18" + }, + "peerDependencies": { + "postcss-selector-parser": "^6.0.13" + } + }, + "node_modules/@csstools/utilities": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@csstools/utilities/-/utilities-1.0.0.tgz", + "integrity": "sha512-tAgvZQe/t2mlvpNosA4+CkMiZ2azISW5WPAcdSalZlEjQvUfghHxfQcrCiK/7/CrfAWVxyM88kGFYO82heIGDg==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "engines": { + "node": "^14 || ^16 || >=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "dev": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@sindresorhus/merge-streams": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-2.3.0.tgz", + "integrity": "sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@tailwindcss/forms": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/@tailwindcss/forms/-/forms-0.5.7.tgz", + "integrity": "sha512-QE7X69iQI+ZXwldE+rzasvbJiyV/ju1FGHH0Qn2W3FKbuYtqp8LKcy6iSw79fVUT5/Vvf+0XgLCeYVG+UV6hOw==", + "dev": true, + "dependencies": { + "mini-svg-data-uri": "^1.2.3" + }, + "peerDependencies": { + "tailwindcss": ">=3.0.0 || >= 3.0.0-alpha.1" + } + }, + "node_modules/@trysound/sax": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", + "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", + "dev": true, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", + "dev": true + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/arg": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", + "dev": true + }, + "node_modules/autoprefixer": { + "version": "10.4.19", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.19.tgz", + "integrity": "sha512-BaENR2+zBZ8xXhM4pUaKUxlVdxZ0EZhjvbopwnXmxRUfqDmwSpC2lAi/QXvx7NRdPCo1WKEcEF6mV64si1z4Ew==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "browserslist": "^4.23.0", + "caniuse-lite": "^1.0.30001599", + "fraction.js": "^4.3.7", + "normalize-range": "^0.1.2", + "picocolors": "^1.0.0", + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" + }, + "engines": { + "node": "^10 || ^12 || >=14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "dev": true + }, + "node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.23.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz", + "integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001587", + "electron-to-chromium": "^1.4.668", + "node-releases": "^2.0.14", + "update-browserslist-db": "^1.0.13" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/camelcase-css": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", + "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/caniuse-api": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", + "integrity": "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==", + "dev": true, + "dependencies": { + "browserslist": "^4.0.0", + "caniuse-lite": "^1.0.0", + "lodash.memoize": "^4.1.2", + "lodash.uniq": "^4.5.0" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001612", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001612.tgz", + "integrity": "sha512-lFgnZ07UhaCcsSZgWW0K5j4e69dK1u/ltrL9lTUiFOwNHs12S3UMIEYgBV0Z6C6hRDev7iRnMzzYmKabYdXF9g==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ] + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/cliui/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/cliui/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/cliui/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/colord": { + "version": "2.9.3", + "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz", + "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==", + "dev": true + }, + "node_modules/commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/cross-env": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz", + "integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.1" + }, + "bin": { + "cross-env": "src/bin/cross-env.js", + "cross-env-shell": "src/bin/cross-env-shell.js" + }, + "engines": { + "node": ">=10.14", + "npm": ">=6", + "yarn": ">=1" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/css-blank-pseudo": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/css-blank-pseudo/-/css-blank-pseudo-6.0.2.tgz", + "integrity": "sha512-J/6m+lsqpKPqWHOifAFtKFeGLOzw3jR92rxQcwRUfA/eTuZzKfKlxOmYDx2+tqOPQAueNvBiY8WhAeHu5qNmTg==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "dependencies": { + "postcss-selector-parser": "^6.0.13" + }, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/css-declaration-sorter": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-7.2.0.tgz", + "integrity": "sha512-h70rUM+3PNFuaBDTLe8wF/cdWu+dOZmb7pJt8Z2sedYbAcQVQV/tEchueg3GWxwqS0cxtbxmaHEdkNACqcvsow==", + "dev": true, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "peerDependencies": { + "postcss": "^8.0.9" + } + }, + "node_modules/css-has-pseudo": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/css-has-pseudo/-/css-has-pseudo-6.0.3.tgz", + "integrity": "sha512-qIsDxK/z0byH/mpNsv5hzQ5NOl8m1FRmOLgZpx4bG5uYHnOlO2XafeMI4mFIgNSViHwoUWcxSJZyyijaAmbs+A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "dependencies": { + "@csstools/selector-specificity": "^3.0.3", + "postcss-selector-parser": "^6.0.13", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/css-prefers-color-scheme": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/css-prefers-color-scheme/-/css-prefers-color-scheme-9.0.1.tgz", + "integrity": "sha512-iFit06ochwCKPRiWagbTa1OAWCvWWVdEnIFd8BaRrgO8YrrNh4RAWUQTFcYX5tdFZgFl1DJ3iiULchZyEbnF4g==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "engines": { + "node": "^14 || ^16 || >=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/css-select": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", + "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", + "dev": true, + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css-tree": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz", + "integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==", + "dev": true, + "dependencies": { + "mdn-data": "2.0.30", + "source-map-js": "^1.0.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" + } + }, + "node_modules/css-what": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", + "dev": true, + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/cssdb": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/cssdb/-/cssdb-8.0.0.tgz", + "integrity": "sha512-hfpm8VXc7/dhcEWpLvKDLwImOSk1sa2DxL36OEiY/4h2MGfKjPYIMZo4hnEEl+TCJr2GwcX46jF5TafRASDe9w==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + } + ] + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true, + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/cssnano": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-7.0.1.tgz", + "integrity": "sha512-917Mej/4SdI7b55atsli3sU4MOJ9XDoKgnlCtQtXYj8XUFcM3riTuYHyqBBnnskawW+zWwp0KxJzpEUodlpqUg==", + "dev": true, + "dependencies": { + "cssnano-preset-default": "^7.0.1", + "lilconfig": "^3.1.1" + }, + "engines": { + "node": "^18.12.0 || ^20.9.0 || >=22.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/cssnano" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/cssnano-preset-default": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-7.0.1.tgz", + "integrity": "sha512-Fumyr+uZMcjYQeuHssAZxn0cKj3cdQc5GcxkBcmEzISGB+UW9CLNlU4tBOJbJGcPukFDlicG32eFbrc8K9V5pw==", + "dev": true, + "dependencies": { + "browserslist": "^4.23.0", + "css-declaration-sorter": "^7.2.0", + "cssnano-utils": "^5.0.0", + "postcss-calc": "^10.0.0", + "postcss-colormin": "^7.0.0", + "postcss-convert-values": "^7.0.0", + "postcss-discard-comments": "^7.0.0", + "postcss-discard-duplicates": "^7.0.0", + "postcss-discard-empty": "^7.0.0", + "postcss-discard-overridden": "^7.0.0", + "postcss-merge-longhand": "^7.0.0", + "postcss-merge-rules": "^7.0.0", + "postcss-minify-font-values": "^7.0.0", + "postcss-minify-gradients": "^7.0.0", + "postcss-minify-params": "^7.0.0", + "postcss-minify-selectors": "^7.0.0", + "postcss-normalize-charset": "^7.0.0", + "postcss-normalize-display-values": "^7.0.0", + "postcss-normalize-positions": "^7.0.0", + "postcss-normalize-repeat-style": "^7.0.0", + "postcss-normalize-string": "^7.0.0", + "postcss-normalize-timing-functions": "^7.0.0", + "postcss-normalize-unicode": "^7.0.0", + "postcss-normalize-url": "^7.0.0", + "postcss-normalize-whitespace": "^7.0.0", + "postcss-ordered-values": "^7.0.0", + "postcss-reduce-initial": "^7.0.0", + "postcss-reduce-transforms": "^7.0.0", + "postcss-svgo": "^7.0.0", + "postcss-unique-selectors": "^7.0.0" + }, + "engines": { + "node": "^18.12.0 || ^20.9.0 || >=22.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/cssnano-utils": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cssnano-utils/-/cssnano-utils-5.0.0.tgz", + "integrity": "sha512-Uij0Xdxc24L6SirFr25MlwC2rCFX6scyUmuKpzI+JQ7cyqDEwD42fJ0xfB3yLfOnRDU5LKGgjQ9FA6LYh76GWQ==", + "dev": true, + "engines": { + "node": "^18.12.0 || ^20.9.0 || >=22.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/csso": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/csso/-/csso-5.0.5.tgz", + "integrity": "sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==", + "dev": true, + "dependencies": { + "css-tree": "~2.2.0" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/csso/node_modules/css-tree": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.2.1.tgz", + "integrity": "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==", + "dev": true, + "dependencies": { + "mdn-data": "2.0.28", + "source-map-js": "^1.0.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/csso/node_modules/mdn-data": { + "version": "2.0.28", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.28.tgz", + "integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==", + "dev": true + }, + "node_modules/dependency-graph": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/dependency-graph/-/dependency-graph-0.11.0.tgz", + "integrity": "sha512-JeMq7fEshyepOWDfcfHK06N3MhyPhz++vtqWhMT5O9A3K42rdsEDpfdVqjaqaAhsw6a+ZqeDvQVtD0hFHQWrzg==", + "dev": true, + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/didyoumean": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", + "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", + "dev": true + }, + "node_modules/dlv": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", + "dev": true + }, + "node_modules/dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "dev": true, + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ] + }, + "node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "dev": true, + "dependencies": { + "domelementtype": "^2.3.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/domutils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz", + "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==", + "dev": true, + "dependencies": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true + }, + "node_modules/electron-to-chromium": { + "version": "1.4.748", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.748.tgz", + "integrity": "sha512-VWqjOlPZn70UZ8FTKUOkUvBLeTQ0xpty66qV0yJcAGY2/CthI4xyW9aEozRVtuwv3Kpf5xTesmJUcPwuJmgP4A==", + "dev": true + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "dev": true, + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/escalade": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", + "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fastq": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/foreground-child": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", + "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/fraction.js": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", + "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==", + "dev": true, + "engines": { + "node": "*" + }, + "funding": { + "type": "patreon", + "url": "https://github.com/sponsors/rawify" + } + }, + "node_modules/fs-extra": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", + "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-stdin": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-9.0.0.tgz", + "integrity": "sha512-dVKBjfWisLAicarI2Sf+JuBE/DghV4UzNAVe9yhEJuzeREd3JhOTE9cUaJTeSa77fsbQUK3pcOpJfM59+VKZaA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/glob": { + "version": "10.3.12", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.12.tgz", + "integrity": "sha512-TCNv8vJ+xz4QiqTpfOJA7HvYv+tNIRHKfUWw/q+v2jdgN4ebz+KY9tGx5J4rHP0o84mNP+ApH66HRX8us3Khqg==", + "dev": true, + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.6", + "minimatch": "^9.0.1", + "minipass": "^7.0.4", + "path-scurry": "^1.10.2" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/globby": { + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/globby/-/globby-14.0.1.tgz", + "integrity": "sha512-jOMLD2Z7MAhyG8aJpNOpmziMOP4rPLcc95oQPKXBazW82z+CEgPFBQvEpRUa1KeIMUJo4Wsm+q6uzO/Q/4BksQ==", + "dev": true, + "dependencies": { + "@sindresorhus/merge-streams": "^2.1.0", + "fast-glob": "^3.3.2", + "ignore": "^5.2.4", + "path-type": "^5.0.0", + "slash": "^5.1.0", + "unicorn-magic": "^0.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ignore": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", + "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-core-module": { + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", + "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", + "dev": true, + "dependencies": { + "hasown": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/jackspeak": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", + "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", + "dev": true, + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/jiti": { + "version": "1.21.0", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.0.tgz", + "integrity": "sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==", + "dev": true, + "bin": { + "jiti": "bin/jiti.js" + } + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/lilconfig": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.1.tgz", + "integrity": "sha512-O18pf7nyvHTckunPWCV1XUNXU1piu01y2b7ATJ0ppkUkk8ocqVWBrYjJBCwHDjD/ZWcfyrA0P4gKhzWGi5EINQ==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true + }, + "node_modules/lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", + "dev": true + }, + "node_modules/lodash.uniq": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", + "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==", + "dev": true + }, + "node_modules/lru-cache": { + "version": "10.2.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.1.tgz", + "integrity": "sha512-tS24spDe/zXhWbNPErCHs/AGOzbKGHT+ybSBqmdLm8WZ1xXLWvH8Qn71QPAlqVhd0qUTWjy+Kl9JmISgDdEjsA==", + "dev": true, + "engines": { + "node": "14 || >=16.14" + } + }, + "node_modules/mdn-data": { + "version": "2.0.30", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz", + "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==", + "dev": true + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, + "dependencies": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mini-svg-data-uri": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/mini-svg-data-uri/-/mini-svg-data-uri-1.4.4.tgz", + "integrity": "sha512-r9deDe9p5FJUPZAk3A59wGH7Ii9YrjjWw0jmw/liSbHl2CHiyXj6FcDXDu2K3TjVAXqiJdaw3xxwlZZr9E6nHg==", + "dev": true, + "bin": { + "mini-svg-data-uri": "cli.js" + } + }, + "node_modules/minimatch": { + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", + "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minipass": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "dev": true, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "dev": true, + "dependencies": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, + "node_modules/nanoid": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/node-releases": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", + "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", + "dev": true + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "dev": true, + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "node_modules/path-scurry": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.2.tgz", + "integrity": "sha512-7xTavNy5RQXnsjANvVvMkEjvloOinkAjv/Z6Ildz9v2RinZ4SBKTWFOVRbaF8p0vpHnyjV/UwNDdKuUv6M5qcA==", + "dev": true, + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-type": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-5.0.0.tgz", + "integrity": "sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pirates": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/postcss": { + "version": "8.4.38", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz", + "integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "nanoid": "^3.3.7", + "picocolors": "^1.0.0", + "source-map-js": "^1.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-attribute-case-insensitive": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/postcss-attribute-case-insensitive/-/postcss-attribute-case-insensitive-6.0.3.tgz", + "integrity": "sha512-KHkmCILThWBRtg+Jn1owTnHPnFit4OkqS+eKiGEOPIGke54DCeYGJ6r0Fx/HjfE9M9kznApCLcU0DvnPchazMQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "dependencies": { + "postcss-selector-parser": "^6.0.13" + }, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-calc": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-10.0.0.tgz", + "integrity": "sha512-OmjhudoNTP0QleZCwl1i6NeBwN+5MZbY5ersLZz69mjJiDVv/p57RjRuKDkHeDWr4T+S97wQfsqRTNoDHB2e3g==", + "dev": true, + "dependencies": { + "postcss-selector-parser": "^6.0.16", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^18.12 || ^20.9 || >=22.0" + }, + "peerDependencies": { + "postcss": "^8.4.38" + } + }, + "node_modules/postcss-clamp": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/postcss-clamp/-/postcss-clamp-4.1.0.tgz", + "integrity": "sha512-ry4b1Llo/9zz+PKC+030KUnPITTJAHeOwjfAyyB60eT0AorGLdzp52s31OsPRHRf8NchkgFoG2y6fCfn1IV1Ow==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": ">=7.6.0" + }, + "peerDependencies": { + "postcss": "^8.4.6" + } + }, + "node_modules/postcss-cli": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/postcss-cli/-/postcss-cli-11.0.0.tgz", + "integrity": "sha512-xMITAI7M0u1yolVcXJ9XTZiO9aO49mcoKQy6pCDFdMh9kGqhzLVpWxeD/32M/QBmkhcGypZFFOLNLmIW4Pg4RA==", + "dev": true, + "dependencies": { + "chokidar": "^3.3.0", + "dependency-graph": "^0.11.0", + "fs-extra": "^11.0.0", + "get-stdin": "^9.0.0", + "globby": "^14.0.0", + "picocolors": "^1.0.0", + "postcss-load-config": "^5.0.0", + "postcss-reporter": "^7.0.0", + "pretty-hrtime": "^1.0.3", + "read-cache": "^1.0.0", + "slash": "^5.0.0", + "yargs": "^17.0.0" + }, + "bin": { + "postcss": "index.js" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.0.0" + } + }, + "node_modules/postcss-color-functional-notation": { + "version": "6.0.9", + "resolved": "https://registry.npmjs.org/postcss-color-functional-notation/-/postcss-color-functional-notation-6.0.9.tgz", + "integrity": "sha512-8i/ofOArZ4fljp+3g+HI6Pok01Kb8YaSqInrJt2vMimEKrI0ZDNRLpH+wLhXBNu/Bi8zeWDvxhvCqsGSpu8E6Q==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "dependencies": { + "@csstools/css-color-parser": "^2.0.0", + "@csstools/css-parser-algorithms": "^2.6.1", + "@csstools/css-tokenizer": "^2.2.4", + "@csstools/postcss-progressive-custom-properties": "^3.2.0", + "@csstools/utilities": "^1.0.0" + }, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-color-hex-alpha": { + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/postcss-color-hex-alpha/-/postcss-color-hex-alpha-9.0.4.tgz", + "integrity": "sha512-XQZm4q4fNFqVCYMGPiBjcqDhuG7Ey2xrl99AnDJMyr5eDASsAGalndVgHZF8i97VFNy1GQeZc4q2ydagGmhelQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "dependencies": { + "@csstools/utilities": "^1.0.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-color-rebeccapurple": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/postcss-color-rebeccapurple/-/postcss-color-rebeccapurple-9.0.3.tgz", + "integrity": "sha512-ruBqzEFDYHrcVq3FnW3XHgwRqVMrtEPLBtD7K2YmsLKVc2jbkxzzNEctJKsPCpDZ+LeMHLKRDoSShVefGc+CkQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "dependencies": { + "@csstools/utilities": "^1.0.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-colormin": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-7.0.0.tgz", + "integrity": "sha512-5CN6fqtsEtEtwf3mFV3B4UaZnlYljPpzmGeDB4yCK067PnAtfLe9uX2aFZaEwxHE7HopG5rUkW8gyHrNAesHEg==", + "dev": true, + "dependencies": { + "browserslist": "^4.23.0", + "caniuse-api": "^3.0.0", + "colord": "^2.9.3", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^18.12.0 || ^20.9.0 || >=22.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-convert-values": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-7.0.0.tgz", + "integrity": "sha512-bMuzDgXBbFbByPgj+/r6va8zNuIDUaIIbvAFgdO1t3zdgJZ77BZvu6dfWyd6gHEJnYzmeVr9ayUsAQL3/qLJ0w==", + "dev": true, + "dependencies": { + "browserslist": "^4.23.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^18.12.0 || ^20.9.0 || >=22.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-custom-media": { + "version": "10.0.4", + "resolved": "https://registry.npmjs.org/postcss-custom-media/-/postcss-custom-media-10.0.4.tgz", + "integrity": "sha512-Ubs7O3wj2prghaKRa68VHBvuy3KnTQ0zbGwqDYY1mntxJD0QL2AeiAy+AMfl3HBedTCVr2IcFNktwty9YpSskA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "dependencies": { + "@csstools/cascade-layer-name-parser": "^1.0.9", + "@csstools/css-parser-algorithms": "^2.6.1", + "@csstools/css-tokenizer": "^2.2.4", + "@csstools/media-query-list-parser": "^2.1.9" + }, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-custom-properties": { + "version": "13.3.8", + "resolved": "https://registry.npmjs.org/postcss-custom-properties/-/postcss-custom-properties-13.3.8.tgz", + "integrity": "sha512-OP9yj4yXxYOiW2n2TRpnE7C0yePvBiZb72S22mZVNzZEObdTYFjNaX6oZO4R4E8Ie9RmC/Jxw8EKYSbLrC1EFA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "dependencies": { + "@csstools/cascade-layer-name-parser": "^1.0.9", + "@csstools/css-parser-algorithms": "^2.6.1", + "@csstools/css-tokenizer": "^2.2.4", + "@csstools/utilities": "^1.0.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-custom-selectors": { + "version": "7.1.8", + "resolved": "https://registry.npmjs.org/postcss-custom-selectors/-/postcss-custom-selectors-7.1.8.tgz", + "integrity": "sha512-fqDkGSEsO7+oQaqdRdR8nwwqH+N2uk6LE/2g4myVJJYz/Ly418lHKEleKTdV/GzjBjFcG4n0dbfuH/Pd2BE8YA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "dependencies": { + "@csstools/cascade-layer-name-parser": "^1.0.9", + "@csstools/css-parser-algorithms": "^2.6.1", + "@csstools/css-tokenizer": "^2.2.4", + "postcss-selector-parser": "^6.0.13" + }, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-dir-pseudo-class": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/postcss-dir-pseudo-class/-/postcss-dir-pseudo-class-8.0.1.tgz", + "integrity": "sha512-uULohfWBBVoFiZXgsQA24JV6FdKIidQ+ZqxOouhWwdE+qJlALbkS5ScB43ZTjPK+xUZZhlaO/NjfCt5h4IKUfw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "dependencies": { + "postcss-selector-parser": "^6.0.13" + }, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-discard-comments": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-7.0.0.tgz", + "integrity": "sha512-xpSdzRqYmy4YIVmjfGyYXKaI1SRnK6CTr+4Zmvyof8ANwvgfZgGdVtmgAvzh59gJm808mJCWQC9tFN0KF5dEXA==", + "dev": true, + "engines": { + "node": "^18.12.0 || ^20.9.0 || >=22.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-discard-duplicates": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-7.0.0.tgz", + "integrity": "sha512-bAnSuBop5LpAIUmmOSsuvtKAAKREB6BBIYStWUTGq8oG5q9fClDMMuY8i4UPI/cEcDx2TN+7PMnXYIId20UVDw==", + "dev": true, + "engines": { + "node": "^18.12.0 || ^20.9.0 || >=22.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-discard-empty": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-7.0.0.tgz", + "integrity": "sha512-e+QzoReTZ8IAwhnSdp/++7gBZ/F+nBq9y6PomfwORfP7q9nBpK5AMP64kOt0bA+lShBFbBDcgpJ3X4etHg4lzA==", + "dev": true, + "engines": { + "node": "^18.12.0 || ^20.9.0 || >=22.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-discard-overridden": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-7.0.0.tgz", + "integrity": "sha512-GmNAzx88u3k2+sBTZrJSDauR0ccpE24omTQCVmaTTZFz1du6AasspjaUPMJ2ud4RslZpoFKyf+6MSPETLojc6w==", + "dev": true, + "engines": { + "node": "^18.12.0 || ^20.9.0 || >=22.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-double-position-gradients": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/postcss-double-position-gradients/-/postcss-double-position-gradients-5.0.6.tgz", + "integrity": "sha512-QJ+089FKMaqDxOhhIHsJrh4IP7h4PIHNC5jZP5PMmnfUScNu8Hji2lskqpFWCvu+5sj+2EJFyzKd13sLEWOZmQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "dependencies": { + "@csstools/postcss-progressive-custom-properties": "^3.2.0", + "@csstools/utilities": "^1.0.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-focus-visible": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/postcss-focus-visible/-/postcss-focus-visible-9.0.1.tgz", + "integrity": "sha512-N2VQ5uPz3Z9ZcqI5tmeholn4d+1H14fKXszpjogZIrFbhaq0zNAtq8sAnw6VLiqGbL8YBzsnu7K9bBkTqaRimQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "dependencies": { + "postcss-selector-parser": "^6.0.13" + }, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-focus-within": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/postcss-focus-within/-/postcss-focus-within-8.0.1.tgz", + "integrity": "sha512-NFU3xcY/xwNaapVb+1uJ4n23XImoC86JNwkY/uduytSl2s9Ekc2EpzmRR63+ExitnW3Mab3Fba/wRPCT5oDILA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "dependencies": { + "postcss-selector-parser": "^6.0.13" + }, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-font-variant": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-font-variant/-/postcss-font-variant-5.0.0.tgz", + "integrity": "sha512-1fmkBaCALD72CK2a9i468mA/+tr9/1cBxRRMXOUaZqO43oWPR5imcyPjXwuv7PXbCid4ndlP5zWhidQVVa3hmA==", + "dev": true, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-gap-properties": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/postcss-gap-properties/-/postcss-gap-properties-5.0.1.tgz", + "integrity": "sha512-k2z9Cnngc24c0KF4MtMuDdToROYqGMMUQGcE6V0odwjHyOHtaDBlLeRBV70y9/vF7KIbShrTRZ70JjsI1BZyWw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "engines": { + "node": "^14 || ^16 || >=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-image-set-function": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/postcss-image-set-function/-/postcss-image-set-function-6.0.3.tgz", + "integrity": "sha512-i2bXrBYzfbRzFnm+pVuxVePSTCRiNmlfssGI4H0tJQvDue+yywXwUxe68VyzXs7cGtMaH6MCLY6IbCShrSroCw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "dependencies": { + "@csstools/utilities": "^1.0.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-import": { + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", + "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.0.0", + "read-cache": "^1.0.0", + "resolve": "^1.1.7" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "postcss": "^8.0.0" + } + }, + "node_modules/postcss-js": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz", + "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==", + "dev": true, + "dependencies": { + "camelcase-css": "^2.0.1" + }, + "engines": { + "node": "^12 || ^14 || >= 16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.4.21" + } + }, + "node_modules/postcss-lab-function": { + "version": "6.0.14", + "resolved": "https://registry.npmjs.org/postcss-lab-function/-/postcss-lab-function-6.0.14.tgz", + "integrity": "sha512-ddQS9FRWT8sfl4wfW0ae8fpP2JdLIuhC9pYpHq1077avjrLzg73T9IEVu5QmFa72nJhYFlO9CbqjcoSdEzfY9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "dependencies": { + "@csstools/css-color-parser": "^2.0.0", + "@csstools/css-parser-algorithms": "^2.6.1", + "@csstools/css-tokenizer": "^2.2.4", + "@csstools/postcss-progressive-custom-properties": "^3.2.0", + "@csstools/utilities": "^1.0.0" + }, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-load-config": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-5.0.3.tgz", + "integrity": "sha512-90pBBI5apUVruIEdCxZic93Wm+i9fTrp7TXbgdUCH+/L+2WnfpITSpq5dFU/IPvbv7aNiMlQISpUkAm3fEcvgQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "lilconfig": "^3.0.0", + "yaml": "^2.3.4" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "jiti": ">=1.21.0", + "postcss": ">=8.0.9" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + }, + "postcss": { + "optional": true + } + } + }, + "node_modules/postcss-logical": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/postcss-logical/-/postcss-logical-7.0.1.tgz", + "integrity": "sha512-8GwUQZE0ri0K0HJHkDv87XOLC8DE0msc+HoWLeKdtjDZEwpZ5xuK3QdV6FhmHSQW40LPkg43QzvATRAI3LsRkg==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-merge-longhand": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-7.0.0.tgz", + "integrity": "sha512-0X8I4/9+G03X5/5NnrfopG/YEln2XU8heDh7YqBaiq2SeaKIG3n66ShZPjIolmVuLBQ0BEm3yS8o1mlCLHdW7A==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0", + "stylehacks": "^7.0.0" + }, + "engines": { + "node": "^18.12.0 || ^20.9.0 || >=22.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-merge-rules": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-7.0.0.tgz", + "integrity": "sha512-Zty3VlOsD6VSjBMu6PiHCVpLegtBT/qtZRVBcSeyEZ6q1iU5qTYT0WtEoLRV+YubZZguS5/ycfP+NRiKfjv6aw==", + "dev": true, + "dependencies": { + "browserslist": "^4.23.0", + "caniuse-api": "^3.0.0", + "cssnano-utils": "^5.0.0", + "postcss-selector-parser": "^6.0.16" + }, + "engines": { + "node": "^18.12.0 || ^20.9.0 || >=22.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-minify-font-values": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-7.0.0.tgz", + "integrity": "sha512-2ckkZtgT0zG8SMc5aoNwtm5234eUx1GGFJKf2b1bSp8UflqaeFzR50lid4PfqVI9NtGqJ2J4Y7fwvnP/u1cQog==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^18.12.0 || ^20.9.0 || >=22.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-minify-gradients": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-7.0.0.tgz", + "integrity": "sha512-pdUIIdj/C93ryCHew0UgBnL2DtUS3hfFa5XtERrs4x+hmpMYGhbzo6l/Ir5de41O0GaKVpK1ZbDNXSY6GkXvtg==", + "dev": true, + "dependencies": { + "colord": "^2.9.3", + "cssnano-utils": "^5.0.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^18.12.0 || ^20.9.0 || >=22.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-minify-params": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-7.0.0.tgz", + "integrity": "sha512-XOJAuX8Q/9GT1sGxlUvaFEe2H9n50bniLZblXXsAT/BwSfFYvzSZeFG7uupwc0KbKpTnflnQ7aMwGzX6JUWliQ==", + "dev": true, + "dependencies": { + "browserslist": "^4.23.0", + "cssnano-utils": "^5.0.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^18.12.0 || ^20.9.0 || >=22.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-minify-selectors": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-7.0.0.tgz", + "integrity": "sha512-f00CExZhD6lNw2vTZbcnmfxVgaVKzUw6IRsIFX3JTT8GdsoABc1WnhhGwL1i8YPJ3sSWw39fv7XPtvLb+3Uitw==", + "dev": true, + "dependencies": { + "postcss-selector-parser": "^6.0.16" + }, + "engines": { + "node": "^18.12.0 || ^20.9.0 || >=22.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-nested": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.0.1.tgz", + "integrity": "sha512-mEp4xPMi5bSWiMbsgoPfcP74lsWLHkQbZc3sY+jWYd65CUwXrUaTp0fmNpa01ZcETKlIgUdFN/MpS2xZtqL9dQ==", + "dev": true, + "dependencies": { + "postcss-selector-parser": "^6.0.11" + }, + "engines": { + "node": ">=12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.2.14" + } + }, + "node_modules/postcss-nesting": { + "version": "12.1.2", + "resolved": "https://registry.npmjs.org/postcss-nesting/-/postcss-nesting-12.1.2.tgz", + "integrity": "sha512-FUmTHGDNundodutB4PUBxt/EPuhgtpk8FJGRsBhOuy+6FnkR2A8RZWIsyyy6XmhvX2DZQQWIkvu+HB4IbJm+Ew==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "dependencies": { + "@csstools/selector-resolve-nested": "^1.1.0", + "@csstools/selector-specificity": "^3.0.3", + "postcss-selector-parser": "^6.0.13" + }, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-normalize-charset": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-7.0.0.tgz", + "integrity": "sha512-ABisNUXMeZeDNzCQxPxBCkXexvBrUHV+p7/BXOY+ulxkcjUZO0cp8ekGBwvIh2LbCwnWbyMPNJVtBSdyhM2zYQ==", + "dev": true, + "engines": { + "node": "^18.12.0 || ^20.9.0 || >=22.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-normalize-display-values": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-7.0.0.tgz", + "integrity": "sha512-lnFZzNPeDf5uGMPYgGOw7v0BfB45+irSRz9gHQStdkkhiM0gTfvWkWB5BMxpn0OqgOQuZG/mRlZyJxp0EImr2Q==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^18.12.0 || ^20.9.0 || >=22.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-normalize-positions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-7.0.0.tgz", + "integrity": "sha512-I0yt8wX529UKIGs2y/9Ybs2CelSvItfmvg/DBIjTnoUSrPxSV7Z0yZ8ShSVtKNaV/wAY+m7bgtyVQLhB00A1NQ==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^18.12.0 || ^20.9.0 || >=22.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-normalize-repeat-style": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-7.0.0.tgz", + "integrity": "sha512-o3uSGYH+2q30ieM3ppu9GTjSXIzOrRdCUn8UOMGNw7Af61bmurHTWI87hRybrP6xDHvOe5WlAj3XzN6vEO8jLw==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^18.12.0 || ^20.9.0 || >=22.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-normalize-string": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-7.0.0.tgz", + "integrity": "sha512-w/qzL212DFVOpMy3UGyxrND+Kb0fvCiBBujiaONIihq7VvtC7bswjWgKQU/w4VcRyDD8gpfqUiBQ4DUOwEJ6Qg==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^18.12.0 || ^20.9.0 || >=22.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-normalize-timing-functions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-7.0.0.tgz", + "integrity": "sha512-tNgw3YV0LYoRwg43N3lTe3AEWZ66W7Dh7lVEpJbHoKOuHc1sLrzMLMFjP8SNULHaykzsonUEDbKedv8C+7ej6g==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^18.12.0 || ^20.9.0 || >=22.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-normalize-unicode": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-7.0.0.tgz", + "integrity": "sha512-OnKV52/VFFDAim4n0pdI+JAhsolLBdnCKxE6VV5lW5Q/JeVGFN8UM8ur6/A3EAMLsT1ZRm3fDHh/rBoBQpqi2w==", + "dev": true, + "dependencies": { + "browserslist": "^4.23.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^18.12.0 || ^20.9.0 || >=22.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-normalize-url": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-7.0.0.tgz", + "integrity": "sha512-+d7+PpE+jyPX1hDQZYG+NaFD+Nd2ris6r8fPTBAjE8z/U41n/bib3vze8x7rKs5H1uEw5ppe9IojewouHk0klQ==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^18.12.0 || ^20.9.0 || >=22.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-normalize-whitespace": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-7.0.0.tgz", + "integrity": "sha512-37/toN4wwZErqohedXYqWgvcHUGlT8O/m2jVkAfAe9Bd4MzRqlBmXrJRePH0e9Wgnz2X7KymTgTOaaFizQe3AQ==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^18.12.0 || ^20.9.0 || >=22.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-opacity-percentage": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postcss-opacity-percentage/-/postcss-opacity-percentage-2.0.0.tgz", + "integrity": "sha512-lyDrCOtntq5Y1JZpBFzIWm2wG9kbEdujpNt4NLannF+J9c8CgFIzPa80YQfdza+Y+yFfzbYj/rfoOsYsooUWTQ==", + "dev": true, + "funding": [ + { + "type": "kofi", + "url": "https://ko-fi.com/mrcgrtz" + }, + { + "type": "liberapay", + "url": "https://liberapay.com/mrcgrtz" + } + ], + "engines": { + "node": "^14 || ^16 || >=18" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-ordered-values": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-7.0.0.tgz", + "integrity": "sha512-KROvC63A8UQW1eYDljQe1dtwc1E/M+mMwDT6z7khV/weHYLWTghaLRLunU7x1xw85lWFwVZOAGakxekYvKV+0w==", + "dev": true, + "dependencies": { + "cssnano-utils": "^5.0.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^18.12.0 || ^20.9.0 || >=22.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-overflow-shorthand": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/postcss-overflow-shorthand/-/postcss-overflow-shorthand-5.0.1.tgz", + "integrity": "sha512-XzjBYKLd1t6vHsaokMV9URBt2EwC9a7nDhpQpjoPk2HRTSQfokPfyAS/Q7AOrzUu6q+vp/GnrDBGuj/FCaRqrQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-page-break": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/postcss-page-break/-/postcss-page-break-3.0.4.tgz", + "integrity": "sha512-1JGu8oCjVXLa9q9rFTo4MbeeA5FMe00/9C7lN4va606Rdb+HkxXtXsmEDrIraQ11fGz/WvKWa8gMuCKkrXpTsQ==", + "dev": true, + "peerDependencies": { + "postcss": "^8" + } + }, + "node_modules/postcss-place": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/postcss-place/-/postcss-place-9.0.1.tgz", + "integrity": "sha512-JfL+paQOgRQRMoYFc2f73pGuG/Aw3tt4vYMR6UA3cWVMxivviPTnMFnFTczUJOA4K2Zga6xgQVE+PcLs64WC8Q==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-preset-env": { + "version": "9.5.9", + "resolved": "https://registry.npmjs.org/postcss-preset-env/-/postcss-preset-env-9.5.9.tgz", + "integrity": "sha512-W+WgDH1MOWLT3Fsvknd45pzGMQ8Sp3fmt94Pxeik3Zkqfhw2XUDF8FehfV3Naxw4l/NrKPWLtltPJYVnpjMmfw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "dependencies": { + "@csstools/postcss-cascade-layers": "^4.0.4", + "@csstools/postcss-color-function": "^3.0.14", + "@csstools/postcss-color-mix-function": "^2.0.14", + "@csstools/postcss-exponential-functions": "^1.0.5", + "@csstools/postcss-font-format-keywords": "^3.0.2", + "@csstools/postcss-gamut-mapping": "^1.0.7", + "@csstools/postcss-gradients-interpolation-method": "^4.0.15", + "@csstools/postcss-hwb-function": "^3.0.13", + "@csstools/postcss-ic-unit": "^3.0.6", + "@csstools/postcss-initial": "^1.0.1", + "@csstools/postcss-is-pseudo-class": "^4.0.6", + "@csstools/postcss-light-dark-function": "^1.0.3", + "@csstools/postcss-logical-float-and-clear": "^2.0.1", + "@csstools/postcss-logical-overflow": "^1.0.1", + "@csstools/postcss-logical-overscroll-behavior": "^1.0.1", + "@csstools/postcss-logical-resize": "^2.0.1", + "@csstools/postcss-logical-viewport-units": "^2.0.7", + "@csstools/postcss-media-minmax": "^1.1.4", + "@csstools/postcss-media-queries-aspect-ratio-number-values": "^2.0.7", + "@csstools/postcss-nested-calc": "^3.0.2", + "@csstools/postcss-normalize-display-values": "^3.0.2", + "@csstools/postcss-oklab-function": "^3.0.14", + "@csstools/postcss-progressive-custom-properties": "^3.2.0", + "@csstools/postcss-relative-color-syntax": "^2.0.14", + "@csstools/postcss-scope-pseudo-class": "^3.0.1", + "@csstools/postcss-stepped-value-functions": "^3.0.6", + "@csstools/postcss-text-decoration-shorthand": "^3.0.6", + "@csstools/postcss-trigonometric-functions": "^3.0.6", + "@csstools/postcss-unset-value": "^3.0.1", + "autoprefixer": "^10.4.19", + "browserslist": "^4.22.3", + "css-blank-pseudo": "^6.0.2", + "css-has-pseudo": "^6.0.3", + "css-prefers-color-scheme": "^9.0.1", + "cssdb": "^8.0.0", + "postcss-attribute-case-insensitive": "^6.0.3", + "postcss-clamp": "^4.1.0", + "postcss-color-functional-notation": "^6.0.9", + "postcss-color-hex-alpha": "^9.0.4", + "postcss-color-rebeccapurple": "^9.0.3", + "postcss-custom-media": "^10.0.4", + "postcss-custom-properties": "^13.3.8", + "postcss-custom-selectors": "^7.1.8", + "postcss-dir-pseudo-class": "^8.0.1", + "postcss-double-position-gradients": "^5.0.6", + "postcss-focus-visible": "^9.0.1", + "postcss-focus-within": "^8.0.1", + "postcss-font-variant": "^5.0.0", + "postcss-gap-properties": "^5.0.1", + "postcss-image-set-function": "^6.0.3", + "postcss-lab-function": "^6.0.14", + "postcss-logical": "^7.0.1", + "postcss-nesting": "^12.1.2", + "postcss-opacity-percentage": "^2.0.0", + "postcss-overflow-shorthand": "^5.0.1", + "postcss-page-break": "^3.0.4", + "postcss-place": "^9.0.1", + "postcss-pseudo-class-any-link": "^9.0.2", + "postcss-replace-overflow-wrap": "^4.0.0", + "postcss-selector-not": "^7.0.2" + }, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-pseudo-class-any-link": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/postcss-pseudo-class-any-link/-/postcss-pseudo-class-any-link-9.0.2.tgz", + "integrity": "sha512-HFSsxIqQ9nA27ahyfH37cRWGk3SYyQLpk0LiWw/UGMV4VKT5YG2ONee4Pz/oFesnK0dn2AjcyequDbIjKJgB0g==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "dependencies": { + "postcss-selector-parser": "^6.0.13" + }, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-reduce-initial": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-7.0.0.tgz", + "integrity": "sha512-iqGgmBxY9LrblZ0BKLjmrA1mC/cf9A/wYCCqSmD6tMi+xAyVl0+DfixZIHSVDMbCPRPjNmVF0DFGth/IDGelFQ==", + "dev": true, + "dependencies": { + "browserslist": "^4.23.0", + "caniuse-api": "^3.0.0" + }, + "engines": { + "node": "^18.12.0 || ^20.9.0 || >=22.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-reduce-transforms": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-7.0.0.tgz", + "integrity": "sha512-pnt1HKKZ07/idH8cpATX/ujMbtOGhUfE+m8gbqwJE05aTaNw8gbo34a2e3if0xc0dlu75sUOiqvwCGY3fzOHew==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^18.12.0 || ^20.9.0 || >=22.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-replace-overflow-wrap": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-replace-overflow-wrap/-/postcss-replace-overflow-wrap-4.0.0.tgz", + "integrity": "sha512-KmF7SBPphT4gPPcKZc7aDkweHiKEEO8cla/GjcBK+ckKxiZslIu3C4GCRW3DNfL0o7yW7kMQu9xlZ1kXRXLXtw==", + "dev": true, + "peerDependencies": { + "postcss": "^8.0.3" + } + }, + "node_modules/postcss-reporter": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/postcss-reporter/-/postcss-reporter-7.1.0.tgz", + "integrity": "sha512-/eoEylGWyy6/DOiMP5lmFRdmDKThqgn7D6hP2dXKJI/0rJSO1ADFNngZfDzxL0YAxFvws+Rtpuji1YIHj4mySA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "picocolors": "^1.0.0", + "thenby": "^1.3.4" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-selector-not": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/postcss-selector-not/-/postcss-selector-not-7.0.2.tgz", + "integrity": "sha512-/SSxf/90Obye49VZIfc0ls4H0P6i6V1iHv0pzZH8SdgvZOPFkF37ef1r5cyWcMflJSFJ5bfuoluTnFnBBFiuSA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "dependencies": { + "postcss-selector-parser": "^6.0.13" + }, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.0.16", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.16.tgz", + "integrity": "sha512-A0RVJrX+IUkVZbW3ClroRWurercFhieevHB38sr2+l9eUClMqome3LmEmnhlNy+5Mr2EYN6B2Kaw9wYdd+VHiw==", + "dev": true, + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-svgo": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-7.0.0.tgz", + "integrity": "sha512-Xj5DRdvA97yRy3wjbCH2NKXtDUwEnph6EHr5ZXszsBVKCNrKXYBjzAXqav7/Afz5WwJ/1peZoTguCEJIg7ytmA==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0", + "svgo": "^3.2.0" + }, + "engines": { + "node": "^18.12.0 || ^20.9.0 || >= 18" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-unique-selectors": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-7.0.0.tgz", + "integrity": "sha512-NYFqcft7vVQMZlQPsMdMPy+qU/zDpy95Malpw4GeA9ZZjM6dVXDshXtDmLc0m4WCD6XeZCJqjTfPT1USsdt+rA==", + "dev": true, + "dependencies": { + "postcss-selector-parser": "^6.0.16" + }, + "engines": { + "node": "^18.12.0 || ^20.9.0 || >=22.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true + }, + "node_modules/pretty-hrtime": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", + "integrity": "sha512-66hKPCr+72mlfiSjlEB1+45IjXSqvVAIy6mocupoww4tBFE9R9IhwwUGoI4G++Tc9Aq+2rxOt0RFU6gPcrte0A==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/read-cache": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", + "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", + "dev": true, + "dependencies": { + "pify": "^2.3.0" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "dev": true, + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/slash": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", + "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", + "dev": true, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/source-map-js": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", + "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/string-width-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/stylehacks": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-7.0.0.tgz", + "integrity": "sha512-47Nw4pQ6QJb4CA6dzF2m9810sjQik4dfk4UwAm5wlwhrW3syzZKF8AR4/cfO3Cr6lsFgAoznQq0Wg57qhjTA2A==", + "dev": true, + "dependencies": { + "browserslist": "^4.23.0", + "postcss-selector-parser": "^6.0.16" + }, + "engines": { + "node": "^18.12.0 || ^20.9.0 || >=22.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/sucrase": { + "version": "3.35.0", + "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", + "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.2", + "commander": "^4.0.0", + "glob": "^10.3.10", + "lines-and-columns": "^1.1.6", + "mz": "^2.7.0", + "pirates": "^4.0.1", + "ts-interface-checker": "^0.1.9" + }, + "bin": { + "sucrase": "bin/sucrase", + "sucrase-node": "bin/sucrase-node" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/svgo": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-3.2.0.tgz", + "integrity": "sha512-4PP6CMW/V7l/GmKRKzsLR8xxjdHTV4IMvhTnpuHwwBazSIlw5W/5SmPjN8Dwyt7lKbSJrRDgp4t9ph0HgChFBQ==", + "dev": true, + "dependencies": { + "@trysound/sax": "0.2.0", + "commander": "^7.2.0", + "css-select": "^5.1.0", + "css-tree": "^2.3.1", + "css-what": "^6.1.0", + "csso": "^5.0.5", + "picocolors": "^1.0.0" + }, + "bin": { + "svgo": "bin/svgo" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/svgo" + } + }, + "node_modules/svgo/node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "dev": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/tailwindcss": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.3.tgz", + "integrity": "sha512-U7sxQk/n397Bmx4JHbJx/iSOOv5G+II3f1kpLpY2QeUv5DcPdcTsYLlusZfq1NthHS1c1cZoyFmmkex1rzke0A==", + "dev": true, + "dependencies": { + "@alloc/quick-lru": "^5.2.0", + "arg": "^5.0.2", + "chokidar": "^3.5.3", + "didyoumean": "^1.2.2", + "dlv": "^1.1.3", + "fast-glob": "^3.3.0", + "glob-parent": "^6.0.2", + "is-glob": "^4.0.3", + "jiti": "^1.21.0", + "lilconfig": "^2.1.0", + "micromatch": "^4.0.5", + "normalize-path": "^3.0.0", + "object-hash": "^3.0.0", + "picocolors": "^1.0.0", + "postcss": "^8.4.23", + "postcss-import": "^15.1.0", + "postcss-js": "^4.0.1", + "postcss-load-config": "^4.0.1", + "postcss-nested": "^6.0.1", + "postcss-selector-parser": "^6.0.11", + "resolve": "^1.22.2", + "sucrase": "^3.32.0" + }, + "bin": { + "tailwind": "lib/cli.js", + "tailwindcss": "lib/cli.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tailwindcss/node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/tailwindcss/node_modules/lilconfig": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", + "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/tailwindcss/node_modules/postcss-load-config": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz", + "integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "lilconfig": "^3.0.0", + "yaml": "^2.3.4" + }, + "engines": { + "node": ">= 14" + }, + "peerDependencies": { + "postcss": ">=8.0.9", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "postcss": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "node_modules/tailwindcss/node_modules/postcss-load-config/node_modules/lilconfig": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.1.tgz", + "integrity": "sha512-O18pf7nyvHTckunPWCV1XUNXU1piu01y2b7ATJ0ppkUkk8ocqVWBrYjJBCwHDjD/ZWcfyrA0P4gKhzWGi5EINQ==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" + } + }, + "node_modules/thenby": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/thenby/-/thenby-1.3.4.tgz", + "integrity": "sha512-89Gi5raiWA3QZ4b2ePcEwswC3me9JIg+ToSgtE0JWeCynLnLxNr/f9G+xfo9K+Oj4AFdom8YNJjibIARTJmapQ==", + "dev": true + }, + "node_modules/thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "dev": true, + "dependencies": { + "any-promise": "^1.0.0" + } + }, + "node_modules/thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", + "dev": true, + "dependencies": { + "thenify": ">= 3.1.0 < 4" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/ts-interface-checker": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", + "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", + "dev": true + }, + "node_modules/unicorn-magic": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.1.0.tgz", + "integrity": "sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", + "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/wrap-ansi-cjs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yaml": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.1.tgz", + "integrity": "sha512-pIXzoImaqmfOrL7teGUBt/T7ZDnyeGBWyXQBvOVhLkWLN37GXv8NMLK406UY6dS51JfcQHsmcW5cJ441bHg6Lg==", + "dev": true, + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/yargs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + } + } +} diff --git a/src/App/package.json b/src/App/package.json new file mode 100644 index 0000000..84572a7 --- /dev/null +++ b/src/App/package.json @@ -0,0 +1,18 @@ +{ + "private": true, + "type": "module", + "browserslist": [ + "defaults and not dead", + "fully supports wasm", + "fully supports es6-module" + ], + "devDependencies": { + "@tailwindcss/forms": "^0.5.7", + "cross-env": "^7.0.3", + "cssnano": "^7.0.1", + "postcss": "^8.4.38", + "postcss-cli": "^11.0.0", + "postcss-preset-env": "^9.5.9", + "tailwindcss": "^3.4.3" + } +} \ No newline at end of file diff --git a/src/App/packages.lock.json b/src/App/packages.lock.json new file mode 100644 index 0000000..984900b --- /dev/null +++ b/src/App/packages.lock.json @@ -0,0 +1,412 @@ +{ + "version": 1, + "dependencies": { + "net8.0": { + "Microsoft.AspNetCore.Components.WebAssembly": { + "type": "Direct", + "requested": "[8.0.4, )", + "resolved": "8.0.4", + "contentHash": "4mi1GyihE1R9BocAc5ZUeYZN/G2cFfoGibb6H+yQ7xXk3ec7cvqkjamdnXH2EwsikS+hX44pgirtiwUHDUw1uw==", + "dependencies": { + "Microsoft.AspNetCore.Components.Web": "8.0.4", + "Microsoft.Extensions.Configuration.Binder": "8.0.1", + "Microsoft.Extensions.Configuration.Json": "8.0.0", + "Microsoft.Extensions.Logging": "8.0.0", + "Microsoft.JSInterop.WebAssembly": "8.0.4" + } + }, + "Microsoft.AspNetCore.SignalR.Client": { + "type": "Direct", + "requested": "[8.0.4, )", + "resolved": "8.0.4", + "contentHash": "HPM5/ifdz4PvK6W3t7CNHgV69MPPrS75tLD9HUYFRlwGmvbVPYbsgES2b7wmnvZEsaGlEBNOdw//xU1jK4FM0w==", + "dependencies": { + "Microsoft.AspNetCore.Http.Connections.Client": "8.0.4", + "Microsoft.AspNetCore.SignalR.Client.Core": "8.0.4" + } + }, + "Microsoft.AspNetCore.SignalR.Protocols.MessagePack": { + "type": "Direct", + "requested": "[8.0.4, )", + "resolved": "8.0.4", + "contentHash": "Zr+ur9AHHLuKWbp1b2Tw/evvY41xt2Dar5zEmtfYg0vO/ztU4CBLCDdXvB01o9Dtb0bHoQ+25xwF11ur08/l1g==", + "dependencies": { + "MessagePack": "2.5.108", + "Microsoft.AspNetCore.SignalR.Common": "8.0.4" + } + }, + "Microsoft.CodeAnalysis.NetAnalyzers": { + "type": "Direct", + "requested": "[8.0.0, )", + "resolved": "8.0.0", + "contentHash": "DxiTgkCl3CGq1rYmBX2wjY7XGbxiBdL4J+/AJIAFLKy5z70NxhnVRnPghnicXZ8oF6JKVXlW3xwznRbI3ioEKg==" + }, + "Microsoft.NET.ILLink.Tasks": { + "type": "Direct", + "requested": "[8.0.4, )", + "resolved": "8.0.4", + "contentHash": "PZb5nfQ+U19nhnmnR9T1jw+LTmozhuG2eeuzuW5A7DqxD/UXW2ucjmNJqnqOuh8rdPzM3MQXoF8AfFCedJdCUw==" + }, + "Microsoft.SourceLink.GitHub": { + "type": "Direct", + "requested": "[8.0.0, )", + "resolved": "8.0.0", + "contentHash": "G5q7OqtwIyGTkeIOAc3u2ZuV/kicQaec5EaRnc0pIeSnh9LUjj+PYQrJYBURvDt7twGl2PKA7nSN0kz1Zw5bnQ==", + "dependencies": { + "Microsoft.Build.Tasks.Git": "8.0.0", + "Microsoft.SourceLink.Common": "8.0.0" + } + }, + "MinVer": { + "type": "Direct", + "requested": "[5.0.0, )", + "resolved": "5.0.0", + "contentHash": "ybkgpQMtt0Fo91l5rYtE3TZtD+Nmy5Ko091xvfXXOosQdMi30XO2EZ2+ShZt89gdu7RMmJqZaJ+e1q6d+6+KNw==" + }, + "Nito.AsyncEx.Coordination": { + "type": "Direct", + "requested": "[5.1.2, )", + "resolved": "5.1.2", + "contentHash": "QMyUfsaxov//0ZMbOHWr9hJaBFteZd66DV1ay4J5wRODDb8+K/uHC7+3VsOflo6SVw/29mu8OWZp8vMDSuzc0w==", + "dependencies": { + "Nito.AsyncEx.Tasks": "5.1.2", + "Nito.Collections.Deque": "1.1.1" + } + }, + "MessagePack": { + "type": "Transitive", + "resolved": "2.5.108", + "contentHash": "kcVRbdWP3xNWLZmmpm4DFO+kuXf6mUR2mHZ27WoZIEFIv9hazuUd80injXhNrZnlq/FklAdCsLOil5M76I4Ndg==", + "dependencies": { + "MessagePack.Annotations": "2.5.108", + "Microsoft.NET.StringTools": "17.4.0", + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + }, + "MessagePack.Annotations": { + "type": "Transitive", + "resolved": "2.5.108", + "contentHash": "28aNCvfJClgwaKr26gf2S6LT+C1PNyPxiG+ihYpy8uCJsRLJEDoCt2I0Uk5hqOPQ8P8hI0ESy520oMkZkPmsOQ==" + }, + "Microsoft.AspNetCore.Authorization": { + "type": "Transitive", + "resolved": "8.0.4", + "contentHash": "dzYUHvqyavBiYVd5BZNAgV5rT+DC4HyIWPnbeYgxQNBYOFomvvwzPfidQf1Ld/HhkXhEj3tlzqNb4gy2P2ukUg==", + "dependencies": { + "Microsoft.AspNetCore.Metadata": "8.0.4", + "Microsoft.Extensions.Logging.Abstractions": "8.0.1", + "Microsoft.Extensions.Options": "8.0.2" + } + }, + "Microsoft.AspNetCore.Components": { + "type": "Transitive", + "resolved": "8.0.4", + "contentHash": "ExTJT1u3QCTKaq2LjazkoHMNVlz0Q93A4ei5Zqd38bj3hggpShi4A/U22zk1LOmT0eUE5WklOBMpKZMg+T6Veg==", + "dependencies": { + "Microsoft.AspNetCore.Authorization": "8.0.4", + "Microsoft.AspNetCore.Components.Analyzers": "8.0.4" + } + }, + "Microsoft.AspNetCore.Components.Analyzers": { + "type": "Transitive", + "resolved": "8.0.4", + "contentHash": "kEvEOOkgN8uLjP2PMR481yxSjUsyGLaehHSD3HWjboNsXA5++7Hxn83LRdVri9/0rlY2zS/dP9oGHZpgxYu2iQ==" + }, + "Microsoft.AspNetCore.Components.Forms": { + "type": "Transitive", + "resolved": "8.0.4", + "contentHash": "I/kttR/nmRZTc+bsetYnvbkVzHgsJXrWKxHo30vGvQV+dTeur9LV2g2TvyLerpWL9OFbNWgpTGBUwgX1IW/0Zw==", + "dependencies": { + "Microsoft.AspNetCore.Components": "8.0.4" + } + }, + "Microsoft.AspNetCore.Components.Web": { + "type": "Transitive", + "resolved": "8.0.4", + "contentHash": "K9zcUkciMHmPjYdaB417xlG9Srv2udLT5j7CIAN92H5KNLH1ItIGIEIIUMJT3r+2Ma3ZLZO0eddEbR+Z59MbOQ==", + "dependencies": { + "Microsoft.AspNetCore.Components": "8.0.4", + "Microsoft.AspNetCore.Components.Forms": "8.0.4", + "Microsoft.Extensions.DependencyInjection": "8.0.0", + "Microsoft.Extensions.Primitives": "8.0.0", + "Microsoft.JSInterop": "8.0.4", + "System.IO.Pipelines": "8.0.0" + } + }, + "Microsoft.AspNetCore.Connections.Abstractions": { + "type": "Transitive", + "resolved": "8.0.4", + "contentHash": "pvO0JgjrNOas+WzmHxqawTv64lwTy1zbGm4WQY7OOd/OfKMw8LaoNEtn9jsAfiKUkt3lYK8kOL8Uy9XyyTCUwg==", + "dependencies": { + "Microsoft.Extensions.Features": "8.0.4", + "System.IO.Pipelines": "8.0.0" + } + }, + "Microsoft.AspNetCore.Http.Connections.Client": { + "type": "Transitive", + "resolved": "8.0.4", + "contentHash": "Tl9Hf+ftWZeKDGJpQOMwDgev7EXiiqk71NvoGDNhAYhYJMpoyf4591aINACAPSZ3zWNs4cqKIm8YQ5eG1slf5Q==", + "dependencies": { + "Microsoft.AspNetCore.Http.Connections.Common": "8.0.4", + "Microsoft.Extensions.Logging.Abstractions": "8.0.1", + "Microsoft.Extensions.Options": "8.0.2" + } + }, + "Microsoft.AspNetCore.Http.Connections.Common": { + "type": "Transitive", + "resolved": "8.0.4", + "contentHash": "SG02A6/ZET3sCW/PiJumg3q4yZdBZeMetdy/ebS4ZcmFPr+yI9sSmLAw9MHZVNNxxBWM5VuLg463YwlXoxhJHQ==", + "dependencies": { + "Microsoft.AspNetCore.Connections.Abstractions": "8.0.4" + } + }, + "Microsoft.AspNetCore.Metadata": { + "type": "Transitive", + "resolved": "8.0.4", + "contentHash": "TG3JhI7dkDCIoxZ3TL/5yptLYLg56w1f4jE8GSYnZXSso1xY5JKKCxObK+xKQJU5kZir30+QUGX1WpbC1kDcow==" + }, + "Microsoft.AspNetCore.SignalR.Client.Core": { + "type": "Transitive", + "resolved": "8.0.4", + "contentHash": "w8eaEHS6Qn0VALv3G7EuLg/i5WInxt2Jps4IbvB0u61l9GaTAOGw0Xx1G+0UJgWwd2RZoaJXqMr748TuSpxm6g==", + "dependencies": { + "Microsoft.AspNetCore.SignalR.Common": "8.0.4", + "Microsoft.AspNetCore.SignalR.Protocols.Json": "8.0.4", + "Microsoft.Extensions.DependencyInjection": "8.0.0", + "Microsoft.Extensions.Logging": "8.0.0", + "System.Threading.Channels": "8.0.0" + } + }, + "Microsoft.AspNetCore.SignalR.Common": { + "type": "Transitive", + "resolved": "8.0.4", + "contentHash": "vsoXzcAibrem3/qWSpZ9Q/Wc/4UpFdXtsNTBMAmltnQPGR07qa7Pzgrc7K9pT/gEkFR5DkFKkEOzgCkNBDUE+g==", + "dependencies": { + "Microsoft.AspNetCore.Connections.Abstractions": "8.0.4", + "Microsoft.Extensions.Options": "8.0.2" + } + }, + "Microsoft.AspNetCore.SignalR.Protocols.Json": { + "type": "Transitive", + "resolved": "8.0.4", + "contentHash": "9X4TnAZTGMVzH7DghV7AWXX5r8UO7RpSJAPxfd9lTu3GChEyUpppKIJMaOKpseplnlRxOedve8UPdjx5ks06vA==", + "dependencies": { + "Microsoft.AspNetCore.SignalR.Common": "8.0.4" + } + }, + "Microsoft.Build.Tasks.Git": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "bZKfSIKJRXLTuSzLudMFte/8CempWjVamNUR5eHJizsy+iuOuO/k2gnh7W0dHJmYY0tBf+gUErfluCv5mySAOQ==" + }, + "Microsoft.Extensions.Configuration": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "0J/9YNXTMWSZP2p2+nvl8p71zpSwokZXZuJW+VjdErkegAnFdO1XlqtA62SJtgVYHdKu3uPxJHcMR/r35HwFBA==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "8.0.0", + "Microsoft.Extensions.Primitives": "8.0.0" + } + }, + "Microsoft.Extensions.Configuration.Abstractions": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "3lE/iLSutpgX1CC0NOW70FJoGARRHbyKmG7dc0klnUZ9Dd9hS6N/POPWhKhMLCEuNN5nXEY5agmlFtH562vqhQ==", + "dependencies": { + "Microsoft.Extensions.Primitives": "8.0.0" + } + }, + "Microsoft.Extensions.Configuration.Binder": { + "type": "Transitive", + "resolved": "8.0.1", + "contentHash": "2UKFJnLiBt7Od6nCnTqP9rTIUNhzmn9Hv1l2FchyKbz8xieB9ULwZTbQZMw+M24Qw3F5dzzH1U9PPleN0LNLOQ==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "8.0.0" + } + }, + "Microsoft.Extensions.Configuration.FileExtensions": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "McP+Lz/EKwvtCv48z0YImw+L1gi1gy5rHhNaNIY2CrjloV+XY8gydT8DjMR6zWeL13AFK+DioVpppwAuO1Gi1w==", + "dependencies": { + "Microsoft.Extensions.Configuration": "8.0.0", + "Microsoft.Extensions.Configuration.Abstractions": "8.0.0", + "Microsoft.Extensions.FileProviders.Abstractions": "8.0.0", + "Microsoft.Extensions.FileProviders.Physical": "8.0.0", + "Microsoft.Extensions.Primitives": "8.0.0" + } + }, + "Microsoft.Extensions.Configuration.Json": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "C2wqUoh9OmRL1akaCcKSTmRU8z0kckfImG7zLNI8uyi47Lp+zd5LWAD17waPQEqCz3ioWOCrFUo+JJuoeZLOBw==", + "dependencies": { + "Microsoft.Extensions.Configuration": "8.0.0", + "Microsoft.Extensions.Configuration.Abstractions": "8.0.0", + "Microsoft.Extensions.Configuration.FileExtensions": "8.0.0", + "Microsoft.Extensions.FileProviders.Abstractions": "8.0.0", + "System.Text.Json": "8.0.0" + } + }, + "Microsoft.Extensions.DependencyInjection": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "V8S3bsm50ig6JSyrbcJJ8bW2b9QLGouz+G1miK3UTaOWmMtFwNNNzUf4AleyDWUmTrWMLNnFSLEQtxmxgNQnNQ==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0" + } + }, + "Microsoft.Extensions.DependencyInjection.Abstractions": { + "type": "Transitive", + "resolved": "8.0.1", + "contentHash": "fGLiCRLMYd00JYpClraLjJTNKLmMJPnqxMaiRzEBIIvevlzxz33mXy39Lkd48hu1G+N21S7QpaO5ZzKsI6FRuA==" + }, + "Microsoft.Extensions.Features": { + "type": "Transitive", + "resolved": "8.0.4", + "contentHash": "ym56/tUtFHFHucqiyQq42Ha6n1CT3CkrSZmbb3Szfkl/KNEaNqotKXFQMWHlFk2WMvU4fepqUsW8VK5WEjMChA==" + }, + "Microsoft.Extensions.FileProviders.Abstractions": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "ZbaMlhJlpisjuWbvXr4LdAst/1XxH3vZ6A0BsgTphZ2L4PGuxRLz7Jr/S7mkAAnOn78Vu0fKhEgNF5JO3zfjqQ==", + "dependencies": { + "Microsoft.Extensions.Primitives": "8.0.0" + } + }, + "Microsoft.Extensions.FileProviders.Physical": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "UboiXxpPUpwulHvIAVE36Knq0VSHaAmfrFkegLyBZeaADuKezJ/AIXYAW8F5GBlGk/VaibN2k/Zn1ca8YAfVdA==", + "dependencies": { + "Microsoft.Extensions.FileProviders.Abstractions": "8.0.0", + "Microsoft.Extensions.FileSystemGlobbing": "8.0.0", + "Microsoft.Extensions.Primitives": "8.0.0" + } + }, + "Microsoft.Extensions.FileSystemGlobbing": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "OK+670i7esqlQrPjdIKRbsyMCe9g5kSLpRRQGSr4Q58AOYEe/hCnfLZprh7viNisSUUQZmMrbbuDaIrP+V1ebQ==" + }, + "Microsoft.Extensions.Logging": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "tvRkov9tAJ3xP51LCv3FJ2zINmv1P8Hi8lhhtcKGqM+ImiTCC84uOPEI4z8Cdq2C3o9e+Aa0Gw0rmrsJD77W+w==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection": "8.0.0", + "Microsoft.Extensions.Logging.Abstractions": "8.0.0", + "Microsoft.Extensions.Options": "8.0.0" + } + }, + "Microsoft.Extensions.Logging.Abstractions": { + "type": "Transitive", + "resolved": "8.0.1", + "contentHash": "RIFgaqoaINxkM2KTOw72dmilDmTrYA0ns2KW4lDz4gZ2+o6IQ894CzmdL3StM2oh7QQq44nCWiqKqc4qUI9Jmg==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.1" + } + }, + "Microsoft.Extensions.Options": { + "type": "Transitive", + "resolved": "8.0.2", + "contentHash": "dWGKvhFybsaZpGmzkGCbNNwBD1rVlWzrZKANLW/CcbFJpCEceMCGzT7zZwHOGBCbwM0SzBuceMj5HN1LKV1QqA==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0", + "Microsoft.Extensions.Primitives": "8.0.0" + } + }, + "Microsoft.Extensions.Primitives": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "bXJEZrW9ny8vjMF1JV253WeLhpEVzFo1lyaZu1vQ4ZxWUlVvknZ/+ftFgVheLubb4eZPSwwxBeqS1JkCOjxd8g==" + }, + "Microsoft.JSInterop": { + "type": "Transitive", + "resolved": "8.0.4", + "contentHash": "97XhCIlz57G74fuf9XsuItyeO/8e6etWYAPH8XuDmmIW7461Gu9WN3louVqjkh4BU0q3Nf5acvSIfkIuGzHVWw==" + }, + "Microsoft.JSInterop.WebAssembly": { + "type": "Transitive", + "resolved": "8.0.4", + "contentHash": "mG6XiYUmdLdrvowICG/nmGolx6oDZGt8xbkkI+7QvJL1aWuR/TTWPb6I6/N1ngQHMWzKpeRx1gWkmGV+dhJ58A==", + "dependencies": { + "Microsoft.JSInterop": "8.0.4" + } + }, + "Microsoft.NET.StringTools": { + "type": "Transitive", + "resolved": "17.4.0", + "contentHash": "06T6Hqfs3JDIaBvJaBRFFMIdU7oE0OMab5Xl8LKQjWPxBQr3BgVFKMQPTC+GsSEuYREWmK6g5eOd7Xqd9p1YCA==", + "dependencies": { + "System.Memory": "4.5.5", + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + }, + "Microsoft.SourceLink.Common": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw==" + }, + "Nito.AsyncEx.Tasks": { + "type": "Transitive", + "resolved": "5.1.2", + "contentHash": "jEkCfR2/M26OK/U4G7SEN063EU/F4LiVA06TtpZILMdX/quIHCg+wn31Zerl2LC+u1cyFancjTY3cNAr2/89PA==", + "dependencies": { + "Nito.Disposables": "2.2.1" + } + }, + "Nito.Collections.Deque": { + "type": "Transitive", + "resolved": "1.1.1", + "contentHash": "CU0/Iuv5VDynK8I8pDLwkgF0rZhbQoZahtodfL0M3x2gFkpBRApKs8RyMyNlAi1mwExE4gsmqQXk4aFVvW9a4Q==" + }, + "Nito.Disposables": { + "type": "Transitive", + "resolved": "2.2.1", + "contentHash": "6sZ5uynQeAE9dPWBQGKebNmxbY4xsvcc5VplB5WkYEESUS7oy4AwnFp0FhqxTSKm/PaFrFqLrYr696CYN8cugg==", + "dependencies": { + "System.Collections.Immutable": "1.7.1" + } + }, + "System.Collections.Immutable": { + "type": "Transitive", + "resolved": "1.7.1", + "contentHash": "B43Zsz5EfMwyEbnObwRxW5u85fzJma3lrDeGcSAV1qkhSRTNY5uXAByTn9h9ddNdhM+4/YoLc/CI43umjwIl9Q==" + }, + "System.IO.Pipelines": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "FHNOatmUq0sqJOkTx+UF/9YK1f180cnW5FVqnQMvYUN0elp6wFzbtPSiqbo1/ru8ICp43JM1i7kKkk6GsNGHlA==" + }, + "System.Memory": { + "type": "Transitive", + "resolved": "4.5.5", + "contentHash": "XIWiDvKPXaTveaB7HVganDlOCRoj03l+jrwNvcge/t8vhGYKvqV+dMv6G4SAX2NoNmN0wZfVPTAlFwZcZvVOUw==" + }, + "System.Runtime.CompilerServices.Unsafe": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg==" + }, + "System.Text.Encodings.Web": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "yev/k9GHAEGx2Rg3/tU6MQh4HGBXJs70y7j1LaM1i/ER9po+6nnQ6RRqTJn1E7Xu0fbIFK80Nh5EoODxrbxwBQ==" + }, + "System.Text.Json": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "OdrZO2WjkiEG6ajEFRABTRCi/wuXQPxeV6g8xvUJqdxMvvuCCEk86zPla8UiIQJz3durtUEbNyY/3lIhS0yZvQ==", + "dependencies": { + "System.Text.Encodings.Web": "8.0.0" + } + }, + "System.Threading.Channels": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "CMaFr7v+57RW7uZfZkPExsPB6ljwzhjACWW1gfU35Y56rk72B/Wu+sTqxVmGSk4SFUlPc3cjeKND0zktziyjBA==" + } + } + } +} \ No newline at end of file diff --git a/src/App/postcss.config.js b/src/App/postcss.config.js new file mode 100644 index 0000000..5967a75 --- /dev/null +++ b/src/App/postcss.config.js @@ -0,0 +1,11 @@ +export default ctx => ({ + map: ctx.options.map, + parser: ctx.options.parser, + plugins: { + tailwindcss: {}, + 'postcss-preset-env': { + env: ctx.env + }, + cssnano: ctx.env === 'production' ? {} : false, + } +}) \ No newline at end of file diff --git a/src/App/tailwind.config.js b/src/App/tailwind.config.js new file mode 100644 index 0000000..6576fa5 --- /dev/null +++ b/src/App/tailwind.config.js @@ -0,0 +1,21 @@ +import defaultTheme from 'tailwindcss/defaultTheme' +import path from 'node:path' + +const ProjectDirectory = process.env.MSBUILD_PROJECT_DIR +const SupportedFileExtensions = ['razor'] + +export default { + content: SupportedFileExtensions.map(ext => path.join(ProjectDirectory, `./**/*.${ext}`)), + plugins: [ + require('@tailwindcss/forms'), + ], + safelist: ['invalid', 'modified', 'validation-message'], + theme: { + extend: { + fontFamily: { + mono: ['IBM Plex Mono', ...defaultTheme.fontFamily.mono], + sans: ['Nunito', ...defaultTheme.fontFamily.sans] + }, + } + }, +} \ No newline at end of file diff --git a/src/App/wwwroot/Interop/Element.module.js b/src/App/wwwroot/Interop/Element.module.js new file mode 100644 index 0000000..0a2a7fb --- /dev/null +++ b/src/App/wwwroot/Interop/Element.module.js @@ -0,0 +1,8 @@ +export function focusAndSelectEnd(element) { + element.scrollIntoView({ behavior: "smooth" }); + element.focus(); + + if (!!element.value) { + element.setSelectionRange(element.value.length, element.value.length); + } +} \ No newline at end of file diff --git a/src/Directory.Build.props b/src/Directory.Build.props index cd7876b..cae7de7 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -7,14 +7,14 @@ true - True + $(DefaultItemExcludesInProjectFolder);packages.lock.json;package.json;package-lock.json true true + false strict true true true - true latest enable $(NoWarn);CS8618 diff --git a/src/Launcher/Abstractions/LauncherAppOptions.cs b/src/Launcher/Abstractions/LauncherAppOptions.cs new file mode 100644 index 0000000..de96e38 --- /dev/null +++ b/src/Launcher/Abstractions/LauncherAppOptions.cs @@ -0,0 +1,8 @@ +namespace CS2Launcher.AspNetCore.Launcher.Abstractions; + +/// Represents the options for configuring the CS2Launcher App. +public sealed class LauncherAppOptions +{ + /// The Steam64 User IDs of users permitted access. + public List Users { get; set; } = []; +} \ No newline at end of file diff --git a/src/Launcher/Api/ConsoleHub.cs b/src/Launcher/Api/ConsoleHub.cs new file mode 100644 index 0000000..2a4733c --- /dev/null +++ b/src/Launcher/Api/ConsoleHub.cs @@ -0,0 +1,98 @@ +using System.Net; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.SignalR; +using CoreRCON; +using CoreRCON.Extensions.CounterStrike; +using CS2Launcher.AspNetCore.App.Abstractions.Signaling; +using CS2Launcher.AspNetCore.App.Abstractions; +using Microsoft.Extensions.Options; +using CS2Launcher.AspNetCore.Launcher.Proc; + +namespace CS2Launcher.AspNetCore.Launcher.Api; + +/// Hub for handling . +[Authorize] +public sealed class ConsoleHub( IOptions serverOptionsAccessor ) : Hub +{ + private static readonly object ConsoleKey = new(); + + /// Handle the . + [HubMethodName( nameof( ConsoleSignals.ExecuteCommand ) )] + public async Task ExecuteCommand( ConsoleSignals.ExecuteCommand command ) + { + string value; + try + { + value = await GetOrCreateConsole().SendCommandAsync( command.Command, Context.ConnectionAborted ); + } + catch( RCONException exception ) + { + await Clients.Caller.Signal( + new ConsoleSignals.ExecuteCommandFailed( exception.Message, command.Token ), + Context.ConnectionAborted ); + + return; + } + + await Clients.Caller.Signal( + new ConsoleSignals.ExecutedCommand( value, command.Token ), + Context.ConnectionAborted ); + } + + private RCONClient GetOrCreateConsole( ) + { + if( Context.Items.TryGetValue( ConsoleKey, out var value ) && value is RCONClient client ) + { + return client; + } + + var options = serverOptionsAccessor.Value; + client = new RCONClient( + new IPEndPoint( IPAddress.Parse( options.Host ), 27015 ), + options.RconPassword!, + new() { AutoConnect = true } ); + + Context.Items[ ConsoleKey ] = client; + return client; + } + + /// + public override async Task OnConnectedAsync( ) + { + await Connected( + Clients.Caller, + GetOrCreateConsole(), + Context.ConnectionAborted ); + + await base.OnConnectedAsync(); + + static async Task Connected( IClientProxy caller, RCONClient console, CancellationToken cancellation ) + { + await console.ConnectAsync(); + + var status = await console.Status( cancellation ); + await caller.Signal( new ConsoleSignals.Connected( status.Hostname ?? status.Endpoints?.Public.ToString() ?? "" ), cancellation ); + } + } + + /// + public override Task OnDisconnectedAsync( Exception? exception ) + { + if( Context.Items.Remove( ConsoleKey, out var value ) && value is RCONClient console ) + { + console.Dispose(); + } + + return base.OnDisconnectedAsync( exception ); + } +} + +internal static class HubClientExtensions +{ + public static Task Signal( this IClientProxy client, TSignal signal, CancellationToken cancellation = default ) + where TSignal : Signal + { + ArgumentNullException.ThrowIfNull( client ); + return client.SendAsync( typeof( TSignal ).Name, signal, cancellationToken: cancellation ); + } +} \ No newline at end of file diff --git a/src/Launcher/Authorization/AppUserRequirement.cs b/src/Launcher/Authorization/AppUserRequirement.cs new file mode 100644 index 0000000..01456f1 --- /dev/null +++ b/src/Launcher/Authorization/AppUserRequirement.cs @@ -0,0 +1,46 @@ +using System.Globalization; +using System.Security.Claims; +using AspNet.Security.OpenId.Steam; +using CS2Launcher.AspNetCore.Launcher.Abstractions; +using Microsoft.AspNetCore.Authorization; +using Microsoft.Extensions.Options; + +namespace CS2Launcher.AspNetCore.Launcher.Authorization; + +internal sealed class AppUserAuthorizationHandler( IOptions optionsAccessor ) : AuthorizationHandler +{ + protected override Task HandleRequirementAsync( AuthorizationHandlerContext context, AppUserRequirement requirement ) + { + ArgumentNullException.ThrowIfNull( context ); + ArgumentNullException.ThrowIfNull( requirement ); + + if( context.User.TryGetSteamUserId( out var userId ) && optionsAccessor.Value.Users.Contains( userId ) ) + { + context.Succeed( requirement ); + return Task.CompletedTask; + } + + return Task.CompletedTask; + } +} + +internal sealed class AppUserRequirement : IAuthorizationRequirement; + +internal static class SteamClaimsExtensions +{ + public static bool TryGetSteamUserId( this ClaimsPrincipal principal, out ulong userId ) + { + ArgumentNullException.ThrowIfNull( principal ); + if( principal.Identity?.IsAuthenticated is true ) + { + var value = principal.FindFirstValue( ClaimTypes.NameIdentifier ); + if( value?.StartsWith( SteamAuthenticationConstants.Namespaces.Identifier, StringComparison.OrdinalIgnoreCase ) is true ) + { + return ulong.TryParse( value[ SteamAuthenticationConstants.Namespaces.Identifier.Length.. ], CultureInfo.InvariantCulture, out userId ); + } + } + + userId = default; + return false; + } +} \ No newline at end of file diff --git a/src/Launcher/CS2Launcher.AspNetCore.Launcher.csproj b/src/Launcher/CS2Launcher.AspNetCore.Launcher.csproj index 9cbf59f..920c386 100644 --- a/src/Launcher/CS2Launcher.AspNetCore.Launcher.csproj +++ b/src/Launcher/CS2Launcher.AspNetCore.Launcher.csproj @@ -1,7 +1,9 @@ - + + true A .NET Generic Host Builder for running CS2 Dedicated Servers. + true README.md @@ -10,4 +12,14 @@ + + + + + + + + + + diff --git a/src/Launcher/CS2LauncherApplication.cs b/src/Launcher/CS2LauncherApplication.cs index 53c6221..090d5dc 100644 --- a/src/Launcher/CS2LauncherApplication.cs +++ b/src/Launcher/CS2LauncherApplication.cs @@ -1,4 +1,19 @@ -using Microsoft.AspNetCore.Builder; +using System.Diagnostics.CodeAnalysis; +using System.Reflection; +using CS2Launcher.AspNetCore.App; +using CS2Launcher.AspNetCore.App.Hosting; +using CS2Launcher.AspNetCore.Launcher.Abstractions; +using CS2Launcher.AspNetCore.Launcher.Authorization; +using CS2Launcher.AspNetCore.Launcher.Configuration; +using CS2Launcher.AspNetCore.Launcher.Hosting; +using CS2Launcher.AspNetCore.Launcher.Proc; +using Microsoft.AspNetCore.Authentication.Cookies; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Http.Features; +using Microsoft.AspNetCore.Routing; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Diagnostics.Metrics; @@ -8,31 +23,64 @@ namespace CS2Launcher.AspNetCore.Launcher; /// The launcher application used to configure CS2 and the underlying host. -public sealed class CS2LauncherApplication : IAsyncDisposable +public sealed class CS2LauncherApplication : IApplicationBuilder, IAsyncDisposable, IEndpointRouteBuilder, IHost { /// The underlying host of the launcher. - public WebApplication WebApp { get; } + internal readonly WebApplication WebApp; + + IServiceProvider IEndpointRouteBuilder.ServiceProvider => (( IEndpointRouteBuilder )WebApp).ServiceProvider; + ICollection IEndpointRouteBuilder.DataSources => (( IEndpointRouteBuilder )WebApp).DataSources; + + IServiceProvider IHost.Services => WebApp.Services; + + IServiceProvider IApplicationBuilder.ApplicationServices { get => (( IApplicationBuilder )WebApp).ApplicationServices; set => (( IApplicationBuilder )WebApp).ApplicationServices = value; } + IFeatureCollection IApplicationBuilder.ServerFeatures => (( IApplicationBuilder )WebApp).ServerFeatures; + IDictionary IApplicationBuilder.Properties => (( IApplicationBuilder )WebApp).Properties; internal CS2LauncherApplication( WebApplication app ) => WebApp = app; + RequestDelegate IApplicationBuilder.Build( ) => (( IApplicationBuilder )WebApp).Build(); + + IApplicationBuilder IEndpointRouteBuilder.CreateApplicationBuilder( ) => (( IEndpointRouteBuilder )WebApp).CreateApplicationBuilder(); + /// Initialize a with pre-configured defaults. /// The command line arguments. public static CS2LauncherApplicationBuilder CreateBuilder( string[] args ) { var builder = WebApplication.CreateBuilder( args ); builder.Configuration.AddEnvironmentVariables( prefix: "CS2L_" ); - builder.Services.AddCS2Launcher(); + + builder.Services.AddCors() + .AddRequestDecompression() + .AddResponseCaching() + .AddResponseCompression() + .AddRouting( options => options.LowercaseUrls = true ); + + builder.Services.AddHostedService() + .AddOptions() + .BindConfiguration( "Server" ) + .ValidateDataAnnotations(); return new( builder ); } + void IDisposable.Dispose( ) => (WebApp as IDisposable)?.Dispose(); + /// public ValueTask DisposeAsync( ) => WebApp.DisposeAsync(); + IApplicationBuilder IApplicationBuilder.New( ) => (( IApplicationBuilder )WebApp).New(); + /// Runs the applications. /// A task that completes when the application is shutdown. - /// If the crashes, the host application will be shutdown. + /// If the crashes, the host application will be shutdown. public Task RunAsync( ) => WebApp.RunAsync(); + + Task IHost.StartAsync( CancellationToken cancellation ) => WebApp.StartAsync( cancellation ); + + Task IHost.StopAsync( CancellationToken cancellation ) => WebApp.StopAsync( cancellation ); + + IApplicationBuilder IApplicationBuilder.Use( Func middleware ) => WebApp.Use( middleware ); } /// A builder for a CS2 Launcher and its services. @@ -45,6 +93,9 @@ public sealed class CS2LauncherApplicationBuilder : IHostApplicationBuilder /// public IConfigurationManager Configuration => builder.Configuration; + /// An for configuring host specific properties. + public ConfigureHostBuilder Host => builder.Host; + /// public IHostEnvironment Environment => builder.Environment; @@ -60,11 +111,79 @@ public sealed class CS2LauncherApplicationBuilder : IHostApplicationBuilder /// public IServiceCollection Services => builder.Services; + /// An for configuring server specific properties. + public ConfigureWebHostBuilder WebHost => builder.WebHost; + /// Build the CS2 launcher application. - public CS2LauncherApplication Build( ) => new( builder.Build() ); + public CS2LauncherApplication Build( ) + { + var app = builder.Build(); + if( app.Environment.IsDevelopment() ) + { + app.UseDeveloperExceptionPage(); + } + else + { + app.UseHsts(); + } + + app.UseHttpsRedirection(); + app.UseCookiePolicy(); + app.UseCors(); + + app.UseRequestDecompression(); + app.UseResponseCaching(); + if( !app.Environment.IsDevelopment() ) + { + app.UseResponseCompression(); + } + + if( app.Services.GetService() is not null ) + { + app.UseLauncherApp(); + } + else + { + app.Map( "/", ( ) => Results.NoContent() ); + } + + return new( app ); + } /// public void ConfigureContainer( IServiceProviderFactory factory, Action? configure = null ) where TContainerBuilder : notnull => (( IHostApplicationBuilder )builder).ConfigureContainer( factory, configure ); + + /// Host the Launcher App with the root component of type . + /// The root component of the Launcher App. + public CS2LauncherApplicationBuilder WithLauncherApp<[DynamicallyAccessedMembers( DynamicallyAccessedMemberTypes.All )] TRoot>( ) + where TRoot : RootComponent + { + Services.AddCS2LauncherApp() + .AddSingleton( LauncherHostContext.From( Assembly.GetEntryAssembly()! ) ) + .AddControllersWithViews(); + + Services.AddAuthorization() + .AddSingleton() + .AddAuthentication( CookieAuthenticationDefaults.AuthenticationScheme ) + .AddCookie() + .AddSteam(); + + Services.AddSignalR() +#if DEBUG + .AddJsonProtocol() +#endif + .AddMessagePackProtocol(); + + Services.AddOptions() + .BindConfiguration( "App" ) + .ValidateDataAnnotations(); + + Services.ConfigureOptions() + .ConfigureOptions() + .ConfigureOptions(); + + return this; + } } \ No newline at end of file diff --git a/src/Launcher/Configuration/ConfigureAuthentication.cs b/src/Launcher/Configuration/ConfigureAuthentication.cs new file mode 100644 index 0000000..6997215 --- /dev/null +++ b/src/Launcher/Configuration/ConfigureAuthentication.cs @@ -0,0 +1,18 @@ +using AspNet.Security.OpenId.Steam; +using Microsoft.AspNetCore.Authentication.Cookies; +using Microsoft.Extensions.Options; + +namespace CS2Launcher.AspNetCore.Launcher.Configuration; + +internal sealed class ConfigureAuthentication : IPostConfigureOptions, IPostConfigureOptions +{ + public void PostConfigure( string? name, CookieAuthenticationOptions options ) + { + options.LoginPath = "/login"; + } + + public void PostConfigure( string? name, SteamAuthenticationOptions options ) + { + options.SaveTokens = true; + } +} \ No newline at end of file diff --git a/src/Launcher/Configuration/ConfigureAuthorization.cs b/src/Launcher/Configuration/ConfigureAuthorization.cs new file mode 100644 index 0000000..788f555 --- /dev/null +++ b/src/Launcher/Configuration/ConfigureAuthorization.cs @@ -0,0 +1,17 @@ +using AspNet.Security.OpenId.Steam; +using CS2Launcher.AspNetCore.Launcher.Authorization; +using Microsoft.AspNetCore.Authorization; +using Microsoft.Extensions.Options; + +namespace CS2Launcher.AspNetCore.Launcher.Configuration; + +internal sealed class ConfigureAuthorization : IConfigureOptions +{ + public void Configure( AuthorizationOptions options ) + { + options.DefaultPolicy = new AuthorizationPolicyBuilder( SteamAuthenticationDefaults.AuthenticationScheme ) + .RequireAuthenticatedUser() + .AddRequirements( new AppUserRequirement() ) + .Build(); + } +} \ No newline at end of file diff --git a/src/Launcher/Configuration/ConfigureResponseCompression.cs b/src/Launcher/Configuration/ConfigureResponseCompression.cs new file mode 100644 index 0000000..a8e5848 --- /dev/null +++ b/src/Launcher/Configuration/ConfigureResponseCompression.cs @@ -0,0 +1,37 @@ +using System.Net.Mime; +using Microsoft.AspNetCore.ResponseCompression; +using Microsoft.Extensions.Options; + +namespace CS2Launcher.AspNetCore.Launcher.Configuration; + +internal sealed class ConfigureResponseCompression : IConfigureOptions +{ + public void Configure( ResponseCompressionOptions options ) + { + options.EnableForHttps = true; + options.MimeTypes = [.. ResponseCompressionDefaults.MimeTypes, + // documents + MediaTypeNames.Application.Json, + "text/json", + MediaTypeNames.Application.Manifest, + MediaTypeNames.Application.Octet, + MediaTypeNames.Application.Pdf, + + // images + MediaTypeNames.Image.Gif, + MediaTypeNames.Image.Icon, + MediaTypeNames.Image.Jpeg, + "image/jpg", + MediaTypeNames.Image.Png, + MediaTypeNames.Image.Svg, + "image/svg", + MediaTypeNames.Image.Webp, + + // fonts + "application/vnd.ms-fontobject", + MediaTypeNames.Font.Otf, + MediaTypeNames.Font.Ttf, + MediaTypeNames.Font.Woff, + MediaTypeNames.Font.Woff2 ]; + } +} \ No newline at end of file diff --git a/src/Launcher/Controllers/AppController.cs b/src/Launcher/Controllers/AppController.cs new file mode 100644 index 0000000..551b340 --- /dev/null +++ b/src/Launcher/Controllers/AppController.cs @@ -0,0 +1,26 @@ +using AspNet.Security.OpenId.Steam; +using Microsoft.AspNetCore.Authentication; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; + +namespace CS2Launcher.AspNetCore.Launcher.Controllers; + +/// Default controller for routing to the CS2Launcher App. +public sealed class AppController : Controller +{ + /// Default route for the CS2Launcher App. + [Authorize] + public ViewResult Index( ) => View( "_App" ); + + /// Challenges authentication via Steam. + [AllowAnonymous] + [HttpGet( "/login" )] + public ChallengeResult Login( string returnUrl = "/" ) => Challenge( + new AuthenticationProperties + { + AllowRefresh = true, + IsPersistent = true, + RedirectUri = returnUrl, + }, + SteamAuthenticationDefaults.AuthenticationScheme ); +} \ No newline at end of file diff --git a/src/Launcher/Hosting/LauncherHostContext.cs b/src/Launcher/Hosting/LauncherHostContext.cs new file mode 100644 index 0000000..364e083 --- /dev/null +++ b/src/Launcher/Hosting/LauncherHostContext.cs @@ -0,0 +1,15 @@ +using System.Reflection; + +namespace CS2Launcher.AspNetCore.Launcher.Hosting; + +/// Represents metadata about the launcher host. +/// The name of the launcher host's assembly. +public sealed record LauncherHostContext( string AssemblyName ) +{ + /// Create a from the given . + public static LauncherHostContext From( Assembly assembly ) + { + ArgumentNullException.ThrowIfNull( assembly ); + return new( assembly.GetName().Name! ); + } +} \ No newline at end of file diff --git a/src/Launcher/LauncherApplicationExtensions.cs b/src/Launcher/LauncherApplicationExtensions.cs new file mode 100644 index 0000000..1d308d2 --- /dev/null +++ b/src/Launcher/LauncherApplicationExtensions.cs @@ -0,0 +1,28 @@ +using CS2Launcher.AspNetCore.Launcher.Api; +using Microsoft.AspNetCore.Builder; +using Microsoft.Extensions.Hosting; + +namespace CS2Launcher.AspNetCore.Launcher; + +internal static class LauncherApplicationExtensions +{ + internal static WebApplication UseLauncherApp( this WebApplication app ) + { + ArgumentNullException.ThrowIfNull( app ); + if( app.Environment.IsDevelopment() ) + { + app.UseWebAssemblyDebugging(); + } + + app.UseBlazorFrameworkFiles(); + app.UseStaticFiles( new StaticFileOptions { ServeUnknownFileTypes = true } ); + + app.UseAuthentication(); + app.UseAuthorization(); + + app.MapHub( "/api/signals/console", options => options.AllowStatefulReconnects = true ); + app.MapFallbackToController( "Index", "App" ); + + return app; + } +} \ No newline at end of file diff --git a/src/Launcher/LauncherServiceExtensions.cs b/src/Launcher/LauncherServiceExtensions.cs deleted file mode 100644 index e0c442b..0000000 --- a/src/Launcher/LauncherServiceExtensions.cs +++ /dev/null @@ -1,24 +0,0 @@ -using CS2Launcher.AspNetCore.Launcher.Proc; -using Microsoft.Extensions.DependencyInjection; - -namespace CS2Launcher.AspNetCore.Launcher; - -/// Extensions for register services required by launchers. -public static class LauncherServiceExtensions -{ - /// Adds services for CS2 launcher applications. - /// - public static IServiceCollection AddCS2Launcher( this IServiceCollection services ) - { - ArgumentNullException.ThrowIfNull( services ); - -#pragma warning disable IL2026,IL3050 - services.AddHostedService() - .AddOptions() - .BindConfiguration( "Server" ) - .ValidateDataAnnotations(); -#pragma warning restore IL2026,IL3050 - - return services; - } -} \ No newline at end of file diff --git a/src/Launcher/Proc/DedicatedServer.cs b/src/Launcher/Proc/DedicatedServer.cs index 6b4074d..6f90abe 100644 --- a/src/Launcher/Proc/DedicatedServer.cs +++ b/src/Launcher/Proc/DedicatedServer.cs @@ -16,6 +16,8 @@ internal sealed partial class DedicatedServer( [SupportedOSPlatform( "windows" )] protected override async Task ExecuteAsync( CancellationToken cancellation ) { + if( !options.Enabled ) return; + using( var process = new DedicatedServerProcess( options ) ) using( cancellation.Register( OnCancellation, process ) ) { diff --git a/src/Launcher/Proc/DedicatedServerOptions.cs b/src/Launcher/Proc/DedicatedServerOptions.cs index ef073ea..84cd502 100644 --- a/src/Launcher/Proc/DedicatedServerOptions.cs +++ b/src/Launcher/Proc/DedicatedServerOptions.cs @@ -14,12 +14,19 @@ public sealed class DedicatedServerOptions /// Additional custom arguments. public List AdditionalArgs { get; set; } = []; + /// Whether the server is enabled. + public bool Enabled { get; set; } = true; + /// The game_alias to launch with. public string GameAlias { get; set; } = "deathmatch"; /// A Game Server Login Token to launch with. public string? GSLToken { get; set; } + /// The host ip to bind the server to. + [Required] + public string Host { get; set; } + /// Whether to launch the dedicated server in 'insecure' mode. public bool Insecure { get; set; } @@ -38,12 +45,12 @@ public sealed class DedicatedServerOptions [Required] public string Program { get; set; } - /// Whether stdout of the underlying process should be redirected. - public bool RedirectOutput { get; set; } = true; - /// The RCON password the launch with. public string? RconPassword { get; set; } + /// Whether stdout of the underlying process should be redirected. + public bool RedirectOutput { get; set; } = true; + /// The name of the system user to run the underlying process as. public string? SystemUser { get; set; } diff --git a/src/Launcher/Views/Shared/_App.cshtml b/src/Launcher/Views/Shared/_App.cshtml new file mode 100644 index 0000000..a7698e4 --- /dev/null +++ b/src/Launcher/Views/Shared/_App.cshtml @@ -0,0 +1,41 @@ +@using CS2Launcher.AspNetCore.App.Hosting +@using CS2Launcher.AspNetCore.Launcher.Hosting +@using Microsoft.AspNetCore.Components.Web +@using Microsoft.Extensions.Hosting + +@inject LauncherHostContext LauncherHost +@inject RootComponentDescriptor RootComponent + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Launcher/Views/_ViewImports.cshtml b/src/Launcher/Views/_ViewImports.cshtml new file mode 100644 index 0000000..2f5f019 --- /dev/null +++ b/src/Launcher/Views/_ViewImports.cshtml @@ -0,0 +1,4 @@ +@using CS2Launcher.AspNetCore.App +@using CS2Launcher.AspNetCore.App.Abstractions + +@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers \ No newline at end of file diff --git a/src/Launcher/packages.lock.json b/src/Launcher/packages.lock.json index 1bad49d..bce755a 100644 --- a/src/Launcher/packages.lock.json +++ b/src/Launcher/packages.lock.json @@ -2,17 +2,26 @@ "version": 1, "dependencies": { "net8.0": { - "Microsoft.CodeAnalysis.NetAnalyzers": { + "AspNet.Security.OpenId.Steam": { "type": "Direct", "requested": "[8.0.0, )", "resolved": "8.0.0", - "contentHash": "DxiTgkCl3CGq1rYmBX2wjY7XGbxiBdL4J+/AJIAFLKy5z70NxhnVRnPghnicXZ8oF6JKVXlW3xwznRbI3ioEKg==" + "contentHash": "7uJhN/asrC4h6EairBZiIyFL2wJtVe2FCmoKdWOebZISh+bhq+fkwMnWupL3iLONXuLRnGxk1m0kGwMmvsTV0g==", + "dependencies": { + "AspNet.Security.OpenId": "8.0.0" + } }, - "Microsoft.NET.ILLink.Tasks": { + "Microsoft.AspNetCore.Components.WebAssembly.Server": { "type": "Direct", "requested": "[8.0.4, )", "resolved": "8.0.4", - "contentHash": "PZb5nfQ+U19nhnmnR9T1jw+LTmozhuG2eeuzuW5A7DqxD/UXW2ucjmNJqnqOuh8rdPzM3MQXoF8AfFCedJdCUw==" + "contentHash": "oUax9BrdzlLdmRt1R39F/0PIUahHDI9AvysMmwqAZT7vgx+elAYLYdSXb/SA8DA+S14blLVkcTkY4ALtFqzGnw==" + }, + "Microsoft.CodeAnalysis.NetAnalyzers": { + "type": "Direct", + "requested": "[8.0.0, )", + "resolved": "8.0.0", + "contentHash": "DxiTgkCl3CGq1rYmBX2wjY7XGbxiBdL4J+/AJIAFLKy5z70NxhnVRnPghnicXZ8oF6JKVXlW3xwznRbI3ioEKg==" }, "Microsoft.SourceLink.GitHub": { "type": "Direct", @@ -30,15 +39,464 @@ "resolved": "5.0.0", "contentHash": "ybkgpQMtt0Fo91l5rYtE3TZtD+Nmy5Ko091xvfXXOosQdMi30XO2EZ2+ShZt89gdu7RMmJqZaJ+e1q6d+6+KNw==" }, + "AngleSharp": { + "type": "Transitive", + "resolved": "1.0.6", + "contentHash": "OIU4pbC6KjSzYdQZOjV4nme1RgGfCd3TdZgx1/blDUpgagYc9Es1NcyLHNp6tTyHJBp1aU4cvxr9c679bWX0Rw==", + "dependencies": { + "System.Text.Encoding.CodePages": "7.0.0" + } + }, + "AspNet.Security.OpenId": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "QeBs3rnIPyc1DYl2b4Ukb078/n0QKBpPTVKdFOMEbC/2iMYwPDtflhlPe4ikwX6kV/Dhbj2rqArFA0SqeyzceA==", + "dependencies": { + "AngleSharp": "1.0.6", + "Microsoft.IdentityModel.Protocols": "7.0.3" + } + }, + "MessagePack": { + "type": "Transitive", + "resolved": "2.5.108", + "contentHash": "kcVRbdWP3xNWLZmmpm4DFO+kuXf6mUR2mHZ27WoZIEFIv9hazuUd80injXhNrZnlq/FklAdCsLOil5M76I4Ndg==", + "dependencies": { + "MessagePack.Annotations": "2.5.108", + "Microsoft.NET.StringTools": "17.4.0", + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + }, + "MessagePack.Annotations": { + "type": "Transitive", + "resolved": "2.5.108", + "contentHash": "28aNCvfJClgwaKr26gf2S6LT+C1PNyPxiG+ihYpy8uCJsRLJEDoCt2I0Uk5hqOPQ8P8hI0ESy520oMkZkPmsOQ==" + }, + "Microsoft.AspNetCore.Authorization": { + "type": "Transitive", + "resolved": "8.0.4", + "contentHash": "dzYUHvqyavBiYVd5BZNAgV5rT+DC4HyIWPnbeYgxQNBYOFomvvwzPfidQf1Ld/HhkXhEj3tlzqNb4gy2P2ukUg==", + "dependencies": { + "Microsoft.AspNetCore.Metadata": "8.0.4", + "Microsoft.Extensions.Logging.Abstractions": "8.0.1", + "Microsoft.Extensions.Options": "8.0.2" + } + }, + "Microsoft.AspNetCore.Components": { + "type": "Transitive", + "resolved": "8.0.4", + "contentHash": "ExTJT1u3QCTKaq2LjazkoHMNVlz0Q93A4ei5Zqd38bj3hggpShi4A/U22zk1LOmT0eUE5WklOBMpKZMg+T6Veg==", + "dependencies": { + "Microsoft.AspNetCore.Authorization": "8.0.4", + "Microsoft.AspNetCore.Components.Analyzers": "8.0.4" + } + }, + "Microsoft.AspNetCore.Components.Analyzers": { + "type": "Transitive", + "resolved": "8.0.4", + "contentHash": "kEvEOOkgN8uLjP2PMR481yxSjUsyGLaehHSD3HWjboNsXA5++7Hxn83LRdVri9/0rlY2zS/dP9oGHZpgxYu2iQ==" + }, + "Microsoft.AspNetCore.Components.Forms": { + "type": "Transitive", + "resolved": "8.0.4", + "contentHash": "I/kttR/nmRZTc+bsetYnvbkVzHgsJXrWKxHo30vGvQV+dTeur9LV2g2TvyLerpWL9OFbNWgpTGBUwgX1IW/0Zw==", + "dependencies": { + "Microsoft.AspNetCore.Components": "8.0.4" + } + }, + "Microsoft.AspNetCore.Components.Web": { + "type": "Transitive", + "resolved": "8.0.4", + "contentHash": "K9zcUkciMHmPjYdaB417xlG9Srv2udLT5j7CIAN92H5KNLH1ItIGIEIIUMJT3r+2Ma3ZLZO0eddEbR+Z59MbOQ==", + "dependencies": { + "Microsoft.AspNetCore.Components": "8.0.4", + "Microsoft.AspNetCore.Components.Forms": "8.0.4", + "Microsoft.Extensions.DependencyInjection": "8.0.0", + "Microsoft.Extensions.Primitives": "8.0.0", + "Microsoft.JSInterop": "8.0.4", + "System.IO.Pipelines": "8.0.0" + } + }, + "Microsoft.AspNetCore.Components.WebAssembly": { + "type": "Transitive", + "resolved": "8.0.4", + "contentHash": "4mi1GyihE1R9BocAc5ZUeYZN/G2cFfoGibb6H+yQ7xXk3ec7cvqkjamdnXH2EwsikS+hX44pgirtiwUHDUw1uw==", + "dependencies": { + "Microsoft.AspNetCore.Components.Web": "8.0.4", + "Microsoft.Extensions.Configuration.Binder": "8.0.1", + "Microsoft.Extensions.Configuration.Json": "8.0.0", + "Microsoft.Extensions.Logging": "8.0.0", + "Microsoft.JSInterop.WebAssembly": "8.0.4" + } + }, + "Microsoft.AspNetCore.Connections.Abstractions": { + "type": "Transitive", + "resolved": "8.0.4", + "contentHash": "pvO0JgjrNOas+WzmHxqawTv64lwTy1zbGm4WQY7OOd/OfKMw8LaoNEtn9jsAfiKUkt3lYK8kOL8Uy9XyyTCUwg==", + "dependencies": { + "Microsoft.Extensions.Features": "8.0.4", + "System.IO.Pipelines": "8.0.0" + } + }, + "Microsoft.AspNetCore.Http.Connections.Client": { + "type": "Transitive", + "resolved": "8.0.4", + "contentHash": "Tl9Hf+ftWZeKDGJpQOMwDgev7EXiiqk71NvoGDNhAYhYJMpoyf4591aINACAPSZ3zWNs4cqKIm8YQ5eG1slf5Q==", + "dependencies": { + "Microsoft.AspNetCore.Http.Connections.Common": "8.0.4", + "Microsoft.Extensions.Logging.Abstractions": "8.0.1", + "Microsoft.Extensions.Options": "8.0.2" + } + }, + "Microsoft.AspNetCore.Http.Connections.Common": { + "type": "Transitive", + "resolved": "8.0.4", + "contentHash": "SG02A6/ZET3sCW/PiJumg3q4yZdBZeMetdy/ebS4ZcmFPr+yI9sSmLAw9MHZVNNxxBWM5VuLg463YwlXoxhJHQ==", + "dependencies": { + "Microsoft.AspNetCore.Connections.Abstractions": "8.0.4" + } + }, + "Microsoft.AspNetCore.Metadata": { + "type": "Transitive", + "resolved": "8.0.4", + "contentHash": "TG3JhI7dkDCIoxZ3TL/5yptLYLg56w1f4jE8GSYnZXSso1xY5JKKCxObK+xKQJU5kZir30+QUGX1WpbC1kDcow==" + }, + "Microsoft.AspNetCore.SignalR.Client": { + "type": "Transitive", + "resolved": "8.0.4", + "contentHash": "HPM5/ifdz4PvK6W3t7CNHgV69MPPrS75tLD9HUYFRlwGmvbVPYbsgES2b7wmnvZEsaGlEBNOdw//xU1jK4FM0w==", + "dependencies": { + "Microsoft.AspNetCore.Http.Connections.Client": "8.0.4", + "Microsoft.AspNetCore.SignalR.Client.Core": "8.0.4" + } + }, + "Microsoft.AspNetCore.SignalR.Client.Core": { + "type": "Transitive", + "resolved": "8.0.4", + "contentHash": "w8eaEHS6Qn0VALv3G7EuLg/i5WInxt2Jps4IbvB0u61l9GaTAOGw0Xx1G+0UJgWwd2RZoaJXqMr748TuSpxm6g==", + "dependencies": { + "Microsoft.AspNetCore.SignalR.Common": "8.0.4", + "Microsoft.AspNetCore.SignalR.Protocols.Json": "8.0.4", + "Microsoft.Extensions.DependencyInjection": "8.0.0", + "Microsoft.Extensions.Logging": "8.0.0", + "System.Threading.Channels": "8.0.0" + } + }, + "Microsoft.AspNetCore.SignalR.Common": { + "type": "Transitive", + "resolved": "8.0.4", + "contentHash": "vsoXzcAibrem3/qWSpZ9Q/Wc/4UpFdXtsNTBMAmltnQPGR07qa7Pzgrc7K9pT/gEkFR5DkFKkEOzgCkNBDUE+g==", + "dependencies": { + "Microsoft.AspNetCore.Connections.Abstractions": "8.0.4", + "Microsoft.Extensions.Options": "8.0.2" + } + }, + "Microsoft.AspNetCore.SignalR.Protocols.Json": { + "type": "Transitive", + "resolved": "8.0.4", + "contentHash": "9X4TnAZTGMVzH7DghV7AWXX5r8UO7RpSJAPxfd9lTu3GChEyUpppKIJMaOKpseplnlRxOedve8UPdjx5ks06vA==", + "dependencies": { + "Microsoft.AspNetCore.SignalR.Common": "8.0.4" + } + }, + "Microsoft.AspNetCore.SignalR.Protocols.MessagePack": { + "type": "Transitive", + "resolved": "8.0.4", + "contentHash": "Zr+ur9AHHLuKWbp1b2Tw/evvY41xt2Dar5zEmtfYg0vO/ztU4CBLCDdXvB01o9Dtb0bHoQ+25xwF11ur08/l1g==", + "dependencies": { + "MessagePack": "2.5.108", + "Microsoft.AspNetCore.SignalR.Common": "8.0.4" + } + }, "Microsoft.Build.Tasks.Git": { "type": "Transitive", "resolved": "8.0.0", "contentHash": "bZKfSIKJRXLTuSzLudMFte/8CempWjVamNUR5eHJizsy+iuOuO/k2gnh7W0dHJmYY0tBf+gUErfluCv5mySAOQ==" }, + "Microsoft.Extensions.Configuration": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "0J/9YNXTMWSZP2p2+nvl8p71zpSwokZXZuJW+VjdErkegAnFdO1XlqtA62SJtgVYHdKu3uPxJHcMR/r35HwFBA==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "8.0.0", + "Microsoft.Extensions.Primitives": "8.0.0" + } + }, + "Microsoft.Extensions.Configuration.Abstractions": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "3lE/iLSutpgX1CC0NOW70FJoGARRHbyKmG7dc0klnUZ9Dd9hS6N/POPWhKhMLCEuNN5nXEY5agmlFtH562vqhQ==", + "dependencies": { + "Microsoft.Extensions.Primitives": "8.0.0" + } + }, + "Microsoft.Extensions.Configuration.Binder": { + "type": "Transitive", + "resolved": "8.0.1", + "contentHash": "2UKFJnLiBt7Od6nCnTqP9rTIUNhzmn9Hv1l2FchyKbz8xieB9ULwZTbQZMw+M24Qw3F5dzzH1U9PPleN0LNLOQ==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "8.0.0" + } + }, + "Microsoft.Extensions.Configuration.FileExtensions": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "McP+Lz/EKwvtCv48z0YImw+L1gi1gy5rHhNaNIY2CrjloV+XY8gydT8DjMR6zWeL13AFK+DioVpppwAuO1Gi1w==", + "dependencies": { + "Microsoft.Extensions.Configuration": "8.0.0", + "Microsoft.Extensions.Configuration.Abstractions": "8.0.0", + "Microsoft.Extensions.FileProviders.Abstractions": "8.0.0", + "Microsoft.Extensions.FileProviders.Physical": "8.0.0", + "Microsoft.Extensions.Primitives": "8.0.0" + } + }, + "Microsoft.Extensions.Configuration.Json": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "C2wqUoh9OmRL1akaCcKSTmRU8z0kckfImG7zLNI8uyi47Lp+zd5LWAD17waPQEqCz3ioWOCrFUo+JJuoeZLOBw==", + "dependencies": { + "Microsoft.Extensions.Configuration": "8.0.0", + "Microsoft.Extensions.Configuration.Abstractions": "8.0.0", + "Microsoft.Extensions.Configuration.FileExtensions": "8.0.0", + "Microsoft.Extensions.FileProviders.Abstractions": "8.0.0", + "System.Text.Json": "8.0.0" + } + }, + "Microsoft.Extensions.DependencyInjection": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "V8S3bsm50ig6JSyrbcJJ8bW2b9QLGouz+G1miK3UTaOWmMtFwNNNzUf4AleyDWUmTrWMLNnFSLEQtxmxgNQnNQ==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0" + } + }, + "Microsoft.Extensions.DependencyInjection.Abstractions": { + "type": "Transitive", + "resolved": "8.0.1", + "contentHash": "fGLiCRLMYd00JYpClraLjJTNKLmMJPnqxMaiRzEBIIvevlzxz33mXy39Lkd48hu1G+N21S7QpaO5ZzKsI6FRuA==" + }, + "Microsoft.Extensions.Features": { + "type": "Transitive", + "resolved": "8.0.4", + "contentHash": "ym56/tUtFHFHucqiyQq42Ha6n1CT3CkrSZmbb3Szfkl/KNEaNqotKXFQMWHlFk2WMvU4fepqUsW8VK5WEjMChA==" + }, + "Microsoft.Extensions.FileProviders.Abstractions": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "ZbaMlhJlpisjuWbvXr4LdAst/1XxH3vZ6A0BsgTphZ2L4PGuxRLz7Jr/S7mkAAnOn78Vu0fKhEgNF5JO3zfjqQ==", + "dependencies": { + "Microsoft.Extensions.Primitives": "8.0.0" + } + }, + "Microsoft.Extensions.FileProviders.Physical": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "UboiXxpPUpwulHvIAVE36Knq0VSHaAmfrFkegLyBZeaADuKezJ/AIXYAW8F5GBlGk/VaibN2k/Zn1ca8YAfVdA==", + "dependencies": { + "Microsoft.Extensions.FileProviders.Abstractions": "8.0.0", + "Microsoft.Extensions.FileSystemGlobbing": "8.0.0", + "Microsoft.Extensions.Primitives": "8.0.0" + } + }, + "Microsoft.Extensions.FileSystemGlobbing": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "OK+670i7esqlQrPjdIKRbsyMCe9g5kSLpRRQGSr4Q58AOYEe/hCnfLZprh7viNisSUUQZmMrbbuDaIrP+V1ebQ==" + }, + "Microsoft.Extensions.Logging": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "tvRkov9tAJ3xP51LCv3FJ2zINmv1P8Hi8lhhtcKGqM+ImiTCC84uOPEI4z8Cdq2C3o9e+Aa0Gw0rmrsJD77W+w==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection": "8.0.0", + "Microsoft.Extensions.Logging.Abstractions": "8.0.0", + "Microsoft.Extensions.Options": "8.0.0" + } + }, + "Microsoft.Extensions.Logging.Abstractions": { + "type": "Transitive", + "resolved": "8.0.1", + "contentHash": "RIFgaqoaINxkM2KTOw72dmilDmTrYA0ns2KW4lDz4gZ2+o6IQ894CzmdL3StM2oh7QQq44nCWiqKqc4qUI9Jmg==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.1" + } + }, + "Microsoft.Extensions.Options": { + "type": "Transitive", + "resolved": "8.0.2", + "contentHash": "dWGKvhFybsaZpGmzkGCbNNwBD1rVlWzrZKANLW/CcbFJpCEceMCGzT7zZwHOGBCbwM0SzBuceMj5HN1LKV1QqA==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0", + "Microsoft.Extensions.Primitives": "8.0.0" + } + }, + "Microsoft.Extensions.Primitives": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "bXJEZrW9ny8vjMF1JV253WeLhpEVzFo1lyaZu1vQ4ZxWUlVvknZ/+ftFgVheLubb4eZPSwwxBeqS1JkCOjxd8g==" + }, + "Microsoft.IdentityModel.Abstractions": { + "type": "Transitive", + "resolved": "7.0.3", + "contentHash": "cfPUWdjigLIRIJSKz3uaZxShgf86RVDXHC1VEEchj1gnY25akwPYpbrfSoIGDCqA9UmOMdlctq411+2pAViFow==" + }, + "Microsoft.IdentityModel.Logging": { + "type": "Transitive", + "resolved": "7.0.3", + "contentHash": "b6GbGO+2LOTBEccHhqoJsOsmemG4A/MY+8H0wK/ewRhiG+DCYwEnucog1cSArPIY55zcn+XdZl0YEiUHkpDISQ==", + "dependencies": { + "Microsoft.IdentityModel.Abstractions": "7.0.3" + } + }, + "Microsoft.IdentityModel.Protocols": { + "type": "Transitive", + "resolved": "7.0.3", + "contentHash": "BtwR+tctBYhPNygyZmt1Rnw74GFrJteW+1zcdIgyvBCjkek6cNwPPqRfdhzCv61i+lwyNomRi8+iI4QKd4YCKA==", + "dependencies": { + "Microsoft.IdentityModel.Logging": "7.0.3", + "Microsoft.IdentityModel.Tokens": "7.0.3" + } + }, + "Microsoft.IdentityModel.Tokens": { + "type": "Transitive", + "resolved": "7.0.3", + "contentHash": "wB+LlbDjhnJ98DULjmFepqf9eEMh/sDs6S6hFh68iNRHmwollwhxk+nbSSfpA5+j+FbRyNskoaY4JsY1iCOKCg==", + "dependencies": { + "Microsoft.IdentityModel.Logging": "7.0.3" + } + }, + "Microsoft.JSInterop": { + "type": "Transitive", + "resolved": "8.0.4", + "contentHash": "97XhCIlz57G74fuf9XsuItyeO/8e6etWYAPH8XuDmmIW7461Gu9WN3louVqjkh4BU0q3Nf5acvSIfkIuGzHVWw==" + }, + "Microsoft.JSInterop.WebAssembly": { + "type": "Transitive", + "resolved": "8.0.4", + "contentHash": "mG6XiYUmdLdrvowICG/nmGolx6oDZGt8xbkkI+7QvJL1aWuR/TTWPb6I6/N1ngQHMWzKpeRx1gWkmGV+dhJ58A==", + "dependencies": { + "Microsoft.JSInterop": "8.0.4" + } + }, + "Microsoft.NET.StringTools": { + "type": "Transitive", + "resolved": "17.4.0", + "contentHash": "06T6Hqfs3JDIaBvJaBRFFMIdU7oE0OMab5Xl8LKQjWPxBQr3BgVFKMQPTC+GsSEuYREWmK6g5eOd7Xqd9p1YCA==", + "dependencies": { + "System.Memory": "4.5.5", + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + }, "Microsoft.SourceLink.Common": { "type": "Transitive", "resolved": "8.0.0", "contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw==" + }, + "Nito.AsyncEx.Coordination": { + "type": "Transitive", + "resolved": "5.1.2", + "contentHash": "QMyUfsaxov//0ZMbOHWr9hJaBFteZd66DV1ay4J5wRODDb8+K/uHC7+3VsOflo6SVw/29mu8OWZp8vMDSuzc0w==", + "dependencies": { + "Nito.AsyncEx.Tasks": "5.1.2", + "Nito.Collections.Deque": "1.1.1" + } + }, + "Nito.AsyncEx.Tasks": { + "type": "Transitive", + "resolved": "5.1.2", + "contentHash": "jEkCfR2/M26OK/U4G7SEN063EU/F4LiVA06TtpZILMdX/quIHCg+wn31Zerl2LC+u1cyFancjTY3cNAr2/89PA==", + "dependencies": { + "Nito.Disposables": "2.2.1" + } + }, + "Nito.Collections.Deque": { + "type": "Transitive", + "resolved": "1.1.1", + "contentHash": "CU0/Iuv5VDynK8I8pDLwkgF0rZhbQoZahtodfL0M3x2gFkpBRApKs8RyMyNlAi1mwExE4gsmqQXk4aFVvW9a4Q==" + }, + "Nito.Disposables": { + "type": "Transitive", + "resolved": "2.2.1", + "contentHash": "6sZ5uynQeAE9dPWBQGKebNmxbY4xsvcc5VplB5WkYEESUS7oy4AwnFp0FhqxTSKm/PaFrFqLrYr696CYN8cugg==", + "dependencies": { + "System.Collections.Immutable": "1.7.1" + } + }, + "System.Collections.Immutable": { + "type": "Transitive", + "resolved": "1.7.1", + "contentHash": "B43Zsz5EfMwyEbnObwRxW5u85fzJma3lrDeGcSAV1qkhSRTNY5uXAByTn9h9ddNdhM+4/YoLc/CI43umjwIl9Q==" + }, + "System.Diagnostics.DiagnosticSource": { + "type": "Transitive", + "resolved": "8.0.1", + "contentHash": "vaoWjvkG1aenR2XdjaVivlCV9fADfgyhW5bZtXT23qaEea0lWiUljdQuze4E31vKM7ZWJaSUsbYIKE3rnzfZUg==" + }, + "System.IO.Pipelines": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "FHNOatmUq0sqJOkTx+UF/9YK1f180cnW5FVqnQMvYUN0elp6wFzbtPSiqbo1/ru8ICp43JM1i7kKkk6GsNGHlA==" + }, + "System.Memory": { + "type": "Transitive", + "resolved": "4.5.5", + "contentHash": "XIWiDvKPXaTveaB7HVganDlOCRoj03l+jrwNvcge/t8vhGYKvqV+dMv6G4SAX2NoNmN0wZfVPTAlFwZcZvVOUw==" + }, + "System.Runtime.CompilerServices.Unsafe": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg==" + }, + "System.Text.Encoding.CodePages": { + "type": "Transitive", + "resolved": "7.0.0", + "contentHash": "LSyCblMpvOe0N3E+8e0skHcrIhgV2huaNcjUUEa8hRtgEAm36aGkRoC8Jxlb6Ra6GSfF29ftduPNywin8XolzQ==" + }, + "System.Text.Encodings.Web": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "yev/k9GHAEGx2Rg3/tU6MQh4HGBXJs70y7j1LaM1i/ER9po+6nnQ6RRqTJn1E7Xu0fbIFK80Nh5EoODxrbxwBQ==" + }, + "System.Text.Json": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "OdrZO2WjkiEG6ajEFRABTRCi/wuXQPxeV6g8xvUJqdxMvvuCCEk86zPla8UiIQJz3durtUEbNyY/3lIhS0yZvQ==", + "dependencies": { + "System.Text.Encodings.Web": "8.0.0" + } + }, + "System.Threading.Channels": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "CMaFr7v+57RW7uZfZkPExsPB6ljwzhjACWW1gfU35Y56rk72B/Wu+sTqxVmGSk4SFUlPc3cjeKND0zktziyjBA==" + }, + "corercon": { + "type": "Project", + "dependencies": { + "CoreRCON.Parsers": "[1.0.0, )", + "System.Diagnostics.DiagnosticSource": "[8.0.1, )", + "System.IO.Pipelines": "[8.0.0, )" + } + }, + "corercon.extensions.counterstrike": { + "type": "Project", + "dependencies": { + "CoreRCON": "[6.0.0, )" + } + }, + "corercon.parsers": { + "type": "Project", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "[6.0.0, )" + } + }, + "cs2launcher.aspnetcore.app": { + "type": "Project", + "dependencies": { + "Microsoft.AspNetCore.Components.WebAssembly": "[8.0.4, )", + "Microsoft.AspNetCore.SignalR.Client": "[8.0.4, )", + "Microsoft.AspNetCore.SignalR.Protocols.MessagePack": "[8.0.4, )", + "Nito.AsyncEx.Coordination": "[5.1.2, )" + } } } }
Nothing to see here...