From f7de7bd430acec842875c50482d580f4b967e235 Mon Sep 17 00:00:00 2001 From: "Namhyeon, Go" Date: Sun, 6 Apr 2025 15:23:19 +0900 Subject: [PATCH 1/9] Add Cache Compression --- .../WelsonJS.Launcher/ResourceServer.cs | 43 ++++++++++++++++++- 1 file changed, 41 insertions(+), 2 deletions(-) diff --git a/WelsonJS.Toolkit/WelsonJS.Launcher/ResourceServer.cs b/WelsonJS.Toolkit/WelsonJS.Launcher/ResourceServer.cs index 02f3e0b..71c28e6 100644 --- a/WelsonJS.Toolkit/WelsonJS.Launcher/ResourceServer.cs +++ b/WelsonJS.Toolkit/WelsonJS.Launcher/ResourceServer.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.IO; +using System.IO.Compression; using System.Net; using System.Net.Http; using System.Reflection; @@ -213,7 +214,15 @@ namespace WelsonJS.Launcher { if (File.Exists(cachePath)) { - data = File.ReadAllBytes(cachePath); + byte[] raw = File.ReadAllBytes(cachePath); + + if (isMetadata) + { + data = raw; + return true; + } + + data = IsCompressed(raw) ? Decompress(raw) : raw; return true; } } @@ -255,7 +264,8 @@ namespace WelsonJS.Launcher } // Save the cache - File.WriteAllBytes(cachePath, data); + byte[] compressed = Compress(data); + File.WriteAllBytes(cachePath, compressed); // Save the cache meta File.WriteAllBytes($"{cachePath}.meta", Encoding.UTF8.GetBytes(mimeType)); @@ -360,5 +370,34 @@ namespace WelsonJS.Launcher return memoryStream.ToArray(); } } + + private byte[] Compress(byte[] data) + { + using (var output = new MemoryStream()) + { + using (var gzip = new GZipStream(output, CompressionMode.Compress)) + { + gzip.Write(data, 0, data.Length); + } + return output.ToArray(); // includes GZip signature + } + } + + private byte[] Decompress(byte[] data) + { + using (var input = new MemoryStream(data)) + using (var gzip = new GZipStream(input, CompressionMode.Decompress)) + using (var output = new MemoryStream()) + { + gzip.CopyTo(output); + return output.ToArray(); + } + } + + private bool IsCompressed(byte[] data) + { + // GZip signature: 0x1F 0x8B + return data != null && data.Length >= 2 && data[0] == 0x1F && data[1] == 0x8B; + } } } From a273d6aac6f6848bbb675dc9c8abb3d752827817 Mon Sep 17 00:00:00 2001 From: "Namhyeon, Go" Date: Mon, 7 Apr 2025 14:41:56 +0900 Subject: [PATCH 2/9] Update README.md --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index ebde194..be85a61 100644 --- a/README.md +++ b/README.md @@ -26,9 +26,10 @@ WelsonJS = ***W***indows + ***El***ectr***on***-like + ***Javascript(JS)*** + :h ## Sponsors - :octocat: [GitHub Sponsors](https://github.com/sponsors/gnh1201) +- :coffee: [Buy me a coffee](https://buymeacoffee.com/catswords) - [Open Software Portal](https://oss.kr), Korea National Industry Promotion Agency - Awarded Prize - Free code signing provided by [SignPath.io](https://signpath.io), certificate by [SignPath Foundation](https://signpath.org/) -- [F1Security](https://azuremarketplace.microsoft.com/ko-kr/marketplace/apps/1599123192819.uwss?tab=overview) provides web security services designed by [industry-leading experts](https://www.ksecurity.or.kr/kisis/subIndex/469.do). +- [F1Security](https://f1security.co.kr/) provides [industry-leading]((https://www.ksecurity.or.kr/kisis/subIndex/469.do) web security services. - [Microsoft ISV Success Program](https://www.microsoft.com/en-us/isv/isv-success), Grow your business with powerful tools. - :zap: [Integrations](https://catswords-oss.rdbl.io/5719744820/8278298336) ([ScrapeOps](https://scrapeops.io?fpr=namhyeon75), [SearchApi](https://www.searchapi.io/?via=namhyeon), [AviationStack](https://aviationstack.com?utm_source=FirstPromoter&utm_medium=Affiliate&fpr=namhyeon71), [Coupang](https://link.coupang.com/a/b7HV3V)...) From 53a84b23497bad78286e82d7a0132f8b133d9da9 Mon Sep 17 00:00:00 2001 From: "Namhyeon, Go" Date: Mon, 7 Apr 2025 14:45:25 +0900 Subject: [PATCH 3/9] Update README.md --- README.md | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index be85a61..a329e7b 100644 --- a/README.md +++ b/README.md @@ -20,16 +20,16 @@ Now, You can build a Windows desktop app with JavaScript, TypeScript, CoffeeScri WelsonJS = ***W***indows + ***El***ectr***on***-like + ***Javascript(JS)*** + :heart:[Contributions](https://github.com/sponsors/gnh1201) -:kissing_cat: [Download Latest WelsonJS Launcher (ics.catswords.net)](https://ics.catswords.net/welsonjs_launcher_latest.zip) +* :kissing_cat: [Download Latest WelsonJS Launcher (ics.catswords.net)](https://ics.catswords.net/welsonjs_launcher_latest.zip) +* :rocket: [Launch the WelsonJS environment on Microsoft Azure (azuremarketplace.microsoft.com)](https://azuremarketplace.microsoft.com/en-us/marketplace/apps/catswords.catswords-welsonjs-feb2025-02?tab=Overview) **Note**: The default license for this project is GPL 3.0. However, if the GPL 3.0 license is not compatible with Microsoft products, it is subject to the MS-RL license. ## Sponsors -- :octocat: [GitHub Sponsors](https://github.com/sponsors/gnh1201) -- :coffee: [Buy me a coffee](https://buymeacoffee.com/catswords) -- [Open Software Portal](https://oss.kr), Korea National Industry Promotion Agency - Awarded Prize +- :octocat: [GitHub Sponsors](https://github.com/sponsors/gnh1201), :coffee: [Buy me a coffee](https://buymeacoffee.com/catswords) +- [Open SW Portal](https://oss.kr), NIPA National IT Industry Promotion Agency(정보통신산업진흥원) - Free code signing provided by [SignPath.io](https://signpath.io), certificate by [SignPath Foundation](https://signpath.org/) -- [F1Security](https://f1security.co.kr/) provides [industry-leading]((https://www.ksecurity.or.kr/kisis/subIndex/469.do) web security services. +- [F1Security(에프원시큐리티)](https://f1security.co.kr/) provides [industry-leading](https://www.ksecurity.or.kr/kisis/subIndex/469.do) web security services. - [Microsoft ISV Success Program](https://www.microsoft.com/en-us/isv/isv-success), Grow your business with powerful tools. - :zap: [Integrations](https://catswords-oss.rdbl.io/5719744820/8278298336) ([ScrapeOps](https://scrapeops.io?fpr=namhyeon75), [SearchApi](https://www.searchapi.io/?via=namhyeon), [AviationStack](https://aviationstack.com?utm_source=FirstPromoter&utm_medium=Affiliate&fpr=namhyeon71), [Coupang](https://link.coupang.com/a/b7HV3V)...) @@ -62,7 +62,7 @@ WelsonJS is tailored for developers who need a reliable, lightweight JavaScript ## Specifications - Built-in transpilers: [TypeScript](https://www.typescriptlang.org/), [Rescript](https://rescript-lang.org/), [CoffeeScript 2](https://coffeescript.org/), [LiveScript](https://livescript.net/) - **Ready to use on Windows machine immediately. No require additional software installation.** -- **WelsonJS Launcher**: Instance management (You can manage previously run apps), User-defined variable editor (You can pass user-defined variables if needed), [Microsoft Monaco Editor](https://github.com/microsoft/monaco-editor) (You can edit code without installing an additional editor). +- **WelsonJS Launcher**: Manage an instances (Like a container), User-defined variable editor, [Microsoft Monaco Editor](https://github.com/microsoft/monaco-editor) (Pre-embedded rich code editor), [Microsoft Copilot](https://copilot.microsoft.com) on the code editor. - ES5(ECMAScript 5), XML, JSON, YAML compatibility: [core-js](https://github.com/zloirock/core-js), [JSON2.js](https://github.com/douglascrockford/JSON-js), [js-yaml](https://github.com/nodeca/js-yaml) - HTML5, CSS3 compatibility: [html5shiv](https://github.com/aFarkas/html5shiv), [jquery-html5-placeholder-shim](https://github.com/parndt/jquery-html5-placeholder-shim), [Respond](https://github.com/scottjehl/Respond), [selectivizr](https://github.com/keithclark/selectivizr), [ExplorerCanvas](https://github.com/arv/ExplorerCanvas), [Modernizr](https://github.com/Modernizr/Modernizr) - Classical CSS Frameworks: [cascadeframework](https://github.com/jslegers/cascadeframework), [golden-layout](https://github.com/golden-layout/golden-layout) @@ -137,9 +137,12 @@ The WelsonJS framework suggests the following application release methods: ![(Screenshot 6) The Launcher for WelsonJS Application Packages](https://ics.catswords.net/screenshot6.png) +![(Screenshot 7) Microsoft Monaco Editor on WelsonJS Launcher](https://ics.catswords.net/screenshot7.png) + ## Thanks to - :heart: Artwork (Logo image): [@druidesse](https://github.com/druidesse) - :heart: Artwork (Cover image): [@_bag0@x.com](https://x.com/_bag0) +- :heart: Special Contributor: [@hcho3](https://github.com/hcho3) - :sunglasses: Heavy-industry specialized CSP(Cloud Service Provider) in Republic of Korea - Use case establishment - :sunglasses: Live-commerce specialized online advertisement companies in Republic of Korea - Use case establishment - :sunglasses: Information security companies in Republic of Korea - Use case establishment From 916154499c0347087427813bd4f3746326c831f4 Mon Sep 17 00:00:00 2001 From: "Namhyeon, Go" Date: Wed, 9 Apr 2025 19:58:41 +0900 Subject: [PATCH 4/9] Some updates --- .../WelsonJS.Launcher/MainForm.cs | 5 +--- WelsonJS.Toolkit/WelsonJS.Launcher/Program.cs | 13 +++++++-- .../ResourceTools/AzureAi.cs | 29 +++++++++++++++++++ .../WelsonJS.Launcher.csproj | 2 +- .../WelsonJS.Launcher/editor.html | 25 ++++++---------- 5 files changed, 51 insertions(+), 23 deletions(-) create mode 100644 WelsonJS.Toolkit/WelsonJS.Launcher/ResourceTools/AzureAi.cs diff --git a/WelsonJS.Toolkit/WelsonJS.Launcher/MainForm.cs b/WelsonJS.Toolkit/WelsonJS.Launcher/MainForm.cs index 11e21e5..dcb3ce2 100644 --- a/WelsonJS.Toolkit/WelsonJS.Launcher/MainForm.cs +++ b/WelsonJS.Toolkit/WelsonJS.Launcher/MainForm.cs @@ -242,10 +242,7 @@ namespace WelsonJS.Launcher private void startCodeEditorToolStripMenuItem_Click(object sender, EventArgs e) { - if (Program.resourceServer == null) - { - Program.resourceServer = new ResourceServer(Program.GetAppConfig("ResourceServerPrefix"), "editor.html"); - } + Program.StartResourceServer(); if (!Program.resourceServer.IsRunning()) { diff --git a/WelsonJS.Toolkit/WelsonJS.Launcher/Program.cs b/WelsonJS.Toolkit/WelsonJS.Launcher/Program.cs index aebad66..f7abf6b 100644 --- a/WelsonJS.Toolkit/WelsonJS.Launcher/Program.cs +++ b/WelsonJS.Toolkit/WelsonJS.Launcher/Program.cs @@ -138,13 +138,22 @@ namespace WelsonJS.Launcher return workingDirectory; } + public static void StartResourceServer() + { + if (resourceServer == null) + { + resourceServer = new ResourceServer(GetAppConfig("ResourceServerPrefix"), "editor.html"); + } + } + public static void OpenWebBrowser(string url) { string userDataDir = Path.Combine(GetAppDataPath(), "EdgeUserProfile"); - string remoteAllowOrigins = "http://localhost:3000"; + string remoteAllowOrigins = GetAppConfig("ResourceServerPrefix"); + int remoteDebuggingPort = new Uri(GetAppConfig("DevToolsPrefix")).Port; string[] arguments = { $"\"{url}\"", - "--remote-debugging-port=9222", + $"--remote-debugging-port={remoteDebuggingPort}", $"--remote-allow-origins={remoteAllowOrigins}", // for security reason $"--user-data-dir=\"{userDataDir}\"" }; diff --git a/WelsonJS.Toolkit/WelsonJS.Launcher/ResourceTools/AzureAi.cs b/WelsonJS.Toolkit/WelsonJS.Launcher/ResourceTools/AzureAi.cs new file mode 100644 index 0000000..34440a4 --- /dev/null +++ b/WelsonJS.Toolkit/WelsonJS.Launcher/ResourceTools/AzureAi.cs @@ -0,0 +1,29 @@ +using System; +using System.Net; +using System.Threading.Tasks; + +namespace WelsonJS.Launcher.ResourceTools +{ + public class AzureAi : IResourceTool + { + private ResourceServer Server; + private const string Prefix = "azure-ai/"; + + public AzureAi(ResourceServer server) + { + Server = server; + } + + public bool CanHandle(string path) + { + return path.StartsWith(Prefix, StringComparison.OrdinalIgnoreCase); + } + + public async Task HandleAsync(HttpListenerContext context, string path) + { + await Task.Delay(0); + + // TODO: Pass Azure AI request to Azure AI Foundry + } + } +} \ No newline at end of file diff --git a/WelsonJS.Toolkit/WelsonJS.Launcher/WelsonJS.Launcher.csproj b/WelsonJS.Toolkit/WelsonJS.Launcher/WelsonJS.Launcher.csproj index df1cc5c..731acee 100644 --- a/WelsonJS.Toolkit/WelsonJS.Launcher/WelsonJS.Launcher.csproj +++ b/WelsonJS.Toolkit/WelsonJS.Launcher/WelsonJS.Launcher.csproj @@ -74,6 +74,7 @@ + @@ -165,6 +166,5 @@ - \ No newline at end of file diff --git a/WelsonJS.Toolkit/WelsonJS.Launcher/editor.html b/WelsonJS.Toolkit/WelsonJS.Launcher/editor.html index 53a1b50..3e49309 100644 --- a/WelsonJS.Toolkit/WelsonJS.Launcher/editor.html +++ b/WelsonJS.Toolkit/WelsonJS.Launcher/editor.html @@ -50,16 +50,14 @@ Save File - - - - Common + Generative
- - Network tools + Network
@@ -240,18 +237,14 @@ document.body.removeChild(a); }; - document.getElementById("btnSponsor").onclick = function () { - navigate('https://github.com/sponsors/gnh1201'); - }; - - document.getElementById("btnGenerate").onclick = function () { + document.getElementById("btnCopilot").onclick = function () { const promptMessage = prompt("Enter a prompt message:", ''); if (!promptMessage || promptMessage.trim() == '') { alert("A prompt message is required."); return; } - appendTextToEditor(`\n//${promptMessage}... Thinking with Generative AI...`); + appendTextToEditor(`\n//${promptMessage}... Generating text with Copilot...`); (async function () { const targetWsUrl = await getTargetByUrl('copilot.microsoft.com'); From 2a9ebaff519fe1c08f16ca48c3e995cdc829d991 Mon Sep 17 00:00:00 2001 From: "Namhyeon, Go" Date: Thu, 10 Apr 2025 01:48:33 +0900 Subject: [PATCH 5/9] Update AzureAi.cs --- .../ResourceTools/AzureAi.cs | 112 +++++++++++++++++- 1 file changed, 110 insertions(+), 2 deletions(-) diff --git a/WelsonJS.Toolkit/WelsonJS.Launcher/ResourceTools/AzureAi.cs b/WelsonJS.Toolkit/WelsonJS.Launcher/ResourceTools/AzureAi.cs index 34440a4..70decad 100644 --- a/WelsonJS.Toolkit/WelsonJS.Launcher/ResourceTools/AzureAi.cs +++ b/WelsonJS.Toolkit/WelsonJS.Launcher/ResourceTools/AzureAi.cs @@ -1,5 +1,8 @@ using System; +using System.IO; using System.Net; +using System.Net.Http; +using System.Text; using System.Threading.Tasks; namespace WelsonJS.Launcher.ResourceTools @@ -7,11 +10,18 @@ namespace WelsonJS.Launcher.ResourceTools public class AzureAi : IResourceTool { private ResourceServer Server; + private static readonly HttpClient HttpClient = new HttpClient(); private const string Prefix = "azure-ai/"; + private const int StreamingBufferSize = 4096; + private readonly string AzureAiServiceUrl; + private readonly string AzureAiServiceApiKey; public AzureAi(ResourceServer server) { Server = server; + + AzureAiServiceUrl = Program.GetAppConfig("AzureAiServiceUrl"); + AzureAiServiceApiKey = Program.GetAppConfig("AzureAiServiceApiKey"); } public bool CanHandle(string path) @@ -21,9 +31,107 @@ namespace WelsonJS.Launcher.ResourceTools public async Task HandleAsync(HttpListenerContext context, string path) { - await Task.Delay(0); + string apiKey = AzureAiServiceApiKey; + if (string.IsNullOrEmpty(apiKey)) + { + WriteError(context, "Missing 'api-key' header.", HttpStatusCode.BadRequest); + return; + } - // TODO: Pass Azure AI request to Azure AI Foundry + string requestBody = ReadRequestBody(context); + bool isStreaming = ContainsSequentialKeywords(requestBody, new[] { "\"stream\"", "true" }, 30); + + try + { + using (var response = await SendAzureRequestAsync(apiKey, requestBody, isStreaming)) + { + await ForwardResponseAsync(context, response, isStreaming); + } + } + catch (HttpRequestException ex) + { + WriteError(context, "Request error: " + ex.Message, HttpStatusCode.BadGateway); + } + } + + private string ReadRequestBody(HttpListenerContext context) + { + using (var reader = new StreamReader(context.Request.InputStream, context.Request.ContentEncoding)) + { + return reader.ReadToEnd(); + } + } + + private async Task SendAzureRequestAsync(string apiKey, string requestBody, bool isStreaming) + { + var requestMessage = new HttpRequestMessage(HttpMethod.Post, AzureAiServiceUrl); + requestMessage.Headers.Add("api-key", apiKey); + requestMessage.Content = new StringContent(requestBody, Encoding.UTF8, "application/json"); + + var completionOption = isStreaming + ? HttpCompletionOption.ResponseHeadersRead + : HttpCompletionOption.ResponseContentRead; + + return await HttpClient.SendAsync(requestMessage, completionOption); + } + + private async Task ForwardResponseAsync(HttpListenerContext context, HttpResponseMessage response, bool isStreaming) + { + context.Response.StatusCode = (int)response.StatusCode; + context.Response.ContentType = response.Content.Headers.ContentType?.ToString() ?? "application/json"; + + using (var responseStream = await response.Content.ReadAsStreamAsync()) + { + if (isStreaming) + { + context.Response.SendChunked = true; + context.Response.Headers.Add("Transfer-Encoding", "chunked"); + context.Response.Headers.Add("Cache-Control", "no-cache"); + + byte[] buffer = new byte[StreamingBufferSize]; + int bytesRead; + while ((bytesRead = await responseStream.ReadAsync(buffer, 0, buffer.Length)) > 0) + { + await context.Response.OutputStream.WriteAsync(buffer, 0, bytesRead); + context.Response.OutputStream.Flush(); + } + } + else + { + await responseStream.CopyToAsync(context.Response.OutputStream); + } + } + } + + private void WriteError(HttpListenerContext context, string message, HttpStatusCode statusCode) + { + context.Response.StatusCode = (int)statusCode; + using (var writer = new StreamWriter(context.Response.OutputStream, Encoding.UTF8)) + { + writer.Write(message); + } + } + + public static bool ContainsSequentialKeywords(string input, string[] keywords, int maxDistance) + { + if (input == null || keywords == null || keywords.Length < 2) + return false; + + int position = 0; + + for (int i = 0; i < keywords.Length; i++) + { + int index = input.IndexOf(keywords[i], position, StringComparison.OrdinalIgnoreCase); + if (index < 0) + return false; + + if (i > 0 && (index - position) > maxDistance) + return false; + + position = index + keywords[i].Length; + } + + return true; } } } \ No newline at end of file From 1742ca385b719bd9be731a4fa5854cd549f6c0b6 Mon Sep 17 00:00:00 2001 From: "Namhyeon, Go" Date: Thu, 10 Apr 2025 02:00:18 +0900 Subject: [PATCH 6/9] Update AzureAi.cs --- .../ResourceTools/AzureAi.cs | 24 ++++++++++--------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/WelsonJS.Toolkit/WelsonJS.Launcher/ResourceTools/AzureAi.cs b/WelsonJS.Toolkit/WelsonJS.Launcher/ResourceTools/AzureAi.cs index 70decad..147e78a 100644 --- a/WelsonJS.Toolkit/WelsonJS.Launcher/ResourceTools/AzureAi.cs +++ b/WelsonJS.Toolkit/WelsonJS.Launcher/ResourceTools/AzureAi.cs @@ -10,9 +10,8 @@ namespace WelsonJS.Launcher.ResourceTools public class AzureAi : IResourceTool { private ResourceServer Server; - private static readonly HttpClient HttpClient = new HttpClient(); private const string Prefix = "azure-ai/"; - private const int StreamingBufferSize = 4096; + private const int ChunkSize = 4096; private readonly string AzureAiServiceUrl; private readonly string AzureAiServiceApiKey; @@ -34,7 +33,7 @@ namespace WelsonJS.Launcher.ResourceTools string apiKey = AzureAiServiceApiKey; if (string.IsNullOrEmpty(apiKey)) { - WriteError(context, "Missing 'api-key' header.", HttpStatusCode.BadRequest); + WriteError(context, "Missing the API key.", HttpStatusCode.BadRequest); return; } @@ -64,15 +63,18 @@ namespace WelsonJS.Launcher.ResourceTools private async Task SendAzureRequestAsync(string apiKey, string requestBody, bool isStreaming) { - var requestMessage = new HttpRequestMessage(HttpMethod.Post, AzureAiServiceUrl); - requestMessage.Headers.Add("api-key", apiKey); - requestMessage.Content = new StringContent(requestBody, Encoding.UTF8, "application/json"); + using (var client = new HttpClient()) + { + var requestMessage = new HttpRequestMessage(HttpMethod.Post, AzureAiServiceUrl); + requestMessage.Headers.Add("api-key", apiKey); + requestMessage.Content = new StringContent(requestBody, Encoding.UTF8, "application/json"); - var completionOption = isStreaming - ? HttpCompletionOption.ResponseHeadersRead - : HttpCompletionOption.ResponseContentRead; + var completionOption = isStreaming + ? HttpCompletionOption.ResponseHeadersRead + : HttpCompletionOption.ResponseContentRead; - return await HttpClient.SendAsync(requestMessage, completionOption); + return await client.SendAsync(requestMessage, completionOption); + } } private async Task ForwardResponseAsync(HttpListenerContext context, HttpResponseMessage response, bool isStreaming) @@ -88,7 +90,7 @@ namespace WelsonJS.Launcher.ResourceTools context.Response.Headers.Add("Transfer-Encoding", "chunked"); context.Response.Headers.Add("Cache-Control", "no-cache"); - byte[] buffer = new byte[StreamingBufferSize]; + byte[] buffer = new byte[ChunkSize]; int bytesRead; while ((bytesRead = await responseStream.ReadAsync(buffer, 0, buffer.Length)) > 0) { From f84f2195c3bc3bba67e0a5a23159b444e6e1348f Mon Sep 17 00:00:00 2001 From: "Namhyeon, Go" Date: Thu, 10 Apr 2025 02:12:28 +0900 Subject: [PATCH 7/9] Revert Cache Compression --- .../WelsonJS.Launcher/ResourceServer.cs | 42 +------------------ 1 file changed, 2 insertions(+), 40 deletions(-) diff --git a/WelsonJS.Toolkit/WelsonJS.Launcher/ResourceServer.cs b/WelsonJS.Toolkit/WelsonJS.Launcher/ResourceServer.cs index 71c28e6..c218177 100644 --- a/WelsonJS.Toolkit/WelsonJS.Launcher/ResourceServer.cs +++ b/WelsonJS.Toolkit/WelsonJS.Launcher/ResourceServer.cs @@ -214,15 +214,7 @@ namespace WelsonJS.Launcher { if (File.Exists(cachePath)) { - byte[] raw = File.ReadAllBytes(cachePath); - - if (isMetadata) - { - data = raw; - return true; - } - - data = IsCompressed(raw) ? Decompress(raw) : raw; + data = File.ReadAllBytes(cachePath); return true; } } @@ -264,8 +256,7 @@ namespace WelsonJS.Launcher } // Save the cache - byte[] compressed = Compress(data); - File.WriteAllBytes(cachePath, compressed); + File.WriteAllBytes(cachePath, data); // Save the cache meta File.WriteAllBytes($"{cachePath}.meta", Encoding.UTF8.GetBytes(mimeType)); @@ -370,34 +361,5 @@ namespace WelsonJS.Launcher return memoryStream.ToArray(); } } - - private byte[] Compress(byte[] data) - { - using (var output = new MemoryStream()) - { - using (var gzip = new GZipStream(output, CompressionMode.Compress)) - { - gzip.Write(data, 0, data.Length); - } - return output.ToArray(); // includes GZip signature - } - } - - private byte[] Decompress(byte[] data) - { - using (var input = new MemoryStream(data)) - using (var gzip = new GZipStream(input, CompressionMode.Decompress)) - using (var output = new MemoryStream()) - { - gzip.CopyTo(output); - return output.ToArray(); - } - } - - private bool IsCompressed(byte[] data) - { - // GZip signature: 0x1F 0x8B - return data != null && data.Length >= 2 && data[0] == 0x1F && data[1] == 0x8B; - } } } From 8ca4faa88ae08aea4614e6e3cce9b2caad5e312a Mon Sep 17 00:00:00 2001 From: "Namhyeon, Go" Date: Thu, 10 Apr 2025 02:23:24 +0900 Subject: [PATCH 8/9] Update README.md Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com> --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a329e7b..645f791 100644 --- a/README.md +++ b/README.md @@ -62,7 +62,7 @@ WelsonJS is tailored for developers who need a reliable, lightweight JavaScript ## Specifications - Built-in transpilers: [TypeScript](https://www.typescriptlang.org/), [Rescript](https://rescript-lang.org/), [CoffeeScript 2](https://coffeescript.org/), [LiveScript](https://livescript.net/) - **Ready to use on Windows machine immediately. No require additional software installation.** -- **WelsonJS Launcher**: Manage an instances (Like a container), User-defined variable editor, [Microsoft Monaco Editor](https://github.com/microsoft/monaco-editor) (Pre-embedded rich code editor), [Microsoft Copilot](https://copilot.microsoft.com) on the code editor. +- **WelsonJS Launcher**: Manage instances (Like a container), User-defined variable editor, [Microsoft Monaco Editor](https://github.com/microsoft/monaco-editor) (Pre-embedded rich code editor), [Microsoft Copilot](https://copilot.microsoft.com) on the code editor. - ES5(ECMAScript 5), XML, JSON, YAML compatibility: [core-js](https://github.com/zloirock/core-js), [JSON2.js](https://github.com/douglascrockford/JSON-js), [js-yaml](https://github.com/nodeca/js-yaml) - HTML5, CSS3 compatibility: [html5shiv](https://github.com/aFarkas/html5shiv), [jquery-html5-placeholder-shim](https://github.com/parndt/jquery-html5-placeholder-shim), [Respond](https://github.com/scottjehl/Respond), [selectivizr](https://github.com/keithclark/selectivizr), [ExplorerCanvas](https://github.com/arv/ExplorerCanvas), [Modernizr](https://github.com/Modernizr/Modernizr) - Classical CSS Frameworks: [cascadeframework](https://github.com/jslegers/cascadeframework), [golden-layout](https://github.com/golden-layout/golden-layout) From d42210f9225023f290f3506c8e51970b9d374d4f Mon Sep 17 00:00:00 2001 From: "Namhyeon, Go" Date: Thu, 10 Apr 2025 02:27:42 +0900 Subject: [PATCH 9/9] Update WelsonJS.Toolkit/WelsonJS.Launcher/Program.cs Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- WelsonJS.Toolkit/WelsonJS.Launcher/Program.cs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/WelsonJS.Toolkit/WelsonJS.Launcher/Program.cs b/WelsonJS.Toolkit/WelsonJS.Launcher/Program.cs index f7abf6b..cb51fca 100644 --- a/WelsonJS.Toolkit/WelsonJS.Launcher/Program.cs +++ b/WelsonJS.Toolkit/WelsonJS.Launcher/Program.cs @@ -140,12 +140,14 @@ namespace WelsonJS.Launcher public static void StartResourceServer() { - if (resourceServer == null) + lock(typeof(Program)) { - resourceServer = new ResourceServer(GetAppConfig("ResourceServerPrefix"), "editor.html"); + if (resourceServer == null) + { + resourceServer = new ResourceServer(GetAppConfig("ResourceServerPrefix"), "editor.html"); + } } } - public static void OpenWebBrowser(string url) { string userDataDir = Path.Combine(GetAppDataPath(), "EdgeUserProfile");