Skip to content

Commit 6d7a1d8

Browse files
authored
feat: add ClientGeneratorService for single-file client/upgrade code (#34)
- Generates client.cs and upgrade.cs using #r nuget: inline references - Client uses GeneralUpdate.ClientCore to poll for updates - Upgrade uses GeneralUpdate.Core to apply patches - Templates replace placeholders (version, URL, keys, paths) - Added ServerPort to SimulateConfigModel
1 parent 9c98870 commit 6d7a1d8

2 files changed

Lines changed: 150 additions & 0 deletions

File tree

src/Models/SimulateConfigModel.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,7 @@ public partial class SimulateConfigModel : ObservableObject
3333

3434
/// <summary>Directory where client.cs / upgrade.cs and server are generated.</summary>
3535
[ObservableProperty] private string _outputDirectory = string.Empty;
36+
37+
/// <summary>Server port assigned at runtime (set by SimulationService).</summary>
38+
public int ServerPort { get; set; } = 5000;
3639
}
Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
using System;
2+
using System.IO;
3+
using System.Text;
4+
using System.Threading.Tasks;
5+
using GeneralUpdate.Tools.Models;
6+
7+
namespace GeneralUpdate.Tools.Services;
8+
9+
/// <summary>
10+
/// Generates single-file client.cs and upgrade.cs for simulation,
11+
/// using dotnet-run (#r nuget:...) without project files.
12+
/// </summary>
13+
public class ClientGeneratorService
14+
{
15+
private const string ClientTemplate = """
16+
#r "nuget: GeneralUpdate.ClientCore, 10.*"
17+
#r "nuget: GeneralUpdate.Core, 10.*"
18+
19+
using GeneralUpdate.ClientCore;
20+
using GeneralUpdate.Common.Shared.Object;
21+
using GeneralUpdate.Common.Internal.Event;
22+
23+
var log = (string msg) => Console.WriteLine($"[{DateTime.Now:HH:mm:ss}] {msg}");
24+
25+
try
26+
{{
27+
log("Client started");
28+
log("Install path: {0}");
29+
30+
var config = new Configinfo
31+
{{
32+
ReportUrl = "{1}/Upgrade/Report",
33+
UpdateUrl = "{1}/Upgrade/Verification",
34+
AppName = "{2}",
35+
MainAppName = "{3}",
36+
InstallPath = @"{0}",
37+
ClientVersion = "{4}",
38+
UpgradeClientVersion = "{5}",
39+
ProductId = "{6}",
40+
AppSecretKey = "{7}",
41+
}};
42+
43+
await new GeneralClientBootstrap()
44+
.SetConfig(config)
45+
.AddListenerMultiDownloadStatistics((_, e) =>
46+
{{
47+
var v = e.Version as VersionInfo;
48+
log($"Download: {{v?.Version}} {{e.ProgressPercentage}}% {{e.Speed}}/s");
49+
}})
50+
.AddListenerMultiAllDownloadCompleted((_, e) =>
51+
{{
52+
log(e.IsAllDownloadCompleted ? "All downloads completed" : $"Download failed: {{e.FailedVersions.Count}}");
53+
}})
54+
.AddListenerException((_, e) =>
55+
{{
56+
log($"ERROR: {{e.Exception}}");
57+
}})
58+
.AddListenerUpdateInfo((_, e) =>
59+
{{
60+
log($"Update info: Code={{e.Info.Code}}, Versions={{e.Info.Body?.Count ?? 0}}");
61+
}})
62+
.LaunchAsync();
63+
64+
log("Update process completed");
65+
}}
66+
catch (Exception ex)
67+
{{
68+
log($"FATAL: {{ex.Message}}");
69+
Console.Error.WriteLine(ex);
70+
Environment.Exit(1);
71+
}}
72+
""";
73+
74+
private const string UpgradeTemplate = """
75+
#r "nuget: GeneralUpdate.Core, 10.*"
76+
#r "nuget: GeneralUpdate.ClientCore, 10.*"
77+
78+
using GeneralUpdate.Core;
79+
using GeneralUpdate.Common.Shared;
80+
using GeneralUpdate.Common.Internal.Event;
81+
82+
var log = (string msg) => Console.WriteLine($"[{DateTime.Now:HH:mm:ss}] {msg}");
83+
84+
try
85+
{{
86+
log("Upgrade process started");
87+
log("Working directory: " + Environment.CurrentDirectory);
88+
89+
await new GeneralUpdateBootstrap()
90+
.AddListenerMultiDownloadStatistics((_, e) =>
91+
{{
92+
var v = e.Version as GeneralUpdate.Common.Shared.Object.VersionInfo;
93+
log($"Download: {{v?.Version}} {{e.ProgressPercentage}}%");
94+
}})
95+
.AddListenerMultiAllDownloadCompleted((_, e) =>
96+
{{
97+
log(e.IsAllDownloadCompleted ? "Downloads done" : "Download failed");
98+
}})
99+
.AddListenerException((_, e) =>
100+
{{
101+
log($"ERROR: {{e.Exception}}");
102+
}})
103+
.LaunchAsync();
104+
105+
log("Upgrade process finished successfully");
106+
}}
107+
catch (Exception ex)
108+
{{
109+
log($"FATAL: {{ex.Message}}");
110+
Console.Error.WriteLine(ex);
111+
Environment.Exit(1);
112+
}}
113+
""";
114+
115+
public async Task GenerateAsync(SimulateConfigModel config, string outputDir)
116+
{
117+
var serverUrl = $"http://127.0.0.1:{config.ServerPort}";
118+
119+
// client.cs
120+
var clientCode = string.Format(ClientTemplate,
121+
EscapeForCSharp(config.AppDirectory),
122+
serverUrl,
123+
"upgrade.cs", // AppName - the upgrade process
124+
"client.cs", // MainAppName
125+
config.CurrentVersion,
126+
"1.0.0.0", // upgrade client version
127+
config.ProductId,
128+
config.AppSecretKey);
129+
130+
await File.WriteAllTextAsync(
131+
Path.Combine(outputDir, "client.cs"),
132+
clientCode,
133+
Encoding.UTF8);
134+
135+
// upgrade.cs
136+
var upgradeCode = string.Format(UpgradeTemplate,
137+
EscapeForCSharp(config.AppDirectory));
138+
139+
await File.WriteAllTextAsync(
140+
Path.Combine(outputDir, "upgrade.cs"),
141+
upgradeCode,
142+
Encoding.UTF8);
143+
}
144+
145+
private static string EscapeForCSharp(string s) =>
146+
s.Replace(@"\", @"\\").Replace("\"", "\\\"");
147+
}

0 commit comments

Comments
 (0)