From f0ee5dcd4a3e0be5be19cf08f638258ccbd87f5c Mon Sep 17 00:00:00 2001 From: "Diogo Paulo (dpa)" Date: Thu, 16 Jul 2026 22:34:36 +0100 Subject: [PATCH 1/2] update to .net10 --- .gitignore | 3 +++ ARCHITECTURE.md | 4 ++-- CLAUDE.md | 8 ++++---- .../UltimatePDF_ExternalLogic.E2ETests.csproj | 4 ++-- .../UltimatePDF_ExternalLogic.IntegrationTests.csproj | 2 +- .../UltimatePDF_ExternalLogic.Test.Helpers.csproj | 4 ++-- src/UltimatePDF_ExternalLogic.UnitTests/PipelineTests.cs | 2 +- .../UltimatePDF_ExternalLogic.UnitTests.csproj | 2 +- .../UltimatePDF_ExternalLogic.csproj | 6 +++--- 9 files changed, 19 insertions(+), 16 deletions(-) diff --git a/.gitignore b/.gitignore index cd59838..6f0d0dc 100644 --- a/.gitignore +++ b/.gitignore @@ -19,3 +19,6 @@ src/UltimatePDF_ExternalLogic.E2ETests/appsettings.local.json # IDE launch profiles src/**/Properties/launchSettings.json + +# AI working folder +specs/ \ No newline at end of file diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index bffba74..127aa36 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -117,7 +117,7 @@ This component operates within ODC's external logic environment, subject to: ## Deployment -The library is packaged as a ZIP file containing compiled .NET 8.0 binaries for linux-x64 runtime. Generate the package by running: +The library is packaged as a ZIP file containing compiled .NET 10.0 binaries for linux-x64 runtime. Generate the package by running: ```bash .\generate_upload_package.ps1 @@ -132,7 +132,7 @@ Companion OutSystems modules in the `oml/` directory provide client-side acceler ## Technology Stack -- **.NET 8.0:** Target framework for ODC external logic +- **.NET 10.0:** Target framework for ODC external logic - **PuppeteerSharp:** Browser automation library wrapping Chromium DevTools Protocol - **HeadlessChromium.Puppeteer.Lambda.Dotnet:** Provides Chromium binaries compatible with AWS Lambda (ODC infrastructure) - **PDFsharp 6.2.0:** PDF manipulation for merging layers (backgrounds, headers, footers) diff --git a/CLAUDE.md b/CLAUDE.md index 2d1a94b..eada4e4 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -4,7 +4,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co ## Overview -UltimatePDF-ExternalLogic is an OutSystems Developer Cloud (ODC) external logic component that generates PDFs from web pages using Chromium's rendering engine. The code is written in C# targeting .NET 8.0 and runs within ODC's managed infrastructure. +UltimatePDF-ExternalLogic is an OutSystems Developer Cloud (ODC) external logic component that generates PDFs from web pages using Chromium's rendering engine. The code is written in C# targeting .NET 10.0 and runs within ODC's managed infrastructure. For system architecture and design patterns, see [ARCHITECTURE.md](./ARCHITECTURE.md). For development workflow and contribution guidelines, see [CONTRIBUTING.md](./CONTRIBUTING.md). @@ -143,10 +143,10 @@ See `LayoutPrintPipeline/Pipeline.cs` methods (`MergeBackground`, `MergeHeaders` ## Technology Stack -- **.NET 8.0** - Target framework for ODC external logic +- **.NET 10.0** - Target framework for ODC external logic - **PuppeteerSharp** - Browser automation via Chrome DevTools Protocol -- **HeadlessChromium.Puppeteer.Lambda.Dotnet** (v1.1.0.97) - Chromium binaries for AWS Lambda (ODC infrastructure) -- **PDFsharp** (v6.2.0) - PDF layer composition +- **HeadlessChromium.Puppeteer.Dotnet.OS.Fork** (v1.1.1.1) - Chromium binaries for AWS Lambda (ODC infrastructure) +- **PDFsharp** (v6.2.4) - PDF layer composition - **OutSystems.ExternalLibraries.SDK** (v1.5.0) - ODC external logic framework ## Additional Resources diff --git a/src/UltimatePDF_ExternalLogic.E2ETests/UltimatePDF_ExternalLogic.E2ETests.csproj b/src/UltimatePDF_ExternalLogic.E2ETests/UltimatePDF_ExternalLogic.E2ETests.csproj index e294bf3..6d22db6 100644 --- a/src/UltimatePDF_ExternalLogic.E2ETests/UltimatePDF_ExternalLogic.E2ETests.csproj +++ b/src/UltimatePDF_ExternalLogic.E2ETests/UltimatePDF_ExternalLogic.E2ETests.csproj @@ -1,7 +1,7 @@ - net8.0 + net10.0 enable enable false @@ -18,7 +18,7 @@ - + diff --git a/src/UltimatePDF_ExternalLogic.IntegrationTests/UltimatePDF_ExternalLogic.IntegrationTests.csproj b/src/UltimatePDF_ExternalLogic.IntegrationTests/UltimatePDF_ExternalLogic.IntegrationTests.csproj index ee03e23..8bd4225 100644 --- a/src/UltimatePDF_ExternalLogic.IntegrationTests/UltimatePDF_ExternalLogic.IntegrationTests.csproj +++ b/src/UltimatePDF_ExternalLogic.IntegrationTests/UltimatePDF_ExternalLogic.IntegrationTests.csproj @@ -1,7 +1,7 @@ - net8.0 + net10.0 enable enable false diff --git a/src/UltimatePDF_ExternalLogic.Test.Helpers/UltimatePDF_ExternalLogic.Test.Helpers.csproj b/src/UltimatePDF_ExternalLogic.Test.Helpers/UltimatePDF_ExternalLogic.Test.Helpers.csproj index fe47456..a42d6f6 100644 --- a/src/UltimatePDF_ExternalLogic.Test.Helpers/UltimatePDF_ExternalLogic.Test.Helpers.csproj +++ b/src/UltimatePDF_ExternalLogic.Test.Helpers/UltimatePDF_ExternalLogic.Test.Helpers.csproj @@ -1,7 +1,7 @@  - net8.0 + net10.0 enable enable false @@ -12,7 +12,7 @@ - + diff --git a/src/UltimatePDF_ExternalLogic.UnitTests/PipelineTests.cs b/src/UltimatePDF_ExternalLogic.UnitTests/PipelineTests.cs index f6441c4..849abc1 100644 --- a/src/UltimatePDF_ExternalLogic.UnitTests/PipelineTests.cs +++ b/src/UltimatePDF_ExternalLogic.UnitTests/PipelineTests.cs @@ -19,7 +19,7 @@ private static Mock BuildPageMock(Pipeline.LayoutPrint[] layouts) { mock.Setup(p => p.EvaluateFunctionAsync(It.IsAny(), It.IsAny())) .ReturnsAsync(layouts); mock.Setup(p => p.EvaluateFunctionAsync(It.IsAny(), It.IsAny())) - .ReturnsAsync(JValue.CreateNull()); + .Returns(Task.CompletedTask); mock.Setup(p => p.PdfDataAsync(It.IsAny())) .ReturnsAsync(PdfFactory.CreateMinimal()); return mock; diff --git a/src/UltimatePDF_ExternalLogic.UnitTests/UltimatePDF_ExternalLogic.UnitTests.csproj b/src/UltimatePDF_ExternalLogic.UnitTests/UltimatePDF_ExternalLogic.UnitTests.csproj index 13de9d0..fc91750 100644 --- a/src/UltimatePDF_ExternalLogic.UnitTests/UltimatePDF_ExternalLogic.UnitTests.csproj +++ b/src/UltimatePDF_ExternalLogic.UnitTests/UltimatePDF_ExternalLogic.UnitTests.csproj @@ -1,7 +1,7 @@ - net8.0 + net10.0 enable enable false diff --git a/src/UltimatePDF_ExternalLogic/UltimatePDF_ExternalLogic.csproj b/src/UltimatePDF_ExternalLogic/UltimatePDF_ExternalLogic.csproj index a6bf964..b3c3b84 100644 --- a/src/UltimatePDF_ExternalLogic/UltimatePDF_ExternalLogic.csproj +++ b/src/UltimatePDF_ExternalLogic/UltimatePDF_ExternalLogic.csproj @@ -1,7 +1,7 @@  - net8.0 + net10.0 enable @@ -10,9 +10,9 @@ - + - + From 73461ece6381b9e55722b397d43712dbc8457a60 Mon Sep 17 00:00:00 2001 From: "Diogo Paulo (dpa)" Date: Thu, 16 Jul 2026 23:11:44 +0100 Subject: [PATCH 2/2] Fix error in tests --- .../Management/Troubleshooting/Logger.cs | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/UltimatePDF_ExternalLogic/Management/Troubleshooting/Logger.cs b/src/UltimatePDF_ExternalLogic/Management/Troubleshooting/Logger.cs index 226d808..874dd3f 100644 --- a/src/UltimatePDF_ExternalLogic/Management/Troubleshooting/Logger.cs +++ b/src/UltimatePDF_ExternalLogic/Management/Troubleshooting/Logger.cs @@ -12,12 +12,14 @@ public class Logger { private readonly ILogger logger; private readonly ICollection attachments; private readonly ICollection loggerFactories; + private readonly StringBuilder executionLog; private readonly bool attachFilesLogs; private Logger() { logger = NullLogger.Instance; attachments = new List(6); loggerFactories = new List(1); + executionLog = new StringBuilder(); } protected Logger(ILogger logger, bool attachFilesLogs) : this() { @@ -42,25 +44,39 @@ public void Log(string message) { } public virtual void Error(Exception? e, string? message, params object?[] args) { + AppendToExecutionLog(LogLevel.Error, message, e); logger.LogError(e, message, args); } public virtual void Error(string message) { + AppendToExecutionLog(LogLevel.Error, message); logger.LogError(message); } public virtual void Warning(string message) { + AppendToExecutionLog(LogLevel.Warning, message); logger.LogWarning(message); } public virtual void Warning(string? message, params object?[] args) { + AppendToExecutionLog(LogLevel.Warning, message); logger.LogWarning(message, args); } public virtual void Log(LogLevel level, string? message, params object?[] args) { + AppendToExecutionLog(level, message); logger.Log(level, message, args); } + private void AppendToExecutionLog(LogLevel level, string? message, Exception? exception = null) { + lock (executionLog) { + executionLog.AppendLine($"[{DateTime.UtcNow:o}] [{level}] - {message}"); + if (exception != null) { + executionLog.AppendLine(exception.ToString()); + } + } + } + public void Log(string message, bool condition) { if (condition) { Log(message); @@ -89,6 +105,7 @@ public virtual byte[] GetZipFile() { using (var zip = new ZipArchive(stream, ZipArchiveMode.Create, true)) { + AddExecutionLogToZip(zip); AddAttachmentsToZip(zip); AddCustomLoggersToZip(zip); } @@ -96,6 +113,17 @@ public virtual byte[] GetZipFile() { return stream.ToArray(); } + private void AddExecutionLogToZip(ZipArchive zip) { + if (executionLog.Length == 0) { + return; + } + + var entry = zip.CreateEntry("execution.txt"); + using var stream = entry.Open(); + using var writer = new StreamWriter(stream, Encoding.UTF8); + writer.Write(executionLog.ToString()); + } + private void AddAttachmentsToZip(ZipArchive zip) { foreach (var attachment in attachments) { var attachmentEntry = zip.CreateEntry(attachment.filename);