diff --git a/.gitignore b/.gitignore index 57a872f00..681a3fc84 100644 --- a/.gitignore +++ b/.gitignore @@ -67,3 +67,5 @@ obj /LearningHub.Nhs.WebUI.BlazorClient/wwwroot/appsettings.Development.json /LearningHub.Nhs.WebUI.BlazorClient/Properties/launchSettings.json /.github/dependabot.yml +/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/LearningHub.Nhs.MessageQueueing.Database.dbmdl +/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/LearningHub.Nhs.MessageQueueing.Database.jfm \ No newline at end of file diff --git a/AdminUI/LearningHub.Nhs.AdminUI/Controllers/GovNotifyDashboardController.cs b/AdminUI/LearningHub.Nhs.AdminUI/Controllers/GovNotifyDashboardController.cs new file mode 100644 index 000000000..d6826bcd2 --- /dev/null +++ b/AdminUI/LearningHub.Nhs.AdminUI/Controllers/GovNotifyDashboardController.cs @@ -0,0 +1,120 @@ +using LearningHub.Nhs.AdminUI.Configuration; +using LearningHub.Nhs.AdminUI.Extensions; +using LearningHub.Nhs.AdminUI.Interfaces; +using LearningHub.Nhs.Models.Paging; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Options; +using Newtonsoft.Json; +using System.Collections.Generic; +using System.Linq; +using System; +using System.Threading.Tasks; +using LearningHub.Nhs.Models.GovNotifyMessaging; + +namespace LearningHub.Nhs.AdminUI.Controllers +{ + /// + /// Defines the . + /// + public class GovNotifyDashboardController : BaseController + { + /// + /// Defines the websettings. + /// + private readonly IOptions websettings; + + /// + /// Defines the govNotifyDashboardService. + /// + private IGovNotifyDashboardService govNotifyDashboardService; + + /// + /// Initializes a new instance of the class. + /// + /// The hostingEnvironment. + /// The govNotifyDashboardService. + /// The websettings. + public GovNotifyDashboardController(IWebHostEnvironment hostingEnvironment, + IGovNotifyDashboardService govNotifyDashboardService, + IOptions websettings) + : base(hostingEnvironment) + { + this.websettings = websettings; + this.govNotifyDashboardService = govNotifyDashboardService; + } + + /// + /// Initial call to get paginated result. + /// + /// The . + public async Task Index() + { + return await this.GetMessageRequests( + new PagingRequestModel + { + Page = 1, + PageSize = this.websettings.Value.DefaultPageSize, + SortColumn = "CreatedAt", + SortDirection = "D", + }); + } + + /// + /// Get paginated result based on the filters. + /// + /// + /// The . + [HttpPost] + public async Task Index(string pagingRequestModel) + { + var requestModel = JsonConvert.DeserializeObject(pagingRequestModel); + return await this.GetMessageRequests(requestModel); + } + + /// + /// Get message request details by id. + /// + /// + /// The . + [HttpGet] + public async Task Details(int id) + { + var notification = await this.govNotifyDashboardService.GetMessageRequestById(id); + return this.View(notification); + } + + private async Task GetMessageRequests(PagingRequestModel requestModel) + { + requestModel.Sanitize(); + requestModel.PageSize = this.websettings.Value.DefaultPageSize; + + var model = new TablePagingViewModel + { + Results = await this.govNotifyDashboardService.GetPagedAsync(requestModel), + SortColumn = requestModel.SortColumn, + SortDirection = requestModel.SortDirection, + Filter = requestModel.Filter, + }; + + model.Paging = new PagingViewModel + { + CurrentPage = requestModel.Page, + HasItems = model.Results.Items.Any(), + PageSize = this.websettings.Value.DefaultPageSize, + TotalItems = model.Results.TotalItemCount, + }; + + model.ListPageHeader = new ListPageHeaderViewModel + { + TotalItemCount = model.Results.TotalItemCount, + DisplayedCount = model.Results.Items.Count(), + DefaultPageSize = this.websettings.Value.DefaultPageSize, + FilterCount = model.Filter != null ? model.Filter.Count() : 0, + CreateRequired = false, + }; + + return this.View(model); + } + } +} diff --git a/AdminUI/LearningHub.Nhs.AdminUI/Interfaces/IGovNotifyDashboardService.cs b/AdminUI/LearningHub.Nhs.AdminUI/Interfaces/IGovNotifyDashboardService.cs new file mode 100644 index 000000000..0a5368a13 --- /dev/null +++ b/AdminUI/LearningHub.Nhs.AdminUI/Interfaces/IGovNotifyDashboardService.cs @@ -0,0 +1,27 @@ +namespace LearningHub.Nhs.AdminUI.Interfaces +{ + using LearningHub.Nhs.Models.Common; + using LearningHub.Nhs.Models.GovNotifyMessaging; + using LearningHub.Nhs.Models.Paging; + using System.Threading.Tasks; + + /// + /// Defines the . + /// + public interface IGovNotifyDashboardService + { + /// + /// The GetPagedAsync. + /// + /// The pagingRequestModel. + /// The . + Task> GetPagedAsync(PagingRequestModel pagingRequestModel); + + /// + /// Get Message Request By Id. + /// + /// id. + /// The . + Task GetMessageRequestById(int id); + } +} diff --git a/AdminUI/LearningHub.Nhs.AdminUI/LearningHub.Nhs.AdminUI.csproj b/AdminUI/LearningHub.Nhs.AdminUI/LearningHub.Nhs.AdminUI.csproj index 1e0cbbb2d..0b3d434ad 100644 --- a/AdminUI/LearningHub.Nhs.AdminUI/LearningHub.Nhs.AdminUI.csproj +++ b/AdminUI/LearningHub.Nhs.AdminUI/LearningHub.Nhs.AdminUI.csproj @@ -89,7 +89,7 @@ - + diff --git a/AdminUI/LearningHub.Nhs.AdminUI/ServiceCollectionExtension.cs b/AdminUI/LearningHub.Nhs.AdminUI/ServiceCollectionExtension.cs index 8db722e30..5687cefc7 100644 --- a/AdminUI/LearningHub.Nhs.AdminUI/ServiceCollectionExtension.cs +++ b/AdminUI/LearningHub.Nhs.AdminUI/ServiceCollectionExtension.cs @@ -108,6 +108,7 @@ public static void ConfigureServices(this IServiceCollection services, IConfigur services.AddScoped(); services.AddScoped(); services.AddScoped(); + services.AddScoped(); // Configure Azure Search services.Configure(configuration.GetSection("AzureSearch")); diff --git a/AdminUI/LearningHub.Nhs.AdminUI/Services/GovNotifyDashboardService.cs b/AdminUI/LearningHub.Nhs.AdminUI/Services/GovNotifyDashboardService.cs new file mode 100644 index 000000000..e82a1c468 --- /dev/null +++ b/AdminUI/LearningHub.Nhs.AdminUI/Services/GovNotifyDashboardService.cs @@ -0,0 +1,130 @@ +using LearningHub.Nhs.AdminUI.Interfaces; +using LearningHub.Nhs.Models.Common; +using LearningHub.Nhs.Models.Paging; +using Newtonsoft.Json; +using System.Threading.Tasks; +using System; +using LearningHub.Nhs.Models.GovNotifyMessaging; +using Newtonsoft.Json.Converters; +using System.Collections.Generic; + +namespace LearningHub.Nhs.AdminUI.Services +{ + /// + /// Defines the . + /// + public class GovNotifyDashboardService: BaseService, IGovNotifyDashboardService + { + /// + /// Initializes a new instance of the class. + /// + /// + /// + public GovNotifyDashboardService(ILearningHubHttpClient learningHubHttpClient, IOpenApiHttpClient openApiHttpClient) + :base(learningHubHttpClient, openApiHttpClient) + { + } + + /// + /// The GetPagedAsync. + /// + /// The pagingRequestModel. + /// The . + public async Task> GetPagedAsync(PagingRequestModel pagingRequestModel) + { + try + { + PagedResultSet viewmodel = null; + var sortDirection = " "; + + if (string.IsNullOrEmpty(pagingRequestModel.SortColumn)) + { + pagingRequestModel.SortColumn = " "; + } + + if (string.IsNullOrEmpty(pagingRequestModel.SortDirection)) + { + pagingRequestModel.SortDirection = " "; + } + else + { + sortDirection = pagingRequestModel.SortDirection == "A" ? "ASC" : + pagingRequestModel.SortDirection == "D" ? "DESC" : "ASC"; + } + + var settings = new JsonSerializerSettings + { + Converters = new List + { + new StringEnumConverter() + } + }; + + var filter = JsonConvert.SerializeObject(pagingRequestModel.Filter, settings); + var client = await this.OpenApiHttpClient.GetClientAsync(); + + var request = $"GovNotifyMessage/GetMessageRequests" + + $"/{pagingRequestModel.Page}" + + $"/{pagingRequestModel.PageSize}" + + $"/{pagingRequestModel.SortColumn}" + + $"/{sortDirection}" + +$"/{Uri.EscapeDataString(filter)}"; + + var response = await client.GetAsync(request).ConfigureAwait(false); + + if (response.IsSuccessStatusCode) + { + var result = response.Content.ReadAsStringAsync().Result; + viewmodel = JsonConvert.DeserializeObject>(result); + } + else if (response.StatusCode == System.Net.HttpStatusCode.Unauthorized + || + response.StatusCode == System.Net.HttpStatusCode.Forbidden) + { + throw new Exception("AccessDenied"); + } + + return viewmodel; + } + catch (Exception ex) + { + return null; + } + } + + /// + /// Get message request details by id. + /// + /// id. + /// The . + public async Task GetMessageRequestById(int id) + { + try + { + MessageRequestViewModel viewmodel = null; + var client = await this.OpenApiHttpClient.GetClientAsync(); + + var request = $"GovNotifyMessage/GetMessageRequestById/{id}"; + var response = await client.GetAsync(request).ConfigureAwait(false); + + if (response.IsSuccessStatusCode) + { + var result = response.Content.ReadAsStringAsync().Result; + viewmodel = JsonConvert.DeserializeObject(result); + } + else if (response.StatusCode == System.Net.HttpStatusCode.Unauthorized + || + response.StatusCode == System.Net.HttpStatusCode.Forbidden) + { + throw new Exception("AccessDenied"); + } + + return viewmodel; + } + catch (Exception ex) + { + return null; + } + } + } +} diff --git a/AdminUI/LearningHub.Nhs.AdminUI/Views/GovNotifyDashboard/Details.cshtml b/AdminUI/LearningHub.Nhs.AdminUI/Views/GovNotifyDashboard/Details.cshtml new file mode 100644 index 000000000..fcffc0eae --- /dev/null +++ b/AdminUI/LearningHub.Nhs.AdminUI/Views/GovNotifyDashboard/Details.cshtml @@ -0,0 +1,80 @@ +@model LearningHub.Nhs.Models.GovNotifyMessaging.MessageRequestViewModel +@using LearningHub.Nhs.AdminUI.Services + +@{ + ViewData["Title"] = "Details"; +} +@section SideMenu { + @{ + await Html.RenderPartialAsync("_NavSection"); + } +} + +
+ +
+
+
ID @Model.Id
+
+
+ Recipient +
+
+ @Html.DisplayFor(model => model.Recipient) +
+
+ Request type +
+
+ @Html.DisplayFor(model => model.RequestType) +
+
+ Request status +
+
+ @Html.DisplayFor(model => model.RequestStatus) +
+
+ Retry count +
+
+ @Html.DisplayFor(model => model.RetryCount) +
+
+ Created date +
+
+ @Html.DisplayFor(model => model.CreatedAt) +
+
+ Deliver after date +
+
+ @Html.DisplayFor(model => model.DeliverAfter) +
+
+ Sent Date +
+
+ @Html.DisplayFor(model => model.SentAt) +
+
+ Last attempt date +
+
+ @Html.DisplayFor(model => model.LastAttemptAt) +
+
+ Error message +
+
+ @Html.Raw(OutputSanitizer.SanitizeOutputHtml(Model.ErrorMessage)) +
+
+
+
+ +
+ diff --git a/AdminUI/LearningHub.Nhs.AdminUI/Views/GovNotifyDashboard/Index.cshtml b/AdminUI/LearningHub.Nhs.AdminUI/Views/GovNotifyDashboard/Index.cshtml new file mode 100644 index 000000000..a1a83b1b4 --- /dev/null +++ b/AdminUI/LearningHub.Nhs.AdminUI/Views/GovNotifyDashboard/Index.cshtml @@ -0,0 +1,67 @@ +@using LearningHub.Nhs.Models.GovNotifyMessaging +@using LearningHub.Nhs.Models.Enums +@using LearningHub.Nhs.AdminUI.Controllers +@model LearningHub.Nhs.Models.Paging.TablePagingViewModel + +@{ + ViewData["Title"] = "GovNotify Dashboard"; + ViewData["CurrentPage"] = Model.Paging.CurrentPage; +} + +@section SideMenu { + @{ + await Html.RenderPartialAsync("_NavSection"); + } +} +@{ + await Html.RenderPartialAsync("_ListPageHeader", Model.ListPageHeader); +} + +
+ + + + + + + + + + + + + @if (Model.Paging.HasItems) + { + foreach (var request in Model.Results.Items) + { + + + + + + + + + } + } + +
IdRequestTypeRecipientRequestStatusRetryCountCreated Date
@request.Id@request.RequestType + @Html.ActionLink(request.Recipient, "Details", new { id = request.Id }) + @request.RequestStatus@request.RetryCount@request.CreatedAt.LocalDateTime.ToString("dd/MM/yyyy HH:mm:ss")
+
+@{ + await Html.RenderPartialAsync("_PagingControls", Model.Paging); +} + + +@section Scripts { + + +} \ No newline at end of file diff --git a/AdminUI/LearningHub.Nhs.AdminUI/Views/Shared/_NavPartial.cshtml b/AdminUI/LearningHub.Nhs.AdminUI/Views/Shared/_NavPartial.cshtml index 6a6e66a26..4373eb821 100644 --- a/AdminUI/LearningHub.Nhs.AdminUI/Views/Shared/_NavPartial.cshtml +++ b/AdminUI/LearningHub.Nhs.AdminUI/Views/Shared/_NavPartial.cshtml @@ -13,6 +13,7 @@ switch (controller) { case "notifications": + case "govnotifydashboard": case "externalsystem": case "log": case "roadmap": diff --git a/AdminUI/LearningHub.Nhs.AdminUI/Views/Shared/_NavSection.cshtml b/AdminUI/LearningHub.Nhs.AdminUI/Views/Shared/_NavSection.cshtml index 924c58475..3285d08db 100644 --- a/AdminUI/LearningHub.Nhs.AdminUI/Views/Shared/_NavSection.cshtml +++ b/AdminUI/LearningHub.Nhs.AdminUI/Views/Shared/_NavSection.cshtml @@ -5,6 +5,7 @@ switch (controller) { case "notifications": + case "govnotifydashboard": case "externalsystem": case "log": case "release": @@ -45,6 +46,7 @@
  • Release management
  • Cache management
  • Service updates and releases
  • +
  • GovNotify Dashboard
  • break; case "users": diff --git a/AdminUI/LearningHub.Nhs.AdminUI/package-lock.json b/AdminUI/LearningHub.Nhs.AdminUI/package-lock.json index bbea60904..ccd742288 100644 --- a/AdminUI/LearningHub.Nhs.AdminUI/package-lock.json +++ b/AdminUI/LearningHub.Nhs.AdminUI/package-lock.json @@ -10,20 +10,20 @@ "dependencies": { "@ckeditor/ckeditor5-build-classic": "16.0.0", "@ckeditor/ckeditor5-vue": "1.0.3", - "@mediakind/mkplayer": "^1.22.0", + "@mediakind/mkplayer": "^1.21.0", "axios": "^0.30.0", "babel-polyfill": "^6.26.0", "bootstrap": "^4.6.2", "ckeditor4-vue": "^0.2.0", "concurrently": "^7.6.0", - "core-js": "^3.42.0", + "core-js": "^3.41.0", "js-cookie": "2.2.1", "lodash": "4.17.21", "moment": "^2.30.1", "navigator.sendbeacon": "0.0.20", "nhsuk-frontend": "^6.1.2", "openseadragon": "^2.4.2", - "sanitize-html": "^2.17.0", + "sanitize-html": "^2.15.0", "save": "^2.9.0", "ts-debounce": "2.3.0", "tus-js-client": "^2.3.2", @@ -40,8 +40,8 @@ "vuex": "^3.6.2" }, "devDependencies": { - "@babel/core": "^7.27.3", - "@babel/preset-env": "^7.27.2", + "@babel/core": "^7.26.10", + "@babel/preset-env": "^7.26.9", "@types/axios": "^0.14.0", "@types/bootstrap": "4.1.3", "@types/ckeditor": "4.9.10", @@ -49,9 +49,9 @@ "@types/jquery": "^3.3.32", "@types/jquery-match-height": "^0.7.8", "@types/js-cookie": "2.2.1", - "@types/lodash": "4.17.17", + "@types/lodash": "4.17.16", "@types/openseadragon": "^2.4.5", - "@types/sanitize-html": "^2.16.0", + "@types/sanitize-html": "^2.15.0", "@types/vuelidate": "^0.7.22", "@vue/babel-preset-app": "4.5.19", "@vue/test-utils": "^1.3.6", @@ -63,7 +63,7 @@ "css-loader": "^5.2.4", "file-loader": "^6.2.0", "jest": "^27.5.1", - "sass": "^1.89.0", + "sass": "^1.86.3", "sass-loader": "^11.0.1", "style-loader": "^2.0.0", "ts-jest": "^27.1.5", @@ -72,7 +72,7 @@ "vue-jest": "^3.0.7", "vue-loader": "^15.11.1", "vue-template-compiler": "^2.7.16", - "webpack": "^5.99.9", + "webpack": "^5.99.5", "webpack-cli": "^4.10.0", "webpack-dev-server": "^3.11.3" } @@ -92,24 +92,24 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", - "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", + "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-validator-identifier": "^7.27.1", + "@babel/helper-validator-identifier": "^7.25.9", "js-tokens": "^4.0.0", - "picocolors": "^1.1.1" + "picocolors": "^1.0.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/compat-data": { - "version": "7.27.2", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.27.2.tgz", - "integrity": "sha512-TUtMJYRPyUb/9aU8f3K0mjmjf6M9N5Woshn2CS6nqJSeJtTtQcpLUXjGt9vbF8ZGff0El99sWkLgzwW3VXnxZQ==", + "version": "7.26.8", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.8.tgz", + "integrity": "sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ==", "dev": true, "license": "MIT", "engines": { @@ -117,22 +117,22 @@ } }, "node_modules/@babel/core": { - "version": "7.27.3", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.27.3.tgz", - "integrity": "sha512-hyrN8ivxfvJ4i0fIJuV4EOlV0WDMz5Ui4StRTgVaAvWeiRCilXgwVvxJKtFQ3TKtHgJscB2YiXKGNJuVwhQMtA==", + "version": "7.26.10", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.10.tgz", + "integrity": "sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ==", "dev": true, "license": "MIT", "dependencies": { "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.27.3", - "@babel/helper-compilation-targets": "^7.27.2", - "@babel/helper-module-transforms": "^7.27.3", - "@babel/helpers": "^7.27.3", - "@babel/parser": "^7.27.3", - "@babel/template": "^7.27.2", - "@babel/traverse": "^7.27.3", - "@babel/types": "^7.27.3", + "@babel/code-frame": "^7.26.2", + "@babel/generator": "^7.26.10", + "@babel/helper-compilation-targets": "^7.26.5", + "@babel/helper-module-transforms": "^7.26.0", + "@babel/helpers": "^7.26.10", + "@babel/parser": "^7.26.10", + "@babel/template": "^7.26.9", + "@babel/traverse": "^7.26.10", + "@babel/types": "^7.26.10", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -178,14 +178,14 @@ "dev": true }, "node_modules/@babel/generator": { - "version": "7.27.3", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.27.3.tgz", - "integrity": "sha512-xnlJYj5zepml8NXtjkG0WquFUv8RskFqyFcVgTBp5k+NaA/8uw/K+OSVf8AMGw5e9HKP2ETd5xpK5MLZQD6b4Q==", + "version": "7.26.10", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.10.tgz", + "integrity": "sha512-rRHT8siFIXQrAYOYqZQVsAr8vJ+cBNqcVAY6m5V8/4QqzaPl+zDBe6cLEPRDuNOUf3ww8RfJVlOyQMoSI+5Ang==", "dev": true, "license": "MIT", "dependencies": { - "@babel/parser": "^7.27.3", - "@babel/types": "^7.27.3", + "@babel/parser": "^7.26.10", + "@babel/types": "^7.26.10", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^3.0.2" @@ -195,27 +195,27 @@ } }, "node_modules/@babel/helper-annotate-as-pure": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.27.1.tgz", - "integrity": "sha512-WnuuDILl9oOBbKnb4L+DyODx7iC47XfzmNCpTttFsSp6hTG7XZxu60+4IO+2/hPfcGOoKbFiwoI/+zwARbNQow==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.9.tgz", + "integrity": "sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.27.1" + "@babel/types": "^7.25.9" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.27.2", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz", - "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==", + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.26.5.tgz", + "integrity": "sha512-IXuyn5EkouFJscIDuFF5EsiSolseme1s0CZB+QxVugqJLYmKdxI1VfIBOst0SUu4rnk2Z7kqTwmoO1lp3HIfnA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.27.2", - "@babel/helper-validator-option": "^7.27.1", + "@babel/compat-data": "^7.26.5", + "@babel/helper-validator-option": "^7.25.9", "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" @@ -242,18 +242,18 @@ "license": "ISC" }, "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.27.1.tgz", - "integrity": "sha512-QwGAmuvM17btKU5VqXfb+Giw4JcN0hjuufz3DYnpeVDvZLAObloM77bhMXiqry3Iio+Ai4phVRDwl6WU10+r5A==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.25.9.tgz", + "integrity": "sha512-UTZQMvt0d/rSz6KI+qdu7GQze5TIajwTS++GUozlw8VBJDEOAqSXwm1WvmYEZwqdqSGQshRocPDqrt4HBZB3fQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.27.1", - "@babel/helper-member-expression-to-functions": "^7.27.1", - "@babel/helper-optimise-call-expression": "^7.27.1", - "@babel/helper-replace-supers": "^7.27.1", - "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", - "@babel/traverse": "^7.27.1", + "@babel/helper-annotate-as-pure": "^7.25.9", + "@babel/helper-member-expression-to-functions": "^7.25.9", + "@babel/helper-optimise-call-expression": "^7.25.9", + "@babel/helper-replace-supers": "^7.25.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9", + "@babel/traverse": "^7.25.9", "semver": "^6.3.1" }, "engines": { @@ -264,13 +264,13 @@ } }, "node_modules/@babel/helper-create-regexp-features-plugin": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.27.1.tgz", - "integrity": "sha512-uVDC72XVf8UbrH5qQTc18Agb8emwjTiZrQE11Nv3CuBEZmVvTwwE9CBUEvHku06gQCAyYf8Nv6ja1IN+6LMbxQ==", + "version": "7.26.3", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.26.3.tgz", + "integrity": "sha512-G7ZRb40uUgdKOQqPLjfD12ZmGA54PzqDFUv2BKImnC9QIfGhIHKvVML0oN8IUiDq4iRqpq74ABpvOaerfWdong==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.27.1", + "@babel/helper-annotate-as-pure": "^7.25.9", "regexpu-core": "^6.2.0", "semver": "^6.3.1" }, @@ -324,43 +324,43 @@ "license": "MIT" }, "node_modules/@babel/helper-member-expression-to-functions": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.27.1.tgz", - "integrity": "sha512-E5chM8eWjTp/aNoVpcbfM7mLxu9XGLWYise2eBKGQomAk/Mb4XoxyqXTZbuTohbsl8EKqdlMhnDI2CCLfcs9wA==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.25.9.tgz", + "integrity": "sha512-wbfdZ9w5vk0C0oyHqAJbc62+vet5prjj01jjJ8sKn3j9h3MQQlflEdXYvuqRWjHnM12coDEqiC1IRCi0U/EKwQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/traverse": "^7.27.1", - "@babel/types": "^7.27.1" + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-imports": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", - "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz", + "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/traverse": "^7.27.1", - "@babel/types": "^7.27.1" + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.27.3", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.27.3.tgz", - "integrity": "sha512-dSOvYwvyLsWBeIRyOeHXp5vPj5l1I011r52FM1+r1jCERv+aFXYk4whgQccYEGYxK2H3ZAIA8nuPkQ0HaUo3qg==", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz", + "integrity": "sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-module-imports": "^7.27.1", - "@babel/helper-validator-identifier": "^7.27.1", - "@babel/traverse": "^7.27.3" + "@babel/helper-module-imports": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9", + "@babel/traverse": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -370,22 +370,22 @@ } }, "node_modules/@babel/helper-optimise-call-expression": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.27.1.tgz", - "integrity": "sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.25.9.tgz", + "integrity": "sha512-FIpuNaz5ow8VyrYcnXQTDRGvV6tTjkNtCK/RYNDXGSLlUD6cBuQTSw43CShGxjvfBTfcUA/r6UhUCbtYqkhcuQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.27.1" + "@babel/types": "^7.25.9" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz", - "integrity": "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==", + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.26.5.tgz", + "integrity": "sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg==", "dev": true, "license": "MIT", "engines": { @@ -393,15 +393,15 @@ } }, "node_modules/@babel/helper-remap-async-to-generator": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.27.1.tgz", - "integrity": "sha512-7fiA521aVw8lSPeI4ZOD3vRFkoqkJcS+z4hFo82bFSH/2tNd6eJ5qCVMS5OzDmZh/kaHQeBaeyxK6wljcPtveA==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.25.9.tgz", + "integrity": "sha512-IZtukuUeBbhgOcaW2s06OXTzVNJR0ybm4W5xC1opWFFJMZbwRj5LCk+ByYH7WdZPZTt8KnFwA8pvjN2yqcPlgw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.27.1", - "@babel/helper-wrap-function": "^7.27.1", - "@babel/traverse": "^7.27.1" + "@babel/helper-annotate-as-pure": "^7.25.9", + "@babel/helper-wrap-function": "^7.25.9", + "@babel/traverse": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -411,15 +411,15 @@ } }, "node_modules/@babel/helper-replace-supers": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.27.1.tgz", - "integrity": "sha512-7EHz6qDZc8RYS5ElPoShMheWvEgERonFCs7IAonWLLUTXW59DP14bCZt89/GKyreYn8g3S83m21FelHKbeDCKA==", + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.26.5.tgz", + "integrity": "sha512-bJ6iIVdYX1YooY2X7w1q6VITt+LnUILtNk7zT78ykuwStx8BauCzxvFqFaHjOpW1bVnSUM1PN1f0p5P21wHxvg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-member-expression-to-functions": "^7.27.1", - "@babel/helper-optimise-call-expression": "^7.27.1", - "@babel/traverse": "^7.27.1" + "@babel/helper-member-expression-to-functions": "^7.25.9", + "@babel/helper-optimise-call-expression": "^7.25.9", + "@babel/traverse": "^7.26.5" }, "engines": { "node": ">=6.9.0" @@ -429,41 +429,40 @@ } }, "node_modules/@babel/helper-skip-transparent-expression-wrappers": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.27.1.tgz", - "integrity": "sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.25.9.tgz", + "integrity": "sha512-K4Du3BFa3gvyhzgPcntrkDgZzQaq6uozzcpGbOO1OEJaI+EJdqWIMTLgFgQf6lrfiDFo5FU+BxKepI9RmZqahA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/traverse": "^7.27.1", - "@babel/types": "^7.27.1" + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-string-parser": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", - "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", - "license": "MIT", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", + "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", - "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", + "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-option": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", - "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz", + "integrity": "sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==", "dev": true, "license": "MIT", "engines": { @@ -471,41 +470,41 @@ } }, "node_modules/@babel/helper-wrap-function": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.27.1.tgz", - "integrity": "sha512-NFJK2sHUvrjo8wAU/nQTWU890/zB2jj0qBcCbZbbf+005cAsv6tMjXz31fBign6M5ov1o0Bllu+9nbqkfsjjJQ==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.25.9.tgz", + "integrity": "sha512-ETzz9UTjQSTmw39GboatdymDq4XIQbR8ySgVrylRhPOFpsd+JrKHIuF0de7GCWmem+T4uC5z7EZguod7Wj4A4g==", "dev": true, "license": "MIT", "dependencies": { - "@babel/template": "^7.27.1", - "@babel/traverse": "^7.27.1", - "@babel/types": "^7.27.1" + "@babel/template": "^7.25.9", + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helpers": { - "version": "7.27.3", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.3.tgz", - "integrity": "sha512-h/eKy9agOya1IGuLaZ9tEUgz+uIRXcbtOhRtUyyMf8JFmn1iT13vnl/IGVWSkdOCG/pC57U4S1jnAabAavTMwg==", + "version": "7.26.10", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.26.10.tgz", + "integrity": "sha512-UPYc3SauzZ3JGgj87GgZ89JVdC5dj0AoetR5Bw6wj4niittNyFh6+eOGonYvJ1ao6B8lEa3Q3klS7ADZ53bc5g==", "dev": true, "license": "MIT", "dependencies": { - "@babel/template": "^7.27.2", - "@babel/types": "^7.27.3" + "@babel/template": "^7.26.9", + "@babel/types": "^7.26.10" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/parser": { - "version": "7.27.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.3.tgz", - "integrity": "sha512-xyYxRj6+tLNDTWi0KCBcZ9V7yg3/lwL9DWh9Uwh/RIVlIfFidggcgxKX3GCXwCiswwcGRawBKbEg2LG/Y8eJhw==", + "version": "7.26.10", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.10.tgz", + "integrity": "sha512-6aQR2zGE/QFi8JpDLjUZEPYOs7+mhKXm86VaKFiLP35JQwQb6bwUE+XbvkH0EptsYhbNBSUGaUBLKqxH1xSgsA==", "license": "MIT", "dependencies": { - "@babel/types": "^7.27.3" + "@babel/types": "^7.26.10" }, "bin": { "parser": "bin/babel-parser.js" @@ -515,14 +514,14 @@ } }, "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.27.1.tgz", - "integrity": "sha512-QPG3C9cCVRQLxAVwmefEmwdTanECuUBMQZ/ym5kiw3XKCGA7qkuQLcjWWHcrD/GKbn/WmJwaezfuuAOcyKlRPA==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.25.9.tgz", + "integrity": "sha512-ZkRyVkThtxQ/J6nv3JFYv1RYY+JT5BvU0y3k5bWrmuG4woXypRa4PXmm9RhOwodRkYFWqC0C0cqcJ4OqR7kW+g==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/traverse": "^7.27.1" + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/traverse": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -532,13 +531,13 @@ } }, "node_modules/@babel/plugin-bugfix-safari-class-field-initializer-scope": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.27.1.tgz", - "integrity": "sha512-qNeq3bCKnGgLkEXUuFry6dPlGfCdQNZbn7yUAPCInwAJHMU7THJfrBSozkcWq5sNM6RcF3S8XyQL2A52KNR9IA==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.25.9.tgz", + "integrity": "sha512-MrGRLZxLD/Zjj0gdU15dfs+HH/OXvnw/U4jJD8vpcP2CJQapPEv1IWwjc/qMg7ItBlPwSv1hRBbb7LeuANdcnw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -548,13 +547,13 @@ } }, "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.27.1.tgz", - "integrity": "sha512-g4L7OYun04N1WyqMNjldFwlfPCLVkgB54A/YCXICZYBsvJJE3kByKv9c9+R/nAfmIfjl2rKYLNyMHboYbZaWaA==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.25.9.tgz", + "integrity": "sha512-2qUwwfAFpJLZqxd02YW9btUCZHl+RFvdDkNfZwaIJrvB8Tesjsk8pEQkTvGwZXLqXUx/2oyY3ySRhm6HOXuCug==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -564,15 +563,15 @@ } }, "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.27.1.tgz", - "integrity": "sha512-oO02gcONcD5O1iTLi/6frMJBIwWEHceWGSGqrpCmEL8nogiS6J9PBlE48CaK20/Jx1LuRml9aDftLgdjXT8+Cw==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.25.9.tgz", + "integrity": "sha512-6xWgLZTJXwilVjlnV7ospI3xi+sl8lN8rXXbBD6vYn3UYDlGsag8wrZkKcSI8G6KgqKP7vNFaDgeDnfAABq61g==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", - "@babel/plugin-transform-optional-chaining": "^7.27.1" + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9", + "@babel/plugin-transform-optional-chaining": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -582,14 +581,14 @@ } }, "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.27.1.tgz", - "integrity": "sha512-6BpaYGDavZqkI6yT+KSPdpZFfpnd68UKXbcjI9pJ13pvHhPrCKWOOLp+ysvMeA+DxnhuPpgIaRpxRxo5A9t5jw==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.25.9.tgz", + "integrity": "sha512-aLnMXYPnzwwqhYSCyXfKkIkYgJ8zv9RK+roo9DkTXz38ynIhd9XCbN08s3MGvqL2MYGVUGdRQLL/JqBIeJhJBg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/traverse": "^7.27.1" + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/traverse": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -724,13 +723,13 @@ } }, "node_modules/@babel/plugin-syntax-import-assertions": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.27.1.tgz", - "integrity": "sha512-UT/Jrhw57xg4ILHLFnzFpPDlMbcdEicaAtjPQpbj9wa8T4r5KVWCimHcL/460g8Ht0DMxDyjsLgiWSkVjnwPFg==", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.26.0.tgz", + "integrity": "sha512-QCWT5Hh830hK5EQa7XzuqIkQU9tT/whqbDz7kuaZMHFl1inRRg7JnuAEOQ0Ur0QUl0NufCk1msK2BeY79Aj/eg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -740,13 +739,12 @@ } }, "node_modules/@babel/plugin-syntax-import-attributes": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.27.1.tgz", - "integrity": "sha512-oFT0FrKHgF53f4vOsZGi2Hh3I35PfSmVs4IBFLFj4dnafP+hIWDLg3VyKmUHfLoLHlyxY4C7DGtmHuJgn+IGww==", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.26.0.tgz", + "integrity": "sha512-e2dttdsJ1ZTpi3B9UYGLw41hifAubg19AtCu/2I/F1QNVclOBr1dYpTdmdyZ84Xiz43BS/tCUkMAZNLv12Pi+A==", "dev": true, - "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -929,13 +927,13 @@ } }, "node_modules/@babel/plugin-transform-arrow-functions": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.27.1.tgz", - "integrity": "sha512-8Z4TGic6xW70FKThA5HYEKKyBpOOsucTOD1DjU3fZxDg+K3zBJcXMFnt/4yQiZnf5+MiOMSXQ9PaEK/Ilh1DeA==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.25.9.tgz", + "integrity": "sha512-6jmooXYIwn9ca5/RylZADJ+EnSxVUS5sjeJ9UPk6RWRzXCmOJCy6dqItPJFpw2cuCangPK4OYr5uhGKcmrm5Qg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -945,15 +943,15 @@ } }, "node_modules/@babel/plugin-transform-async-generator-functions": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.27.1.tgz", - "integrity": "sha512-eST9RrwlpaoJBDHShc+DS2SG4ATTi2MYNb4OxYkf3n+7eb49LWpnS+HSpVfW4x927qQwgk8A2hGNVaajAEw0EA==", + "version": "7.26.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.26.8.tgz", + "integrity": "sha512-He9Ej2X7tNf2zdKMAGOsmg2MrFc+hfoAhd3po4cWfo/NWjzEAKa0oQruj1ROVUdl0e6fb6/kE/G3SSxE0lRJOg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/helper-remap-async-to-generator": "^7.27.1", - "@babel/traverse": "^7.27.1" + "@babel/helper-plugin-utils": "^7.26.5", + "@babel/helper-remap-async-to-generator": "^7.25.9", + "@babel/traverse": "^7.26.8" }, "engines": { "node": ">=6.9.0" @@ -963,15 +961,15 @@ } }, "node_modules/@babel/plugin-transform-async-to-generator": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.27.1.tgz", - "integrity": "sha512-NREkZsZVJS4xmTr8qzE5y8AfIPqsdQfRuUiLRTEzb7Qii8iFWCyDKaUV2c0rCuh4ljDZ98ALHP/PetiBV2nddA==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.25.9.tgz", + "integrity": "sha512-NT7Ejn7Z/LjUH0Gv5KsBCxh7BH3fbLTV0ptHvpeMvrt3cPThHfJfst9Wrb7S8EvJ7vRTFI7z+VAvFVEQn/m5zQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-module-imports": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/helper-remap-async-to-generator": "^7.27.1" + "@babel/helper-module-imports": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-remap-async-to-generator": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -981,13 +979,13 @@ } }, "node_modules/@babel/plugin-transform-block-scoped-functions": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.27.1.tgz", - "integrity": "sha512-cnqkuOtZLapWYZUYM5rVIdv1nXYuFVIltZ6ZJ7nIj585QsjKM5dhL2Fu/lICXZ1OyIAFc7Qy+bvDAtTXqGrlhg==", + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.26.5.tgz", + "integrity": "sha512-chuTSY+hq09+/f5lMj8ZSYgCFpppV2CbYrhNFJ1BFoXpiWPnnAb7R0MqrafCpN8E1+YRrtM1MXZHJdIx8B6rMQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.26.5" }, "engines": { "node": ">=6.9.0" @@ -997,13 +995,13 @@ } }, "node_modules/@babel/plugin-transform-block-scoping": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.27.1.tgz", - "integrity": "sha512-QEcFlMl9nGTgh1rn2nIeU5bkfb9BAjaQcWbiP4LvKxUot52ABcTkpcyJ7f2Q2U2RuQ84BNLgts3jRme2dTx6Fw==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.25.9.tgz", + "integrity": "sha512-1F05O7AYjymAtqbsFETboN1NvBdcnzMerO+zlMyJBEz6WkMdejvGWw9p05iTSjC85RLlBseHHQpYaM4gzJkBGg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1013,14 +1011,14 @@ } }, "node_modules/@babel/plugin-transform-class-properties": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.27.1.tgz", - "integrity": "sha512-D0VcalChDMtuRvJIu3U/fwWjf8ZMykz5iZsg77Nuj821vCKI3zCyRLwRdWbsuJ/uRwZhZ002QtCqIkwC/ZkvbA==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.25.9.tgz", + "integrity": "sha512-bbMAII8GRSkcd0h0b4X+36GksxuheLFjP65ul9w6C3KgAamI3JqErNgSrosX6ZPj+Mpim5VvEbawXxJCyEUV3Q==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-create-class-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1030,14 +1028,14 @@ } }, "node_modules/@babel/plugin-transform-class-static-block": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.27.1.tgz", - "integrity": "sha512-s734HmYU78MVzZ++joYM+NkJusItbdRcbm+AGRgJCt3iA+yux0QpD9cBVdz3tKyrjVYWRl7j0mHSmv4lhV0aoA==", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.26.0.tgz", + "integrity": "sha512-6J2APTs7BDDm+UMqP1useWqhcRAXo0WIoVj26N7kPFB6S73Lgvyka4KTZYIxtgYXiN5HTyRObA72N2iu628iTQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-create-class-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1047,17 +1045,17 @@ } }, "node_modules/@babel/plugin-transform-classes": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.27.1.tgz", - "integrity": "sha512-7iLhfFAubmpeJe/Wo2TVuDrykh/zlWXLzPNdL0Jqn/Xu8R3QQ8h9ff8FQoISZOsw74/HFqFI7NX63HN7QFIHKA==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.25.9.tgz", + "integrity": "sha512-mD8APIXmseE7oZvZgGABDyM34GUmK45Um2TXiBUt7PnuAxrgoSVf123qUzPxEr/+/BHrRn5NMZCdE2m/1F8DGg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.27.1", - "@babel/helper-compilation-targets": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/helper-replace-supers": "^7.27.1", - "@babel/traverse": "^7.27.1", + "@babel/helper-annotate-as-pure": "^7.25.9", + "@babel/helper-compilation-targets": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-replace-supers": "^7.25.9", + "@babel/traverse": "^7.25.9", "globals": "^11.1.0" }, "engines": { @@ -1068,14 +1066,14 @@ } }, "node_modules/@babel/plugin-transform-computed-properties": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.27.1.tgz", - "integrity": "sha512-lj9PGWvMTVksbWiDT2tW68zGS/cyo4AkZ/QTp0sQT0mjPopCmrSkzxeXkznjqBxzDI6TclZhOJbBmbBLjuOZUw==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.25.9.tgz", + "integrity": "sha512-HnBegGqXZR12xbcTHlJ9HGxw1OniltT26J5YpfruGqtUHlz/xKf/G2ak9e+t0rVqrjXa9WOhvYPz1ERfMj23AA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/template": "^7.27.1" + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/template": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1085,13 +1083,13 @@ } }, "node_modules/@babel/plugin-transform-destructuring": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.27.1.tgz", - "integrity": "sha512-ttDCqhfvpE9emVkXbPD8vyxxh4TWYACVybGkDj+oReOGwnp066ITEivDlLwe0b1R0+evJ13IXQuLNB5w1fhC5Q==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.25.9.tgz", + "integrity": "sha512-WkCGb/3ZxXepmMiX101nnGiU+1CAdut8oHyEOHxkKuS1qKpU2SMXE2uSvfz8PBuLd49V6LEsbtyPhWC7fnkgvQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1101,14 +1099,14 @@ } }, "node_modules/@babel/plugin-transform-dotall-regex": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.27.1.tgz", - "integrity": "sha512-gEbkDVGRvjj7+T1ivxrfgygpT7GUd4vmODtYpbs0gZATdkX8/iSnOtZSxiZnsgm1YjTgjI6VKBGSJJevkrclzw==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.25.9.tgz", + "integrity": "sha512-t7ZQ7g5trIgSRYhI9pIJtRl64KHotutUJsh4Eze5l7olJv+mRSg4/MmbZ0tv1eeqRbdvo/+trvJD/Oc5DmW2cA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-create-regexp-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1118,13 +1116,13 @@ } }, "node_modules/@babel/plugin-transform-duplicate-keys": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.27.1.tgz", - "integrity": "sha512-MTyJk98sHvSs+cvZ4nOauwTTG1JeonDjSGvGGUNHreGQns+Mpt6WX/dVzWBHgg+dYZhkC4X+zTDfkTU+Vy9y7Q==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.25.9.tgz", + "integrity": "sha512-LZxhJ6dvBb/f3x8xwWIuyiAHy56nrRG3PeYTpBkkzkYRRQ6tJLu68lEF5VIqMUZiAV7a8+Tb78nEoMCMcqjXBw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1134,14 +1132,14 @@ } }, "node_modules/@babel/plugin-transform-duplicate-named-capturing-groups-regex": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.27.1.tgz", - "integrity": "sha512-hkGcueTEzuhB30B3eJCbCYeCaaEQOmQR0AdvzpD4LoN0GXMWzzGSuRrxR2xTnCrvNbVwK9N6/jQ92GSLfiZWoQ==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.25.9.tgz", + "integrity": "sha512-0UfuJS0EsXbRvKnwcLjFtJy/Sxc5J5jhLHnFhy7u4zih97Hz6tJkLU+O+FMMrNZrosUPxDi6sYxJ/EA8jDiAog==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-create-regexp-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1151,13 +1149,13 @@ } }, "node_modules/@babel/plugin-transform-dynamic-import": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.27.1.tgz", - "integrity": "sha512-MHzkWQcEmjzzVW9j2q8LGjwGWpG2mjwaaB0BNQwst3FIjqsg8Ct/mIZlvSPJvfi9y2AC8mi/ktxbFVL9pZ1I4A==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.25.9.tgz", + "integrity": "sha512-GCggjexbmSLaFhqsojeugBpeaRIgWNTcgKVq/0qIteFEqY2A+b9QidYadrWlnbWQUrW5fn+mCvf3tr7OeBFTyg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1167,13 +1165,13 @@ } }, "node_modules/@babel/plugin-transform-exponentiation-operator": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.27.1.tgz", - "integrity": "sha512-uspvXnhHvGKf2r4VVtBpeFnuDWsJLQ6MF6lGJLC89jBR1uoVeqM416AZtTuhTezOfgHicpJQmoD5YUakO/YmXQ==", + "version": "7.26.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.26.3.tgz", + "integrity": "sha512-7CAHcQ58z2chuXPWblnn1K6rLDnDWieghSOEmqQsrBenH0P9InCUtOJYD89pvngljmZlJcz3fcmgYsXFNGa1ZQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1183,13 +1181,13 @@ } }, "node_modules/@babel/plugin-transform-export-namespace-from": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.27.1.tgz", - "integrity": "sha512-tQvHWSZ3/jH2xuq/vZDy0jNn+ZdXJeM8gHvX4lnJmsc3+50yPlWdZXIc5ay+umX+2/tJIqHqiEqcJvxlmIvRvQ==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.25.9.tgz", + "integrity": "sha512-2NsEz+CxzJIVOPx2o9UsW1rXLqtChtLoVnwYHHiB04wS5sgn7mrV45fWMBX0Kk+ub9uXytVYfNP2HjbVbCB3Ww==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1199,14 +1197,14 @@ } }, "node_modules/@babel/plugin-transform-for-of": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.27.1.tgz", - "integrity": "sha512-BfbWFFEJFQzLCQ5N8VocnCtA8J1CLkNTe2Ms2wocj75dd6VpiqS5Z5quTYcUoo4Yq+DN0rtikODccuv7RU81sw==", + "version": "7.26.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.26.9.tgz", + "integrity": "sha512-Hry8AusVm8LW5BVFgiyUReuoGzPUpdHQQqJY5bZnbbf+ngOHWuCuYFKw/BqaaWlvEUrF91HMhDtEaI1hZzNbLg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" + "@babel/helper-plugin-utils": "^7.26.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1216,15 +1214,15 @@ } }, "node_modules/@babel/plugin-transform-function-name": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.27.1.tgz", - "integrity": "sha512-1bQeydJF9Nr1eBCMMbC+hdwmRlsv5XYOMu03YSWFwNs0HsAmtSxxF1fyuYPqemVldVyFmlCU7w8UE14LupUSZQ==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.25.9.tgz", + "integrity": "sha512-8lP+Yxjv14Vc5MuWBpJsoUCd3hD6V9DgBon2FVYL4jJgbnVQ9fTgYmonchzZJOVNgzEgbxp4OwAf6xz6M/14XA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-compilation-targets": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/traverse": "^7.27.1" + "@babel/helper-compilation-targets": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/traverse": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1234,13 +1232,13 @@ } }, "node_modules/@babel/plugin-transform-json-strings": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.27.1.tgz", - "integrity": "sha512-6WVLVJiTjqcQauBhn1LkICsR2H+zm62I3h9faTDKt1qP4jn2o72tSvqMwtGFKGTpojce0gJs+76eZ2uCHRZh0Q==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.25.9.tgz", + "integrity": "sha512-xoTMk0WXceiiIvsaquQQUaLLXSW1KJ159KP87VilruQm0LNNGxWzahxSS6T6i4Zg3ezp4vA4zuwiNUR53qmQAw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1250,13 +1248,13 @@ } }, "node_modules/@babel/plugin-transform-literals": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.27.1.tgz", - "integrity": "sha512-0HCFSepIpLTkLcsi86GG3mTUzxV5jpmbv97hTETW3yzrAij8aqlD36toB1D0daVFJM8NK6GvKO0gslVQmm+zZA==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.25.9.tgz", + "integrity": "sha512-9N7+2lFziW8W9pBl2TzaNht3+pgMIRP74zizeCSrtnSKVdUl8mAjjOP2OOVQAfZ881P2cNjDj1uAMEdeD50nuQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1266,13 +1264,13 @@ } }, "node_modules/@babel/plugin-transform-logical-assignment-operators": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.27.1.tgz", - "integrity": "sha512-SJvDs5dXxiae4FbSL1aBJlG4wvl594N6YEVVn9e3JGulwioy6z3oPjx/sQBO3Y4NwUu5HNix6KJ3wBZoewcdbw==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.25.9.tgz", + "integrity": "sha512-wI4wRAzGko551Y8eVf6iOY9EouIDTtPb0ByZx+ktDGHwv6bHFimrgJM/2T021txPZ2s4c7bqvHbd+vXG6K948Q==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1282,13 +1280,13 @@ } }, "node_modules/@babel/plugin-transform-member-expression-literals": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.27.1.tgz", - "integrity": "sha512-hqoBX4dcZ1I33jCSWcXrP+1Ku7kdqXf1oeah7ooKOIiAdKQ+uqftgCFNOSzA5AMS2XIHEYeGFg4cKRCdpxzVOQ==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.25.9.tgz", + "integrity": "sha512-PYazBVfofCQkkMzh2P6IdIUaCEWni3iYEerAsRWuVd8+jlM1S9S9cz1dF9hIzyoZ8IA3+OwVYIp9v9e+GbgZhA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1298,14 +1296,14 @@ } }, "node_modules/@babel/plugin-transform-modules-amd": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.27.1.tgz", - "integrity": "sha512-iCsytMg/N9/oFq6n+gFTvUYDZQOMK5kEdeYxmxt91fcJGycfxVP9CnrxoliM0oumFERba2i8ZtwRUCMhvP1LnA==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.25.9.tgz", + "integrity": "sha512-g5T11tnI36jVClQlMlt4qKDLlWnG5pP9CSM4GhdRciTNMRgkfpo5cR6b4rGIOYPgRRuFAvwjPQ/Yk+ql4dyhbw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-module-transforms": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-module-transforms": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1315,14 +1313,14 @@ } }, "node_modules/@babel/plugin-transform-modules-commonjs": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.27.1.tgz", - "integrity": "sha512-OJguuwlTYlN0gBZFRPqwOGNWssZjfIUdS7HMYtN8c1KmwpwHFBwTeFZrg9XZa+DFTitWOW5iTAG7tyCUPsCCyw==", + "version": "7.26.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.26.3.tgz", + "integrity": "sha512-MgR55l4q9KddUDITEzEFYn5ZsGDXMSsU9E+kh7fjRXTIC3RHqfCo8RPRbyReYJh44HQ/yomFkqbOFohXvDCiIQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-module-transforms": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-module-transforms": "^7.26.0", + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1332,16 +1330,16 @@ } }, "node_modules/@babel/plugin-transform-modules-systemjs": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.27.1.tgz", - "integrity": "sha512-w5N1XzsRbc0PQStASMksmUeqECuzKuTJer7kFagK8AXgpCMkeDMO5S+aaFb7A51ZYDF7XI34qsTX+fkHiIm5yA==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.25.9.tgz", + "integrity": "sha512-hyss7iIlH/zLHaehT+xwiymtPOpsiwIIRlCAOwBB04ta5Tt+lNItADdlXw3jAWZ96VJ2jlhl/c+PNIQPKNfvcA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-module-transforms": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/helper-validator-identifier": "^7.27.1", - "@babel/traverse": "^7.27.1" + "@babel/helper-module-transforms": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9", + "@babel/traverse": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1351,14 +1349,14 @@ } }, "node_modules/@babel/plugin-transform-modules-umd": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.27.1.tgz", - "integrity": "sha512-iQBE/xC5BV1OxJbp6WG7jq9IWiD+xxlZhLrdwpPkTX3ydmXdvoCpyfJN7acaIBZaOqTfr76pgzqBJflNbeRK+w==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.25.9.tgz", + "integrity": "sha512-bS9MVObUgE7ww36HEfwe6g9WakQ0KF07mQF74uuXdkoziUPfKyu/nIm663kz//e5O1nPInPFx36z7WJmJ4yNEw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-module-transforms": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-module-transforms": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1368,14 +1366,14 @@ } }, "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.27.1.tgz", - "integrity": "sha512-SstR5JYy8ddZvD6MhV0tM/j16Qds4mIpJTOd1Yu9J9pJjH93bxHECF7pgtc28XvkzTD6Pxcm/0Z73Hvk7kb3Ng==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.25.9.tgz", + "integrity": "sha512-oqB6WHdKTGl3q/ItQhpLSnWWOpjUJLsOCLVyeFgeTktkBSCiurvPOsyt93gibI9CmuKvTUEtWmG5VhZD+5T/KA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-create-regexp-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1385,13 +1383,13 @@ } }, "node_modules/@babel/plugin-transform-new-target": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.27.1.tgz", - "integrity": "sha512-f6PiYeqXQ05lYq3TIfIDu/MtliKUbNwkGApPUvyo6+tc7uaR4cPjPe7DFPr15Uyycg2lZU6btZ575CuQoYh7MQ==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.25.9.tgz", + "integrity": "sha512-U/3p8X1yCSoKyUj2eOBIx3FOn6pElFOKvAAGf8HTtItuPyB+ZeOqfn+mvTtg9ZlOAjsPdK3ayQEjqHjU/yLeVQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1401,13 +1399,13 @@ } }, "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.27.1.tgz", - "integrity": "sha512-aGZh6xMo6q9vq1JGcw58lZ1Z0+i0xB2x0XaauNIUXd6O1xXc3RwoWEBlsTQrY4KQ9Jf0s5rgD6SiNkaUdJegTA==", + "version": "7.26.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.26.6.tgz", + "integrity": "sha512-CKW8Vu+uUZneQCPtXmSBUC6NCAUdya26hWCElAWh5mVSlSRsmiCPUUDKb3Z0szng1hiAJa098Hkhg9o4SE35Qw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.26.5" }, "engines": { "node": ">=6.9.0" @@ -1417,13 +1415,13 @@ } }, "node_modules/@babel/plugin-transform-numeric-separator": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.27.1.tgz", - "integrity": "sha512-fdPKAcujuvEChxDBJ5c+0BTaS6revLV7CJL08e4m3de8qJfNIuCc2nc7XJYOjBoTMJeqSmwXJ0ypE14RCjLwaw==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.25.9.tgz", + "integrity": "sha512-TlprrJ1GBZ3r6s96Yq8gEQv82s8/5HnCVHtEJScUj90thHQbwe+E5MLhi2bbNHBEJuzrvltXSru+BUxHDoog7Q==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1433,16 +1431,15 @@ } }, "node_modules/@babel/plugin-transform-object-rest-spread": { - "version": "7.27.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.27.2.tgz", - "integrity": "sha512-AIUHD7xJ1mCrj3uPozvtngY3s0xpv7Nu7DoUSnzNY6Xam1Cy4rUznR//pvMHOhQ4AvbCexhbqXCtpxGHOGOO6g==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.25.9.tgz", + "integrity": "sha512-fSaXafEE9CVHPweLYw4J0emp1t8zYTXyzN3UuG+lylqkvYd7RMrsOQ8TYx5RF231be0vqtFC6jnx3UmpJmKBYg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-compilation-targets": "^7.27.2", - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/plugin-transform-destructuring": "^7.27.1", - "@babel/plugin-transform-parameters": "^7.27.1" + "@babel/helper-compilation-targets": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/plugin-transform-parameters": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1452,14 +1449,14 @@ } }, "node_modules/@babel/plugin-transform-object-super": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.27.1.tgz", - "integrity": "sha512-SFy8S9plRPbIcxlJ8A6mT/CxFdJx/c04JEctz4jf8YZaVS2px34j7NXRrlGlHkN/M2gnpL37ZpGRGVFLd3l8Ng==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.25.9.tgz", + "integrity": "sha512-Kj/Gh+Rw2RNLbCK1VAWj2U48yxxqL2x0k10nPtSdRa0O2xnHXalD0s+o1A6a0W43gJ00ANo38jxkQreckOzv5A==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/helper-replace-supers": "^7.27.1" + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-replace-supers": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1469,13 +1466,13 @@ } }, "node_modules/@babel/plugin-transform-optional-catch-binding": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.27.1.tgz", - "integrity": "sha512-txEAEKzYrHEX4xSZN4kJ+OfKXFVSWKB2ZxM9dpcE3wT7smwkNmXo5ORRlVzMVdJbD+Q8ILTgSD7959uj+3Dm3Q==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.25.9.tgz", + "integrity": "sha512-qM/6m6hQZzDcZF3onzIhZeDHDO43bkNNlOX0i8n3lR6zLbu0GN2d8qfM/IERJZYauhAHSLHy39NF0Ctdvcid7g==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1485,14 +1482,14 @@ } }, "node_modules/@babel/plugin-transform-optional-chaining": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.27.1.tgz", - "integrity": "sha512-BQmKPPIuc8EkZgNKsv0X4bPmOoayeu4F1YCwx2/CfmDSXDbp7GnzlUH+/ul5VGfRg1AoFPsrIThlEBj2xb4CAg==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.25.9.tgz", + "integrity": "sha512-6AvV0FsLULbpnXeBjrY4dmWF8F7gf8QnvTEoO/wX/5xm/xE1Xo8oPuD3MPS+KS9f9XBEAWN7X1aWr4z9HdOr7A==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1502,13 +1499,13 @@ } }, "node_modules/@babel/plugin-transform-parameters": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.27.1.tgz", - "integrity": "sha512-018KRk76HWKeZ5l4oTj2zPpSh+NbGdt0st5S6x0pga6HgrjBOJb24mMDHorFopOOd6YHkLgOZ+zaCjZGPO4aKg==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.25.9.tgz", + "integrity": "sha512-wzz6MKwpnshBAiRmn4jR8LYz/g8Ksg0o80XmwZDlordjwEk9SxBzTWC7F5ef1jhbrbOW2DJ5J6ayRukrJmnr0g==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1518,14 +1515,14 @@ } }, "node_modules/@babel/plugin-transform-private-methods": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.27.1.tgz", - "integrity": "sha512-10FVt+X55AjRAYI9BrdISN9/AQWHqldOeZDUoLyif1Kn05a56xVBXb8ZouL8pZ9jem8QpXaOt8TS7RHUIS+GPA==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.25.9.tgz", + "integrity": "sha512-D/JUozNpQLAPUVusvqMxyvjzllRaF8/nSrP1s2YGQT/W4LHK4xxsMcHjhOGTS01mp9Hda8nswb+FblLdJornQw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-create-class-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1535,15 +1532,15 @@ } }, "node_modules/@babel/plugin-transform-private-property-in-object": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.27.1.tgz", - "integrity": "sha512-5J+IhqTi1XPa0DXF83jYOaARrX+41gOewWbkPyjMNRDqgOCqdffGh8L3f/Ek5utaEBZExjSAzcyjmV9SSAWObQ==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.25.9.tgz", + "integrity": "sha512-Evf3kcMqzXA3xfYJmZ9Pg1OvKdtqsDMSWBDzZOPLvHiTt36E75jLDQo5w1gtRU95Q4E5PDttrTf25Fw8d/uWLw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.27.1", - "@babel/helper-create-class-features-plugin": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-annotate-as-pure": "^7.25.9", + "@babel/helper-create-class-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1553,13 +1550,13 @@ } }, "node_modules/@babel/plugin-transform-property-literals": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.27.1.tgz", - "integrity": "sha512-oThy3BCuCha8kDZ8ZkgOg2exvPYUlprMukKQXI1r1pJ47NCvxfkEy8vK+r/hT9nF0Aa4H1WUPZZjHTFtAhGfmQ==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.25.9.tgz", + "integrity": "sha512-IvIUeV5KrS/VPavfSM/Iu+RE6llrHrYIKY1yfCzyO/lMXHQ+p7uGhonmGVisv6tSBSVgWzMBohTcvkC9vQcQFA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1569,13 +1566,14 @@ } }, "node_modules/@babel/plugin-transform-regenerator": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.27.1.tgz", - "integrity": "sha512-B19lbbL7PMrKr52BNPjCqg1IyNUIjTcxKj8uX9zHO+PmWN93s19NDr/f69mIkEp2x9nmDJ08a7lgHaTTzvW7mw==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.25.9.tgz", + "integrity": "sha512-vwDcDNsgMPDGP0nMqzahDWE5/MLcX8sv96+wfX7as7LoF/kr97Bo/7fI00lXY4wUXYfVmwIIyG80fGZ1uvt2qg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.25.9", + "regenerator-transform": "^0.15.2" }, "engines": { "node": ">=6.9.0" @@ -1585,14 +1583,14 @@ } }, "node_modules/@babel/plugin-transform-regexp-modifiers": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regexp-modifiers/-/plugin-transform-regexp-modifiers-7.27.1.tgz", - "integrity": "sha512-TtEciroaiODtXvLZv4rmfMhkCv8jx3wgKpL68PuiPh2M4fvz5jhsA7697N1gMvkvr/JTF13DrFYyEbY9U7cVPA==", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regexp-modifiers/-/plugin-transform-regexp-modifiers-7.26.0.tgz", + "integrity": "sha512-vN6saax7lrA2yA/Pak3sCxuD6F5InBjn9IcrIKQPjpsLvuHYLVroTxjdlVRHjjBWxKOqIwpTXDkOssYT4BFdRw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-create-regexp-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1602,13 +1600,13 @@ } }, "node_modules/@babel/plugin-transform-reserved-words": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.27.1.tgz", - "integrity": "sha512-V2ABPHIJX4kC7HegLkYoDpfg9PVmuWy/i6vUM5eGK22bx4YVFD3M5F0QQnWQoDs6AGsUWTVOopBiMFQgHaSkVw==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.25.9.tgz", + "integrity": "sha512-7DL7DKYjn5Su++4RXu8puKZm2XBPHyjWLUidaPEkCUBbE7IPcsrkRHggAOOKydH1dASWdcUBxrkOGNxUv5P3Jg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1638,13 +1636,13 @@ } }, "node_modules/@babel/plugin-transform-shorthand-properties": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.27.1.tgz", - "integrity": "sha512-N/wH1vcn4oYawbJ13Y/FxcQrWk63jhfNa7jef0ih7PHSIHX2LB7GWE1rkPrOnka9kwMxb6hMl19p7lidA+EHmQ==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.25.9.tgz", + "integrity": "sha512-MUv6t0FhO5qHnS/W8XCbHmiRWOphNufpE1IVxhK5kuN3Td9FT1x4rx4K42s3RYdMXCXpfWkGSbCSd0Z64xA7Ng==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1654,14 +1652,14 @@ } }, "node_modules/@babel/plugin-transform-spread": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.27.1.tgz", - "integrity": "sha512-kpb3HUqaILBJcRFVhFUs6Trdd4mkrzcGXss+6/mxUd273PfbWqSDHRzMT2234gIg2QYfAjvXLSquP1xECSg09Q==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.25.9.tgz", + "integrity": "sha512-oNknIB0TbURU5pqJFVbOOFspVlrpVwo2H1+HUIsVDvp5VauGGDP1ZEvO8Nn5xyMEs3dakajOxlmkNW7kNgSm6A==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1671,13 +1669,13 @@ } }, "node_modules/@babel/plugin-transform-sticky-regex": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.27.1.tgz", - "integrity": "sha512-lhInBO5bi/Kowe2/aLdBAawijx+q1pQzicSgnkB6dUPc1+RC8QmJHKf2OjvU+NZWitguJHEaEmbV6VWEouT58g==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.25.9.tgz", + "integrity": "sha512-WqBUSgeVwucYDP9U/xNRQam7xV8W5Zf+6Eo7T2SRVUFlhRiMNFdFz58u0KZmCVVqs2i7SHgpRnAhzRNmKfi2uA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1687,13 +1685,13 @@ } }, "node_modules/@babel/plugin-transform-template-literals": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.27.1.tgz", - "integrity": "sha512-fBJKiV7F2DxZUkg5EtHKXQdbsbURW3DZKQUWphDum0uRP6eHGGa/He9mc0mypL680pb+e/lDIthRohlv8NCHkg==", + "version": "7.26.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.26.8.tgz", + "integrity": "sha512-OmGDL5/J0CJPJZTHZbi2XpO0tyT2Ia7fzpW5GURwdtp2X3fMmN8au/ej6peC/T33/+CRiIpA8Krse8hFGVmT5Q==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.26.5" }, "engines": { "node": ">=6.9.0" @@ -1703,13 +1701,13 @@ } }, "node_modules/@babel/plugin-transform-typeof-symbol": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.27.1.tgz", - "integrity": "sha512-RiSILC+nRJM7FY5srIyc4/fGIwUhyDuuBSdWn4y6yT6gm652DpCHZjIipgn6B7MQ1ITOUnAKWixEUjQRIBIcLw==", + "version": "7.26.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.26.7.tgz", + "integrity": "sha512-jfoTXXZTgGg36BmhqT3cAYK5qkmqvJpvNrPhaK/52Vgjhw4Rq29s9UqpWWV0D6yuRmgiFH/BUVlkl96zJWqnaw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.26.5" }, "engines": { "node": ">=6.9.0" @@ -1719,13 +1717,13 @@ } }, "node_modules/@babel/plugin-transform-unicode-escapes": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.27.1.tgz", - "integrity": "sha512-Ysg4v6AmF26k9vpfFuTZg8HRfVWzsh1kVfowA23y9j/Gu6dOuahdUVhkLqpObp3JIv27MLSii6noRnuKN8H0Mg==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.25.9.tgz", + "integrity": "sha512-s5EDrE6bW97LtxOcGj1Khcx5AaXwiMmi4toFWRDP9/y0Woo6pXC+iyPu/KuhKtfSrNFd7jJB+/fkOtZy6aIC6Q==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1735,14 +1733,14 @@ } }, "node_modules/@babel/plugin-transform-unicode-property-regex": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.27.1.tgz", - "integrity": "sha512-uW20S39PnaTImxp39O5qFlHLS9LJEmANjMG7SxIhap8rCHqu0Ik+tLEPX5DKmHn6CsWQ7j3lix2tFOa5YtL12Q==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.25.9.tgz", + "integrity": "sha512-Jt2d8Ga+QwRluxRQ307Vlxa6dMrYEMZCgGxoPR8V52rxPyldHu3hdlHspxaqYmE7oID5+kB+UKUB/eWS+DkkWg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-create-regexp-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1752,14 +1750,14 @@ } }, "node_modules/@babel/plugin-transform-unicode-regex": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.27.1.tgz", - "integrity": "sha512-xvINq24TRojDuyt6JGtHmkVkrfVV3FPT16uytxImLeBZqW3/H52yN+kM1MGuyPkIQxrzKwPHs5U/MP3qKyzkGw==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.25.9.tgz", + "integrity": "sha512-yoxstj7Rg9dlNn9UQxzk4fcNivwv4nUYz7fYXBaKxvw/lnmPuOm/ikoELygbYq68Bls3D/D+NBPHiLwZdZZ4HA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-create-regexp-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1769,14 +1767,14 @@ } }, "node_modules/@babel/plugin-transform-unicode-sets-regex": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.27.1.tgz", - "integrity": "sha512-EtkOujbc4cgvb0mlpQefi4NTPBzhSIevblFevACNLUspmrALgmEBdL/XfnyyITfd8fKBZrZys92zOWcik7j9Tw==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.25.9.tgz", + "integrity": "sha512-8BYqO3GeVNHtx69fdPshN3fnzUNLrWdHhk/icSwigksJGczKSizZ+Z6SBCxTs723Fr5VSNorTIK7a+R2tISvwQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-create-regexp-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1786,75 +1784,75 @@ } }, "node_modules/@babel/preset-env": { - "version": "7.27.2", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.27.2.tgz", - "integrity": "sha512-Ma4zSuYSlGNRlCLO+EAzLnCmJK2vdstgv+n7aUP+/IKZrOfWHOJVdSJtuub8RzHTj3ahD37k5OKJWvzf16TQyQ==", + "version": "7.26.9", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.26.9.tgz", + "integrity": "sha512-vX3qPGE8sEKEAZCWk05k3cpTAE3/nOYca++JA+Rd0z2NCNzabmYvEiSShKzm10zdquOIAVXsy2Ei/DTW34KlKQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.27.2", - "@babel/helper-compilation-targets": "^7.27.2", - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/helper-validator-option": "^7.27.1", - "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.27.1", - "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.27.1", - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.27.1", - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.27.1", - "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.27.1", + "@babel/compat-data": "^7.26.8", + "@babel/helper-compilation-targets": "^7.26.5", + "@babel/helper-plugin-utils": "^7.26.5", + "@babel/helper-validator-option": "^7.25.9", + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.25.9", + "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.25.9", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.25.9", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.25.9", + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.25.9", "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", - "@babel/plugin-syntax-import-assertions": "^7.27.1", - "@babel/plugin-syntax-import-attributes": "^7.27.1", + "@babel/plugin-syntax-import-assertions": "^7.26.0", + "@babel/plugin-syntax-import-attributes": "^7.26.0", "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", - "@babel/plugin-transform-arrow-functions": "^7.27.1", - "@babel/plugin-transform-async-generator-functions": "^7.27.1", - "@babel/plugin-transform-async-to-generator": "^7.27.1", - "@babel/plugin-transform-block-scoped-functions": "^7.27.1", - "@babel/plugin-transform-block-scoping": "^7.27.1", - "@babel/plugin-transform-class-properties": "^7.27.1", - "@babel/plugin-transform-class-static-block": "^7.27.1", - "@babel/plugin-transform-classes": "^7.27.1", - "@babel/plugin-transform-computed-properties": "^7.27.1", - "@babel/plugin-transform-destructuring": "^7.27.1", - "@babel/plugin-transform-dotall-regex": "^7.27.1", - "@babel/plugin-transform-duplicate-keys": "^7.27.1", - "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.27.1", - "@babel/plugin-transform-dynamic-import": "^7.27.1", - "@babel/plugin-transform-exponentiation-operator": "^7.27.1", - "@babel/plugin-transform-export-namespace-from": "^7.27.1", - "@babel/plugin-transform-for-of": "^7.27.1", - "@babel/plugin-transform-function-name": "^7.27.1", - "@babel/plugin-transform-json-strings": "^7.27.1", - "@babel/plugin-transform-literals": "^7.27.1", - "@babel/plugin-transform-logical-assignment-operators": "^7.27.1", - "@babel/plugin-transform-member-expression-literals": "^7.27.1", - "@babel/plugin-transform-modules-amd": "^7.27.1", - "@babel/plugin-transform-modules-commonjs": "^7.27.1", - "@babel/plugin-transform-modules-systemjs": "^7.27.1", - "@babel/plugin-transform-modules-umd": "^7.27.1", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.27.1", - "@babel/plugin-transform-new-target": "^7.27.1", - "@babel/plugin-transform-nullish-coalescing-operator": "^7.27.1", - "@babel/plugin-transform-numeric-separator": "^7.27.1", - "@babel/plugin-transform-object-rest-spread": "^7.27.2", - "@babel/plugin-transform-object-super": "^7.27.1", - "@babel/plugin-transform-optional-catch-binding": "^7.27.1", - "@babel/plugin-transform-optional-chaining": "^7.27.1", - "@babel/plugin-transform-parameters": "^7.27.1", - "@babel/plugin-transform-private-methods": "^7.27.1", - "@babel/plugin-transform-private-property-in-object": "^7.27.1", - "@babel/plugin-transform-property-literals": "^7.27.1", - "@babel/plugin-transform-regenerator": "^7.27.1", - "@babel/plugin-transform-regexp-modifiers": "^7.27.1", - "@babel/plugin-transform-reserved-words": "^7.27.1", - "@babel/plugin-transform-shorthand-properties": "^7.27.1", - "@babel/plugin-transform-spread": "^7.27.1", - "@babel/plugin-transform-sticky-regex": "^7.27.1", - "@babel/plugin-transform-template-literals": "^7.27.1", - "@babel/plugin-transform-typeof-symbol": "^7.27.1", - "@babel/plugin-transform-unicode-escapes": "^7.27.1", - "@babel/plugin-transform-unicode-property-regex": "^7.27.1", - "@babel/plugin-transform-unicode-regex": "^7.27.1", - "@babel/plugin-transform-unicode-sets-regex": "^7.27.1", + "@babel/plugin-transform-arrow-functions": "^7.25.9", + "@babel/plugin-transform-async-generator-functions": "^7.26.8", + "@babel/plugin-transform-async-to-generator": "^7.25.9", + "@babel/plugin-transform-block-scoped-functions": "^7.26.5", + "@babel/plugin-transform-block-scoping": "^7.25.9", + "@babel/plugin-transform-class-properties": "^7.25.9", + "@babel/plugin-transform-class-static-block": "^7.26.0", + "@babel/plugin-transform-classes": "^7.25.9", + "@babel/plugin-transform-computed-properties": "^7.25.9", + "@babel/plugin-transform-destructuring": "^7.25.9", + "@babel/plugin-transform-dotall-regex": "^7.25.9", + "@babel/plugin-transform-duplicate-keys": "^7.25.9", + "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.25.9", + "@babel/plugin-transform-dynamic-import": "^7.25.9", + "@babel/plugin-transform-exponentiation-operator": "^7.26.3", + "@babel/plugin-transform-export-namespace-from": "^7.25.9", + "@babel/plugin-transform-for-of": "^7.26.9", + "@babel/plugin-transform-function-name": "^7.25.9", + "@babel/plugin-transform-json-strings": "^7.25.9", + "@babel/plugin-transform-literals": "^7.25.9", + "@babel/plugin-transform-logical-assignment-operators": "^7.25.9", + "@babel/plugin-transform-member-expression-literals": "^7.25.9", + "@babel/plugin-transform-modules-amd": "^7.25.9", + "@babel/plugin-transform-modules-commonjs": "^7.26.3", + "@babel/plugin-transform-modules-systemjs": "^7.25.9", + "@babel/plugin-transform-modules-umd": "^7.25.9", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.25.9", + "@babel/plugin-transform-new-target": "^7.25.9", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.26.6", + "@babel/plugin-transform-numeric-separator": "^7.25.9", + "@babel/plugin-transform-object-rest-spread": "^7.25.9", + "@babel/plugin-transform-object-super": "^7.25.9", + "@babel/plugin-transform-optional-catch-binding": "^7.25.9", + "@babel/plugin-transform-optional-chaining": "^7.25.9", + "@babel/plugin-transform-parameters": "^7.25.9", + "@babel/plugin-transform-private-methods": "^7.25.9", + "@babel/plugin-transform-private-property-in-object": "^7.25.9", + "@babel/plugin-transform-property-literals": "^7.25.9", + "@babel/plugin-transform-regenerator": "^7.25.9", + "@babel/plugin-transform-regexp-modifiers": "^7.26.0", + "@babel/plugin-transform-reserved-words": "^7.25.9", + "@babel/plugin-transform-shorthand-properties": "^7.25.9", + "@babel/plugin-transform-spread": "^7.25.9", + "@babel/plugin-transform-sticky-regex": "^7.25.9", + "@babel/plugin-transform-template-literals": "^7.26.8", + "@babel/plugin-transform-typeof-symbol": "^7.26.7", + "@babel/plugin-transform-unicode-escapes": "^7.25.9", + "@babel/plugin-transform-unicode-property-regex": "^7.25.9", + "@babel/plugin-transform-unicode-regex": "^7.25.9", + "@babel/plugin-transform-unicode-sets-regex": "^7.25.9", "@babel/preset-modules": "0.1.6-no-external-plugins", "babel-plugin-polyfill-corejs2": "^0.4.10", "babel-plugin-polyfill-corejs3": "^0.11.0", @@ -1914,32 +1912,32 @@ "dev": true }, "node_modules/@babel/template": { - "version": "7.27.2", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", - "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", + "version": "7.26.9", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.26.9.tgz", + "integrity": "sha512-qyRplbeIpNZhmzOysF/wFMuP9sctmh2cFzRAZOn1YapxBsE1i9bJIY586R/WBLfLcmcBlM8ROBiQURnnNy+zfA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.27.1", - "@babel/parser": "^7.27.2", - "@babel/types": "^7.27.1" + "@babel/code-frame": "^7.26.2", + "@babel/parser": "^7.26.9", + "@babel/types": "^7.26.9" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.27.3", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.27.3.tgz", - "integrity": "sha512-lId/IfN/Ye1CIu8xG7oKBHXd2iNb2aW1ilPszzGcJug6M8RCKfVNcYhpI5+bMvFYjK7lXIM0R+a+6r8xhHp2FQ==", + "version": "7.26.10", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.26.10.tgz", + "integrity": "sha512-k8NuDrxr0WrPH5Aupqb2LCVURP/S0vBEn5mK6iH+GIYob66U5EtoZvcdudR2jQ4cmTwhEwW1DLB+Yyas9zjF6A==", "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.27.3", - "@babel/parser": "^7.27.3", - "@babel/template": "^7.27.2", - "@babel/types": "^7.27.3", + "@babel/code-frame": "^7.26.2", + "@babel/generator": "^7.26.10", + "@babel/parser": "^7.26.10", + "@babel/template": "^7.26.9", + "@babel/types": "^7.26.10", "debug": "^4.3.1", "globals": "^11.1.0" }, @@ -1971,13 +1969,13 @@ "dev": true }, "node_modules/@babel/types": { - "version": "7.27.3", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.3.tgz", - "integrity": "sha512-Y1GkI4ktrtvmawoSq+4FCVHNryea6uR+qUQy0AGxLSsjCX0nVmkYQMBLHDkXZuo5hGx7eYdnIaslsdBFm7zbUw==", + "version": "7.26.10", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.10.tgz", + "integrity": "sha512-emqcG3vHrpxUKTrxcblR36dcrcoRDvKmnL/dCL6ZsHaShW80qxCAcNhzQZrpeM765VzEos+xOi4s+r4IXzTwdQ==", "license": "MIT", "dependencies": { - "@babel/helper-string-parser": "^7.27.1", - "@babel/helper-validator-identifier": "^7.27.1" + "@babel/helper-string-parser": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -3375,9 +3373,9 @@ } }, "node_modules/@mediakind/mkplayer": { - "version": "1.22.0", - "resolved": "https://registry.npmjs.org/@mediakind/mkplayer/-/mkplayer-1.22.0.tgz", - "integrity": "sha512-1PWswbIw3U84QkRWbkCVDha0qppzrpDbxiytnRFkLeUpE8klKRWJtI92ph0favspfTFjanX8A0qTGRkA8lsLwA==", + "version": "1.21.0", + "resolved": "https://registry.npmjs.org/@mediakind/mkplayer/-/mkplayer-1.21.0.tgz", + "integrity": "sha512-6sZwxQObISgmD4z0RV6xoi2bJgnOBtDAa2bPg4H/D095MaUInaDkrCimROst/rWfeMFg2m4h9PSmJV88cYbvQw==", "license": "©2025 Copyright Mediakind Ltd. All Rights Reserved. Including All Downloadable Materials.", "dependencies": { "bitmovin-player": "8.193.0", @@ -3951,16 +3949,15 @@ "dev": true }, "node_modules/@types/json-schema": { - "version": "7.0.15", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "dev": true, - "license": "MIT" + "version": "7.0.9", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz", + "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==", + "dev": true }, "node_modules/@types/lodash": { - "version": "4.17.17", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.17.tgz", - "integrity": "sha512-RRVJ+J3J+WmyOTqnz3PiBLA501eKwXl2noseKOrNo/6+XEHjTAxO4xHvxQB6QuNm+s4WRbn6rSiap8+EA+ykFQ==", + "version": "4.17.16", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.16.tgz", + "integrity": "sha512-HX7Em5NYQAXKW+1T+FiuG27NGwzJfCX3s1GjOa7ujxZa52kjJLOr4FUxT+giF6Tgxv1e+/czV/iTtBw27WTU9g==", "dev": true, "license": "MIT" }, @@ -3989,9 +3986,9 @@ "dev": true }, "node_modules/@types/sanitize-html": { - "version": "2.16.0", - "resolved": "https://registry.npmjs.org/@types/sanitize-html/-/sanitize-html-2.16.0.tgz", - "integrity": "sha512-l6rX1MUXje5ztPT0cAFtUayXF06DqPhRyfVXareEN5gGCFaP/iwsxIyKODr9XDhfxPpN6vXUFNfo5kZMXCxBtw==", + "version": "2.15.0", + "resolved": "https://registry.npmjs.org/@types/sanitize-html/-/sanitize-html-2.15.0.tgz", + "integrity": "sha512-71Z6PbYsVKfp4i6Jvr37s5ql6if1Q/iJQT80NbaSi7uGaG8CqBMXP0pk/EsURAOuGdk5IJCd/vnzKrR7S3Txsw==", "dev": true, "license": "MIT", "dependencies": { @@ -4063,6 +4060,12 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, + "node_modules/@types/vuelidate/node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true + }, "node_modules/@types/vuelidate/node_modules/postcss": { "version": "8.5.1", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.1.tgz", @@ -4252,6 +4255,12 @@ "node": "^10 || ^12 || >=14" } }, + "node_modules/@vue/babel-plugin-resolve-type/node_modules/postcss/node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true + }, "node_modules/@vue/babel-plugin-resolve-type/node_modules/source-map-js": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", @@ -7240,9 +7249,9 @@ } }, "node_modules/core-js": { - "version": "3.42.0", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.42.0.tgz", - "integrity": "sha512-Sz4PP4ZA+Rq4II21qkNqOEDTDrCvcANId3xpIgB34NDkWc3UduWj2dqEtN9yZIq8Dk3HyPI33x9sqqU5C8sr0g==", + "version": "3.41.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.41.0.tgz", + "integrity": "sha512-SJ4/EHwS36QMJd6h/Rg+GyR4A5xE0FSI3eZ+iBVpfqf1x0eTSg1smWLHrA+2jQThZSh97fmSgFSU8B61nxosxA==", "hasInstallScript": true, "license": "MIT", "funding": { @@ -15034,10 +15043,9 @@ } }, "node_modules/picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "license": "ISC" + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" }, "node_modules/picomatch": { "version": "2.2.3", @@ -15665,6 +15673,16 @@ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz", "integrity": "sha1-M2w+/BIgrc7dosn6tntaeVWjNlg=" }, + "node_modules/regenerator-transform": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz", + "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.8.4" + } + }, "node_modules/regex-not": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", @@ -15941,9 +15959,9 @@ "dev": true }, "node_modules/sanitize-html": { - "version": "2.17.0", - "resolved": "https://registry.npmjs.org/sanitize-html/-/sanitize-html-2.17.0.tgz", - "integrity": "sha512-dLAADUSS8rBwhaevT12yCezvioCA+bmUTPH/u57xKPT8d++voeYE6HeluA/bPbQ15TwDBG2ii+QZIEmYx8VdxA==", + "version": "2.15.0", + "resolved": "https://registry.npmjs.org/sanitize-html/-/sanitize-html-2.15.0.tgz", + "integrity": "sha512-wIjst57vJGpLyBP8ioUbg6ThwJie5SuSIjHxJg53v5Fg+kUK+AXlb7bK3RNXpp315MvwM+0OBGCV6h5pPHsVhA==", "license": "MIT", "dependencies": { "deepmerge": "^4.2.2", @@ -15990,6 +16008,11 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, + "node_modules/sanitize-html/node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==" + }, "node_modules/sanitize-html/node_modules/postcss": { "version": "8.5.1", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.1.tgz", @@ -16026,9 +16049,9 @@ } }, "node_modules/sass": { - "version": "1.89.0", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.89.0.tgz", - "integrity": "sha512-ld+kQU8YTdGNjOLfRWBzewJpU5cwEv/h5yyqlSeJcj6Yh8U4TDA9UA5FPicqDz/xgRPWRSYIQNiFks21TbA9KQ==", + "version": "1.86.3", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.86.3.tgz", + "integrity": "sha512-iGtg8kus4GrsGLRDLRBRHY9dNVA78ZaS7xr01cWnS7PEMQyFtTqBiyCrfpTYTZXRWM94akzckYjh8oADfFNTzw==", "dev": true, "license": "MIT", "dependencies": { @@ -17898,6 +17921,12 @@ "node": ">=6" } }, + "node_modules/update-browserslist-db/node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true + }, "node_modules/uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", @@ -18261,15 +18290,14 @@ } }, "node_modules/webpack": { - "version": "5.99.9", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.99.9.tgz", - "integrity": "sha512-brOPwM3JnmOa+7kd3NsmOUOwbDAj8FT9xDsG3IW0MgbN9yZV7Oi/s/+MNQ/EcSMqw7qfoRyXPoeEWT8zLVdVGg==", + "version": "5.99.5", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.99.5.tgz", + "integrity": "sha512-q+vHBa6H9qwBLUlHL4Y7L0L1/LlyBKZtS9FHNCQmtayxjI5RKC9yD8gpvLeqGv5lCQp1Re04yi0MF40pf30Pvg==", "dev": true, "license": "MIT", "dependencies": { "@types/eslint-scope": "^3.7.7", "@types/estree": "^1.0.6", - "@types/json-schema": "^7.0.15", "@webassemblyjs/ast": "^1.14.1", "@webassemblyjs/wasm-edit": "^1.14.1", "@webassemblyjs/wasm-parser": "^1.14.1", @@ -18286,7 +18314,7 @@ "loader-runner": "^4.2.0", "mime-types": "^2.1.27", "neo-async": "^2.6.2", - "schema-utils": "^4.3.2", + "schema-utils": "^4.3.0", "tapable": "^2.1.1", "terser-webpack-plugin": "^5.3.11", "watchpack": "^2.4.1", @@ -19048,9 +19076,9 @@ "license": "MIT" }, "node_modules/webpack/node_modules/schema-utils": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.2.tgz", - "integrity": "sha512-Gn/JaSk/Mt9gYubxTtSn/QCV4em9mpAPiR1rqy/Ocu19u/G9J5WWdNoUT4SiV6mFC3y6cxyFcFwdzPM3FgxGAQ==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.0.tgz", + "integrity": "sha512-Gf9qqc58SpCA/xdziiHz35F4GNIWYWZrEshUc/G/r5BnLph6xpKuLeoJoQuj5WfBIx/eQLf+hmVPYHaxJu7V2g==", "dev": true, "license": "MIT", "dependencies": { diff --git a/AdminUI/LearningHub.Nhs.AdminUI/package.json b/AdminUI/LearningHub.Nhs.AdminUI/package.json index 0c7f82eca..ee739c496 100644 --- a/AdminUI/LearningHub.Nhs.AdminUI/package.json +++ b/AdminUI/LearningHub.Nhs.AdminUI/package.json @@ -22,20 +22,20 @@ "dependencies": { "@ckeditor/ckeditor5-build-classic": "16.0.0", "@ckeditor/ckeditor5-vue": "1.0.3", - "@mediakind/mkplayer": "^1.22.0", + "@mediakind/mkplayer": "^1.21.0", "axios": "^0.30.0", "babel-polyfill": "^6.26.0", "bootstrap": "^4.6.2", "ckeditor4-vue": "^0.2.0", "concurrently": "^7.6.0", - "core-js": "^3.42.0", + "core-js": "^3.41.0", "js-cookie": "2.2.1", "lodash": "4.17.21", "moment": "^2.30.1", "navigator.sendbeacon": "0.0.20", "nhsuk-frontend": "^6.1.2", "openseadragon": "^2.4.2", - "sanitize-html": "^2.17.0", + "sanitize-html": "^2.15.0", "save": "^2.9.0", "ts-debounce": "2.3.0", "tus-js-client": "^2.3.2", @@ -52,8 +52,8 @@ "vuex": "^3.6.2" }, "devDependencies": { - "@babel/preset-env": "^7.27.2", - "@babel/core": "^7.27.3", + "@babel/preset-env": "^7.26.9", + "@babel/core": "^7.26.10", "@types/axios": "^0.14.0", "@types/bootstrap": "4.1.3", "@types/ckeditor": "4.9.10", @@ -61,9 +61,9 @@ "@types/jquery": "^3.3.32", "@types/jquery-match-height": "^0.7.8", "@types/js-cookie": "2.2.1", - "@types/lodash": "4.17.17", + "@types/lodash": "4.17.16", "@types/openseadragon": "^2.4.5", - "@types/sanitize-html": "^2.16.0", + "@types/sanitize-html": "^2.15.0", "@types/vuelidate": "^0.7.22", "@vue/babel-preset-app": "4.5.19", "@vue/test-utils": "^1.3.6", @@ -75,7 +75,7 @@ "css-loader": "^5.2.4", "file-loader": "^6.2.0", "jest": "^27.5.1", - "sass": "^1.89.0", + "sass": "^1.86.3", "sass-loader": "^11.0.1", "style-loader": "^2.0.0", "ts-jest": "^27.1.5", @@ -84,7 +84,7 @@ "vue-jest": "^3.0.7", "vue-loader": "^15.11.1", "vue-template-compiler": "^2.7.16", - "webpack": "^5.99.9", + "webpack": "^5.99.5", "webpack-cli": "^4.10.0", "webpack-dev-server": "^3.11.3" } diff --git a/LearningHub.Nhs.WebUI.AutomatedUiTests/LearningHub.Nhs.WebUI.AutomatedUiTests.csproj b/LearningHub.Nhs.WebUI.AutomatedUiTests/LearningHub.Nhs.WebUI.AutomatedUiTests.csproj index 34a9455d2..404a00d6e 100644 --- a/LearningHub.Nhs.WebUI.AutomatedUiTests/LearningHub.Nhs.WebUI.AutomatedUiTests.csproj +++ b/LearningHub.Nhs.WebUI.AutomatedUiTests/LearningHub.Nhs.WebUI.AutomatedUiTests.csproj @@ -13,7 +13,7 @@ - + diff --git a/LearningHub.Nhs.WebUI.sln b/LearningHub.Nhs.WebUI.sln index 55cce01f0..a0ebae6cc 100644 --- a/LearningHub.Nhs.WebUI.sln +++ b/LearningHub.Nhs.WebUI.sln @@ -82,6 +82,16 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LearningHub.Nhs.ReportApi.S EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LearningHub.Nhs.WebUI.AutomatedUiTests", "LearningHub.Nhs.WebUI.AutomatedUiTests\LearningHub.Nhs.WebUI.AutomatedUiTests.csproj", "{A84EC50B-2B01-4819-A2B1-BD867B7595CA}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "MessagingService", "MessagingService", "{02EA681E-C7D8-13C7-8484-4AC65E1B71E8}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "MessageQueueing", "MessageQueueing", "{FC592E2B-861F-4C9A-BD1A-95CB97D36285}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LearningHub.Nhs.MessageQueueing", "MessageQueueing\LearningHub.Nhs.MessageQueueing\LearningHub.Nhs.MessageQueueing.csproj", "{534A145F-1FE4-B601-48FF-979744373E4B}" +EndProject +Project("{00D1A9C2-B5F0-4AF3-8072-F6C62B433612}") = "LearningHub.Nhs.MessageQueueing.Database", "MessageQueueing\LearningHub.Nhs.MessageQueueing.Database\LearningHub.Nhs.MessageQueueing.Database.sqlproj", "{AFC1A740-BBA1-44BC-8A52-A65D2E506E69}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LearningHub.Nhs.MessagingService", "MessagingService\LearningHub.Nhs.MessagingService\LearningHub.Nhs.MessagingService.csproj", "{CCB52C7C-47B6-1AE7-7578-7A26B3FFEB71}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -346,6 +356,34 @@ Global {A84EC50B-2B01-4819-A2B1-BD867B7595CA}.Release|Any CPU.Build.0 = Release|Any CPU {A84EC50B-2B01-4819-A2B1-BD867B7595CA}.Release|x64.ActiveCfg = Release|Any CPU {A84EC50B-2B01-4819-A2B1-BD867B7595CA}.Release|x64.Build.0 = Release|Any CPU + {534A145F-1FE4-B601-48FF-979744373E4B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {534A145F-1FE4-B601-48FF-979744373E4B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {534A145F-1FE4-B601-48FF-979744373E4B}.Debug|x64.ActiveCfg = Debug|Any CPU + {534A145F-1FE4-B601-48FF-979744373E4B}.Debug|x64.Build.0 = Debug|Any CPU + {534A145F-1FE4-B601-48FF-979744373E4B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {534A145F-1FE4-B601-48FF-979744373E4B}.Release|Any CPU.Build.0 = Release|Any CPU + {534A145F-1FE4-B601-48FF-979744373E4B}.Release|x64.ActiveCfg = Release|Any CPU + {534A145F-1FE4-B601-48FF-979744373E4B}.Release|x64.Build.0 = Release|Any CPU + {AFC1A740-BBA1-44BC-8A52-A65D2E506E69}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AFC1A740-BBA1-44BC-8A52-A65D2E506E69}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AFC1A740-BBA1-44BC-8A52-A65D2E506E69}.Debug|Any CPU.Deploy.0 = Debug|Any CPU + {AFC1A740-BBA1-44BC-8A52-A65D2E506E69}.Debug|x64.ActiveCfg = Debug|Any CPU + {AFC1A740-BBA1-44BC-8A52-A65D2E506E69}.Debug|x64.Build.0 = Debug|Any CPU + {AFC1A740-BBA1-44BC-8A52-A65D2E506E69}.Debug|x64.Deploy.0 = Debug|Any CPU + {AFC1A740-BBA1-44BC-8A52-A65D2E506E69}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AFC1A740-BBA1-44BC-8A52-A65D2E506E69}.Release|Any CPU.Build.0 = Release|Any CPU + {AFC1A740-BBA1-44BC-8A52-A65D2E506E69}.Release|Any CPU.Deploy.0 = Release|Any CPU + {AFC1A740-BBA1-44BC-8A52-A65D2E506E69}.Release|x64.ActiveCfg = Release|Any CPU + {AFC1A740-BBA1-44BC-8A52-A65D2E506E69}.Release|x64.Build.0 = Release|Any CPU + {AFC1A740-BBA1-44BC-8A52-A65D2E506E69}.Release|x64.Deploy.0 = Release|Any CPU + {CCB52C7C-47B6-1AE7-7578-7A26B3FFEB71}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CCB52C7C-47B6-1AE7-7578-7A26B3FFEB71}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CCB52C7C-47B6-1AE7-7578-7A26B3FFEB71}.Debug|x64.ActiveCfg = Debug|Any CPU + {CCB52C7C-47B6-1AE7-7578-7A26B3FFEB71}.Debug|x64.Build.0 = Debug|Any CPU + {CCB52C7C-47B6-1AE7-7578-7A26B3FFEB71}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CCB52C7C-47B6-1AE7-7578-7A26B3FFEB71}.Release|Any CPU.Build.0 = Release|Any CPU + {CCB52C7C-47B6-1AE7-7578-7A26B3FFEB71}.Release|x64.ActiveCfg = Release|Any CPU + {CCB52C7C-47B6-1AE7-7578-7A26B3FFEB71}.Release|x64.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -381,6 +419,9 @@ Global {E585A74A-F358-4446-B10E-0FF07B4FF601} = {A4209011-1740-4902-B889-2F2FAF98383F} {AAC8306E-1DEB-460D-84C7-40166D189B88} = {A4209011-1740-4902-B889-2F2FAF98383F} {6167F037-166C-4C5A-81BE-55618E77D4E8} = {A4209011-1740-4902-B889-2F2FAF98383F} + {534A145F-1FE4-B601-48FF-979744373E4B} = {FC592E2B-861F-4C9A-BD1A-95CB97D36285} + {AFC1A740-BBA1-44BC-8A52-A65D2E506E69} = {FC592E2B-861F-4C9A-BD1A-95CB97D36285} + {CCB52C7C-47B6-1AE7-7578-7A26B3FFEB71} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {1ECA38C8-7C69-4DE6-8293-852C603F4217} diff --git a/LearningHub.Nhs.WebUI/Controllers/Api/CatalogueController.cs b/LearningHub.Nhs.WebUI/Controllers/Api/CatalogueController.cs index 0bec9e8d3..aca03ca60 100644 --- a/LearningHub.Nhs.WebUI/Controllers/Api/CatalogueController.cs +++ b/LearningHub.Nhs.WebUI/Controllers/Api/CatalogueController.cs @@ -129,7 +129,7 @@ public async Task GetLatestCatalogueAccessRequestAsync(int catalo [HttpPost("catalogue/RequestAccess/{reference}")] public async Task RequestAccess(string reference, CatalogueAccessRequestViewModel vm) { - return this.Ok(await this.catalogueService.RequestAccessAsync(reference, vm, "access")); + return this.Ok(await this.catalogueService.RequestAccessAsync(reference, null, vm, "access")); } /// diff --git a/LearningHub.Nhs.WebUI/Controllers/CatalogueController.cs b/LearningHub.Nhs.WebUI/Controllers/CatalogueController.cs index c8156e23e..cd7355b8e 100644 --- a/LearningHub.Nhs.WebUI/Controllers/CatalogueController.cs +++ b/LearningHub.Nhs.WebUI/Controllers/CatalogueController.cs @@ -541,7 +541,8 @@ public async Task RequestAccess(CatalogueRequestAccessViewModel v { if (this.ModelState.IsValid) { - var validationResult = await this.catalogueService.RequestAccessAsync(viewModel.CatalogueUrl, new CatalogueAccessRequestViewModel() { Message = viewModel.AccessRequestMessage, RoleId = (int)RoleEnum.Reader }, "access"); + var userFullName = viewModel.CurrentUser.FirstName + " " + viewModel.CurrentUser.LastName; + var validationResult = await this.catalogueService.RequestAccessAsync(viewModel.CatalogueUrl, viewModel.CatalogueName, new CatalogueAccessRequestViewModel() { Message = viewModel.AccessRequestMessage, RoleId = (int)RoleEnum.Reader, EmailAddress = viewModel.CurrentUser.EmailAddress, UserFullName = userFullName }, "access"); if (validationResult.IsValid) { @@ -623,7 +624,8 @@ public async Task RequestPermission(CatalogueRequestAccessViewMod { if (this.ModelState.IsValid) { - var validationResult = await this.catalogueService.RequestAccessAsync(viewModel.CatalogueUrl, new CatalogueAccessRequestViewModel() { Message = viewModel.AccessRequestMessage, RoleId = (int)RoleEnum.Previewer }, "permission"); + var userFullName = viewModel.CurrentUser.FirstName + " " + viewModel.CurrentUser.LastName; + var validationResult = await this.catalogueService.RequestAccessAsync(viewModel.CatalogueUrl, viewModel.CatalogueName, new CatalogueAccessRequestViewModel() { Message = viewModel.AccessRequestMessage, RoleId = (int)RoleEnum.Previewer, EmailAddress = viewModel.CurrentUser.EmailAddress, UserFullName = userFullName }, "permission"); if (validationResult.IsValid) { @@ -657,7 +659,9 @@ public async Task RequestPreviewAccess(CatalogueRequestAccessView { if (this.ModelState.IsValid) { - var validationResult = await this.catalogueService.RequestAccessAsync(viewModel.CatalogueUrl, new CatalogueAccessRequestViewModel() { Message = viewModel.AccessRequestMessage, RoleId = (int)RoleEnum.Previewer }, "access"); + var userFullName = viewModel.CurrentUser.FirstName + " " + viewModel.CurrentUser.LastName; + + var validationResult = await this.catalogueService.RequestAccessAsync(viewModel.CatalogueUrl, viewModel.CatalogueName, new CatalogueAccessRequestViewModel() { Message = viewModel.AccessRequestMessage, RoleId = (int)RoleEnum.Previewer, EmailAddress = viewModel.CurrentUser.EmailAddress, UserFullName = userFullName }, "access"); if (validationResult.IsValid) { diff --git a/LearningHub.Nhs.WebUI/Interfaces/ICatalogueService.cs b/LearningHub.Nhs.WebUI/Interfaces/ICatalogueService.cs index 42f4ecb39..a502733bc 100644 --- a/LearningHub.Nhs.WebUI/Interfaces/ICatalogueService.cs +++ b/LearningHub.Nhs.WebUI/Interfaces/ICatalogueService.cs @@ -70,10 +70,11 @@ public interface ICatalogueService /// The RequestAccessAsync. /// /// The catalogue reference. + /// The catalogue name. /// The view model. /// The accessType. /// The task. - Task RequestAccessAsync(string reference, CatalogueAccessRequestViewModel vm, string accessType); + Task RequestAccessAsync(string reference, string catalogueName, CatalogueAccessRequestViewModel vm, string accessType); /// /// The InviteUserAsync. diff --git a/LearningHub.Nhs.WebUI/LearningHub.Nhs.WebUI.csproj b/LearningHub.Nhs.WebUI/LearningHub.Nhs.WebUI.csproj index 9e1f484cb..cd2698968 100644 --- a/LearningHub.Nhs.WebUI/LearningHub.Nhs.WebUI.csproj +++ b/LearningHub.Nhs.WebUI/LearningHub.Nhs.WebUI.csproj @@ -112,7 +112,7 @@ - + diff --git a/LearningHub.Nhs.WebUI/Services/CatalogueService.cs b/LearningHub.Nhs.WebUI/Services/CatalogueService.cs index 3833a4e28..dd2766f2e 100644 --- a/LearningHub.Nhs.WebUI/Services/CatalogueService.cs +++ b/LearningHub.Nhs.WebUI/Services/CatalogueService.cs @@ -269,12 +269,13 @@ public async Task GetLatestCatalogueAccessReque /// The RequestAccessAsync. /// /// The catalogue reference. + /// The catalogue catalogueName. /// The view model. /// The accessType. /// The task. - public async Task RequestAccessAsync(string reference, CatalogueAccessRequestViewModel vm, string accessType) + public async Task RequestAccessAsync(string reference, string catalogueName, CatalogueAccessRequestViewModel vm, string accessType) { - var request = $"Catalogue/RequestAccess/{reference}/{accessType}"; + var request = $"Catalogue/RequestAccess/{reference}/{catalogueName}/{accessType}"; var client = await this.OpenApiHttpClient.GetClientAsync(); var content = new StringContent(JsonConvert.SerializeObject(vm), Encoding.UTF8, "application/json"); diff --git a/LearningHub.Nhs.WebUI/package-lock.json b/LearningHub.Nhs.WebUI/package-lock.json index 1b09c4094..038d6c04e 100644 --- a/LearningHub.Nhs.WebUI/package-lock.json +++ b/LearningHub.Nhs.WebUI/package-lock.json @@ -11,14 +11,14 @@ "dependencies": { "@ckeditor/ckeditor5-build-classic": "16.0.0", "@ckeditor/ckeditor5-vue": "1.0.3", - "@mediakind/mkplayer": "1.22.0", + "@mediakind/mkplayer": "1.21.0", "@types/uuid": "^8.3.4", "axios": "^0.30.0", "babel-polyfill": "^6.26.0", "bootstrap": "^4.6.2", "ckeditor4-vue": "^0.2.0", "concurrently": "^7.6.0", - "core-js": "^3.42.0", + "core-js": "^3.41.0", "js-cookie": "2.2.1", "lodash": "4.17.21", "moment": "^2.30.1", @@ -26,7 +26,7 @@ "nhsuk-frontend": "^7.1.0", "node": "^14.0.0", "openseadragon": "^2.4.2", - "sanitize-html": "^2.17.0", + "sanitize-html": "^2.15.0", "save": "^2.9.0", "ts-debounce": "2.3.0", "tus-js-client": "^2.3.2", @@ -45,8 +45,8 @@ "vuex": "^3.6.2" }, "devDependencies": { - "@babel/core": "^7.27.1", - "@babel/preset-env": "^7.27.2", + "@babel/core": "^7.26.10", + "@babel/preset-env": "^7.26.9", "@types/axios": "^0.14.0", "@types/bootstrap": "4.6.1", "@types/ckeditor": "4.9.10", @@ -54,9 +54,9 @@ "@types/jquery": "^3.3.32", "@types/jquery-match-height": "^0.7.8", "@types/js-cookie": "2.2.1", - "@types/lodash": "4.17.17", + "@types/lodash": "4.17.16", "@types/openseadragon": "^2.4.5", - "@types/sanitize-html": "^2.16.0", + "@types/sanitize-html": "^2.13.0", "@types/vuelidate": "^0.7.22", "@vue/babel-preset-app": "4.5.19", "@vue/test-utils": "^1.3.6", @@ -69,7 +69,7 @@ "eslint": "^8.51.0", "file-loader": "^6.2.0", "jest": "^27.5.1", - "sass": "^1.89.0", + "sass": "^1.86.3", "sass-loader": "^11.1.1", "style-loader": "^2.0.0", "ts-jest": "^27.1.5", @@ -79,7 +79,7 @@ "vue-jest": "^3.0.7", "vue-loader": "^15.11.1", "vue-template-compiler": "2.7.16", - "webpack": "^5.99.9", + "webpack": "^5.99.5", "webpack-cli": "^4.10.0", "webpack-dev-server": "^3.11.3" } @@ -108,15 +108,15 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", - "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", + "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-validator-identifier": "^7.27.1", + "@babel/helper-validator-identifier": "^7.25.9", "js-tokens": "^4.0.0", - "picocolors": "^1.1.1" + "picocolors": "^1.0.0" }, "engines": { "node": ">=6.9.0" @@ -130,9 +130,9 @@ "license": "MIT" }, "node_modules/@babel/compat-data": { - "version": "7.27.2", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.27.2.tgz", - "integrity": "sha512-TUtMJYRPyUb/9aU8f3K0mjmjf6M9N5Woshn2CS6nqJSeJtTtQcpLUXjGt9vbF8ZGff0El99sWkLgzwW3VXnxZQ==", + "version": "7.26.8", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.8.tgz", + "integrity": "sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ==", "dev": true, "license": "MIT", "engines": { @@ -140,22 +140,22 @@ } }, "node_modules/@babel/core": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.27.1.tgz", - "integrity": "sha512-IaaGWsQqfsQWVLqMn9OB92MNN7zukfVA4s7KKAI0KfrrDsZ0yhi5uV4baBuLuN7n3vsZpwP8asPPcVwApxvjBQ==", + "version": "7.26.10", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.10.tgz", + "integrity": "sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ==", "dev": true, "license": "MIT", "dependencies": { "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.27.1", - "@babel/helper-compilation-targets": "^7.27.1", - "@babel/helper-module-transforms": "^7.27.1", - "@babel/helpers": "^7.27.1", - "@babel/parser": "^7.27.1", - "@babel/template": "^7.27.1", - "@babel/traverse": "^7.27.1", - "@babel/types": "^7.27.1", + "@babel/code-frame": "^7.26.2", + "@babel/generator": "^7.26.10", + "@babel/helper-compilation-targets": "^7.26.5", + "@babel/helper-module-transforms": "^7.26.0", + "@babel/helpers": "^7.26.10", + "@babel/parser": "^7.26.10", + "@babel/template": "^7.26.9", + "@babel/traverse": "^7.26.10", + "@babel/types": "^7.26.10", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -224,14 +224,14 @@ } }, "node_modules/@babel/generator": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.27.1.tgz", - "integrity": "sha512-UnJfnIpc/+JO0/+KRVQNGU+y5taA5vCbwN8+azkX6beii/ZF+enZJSOKo11ZSzGJjlNfJHfQtmQT8H+9TXPG2w==", + "version": "7.26.10", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.10.tgz", + "integrity": "sha512-rRHT8siFIXQrAYOYqZQVsAr8vJ+cBNqcVAY6m5V8/4QqzaPl+zDBe6cLEPRDuNOUf3ww8RfJVlOyQMoSI+5Ang==", "dev": true, "license": "MIT", "dependencies": { - "@babel/parser": "^7.27.1", - "@babel/types": "^7.27.1", + "@babel/parser": "^7.26.10", + "@babel/types": "^7.26.10", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^3.0.2" @@ -254,27 +254,27 @@ } }, "node_modules/@babel/helper-annotate-as-pure": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.27.1.tgz", - "integrity": "sha512-WnuuDILl9oOBbKnb4L+DyODx7iC47XfzmNCpTttFsSp6hTG7XZxu60+4IO+2/hPfcGOoKbFiwoI/+zwARbNQow==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.9.tgz", + "integrity": "sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.27.1" + "@babel/types": "^7.25.9" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.27.2", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz", - "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==", + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.26.5.tgz", + "integrity": "sha512-IXuyn5EkouFJscIDuFF5EsiSolseme1s0CZB+QxVugqJLYmKdxI1VfIBOst0SUu4rnk2Z7kqTwmoO1lp3HIfnA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.27.2", - "@babel/helper-validator-option": "^7.27.1", + "@babel/compat-data": "^7.26.5", + "@babel/helper-validator-option": "^7.25.9", "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" @@ -311,18 +311,18 @@ "license": "ISC" }, "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.27.1.tgz", - "integrity": "sha512-QwGAmuvM17btKU5VqXfb+Giw4JcN0hjuufz3DYnpeVDvZLAObloM77bhMXiqry3Iio+Ai4phVRDwl6WU10+r5A==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.25.9.tgz", + "integrity": "sha512-UTZQMvt0d/rSz6KI+qdu7GQze5TIajwTS++GUozlw8VBJDEOAqSXwm1WvmYEZwqdqSGQshRocPDqrt4HBZB3fQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.27.1", - "@babel/helper-member-expression-to-functions": "^7.27.1", - "@babel/helper-optimise-call-expression": "^7.27.1", - "@babel/helper-replace-supers": "^7.27.1", - "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", - "@babel/traverse": "^7.27.1", + "@babel/helper-annotate-as-pure": "^7.25.9", + "@babel/helper-member-expression-to-functions": "^7.25.9", + "@babel/helper-optimise-call-expression": "^7.25.9", + "@babel/helper-replace-supers": "^7.25.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9", + "@babel/traverse": "^7.25.9", "semver": "^6.3.1" }, "engines": { @@ -343,13 +343,13 @@ } }, "node_modules/@babel/helper-create-regexp-features-plugin": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.27.1.tgz", - "integrity": "sha512-uVDC72XVf8UbrH5qQTc18Agb8emwjTiZrQE11Nv3CuBEZmVvTwwE9CBUEvHku06gQCAyYf8Nv6ja1IN+6LMbxQ==", + "version": "7.26.3", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.26.3.tgz", + "integrity": "sha512-G7ZRb40uUgdKOQqPLjfD12ZmGA54PzqDFUv2BKImnC9QIfGhIHKvVML0oN8IUiDq4iRqpq74ABpvOaerfWdong==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.27.1", + "@babel/helper-annotate-as-pure": "^7.25.9", "regexpu-core": "^6.2.0", "semver": "^6.3.1" }, @@ -464,43 +464,43 @@ "license": "MIT" }, "node_modules/@babel/helper-member-expression-to-functions": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.27.1.tgz", - "integrity": "sha512-E5chM8eWjTp/aNoVpcbfM7mLxu9XGLWYise2eBKGQomAk/Mb4XoxyqXTZbuTohbsl8EKqdlMhnDI2CCLfcs9wA==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.25.9.tgz", + "integrity": "sha512-wbfdZ9w5vk0C0oyHqAJbc62+vet5prjj01jjJ8sKn3j9h3MQQlflEdXYvuqRWjHnM12coDEqiC1IRCi0U/EKwQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/traverse": "^7.27.1", - "@babel/types": "^7.27.1" + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-imports": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", - "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz", + "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/traverse": "^7.27.1", - "@babel/types": "^7.27.1" + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.27.1.tgz", - "integrity": "sha512-9yHn519/8KvTU5BjTVEEeIM3w9/2yXNKoD82JifINImhpKkARMJKPP59kLo+BafpdN5zgNeIcS4jsGDmd3l58g==", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz", + "integrity": "sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-module-imports": "^7.27.1", - "@babel/helper-validator-identifier": "^7.27.1", - "@babel/traverse": "^7.27.1" + "@babel/helper-module-imports": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9", + "@babel/traverse": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -510,22 +510,22 @@ } }, "node_modules/@babel/helper-optimise-call-expression": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.27.1.tgz", - "integrity": "sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.25.9.tgz", + "integrity": "sha512-FIpuNaz5ow8VyrYcnXQTDRGvV6tTjkNtCK/RYNDXGSLlUD6cBuQTSw43CShGxjvfBTfcUA/r6UhUCbtYqkhcuQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.27.1" + "@babel/types": "^7.25.9" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz", - "integrity": "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==", + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.26.5.tgz", + "integrity": "sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg==", "dev": true, "license": "MIT", "engines": { @@ -533,15 +533,15 @@ } }, "node_modules/@babel/helper-remap-async-to-generator": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.27.1.tgz", - "integrity": "sha512-7fiA521aVw8lSPeI4ZOD3vRFkoqkJcS+z4hFo82bFSH/2tNd6eJ5qCVMS5OzDmZh/kaHQeBaeyxK6wljcPtveA==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.25.9.tgz", + "integrity": "sha512-IZtukuUeBbhgOcaW2s06OXTzVNJR0ybm4W5xC1opWFFJMZbwRj5LCk+ByYH7WdZPZTt8KnFwA8pvjN2yqcPlgw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.27.1", - "@babel/helper-wrap-function": "^7.27.1", - "@babel/traverse": "^7.27.1" + "@babel/helper-annotate-as-pure": "^7.25.9", + "@babel/helper-wrap-function": "^7.25.9", + "@babel/traverse": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -551,15 +551,15 @@ } }, "node_modules/@babel/helper-replace-supers": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.27.1.tgz", - "integrity": "sha512-7EHz6qDZc8RYS5ElPoShMheWvEgERonFCs7IAonWLLUTXW59DP14bCZt89/GKyreYn8g3S83m21FelHKbeDCKA==", + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.26.5.tgz", + "integrity": "sha512-bJ6iIVdYX1YooY2X7w1q6VITt+LnUILtNk7zT78ykuwStx8BauCzxvFqFaHjOpW1bVnSUM1PN1f0p5P21wHxvg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-member-expression-to-functions": "^7.27.1", - "@babel/helper-optimise-call-expression": "^7.27.1", - "@babel/traverse": "^7.27.1" + "@babel/helper-member-expression-to-functions": "^7.25.9", + "@babel/helper-optimise-call-expression": "^7.25.9", + "@babel/traverse": "^7.26.5" }, "engines": { "node": ">=6.9.0" @@ -569,41 +569,40 @@ } }, "node_modules/@babel/helper-skip-transparent-expression-wrappers": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.27.1.tgz", - "integrity": "sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.25.9.tgz", + "integrity": "sha512-K4Du3BFa3gvyhzgPcntrkDgZzQaq6uozzcpGbOO1OEJaI+EJdqWIMTLgFgQf6lrfiDFo5FU+BxKepI9RmZqahA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/traverse": "^7.27.1", - "@babel/types": "^7.27.1" + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-string-parser": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", - "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", - "license": "MIT", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", + "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", - "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", + "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-option": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", - "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz", + "integrity": "sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==", "dev": true, "license": "MIT", "engines": { @@ -611,41 +610,41 @@ } }, "node_modules/@babel/helper-wrap-function": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.27.1.tgz", - "integrity": "sha512-NFJK2sHUvrjo8wAU/nQTWU890/zB2jj0qBcCbZbbf+005cAsv6tMjXz31fBign6M5ov1o0Bllu+9nbqkfsjjJQ==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.25.9.tgz", + "integrity": "sha512-ETzz9UTjQSTmw39GboatdymDq4XIQbR8ySgVrylRhPOFpsd+JrKHIuF0de7GCWmem+T4uC5z7EZguod7Wj4A4g==", "dev": true, "license": "MIT", "dependencies": { - "@babel/template": "^7.27.1", - "@babel/traverse": "^7.27.1", - "@babel/types": "^7.27.1" + "@babel/template": "^7.25.9", + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helpers": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.1.tgz", - "integrity": "sha512-FCvFTm0sWV8Fxhpp2McP5/W53GPllQ9QeQ7SiqGWjMf/LVG07lFa5+pgK05IRhVwtvafT22KF+ZSnM9I545CvQ==", + "version": "7.26.10", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.26.10.tgz", + "integrity": "sha512-UPYc3SauzZ3JGgj87GgZ89JVdC5dj0AoetR5Bw6wj4niittNyFh6+eOGonYvJ1ao6B8lEa3Q3klS7ADZ53bc5g==", "dev": true, "license": "MIT", "dependencies": { - "@babel/template": "^7.27.1", - "@babel/types": "^7.27.1" + "@babel/template": "^7.26.9", + "@babel/types": "^7.26.10" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/parser": { - "version": "7.27.2", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.2.tgz", - "integrity": "sha512-QYLs8299NA7WM/bZAdp+CviYYkVoYXlDW2rzliy3chxd1PQjej7JORuMJDJXJUb9g0TT+B99EwaVLKmX+sPXWw==", + "version": "7.26.10", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.10.tgz", + "integrity": "sha512-6aQR2zGE/QFi8JpDLjUZEPYOs7+mhKXm86VaKFiLP35JQwQb6bwUE+XbvkH0EptsYhbNBSUGaUBLKqxH1xSgsA==", "license": "MIT", "dependencies": { - "@babel/types": "^7.27.1" + "@babel/types": "^7.26.10" }, "bin": { "parser": "bin/babel-parser.js" @@ -655,14 +654,14 @@ } }, "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.27.1.tgz", - "integrity": "sha512-QPG3C9cCVRQLxAVwmefEmwdTanECuUBMQZ/ym5kiw3XKCGA7qkuQLcjWWHcrD/GKbn/WmJwaezfuuAOcyKlRPA==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.25.9.tgz", + "integrity": "sha512-ZkRyVkThtxQ/J6nv3JFYv1RYY+JT5BvU0y3k5bWrmuG4woXypRa4PXmm9RhOwodRkYFWqC0C0cqcJ4OqR7kW+g==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/traverse": "^7.27.1" + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/traverse": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -672,13 +671,13 @@ } }, "node_modules/@babel/plugin-bugfix-safari-class-field-initializer-scope": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.27.1.tgz", - "integrity": "sha512-qNeq3bCKnGgLkEXUuFry6dPlGfCdQNZbn7yUAPCInwAJHMU7THJfrBSozkcWq5sNM6RcF3S8XyQL2A52KNR9IA==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.25.9.tgz", + "integrity": "sha512-MrGRLZxLD/Zjj0gdU15dfs+HH/OXvnw/U4jJD8vpcP2CJQapPEv1IWwjc/qMg7ItBlPwSv1hRBbb7LeuANdcnw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -688,13 +687,13 @@ } }, "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.27.1.tgz", - "integrity": "sha512-g4L7OYun04N1WyqMNjldFwlfPCLVkgB54A/YCXICZYBsvJJE3kByKv9c9+R/nAfmIfjl2rKYLNyMHboYbZaWaA==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.25.9.tgz", + "integrity": "sha512-2qUwwfAFpJLZqxd02YW9btUCZHl+RFvdDkNfZwaIJrvB8Tesjsk8pEQkTvGwZXLqXUx/2oyY3ySRhm6HOXuCug==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -704,15 +703,15 @@ } }, "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.27.1.tgz", - "integrity": "sha512-oO02gcONcD5O1iTLi/6frMJBIwWEHceWGSGqrpCmEL8nogiS6J9PBlE48CaK20/Jx1LuRml9aDftLgdjXT8+Cw==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.25.9.tgz", + "integrity": "sha512-6xWgLZTJXwilVjlnV7ospI3xi+sl8lN8rXXbBD6vYn3UYDlGsag8wrZkKcSI8G6KgqKP7vNFaDgeDnfAABq61g==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", - "@babel/plugin-transform-optional-chaining": "^7.27.1" + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9", + "@babel/plugin-transform-optional-chaining": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -722,14 +721,14 @@ } }, "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.27.1.tgz", - "integrity": "sha512-6BpaYGDavZqkI6yT+KSPdpZFfpnd68UKXbcjI9pJ13pvHhPrCKWOOLp+ysvMeA+DxnhuPpgIaRpxRxo5A9t5jw==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.25.9.tgz", + "integrity": "sha512-aLnMXYPnzwwqhYSCyXfKkIkYgJ8zv9RK+roo9DkTXz38ynIhd9XCbN08s3MGvqL2MYGVUGdRQLL/JqBIeJhJBg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/traverse": "^7.27.1" + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/traverse": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -846,13 +845,13 @@ } }, "node_modules/@babel/plugin-syntax-import-assertions": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.27.1.tgz", - "integrity": "sha512-UT/Jrhw57xg4ILHLFnzFpPDlMbcdEicaAtjPQpbj9wa8T4r5KVWCimHcL/460g8Ht0DMxDyjsLgiWSkVjnwPFg==", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.26.0.tgz", + "integrity": "sha512-QCWT5Hh830hK5EQa7XzuqIkQU9tT/whqbDz7kuaZMHFl1inRRg7JnuAEOQ0Ur0QUl0NufCk1msK2BeY79Aj/eg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -862,13 +861,12 @@ } }, "node_modules/@babel/plugin-syntax-import-attributes": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.27.1.tgz", - "integrity": "sha512-oFT0FrKHgF53f4vOsZGi2Hh3I35PfSmVs4IBFLFj4dnafP+hIWDLg3VyKmUHfLoLHlyxY4C7DGtmHuJgn+IGww==", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.26.0.tgz", + "integrity": "sha512-e2dttdsJ1ZTpi3B9UYGLw41hifAubg19AtCu/2I/F1QNVclOBr1dYpTdmdyZ84Xiz43BS/tCUkMAZNLv12Pi+A==", "dev": true, - "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1021,13 +1019,13 @@ } }, "node_modules/@babel/plugin-transform-arrow-functions": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.27.1.tgz", - "integrity": "sha512-8Z4TGic6xW70FKThA5HYEKKyBpOOsucTOD1DjU3fZxDg+K3zBJcXMFnt/4yQiZnf5+MiOMSXQ9PaEK/Ilh1DeA==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.25.9.tgz", + "integrity": "sha512-6jmooXYIwn9ca5/RylZADJ+EnSxVUS5sjeJ9UPk6RWRzXCmOJCy6dqItPJFpw2cuCangPK4OYr5uhGKcmrm5Qg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1037,15 +1035,15 @@ } }, "node_modules/@babel/plugin-transform-async-generator-functions": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.27.1.tgz", - "integrity": "sha512-eST9RrwlpaoJBDHShc+DS2SG4ATTi2MYNb4OxYkf3n+7eb49LWpnS+HSpVfW4x927qQwgk8A2hGNVaajAEw0EA==", + "version": "7.26.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.26.8.tgz", + "integrity": "sha512-He9Ej2X7tNf2zdKMAGOsmg2MrFc+hfoAhd3po4cWfo/NWjzEAKa0oQruj1ROVUdl0e6fb6/kE/G3SSxE0lRJOg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/helper-remap-async-to-generator": "^7.27.1", - "@babel/traverse": "^7.27.1" + "@babel/helper-plugin-utils": "^7.26.5", + "@babel/helper-remap-async-to-generator": "^7.25.9", + "@babel/traverse": "^7.26.8" }, "engines": { "node": ">=6.9.0" @@ -1055,15 +1053,15 @@ } }, "node_modules/@babel/plugin-transform-async-to-generator": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.27.1.tgz", - "integrity": "sha512-NREkZsZVJS4xmTr8qzE5y8AfIPqsdQfRuUiLRTEzb7Qii8iFWCyDKaUV2c0rCuh4ljDZ98ALHP/PetiBV2nddA==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.25.9.tgz", + "integrity": "sha512-NT7Ejn7Z/LjUH0Gv5KsBCxh7BH3fbLTV0ptHvpeMvrt3cPThHfJfst9Wrb7S8EvJ7vRTFI7z+VAvFVEQn/m5zQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-module-imports": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/helper-remap-async-to-generator": "^7.27.1" + "@babel/helper-module-imports": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-remap-async-to-generator": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1073,13 +1071,13 @@ } }, "node_modules/@babel/plugin-transform-block-scoped-functions": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.27.1.tgz", - "integrity": "sha512-cnqkuOtZLapWYZUYM5rVIdv1nXYuFVIltZ6ZJ7nIj585QsjKM5dhL2Fu/lICXZ1OyIAFc7Qy+bvDAtTXqGrlhg==", + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.26.5.tgz", + "integrity": "sha512-chuTSY+hq09+/f5lMj8ZSYgCFpppV2CbYrhNFJ1BFoXpiWPnnAb7R0MqrafCpN8E1+YRrtM1MXZHJdIx8B6rMQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.26.5" }, "engines": { "node": ">=6.9.0" @@ -1089,13 +1087,13 @@ } }, "node_modules/@babel/plugin-transform-block-scoping": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.27.1.tgz", - "integrity": "sha512-QEcFlMl9nGTgh1rn2nIeU5bkfb9BAjaQcWbiP4LvKxUot52ABcTkpcyJ7f2Q2U2RuQ84BNLgts3jRme2dTx6Fw==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.25.9.tgz", + "integrity": "sha512-1F05O7AYjymAtqbsFETboN1NvBdcnzMerO+zlMyJBEz6WkMdejvGWw9p05iTSjC85RLlBseHHQpYaM4gzJkBGg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1105,14 +1103,14 @@ } }, "node_modules/@babel/plugin-transform-class-properties": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.27.1.tgz", - "integrity": "sha512-D0VcalChDMtuRvJIu3U/fwWjf8ZMykz5iZsg77Nuj821vCKI3zCyRLwRdWbsuJ/uRwZhZ002QtCqIkwC/ZkvbA==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.25.9.tgz", + "integrity": "sha512-bbMAII8GRSkcd0h0b4X+36GksxuheLFjP65ul9w6C3KgAamI3JqErNgSrosX6ZPj+Mpim5VvEbawXxJCyEUV3Q==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-create-class-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1122,14 +1120,14 @@ } }, "node_modules/@babel/plugin-transform-class-static-block": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.27.1.tgz", - "integrity": "sha512-s734HmYU78MVzZ++joYM+NkJusItbdRcbm+AGRgJCt3iA+yux0QpD9cBVdz3tKyrjVYWRl7j0mHSmv4lhV0aoA==", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.26.0.tgz", + "integrity": "sha512-6J2APTs7BDDm+UMqP1useWqhcRAXo0WIoVj26N7kPFB6S73Lgvyka4KTZYIxtgYXiN5HTyRObA72N2iu628iTQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-create-class-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1139,17 +1137,17 @@ } }, "node_modules/@babel/plugin-transform-classes": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.27.1.tgz", - "integrity": "sha512-7iLhfFAubmpeJe/Wo2TVuDrykh/zlWXLzPNdL0Jqn/Xu8R3QQ8h9ff8FQoISZOsw74/HFqFI7NX63HN7QFIHKA==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.25.9.tgz", + "integrity": "sha512-mD8APIXmseE7oZvZgGABDyM34GUmK45Um2TXiBUt7PnuAxrgoSVf123qUzPxEr/+/BHrRn5NMZCdE2m/1F8DGg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.27.1", - "@babel/helper-compilation-targets": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/helper-replace-supers": "^7.27.1", - "@babel/traverse": "^7.27.1", + "@babel/helper-annotate-as-pure": "^7.25.9", + "@babel/helper-compilation-targets": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-replace-supers": "^7.25.9", + "@babel/traverse": "^7.25.9", "globals": "^11.1.0" }, "engines": { @@ -1170,14 +1168,14 @@ } }, "node_modules/@babel/plugin-transform-computed-properties": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.27.1.tgz", - "integrity": "sha512-lj9PGWvMTVksbWiDT2tW68zGS/cyo4AkZ/QTp0sQT0mjPopCmrSkzxeXkznjqBxzDI6TclZhOJbBmbBLjuOZUw==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.25.9.tgz", + "integrity": "sha512-HnBegGqXZR12xbcTHlJ9HGxw1OniltT26J5YpfruGqtUHlz/xKf/G2ak9e+t0rVqrjXa9WOhvYPz1ERfMj23AA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/template": "^7.27.1" + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/template": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1187,13 +1185,13 @@ } }, "node_modules/@babel/plugin-transform-destructuring": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.27.1.tgz", - "integrity": "sha512-ttDCqhfvpE9emVkXbPD8vyxxh4TWYACVybGkDj+oReOGwnp066ITEivDlLwe0b1R0+evJ13IXQuLNB5w1fhC5Q==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.25.9.tgz", + "integrity": "sha512-WkCGb/3ZxXepmMiX101nnGiU+1CAdut8oHyEOHxkKuS1qKpU2SMXE2uSvfz8PBuLd49V6LEsbtyPhWC7fnkgvQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1203,14 +1201,14 @@ } }, "node_modules/@babel/plugin-transform-dotall-regex": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.27.1.tgz", - "integrity": "sha512-gEbkDVGRvjj7+T1ivxrfgygpT7GUd4vmODtYpbs0gZATdkX8/iSnOtZSxiZnsgm1YjTgjI6VKBGSJJevkrclzw==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.25.9.tgz", + "integrity": "sha512-t7ZQ7g5trIgSRYhI9pIJtRl64KHotutUJsh4Eze5l7olJv+mRSg4/MmbZ0tv1eeqRbdvo/+trvJD/Oc5DmW2cA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-create-regexp-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1220,13 +1218,13 @@ } }, "node_modules/@babel/plugin-transform-duplicate-keys": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.27.1.tgz", - "integrity": "sha512-MTyJk98sHvSs+cvZ4nOauwTTG1JeonDjSGvGGUNHreGQns+Mpt6WX/dVzWBHgg+dYZhkC4X+zTDfkTU+Vy9y7Q==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.25.9.tgz", + "integrity": "sha512-LZxhJ6dvBb/f3x8xwWIuyiAHy56nrRG3PeYTpBkkzkYRRQ6tJLu68lEF5VIqMUZiAV7a8+Tb78nEoMCMcqjXBw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1236,14 +1234,14 @@ } }, "node_modules/@babel/plugin-transform-duplicate-named-capturing-groups-regex": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.27.1.tgz", - "integrity": "sha512-hkGcueTEzuhB30B3eJCbCYeCaaEQOmQR0AdvzpD4LoN0GXMWzzGSuRrxR2xTnCrvNbVwK9N6/jQ92GSLfiZWoQ==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.25.9.tgz", + "integrity": "sha512-0UfuJS0EsXbRvKnwcLjFtJy/Sxc5J5jhLHnFhy7u4zih97Hz6tJkLU+O+FMMrNZrosUPxDi6sYxJ/EA8jDiAog==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-create-regexp-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1253,13 +1251,13 @@ } }, "node_modules/@babel/plugin-transform-dynamic-import": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.27.1.tgz", - "integrity": "sha512-MHzkWQcEmjzzVW9j2q8LGjwGWpG2mjwaaB0BNQwst3FIjqsg8Ct/mIZlvSPJvfi9y2AC8mi/ktxbFVL9pZ1I4A==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.25.9.tgz", + "integrity": "sha512-GCggjexbmSLaFhqsojeugBpeaRIgWNTcgKVq/0qIteFEqY2A+b9QidYadrWlnbWQUrW5fn+mCvf3tr7OeBFTyg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1269,13 +1267,13 @@ } }, "node_modules/@babel/plugin-transform-exponentiation-operator": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.27.1.tgz", - "integrity": "sha512-uspvXnhHvGKf2r4VVtBpeFnuDWsJLQ6MF6lGJLC89jBR1uoVeqM416AZtTuhTezOfgHicpJQmoD5YUakO/YmXQ==", + "version": "7.26.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.26.3.tgz", + "integrity": "sha512-7CAHcQ58z2chuXPWblnn1K6rLDnDWieghSOEmqQsrBenH0P9InCUtOJYD89pvngljmZlJcz3fcmgYsXFNGa1ZQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1285,13 +1283,13 @@ } }, "node_modules/@babel/plugin-transform-export-namespace-from": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.27.1.tgz", - "integrity": "sha512-tQvHWSZ3/jH2xuq/vZDy0jNn+ZdXJeM8gHvX4lnJmsc3+50yPlWdZXIc5ay+umX+2/tJIqHqiEqcJvxlmIvRvQ==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.25.9.tgz", + "integrity": "sha512-2NsEz+CxzJIVOPx2o9UsW1rXLqtChtLoVnwYHHiB04wS5sgn7mrV45fWMBX0Kk+ub9uXytVYfNP2HjbVbCB3Ww==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1301,14 +1299,14 @@ } }, "node_modules/@babel/plugin-transform-for-of": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.27.1.tgz", - "integrity": "sha512-BfbWFFEJFQzLCQ5N8VocnCtA8J1CLkNTe2Ms2wocj75dd6VpiqS5Z5quTYcUoo4Yq+DN0rtikODccuv7RU81sw==", + "version": "7.26.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.26.9.tgz", + "integrity": "sha512-Hry8AusVm8LW5BVFgiyUReuoGzPUpdHQQqJY5bZnbbf+ngOHWuCuYFKw/BqaaWlvEUrF91HMhDtEaI1hZzNbLg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" + "@babel/helper-plugin-utils": "^7.26.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1318,15 +1316,15 @@ } }, "node_modules/@babel/plugin-transform-function-name": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.27.1.tgz", - "integrity": "sha512-1bQeydJF9Nr1eBCMMbC+hdwmRlsv5XYOMu03YSWFwNs0HsAmtSxxF1fyuYPqemVldVyFmlCU7w8UE14LupUSZQ==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.25.9.tgz", + "integrity": "sha512-8lP+Yxjv14Vc5MuWBpJsoUCd3hD6V9DgBon2FVYL4jJgbnVQ9fTgYmonchzZJOVNgzEgbxp4OwAf6xz6M/14XA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-compilation-targets": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/traverse": "^7.27.1" + "@babel/helper-compilation-targets": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/traverse": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1336,13 +1334,13 @@ } }, "node_modules/@babel/plugin-transform-json-strings": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.27.1.tgz", - "integrity": "sha512-6WVLVJiTjqcQauBhn1LkICsR2H+zm62I3h9faTDKt1qP4jn2o72tSvqMwtGFKGTpojce0gJs+76eZ2uCHRZh0Q==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.25.9.tgz", + "integrity": "sha512-xoTMk0WXceiiIvsaquQQUaLLXSW1KJ159KP87VilruQm0LNNGxWzahxSS6T6i4Zg3ezp4vA4zuwiNUR53qmQAw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1352,13 +1350,13 @@ } }, "node_modules/@babel/plugin-transform-literals": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.27.1.tgz", - "integrity": "sha512-0HCFSepIpLTkLcsi86GG3mTUzxV5jpmbv97hTETW3yzrAij8aqlD36toB1D0daVFJM8NK6GvKO0gslVQmm+zZA==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.25.9.tgz", + "integrity": "sha512-9N7+2lFziW8W9pBl2TzaNht3+pgMIRP74zizeCSrtnSKVdUl8mAjjOP2OOVQAfZ881P2cNjDj1uAMEdeD50nuQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1368,13 +1366,13 @@ } }, "node_modules/@babel/plugin-transform-logical-assignment-operators": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.27.1.tgz", - "integrity": "sha512-SJvDs5dXxiae4FbSL1aBJlG4wvl594N6YEVVn9e3JGulwioy6z3oPjx/sQBO3Y4NwUu5HNix6KJ3wBZoewcdbw==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.25.9.tgz", + "integrity": "sha512-wI4wRAzGko551Y8eVf6iOY9EouIDTtPb0ByZx+ktDGHwv6bHFimrgJM/2T021txPZ2s4c7bqvHbd+vXG6K948Q==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1384,13 +1382,13 @@ } }, "node_modules/@babel/plugin-transform-member-expression-literals": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.27.1.tgz", - "integrity": "sha512-hqoBX4dcZ1I33jCSWcXrP+1Ku7kdqXf1oeah7ooKOIiAdKQ+uqftgCFNOSzA5AMS2XIHEYeGFg4cKRCdpxzVOQ==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.25.9.tgz", + "integrity": "sha512-PYazBVfofCQkkMzh2P6IdIUaCEWni3iYEerAsRWuVd8+jlM1S9S9cz1dF9hIzyoZ8IA3+OwVYIp9v9e+GbgZhA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1400,14 +1398,14 @@ } }, "node_modules/@babel/plugin-transform-modules-amd": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.27.1.tgz", - "integrity": "sha512-iCsytMg/N9/oFq6n+gFTvUYDZQOMK5kEdeYxmxt91fcJGycfxVP9CnrxoliM0oumFERba2i8ZtwRUCMhvP1LnA==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.25.9.tgz", + "integrity": "sha512-g5T11tnI36jVClQlMlt4qKDLlWnG5pP9CSM4GhdRciTNMRgkfpo5cR6b4rGIOYPgRRuFAvwjPQ/Yk+ql4dyhbw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-module-transforms": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-module-transforms": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1417,14 +1415,14 @@ } }, "node_modules/@babel/plugin-transform-modules-commonjs": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.27.1.tgz", - "integrity": "sha512-OJguuwlTYlN0gBZFRPqwOGNWssZjfIUdS7HMYtN8c1KmwpwHFBwTeFZrg9XZa+DFTitWOW5iTAG7tyCUPsCCyw==", + "version": "7.26.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.26.3.tgz", + "integrity": "sha512-MgR55l4q9KddUDITEzEFYn5ZsGDXMSsU9E+kh7fjRXTIC3RHqfCo8RPRbyReYJh44HQ/yomFkqbOFohXvDCiIQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-module-transforms": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-module-transforms": "^7.26.0", + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1434,16 +1432,16 @@ } }, "node_modules/@babel/plugin-transform-modules-systemjs": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.27.1.tgz", - "integrity": "sha512-w5N1XzsRbc0PQStASMksmUeqECuzKuTJer7kFagK8AXgpCMkeDMO5S+aaFb7A51ZYDF7XI34qsTX+fkHiIm5yA==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.25.9.tgz", + "integrity": "sha512-hyss7iIlH/zLHaehT+xwiymtPOpsiwIIRlCAOwBB04ta5Tt+lNItADdlXw3jAWZ96VJ2jlhl/c+PNIQPKNfvcA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-module-transforms": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/helper-validator-identifier": "^7.27.1", - "@babel/traverse": "^7.27.1" + "@babel/helper-module-transforms": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9", + "@babel/traverse": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1453,14 +1451,14 @@ } }, "node_modules/@babel/plugin-transform-modules-umd": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.27.1.tgz", - "integrity": "sha512-iQBE/xC5BV1OxJbp6WG7jq9IWiD+xxlZhLrdwpPkTX3ydmXdvoCpyfJN7acaIBZaOqTfr76pgzqBJflNbeRK+w==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.25.9.tgz", + "integrity": "sha512-bS9MVObUgE7ww36HEfwe6g9WakQ0KF07mQF74uuXdkoziUPfKyu/nIm663kz//e5O1nPInPFx36z7WJmJ4yNEw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-module-transforms": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-module-transforms": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1470,14 +1468,14 @@ } }, "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.27.1.tgz", - "integrity": "sha512-SstR5JYy8ddZvD6MhV0tM/j16Qds4mIpJTOd1Yu9J9pJjH93bxHECF7pgtc28XvkzTD6Pxcm/0Z73Hvk7kb3Ng==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.25.9.tgz", + "integrity": "sha512-oqB6WHdKTGl3q/ItQhpLSnWWOpjUJLsOCLVyeFgeTktkBSCiurvPOsyt93gibI9CmuKvTUEtWmG5VhZD+5T/KA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-create-regexp-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1487,13 +1485,13 @@ } }, "node_modules/@babel/plugin-transform-new-target": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.27.1.tgz", - "integrity": "sha512-f6PiYeqXQ05lYq3TIfIDu/MtliKUbNwkGApPUvyo6+tc7uaR4cPjPe7DFPr15Uyycg2lZU6btZ575CuQoYh7MQ==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.25.9.tgz", + "integrity": "sha512-U/3p8X1yCSoKyUj2eOBIx3FOn6pElFOKvAAGf8HTtItuPyB+ZeOqfn+mvTtg9ZlOAjsPdK3ayQEjqHjU/yLeVQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1503,13 +1501,13 @@ } }, "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.27.1.tgz", - "integrity": "sha512-aGZh6xMo6q9vq1JGcw58lZ1Z0+i0xB2x0XaauNIUXd6O1xXc3RwoWEBlsTQrY4KQ9Jf0s5rgD6SiNkaUdJegTA==", + "version": "7.26.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.26.6.tgz", + "integrity": "sha512-CKW8Vu+uUZneQCPtXmSBUC6NCAUdya26hWCElAWh5mVSlSRsmiCPUUDKb3Z0szng1hiAJa098Hkhg9o4SE35Qw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.26.5" }, "engines": { "node": ">=6.9.0" @@ -1519,13 +1517,13 @@ } }, "node_modules/@babel/plugin-transform-numeric-separator": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.27.1.tgz", - "integrity": "sha512-fdPKAcujuvEChxDBJ5c+0BTaS6revLV7CJL08e4m3de8qJfNIuCc2nc7XJYOjBoTMJeqSmwXJ0ypE14RCjLwaw==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.25.9.tgz", + "integrity": "sha512-TlprrJ1GBZ3r6s96Yq8gEQv82s8/5HnCVHtEJScUj90thHQbwe+E5MLhi2bbNHBEJuzrvltXSru+BUxHDoog7Q==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1535,16 +1533,15 @@ } }, "node_modules/@babel/plugin-transform-object-rest-spread": { - "version": "7.27.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.27.2.tgz", - "integrity": "sha512-AIUHD7xJ1mCrj3uPozvtngY3s0xpv7Nu7DoUSnzNY6Xam1Cy4rUznR//pvMHOhQ4AvbCexhbqXCtpxGHOGOO6g==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.25.9.tgz", + "integrity": "sha512-fSaXafEE9CVHPweLYw4J0emp1t8zYTXyzN3UuG+lylqkvYd7RMrsOQ8TYx5RF231be0vqtFC6jnx3UmpJmKBYg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-compilation-targets": "^7.27.2", - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/plugin-transform-destructuring": "^7.27.1", - "@babel/plugin-transform-parameters": "^7.27.1" + "@babel/helper-compilation-targets": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/plugin-transform-parameters": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1554,14 +1551,14 @@ } }, "node_modules/@babel/plugin-transform-object-super": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.27.1.tgz", - "integrity": "sha512-SFy8S9plRPbIcxlJ8A6mT/CxFdJx/c04JEctz4jf8YZaVS2px34j7NXRrlGlHkN/M2gnpL37ZpGRGVFLd3l8Ng==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.25.9.tgz", + "integrity": "sha512-Kj/Gh+Rw2RNLbCK1VAWj2U48yxxqL2x0k10nPtSdRa0O2xnHXalD0s+o1A6a0W43gJ00ANo38jxkQreckOzv5A==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/helper-replace-supers": "^7.27.1" + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-replace-supers": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1571,13 +1568,13 @@ } }, "node_modules/@babel/plugin-transform-optional-catch-binding": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.27.1.tgz", - "integrity": "sha512-txEAEKzYrHEX4xSZN4kJ+OfKXFVSWKB2ZxM9dpcE3wT7smwkNmXo5ORRlVzMVdJbD+Q8ILTgSD7959uj+3Dm3Q==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.25.9.tgz", + "integrity": "sha512-qM/6m6hQZzDcZF3onzIhZeDHDO43bkNNlOX0i8n3lR6zLbu0GN2d8qfM/IERJZYauhAHSLHy39NF0Ctdvcid7g==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1587,14 +1584,14 @@ } }, "node_modules/@babel/plugin-transform-optional-chaining": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.27.1.tgz", - "integrity": "sha512-BQmKPPIuc8EkZgNKsv0X4bPmOoayeu4F1YCwx2/CfmDSXDbp7GnzlUH+/ul5VGfRg1AoFPsrIThlEBj2xb4CAg==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.25.9.tgz", + "integrity": "sha512-6AvV0FsLULbpnXeBjrY4dmWF8F7gf8QnvTEoO/wX/5xm/xE1Xo8oPuD3MPS+KS9f9XBEAWN7X1aWr4z9HdOr7A==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1604,13 +1601,13 @@ } }, "node_modules/@babel/plugin-transform-parameters": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.27.1.tgz", - "integrity": "sha512-018KRk76HWKeZ5l4oTj2zPpSh+NbGdt0st5S6x0pga6HgrjBOJb24mMDHorFopOOd6YHkLgOZ+zaCjZGPO4aKg==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.25.9.tgz", + "integrity": "sha512-wzz6MKwpnshBAiRmn4jR8LYz/g8Ksg0o80XmwZDlordjwEk9SxBzTWC7F5ef1jhbrbOW2DJ5J6ayRukrJmnr0g==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1620,14 +1617,14 @@ } }, "node_modules/@babel/plugin-transform-private-methods": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.27.1.tgz", - "integrity": "sha512-10FVt+X55AjRAYI9BrdISN9/AQWHqldOeZDUoLyif1Kn05a56xVBXb8ZouL8pZ9jem8QpXaOt8TS7RHUIS+GPA==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.25.9.tgz", + "integrity": "sha512-D/JUozNpQLAPUVusvqMxyvjzllRaF8/nSrP1s2YGQT/W4LHK4xxsMcHjhOGTS01mp9Hda8nswb+FblLdJornQw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-create-class-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1637,15 +1634,15 @@ } }, "node_modules/@babel/plugin-transform-private-property-in-object": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.27.1.tgz", - "integrity": "sha512-5J+IhqTi1XPa0DXF83jYOaARrX+41gOewWbkPyjMNRDqgOCqdffGh8L3f/Ek5utaEBZExjSAzcyjmV9SSAWObQ==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.25.9.tgz", + "integrity": "sha512-Evf3kcMqzXA3xfYJmZ9Pg1OvKdtqsDMSWBDzZOPLvHiTt36E75jLDQo5w1gtRU95Q4E5PDttrTf25Fw8d/uWLw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.27.1", - "@babel/helper-create-class-features-plugin": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-annotate-as-pure": "^7.25.9", + "@babel/helper-create-class-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1655,13 +1652,13 @@ } }, "node_modules/@babel/plugin-transform-property-literals": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.27.1.tgz", - "integrity": "sha512-oThy3BCuCha8kDZ8ZkgOg2exvPYUlprMukKQXI1r1pJ47NCvxfkEy8vK+r/hT9nF0Aa4H1WUPZZjHTFtAhGfmQ==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.25.9.tgz", + "integrity": "sha512-IvIUeV5KrS/VPavfSM/Iu+RE6llrHrYIKY1yfCzyO/lMXHQ+p7uGhonmGVisv6tSBSVgWzMBohTcvkC9vQcQFA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1671,13 +1668,14 @@ } }, "node_modules/@babel/plugin-transform-regenerator": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.27.1.tgz", - "integrity": "sha512-B19lbbL7PMrKr52BNPjCqg1IyNUIjTcxKj8uX9zHO+PmWN93s19NDr/f69mIkEp2x9nmDJ08a7lgHaTTzvW7mw==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.25.9.tgz", + "integrity": "sha512-vwDcDNsgMPDGP0nMqzahDWE5/MLcX8sv96+wfX7as7LoF/kr97Bo/7fI00lXY4wUXYfVmwIIyG80fGZ1uvt2qg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.25.9", + "regenerator-transform": "^0.15.2" }, "engines": { "node": ">=6.9.0" @@ -1686,15 +1684,25 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-transform-regenerator/node_modules/regenerator-transform": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz", + "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.8.4" + } + }, "node_modules/@babel/plugin-transform-regexp-modifiers": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regexp-modifiers/-/plugin-transform-regexp-modifiers-7.27.1.tgz", - "integrity": "sha512-TtEciroaiODtXvLZv4rmfMhkCv8jx3wgKpL68PuiPh2M4fvz5jhsA7697N1gMvkvr/JTF13DrFYyEbY9U7cVPA==", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regexp-modifiers/-/plugin-transform-regexp-modifiers-7.26.0.tgz", + "integrity": "sha512-vN6saax7lrA2yA/Pak3sCxuD6F5InBjn9IcrIKQPjpsLvuHYLVroTxjdlVRHjjBWxKOqIwpTXDkOssYT4BFdRw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-create-regexp-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1704,13 +1712,13 @@ } }, "node_modules/@babel/plugin-transform-reserved-words": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.27.1.tgz", - "integrity": "sha512-V2ABPHIJX4kC7HegLkYoDpfg9PVmuWy/i6vUM5eGK22bx4YVFD3M5F0QQnWQoDs6AGsUWTVOopBiMFQgHaSkVw==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.25.9.tgz", + "integrity": "sha512-7DL7DKYjn5Su++4RXu8puKZm2XBPHyjWLUidaPEkCUBbE7IPcsrkRHggAOOKydH1dASWdcUBxrkOGNxUv5P3Jg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1749,13 +1757,13 @@ } }, "node_modules/@babel/plugin-transform-shorthand-properties": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.27.1.tgz", - "integrity": "sha512-N/wH1vcn4oYawbJ13Y/FxcQrWk63jhfNa7jef0ih7PHSIHX2LB7GWE1rkPrOnka9kwMxb6hMl19p7lidA+EHmQ==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.25.9.tgz", + "integrity": "sha512-MUv6t0FhO5qHnS/W8XCbHmiRWOphNufpE1IVxhK5kuN3Td9FT1x4rx4K42s3RYdMXCXpfWkGSbCSd0Z64xA7Ng==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1765,14 +1773,14 @@ } }, "node_modules/@babel/plugin-transform-spread": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.27.1.tgz", - "integrity": "sha512-kpb3HUqaILBJcRFVhFUs6Trdd4mkrzcGXss+6/mxUd273PfbWqSDHRzMT2234gIg2QYfAjvXLSquP1xECSg09Q==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.25.9.tgz", + "integrity": "sha512-oNknIB0TbURU5pqJFVbOOFspVlrpVwo2H1+HUIsVDvp5VauGGDP1ZEvO8Nn5xyMEs3dakajOxlmkNW7kNgSm6A==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1782,13 +1790,13 @@ } }, "node_modules/@babel/plugin-transform-sticky-regex": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.27.1.tgz", - "integrity": "sha512-lhInBO5bi/Kowe2/aLdBAawijx+q1pQzicSgnkB6dUPc1+RC8QmJHKf2OjvU+NZWitguJHEaEmbV6VWEouT58g==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.25.9.tgz", + "integrity": "sha512-WqBUSgeVwucYDP9U/xNRQam7xV8W5Zf+6Eo7T2SRVUFlhRiMNFdFz58u0KZmCVVqs2i7SHgpRnAhzRNmKfi2uA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1798,13 +1806,13 @@ } }, "node_modules/@babel/plugin-transform-template-literals": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.27.1.tgz", - "integrity": "sha512-fBJKiV7F2DxZUkg5EtHKXQdbsbURW3DZKQUWphDum0uRP6eHGGa/He9mc0mypL680pb+e/lDIthRohlv8NCHkg==", + "version": "7.26.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.26.8.tgz", + "integrity": "sha512-OmGDL5/J0CJPJZTHZbi2XpO0tyT2Ia7fzpW5GURwdtp2X3fMmN8au/ej6peC/T33/+CRiIpA8Krse8hFGVmT5Q==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.26.5" }, "engines": { "node": ">=6.9.0" @@ -1814,13 +1822,13 @@ } }, "node_modules/@babel/plugin-transform-typeof-symbol": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.27.1.tgz", - "integrity": "sha512-RiSILC+nRJM7FY5srIyc4/fGIwUhyDuuBSdWn4y6yT6gm652DpCHZjIipgn6B7MQ1ITOUnAKWixEUjQRIBIcLw==", + "version": "7.26.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.26.7.tgz", + "integrity": "sha512-jfoTXXZTgGg36BmhqT3cAYK5qkmqvJpvNrPhaK/52Vgjhw4Rq29s9UqpWWV0D6yuRmgiFH/BUVlkl96zJWqnaw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.26.5" }, "engines": { "node": ">=6.9.0" @@ -1830,13 +1838,13 @@ } }, "node_modules/@babel/plugin-transform-unicode-escapes": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.27.1.tgz", - "integrity": "sha512-Ysg4v6AmF26k9vpfFuTZg8HRfVWzsh1kVfowA23y9j/Gu6dOuahdUVhkLqpObp3JIv27MLSii6noRnuKN8H0Mg==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.25.9.tgz", + "integrity": "sha512-s5EDrE6bW97LtxOcGj1Khcx5AaXwiMmi4toFWRDP9/y0Woo6pXC+iyPu/KuhKtfSrNFd7jJB+/fkOtZy6aIC6Q==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1846,14 +1854,14 @@ } }, "node_modules/@babel/plugin-transform-unicode-property-regex": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.27.1.tgz", - "integrity": "sha512-uW20S39PnaTImxp39O5qFlHLS9LJEmANjMG7SxIhap8rCHqu0Ik+tLEPX5DKmHn6CsWQ7j3lix2tFOa5YtL12Q==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.25.9.tgz", + "integrity": "sha512-Jt2d8Ga+QwRluxRQ307Vlxa6dMrYEMZCgGxoPR8V52rxPyldHu3hdlHspxaqYmE7oID5+kB+UKUB/eWS+DkkWg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-create-regexp-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1863,14 +1871,14 @@ } }, "node_modules/@babel/plugin-transform-unicode-regex": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.27.1.tgz", - "integrity": "sha512-xvINq24TRojDuyt6JGtHmkVkrfVV3FPT16uytxImLeBZqW3/H52yN+kM1MGuyPkIQxrzKwPHs5U/MP3qKyzkGw==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.25.9.tgz", + "integrity": "sha512-yoxstj7Rg9dlNn9UQxzk4fcNivwv4nUYz7fYXBaKxvw/lnmPuOm/ikoELygbYq68Bls3D/D+NBPHiLwZdZZ4HA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-create-regexp-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1880,14 +1888,14 @@ } }, "node_modules/@babel/plugin-transform-unicode-sets-regex": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.27.1.tgz", - "integrity": "sha512-EtkOujbc4cgvb0mlpQefi4NTPBzhSIevblFevACNLUspmrALgmEBdL/XfnyyITfd8fKBZrZys92zOWcik7j9Tw==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.25.9.tgz", + "integrity": "sha512-8BYqO3GeVNHtx69fdPshN3fnzUNLrWdHhk/icSwigksJGczKSizZ+Z6SBCxTs723Fr5VSNorTIK7a+R2tISvwQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-create-regexp-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1897,75 +1905,75 @@ } }, "node_modules/@babel/preset-env": { - "version": "7.27.2", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.27.2.tgz", - "integrity": "sha512-Ma4zSuYSlGNRlCLO+EAzLnCmJK2vdstgv+n7aUP+/IKZrOfWHOJVdSJtuub8RzHTj3ahD37k5OKJWvzf16TQyQ==", + "version": "7.26.9", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.26.9.tgz", + "integrity": "sha512-vX3qPGE8sEKEAZCWk05k3cpTAE3/nOYca++JA+Rd0z2NCNzabmYvEiSShKzm10zdquOIAVXsy2Ei/DTW34KlKQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.27.2", - "@babel/helper-compilation-targets": "^7.27.2", - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/helper-validator-option": "^7.27.1", - "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.27.1", - "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.27.1", - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.27.1", - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.27.1", - "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.27.1", + "@babel/compat-data": "^7.26.8", + "@babel/helper-compilation-targets": "^7.26.5", + "@babel/helper-plugin-utils": "^7.26.5", + "@babel/helper-validator-option": "^7.25.9", + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.25.9", + "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.25.9", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.25.9", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.25.9", + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.25.9", "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", - "@babel/plugin-syntax-import-assertions": "^7.27.1", - "@babel/plugin-syntax-import-attributes": "^7.27.1", + "@babel/plugin-syntax-import-assertions": "^7.26.0", + "@babel/plugin-syntax-import-attributes": "^7.26.0", "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", - "@babel/plugin-transform-arrow-functions": "^7.27.1", - "@babel/plugin-transform-async-generator-functions": "^7.27.1", - "@babel/plugin-transform-async-to-generator": "^7.27.1", - "@babel/plugin-transform-block-scoped-functions": "^7.27.1", - "@babel/plugin-transform-block-scoping": "^7.27.1", - "@babel/plugin-transform-class-properties": "^7.27.1", - "@babel/plugin-transform-class-static-block": "^7.27.1", - "@babel/plugin-transform-classes": "^7.27.1", - "@babel/plugin-transform-computed-properties": "^7.27.1", - "@babel/plugin-transform-destructuring": "^7.27.1", - "@babel/plugin-transform-dotall-regex": "^7.27.1", - "@babel/plugin-transform-duplicate-keys": "^7.27.1", - "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.27.1", - "@babel/plugin-transform-dynamic-import": "^7.27.1", - "@babel/plugin-transform-exponentiation-operator": "^7.27.1", - "@babel/plugin-transform-export-namespace-from": "^7.27.1", - "@babel/plugin-transform-for-of": "^7.27.1", - "@babel/plugin-transform-function-name": "^7.27.1", - "@babel/plugin-transform-json-strings": "^7.27.1", - "@babel/plugin-transform-literals": "^7.27.1", - "@babel/plugin-transform-logical-assignment-operators": "^7.27.1", - "@babel/plugin-transform-member-expression-literals": "^7.27.1", - "@babel/plugin-transform-modules-amd": "^7.27.1", - "@babel/plugin-transform-modules-commonjs": "^7.27.1", - "@babel/plugin-transform-modules-systemjs": "^7.27.1", - "@babel/plugin-transform-modules-umd": "^7.27.1", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.27.1", - "@babel/plugin-transform-new-target": "^7.27.1", - "@babel/plugin-transform-nullish-coalescing-operator": "^7.27.1", - "@babel/plugin-transform-numeric-separator": "^7.27.1", - "@babel/plugin-transform-object-rest-spread": "^7.27.2", - "@babel/plugin-transform-object-super": "^7.27.1", - "@babel/plugin-transform-optional-catch-binding": "^7.27.1", - "@babel/plugin-transform-optional-chaining": "^7.27.1", - "@babel/plugin-transform-parameters": "^7.27.1", - "@babel/plugin-transform-private-methods": "^7.27.1", - "@babel/plugin-transform-private-property-in-object": "^7.27.1", - "@babel/plugin-transform-property-literals": "^7.27.1", - "@babel/plugin-transform-regenerator": "^7.27.1", - "@babel/plugin-transform-regexp-modifiers": "^7.27.1", - "@babel/plugin-transform-reserved-words": "^7.27.1", - "@babel/plugin-transform-shorthand-properties": "^7.27.1", - "@babel/plugin-transform-spread": "^7.27.1", - "@babel/plugin-transform-sticky-regex": "^7.27.1", - "@babel/plugin-transform-template-literals": "^7.27.1", - "@babel/plugin-transform-typeof-symbol": "^7.27.1", - "@babel/plugin-transform-unicode-escapes": "^7.27.1", - "@babel/plugin-transform-unicode-property-regex": "^7.27.1", - "@babel/plugin-transform-unicode-regex": "^7.27.1", - "@babel/plugin-transform-unicode-sets-regex": "^7.27.1", + "@babel/plugin-transform-arrow-functions": "^7.25.9", + "@babel/plugin-transform-async-generator-functions": "^7.26.8", + "@babel/plugin-transform-async-to-generator": "^7.25.9", + "@babel/plugin-transform-block-scoped-functions": "^7.26.5", + "@babel/plugin-transform-block-scoping": "^7.25.9", + "@babel/plugin-transform-class-properties": "^7.25.9", + "@babel/plugin-transform-class-static-block": "^7.26.0", + "@babel/plugin-transform-classes": "^7.25.9", + "@babel/plugin-transform-computed-properties": "^7.25.9", + "@babel/plugin-transform-destructuring": "^7.25.9", + "@babel/plugin-transform-dotall-regex": "^7.25.9", + "@babel/plugin-transform-duplicate-keys": "^7.25.9", + "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.25.9", + "@babel/plugin-transform-dynamic-import": "^7.25.9", + "@babel/plugin-transform-exponentiation-operator": "^7.26.3", + "@babel/plugin-transform-export-namespace-from": "^7.25.9", + "@babel/plugin-transform-for-of": "^7.26.9", + "@babel/plugin-transform-function-name": "^7.25.9", + "@babel/plugin-transform-json-strings": "^7.25.9", + "@babel/plugin-transform-literals": "^7.25.9", + "@babel/plugin-transform-logical-assignment-operators": "^7.25.9", + "@babel/plugin-transform-member-expression-literals": "^7.25.9", + "@babel/plugin-transform-modules-amd": "^7.25.9", + "@babel/plugin-transform-modules-commonjs": "^7.26.3", + "@babel/plugin-transform-modules-systemjs": "^7.25.9", + "@babel/plugin-transform-modules-umd": "^7.25.9", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.25.9", + "@babel/plugin-transform-new-target": "^7.25.9", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.26.6", + "@babel/plugin-transform-numeric-separator": "^7.25.9", + "@babel/plugin-transform-object-rest-spread": "^7.25.9", + "@babel/plugin-transform-object-super": "^7.25.9", + "@babel/plugin-transform-optional-catch-binding": "^7.25.9", + "@babel/plugin-transform-optional-chaining": "^7.25.9", + "@babel/plugin-transform-parameters": "^7.25.9", + "@babel/plugin-transform-private-methods": "^7.25.9", + "@babel/plugin-transform-private-property-in-object": "^7.25.9", + "@babel/plugin-transform-property-literals": "^7.25.9", + "@babel/plugin-transform-regenerator": "^7.25.9", + "@babel/plugin-transform-regexp-modifiers": "^7.26.0", + "@babel/plugin-transform-reserved-words": "^7.25.9", + "@babel/plugin-transform-shorthand-properties": "^7.25.9", + "@babel/plugin-transform-spread": "^7.25.9", + "@babel/plugin-transform-sticky-regex": "^7.25.9", + "@babel/plugin-transform-template-literals": "^7.26.8", + "@babel/plugin-transform-typeof-symbol": "^7.26.7", + "@babel/plugin-transform-unicode-escapes": "^7.25.9", + "@babel/plugin-transform-unicode-property-regex": "^7.25.9", + "@babel/plugin-transform-unicode-regex": "^7.25.9", + "@babel/plugin-transform-unicode-sets-regex": "^7.25.9", "@babel/preset-modules": "0.1.6-no-external-plugins", "babel-plugin-polyfill-corejs2": "^0.4.10", "babel-plugin-polyfill-corejs3": "^0.11.0", @@ -2035,32 +2043,32 @@ "dev": true }, "node_modules/@babel/template": { - "version": "7.27.2", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", - "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", + "version": "7.26.9", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.26.9.tgz", + "integrity": "sha512-qyRplbeIpNZhmzOysF/wFMuP9sctmh2cFzRAZOn1YapxBsE1i9bJIY586R/WBLfLcmcBlM8ROBiQURnnNy+zfA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.27.1", - "@babel/parser": "^7.27.2", - "@babel/types": "^7.27.1" + "@babel/code-frame": "^7.26.2", + "@babel/parser": "^7.26.9", + "@babel/types": "^7.26.9" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.27.1.tgz", - "integrity": "sha512-ZCYtZciz1IWJB4U61UPu4KEaqyfj+r5T1Q5mqPo+IBpcG9kHv30Z0aD8LXPgC1trYa6rK0orRyAhqUgk4MjmEg==", + "version": "7.26.10", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.26.10.tgz", + "integrity": "sha512-k8NuDrxr0WrPH5Aupqb2LCVURP/S0vBEn5mK6iH+GIYob66U5EtoZvcdudR2jQ4cmTwhEwW1DLB+Yyas9zjF6A==", "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.27.1", - "@babel/parser": "^7.27.1", - "@babel/template": "^7.27.1", - "@babel/types": "^7.27.1", + "@babel/code-frame": "^7.26.2", + "@babel/generator": "^7.26.10", + "@babel/parser": "^7.26.10", + "@babel/template": "^7.26.9", + "@babel/types": "^7.26.10", "debug": "^4.3.1", "globals": "^11.1.0" }, @@ -2101,13 +2109,13 @@ "dev": true }, "node_modules/@babel/types": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.1.tgz", - "integrity": "sha512-+EzkxvLNfiUeKMgy/3luqfsCWFRXLb7U6wNQTk60tovuckwB15B191tJWvpp4HjiQWdJkCxO3Wbvc6jlk3Xb2Q==", + "version": "7.26.10", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.10.tgz", + "integrity": "sha512-emqcG3vHrpxUKTrxcblR36dcrcoRDvKmnL/dCL6ZsHaShW80qxCAcNhzQZrpeM765VzEos+xOi4s+r4IXzTwdQ==", "license": "MIT", "dependencies": { - "@babel/helper-string-parser": "^7.27.1", - "@babel/helper-validator-identifier": "^7.27.1" + "@babel/helper-string-parser": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -3811,9 +3819,9 @@ } }, "node_modules/@mediakind/mkplayer": { - "version": "1.22.0", - "resolved": "https://registry.npmjs.org/@mediakind/mkplayer/-/mkplayer-1.22.0.tgz", - "integrity": "sha512-1PWswbIw3U84QkRWbkCVDha0qppzrpDbxiytnRFkLeUpE8klKRWJtI92ph0favspfTFjanX8A0qTGRkA8lsLwA==", + "version": "1.21.0", + "resolved": "https://registry.npmjs.org/@mediakind/mkplayer/-/mkplayer-1.21.0.tgz", + "integrity": "sha512-6sZwxQObISgmD4z0RV6xoi2bJgnOBtDAa2bPg4H/D095MaUInaDkrCimROst/rWfeMFg2m4h9PSmJV88cYbvQw==", "license": "©2025 Copyright Mediakind Ltd. All Rights Reserved. Including All Downloadable Materials.", "dependencies": { "bitmovin-player": "8.193.0", @@ -4615,9 +4623,9 @@ "license": "MIT" }, "node_modules/@types/lodash": { - "version": "4.17.17", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.17.tgz", - "integrity": "sha512-RRVJ+J3J+WmyOTqnz3PiBLA501eKwXl2noseKOrNo/6+XEHjTAxO4xHvxQB6QuNm+s4WRbn6rSiap8+EA+ykFQ==", + "version": "4.17.16", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.16.tgz", + "integrity": "sha512-HX7Em5NYQAXKW+1T+FiuG27NGwzJfCX3s1GjOa7ujxZa52kjJLOr4FUxT+giF6Tgxv1e+/czV/iTtBw27WTU9g==", "dev": true, "license": "MIT" }, @@ -4646,11 +4654,10 @@ "dev": true }, "node_modules/@types/sanitize-html": { - "version": "2.16.0", - "resolved": "https://registry.npmjs.org/@types/sanitize-html/-/sanitize-html-2.16.0.tgz", - "integrity": "sha512-l6rX1MUXje5ztPT0cAFtUayXF06DqPhRyfVXareEN5gGCFaP/iwsxIyKODr9XDhfxPpN6vXUFNfo5kZMXCxBtw==", + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/@types/sanitize-html/-/sanitize-html-2.13.0.tgz", + "integrity": "sha512-X31WxbvW9TjIhZZNyNBZ/p5ax4ti7qsNDBDEnH4zAgmEh35YnFD1UiS6z9Cd34kKm0LslFW0KPmTQzu/oGtsqQ==", "dev": true, - "license": "MIT", "dependencies": { "htmlparser2": "^8.0.0" } @@ -4859,6 +4866,12 @@ "node": "^10 || ^12 || >=14" } }, + "node_modules/@vue/babel-plugin-resolve-type/node_modules/postcss/node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true + }, "node_modules/@vue/babel-plugin-resolve-type/node_modules/source-map-js": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", @@ -7846,9 +7859,9 @@ } }, "node_modules/core-js": { - "version": "3.42.0", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.42.0.tgz", - "integrity": "sha512-Sz4PP4ZA+Rq4II21qkNqOEDTDrCvcANId3xpIgB34NDkWc3UduWj2dqEtN9yZIq8Dk3HyPI33x9sqqU5C8sr0g==", + "version": "3.41.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.41.0.tgz", + "integrity": "sha512-SJ4/EHwS36QMJd6h/Rg+GyR4A5xE0FSI3eZ+iBVpfqf1x0eTSg1smWLHrA+2jQThZSh97fmSgFSU8B61nxosxA==", "hasInstallScript": true, "license": "MIT", "funding": { @@ -8013,6 +8026,12 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, + "node_modules/css-loader/node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true + }, "node_modules/css-loader/node_modules/postcss": { "version": "8.5.1", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.1.tgz", @@ -15887,10 +15906,9 @@ } }, "node_modules/picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "license": "ISC" + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" }, "node_modules/picomatch": { "version": "2.2.3", @@ -16164,6 +16182,11 @@ "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", "dev": true }, + "node_modules/postcss/node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==" + }, "node_modules/postcss/node_modules/source-map-js": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", @@ -16866,9 +16889,9 @@ "dev": true }, "node_modules/sanitize-html": { - "version": "2.17.0", - "resolved": "https://registry.npmjs.org/sanitize-html/-/sanitize-html-2.17.0.tgz", - "integrity": "sha512-dLAADUSS8rBwhaevT12yCezvioCA+bmUTPH/u57xKPT8d++voeYE6HeluA/bPbQ15TwDBG2ii+QZIEmYx8VdxA==", + "version": "2.15.0", + "resolved": "https://registry.npmjs.org/sanitize-html/-/sanitize-html-2.15.0.tgz", + "integrity": "sha512-wIjst57vJGpLyBP8ioUbg6ThwJie5SuSIjHxJg53v5Fg+kUK+AXlb7bK3RNXpp315MvwM+0OBGCV6h5pPHsVhA==", "license": "MIT", "dependencies": { "deepmerge": "^4.2.2", @@ -16899,9 +16922,9 @@ } }, "node_modules/sass": { - "version": "1.89.0", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.89.0.tgz", - "integrity": "sha512-ld+kQU8YTdGNjOLfRWBzewJpU5cwEv/h5yyqlSeJcj6Yh8U4TDA9UA5FPicqDz/xgRPWRSYIQNiFks21TbA9KQ==", + "version": "1.86.3", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.86.3.tgz", + "integrity": "sha512-iGtg8kus4GrsGLRDLRBRHY9dNVA78ZaS7xr01cWnS7PEMQyFtTqBiyCrfpTYTZXRWM94akzckYjh8oADfFNTzw==", "dev": true, "license": "MIT", "dependencies": { @@ -18961,6 +18984,12 @@ "node": ">=6" } }, + "node_modules/update-browserslist-db/node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true + }, "node_modules/uri-js": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", @@ -19376,15 +19405,14 @@ } }, "node_modules/webpack": { - "version": "5.99.9", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.99.9.tgz", - "integrity": "sha512-brOPwM3JnmOa+7kd3NsmOUOwbDAj8FT9xDsG3IW0MgbN9yZV7Oi/s/+MNQ/EcSMqw7qfoRyXPoeEWT8zLVdVGg==", + "version": "5.99.5", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.99.5.tgz", + "integrity": "sha512-q+vHBa6H9qwBLUlHL4Y7L0L1/LlyBKZtS9FHNCQmtayxjI5RKC9yD8gpvLeqGv5lCQp1Re04yi0MF40pf30Pvg==", "dev": true, "license": "MIT", "dependencies": { "@types/eslint-scope": "^3.7.7", "@types/estree": "^1.0.6", - "@types/json-schema": "^7.0.15", "@webassemblyjs/ast": "^1.14.1", "@webassemblyjs/wasm-edit": "^1.14.1", "@webassemblyjs/wasm-parser": "^1.14.1", @@ -19401,7 +19429,7 @@ "loader-runner": "^4.2.0", "mime-types": "^2.1.27", "neo-async": "^2.6.2", - "schema-utils": "^4.3.2", + "schema-utils": "^4.3.0", "tapable": "^2.1.1", "terser-webpack-plugin": "^5.3.11", "watchpack": "^2.4.1", @@ -20026,9 +20054,9 @@ } }, "node_modules/webpack/node_modules/schema-utils": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.2.tgz", - "integrity": "sha512-Gn/JaSk/Mt9gYubxTtSn/QCV4em9mpAPiR1rqy/Ocu19u/G9J5WWdNoUT4SiV6mFC3y6cxyFcFwdzPM3FgxGAQ==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.0.tgz", + "integrity": "sha512-Gf9qqc58SpCA/xdziiHz35F4GNIWYWZrEshUc/G/r5BnLph6xpKuLeoJoQuj5WfBIx/eQLf+hmVPYHaxJu7V2g==", "dev": true, "license": "MIT", "dependencies": { diff --git a/LearningHub.Nhs.WebUI/package.json b/LearningHub.Nhs.WebUI/package.json index 19f91556a..a2a0d94ed 100644 --- a/LearningHub.Nhs.WebUI/package.json +++ b/LearningHub.Nhs.WebUI/package.json @@ -22,14 +22,14 @@ "dependencies": { "@ckeditor/ckeditor5-build-classic": "16.0.0", "@ckeditor/ckeditor5-vue": "1.0.3", - "@mediakind/mkplayer": "1.22.0", + "@mediakind/mkplayer": "1.21.0", "@types/uuid": "^8.3.4", "axios": "^0.30.0", "babel-polyfill": "^6.26.0", "bootstrap": "^4.6.2", "ckeditor4-vue": "^0.2.0", "concurrently": "^7.6.0", - "core-js": "^3.42.0", + "core-js": "^3.41.0", "js-cookie": "2.2.1", "lodash": "4.17.21", "moment": "^2.30.1", @@ -37,7 +37,7 @@ "nhsuk-frontend": "^7.1.0", "node": "^14.0.0", "openseadragon": "^2.4.2", - "sanitize-html": "^2.17.0", + "sanitize-html": "^2.15.0", "save": "^2.9.0", "ts-debounce": "2.3.0", "tus-js-client": "^2.3.2", @@ -56,8 +56,8 @@ "vuex": "^3.6.2" }, "devDependencies": { - "@babel/core": "^7.27.1", - "@babel/preset-env": "^7.27.2", + "@babel/core": "^7.26.10", + "@babel/preset-env": "^7.26.9", "@types/axios": "^0.14.0", "@types/bootstrap": "4.6.1", "@types/ckeditor": "4.9.10", @@ -65,9 +65,9 @@ "@types/jquery": "^3.3.32", "@types/jquery-match-height": "^0.7.8", "@types/js-cookie": "2.2.1", - "@types/lodash": "4.17.17", + "@types/lodash": "4.17.16", "@types/openseadragon": "^2.4.5", - "@types/sanitize-html": "^2.16.0", + "@types/sanitize-html": "^2.13.0", "@types/vuelidate": "^0.7.22", "@vue/babel-preset-app": "4.5.19", "@vue/test-utils": "^1.3.6", @@ -80,7 +80,7 @@ "eslint": "^8.51.0", "file-loader": "^6.2.0", "jest": "^27.5.1", - "sass": "^1.89.0", + "sass": "^1.86.3", "sass-loader": "^11.1.1", "style-loader": "^2.0.0", "ts-jest": "^27.1.5", @@ -90,7 +90,7 @@ "vue-jest": "^3.0.7", "vue-loader": "^15.11.1", "vue-template-compiler": "2.7.16", - "webpack": "^5.99.9", + "webpack": "^5.99.5", "webpack-cli": "^4.10.0", "webpack-dev-server": "^3.11.3" } diff --git a/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/LearningHub.Nhs.MessageQueueing.Database.sqlproj b/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/LearningHub.Nhs.MessageQueueing.Database.sqlproj new file mode 100644 index 000000000..502e072a3 --- /dev/null +++ b/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/LearningHub.Nhs.MessageQueueing.Database.sqlproj @@ -0,0 +1,86 @@ + + + + Debug + AnyCPU + LearningHub.Nhs.MessageQueueing.Database + 2.0 + 4.1 + {afc1a740-bba1-44bc-8a52-a65d2e506e69} + Microsoft.Data.Tools.Schema.Sql.Sql160DatabaseSchemaProvider + Database + + + LearningHub.Nhs.MessageQueueing.Database + LearningHub.Nhs.MessageQueueing.Database + 1033, CI + BySchemaAndSchemaType + True + v4.7.2 + CS + Properties + False + True + True + + + bin\Release\ + $(MSBuildProjectName).sql + False + pdbonly + true + false + true + prompt + 4 + + + bin\Debug\ + $(MSBuildProjectName).sql + false + true + full + false + true + true + prompt + 4 + + + 11.0 + + True + 11.0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/LearningHub.Nhs.MessageQueueing.Database.sqlproj.user b/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/LearningHub.Nhs.MessageQueueing.Database.sqlproj.user new file mode 100644 index 000000000..0b07de1b2 --- /dev/null +++ b/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/LearningHub.Nhs.MessageQueueing.Database.sqlproj.user @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Scripts/Post-Deploy/Script.PostDeployment.sql b/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Scripts/Post-Deploy/Script.PostDeployment.sql new file mode 100644 index 000000000..755411369 --- /dev/null +++ b/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Scripts/Post-Deploy/Script.PostDeployment.sql @@ -0,0 +1,14 @@ +/* +Post-Deployment Script Template +-------------------------------------------------------------------------------------- + This file contains SQL statements that will be appended to the build script. + Use SQLCMD syntax to include a file in the post-deployment script. + Example: :r .\myfile.sql + Use SQLCMD syntax to reference a variable in the post-deployment script. + Example: :setvar TableName MyTable + SELECT * FROM [$(TableName)] +-------------------------------------------------------------------------------------- +*/ + +:r .\Scripts\RequestStatusData.sql +:r .\Scripts\RequestTypeData.sql \ No newline at end of file diff --git a/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Scripts/Post-Deploy/Scripts/RequestStatusData.sql b/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Scripts/Post-Deploy/Scripts/RequestStatusData.sql new file mode 100644 index 000000000..3171b73fd --- /dev/null +++ b/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Scripts/Post-Deploy/Scripts/RequestStatusData.sql @@ -0,0 +1,14 @@ +IF NOT EXISTS(SELECT Id FROM [dbo].[RequestStatus] WHERE Id = 1) +BEGIN +INSERT [dbo].[RequestStatus] ([Id], [RequestStatus]) VALUES (1, N'Pending') +END + +IF NOT EXISTS(SELECT Id FROM [dbo].[RequestStatus] WHERE Id = 2) +BEGIN +INSERT [dbo].[RequestStatus] ([Id], [RequestStatus]) VALUES (2, N'Sent') +END + +IF NOT EXISTS(SELECT Id FROM [dbo].[RequestStatus] WHERE Id = 3) +BEGIN +INSERT [dbo].[RequestStatus] ([Id], [RequestStatus]) VALUES (3, N'Failed') +END \ No newline at end of file diff --git a/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Scripts/Post-Deploy/Scripts/RequestTypeData.sql b/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Scripts/Post-Deploy/Scripts/RequestTypeData.sql new file mode 100644 index 000000000..9be01874e --- /dev/null +++ b/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Scripts/Post-Deploy/Scripts/RequestTypeData.sql @@ -0,0 +1,14 @@ +IF NOT EXISTS(SELECT Id FROM [dbo].[RequestType] WHERE Id = 1) +BEGIN +INSERT [dbo].[RequestType] ([Id], [RequestType]) VALUES (1, N'Email') +END + +IF NOT EXISTS(SELECT Id FROM [dbo].[RequestType] WHERE Id = 2) +BEGIN +INSERT [dbo].[RequestType] ([Id], [RequestType]) VALUES (2, N'SMS') +END + +IF NOT EXISTS(SELECT Id FROM [dbo].[RequestType] WHERE Id = 3) +BEGIN +INSERT [dbo].[RequestType] ([Id], [RequestType]) VALUES (3, N'SingleEmail') +END \ No newline at end of file diff --git a/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Stored Procedures/CreateQueueRequests.sql b/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Stored Procedures/CreateQueueRequests.sql new file mode 100644 index 000000000..a7d8bb494 --- /dev/null +++ b/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Stored Procedures/CreateQueueRequests.sql @@ -0,0 +1,20 @@ +------------------------------------------------------------------------------- +-- Author Arunima George +-- Created 27-05-2025 +-- Purpose Create email requests. +-- +-- Modification History +-- +-- 27-05-2025 Arunima George Initial Revision +------------------------------------------------------------------------------- + +Create PROCEDURE [dbo].[CreateQueueRequests] + @QueueRequests dbo.QueueRequestTableType READONLY +AS +BEGIN + + INSERT INTO QueueRequests (RequestTypeId, Recipient, TemplateId, Personalisation, Status, RetryCount, CreatedAt, DeliverAfter) + SELECT 1, Recipient, TemplateId, Personalisation, 1, 0, SYSDATETIMEOFFSET(), DeliverAfter + FROM @QueueRequests; +END +GO diff --git a/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Stored Procedures/GetAllMessageRequests.sql b/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Stored Procedures/GetAllMessageRequests.sql new file mode 100644 index 000000000..a6ce589dc --- /dev/null +++ b/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Stored Procedures/GetAllMessageRequests.sql @@ -0,0 +1,129 @@ +------------------------------------------------------------------------------- +-- Author Arunima George +-- Created 18-03-2026 +-- Purpose Get paginated message requests. +-- +-- Modification History +-- +-- 18-03-2026 Arunima George Initial Revision +------------------------------------------------------------------------------- + +CREATE PROCEDURE [dbo].[GetAllMessageRequests] + @offSet int, + @fetchRows int, + @SortColumn NVARCHAR(50) = 'CreatedAt', + @SortDirection NVARCHAR(4) = 'DESC', + @Filters NVARCHAR(MAX) = NULL, + @totalCount INT OUTPUT +AS +BEGIN +SET NOCOUNT ON; + +IF @SortColumn NOT IN ( +'Id','RequestType','Recipient','RequestStatus', +'RetryCount','CreatedAt' +) +SET @SortColumn = 'CreatedAt' + +IF @SortDirection NOT IN ('ASC','DESC') +SET @SortDirection = 'DESC' + +IF @Filters IS NULL OR @Filters = '' OR @Filters = 'null' +BEGIN + SET @Filters = '[]' +END + +DECLARE @WhereClause NVARCHAR(MAX) = '' + +------------------------------------------------ +-- Build WHERE clause from JSON filters +------------------------------------------------ + +SELECT @WhereClause = +STRING_AGG( + CASE + WHEN FilterType = 'Text' + THEN QUOTENAME(ColumnName) + ' LIKE ''%' + FilterValue + '%''' + + WHEN FilterType = 'Number' + THEN + CASE ColumnName + WHEN 'Id' THEN 'qr.Id' + WHEN 'RetryCount' THEN 'qr.RetryCount' + END + + ' = ' + FilterValue + + WHEN FilterType = 'Date' + THEN + CASE ColumnName + WHEN 'CreatedAt' THEN + 'qr.CreatedAt >= ''' + FilterValue + ''' AND qr.CreatedAt < DATEADD(DAY,1,''' + FilterValue + ''')' + END + + ELSE NULL + END +,' AND ') +FROM OPENJSON(@Filters) +WITH +( + ColumnName NVARCHAR(50) '$.Column', + FilterType NVARCHAR(50) '$.Type', + FilterValue NVARCHAR(200) '$.Value' +) + +------------------------------------------------ +-- Base Query +------------------------------------------------ + +DECLARE @SQL NVARCHAR(MAX) + +SET @SQL = ' +SELECT + qr.Id, + rt.RequestType, + qr.Recipient, + rs.RequestStatus, + qr.RetryCount, + qr.CreatedAt, + qr.DeliverAfter, + qr.SentAt, + qr.LastAttemptAt, + qr.ErrorMessage +FROM QueueRequests qr +JOIN RequestType rt ON qr.RequestTypeId = rt.Id +JOIN RequestStatus rs ON qr.Status = rs.Id +' + +IF @WhereClause IS NOT NULL AND LEN(@WhereClause) > 0 +BEGIN + SET @SQL = @SQL + ' WHERE ' + @WhereClause +END + + +------------------------------------------------ +-- Total Count +------------------------------------------------ + +DECLARE @CountSQL NVARCHAR(MAX) + +SET @CountSQL = 'SELECT @TotalCount = COUNT(*) FROM (' + @SQL + ') A' + +EXEC sp_executesql +@CountSQL, +N'@TotalCount INT OUTPUT', +@TotalCount OUTPUT + + +------------------------------------------------ +-- Pagination Query +------------------------------------------------ + +SET @SQL = @SQL + ' + ORDER BY ' + QUOTENAME(@SortColumn) + ' ' + @SortDirection + ' + OFFSET ' + CAST(@Offset AS NVARCHAR) + ' ROWS + FETCH NEXT ' + CAST(@fetchRows AS NVARCHAR) + ' ROWS ONLY' + +EXEC(@SQL) + +END +GO diff --git a/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Stored Procedures/GetMessageRequestById.sql b/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Stored Procedures/GetMessageRequestById.sql new file mode 100644 index 000000000..03ade3260 --- /dev/null +++ b/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Stored Procedures/GetMessageRequestById.sql @@ -0,0 +1,24 @@ +------------------------------------------------------------------------------- +-- Author Arunima George +-- Created 18-03-2026 +-- Purpose To get message request details by id. +-- +-- Modification History +-- +-- 18-03-2026 Arunima George Initial Revision +------------------------------------------------------------------------------- + +CREATE PROCEDURE [dbo].[GetMessageRequestById] +@id int +AS +BEGIN +SET NOCOUNT ON; + select qr.Id,rt.RequestType,Recipient,rs.RequestStatus,RetryCount,CreatedAt,DeliverAfter,SentAt,LastAttemptAt,ErrorMessage + from dbo.QueueRequests qr + left join RequestType as rt on rt.Id = qr.RequestTypeId + left join RequestStatus as rs on rs.Id = qr.Status + where qr.Id = @Id + + +END +GO diff --git a/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Stored Procedures/GetQueueRequests.sql b/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Stored Procedures/GetQueueRequests.sql new file mode 100644 index 000000000..7f2ac520c --- /dev/null +++ b/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Stored Procedures/GetQueueRequests.sql @@ -0,0 +1,20 @@ +------------------------------------------------------------------------------- +-- Author Arunima George +-- Created 27-05-2025 +-- Purpose Fetch pending/failed email requests from QueueRequests table. +-- +-- Modification History +-- +-- 27-05-2025 Arunima George Initial Revision +------------------------------------------------------------------------------- + +CREATE PROCEDURE [dbo].[GetQueueRequests] +AS +BEGIN + + select Id,Recipient,TemplateId,Personalisation,Status,RetryCount + from dbo.QueueRequests +where RequestTypeId = 1 and Status in (1,3) and RetryCount < 3 and (DeliverAfter is null or DeliverAfter <= SYSDATETIMEOFFSET()) + +END +GO \ No newline at end of file diff --git a/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Stored Procedures/MessageDeliveryFailed.sql b/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Stored Procedures/MessageDeliveryFailed.sql new file mode 100644 index 000000000..4d00ebac4 --- /dev/null +++ b/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Stored Procedures/MessageDeliveryFailed.sql @@ -0,0 +1,24 @@ +------------------------------------------------------------------------------- +-- Author Arunima George +-- Created 27-05-2025 +-- Purpose Update message request status as failed. +-- +-- Modification History +-- +-- 27-05-2025 Arunima George Initial Revision +------------------------------------------------------------------------------- + +CREATE PROCEDURE [dbo].[MessageDeliveryFailed] + @Id int, + @ErrorMessage nvarchar(max) +AS +BEGIN + UPDATE [dbo].[QueueRequests] + SET + Status = 3, + RetryCount = RetryCount + 1, + ErrorMessage = @ErrorMessage, + LastAttemptAt = SYSDATETIMEOFFSET() + where Id = @Id; +END +GO \ No newline at end of file diff --git a/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Stored Procedures/MessageDeliverySuccess.sql b/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Stored Procedures/MessageDeliverySuccess.sql new file mode 100644 index 000000000..b971d912f --- /dev/null +++ b/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Stored Procedures/MessageDeliverySuccess.sql @@ -0,0 +1,26 @@ +------------------------------------------------------------------------------- +-- Author Arunima George +-- Created 27-05-2025 +-- Purpose Update message request status as success. +-- +-- Modification History +-- +-- 27-05-2025 Arunima George Initial Revision +------------------------------------------------------------------------------- + +CREATE PROCEDURE [dbo].[MessageDeliverySuccess] + @Id int, + @NotificationId nvarchar(100) + +AS +BEGIN + UPDATE [dbo].[QueueRequests] + SET + Status = 2, + NotificationId = @NotificationId, + RetryCount = RetryCount + 1, + SentAt = SYSDATETIMEOFFSET(), + LastAttemptAt = SYSDATETIMEOFFSET() + where Id = @Id; +END +GO \ No newline at end of file diff --git a/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Stored Procedures/SaveSingleEmailTransactions.sql b/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Stored Procedures/SaveSingleEmailTransactions.sql new file mode 100644 index 000000000..285c072d4 --- /dev/null +++ b/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Stored Procedures/SaveSingleEmailTransactions.sql @@ -0,0 +1,22 @@ +------------------------------------------------------------------------------- +-- Author Arunima George +-- Created 27-05-2025 +-- Purpose Save all one-off(like otp) email request transactions. +-- +-- Modification History +-- +-- 27-05-2025 Arunima George Initial Revision +------------------------------------------------------------------------------- + +CREATE PROCEDURE [dbo].[SaveSingleEmailTransactions] + @Recipient nvarchar(255), + @TemplateId nvarchar(50), + @Personalisation nvarchar(max) = NULL, + @Status int, + @ErrorMessage nvarchar(max) = NULL +AS +BEGIN + insert into [dbo].[QueueRequests] (RequestTypeId, Recipient, TemplateId, Personalisation, Status, CreatedAt, LastAttemptAt,ErrorMessage ) + values (3, @Recipient, @TemplateId, @Personalisation, @Status, SYSDATETIMEOFFSET(), SYSDATETIMEOFFSET(), @ErrorMessage); +END +GO diff --git a/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Tables/QueueRequests.sql b/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Tables/QueueRequests.sql new file mode 100644 index 000000000..fad33bf9d --- /dev/null +++ b/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Tables/QueueRequests.sql @@ -0,0 +1,34 @@ +CREATE TABLE [dbo].[QueueRequests]( + [Id] [int] IDENTITY(1,1) NOT NULL, + [RequestTypeId] [int] NOT NULL, + [Recipient] [nvarchar](255) NOT NULL, + [TemplateId] [nvarchar](50) NOT NULL, + [Personalisation] [nvarchar](max) NULL, + [Status] [int] NOT NULL, + [NotificationId] [nvarchar](100) NULL, + [RetryCount] [int] NULL, + [CreatedAt] [datetimeoffset](7) NOT NULL, + [DeliverAfter] [datetimeoffset](7) NULL, + [SentAt] [datetimeoffset](7) NULL, + [LastAttemptAt] [datetimeoffset](7) NULL, + [ErrorMessage] [nvarchar](max) NULL, + CONSTRAINT [PK_QueueRequests] PRIMARY KEY CLUSTERED +( + [Id] ASC +)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY] +) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY] +GO + +ALTER TABLE [dbo].[QueueRequests] WITH CHECK ADD CONSTRAINT [FK_QueueRequests_RequestStatus] FOREIGN KEY([Status]) +REFERENCES [dbo].[RequestStatus] ([Id]) +GO + +ALTER TABLE [dbo].[QueueRequests] CHECK CONSTRAINT [FK_QueueRequests_RequestStatus] +GO + +ALTER TABLE [dbo].[QueueRequests] WITH CHECK ADD CONSTRAINT [FK_QueueRequests_RequestType] FOREIGN KEY([RequestTypeId]) +REFERENCES [dbo].[RequestType] ([Id]) +GO + +ALTER TABLE [dbo].[QueueRequests] CHECK CONSTRAINT [FK_QueueRequests_RequestType] +GO \ No newline at end of file diff --git a/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Tables/RequestStatus.sql b/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Tables/RequestStatus.sql new file mode 100644 index 000000000..ce9918dc3 --- /dev/null +++ b/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Tables/RequestStatus.sql @@ -0,0 +1,9 @@ +CREATE TABLE [dbo].[RequestStatus]( + [Id] [int] NOT NULL, + [RequestStatus] [nvarchar](20) NOT NULL, + CONSTRAINT [PK_RequestStatus] PRIMARY KEY CLUSTERED +( + [Id] ASC +)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY] +) ON [PRIMARY] +GO \ No newline at end of file diff --git a/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Tables/RequestType.sql b/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Tables/RequestType.sql new file mode 100644 index 000000000..a9be6c049 --- /dev/null +++ b/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Tables/RequestType.sql @@ -0,0 +1,9 @@ +CREATE TABLE [dbo].[RequestType]( + [Id] [int] NOT NULL, + [RequestType] [nvarchar](20) NOT NULL, + CONSTRAINT [PK_RequestType] PRIMARY KEY CLUSTERED +( + [Id] ASC +)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY] +) ON [PRIMARY] +GO diff --git a/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/User-Defined Table Types/QueueRequestTableType.sql b/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/User-Defined Table Types/QueueRequestTableType.sql new file mode 100644 index 000000000..479676b6b --- /dev/null +++ b/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/User-Defined Table Types/QueueRequestTableType.sql @@ -0,0 +1,7 @@ +CREATE TYPE [dbo].[QueueRequestTableType] AS TABLE( + [Recipient] [nvarchar](255) NOT NULL, + [TemplateId] [nvarchar](50) NOT NULL, + [Personalisation] [nvarchar](max) NULL, + [DeliverAfter] [datetimeoffset](7) NULL +) +GO diff --git a/MessageQueueing/LearningHub.Nhs.MessageQueueing/EntityFramework/MessageQueueDbContext.cs b/MessageQueueing/LearningHub.Nhs.MessageQueueing/EntityFramework/MessageQueueDbContext.cs new file mode 100644 index 000000000..d889ebf3f --- /dev/null +++ b/MessageQueueing/LearningHub.Nhs.MessageQueueing/EntityFramework/MessageQueueDbContext.cs @@ -0,0 +1,44 @@ +namespace LearningHub.Nhs.MessageQueueing.EntityFramework +{ + using LearningHub.Nhs.Models.GovNotifyMessaging; + using Microsoft.EntityFrameworkCore; + + /// + /// The Message Queue Db Context. + /// + public class MessageQueueDbContext : DbContext + { + /// + /// The options. + /// + private readonly MessageQueueDbContextOptions options; + + /// + /// Initializes a new instance of the class. + /// + /// The options. + public MessageQueueDbContext(MessageQueueDbContextOptions options) + : base(options.Options) + { + this.options = options; + } + + /// + /// Gets the Options. + /// + public MessageQueueDbContextOptions Options + { + get { return this.options; } + } + + /// + /// Gets or sets the PendingMessageRequests. + /// + public virtual DbSet PendingMessageRequests { get; set; } + + /// + /// Gets or sets the MessageRequestViewModel. + /// + public virtual DbSet MessageRequestViewModel { get; set; } + } +} diff --git a/MessageQueueing/LearningHub.Nhs.MessageQueueing/EntityFramework/MessageQueueDbContextOptions.cs b/MessageQueueing/LearningHub.Nhs.MessageQueueing/EntityFramework/MessageQueueDbContextOptions.cs new file mode 100644 index 000000000..7a6f0d985 --- /dev/null +++ b/MessageQueueing/LearningHub.Nhs.MessageQueueing/EntityFramework/MessageQueueDbContextOptions.cs @@ -0,0 +1,24 @@ +namespace LearningHub.Nhs.MessageQueueing.EntityFramework +{ + using Microsoft.EntityFrameworkCore; + + /// + /// The MessageQueueDbContextOptions. + /// + public class MessageQueueDbContextOptions + { + /// + /// Initializes a new instance of the class. + /// + /// The options. + public MessageQueueDbContextOptions(DbContextOptions options) + { + this.Options = options; + } + + /// + /// Gets the options. + /// + public DbContextOptions Options { get; } + } +} diff --git a/MessageQueueing/LearningHub.Nhs.MessageQueueing/Helpers/DataTableBuilder.cs b/MessageQueueing/LearningHub.Nhs.MessageQueueing/Helpers/DataTableBuilder.cs new file mode 100644 index 000000000..f4e278b94 --- /dev/null +++ b/MessageQueueing/LearningHub.Nhs.MessageQueueing/Helpers/DataTableBuilder.cs @@ -0,0 +1,34 @@ +namespace LearningHub.Nhs.MessageQueueing.Helpers +{ + using System; + using System.Collections.Generic; + using System.Data; + using LearningHub.Nhs.Models.Entities.GovNotifyMessaging; + + /// + /// DataTable Builder. + /// + public static class DataTableBuilder + { + /// + /// ToQueueRequestDataTable. + /// + /// The requests list. + /// The table. + public static DataTable ToQueueRequestDataTable(IEnumerable requests) + { + var table = new DataTable(); + table.Columns.Add("Recipient", typeof(string)); + table.Columns.Add("TemplateId", typeof(string)); + table.Columns.Add("Personalisation", typeof(string)); + table.Columns.Add("DeliverAfter", typeof(DateTimeOffset)); + + foreach (var req in requests) + { + table.Rows.Add(req.Recipient, req.TemplateId, req.Personalisation, req.DeliverAfter); + } + + return table; + } + } +} diff --git a/MessageQueueing/LearningHub.Nhs.MessageQueueing/LearningHub.Nhs.MessageQueueing.csproj b/MessageQueueing/LearningHub.Nhs.MessageQueueing/LearningHub.Nhs.MessageQueueing.csproj new file mode 100644 index 000000000..3537682c0 --- /dev/null +++ b/MessageQueueing/LearningHub.Nhs.MessageQueueing/LearningHub.Nhs.MessageQueueing.csproj @@ -0,0 +1,15 @@ + + + + net8.0 + enable + true + + + + + + + + + diff --git a/MessageQueueing/LearningHub.Nhs.MessageQueueing/Repositories/IMessageQueueRepository.cs b/MessageQueueing/LearningHub.Nhs.MessageQueueing/Repositories/IMessageQueueRepository.cs new file mode 100644 index 000000000..2685e4009 --- /dev/null +++ b/MessageQueueing/LearningHub.Nhs.MessageQueueing/Repositories/IMessageQueueRepository.cs @@ -0,0 +1,66 @@ +namespace LearningHub.Nhs.MessageQueueing.Repositories +{ + using System.Collections.Generic; + using System.Threading.Tasks; + using LearningHub.Nhs.Models.Common; + using LearningHub.Nhs.Models.Entities.GovNotifyMessaging; + using LearningHub.Nhs.Models.GovNotifyMessaging; + + /// + /// The IEmailQueueRepository class. + /// + public interface IMessageQueueRepository + { + /// + /// The QueueMessagesAsync. + /// + /// The emails list. + /// The . + Task QueueMessagesAsync(IEnumerable emails); + + /// + /// The GetPendingEmailsAsync. + /// + /// The . + Task> GetPendingEmailsAsync(); + + /// + /// Marks a message as failed, or queues it for a retry. + /// + /// The response. + /// The . + Task MessageDeliveryFailed(GovNotifyResponse response); + + /// + /// Marks a message as send. + /// + /// The response. + /// The . + Task MessageDeliverySuccess(GovNotifyResponse response); + + /// + /// Save one-off emails. + /// + /// The email request. + /// The . + Task SaveSingleEmailTransactions(SingleEmailRequest request); + + /// + /// The GetPaginatedMessageRequests. + /// + /// offSet count. + /// fetchRows count. + /// sort column. + /// sort direction. + /// filter. + /// The . + Task> GetPaginatedMessageRequests(int? offSet, int? fetchRows, string sortColumn, string sortDirection, string filter); + + /// + /// Get Message Request By Id. + /// + /// id. + /// The . + Task GetMessageRequestById(int id); + } +} diff --git a/MessageQueueing/LearningHub.Nhs.MessageQueueing/Repositories/MessageQueueRepository.cs b/MessageQueueing/LearningHub.Nhs.MessageQueueing/Repositories/MessageQueueRepository.cs new file mode 100644 index 000000000..071e6f364 --- /dev/null +++ b/MessageQueueing/LearningHub.Nhs.MessageQueueing/Repositories/MessageQueueRepository.cs @@ -0,0 +1,136 @@ +namespace LearningHub.Nhs.MessageQueueing.Repositories +{ + using System; + using System.Collections.Generic; + using System.Data; + using System.Linq; + using System.Threading.Tasks; + using AutoMapper; + using LearningHub.Nhs.MessageQueueing.EntityFramework; + using LearningHub.Nhs.MessageQueueing.Helpers; + using LearningHub.Nhs.Models.Common; + using LearningHub.Nhs.Models.Entities.GovNotifyMessaging; + using LearningHub.Nhs.Models.GovNotifyMessaging; + using Microsoft.Data.SqlClient; + using Microsoft.EntityFrameworkCore; + + /// + /// The MessageQueueRepository. + /// + public class MessageQueueRepository : IMessageQueueRepository + { + private readonly MessageQueueDbContext dbContext; + private readonly IMapper mapper; + + /// + /// Initializes a new instance of the class. + /// + /// The context. + /// mapper. + public MessageQueueRepository(MessageQueueDbContext dbContext, IMapper mapper) + { + this.dbContext = dbContext; + this.mapper = mapper; + } + + /// + /// The QueueMessagesAsync. + /// + /// The queue requests. + /// The . + public async Task QueueMessagesAsync(IEnumerable requests) + { + var dataTable = DataTableBuilder.ToQueueRequestDataTable(requests); + var param0 = new SqlParameter("@p0", SqlDbType.Structured) { Value = dataTable, TypeName = "dbo.QueueRequestTableType" }; + await this.dbContext.Database.ExecuteSqlRawAsync("dbo.CreateQueueRequests @p0", param0); + } + + /// + /// The GetPendingEmailsAsync. + /// + /// The . + public async Task> GetPendingEmailsAsync() + { + var result = await this.dbContext.PendingMessageRequests.FromSqlRaw("[dbo].[GetQueueRequests]") + .AsNoTracking().ToListAsync(); + return result; + } + + /// + /// The Update Email request as success. + /// + /// Th response. + /// The . + public async Task MessageDeliverySuccess(GovNotifyResponse response) + { + var param0 = new SqlParameter("@p0", SqlDbType.Int) { Value = response.Id }; + var param1 = new SqlParameter("@p1", SqlDbType.NVarChar) { Value = response.NotificationId }; + await this.dbContext.Database.ExecuteSqlRawAsync("dbo.MessageDeliverySuccess @p0, @p1", param0, param1); + } + + /// + /// The Update Email request as failed. + /// + /// Th response. + /// The . + public async Task MessageDeliveryFailed(GovNotifyResponse response) + { + var param0 = new SqlParameter("@p0", SqlDbType.Int) { Value = response.Id }; + var param1 = new SqlParameter("@p1", SqlDbType.NVarChar) { Value = response.ErrorMessage }; + await this.dbContext.Database.ExecuteSqlRawAsync("dbo.MessageDeliveryFailed @p0, @p1", param0, param1); + } + + /// + /// The Save Single Emails. + /// + /// The request. + /// The . + public async Task SaveSingleEmailTransactions(SingleEmailRequest request) + { + var param0 = new SqlParameter("@p0", SqlDbType.NVarChar) { Value = request.Recipient }; + var param1 = new SqlParameter("@p1", SqlDbType.NVarChar) { Value = request.TemplateId }; + var param2 = new SqlParameter("@p2", SqlDbType.NVarChar) { Value = request.Personalisation == null ? DBNull.Value : request.Personalisation }; + var param3 = new SqlParameter("@p3", SqlDbType.Int) { Value = request.Status }; + var param4 = new SqlParameter("@p4", SqlDbType.NVarChar) { Value = request.ErrorMessage == null ? DBNull.Value : request.ErrorMessage }; + await this.dbContext.Database.ExecuteSqlRawAsync("dbo.SaveSingleEmailTransactions @p0, @p1, @p2, @p3, @p4", param0, param1, param2, param3, param4); + } + + /// + /// The Get Paginated MessageRequests. + /// + /// offset count. + /// fetch rows. + /// sort column. + /// sort direction. + /// filter. + /// The . + public async Task> GetPaginatedMessageRequests(int? offSet, int? fetchRows, string sortColumn, string sortDirection, string filter) + { + var result = new PagedResultSet(); + var param0 = new SqlParameter("@offSet", SqlDbType.Int) { Value = offSet }; + var param1 = new SqlParameter("@fetchRows", SqlDbType.Int) { Value = fetchRows }; + var param2 = new SqlParameter("@sortColumn", SqlDbType.Text) { Value = sortColumn }; + var param3 = new SqlParameter("@sortDirection", SqlDbType.Text) { Value = sortDirection }; + var param4 = new SqlParameter("@filter", SqlDbType.Text) { Value = filter }; + var param5 = new SqlParameter("@totalCount", SqlDbType.Int) { Direction = ParameterDirection.Output }; + var requests = await this.dbContext.MessageRequestViewModel.FromSqlRaw("dbo.GetAllMessageRequests @offSet,@fetchRows,@sortColumn,@sortDirection,@filter,@totalCount output ", param0, param1, param2, param3, param4, param5) + .AsNoTracking().ToListAsync(); + result.TotalItemCount = (int)param5.Value; + result.Items = mapper.Map>(requests); + return result; + } + + /// + /// Get Message Request By Id. + /// + /// id. + /// The . + public async Task GetMessageRequestById(int id) + { + var param0 = new SqlParameter("@id", SqlDbType.Int) { Value = id }; + var result = await this.dbContext.MessageRequestViewModel.FromSqlRaw("dbo.GetMessageRequestById @id", param0).AsNoTracking().ToListAsync(); + MessageRequestViewModel messageRequestViewModel = result.AsEnumerable().FirstOrDefault(); + return messageRequestViewModel; + } + } +} diff --git a/MessageQueueing/LearningHub.Nhs.MessageQueueing/Startup.cs b/MessageQueueing/LearningHub.Nhs.MessageQueueing/Startup.cs new file mode 100644 index 000000000..e3cfa65d1 --- /dev/null +++ b/MessageQueueing/LearningHub.Nhs.MessageQueueing/Startup.cs @@ -0,0 +1,32 @@ +namespace LearningHub.Nhs.MessageQueueing +{ + using LearningHub.Nhs.MessageQueueing.EntityFramework; + using LearningHub.Nhs.MessageQueueing.Repositories; + using Microsoft.EntityFrameworkCore; + using Microsoft.Extensions.Configuration; + using Microsoft.Extensions.DependencyInjection; + + /// + /// Contains methods to configure the project to be called in an API startup class. + /// + public static class Startup + { + /// + /// Registers the implementations in the project with ASP.NET DI. + /// + /// The IServiceCollection. + /// The IConfiguration. + public static void AddQueueingRepositories(this IServiceCollection services, IConfiguration configuration) + { + var dbContextOptions = new DbContextOptionsBuilder() + .UseSqlServer(configuration.GetConnectionString("GovNotifyMessageDbConnection"), providerOptions => { providerOptions.EnableRetryOnFailure(3); }) + .Options; + + services.AddSingleton(dbContextOptions); + services.AddSingleton(); + + services.AddDbContext(); + services.AddScoped(); + } + } +} diff --git a/MessagingService/LearningHub.Nhs.MessagingService/Interfaces/IGovNotifyService.cs b/MessagingService/LearningHub.Nhs.MessagingService/Interfaces/IGovNotifyService.cs new file mode 100644 index 000000000..588d766e7 --- /dev/null +++ b/MessagingService/LearningHub.Nhs.MessagingService/Interfaces/IGovNotifyService.cs @@ -0,0 +1,30 @@ +namespace LearningHub.Nhs.MessagingService.Interfaces +{ + using System.Collections.Generic; + using System.Threading.Tasks; + using LearningHub.Nhs.Models.GovNotifyMessaging; + + /// + /// IMessageServices. + /// + public interface IGovNotifyService + { + /// + /// Send EmailAsync. + /// + /// email. + /// templateId. + /// personalisation. + /// The . + Task SendEmailAsync(string email, string templateId, Dictionary personalisation); + + /// + /// Send SmsAsync. + /// + /// phoneNumber. + /// templateId. + /// personalisation. + /// The . + Task SendSmsAsync(string phoneNumber, string templateId, Dictionary personalisation); + } +} diff --git a/MessagingService/LearningHub.Nhs.MessagingService/LearningHub.Nhs.MessagingService.csproj b/MessagingService/LearningHub.Nhs.MessagingService/LearningHub.Nhs.MessagingService.csproj new file mode 100644 index 000000000..2f0e9d58b --- /dev/null +++ b/MessagingService/LearningHub.Nhs.MessagingService/LearningHub.Nhs.MessagingService.csproj @@ -0,0 +1,17 @@ + + + + net8.0 + enable + true + + + + + + + + + + + diff --git a/MessagingService/LearningHub.Nhs.MessagingService/MessagingOptions/MessagingServiceOptions.cs b/MessagingService/LearningHub.Nhs.MessagingService/MessagingOptions/MessagingServiceOptions.cs new file mode 100644 index 000000000..b4b395f31 --- /dev/null +++ b/MessagingService/LearningHub.Nhs.MessagingService/MessagingOptions/MessagingServiceOptions.cs @@ -0,0 +1,21 @@ +namespace LearningHub.Nhs.MessagingService.Model +{ + /// + /// MessagingServiceModel. + /// + public class MessagingServiceOptions + { + /// + /// Initializes a new instance of the class. + /// + public MessagingServiceOptions() + { + // Current = this; + } + + /// + /// Gets or Sets ApiKey. + /// + public string GovNotifyApiKey { get; set; } = string.Empty; + } +} diff --git a/MessagingService/LearningHub.Nhs.MessagingService/Services/GovNotifyService.cs b/MessagingService/LearningHub.Nhs.MessagingService/Services/GovNotifyService.cs new file mode 100644 index 000000000..e7eeef4f7 --- /dev/null +++ b/MessagingService/LearningHub.Nhs.MessagingService/Services/GovNotifyService.cs @@ -0,0 +1,141 @@ +namespace LearningHub.Nhs.MessagingService.Services +{ + using System; + using System.Collections.Generic; + using System.Text.Json; + using System.Threading.Tasks; + using LearningHub.Nhs.MessagingService.Interfaces; + using LearningHub.Nhs.MessagingService.Model; + using LearningHub.Nhs.Models.GovNotifyMessaging; + using Microsoft.Extensions.Options; + using Notify.Client; + using Notify.Exceptions; + + /// + /// GovNotify Service class. + /// + public class GovNotifyService : IGovNotifyService + { + private readonly NotificationClient client; + + /// + /// Initializes a new instance of the class. + /// + /// The Messaging Service Options. + public GovNotifyService(IOptions options) + { + this.client = new NotificationClient(options.Value.GovNotifyApiKey); + } + + /// + /// Sends an email via the UK Gov.Notify service. + /// + /// The recipient's email address. + /// The ID of the Gov.Notify template to be used for the email. + /// + /// A dictionary containing key-value pairs for personalising the email template. + /// Keys should match the placeholders in the Gov.Notify template. + /// + /// The . + public async Task SendEmailAsync(string email, string templateId, Dictionary personalisation) + { + try + { + var normalisedPersonlisation = new Dictionary(); + if (personalisation != null) + { + foreach (var item in personalisation) + { + if (item.Value is JsonElement element) + { + normalisedPersonlisation[item.Key] = element.ToString(); + } + else + { + normalisedPersonlisation[item.Key] = item.Value; + } + } + } + + var response = await this.client.SendEmailAsync(email, templateId, normalisedPersonlisation); + return new GovNotifyResponse + { + IsSuccess = true, + NotificationId = response.id, + }; + } + catch (NotifyClientException ex) + { + return new GovNotifyResponse + { + IsSuccess = false, + ErrorMessage = ex.Message, + ////Retry = true, + }; + } + catch (Exception ex) + { + return new GovNotifyResponse + { + IsSuccess = false, + ErrorMessage = ex.Message, + ////Retry = true, + }; + } + } + + /// + /// Sends an SMS via the UK Gov.Notify service. + /// + /// The recipient's phone number. + /// The ID of the Gov.Notify template to be used for the SMS. + /// + /// A dictionary containing key-value pairs for personalising the SMS template. + /// Keys should match the placeholders in the Gov.Notify template. + /// + /// The . + public async Task SendSmsAsync(string phoneNumber, string templateId, Dictionary personalisation) + { + try + { + var normalisedPersonlisation = new Dictionary(); + foreach (var item in personalisation) + { + if (item.Value is JsonElement element) + { + normalisedPersonlisation[item.Key] = element.ToString(); + } + else + { + normalisedPersonlisation[item.Key] = item.Value; + } + } + + var response = await this.client.SendSmsAsync(phoneNumber, templateId, normalisedPersonlisation); + return new GovNotifyResponse + { + IsSuccess = true, + NotificationId = response.id, + }; + } + catch (NotifyClientException ex) + { + return new GovNotifyResponse + { + IsSuccess = false, + ErrorMessage = ex.Message, + ////Retry = true, + }; + } + catch (Exception ex) + { + return new GovNotifyResponse + { + IsSuccess = false, + ErrorMessage = ex.Message, + ////Retry = true, + }; + } + } + } +} diff --git a/MessagingService/LearningHub.Nhs.MessagingService/Startup.cs b/MessagingService/LearningHub.Nhs.MessagingService/Startup.cs new file mode 100644 index 000000000..30359eb08 --- /dev/null +++ b/MessagingService/LearningHub.Nhs.MessagingService/Startup.cs @@ -0,0 +1,25 @@ +namespace LearningHub.Nhs.MessagingService +{ + using LearningHub.Nhs.MessagingService.Interfaces; + using LearningHub.Nhs.MessagingService.Model; + using LearningHub.Nhs.MessagingService.Services; + using Microsoft.Extensions.Configuration; + using Microsoft.Extensions.DependencyInjection; + + /// + /// Contains methods to configure the project to be called in an API startup class. + /// + public static class Startup + { + /// + /// Registers the implementations in the project with ASP.NET DI. + /// + /// The IServiceCollection. + /// The IConfiguration. + public static void AddMessagingServices(this IServiceCollection services, IConfiguration configuration) + { + services.Configure(configuration.GetSection("GovNotify")); + services.AddScoped(); + } + } +} diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Models/LearningHub.Nhs.OpenApi.Models.csproj b/OpenAPI/LearningHub.Nhs.OpenApi.Models/LearningHub.Nhs.OpenApi.Models.csproj index f93a18aa5..ada20d07f 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi.Models/LearningHub.Nhs.OpenApi.Models.csproj +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Models/LearningHub.Nhs.OpenApi.Models.csproj @@ -17,7 +17,7 @@ - + diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Repositories.Interface/LearningHub.Nhs.OpenApi.Repositories.Interface.csproj b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories.Interface/LearningHub.Nhs.OpenApi.Repositories.Interface.csproj index 043795e81..dac1e45d6 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi.Repositories.Interface/LearningHub.Nhs.OpenApi.Repositories.Interface.csproj +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories.Interface/LearningHub.Nhs.OpenApi.Repositories.Interface.csproj @@ -17,7 +17,7 @@ - + diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Repositories.Interface/Repositories/Hierarchy/ICatalogueAccessRequestRepository.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories.Interface/Repositories/Hierarchy/ICatalogueAccessRequestRepository.cs index 05fa86695..f295950fe 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi.Repositories.Interface/Repositories/Hierarchy/ICatalogueAccessRequestRepository.cs +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories.Interface/Repositories/Hierarchy/ICatalogueAccessRequestRepository.cs @@ -1,8 +1,10 @@ namespace LearningHub.Nhs.OpenApi.Repositories.Interface.Repositories.Hierarchy { + using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using LearningHub.Nhs.Models.Entities.Hierarchy; + using LearningHub.Nhs.Models.Hierarchy; /// /// The ICatalogueAccessRequestRepository interface. @@ -42,5 +44,19 @@ Task CreateCatalogueAccessRequestAsync( int roleId, string catalogueManageAccessUrl, string accessType); + + /// + /// The GetCatalogueAdminDetailsAsync. + /// + /// The currentUserId. + /// The reference. + /// The roleId. + /// The accessType. + /// The task. + Task> GetCatalogueAdminDetailsAsync( + int currentUserId, + string reference, + int roleId, + string accessType); } } diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Repositories/EntityFramework/LearningHubDbContext.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories/EntityFramework/LearningHubDbContext.cs index 80ec18a5c..06a7f2d2a 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi.Repositories/EntityFramework/LearningHubDbContext.cs +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories/EntityFramework/LearningHubDbContext.cs @@ -21,6 +21,7 @@ namespace LearningHub.Nhs.OpenApi.Repositories.EntityFramework using LearningHub.Nhs.Models.Resource.ResourceDisplay; using LearningHub.Nhs.Models.User; using Microsoft.EntityFrameworkCore; + using CatalogueAdminViewModel = LearningHub.Nhs.Models.Hierarchy.CatalogueAdminViewModel; using Event = LearningHub.Nhs.Models.Entities.Analytics.Event; /// @@ -407,6 +408,11 @@ public LearningHubDbContextOptions Options public virtual DbSet NodeViewModel { get; set; } + /// + /// Gets or sets the CatalogueAdminViewModel. + /// + public virtual DbSet CatalogueAdminViewModel { get; set; } + /// /// Gets or sets the NodePathNodeViewModel. /// diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Repositories/LearningHub.Nhs.OpenApi.Repositories.csproj b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories/LearningHub.Nhs.OpenApi.Repositories.csproj index 29d8422f7..88adf65de 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi.Repositories/LearningHub.Nhs.OpenApi.Repositories.csproj +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories/LearningHub.Nhs.OpenApi.Repositories.csproj @@ -24,7 +24,7 @@ - + diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Repositories/Repositories/Hierarchy/CatalogueAccessRequestRepository.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories/Repositories/Hierarchy/CatalogueAccessRequestRepository.cs index a3b5832ba..2cef77f52 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi.Repositories/Repositories/Hierarchy/CatalogueAccessRequestRepository.cs +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories/Repositories/Hierarchy/CatalogueAccessRequestRepository.cs @@ -1,10 +1,12 @@ namespace LearningHub.Nhs.OpenApi.Repositories.Repositories.Hierarchy { using System; + using System.Collections.Generic; using System.Data; using System.Linq; using System.Threading.Tasks; using LearningHub.Nhs.Models.Entities.Hierarchy; + using LearningHub.Nhs.Models.Hierarchy; using LearningHub.Nhs.OpenApi.Repositories.EntityFramework; using LearningHub.Nhs.OpenApi.Repositories.Interface.Repositories; using LearningHub.Nhs.OpenApi.Repositories.Interface.Repositories.Hierarchy; @@ -75,5 +77,36 @@ public async Task CreateCatalogueAccessRequestAsync( var param6 = new SqlParameter("@p6", SqlDbType.Int) { Value = roleId }; await DbContext.Database.ExecuteSqlRawAsync("exec [hierarchy].[CatalogueAccessRequestCreate] @p0, @p1, @p2, @p3, @p4, @p5, @p6", param0, param1, param2, param3, param4, param5, param6); } + + /// + /// The GetCatalogueAdminDetailsAsync. + /// + /// The currentUserId. + /// The reference. + /// The roleId. + /// The accessType. + /// The task. + public async Task> GetCatalogueAdminDetailsAsync( + int currentUserId, + string reference, + int roleId, + string accessType) + { + try + { + var param0 = new SqlParameter("@p0", SqlDbType.Int) { Value = currentUserId }; + var param1 = new SqlParameter("@p1", SqlDbType.NVarChar) { Value = reference }; + var param2 = new SqlParameter("@p2", SqlDbType.Int) { Value = TimezoneOffsetManager.UserTimezoneOffset ?? (object)DBNull.Value }; + var param3 = new SqlParameter("@p3", SqlDbType.NVarChar) { Value = accessType }; + var param4 = new SqlParameter("@p4", SqlDbType.Int) { Value = roleId }; + ////await DbContext.Database.ExecuteSqlRawAsync("exec [hierarchy].[GetCatalogueAdminDetails] @p0, @p1, @p2, @p3, @p4", param0, param1, param2, param3, param4); + var retVal = await this.DbContext.CatalogueAdminViewModel.FromSqlRaw("hierarchy.GetCatalogueAdminDetails @p0, @p1, @p2, @p3, @p4", param0, param1, param2, param3, param4).AsNoTracking().ToListAsync(); + return retVal; + } + catch(Exception ex) + { + return null; + } + } } } diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/LearningHub.Nhs.OpenApi.Services.Interface.csproj b/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/LearningHub.Nhs.OpenApi.Services.Interface.csproj index 4f1227545..dd694a31d 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/LearningHub.Nhs.OpenApi.Services.Interface.csproj +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/LearningHub.Nhs.OpenApi.Services.Interface.csproj @@ -17,7 +17,7 @@ - + diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/Services/ICatalogueService.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/Services/ICatalogueService.cs index 0f01277d1..2983e0c42 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/Services/ICatalogueService.cs +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/Services/ICatalogueService.cs @@ -81,10 +81,11 @@ public interface ICatalogueService /// /// The currentUserId. /// The reference. + /// The catalogueName. /// The view model. /// The accessType. /// The bool. - Task RequestAccessAsync(int currentUserId, string reference, CatalogueAccessRequestViewModel vm, string accessType); + Task RequestAccessAsync(int currentUserId, string reference,string catalogueName, CatalogueAccessRequestViewModel vm, string accessType); /// /// The InviteUserAsync. diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/Services/Messaging/IEmailTemplateService.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/Services/Messaging/IEmailTemplateService.cs index 9f676fcda..3bb5a2090 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/Services/Messaging/IEmailTemplateService.cs +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/Services/Messaging/IEmailTemplateService.cs @@ -7,6 +7,7 @@ namespace LearningHub.Nhs.OpenApi.Services.Interface.Services.Messaging using System.Collections.Generic; using LearningHub.Nhs.Models.Email; using LearningHub.Nhs.Models.Email.Models; + using LearningHub.Nhs.Models.Entities.Messaging; /// /// The IEmailTemplateService. @@ -64,5 +65,12 @@ public interface IEmailTemplateService /// The email model. /// The subject and body. EmailDetails GetReportProcessed(SendEmailModel emailModel); + + /// + /// The GetEmailTemplate. + /// + /// <The email template type id. + /// The template. + EmailTemplate GetEmailTemplateById(int emailTemplateTypeId); } } diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/Services/Messaging/IGovMessageService.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/Services/Messaging/IGovMessageService.cs new file mode 100644 index 000000000..4dd4a0969 --- /dev/null +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/Services/Messaging/IGovMessageService.cs @@ -0,0 +1,41 @@ +namespace LearningHub.Nhs.OpenApi.Services.Interface.Services.Messaging +{ + using System; + using System.Threading.Tasks; + using LearningHub.Nhs.Models.Common; + using LearningHub.Nhs.Models.GovNotifyMessaging; + + /// + /// The IGovMessageService interface. + /// + public interface IGovMessageService + { + /// + /// SendEmailAsync. + /// + /// the request. + /// The response. + /// The exception. + Task SendEmailAsync(EmailRequest request); + + /// + /// To queue the MessageRequests. + /// + /// The QueueRequestList. + /// The . + Task QueueRequestsAsync(QueueMessageList request); + + /// + /// Get Message Requests. + /// + /// The . + Task> GetMessageRequests(int page, int pageSize, string sortColumn, string sortDirection, string filter); + + /// + /// Get Message request by Id + /// + /// + /// The . + Task GetMessageRequestById(int id); + } +} diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Services/LearningHub.Nhs.OpenApi.Services.csproj b/OpenAPI/LearningHub.Nhs.OpenApi.Services/LearningHub.Nhs.OpenApi.Services.csproj index 64b868475..ed69e8ba0 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi.Services/LearningHub.Nhs.OpenApi.Services.csproj +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Services/LearningHub.Nhs.OpenApi.Services.csproj @@ -16,11 +16,13 @@ - - - - - + + + + + + + @@ -31,7 +33,7 @@ - + diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/CatalogueService.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/CatalogueService.cs index 71696c3dd..ffe5c4a09 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/CatalogueService.cs +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/CatalogueService.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; using System.Linq; + using System.Runtime.ConstrainedExecution; using System.Threading.Tasks; using AutoMapper; using LearningHub.Nhs.Models.Catalogue; @@ -14,6 +15,7 @@ using LearningHub.Nhs.Models.Entities.Hierarchy; using LearningHub.Nhs.Models.Entities.Resource; using LearningHub.Nhs.Models.Enums; + using LearningHub.Nhs.Models.GovNotifyMessaging; using LearningHub.Nhs.Models.Resource; using LearningHub.Nhs.Models.Search; using LearningHub.Nhs.Models.Validation; @@ -56,6 +58,8 @@ public class CatalogueService : ICatalogueService private readonly INotificationSenderService notificationSenderService; private readonly ITimezoneOffsetManager timezoneOffsetManager; private readonly ICategoryService categoryService; + private readonly IGovMessageService govMessageService; + private readonly IEmailTemplateService emailTemplateService; /// /// Initializes a new instance of the class. @@ -64,20 +68,52 @@ public class CatalogueService : ICatalogueService /// /// The . /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - public CatalogueService(ICatalogueRepository catalogueRepository, ICategoryService categoryService, INodeRepository nodeRepository, IUserUserGroupRepository userUserGroupRepository, IMapper mapper, IOptions findwiseConfig, IOptions learningHubConfig, ICatalogueNodeVersionRepository catalogueNodeVersionRepository, INodeResourceRepository nodeResourceRepository, IResourceVersionRepository resourceVersionRepository, IRoleUserGroupRepository roleUserGroupRepository, IProviderService providerService, ICatalogueAccessRequestRepository catalogueAccessRequestRepository, IUserRepository userRepository, IUserProfileRepository userProfileRepository, IEmailSenderService emailSenderService, IBookmarkRepository bookmarkRepository,INodeActivityRepository nodeActivityRepository, INotificationSenderService notificationSenderService, ITimezoneOffsetManager timezoneOffsetManager) + /// + /// mapper. + /// catalogueNodeVersionRepository. + /// nodeResourceRepository. + /// resourceVersionRepository. + /// roleUserGroupRepository. + /// providerService. + /// catalogueAccessRequestRepository. + /// userRepository. + /// userProfileRepository. + /// emailSenderService. + /// bookmarkRepository. + /// nodeActivityRepository. + /// findwiseApiFacade. + /// nodeRepository. + /// userUserGroupRepository. + /// findwiseConfig. + /// learningHubConfig. + /// notificationSenderService. + /// timezoneOffsetManager. + /// govMessageService. + /// emailTemplateService. + public CatalogueService( + ICatalogueRepository catalogueRepository, + ICategoryService @object, + INodeRepository nodeRepository, + IUserUserGroupRepository userUserGroupRepository, + IMapper mapper, + IOptions findwiseConfig, + IOptions learningHubConfig, + ICatalogueNodeVersionRepository catalogueNodeVersionRepository, + INodeResourceRepository nodeResourceRepository, + IResourceVersionRepository resourceVersionRepository, + IRoleUserGroupRepository roleUserGroupRepository, + IProviderService providerService, + ICatalogueAccessRequestRepository catalogueAccessRequestRepository, + IUserRepository userRepository, + IUserProfileRepository userProfileRepository, + IEmailSenderService emailSenderService, + IBookmarkRepository bookmarkRepository, + INodeActivityRepository nodeActivityRepository, + INotificationSenderService notificationSenderService, + ITimezoneOffsetManager timezoneOffsetManager, + ICategoryService categoryService, + IGovMessageService govMessageService, + IEmailTemplateService emailTemplateService) { this.catalogueRepository = catalogueRepository; this.categoryService = categoryService; @@ -99,6 +135,8 @@ public CatalogueService(ICatalogueRepository catalogueRepository, ICategoryServi this.findwiseConfig = findwiseConfig.Value; this.timezoneOffsetManager = timezoneOffsetManager; this.notificationSenderService = notificationSenderService; + this.govMessageService = govMessageService; + this.emailTemplateService = emailTemplateService; } /// @@ -392,19 +430,51 @@ public RestrictedCatalogueSummaryViewModel GetRestrictedCatalogueSummary(int cat /// /// The currentUserId. /// The reference. + /// The catalogueName. /// The view model. /// The accessType. /// The bool. - public async Task RequestAccessAsync(int currentUserId, string reference, CatalogueAccessRequestViewModel vm, string accessType) + public async Task RequestAccessAsync(int currentUserId, string reference, string catalogueName, CatalogueAccessRequestViewModel vm, string accessType) { - await this.catalogueAccessRequestRepository.CreateCatalogueAccessRequestAsync( - currentUserId, - reference, - vm.Message, - vm.RoleId, - this.learningHubConfig.BaseUrl + "Catalogue/Manage/" + reference, - accessType); + var emailTemplate = this.emailTemplateService.GetEmailTemplateById((int)(accessType == "access" ? EmailTemplates.CatalogueAccessRequest : EmailTemplates.CataloguePermissionRequest)); + + var catalogueAdmin = await this.catalogueAccessRequestRepository.GetCatalogueAdminDetailsAsync(currentUserId, reference, vm.RoleId, accessType); + + var queueMessages = catalogueAdmin + .Where(admin => !string.IsNullOrEmpty(admin.EmailAddress)) + .Select(admin => new QueueMessage + { + Recipient = admin.EmailAddress, + TemplateId = emailTemplate.TemplateId, + Personalisation = new Dictionary + { + ["catalogue admin name"] = admin.FirstName, + ["name"] = vm.UserFullName, + ["email"] = vm.EmailAddress, + ["catalogue name"] = catalogueName, + ["message text"] = vm.Message, + ["Review request url"] = this.learningHubConfig.BaseUrl + "Catalogue/Manage/" + reference, + }, + }) + .ToList(); + + if (queueMessages.Count > 0) + { + var queueMessageList = new QueueMessageList + { + Messages = queueMessages, + }; + await this.govMessageService.QueueRequestsAsync(queueMessageList); + } + + await this.catalogueAccessRequestRepository.CreateCatalogueAccessRequestAsync( + currentUserId, + reference, + vm.Message, + vm.RoleId, + this.learningHubConfig.BaseUrl + "Catalogue/Manage/" + reference, + accessType); return true; } @@ -419,24 +489,40 @@ public async Task InviteUserAsync(int currentUserId, RestrictedCatalogueIn var catalogue = this.catalogueNodeVersionRepository.GetBasicCatalogue(vm.CatalogueNodeId); var user = await this.userProfileRepository.GetByIdAsync(currentUserId); var invitedUser = await this.userProfileRepository.GetByEmailAddressAsync(vm.EmailAddress); - var greeting = "Hi there"; - if (invitedUser != null) + ////var greeting = "Hi there"; + ////if (invitedUser != null) + ////{ + //// greeting = $"Dear {invitedUser.FirstName}"; + ////} + + ////var emailModel = new SendEmailModel( + //// new CatalogueAccessInviteEmailModel + //// { + //// CatalogueName = catalogue.Name, + //// CatalogueUrl = $"{this.learningHubConfig.BaseUrl}Catalogue/{catalogue.Url}", + //// AdminFullName = $"{user.FirstName} {user.LastName}", + //// CreateAccountUrl = $"{this.learningHubConfig.BaseUrl}Registration/create-an-account", + //// Greeting = greeting, + //// }); + ////emailModel.EmailAddress = vm.EmailAddress; + ////await this.emailSenderService.SendAccessRequestInviteEmail(currentUserId, emailModel); + + var emailTemplate = this.emailTemplateService.GetEmailTemplateById((int)EmailTemplates.CatalogueAccessInvitation); + + var personalisation = new Dictionary(); + personalisation["name"] = user.FirstName; + personalisation["catalogue name"] = catalogue.Name; + personalisation["catalogue name url"] = $"{this.learningHubConfig.BaseUrl}Catalogue/{catalogue.Url}"; + + var emailRequest = new EmailRequest { - greeting = $"Dear {invitedUser.FirstName}"; - } + Recipient = vm.EmailAddress, + TemplateId = emailTemplate.TemplateId, + Personalisation = personalisation, + }; - var emailModel = new SendEmailModel( - new CatalogueAccessInviteEmailModel - { - CatalogueName = catalogue.Name, - CatalogueUrl = $"{this.learningHubConfig.BaseUrl}Catalogue/{catalogue.Url}", - AdminFullName = $"{user.FirstName} {user.LastName}", - CreateAccountUrl = $"{this.learningHubConfig.BaseUrl}Registration/create-an-account", - Greeting = greeting, - }); - emailModel.EmailAddress = vm.EmailAddress; + await this.govMessageService.SendEmailAsync(emailRequest); - await this.emailSenderService.SendAccessRequestInviteEmail(currentUserId, emailModel); return true; } @@ -577,7 +663,6 @@ public async Task CreateCatalogueAsync(int userId, CreatedId = catalogueNodeVersionId, }; } - /// /// The AddCategoryToCatalogueAsync. /// @@ -817,6 +902,7 @@ public async Task ShowCatalogueAsync(int userId, in return new LearningHubValidationResult(true); } + /// /// The ValidateForRestrictedAccess. /// @@ -1014,14 +1100,33 @@ await this.notificationSenderService.SendCatalogueAccessRequestRejectedNotificat $"{this.learningHubConfig.BaseUrl}Catalogue/{catalogue.Url}", responseMessage, car.UserId); - await this.emailSenderService.SendRequestAccessFailureEmail(userId, new SendEmailModel(new CatalogueAccessRequestFailureEmailModel + + ////await this.emailSenderService.SendRequestAccessFailureEmail(userId, new SendEmailModel(new CatalogueAccessRequestFailureEmailModel + ////{ + //// UserFirstName = car.UserProfile.FirstName, + //// CatalogueName = catalogue.Name, + //// RejectionReason = responseMessage, + //// CatalogueUrl = this.learningHubConfig.BaseUrl + "Catalogue/" + catalogue.Url, + ////}) + ////{ EmailAddress = car.EmailAddress }); + + var emailTemplate = this.emailTemplateService.GetEmailTemplateById((int)EmailTemplates.CatalogueAccessRequestFailure); + + var personalisation = new Dictionary(); + personalisation["name"] = car.UserProfile.FirstName; + personalisation["catalogue name"] = catalogue.Name; + personalisation["catalogue name url"] = $"{this.learningHubConfig.BaseUrl}Catalogue/{catalogue.Url}"; + personalisation["reason"] = responseMessage; + + var emailRequest = new EmailRequest { - UserFirstName = car.UserProfile.FirstName, - CatalogueName = catalogue.Name, - RejectionReason = responseMessage, - CatalogueUrl = this.learningHubConfig.BaseUrl + "Catalogue/" + catalogue.Url, - }) - { EmailAddress = car.EmailAddress }); + Recipient = car.EmailAddress, + TemplateId = emailTemplate.TemplateId, + Personalisation = personalisation, + }; + + await this.govMessageService.SendEmailAsync(emailRequest); + return new LearningHubValidationResult(true); } @@ -1109,13 +1214,31 @@ await this.notificationSenderService.SendCatalogueAccessRequestAcceptedNotificat catalogue.Name, $"{this.learningHubConfig.BaseUrl}Catalogue/{catalogue.Url}", catalogueAccessRequest.UserId); - await this.emailSenderService.SendRequestAccessSuccessEmail(userId, new SendEmailModel(new CatalogueAccessRequestSuccessEmailModel + + var emailTemplate = this.emailTemplateService.GetEmailTemplateById((int)EmailTemplates.CatalogueAccessRequestSuccess); + + var personalisation = new Dictionary(); + personalisation["name"] = catalogueAccessRequest.UserProfile.FirstName; + personalisation["catalogue name"] = catalogue.Name; + personalisation["catalogue name url"] = $"{this.learningHubConfig.BaseUrl}Catalogue/{catalogue.Url}"; + + var emailRequest = new EmailRequest { - UserFirstName = catalogueAccessRequest.UserProfile.FirstName, - CatalogueName = catalogue.Name, - CatalogueUrl = $"{this.learningHubConfig.BaseUrl}Catalogue/{catalogue.Url}", - }) - { EmailAddress = catalogueAccessRequest.EmailAddress }); + Recipient = catalogueAccessRequest.EmailAddress, + TemplateId = emailTemplate.TemplateId, + Personalisation = personalisation, + }; + + await this.govMessageService.SendEmailAsync(emailRequest); + + ////await this.emailSenderService.SendRequestAccessSuccessEmail(userId, new SendEmailModel(new CatalogueAccessRequestSuccessEmailModel + ////{ + //// UserFirstName = catalogueAccessRequest.UserProfile.FirstName, + //// CatalogueName = catalogue.Name, + //// CatalogueUrl = $"{this.learningHubConfig.BaseUrl}Catalogue/{catalogue.Url}", + ////}) + ////{ EmailAddress = catalogueAccessRequest.EmailAddress }); + return new LearningHubValidationResult(true) { CreatedId = uugId }; } diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/Messaging/EmailTemplateService.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/Messaging/EmailTemplateService.cs index ca048f34a..ea9510b3e 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/Messaging/EmailTemplateService.cs +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/Messaging/EmailTemplateService.cs @@ -9,6 +9,7 @@ using LearningHub.Nhs.OpenApi.Models.ViewModels; using LearningHub.Nhs.OpenApi.Repositories.Interface.Repositories.Messaging; using LearningHub.Nhs.OpenApi.Services.Interface.Services.Messaging; + using EmailTemplate = Nhs.Models.Entities.Messaging.EmailTemplate; /// /// The EmailTemplateService. @@ -233,6 +234,16 @@ public EmailDetails GetEmailVerificationEmail(SendEmailModel + /// The GetEmailTemplate. + /// + /// The email template type id. + /// The template. + public EmailTemplate GetEmailTemplateById(int emailTemplateTypeId) + { + return this.emailTemplateRepository.GetTemplate(emailTemplateTypeId); + } + private string Replace(string str, Dictionary replacements) { return replacements.Aggregate( diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/Messaging/GovMessageService.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/Messaging/GovMessageService.cs new file mode 100644 index 000000000..77328c256 --- /dev/null +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/Messaging/GovMessageService.cs @@ -0,0 +1,129 @@ +namespace LearningHub.Nhs.OpenApi.Services.Services.Messaging +{ + using System; + using System.Linq; + using System.Threading.Tasks; + using AutoMapper; + using LearningHub.Nhs.MessageQueueing.Repositories; + using LearningHub.Nhs.MessagingService.Interfaces; + using LearningHub.Nhs.Models.Common; + using LearningHub.Nhs.Models.Entities.GovNotifyMessaging; + using LearningHub.Nhs.Models.Entities.Messaging; + using LearningHub.Nhs.Models.Enums.GovNotifyMessaging; + using LearningHub.Nhs.Models.GovNotifyMessaging; + using LearningHub.Nhs.OpenApi.Services.Interface.Services.Messaging; + using Microsoft.Extensions.Logging; + using Newtonsoft.Json; + + /// + /// The GOVMessageService class. + /// + public class GovMessageService : BaseService, IGovMessageService + { + private readonly IMessageQueueRepository messageQueueRepository; + private readonly IGovNotifyService messageService; + private readonly IMapper mapper; + + /// + /// Initializes a new instance of the class. + /// + /// The logger. + /// The message repository. + /// The message Service. + /// mapper. + public GovMessageService( + ILogger logger, + IMessageQueueRepository messageQueueRepository, + IGovNotifyService messageService, + IMapper mapper) + : base(logger) + { + this.messageQueueRepository = messageQueueRepository; + this.messageService = messageService; + this.mapper = mapper; + } + + /// + /// SendEmailAsync + /// + /// the request. + /// The response. + /// The exception. + public async Task SendEmailAsync(EmailRequest request) + { + var response = new GovNotifyResponse(); + + if (string.IsNullOrWhiteSpace(request.Recipient) || string.IsNullOrWhiteSpace(request.TemplateId)) + { + response.IsSuccess = false; + response.ErrorMessage = "Email and template ID are required"; + return response; + } + + response = await this.messageService.SendEmailAsync(request.Recipient, request.TemplateId, request.Personalisation); + + if (response != null) + { + if (request.Id == null || request.Id <= 0) + { + var emailRequest = new SingleEmailRequest + { + Recipient = request.Recipient, + TemplateId = request.TemplateId, + Personalisation = request.Personalisation != null ? JsonConvert.SerializeObject(request.Personalisation.ToDictionary(kvp => kvp.Key, kvp => kvp.Value?.ToString())) : null, + Status = response.IsSuccess == true ? RequestStatusEnum.Sent : RequestStatusEnum.Failed, + ErrorMessage = response.ErrorMessage, + }; + await this.messageQueueRepository.SaveSingleEmailTransactions(emailRequest); + } + } + + return response; + } + + /// + /// To queue the MessageRequests. + /// + /// The QueueRequestList. + /// The . + public async Task QueueRequestsAsync(QueueMessageList request) + { + if (request?.Messages == null || !request.Messages.Any()) + { + throw new ArgumentException("At least one email must be provided in the request."); + } + + var requests = request.Messages.Select(q => new QueueRequests + { + Recipient = q.Recipient, + TemplateId = q.TemplateId, + Personalisation = q.Personalisation != null ? JsonConvert.SerializeObject(q.Personalisation) : null, + DeliverAfter = q.DeliverAfter ?? null, + }); + + await this.messageQueueRepository.QueueMessagesAsync(requests); + } + + /// + /// Get paginated Message Requests. + /// + /// The . + public async Task> GetMessageRequests(int page, int pageSize, string sortColumn, string sortDirection, string filter) + { + int? offset = (page - 1) * pageSize; + var result = await this.messageQueueRepository.GetPaginatedMessageRequests(offset, pageSize, sortColumn, sortDirection, filter); + return result; + } + + /// + /// Get message request details by Id. + /// + /// + /// The . + public async Task GetMessageRequestById(int id) + { + var result = await this.messageQueueRepository.GetMessageRequestById(id); + return result; + } + } +} diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/SecurityService.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/SecurityService.cs index 1f87cdc17..58d7e0436 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/SecurityService.cs +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/SecurityService.cs @@ -1,6 +1,7 @@ namespace LearningHub.Nhs.OpenApi.Services.Services { using System; + using System.Collections.Generic; using System.Security.Cryptography; using System.Text; using System.Threading.Tasks; @@ -11,6 +12,7 @@ using LearningHub.Nhs.Models.Email.Models; using LearningHub.Nhs.Models.Entities; using LearningHub.Nhs.Models.Enums; + using LearningHub.Nhs.Models.GovNotifyMessaging; using LearningHub.Nhs.OpenApi.Models.Configuration; using LearningHub.Nhs.OpenApi.Repositories.Interface.Repositories; using LearningHub.Nhs.OpenApi.Services.Interface.Services; @@ -28,6 +30,9 @@ public class SecurityService : ISecurityService private readonly IEmailChangeValidationTokenRepository emailChangeValidationTokenRepository; private readonly IEmailSenderService emailSenderService; private readonly LearningHubConfig learningHubConfig; + private readonly IGovMessageService govMessageService; + private readonly IEmailTemplateService emailTemplateService; + private readonly IUserProfileRepository userProfileRepository; /// /// Initializes a new instance of the class. @@ -35,14 +40,23 @@ public class SecurityService : ISecurityService /// emailChangeValidationTokenRepository. /// emailSenderService. /// settings. + /// govMessageService. + /// emailTemplateService. + /// userProfileRepository. public SecurityService( IEmailChangeValidationTokenRepository emailChangeValidationTokenRepository, IEmailSenderService emailSenderService, - IOptions learningHubConfig) + IOptions learningHubConfig, + IGovMessageService govMessageService, + IEmailTemplateService emailTemplateService, + IUserProfileRepository userProfileRepository) { this.emailChangeValidationTokenRepository = emailChangeValidationTokenRepository; this.emailSenderService = emailSenderService; this.learningHubConfig = learningHubConfig.Value; + this.govMessageService = govMessageService; + this.emailTemplateService = emailTemplateService; + this.userProfileRepository = userProfileRepository; } /// @@ -74,7 +88,24 @@ public async Task GenerateEmailChangeValidationTokenAndSendEmail(int userId, str }; var validateTokenUrl = $"{this.learningHubConfig.BaseUrl}confirm-email?token={HttpUtility.UrlEncode(userToken)}&loctoken={HttpUtility.UrlEncode(lookupToken)}"; - await SendEmailChangeConfirmationEmail(userId, email, validateTokenUrl, isUserRoleUpgrade); + var user = await this.userProfileRepository.GetByIdAsync(userId); + var emailTemplate = this.emailTemplateService.GetEmailTemplateById((int)EmailTemplates.EmailChangeConfirmationEmail); + var personalisation = new Dictionary(); + personalisation["user name"] = user.UserName; + personalisation["confirm_email_link"] = validateTokenUrl; + personalisation["date"] = emailChangeValidationToken.Expiry.ToString("dd-MM-yyyy"); + personalisation["time"] = emailChangeValidationToken.Expiry.ToString("HH:mm"); + + var emailRequest = new EmailRequest + { + Recipient = email, + TemplateId = emailTemplate.TemplateId, + Personalisation = personalisation, + }; + + await this.govMessageService.SendEmailAsync(emailRequest); + + ////await SendEmailChangeConfirmationEmail(userId, email, validateTokenUrl, isUserRoleUpgrade); await emailChangeValidationTokenRepository.CreateAsync(userId, emailChangeValidationToken); } @@ -127,7 +158,21 @@ public async Task ValidateEmailChangeTokenAsyn tokenResult.Email = emailChangeValidationToken.Email; tokenResult.UserId = emailChangeValidationToken.UserId; tokenResult.Valid = true; - await this.SendEmailAfterEmailVerification(emailChangeValidationToken.UserId, emailChangeValidationToken.Email, isUserRoleUpgrade); + + var emailTemplate = this.emailTemplateService.GetEmailTemplateById((int)EmailTemplates.EmailVerified); + var personalisation = new Dictionary(); + personalisation["user name"] = emailChangeValidationToken.User.UserName; + + var emailRequest = new EmailRequest + { + Recipient = emailChangeValidationToken.Email, + TemplateId = emailTemplate.TemplateId, + Personalisation = personalisation, + }; + + await this.govMessageService.SendEmailAsync(emailRequest); + + ////await this.SendEmailAfterEmailVerification(emailChangeValidationToken.UserId, emailChangeValidationToken.Email, isUserRoleUpgrade); } } diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Services/Startup.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Services/Startup.cs index 56b9450ef..73d603c48 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi.Services/Startup.cs +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Services/Startup.cs @@ -80,6 +80,7 @@ public static void AddServices(this IServiceCollection services, IConfiguration services.AddScoped(); services.AddScoped(); services.AddScoped(); + services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Tests/LearningHub.Nhs.OpenApi.Tests.csproj b/OpenAPI/LearningHub.Nhs.OpenApi.Tests/LearningHub.Nhs.OpenApi.Tests.csproj index f4251a236..06c0eb51a 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi.Tests/LearningHub.Nhs.OpenApi.Tests.csproj +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Tests/LearningHub.Nhs.OpenApi.Tests.csproj @@ -11,7 +11,7 @@ - + diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Tests/Services/Services/CatalogueServiceTests.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Tests/Services/Services/CatalogueServiceTests.cs index 8eec10b9d..e17d6effb 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi.Tests/Services/Services/CatalogueServiceTests.cs +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Tests/Services/Services/CatalogueServiceTests.cs @@ -42,6 +42,8 @@ public class CatalogueServiceTests private readonly Mock> findwiseConfig; private readonly Mock notificationSenderService; private readonly Mock timezoneOffsetManager; + private readonly Mock govMessageSevice; + private readonly Mock emailTemplateService; private readonly Mock categoryService; /// @@ -50,6 +52,7 @@ public class CatalogueServiceTests public CatalogueServiceTests() { this.catalogueRepository = new Mock(); + this.categoryService = new Mock(); this.mapper = new Mock(); this.catalogueNodeVersionRepository = new Mock(); this.catalogueAccessRequestRepository = new Mock(); @@ -68,8 +71,15 @@ public CatalogueServiceTests() this.findwiseConfig = new Mock>(); this.notificationSenderService = new Mock(); this.timezoneOffsetManager = new Mock(); + this.govMessageSevice = new Mock(); + this.emailTemplateService = new Mock(); this.categoryService = new Mock(); - this.catalogueService = new CatalogueService(this.catalogueRepository.Object, this.categoryService.Object, this.nodeRepository.Object, this.userUserGroupRepository.Object, this.mapper.Object, this.findwiseConfig.Object, this.learningHubConfig.Object, this.catalogueNodeVersionRepository.Object, this.nodeResourceRepository.Object, this.resourceVersionRepository.Object, this.roleUserGroupRepository.Object, this.providerService.Object, this.catalogueAccessRequestRepository.Object, this.userRepository.Object, this.userProfileRepository.Object, this.emailSenderService.Object, this.bookmarkRepository.Object, this.nodeActivityRepository.Object, this.notificationSenderService.Object,this.timezoneOffsetManager.Object); + this.catalogueService = new CatalogueService(this.catalogueRepository.Object, this.categoryService.Object, + this.nodeRepository.Object, this.userUserGroupRepository.Object, + this.mapper.Object, this.findwiseConfig.Object, this.learningHubConfig.Object, + this.catalogueNodeVersionRepository.Object, this.nodeResourceRepository.Object, this.resourceVersionRepository.Object, + this.roleUserGroupRepository.Object, this.providerService.Object, this.catalogueAccessRequestRepository.Object, this.userRepository.Object, this.userProfileRepository.Object, this.emailSenderService.Object, this.bookmarkRepository.Object, this.nodeActivityRepository.Object, this.notificationSenderService.Object, this.timezoneOffsetManager.Object, this.categoryService.Object, this.govMessageSevice.Object, this.emailTemplateService.Object); + } private static IEnumerable CatalogueNodeVersionList => new List() diff --git a/OpenAPI/LearningHub.Nhs.OpenApi/Controllers/CatalogueController.cs b/OpenAPI/LearningHub.Nhs.OpenApi/Controllers/CatalogueController.cs index b59dd0aa0..898d34dec 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi/Controllers/CatalogueController.cs +++ b/OpenAPI/LearningHub.Nhs.OpenApi/Controllers/CatalogueController.cs @@ -235,15 +235,16 @@ public async Task InviteUser(RestrictedCatalogueInviteUserViewMod /// The RequestAccess. /// /// The reference. + /// The catalogueName. /// The view model. /// The accessType. /// The ActionResult. [HttpPost] - [Route("RequestAccess/{reference}/{accessType}")] + [Route("RequestAccess/{reference}/{catalogueName}/{accessType}")] [Authorize] - public async Task RequestAccess(string reference, CatalogueAccessRequestViewModel vm, string accessType) + public async Task RequestAccess(string reference,string catalogueName, CatalogueAccessRequestViewModel vm, string accessType) { - return this.Ok(await this.catalogueService.RequestAccessAsync(this.CurrentUserId.GetValueOrDefault(), reference, vm, accessType)); + return this.Ok(await this.catalogueService.RequestAccessAsync(this.CurrentUserId.GetValueOrDefault(), reference, catalogueName, vm, accessType)); } /// diff --git a/OpenAPI/LearningHub.Nhs.OpenApi/Controllers/GovNotifyMessagingController.cs b/OpenAPI/LearningHub.Nhs.OpenApi/Controllers/GovNotifyMessagingController.cs new file mode 100644 index 000000000..64afc8844 --- /dev/null +++ b/OpenAPI/LearningHub.Nhs.OpenApi/Controllers/GovNotifyMessagingController.cs @@ -0,0 +1,185 @@ +namespace LearningHub.NHS.OpenAPI.Controllers +{ + using System; + using System.Collections.Generic; + using System.Threading.Tasks; + using LearningHub.Nhs.MessageQueueing.Repositories; + using LearningHub.Nhs.MessagingService.Interfaces; + using LearningHub.Nhs.Models.Common; + using LearningHub.Nhs.Models.GovNotifyMessaging; + using LearningHub.Nhs.OpenApi.Services.Interface.Services.Messaging; + using Microsoft.AspNetCore.Authorization; + using Microsoft.AspNetCore.Mvc; + + /// + /// GovNotify Messaging Controller. + /// + [Route("GovNotifyMessage")] + [Authorize] + public class GovNotifyMessagingController : OpenApiControllerBase + { + private readonly IGovNotifyService messageService; + private readonly IMessageQueueRepository messageQueueRepository; + private readonly IGovMessageService govMessageService; + + /// + /// Initializes a new instance of the class. + /// + /// The message service. + /// The email Queue Repository. + public GovNotifyMessagingController(IGovNotifyService messageService, IMessageQueueRepository messageQueueRepository, IGovMessageService govMessageService) + { + this.messageService = messageService; + this.messageQueueRepository = messageQueueRepository; + this.govMessageService = govMessageService; + } + + /// + /// Sends an email using UK Gov.Notify. + /// + /// personalisation. + /// The . + [Route("SendEmail")] + [HttpPost] + public async Task SendEmailAsync([FromBody] EmailRequest request) + { + try + { + var response = await this.govMessageService.SendEmailAsync(request); + + ////if (!response.IsSuccess) + ////{ + //// return this.BadRequest(new { error = response.ErrorMessage }); + ////} + + return this.Ok(response); + } + catch (Exception ex) + { + return this.Ok(ex.Message); + } + } + + /// + /// Sends a sms using UK Gov.Notify. + /// + /// SendSmsRequest. + /// The . + [Route("SendSms")] + [HttpPost] + public async Task SendSmsAsync([FromBody] SmsRequest request) + { + try + { + if (string.IsNullOrWhiteSpace(request.PhoneNumber) || string.IsNullOrWhiteSpace(request.TemplateId)) + { + return this.BadRequest("phoneNumber and template ID are required"); + } + + var response = await this.messageService.SendSmsAsync(request.PhoneNumber, request.TemplateId, request.Personalisation); + return this.Ok(response); + } + catch (Exception ex) + { + return this.Ok(ex.Message); + } + } + + /// + /// To queue the MessageRequests. + /// + /// The QueueRequestList. + /// The . + [Route("QueueRequests")] + [HttpPost] + public async Task QueueRequests([FromBody] QueueMessageList request) + { + ////if (request?.Messages == null || !request.Messages.Any()) + ////{ + //// return this.BadRequest("At least one email must be provided in the request."); + ////} + + ////var requests = request.Messages.Select(q => new QueueRequests + ////{ + //// Recipient = q.Recipient, + //// TemplateId = q.TemplateId, + //// Personalisation = q.Personalisation != null ? JsonConvert.SerializeObject(q.Personalisation) : null, + //// DeliverAfter = q.DeliverAfter ?? null, + ////}); + + ////await this.messageQueueRepository.QueueMessagesAsync(requests); + ////return this.Ok(new { Message = $"{requests.Count()} message requests queued successfully." }); + + await this.govMessageService.QueueRequestsAsync(request); + + return this.Ok(new { Message = $"{request.Messages.Count} message requests queued successfully." }); + } + + /// + /// To fetch the Pending or failed Message Requests. + /// + /// The . + [Route("PendingMessageRequests")] + [HttpGet] + public async Task> PendingMessageRequests() + { + return await this.messageQueueRepository.GetPendingEmailsAsync(); + } + + /// + /// Update message request as Success. + /// + /// The response. + /// The . + [Route("MessageSuccessUpdate")] + [HttpPost] + public async Task MessageSuccessUpdate([FromBody] GovNotifyResponse response) + { + await this.messageQueueRepository.MessageDeliverySuccess(response); + return this.Ok(); + } + + /// + /// Update message request as Failed. + /// + /// The response. + /// The . + [Route("MessageFailedUpdate")] + [HttpPost] + public async Task MessageFailedUpdate([FromBody] GovNotifyResponse response) + { + await this.messageQueueRepository.MessageDeliveryFailed(response); + return this.Ok(); + } + + /// + /// Get Message Requests. + /// + /// page. + /// page size. + /// sort column name. + /// sort direction. + /// filter. + /// The . + [Route("GetMessageRequests/{page}/{pageSize}/{sortColumn}/{sortDirection}/{filter}")] + [HttpGet] + public async Task GetMessageRequests(int page, int pageSize, string sortColumn, string sortDirection, string filter) + { + PagedResultSet pagedResultSet = await this.govMessageService.GetMessageRequests(page, pageSize, sortColumn, sortDirection, filter); + return this.Ok(pagedResultSet); + } + + /// + /// Get message request details by id. + /// + /// id. + /// The . + [Route("GetMessageRequestById/{id}")] + [HttpGet] + public async Task GetMessageRequestById(int id) + { + MessageRequestViewModel requestDetails = await this.govMessageService.GetMessageRequestById(id); + return this.Ok(requestDetails); + } + } +} diff --git a/OpenAPI/LearningHub.Nhs.OpenApi/LearningHub.NHS.OpenAPI.csproj b/OpenAPI/LearningHub.Nhs.OpenApi/LearningHub.NHS.OpenAPI.csproj index b4bfab382..2c3641eb9 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi/LearningHub.NHS.OpenAPI.csproj +++ b/OpenAPI/LearningHub.Nhs.OpenApi/LearningHub.NHS.OpenAPI.csproj @@ -19,7 +19,7 @@ - + @@ -34,6 +34,8 @@ + + diff --git a/OpenAPI/LearningHub.Nhs.OpenApi/Startup.cs b/OpenAPI/LearningHub.Nhs.OpenApi/Startup.cs index 695565457..5d3312302 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi/Startup.cs +++ b/OpenAPI/LearningHub.Nhs.OpenApi/Startup.cs @@ -8,12 +8,10 @@ namespace LearningHub.NHS.OpenAPI using System.Collections.Generic; using System.IO; using AspNetCore.Authentication.ApiKey; - using LearningHub.Nhs.Api.Authentication; using LearningHub.Nhs.Caching; using LearningHub.Nhs.Models.Enums; using LearningHub.Nhs.Models.Extensions; using LearningHub.NHS.OpenAPI.Auth; - using LearningHub.NHS.OpenAPI.Authentication; using LearningHub.NHS.OpenAPI.Configuration; using LearningHub.NHS.OpenAPI.Middleware; using LearningHub.Nhs.OpenApi.Repositories; @@ -21,7 +19,6 @@ namespace LearningHub.NHS.OpenAPI using LearningHub.Nhs.OpenApi.Services; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authentication.JwtBearer; - using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.EntityFrameworkCore; @@ -31,6 +28,13 @@ namespace LearningHub.NHS.OpenAPI using Microsoft.Extensions.Hosting; using Microsoft.IdentityModel.Tokens; using Microsoft.OpenApi.Models; + using Microsoft.AspNetCore.Authorization; + using LearningHub.NHS.OpenAPI.Authentication; + using System.Configuration; + using LearningHub.Nhs.MessagingService; + using LearningHub.Nhs.MessageQueueing; + using Microsoft.AspNetCore.Authentication.Cookies; + using LearningHub.Nhs.Api.Authentication; /// /// The Startup class. @@ -97,6 +101,8 @@ public void ConfigureServices(IServiceCollection services) var swaggerVersion = this.Configuration["Swagger:Version"]; var swaggerDescription = $"A set of API endpoints for retrieving learning resource information from the Learning Hub learning platform. The [Learning Hub](https://learninghub.nhs.uk/) is a platform for hosting and sharing learning resources for health and social care provided by Technology Enhanced Learning (TEL) at NHS England. An application API key must be used to authorise calls to the API from external applications. To contact TEL to discuss connecting your external system to the Learning Hub, email england.tel@nhs.net.\n\n Build Number: {this.Configuration["Swagger:BuildNumber"]} \n\n"; + services.AddMessagingServices(this.Configuration); + services.AddQueueingRepositories(this.Configuration); services.AddSwaggerGen( c => { diff --git a/OpenAPI/LearningHub.Nhs.OpenApi/SwaggerDefinitions/v1.3.0.json b/OpenAPI/LearningHub.Nhs.OpenApi/SwaggerDefinitions/v1.3.0.json index 1fd6fa2d1..95abc6405 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi/SwaggerDefinitions/v1.3.0.json +++ b/OpenAPI/LearningHub.Nhs.OpenApi/SwaggerDefinitions/v1.3.0.json @@ -6174,6 +6174,202 @@ } } } + }, + "/GovNotifyMessage/SendSms": { + "post": { + "tags": [ + "SendSms" + ], + "summary": "Send an SMS.", + "requestBody": { + "description": "The Sends an SMS using the UK Gov.Notify service.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/LearningHub.Nhs.Models.GovNotifyMessaging.SmsRequest" + } + }, + "text/json": { + "schema": { + "$ref": "#/components/schemas/LearningHub.Nhs.Models.GovNotifyMessaging.SmsRequest" + } + }, + "application/*+json": { + "schema": { + "$ref": "#/components/schemas/LearningHub.Nhs.Models.GovNotifyMessaging.SmsRequest" + } + } + } + }, + "responses": { + "200": { + "description": "SMS successfully sent." + }, + "400": { + "description": "Bad request, invalid input." + }, + "500": { + "description": "Internal server error." + } + } + } + }, + "/GovNotifyMessage/SendEmail": { + "post": { + "tags": [ + "SendEmail" + ], + "summary": "Send an Email.", + "requestBody": { + "description": "Sends an email using the UK Gov.Notify service.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/LearningHub.Nhs.Models.GovNotifyMessaging.EmailRequest" + } + }, + "text/json": { + "schema": { + "$ref": "#/components/schemas/LearningHub.Nhs.Models.GovNotifyMessaging.EmailRequest" + } + }, + "application/*+json": { + "schema": { + "$ref": "#/components/schemas/LearningHub.Nhs.Models.GovNotifyMessaging.EmailRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Email successfully sent." + }, + "400": { + "description": "Bad request, invalid input." + }, + "500": { + "description": "Internal server error." + } + } + } + }, + "/GovNotifyMessage/QueueRequests": { + "post": { + "tags": [ + "QueueRequests" + ], + "summary": "Queue one or more email/sms request for later processing.", + "requestBody": { + "description": "A list of sms/email requests to be queued for sending.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/LearningHub.Nhs.Models.GovNotifyMessaging.QueueRequestsList" + } + }, + "text/json": { + "schema": { + "$ref": "#/components/schemas/LearningHub.Nhs.Models.GovNotifyMessaging.QueueRequestsList" + } + }, + "application/*+json": { + "schema": { + "$ref": "#/components/schemas/LearningHub.Nhs.Models.GovNotifyMessaging.QueueRequestsList" + } + } + } + }, + "responses": { + "200": { + "description": "Requests are queued successfully." + }, + "400": { + "description": "Bad request, invalid input." + }, + "500": { + "description": "Internal server error." + } + } + } + }, + "/GovNotifyMessage/GetMessageRequests/{page}/{pageSize}/{sortColumn}/{sortDirection}/{filter}": { + "post": { + "tags": [ + "GetMessageRequests" + ], + "parameters": [ + { + "name": "page", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + } + }, + { + "name": "pageSize", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + } + }, + { + "name": "sortColumn", + "in": "path", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "sortDirection", + "in": "path", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "filter", + "in": "path", + "required": false, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/GovNotifyMessage/GetMessageRequestById/{id}": { + "post": { + "tags": [ + "GetMessageRequests" + ], + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } } }, "components": { @@ -14279,6 +14475,86 @@ } }, "additionalProperties": false + }, + "LearningHub.Nhs.Models.GovNotifyMessaging.SmsRequest": { + "type": "object", + "required": [ "PhoneNumber", "TemplateId" ], + "properties": { + "PhoneNumber": { + "type": "string", + "nullable": false, + "description": "The recipient's mobile number." + }, + "TemplateId": { + "type": "string", + "nullable": false, + "description": "The ID of the template to be used for the email." + }, + "Personalisation": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Key-value pairs for personalising the sms template." + } + } + }, + "LearningHub.Nhs.Models.GovNotifyMessaging.EmailRequest": { + "type": "object", + "properties": { + "Recipient": { + "type": "string", + "nullable": false, + "description": "The recipient's email address." + }, + "TemplateId": { + "type": "string", + "nullable": false, + "description": "The ID of the template to be used for the email." + }, + "Personalisation": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Key-value pairs for personalising the email template." + } + } + }, + "LearningHub.Nhs.Models.GovNotifyMessaging.QueueRequestsList": { + "type": "object", + "properties": { + "Messages": { + "type": "array", + "items": { + "$ref": "#/components/schemas/LearningHub.Nhs.Models.GovNotifyMessaging.QueueRequests" + } + } + } + }, + "LearningHub.Nhs.Models.GovNotifyMessaging.QueueRequests": { + "type": "object", + "properties": { + "Recipient": { + "type": "string", + "nullable": false + }, + "TemplateId": { + "type": "string", + "nullable": false + }, + "DeliverAfter": { + "type": "string", + "format": "date-time" + }, + "Personalisation": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Key-value pairs for personalising the template." + } + } } }, "securitySchemes": { diff --git a/OpenAPI/LearningHub.Nhs.OpenApi/appsettings.json b/OpenAPI/LearningHub.Nhs.OpenApi/appsettings.json index 3a96c27b9..d50eba9e1 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi/appsettings.json +++ b/OpenAPI/LearningHub.Nhs.OpenApi/appsettings.json @@ -17,6 +17,7 @@ "ElfhHubDbConnection": "", "LearningHubDbConnection": "", "LearningHubRedis": "", + "GovNotifyMessageDbConnection": "", "NLogDb": "" }, "Auth": { @@ -44,6 +45,12 @@ "Keys": [ "" ] + }, + { + "Name": "MessageQueueProcessor", + "Keys": [ + "" + ] } ] }, @@ -171,5 +178,8 @@ "TenantId": "", "ClientId": "", "ClientSecret": "" + }, + "GovNotify": { + "GovNotifyApiKey": "" } } diff --git a/ReportAPI/LearningHub.Nhs.ReportApi.Services.Interface/LearningHub.Nhs.ReportApi.Services.Interface.csproj b/ReportAPI/LearningHub.Nhs.ReportApi.Services.Interface/LearningHub.Nhs.ReportApi.Services.Interface.csproj index 96ff6ae13..cd760fde6 100644 --- a/ReportAPI/LearningHub.Nhs.ReportApi.Services.Interface/LearningHub.Nhs.ReportApi.Services.Interface.csproj +++ b/ReportAPI/LearningHub.Nhs.ReportApi.Services.Interface/LearningHub.Nhs.ReportApi.Services.Interface.csproj @@ -16,7 +16,7 @@ - + diff --git a/ReportAPI/LearningHub.Nhs.ReportApi.Services.UnitTests/LearningHub.Nhs.ReportApi.Services.UnitTests.csproj b/ReportAPI/LearningHub.Nhs.ReportApi.Services.UnitTests/LearningHub.Nhs.ReportApi.Services.UnitTests.csproj index 70e3e863b..ab77f5198 100644 --- a/ReportAPI/LearningHub.Nhs.ReportApi.Services.UnitTests/LearningHub.Nhs.ReportApi.Services.UnitTests.csproj +++ b/ReportAPI/LearningHub.Nhs.ReportApi.Services.UnitTests/LearningHub.Nhs.ReportApi.Services.UnitTests.csproj @@ -18,7 +18,7 @@ - + diff --git a/ReportAPI/LearningHub.Nhs.ReportApi.Services/LearningHub.Nhs.ReportApi.Services.csproj b/ReportAPI/LearningHub.Nhs.ReportApi.Services/LearningHub.Nhs.ReportApi.Services.csproj index c4944deb0..f39b00693 100644 --- a/ReportAPI/LearningHub.Nhs.ReportApi.Services/LearningHub.Nhs.ReportApi.Services.csproj +++ b/ReportAPI/LearningHub.Nhs.ReportApi.Services/LearningHub.Nhs.ReportApi.Services.csproj @@ -19,7 +19,7 @@ - + diff --git a/ReportAPI/LearningHub.Nhs.ReportApi.Shared/LearningHub.Nhs.ReportApi.Shared.csproj b/ReportAPI/LearningHub.Nhs.ReportApi.Shared/LearningHub.Nhs.ReportApi.Shared.csproj index d02c44881..47cbba31f 100644 --- a/ReportAPI/LearningHub.Nhs.ReportApi.Shared/LearningHub.Nhs.ReportApi.Shared.csproj +++ b/ReportAPI/LearningHub.Nhs.ReportApi.Shared/LearningHub.Nhs.ReportApi.Shared.csproj @@ -17,7 +17,7 @@ - + diff --git a/ReportAPI/LearningHub.Nhs.ReportApi/LearningHub.Nhs.ReportApi.csproj b/ReportAPI/LearningHub.Nhs.ReportApi/LearningHub.Nhs.ReportApi.csproj index 5ad3e0d51..eac5217c6 100644 --- a/ReportAPI/LearningHub.Nhs.ReportApi/LearningHub.Nhs.ReportApi.csproj +++ b/ReportAPI/LearningHub.Nhs.ReportApi/LearningHub.Nhs.ReportApi.csproj @@ -20,7 +20,7 @@ - + diff --git a/WebAPI/LearningHub.Nhs.API/LearningHub.Nhs.Api.csproj b/WebAPI/LearningHub.Nhs.API/LearningHub.Nhs.Api.csproj index ce240b56f..5ed4ecf86 100644 --- a/WebAPI/LearningHub.Nhs.API/LearningHub.Nhs.Api.csproj +++ b/WebAPI/LearningHub.Nhs.API/LearningHub.Nhs.Api.csproj @@ -29,7 +29,7 @@ - + diff --git a/WebAPI/LearningHub.Nhs.Api.Shared/LearningHub.Nhs.Api.Shared.csproj b/WebAPI/LearningHub.Nhs.Api.Shared/LearningHub.Nhs.Api.Shared.csproj index 12b019206..c0017cc6f 100644 --- a/WebAPI/LearningHub.Nhs.Api.Shared/LearningHub.Nhs.Api.Shared.csproj +++ b/WebAPI/LearningHub.Nhs.Api.Shared/LearningHub.Nhs.Api.Shared.csproj @@ -9,7 +9,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/WebAPI/LearningHub.Nhs.Api.UnitTests/LearningHub.Nhs.Api.UnitTests.csproj b/WebAPI/LearningHub.Nhs.Api.UnitTests/LearningHub.Nhs.Api.UnitTests.csproj index 70c6f8f9d..c2dd88d3c 100644 --- a/WebAPI/LearningHub.Nhs.Api.UnitTests/LearningHub.Nhs.Api.UnitTests.csproj +++ b/WebAPI/LearningHub.Nhs.Api.UnitTests/LearningHub.Nhs.Api.UnitTests.csproj @@ -11,7 +11,7 @@ - + diff --git a/WebAPI/LearningHub.Nhs.Database/LearningHub.Nhs.Database.sqlproj b/WebAPI/LearningHub.Nhs.Database/LearningHub.Nhs.Database.sqlproj index d1af137b2..ce6aa08f3 100644 --- a/WebAPI/LearningHub.Nhs.Database/LearningHub.Nhs.Database.sqlproj +++ b/WebAPI/LearningHub.Nhs.Database/LearningHub.Nhs.Database.sqlproj @@ -589,6 +589,8 @@ + + diff --git a/WebAPI/LearningHub.Nhs.Database/Scripts/Post-Deploy/Scripts/UpdateEmailTemplateData.sql b/WebAPI/LearningHub.Nhs.Database/Scripts/Post-Deploy/Scripts/UpdateEmailTemplateData.sql new file mode 100644 index 000000000..179343934 --- /dev/null +++ b/WebAPI/LearningHub.Nhs.Database/Scripts/Post-Deploy/Scripts/UpdateEmailTemplateData.sql @@ -0,0 +1,20 @@ +UPDATE [messaging].[EmailTemplate] SET TemplateId ='3c2eece7-e7aa-4966-bc6b-b4fef72ead1c' WHERE Title = 'CatalogueAccessRequest' +GO + +UPDATE [messaging].[EmailTemplate] SET TemplateId ='a8a56741-06ad-4542-a276-ea0fc3636f78' WHERE Title = 'CatalogueAccessRequestSuccess' +GO + +UPDATE [messaging].[EmailTemplate] SET TemplateId ='81125f0f-2306-45cd-b2f6-6dc980d79e69' WHERE Title = 'CatalogueAccessRequestFailure' +GO + +UPDATE [messaging].[EmailTemplate] SET TemplateId ='f4d5bda1-8f72-4ea9-8cba-b77589b7f18e' WHERE Title = 'EmailVerified' +GO + +UPDATE [messaging].[EmailTemplate] SET TemplateId ='c341fe2b-ca62-4af4-bea6-6c52ccfdcfe8' WHERE Title = 'EmailChangeConfirmationEmail' +GO + +UPDATE [messaging].[EmailTemplate] SET TemplateId ='0e7e0333-cf64-4461-b828-2a8c6c339207' WHERE Title = 'CataloguePermissionRequest' +Go + +UPDATE [messaging].[EmailTemplate] SET TemplateId ='e6d981d1-f6b2-4a17-8caa-f727e1b4f445' WHERE Title = 'CatalogueAccessInvitation' +GO \ No newline at end of file diff --git a/WebAPI/LearningHub.Nhs.Database/Scripts/Pre-Deploy/Scripts/EmailTemplateTableChanges.sql b/WebAPI/LearningHub.Nhs.Database/Scripts/Pre-Deploy/Scripts/EmailTemplateTableChanges.sql new file mode 100644 index 000000000..1169c44cf --- /dev/null +++ b/WebAPI/LearningHub.Nhs.Database/Scripts/Pre-Deploy/Scripts/EmailTemplateTableChanges.sql @@ -0,0 +1,2 @@ + ALTER TABLE [messaging].[EmailTemplate] + ADD TemplateId VARCHAR(50) NULL diff --git a/WebAPI/LearningHub.Nhs.Database/Stored Procedures/Hierarchy/CatalogueAccessRequestCreate.sql b/WebAPI/LearningHub.Nhs.Database/Stored Procedures/Hierarchy/CatalogueAccessRequestCreate.sql index 98d7d5d30..ac8c5a7a9 100644 --- a/WebAPI/LearningHub.Nhs.Database/Stored Procedures/Hierarchy/CatalogueAccessRequestCreate.sql +++ b/WebAPI/LearningHub.Nhs.Database/Stored Procedures/Hierarchy/CatalogueAccessRequestCreate.sql @@ -7,6 +7,7 @@ -- -- 01-02-2021 <> Initial Revision -- 12-01-2024 Swapnamol Abraham Added Role ID referernce +-- 08-07-2025 SA GOVnotify Implementation ------------------------------------------------------------------------------- CREATE PROCEDURE [hierarchy].[CatalogueAccessRequestCreate] ( @@ -43,76 +44,76 @@ BEGIN @CurrentUserFullName = FirstName + ' ' + LastName FROM [hub].[UserProfile] where Id = @currentUserId; - DECLARE @emailTemplateBody nvarchar(max); - DECLARE @emailTemplateSubject nvarchar(max); - IF @accessType = 'access' - BEGIN - SELECT - @emailTemplateBody = REPLACE(etl.Body, '[Content]', et.Body), - @emailTemplateSubject = et.Subject - FROM - [messaging].[EmailTemplate] et - JOIN [messaging].[EmailTemplateLayout] etl on et.LayoutId = etl.Id - WHERE et.Title = 'CatalogueAccessRequest'; - END - ELSE - BEGIN - SELECT - @emailTemplateBody = REPLACE(etl.Body, '[Content]', et.Body), - @emailTemplateSubject = et.Subject - FROM - [messaging].[EmailTemplate] et - JOIN [messaging].[EmailTemplateLayout] etl on et.LayoutId = etl.Id - WHERE et.Title = 'CataloguePermissionRequest'; - END + --DECLARE @emailTemplateBody nvarchar(max); + --DECLARE @emailTemplateSubject nvarchar(max); + --IF @accessType = 'access' + --BEGIN + --SELECT + -- @emailTemplateBody = REPLACE(etl.Body, '[Content]', et.Body), + -- @emailTemplateSubject = et.Subject + --FROM + -- [messaging].[EmailTemplate] et + --JOIN [messaging].[EmailTemplateLayout] etl on et.LayoutId = etl.Id + --WHERE et.Title = 'CatalogueAccessRequest'; + --END + --ELSE + --BEGIN + --SELECT + -- @emailTemplateBody = REPLACE(etl.Body, '[Content]', et.Body), + -- @emailTemplateSubject = et.Subject + --FROM + -- [messaging].[EmailTemplate] et + --JOIN [messaging].[EmailTemplateLayout] etl on et.LayoutId = etl.Id + --WHERE et.Title = 'CataloguePermissionRequest'; + --END - DECLARE @AdminUserCursor CURSOR - SET @AdminUserCursor = CURSOR FAST_FORWARD - FOR - SELECT DISTINCT - up.FirstName as AdminFirstName, - u.Id as AdminUserId - FROM - [hub].[UserUserGroup] uug - JOIN - ( - SELECT UserGroupId FROM [hub].[RoleUserGroup] rug - JOIN [hub].[Scope] s on rug.ScopeId = s.Id - WHERE s.CatalogueNodeId = @catalogueNodeId - AND rug.RoleId = @localAdminRoleId - AND s.Deleted = 0 AND rug.Deleted = 0 - AND s.Deleted = 0 - ) arug on uug.UserGroupId = arug.UserGroupId - JOIN [hub].[User] u on u.Id = uug.UserId - JOIN [hub].[UserProfile] up on up.Id = u.Id - where uug.Deleted = 0 and u.Deleted = 0 and up.Deleted = 0; + --DECLARE @AdminUserCursor CURSOR + --SET @AdminUserCursor = CURSOR FAST_FORWARD + --FOR + --SELECT DISTINCT + -- up.FirstName as AdminFirstName, + -- u.Id as AdminUserId + --FROM + -- [hub].[UserUserGroup] uug + --JOIN + -- ( + -- SELECT UserGroupId FROM [hub].[RoleUserGroup] rug + -- JOIN [hub].[Scope] s on rug.ScopeId = s.Id + -- WHERE s.CatalogueNodeId = @catalogueNodeId + -- AND rug.RoleId = @localAdminRoleId + -- AND s.Deleted = 0 AND rug.Deleted = 0 + -- AND s.Deleted = 0 + -- ) arug on uug.UserGroupId = arug.UserGroupId + --JOIN [hub].[User] u on u.Id = uug.UserId + --JOIN [hub].[UserProfile] up on up.Id = u.Id + --where uug.Deleted = 0 and u.Deleted = 0 and up.Deleted = 0; - DECLARE @adminFirstName nvarchar(max); - DECLARE @adminUserId nvarchar(max); + --DECLARE @adminFirstName nvarchar(max); + --DECLARE @adminUserId nvarchar(max); - OPEN @AdminUserCursor; - FETCH NEXT FROM @AdminUserCursor INTO @adminFirstName, @adminUserId; + --OPEN @AdminUserCursor; + --FETCH NEXT FROM @AdminUserCursor INTO @adminFirstName, @adminUserId; - WHILE @@FETCH_STATUS = 0 - BEGIN - DECLARE @fullSubject nvarchar(max); - DECLARE @fullBody nvarchar(max); + --WHILE @@FETCH_STATUS = 0 + --BEGIN + -- DECLARE @fullSubject nvarchar(max); + -- DECLARE @fullBody nvarchar(max); - SELECT - @fullSubject = REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(@emailTemplateSubject, '[AdminFirstName]', @adminFirstName), '[UserEmailAddress]', @currentUserEmailAddress), '[CatalogueName]', @catalogueName), '[UserMessage]', @message), '[UserFullName]', @currentUserFullName), '[ManageAccessUrl]', @catalogueManageAccessUrl), - @fullBody = REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(@emailTemplateBody, '[AdminFirstName]', @adminFirstName), '[UserEmailAddress]', @currentUserEmailAddress), '[CatalogueName]', @catalogueName), '[UserMessage]', @message), '[UserFullName]', @currentUserFullName), '[ManageAccessUrl]', @catalogueManageAccessUrl); + -- SELECT + -- @fullSubject = REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(@emailTemplateSubject, '[AdminFirstName]', @adminFirstName), '[UserEmailAddress]', @currentUserEmailAddress), '[CatalogueName]', @catalogueName), '[UserMessage]', @message), '[UserFullName]', @currentUserFullName), '[ManageAccessUrl]', @catalogueManageAccessUrl), + -- @fullBody = REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(@emailTemplateBody, '[AdminFirstName]', @adminFirstName), '[UserEmailAddress]', @currentUserEmailAddress), '[CatalogueName]', @catalogueName), '[UserMessage]', @message), '[UserFullName]', @currentUserFullName), '[ManageAccessUrl]', @catalogueManageAccessUrl); - exec [messaging].[CreateEmailForUser] - @fullSubject, - @fullBody, - @adminUserId, - @currentUserId, - @UserTimezoneOffset; + -- exec [messaging].[CreateEmailForUser] + -- @fullSubject, + -- @fullBody, + -- @adminUserId, + -- @currentUserId, + -- @UserTimezoneOffset; - FETCH NEXT FROM @AdminUserCursor INTO @adminFirstName, @adminUserId; - END; - CLOSE @AdminUserCursor; - DEALLOCATE @AdminUserCursor; + -- FETCH NEXT FROM @AdminUserCursor INTO @adminFirstName, @adminUserId; + --END; + --CLOSE @AdminUserCursor; + --DEALLOCATE @AdminUserCursor; INSERT INTO [hierarchy].[CatalogueAccessRequest] (UserId, CatalogueNodeId, EmailAddress, Message, Status, Deleted, CreateUserId, CreateDate, AmendUserId, AmendDate, RoleId) diff --git a/WebAPI/LearningHub.Nhs.Database/Stored Procedures/Hierarchy/GetCatalogueAdminDetails.sql b/WebAPI/LearningHub.Nhs.Database/Stored Procedures/Hierarchy/GetCatalogueAdminDetails.sql new file mode 100644 index 000000000..a7aca6785 --- /dev/null +++ b/WebAPI/LearningHub.Nhs.Database/Stored Procedures/Hierarchy/GetCatalogueAdminDetails.sql @@ -0,0 +1,75 @@ +------------------------------------------------------------------------------- +-- Author +-- Created 28-01-2022 +-- Purpose To get the details of catalogue admin users of a catalogue. +-- +-- Modification History +-- +-- 04-07-2025 Swapnamol Abraham Initial Revision +------------------------------------------------------------------------------- +CREATE PROCEDURE [hierarchy].[GetCatalogueAdminDetails] +( + @currentUserId int, + @reference nvarchar(max), + @UserTimezoneOffset int = NULL, + @accessType nvarchar(max), + @roleId int +) +AS +BEGIN + BEGIN TRY + DECLARE @AmendDate datetimeoffset(7) = ISNULL(TODATETIMEOFFSET(DATEADD(mi, @UserTimezoneOffset, GETUTCDATE()), @UserTimezoneOffset), SYSDATETIMEOFFSET()) + + BEGIN TRAN + DECLARE @localAdminRoleId int = 3; + + DECLARE @catalogueNodeId int; + DECLARE @catalogueName nvarchar(max); + DECLARE @currentUserEmailAddress nvarchar(max); + DECLARE @currentUserFullName nvarchar(max); + SELECT + @catalogueNodeId = nv.NodeId, + @catalogueName = cnv.Name + FROM + [hierarchy].[CatalogueNodeVersion] cnv + JOIN [hierarchy].[NodeVersion] nv on cnv.NodeVersionId = nv.Id + WHERE Url = @reference AND cnv.Deleted = 0 AND nv.Deleted = 0; + + SELECT DISTINCT + up.FirstName as FirstName, + up.LastName As LastName, + up.EmailAddress AS EmailAddress, + u.Id as UserId + FROM + [hub].[UserUserGroup] uug + JOIN + ( + SELECT UserGroupId FROM [hub].[RoleUserGroup] rug + JOIN [hub].[Scope] s on rug.ScopeId = s.Id + WHERE s.CatalogueNodeId = @catalogueNodeId + AND rug.RoleId = @localAdminRoleId + AND s.Deleted = 0 AND rug.Deleted = 0 + AND s.Deleted = 0 + ) arug on uug.UserGroupId = arug.UserGroupId + JOIN [hub].[User] u on u.Id = uug.UserId + JOIN [hub].[UserProfile] up on up.Id = u.Id + where uug.Deleted = 0 and u.Deleted = 0 and up.Deleted = 0; + + END TRY + BEGIN CATCH + DECLARE @ErrorMessage NVARCHAR(4000); + DECLARE @ErrorSeverity INT; + DECLARE @ErrorState INT; + + SELECT + @ErrorMessage = ERROR_MESSAGE(), + @ErrorSeverity = ERROR_SEVERITY(), + @ErrorState = ERROR_STATE(); + + IF @@TRANCOUNT > 0 + ROLLBACK TRAN; + + RAISERROR (@ErrorMessage, @ErrorSeverity, @ErrorState); + + END CATCH +END; diff --git a/WebAPI/LearningHub.Nhs.Repository.Interface/LearningHub.Nhs.Repository.Interface.csproj b/WebAPI/LearningHub.Nhs.Repository.Interface/LearningHub.Nhs.Repository.Interface.csproj index 0ff751617..ba7767177 100644 --- a/WebAPI/LearningHub.Nhs.Repository.Interface/LearningHub.Nhs.Repository.Interface.csproj +++ b/WebAPI/LearningHub.Nhs.Repository.Interface/LearningHub.Nhs.Repository.Interface.csproj @@ -10,7 +10,7 @@ - + diff --git a/WebAPI/LearningHub.Nhs.Repository/LearningHub.Nhs.Repository.csproj b/WebAPI/LearningHub.Nhs.Repository/LearningHub.Nhs.Repository.csproj index b206c9818..9236b35b8 100644 --- a/WebAPI/LearningHub.Nhs.Repository/LearningHub.Nhs.Repository.csproj +++ b/WebAPI/LearningHub.Nhs.Repository/LearningHub.Nhs.Repository.csproj @@ -9,7 +9,7 @@ - + diff --git a/WebAPI/LearningHub.Nhs.Services.Interface/LearningHub.Nhs.Services.Interface.csproj b/WebAPI/LearningHub.Nhs.Services.Interface/LearningHub.Nhs.Services.Interface.csproj index 31ce5eb56..e83bb5665 100644 --- a/WebAPI/LearningHub.Nhs.Services.Interface/LearningHub.Nhs.Services.Interface.csproj +++ b/WebAPI/LearningHub.Nhs.Services.Interface/LearningHub.Nhs.Services.Interface.csproj @@ -16,7 +16,7 @@ - + all diff --git a/WebAPI/LearningHub.Nhs.Services.UnitTests/LearningHub.Nhs.Services.UnitTests.csproj b/WebAPI/LearningHub.Nhs.Services.UnitTests/LearningHub.Nhs.Services.UnitTests.csproj index a91b6e0b0..6dea98dfb 100644 --- a/WebAPI/LearningHub.Nhs.Services.UnitTests/LearningHub.Nhs.Services.UnitTests.csproj +++ b/WebAPI/LearningHub.Nhs.Services.UnitTests/LearningHub.Nhs.Services.UnitTests.csproj @@ -13,7 +13,7 @@ - + diff --git a/WebAPI/LearningHub.Nhs.Services/LearningHub.Nhs.Services.csproj b/WebAPI/LearningHub.Nhs.Services/LearningHub.Nhs.Services.csproj index c44ed1fde..f0079e58c 100644 --- a/WebAPI/LearningHub.Nhs.Services/LearningHub.Nhs.Services.csproj +++ b/WebAPI/LearningHub.Nhs.Services/LearningHub.Nhs.Services.csproj @@ -13,7 +13,7 @@ - + diff --git a/WebAPI/MigrationTool/LearningHub.Nhs.Migration.ConsoleApp/LearningHub.Nhs.Migration.ConsoleApp.csproj b/WebAPI/MigrationTool/LearningHub.Nhs.Migration.ConsoleApp/LearningHub.Nhs.Migration.ConsoleApp.csproj index a40466948..d5799d6aa 100644 --- a/WebAPI/MigrationTool/LearningHub.Nhs.Migration.ConsoleApp/LearningHub.Nhs.Migration.ConsoleApp.csproj +++ b/WebAPI/MigrationTool/LearningHub.Nhs.Migration.ConsoleApp/LearningHub.Nhs.Migration.ConsoleApp.csproj @@ -25,7 +25,7 @@ - + all diff --git a/WebAPI/MigrationTool/LearningHub.Nhs.Migration.Interface/LearningHub.Nhs.Migration.Interface.csproj b/WebAPI/MigrationTool/LearningHub.Nhs.Migration.Interface/LearningHub.Nhs.Migration.Interface.csproj index c2ac38a24..ac2ec66db 100644 --- a/WebAPI/MigrationTool/LearningHub.Nhs.Migration.Interface/LearningHub.Nhs.Migration.Interface.csproj +++ b/WebAPI/MigrationTool/LearningHub.Nhs.Migration.Interface/LearningHub.Nhs.Migration.Interface.csproj @@ -9,7 +9,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/WebAPI/MigrationTool/LearningHub.Nhs.Migration.Models/LearningHub.Nhs.Migration.Models.csproj b/WebAPI/MigrationTool/LearningHub.Nhs.Migration.Models/LearningHub.Nhs.Migration.Models.csproj index a10f69fd6..8fc39020c 100644 --- a/WebAPI/MigrationTool/LearningHub.Nhs.Migration.Models/LearningHub.Nhs.Migration.Models.csproj +++ b/WebAPI/MigrationTool/LearningHub.Nhs.Migration.Models/LearningHub.Nhs.Migration.Models.csproj @@ -10,7 +10,7 @@ - + all diff --git a/WebAPI/MigrationTool/LearningHub.Nhs.Migration.Staging.Repository/LearningHub.Nhs.Migration.Staging.Repository.csproj b/WebAPI/MigrationTool/LearningHub.Nhs.Migration.Staging.Repository/LearningHub.Nhs.Migration.Staging.Repository.csproj index ba2b9fc16..88cef3610 100644 --- a/WebAPI/MigrationTool/LearningHub.Nhs.Migration.Staging.Repository/LearningHub.Nhs.Migration.Staging.Repository.csproj +++ b/WebAPI/MigrationTool/LearningHub.Nhs.Migration.Staging.Repository/LearningHub.Nhs.Migration.Staging.Repository.csproj @@ -9,7 +9,7 @@ - + diff --git a/WebAPI/MigrationTool/LearningHub.Nhs.Migration.UnitTests/LearningHub.Nhs.Migration.UnitTests.csproj b/WebAPI/MigrationTool/LearningHub.Nhs.Migration.UnitTests/LearningHub.Nhs.Migration.UnitTests.csproj index d555f0d12..076c8717f 100644 --- a/WebAPI/MigrationTool/LearningHub.Nhs.Migration.UnitTests/LearningHub.Nhs.Migration.UnitTests.csproj +++ b/WebAPI/MigrationTool/LearningHub.Nhs.Migration.UnitTests/LearningHub.Nhs.Migration.UnitTests.csproj @@ -10,7 +10,7 @@ - + diff --git a/WebAPI/MigrationTool/LearningHub.Nhs.Migration/LearningHub.Nhs.Migration.csproj b/WebAPI/MigrationTool/LearningHub.Nhs.Migration/LearningHub.Nhs.Migration.csproj index c00e268d3..78caf696f 100644 --- a/WebAPI/MigrationTool/LearningHub.Nhs.Migration/LearningHub.Nhs.Migration.csproj +++ b/WebAPI/MigrationTool/LearningHub.Nhs.Migration/LearningHub.Nhs.Migration.csproj @@ -12,7 +12,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive