From 288cfbd74d88e4d7fc0751e799a6e5fa56a70165 Mon Sep 17 00:00:00 2001 From: Marcus Perryman Date: Tue, 26 Nov 2024 16:34:53 +0000 Subject: [PATCH 01/11] new enterprise apps (#174) * fix the version number * Add the enterprise aoos --- src/content/applications/AbsoluteSecurity.md | 7 +++++++ src/content/applications/BestCryptVolumeEncryption.md | 8 ++++++++ src/content/applications/BeyondTrustRemoteSupport.md | 7 +++++++ src/content/applications/BitDefenderEnterprise.md | 7 +++++++ src/content/applications/CheckpointMobile.md | 8 ++++++++ src/content/applications/CheckpointSecurRemote.md | 8 ++++++++ src/content/applications/CiscoAnyConnectHostScan.md | 8 ++++++++ src/content/applications/CiscoAnyConnectNVM.md | 8 ++++++++ src/content/applications/CiscoISEPosture.md | 8 ++++++++ src/content/applications/CiscoSecureEndpointAMP.md | 8 ++++++++ src/content/applications/CiscoUmbrella.md | 8 ++++++++ src/content/applications/CitrixEndpointManager.md | 7 +++++++ src/content/applications/ClamAV.md | 8 ++++++++ src/content/applications/Code42BackupAgent.md | 8 ++++++++ src/content/applications/Code42Incydr.md | 8 ++++++++ src/content/applications/CommercialVantage.md | 8 ++++++++ src/content/applications/CrowdStrikeEDR.md | 8 ++++++++ src/content/applications/CrowdStrikeProtectOSML.md | 8 ++++++++ src/content/applications/CrowdStrikeScriptControl.md | 8 ++++++++ src/content/applications/EnCaseEnhancedAgent.md | 8 ++++++++ src/content/applications/EncaseCoreAgent.md | 8 ++++++++ src/content/applications/F5BigIP.md | 8 ++++++++ src/content/applications/FlexeraFNMS.md | 8 ++++++++ src/content/applications/FlexeraITAM.md | 8 ++++++++ src/content/applications/ForcepointDLP.md | 8 ++++++++ src/content/applications/IvantiApps@Work.md | 8 ++++++++ src/content/applications/IvantiLANDesk.md | 8 ++++++++ src/content/applications/LakeSideSystrack.md | 8 ++++++++ src/content/applications/MalwareBytes.md | 7 +++++++ src/content/applications/Netskope.md | 7 +++++++ src/content/applications/NexThink.md | 8 ++++++++ src/content/applications/Okta.md | 7 +++++++ src/content/applications/PolicyPakCSE.md | 8 ++++++++ src/content/applications/PolicyPakCloudConnector.md | 8 ++++++++ src/content/applications/RSANetWitness.md | 8 ++++++++ src/content/applications/Rapid7VM.md | 8 ++++++++ src/content/applications/SafeNetMinidriver109.md | 8 ++++++++ src/content/applications/SafenetAuthenticationClient.md | 8 ++++++++ src/content/applications/SentinelOne.md | 8 ++++++++ src/content/applications/SophosInterceptX.md | 7 +++++++ src/content/applications/SplunkUF.md | 8 ++++++++ src/content/applications/SymantecDLP.md | 8 ++++++++ src/content/applications/SymantecEP.md | 8 ++++++++ src/content/applications/SymantecWSS.md | 8 ++++++++ src/content/applications/TaniumThreatResponse.md | 7 +++++++ src/content/applications/TrendMicroApex.md | 8 ++++++++ src/content/applications/UberAgent.md | 8 ++++++++ src/content/applications/VB-AudioVoicemeeter.md | 1 + src/content/applications/VMWareWorkspaceOne.md | 8 ++++++++ src/content/applications/VenafiCertificateManagement.md | 7 +++++++ src/content/applications/WatchGuard.md | 7 +++++++ src/content/applications/ZscalerZDX.md | 8 ++++++++ 52 files changed, 398 insertions(+) create mode 100644 src/content/applications/AbsoluteSecurity.md create mode 100644 src/content/applications/BestCryptVolumeEncryption.md create mode 100644 src/content/applications/BeyondTrustRemoteSupport.md create mode 100644 src/content/applications/BitDefenderEnterprise.md create mode 100644 src/content/applications/CheckpointMobile.md create mode 100644 src/content/applications/CheckpointSecurRemote.md create mode 100644 src/content/applications/CiscoAnyConnectHostScan.md create mode 100644 src/content/applications/CiscoAnyConnectNVM.md create mode 100644 src/content/applications/CiscoISEPosture.md create mode 100644 src/content/applications/CiscoSecureEndpointAMP.md create mode 100644 src/content/applications/CiscoUmbrella.md create mode 100644 src/content/applications/CitrixEndpointManager.md create mode 100644 src/content/applications/ClamAV.md create mode 100644 src/content/applications/Code42BackupAgent.md create mode 100644 src/content/applications/Code42Incydr.md create mode 100644 src/content/applications/CommercialVantage.md create mode 100644 src/content/applications/CrowdStrikeEDR.md create mode 100644 src/content/applications/CrowdStrikeProtectOSML.md create mode 100644 src/content/applications/CrowdStrikeScriptControl.md create mode 100644 src/content/applications/EnCaseEnhancedAgent.md create mode 100644 src/content/applications/EncaseCoreAgent.md create mode 100644 src/content/applications/F5BigIP.md create mode 100644 src/content/applications/FlexeraFNMS.md create mode 100644 src/content/applications/FlexeraITAM.md create mode 100644 src/content/applications/ForcepointDLP.md create mode 100644 src/content/applications/IvantiApps@Work.md create mode 100644 src/content/applications/IvantiLANDesk.md create mode 100644 src/content/applications/LakeSideSystrack.md create mode 100644 src/content/applications/MalwareBytes.md create mode 100644 src/content/applications/Netskope.md create mode 100644 src/content/applications/NexThink.md create mode 100644 src/content/applications/Okta.md create mode 100644 src/content/applications/PolicyPakCSE.md create mode 100644 src/content/applications/PolicyPakCloudConnector.md create mode 100644 src/content/applications/RSANetWitness.md create mode 100644 src/content/applications/Rapid7VM.md create mode 100644 src/content/applications/SafeNetMinidriver109.md create mode 100644 src/content/applications/SafenetAuthenticationClient.md create mode 100644 src/content/applications/SentinelOne.md create mode 100644 src/content/applications/SophosInterceptX.md create mode 100644 src/content/applications/SplunkUF.md create mode 100644 src/content/applications/SymantecDLP.md create mode 100644 src/content/applications/SymantecEP.md create mode 100644 src/content/applications/SymantecWSS.md create mode 100644 src/content/applications/TaniumThreatResponse.md create mode 100644 src/content/applications/TrendMicroApex.md create mode 100644 src/content/applications/UberAgent.md create mode 100644 src/content/applications/VMWareWorkspaceOne.md create mode 100644 src/content/applications/VenafiCertificateManagement.md create mode 100644 src/content/applications/WatchGuard.md create mode 100644 src/content/applications/ZscalerZDX.md diff --git a/src/content/applications/AbsoluteSecurity.md b/src/content/applications/AbsoluteSecurity.md new file mode 100644 index 00000000..5953c86f --- /dev/null +++ b/src/content/applications/AbsoluteSecurity.md @@ -0,0 +1,7 @@ +--- +name: "Absolute Security" +categories: ['it-sec-tools'] +compatibility: native +display_result: "Compatible" +link: https://www.absolute.com/platform/requirements/ +--- diff --git a/src/content/applications/BestCryptVolumeEncryption.md b/src/content/applications/BestCryptVolumeEncryption.md new file mode 100644 index 00000000..90edb67a --- /dev/null +++ b/src/content/applications/BestCryptVolumeEncryption.md @@ -0,0 +1,8 @@ +--- +name: "BestCrypt Volume Encryption" +categories: ['data-prot'] +compatibility: native +display_result: "Compatible" +version_from: "5.01.02" +link: https://www.jetico.com/downloads +--- diff --git a/src/content/applications/BeyondTrustRemoteSupport.md b/src/content/applications/BeyondTrustRemoteSupport.md new file mode 100644 index 00000000..12ad8997 --- /dev/null +++ b/src/content/applications/BeyondTrustRemoteSupport.md @@ -0,0 +1,7 @@ +--- +name: "BeyondTrust Remote Support" +categories: ['vpn'] +compatibility: emulation +display_result: "Compatible" +link: https://www.beyondtrust.com/sem/remote-support +--- diff --git a/src/content/applications/BitDefenderEnterprise.md b/src/content/applications/BitDefenderEnterprise.md new file mode 100644 index 00000000..f924abdd --- /dev/null +++ b/src/content/applications/BitDefenderEnterprise.md @@ -0,0 +1,7 @@ +--- +name: "BitDefender Enterprise" +categories: ['endpoint-sec'] +compatibility: native +display_result: "Compatible" +link: https://www.bitdefender.com/business/support/en/77212-77540-windows-agent.html#UUID-3b00c44f-134e-b2b1-baf0-0ab2d897b845 +--- diff --git a/src/content/applications/CheckpointMobile.md b/src/content/applications/CheckpointMobile.md new file mode 100644 index 00000000..15a2cc6b --- /dev/null +++ b/src/content/applications/CheckpointMobile.md @@ -0,0 +1,8 @@ +--- +name: "Checkpoint Mobile" +categories: ['vpn'] +compatibility: native +display_result: "Compatible" +version_from: "E87.60" +link: https://support.checkpoint.com/results/sk/sk170777 +--- diff --git a/src/content/applications/CheckpointSecurRemote.md b/src/content/applications/CheckpointSecurRemote.md new file mode 100644 index 00000000..bc32544a --- /dev/null +++ b/src/content/applications/CheckpointSecurRemote.md @@ -0,0 +1,8 @@ +--- +name: "Checkpoint SecurRemote" +categories: ['vpn'] +compatibility: native +display_result: "Compatible" +version_from: "E87.60" +link: https://support.checkpoint.com/results/sk/sk170777 +--- diff --git a/src/content/applications/CiscoAnyConnectHostScan.md b/src/content/applications/CiscoAnyConnectHostScan.md new file mode 100644 index 00000000..cb45abac --- /dev/null +++ b/src/content/applications/CiscoAnyConnectHostScan.md @@ -0,0 +1,8 @@ +--- +name: "Cisco AnyConnect HostScan" +categories: ['vpn'] +compatibility: native +display_result: "Compatible" +version_from: "4.10.08029" +link: https://software.cisco.com/download/home/286281283/type/282364313/release/HostScan4.10 +--- diff --git a/src/content/applications/CiscoAnyConnectNVM.md b/src/content/applications/CiscoAnyConnectNVM.md new file mode 100644 index 00000000..276cfe24 --- /dev/null +++ b/src/content/applications/CiscoAnyConnectNVM.md @@ -0,0 +1,8 @@ +--- +name: "Cisco AnyConnect NVM" +categories: ['vpn'] +compatibility: native +display_result: "Compatible" +version_from: "4.10.08029" +link: https://software.cisco.com/download/home/286281283/type/282364313/release/4.10.08029 +--- diff --git a/src/content/applications/CiscoISEPosture.md b/src/content/applications/CiscoISEPosture.md new file mode 100644 index 00000000..daba9741 --- /dev/null +++ b/src/content/applications/CiscoISEPosture.md @@ -0,0 +1,8 @@ +--- +name: "Cisco ISE Posture" +categories: ['vpn'] +compatibility: native +display_result: "Compatible" +version_from: "4.10.08029" +link: https://software.cisco.com/download/home/286281283/type/282364313/release/4.10.08029 +--- diff --git a/src/content/applications/CiscoSecureEndpointAMP.md b/src/content/applications/CiscoSecureEndpointAMP.md new file mode 100644 index 00000000..85449cad --- /dev/null +++ b/src/content/applications/CiscoSecureEndpointAMP.md @@ -0,0 +1,8 @@ +--- +name: "Cisco Secure Endpoint (AMP)" +categories: ['endpoint-sec'] +compatibility: native +display_result: "Compatible" +version_from: "8.4.1.x" +link: https://www.cisco.com/c/en/us/support/docs/security/amp-endpoints/215704-installation-and-configuration-of-amp-co.html#toc-hId-727641374 +--- diff --git a/src/content/applications/CiscoUmbrella.md b/src/content/applications/CiscoUmbrella.md new file mode 100644 index 00000000..759646a7 --- /dev/null +++ b/src/content/applications/CiscoUmbrella.md @@ -0,0 +1,8 @@ +--- +name: "Cisco Umbrella" +categories: ['data-prot'] +compatibility: native +display_result: "Compatible" +version_from: "5.0.03072" +link: https://support.umbrella.com/hc/en-us/articles/20006704794516-Cisco-Secure-Client-software-download-now-available-from-the-Umbrella-Dashboard +--- diff --git a/src/content/applications/CitrixEndpointManager.md b/src/content/applications/CitrixEndpointManager.md new file mode 100644 index 00000000..d16d9600 --- /dev/null +++ b/src/content/applications/CitrixEndpointManager.md @@ -0,0 +1,7 @@ +--- +name: "Citrix Endpoint Manager" +categories: ['it'] +compatibility: emulation +display_result: "Compatible" +link: https://www.citrix.com/downloads/citrix-endpoint-management/ +--- diff --git a/src/content/applications/ClamAV.md b/src/content/applications/ClamAV.md new file mode 100644 index 00000000..10318d21 --- /dev/null +++ b/src/content/applications/ClamAV.md @@ -0,0 +1,8 @@ +--- +name: "Clam AV" +categories: ['endpoint-sec'] +compatibility: native +display_result: "Compatible" +version_from: "1.4.1" +link: https://www.clamav.net/downloads +--- diff --git a/src/content/applications/Code42BackupAgent.md b/src/content/applications/Code42BackupAgent.md new file mode 100644 index 00000000..1844ee18 --- /dev/null +++ b/src/content/applications/Code42BackupAgent.md @@ -0,0 +1,8 @@ +--- +name: "Code42 Backup Agent" +categories: ['it-tools-vdi'] +compatibility: emulation +display_result: "Compatible" +version_from: "12.3.0" +link: https://support.code42.com/hc/en-us/articles/14827667503511-Downloads-reference#h_01HCATR3S01E4VNF13CJCE58GB +--- diff --git a/src/content/applications/Code42Incydr.md b/src/content/applications/Code42Incydr.md new file mode 100644 index 00000000..c699ae19 --- /dev/null +++ b/src/content/applications/Code42Incydr.md @@ -0,0 +1,8 @@ +--- +name: "Code42 Incydr" +categories: ['data-prot'] +compatibility: native +display_result: "Compatible" +version_from: "1.10.0.31" +link: https://support.code42.com/hc/en-us/articles/14827667503511-Downloads-reference#downloads-reference-0-0 +--- diff --git a/src/content/applications/CommercialVantage.md b/src/content/applications/CommercialVantage.md new file mode 100644 index 00000000..b8a205fe --- /dev/null +++ b/src/content/applications/CommercialVantage.md @@ -0,0 +1,8 @@ +--- +name: "Commercial Vantage" +categories: ['it-tools-vdi'] +compatibility: native +display_result: "Compatible" +version_from: "17763.0" +link: https://apps.microsoft.com/detail/9nr5b8gvvm13?hl=en-us&gl=US +--- diff --git a/src/content/applications/CrowdStrikeEDR.md b/src/content/applications/CrowdStrikeEDR.md new file mode 100644 index 00000000..f6ecf941 --- /dev/null +++ b/src/content/applications/CrowdStrikeEDR.md @@ -0,0 +1,8 @@ +--- +name: "CrowdStrike EDR" +categories: ['endpoint-sec'] +compatibility: native +display_result: "Compatible" +version_from: "71.0" +link: https://www.crowdstrike.com/products/trials/try-falcon-prevent/ +--- diff --git a/src/content/applications/CrowdStrikeProtectOSML.md b/src/content/applications/CrowdStrikeProtectOSML.md new file mode 100644 index 00000000..95b1a8bd --- /dev/null +++ b/src/content/applications/CrowdStrikeProtectOSML.md @@ -0,0 +1,8 @@ +--- +name: "CrowdStrike Protect (OSML)" +categories: ['endpoint-sec'] +compatibility: native +display_result: "Compatible" +version_from: "71.0" +link: https://www.crowdstrike.com/products/trials/try-falcon-prevent/ +--- diff --git a/src/content/applications/CrowdStrikeScriptControl.md b/src/content/applications/CrowdStrikeScriptControl.md new file mode 100644 index 00000000..f2bf07f8 --- /dev/null +++ b/src/content/applications/CrowdStrikeScriptControl.md @@ -0,0 +1,8 @@ +--- +name: "CrowdStrike Script Control" +categories: ['endpoint-sec'] +compatibility: native +display_result: "Compatible" +version_from: "71.0" +link: https://www.crowdstrike.com/products/trials/try-falcon-prevent/ +--- diff --git a/src/content/applications/EnCaseEnhancedAgent.md b/src/content/applications/EnCaseEnhancedAgent.md new file mode 100644 index 00000000..f85393b6 --- /dev/null +++ b/src/content/applications/EnCaseEnhancedAgent.md @@ -0,0 +1,8 @@ +--- +name: "EnCase Enhanced Agent" +categories: ['it-sec-tools'] +compatibility: native +display_result: "Compatible" +version_from: "24.4" +link: https://support.opentext.com/csm?id=search&spa=1&q=%23EndpointInvestigator24.4 +--- diff --git a/src/content/applications/EncaseCoreAgent.md b/src/content/applications/EncaseCoreAgent.md new file mode 100644 index 00000000..994afe69 --- /dev/null +++ b/src/content/applications/EncaseCoreAgent.md @@ -0,0 +1,8 @@ +--- +name: "Encase Core Agent" +categories: ['it-sec-tools'] +compatibility: native +display_result: "Compatible" +version_from: "24.3" +link: https://www.opentext.com/products/encase-forensic +--- diff --git a/src/content/applications/F5BigIP.md b/src/content/applications/F5BigIP.md new file mode 100644 index 00000000..e011af04 --- /dev/null +++ b/src/content/applications/F5BigIP.md @@ -0,0 +1,8 @@ +--- +name: "F5 BigIP" +categories: ['vpn'] +compatibility: native +display_result: "Compatible" +version_from: "7.2.2" +link: https://my.f5.com/manage/s/article/K44328534#p1 +--- diff --git a/src/content/applications/FlexeraFNMS.md b/src/content/applications/FlexeraFNMS.md new file mode 100644 index 00000000..77e84dd5 --- /dev/null +++ b/src/content/applications/FlexeraFNMS.md @@ -0,0 +1,8 @@ +--- +name: "Flexera FNMS" +categories: ['it'] +compatibility: emulation +display_result: "Compatible" +version_from: "2023 R2" +link: https://docs.flexera.com/FlexNetManagerSuite2023R2/EN/Features/index.html#FeatureList/2023R2/RN-chg-fiaWinARM.html +--- diff --git a/src/content/applications/FlexeraITAM.md b/src/content/applications/FlexeraITAM.md new file mode 100644 index 00000000..d681da88 --- /dev/null +++ b/src/content/applications/FlexeraITAM.md @@ -0,0 +1,8 @@ +--- +name: "Flexera ITAM" +categories: ['it'] +compatibility: emulation +display_result: "Compatible" +version_from: "2023 R2" +link: https://docs.flexera.com/FlexNetManagerSuite2023R2/EN/Features/index.html#FeatureList/2023R2/RN-chg-fiaWinARM.html +--- diff --git a/src/content/applications/ForcepointDLP.md b/src/content/applications/ForcepointDLP.md new file mode 100644 index 00000000..bef0adbb --- /dev/null +++ b/src/content/applications/ForcepointDLP.md @@ -0,0 +1,8 @@ +--- +name: "Forcepoint DLP" +categories: ['data-prot'] +compatibility: native +display_result: "Compatible" +version_from: "24.07" +link: https://help.forcepoint.com/F1E/en-us/v24/ep_release_notes/oxy_ex-1/ig/guid-756b0ebb-ec47-4c6b-b34b-df4b427b6482.html +--- diff --git a/src/content/applications/IvantiApps@Work.md b/src/content/applications/IvantiApps@Work.md new file mode 100644 index 00000000..99868808 --- /dev/null +++ b/src/content/applications/IvantiApps@Work.md @@ -0,0 +1,8 @@ +--- +name: "Ivanti Apps@Work" +categories: ['it'] +compatibility: native +display_result: "Compatible" +version_from: "9.6.0.2" +link: https://help.ivanti.com/mi/help/en_us/cld/admin/ivanti/91/all/en-us/Apps@Work%20(iOS,%20Android,%20Windows,%20and%20macOS).htm#Windows%20Apps@Work +--- diff --git a/src/content/applications/IvantiLANDesk.md b/src/content/applications/IvantiLANDesk.md new file mode 100644 index 00000000..33afec5c --- /dev/null +++ b/src/content/applications/IvantiLANDesk.md @@ -0,0 +1,8 @@ +--- +name: "Ivanti LANDesk" +categories: ['it'] +compatibility: native +display_result: "Compatible" +version_from: "2021.1 SU1" +link: https://www.ivanti.com/resources/downloads +--- diff --git a/src/content/applications/LakeSideSystrack.md b/src/content/applications/LakeSideSystrack.md new file mode 100644 index 00000000..cb1f91bc --- /dev/null +++ b/src/content/applications/LakeSideSystrack.md @@ -0,0 +1,8 @@ +--- +name: "LakeSide Systrack" +categories: ['it'] +compatibility: native +display_result: "Compatible" +version_from: "11.0" +link: https://docs.lakesidesoftware.com/Content/Contact%20Lakeside%20Support.htm?tocpath=About%20SysTrack%7CContact%20Lakeside%20Support%7C_____0 +--- diff --git a/src/content/applications/MalwareBytes.md b/src/content/applications/MalwareBytes.md new file mode 100644 index 00000000..db50c7a9 --- /dev/null +++ b/src/content/applications/MalwareBytes.md @@ -0,0 +1,7 @@ +--- +name: "MalwareBytes" +categories: ['endpoint-sec'] +compatibility: native +display_result: "Compatible" +link: https://www.malwarebytes.com/for-home +--- diff --git a/src/content/applications/Netskope.md b/src/content/applications/Netskope.md new file mode 100644 index 00000000..e04420e0 --- /dev/null +++ b/src/content/applications/Netskope.md @@ -0,0 +1,7 @@ +--- +name: "Netskope" +categories: ['data-prot'] +compatibility: native +display_result: "Compatible" +link: https://docs.netskope.com/en/netskope-client-for-windows/ +--- diff --git a/src/content/applications/NexThink.md b/src/content/applications/NexThink.md new file mode 100644 index 00000000..b2ade8c9 --- /dev/null +++ b/src/content/applications/NexThink.md @@ -0,0 +1,8 @@ +--- +name: "NexThink" +categories: ['it'] +compatibility: native +display_result: "Compatible" +version_from: "21.8" +link: https://docs.nexthink.com/platform/getting-started/installing-collector/installing-collector-on-windows +--- diff --git a/src/content/applications/Okta.md b/src/content/applications/Okta.md new file mode 100644 index 00000000..ef15da26 --- /dev/null +++ b/src/content/applications/Okta.md @@ -0,0 +1,7 @@ +--- +name: "Okta" +categories: ['vpn'] +compatibility: emulation +display_result: "Compatible" +link: https://support.okta.com/help/s/article/Direct-download-links-to-The-Latest-Versions-Of-Okta-Verify?language=en_US +--- diff --git a/src/content/applications/PolicyPakCSE.md b/src/content/applications/PolicyPakCSE.md new file mode 100644 index 00000000..90678b85 --- /dev/null +++ b/src/content/applications/PolicyPakCSE.md @@ -0,0 +1,8 @@ +--- +name: "PolicyPak CSE" +categories: ['it-tools-vdi'] +compatibility: native +display_result: "Compatible" +version_from: "23.11" +link: https://www.policypak.com/company/contact-us-for-a-trial/ +--- diff --git a/src/content/applications/PolicyPakCloudConnector.md b/src/content/applications/PolicyPakCloudConnector.md new file mode 100644 index 00000000..cc7d86eb --- /dev/null +++ b/src/content/applications/PolicyPakCloudConnector.md @@ -0,0 +1,8 @@ +--- +name: "PolicyPak Cloud Connector" +categories: ['it-tools-vdi'] +compatibility: native +display_result: "Compatible" +version_from: "23.11" +link: https://www.policypak.com/company/contact-us-for-a-trial/ +--- diff --git a/src/content/applications/RSANetWitness.md b/src/content/applications/RSANetWitness.md new file mode 100644 index 00000000..5f60d62a --- /dev/null +++ b/src/content/applications/RSANetWitness.md @@ -0,0 +1,8 @@ +--- +name: "RSA NetWitness" +categories: ['endpoint-sec'] +compatibility: native +display_result: "Compatible" +version_from: "11.0" +link: https://auth.rsasecurity.com/IMS-AA-IDP/InitialLogonDispatch.do +--- diff --git a/src/content/applications/Rapid7VM.md b/src/content/applications/Rapid7VM.md new file mode 100644 index 00000000..14827ccf --- /dev/null +++ b/src/content/applications/Rapid7VM.md @@ -0,0 +1,8 @@ +--- +name: "Rapid7 VM" +categories: ['data-prot'] +compatibility: emulation +display_result: "Compatible" +version_from: "4.0.10" +link: https://docs.rapid7.com/insight-agent/install/ +--- diff --git a/src/content/applications/SafeNetMinidriver109.md b/src/content/applications/SafeNetMinidriver109.md new file mode 100644 index 00000000..688ee8e3 --- /dev/null +++ b/src/content/applications/SafeNetMinidriver109.md @@ -0,0 +1,8 @@ +--- +name: "SafeNet Minidriver 10.9" +categories: ['it-sec-tools'] +compatibility: native +display_result: "Compatible" +version_from: "10.9.3120" +link: https://supportportal.thalesgroup.com/csm?id=kb_article_view&sys_kb_id=251a10664761cad054c15502e26d4370&sysparm_article=KB0028458 +--- diff --git a/src/content/applications/SafenetAuthenticationClient.md b/src/content/applications/SafenetAuthenticationClient.md new file mode 100644 index 00000000..e714ac7b --- /dev/null +++ b/src/content/applications/SafenetAuthenticationClient.md @@ -0,0 +1,8 @@ +--- +name: "Safenet Authentication Client" +categories: ['vpn'] +compatibility: native +display_result: "Compatible" +version_from: "10.8-R9" +link: https://support.globalsign.com/code-signing/safenet-drivers +--- diff --git a/src/content/applications/SentinelOne.md b/src/content/applications/SentinelOne.md new file mode 100644 index 00000000..2afc38a9 --- /dev/null +++ b/src/content/applications/SentinelOne.md @@ -0,0 +1,8 @@ +--- +name: "SentinelOne" +categories: ['endpoint-sec'] +compatibility: native +display_result: "Compatible" +version_from: "24.1" +link: https://www.sentinelone.com/resources/s1_windows_server_agent/ +--- diff --git a/src/content/applications/SophosInterceptX.md b/src/content/applications/SophosInterceptX.md new file mode 100644 index 00000000..698daecc --- /dev/null +++ b/src/content/applications/SophosInterceptX.md @@ -0,0 +1,7 @@ +--- +name: "Sophos Intercept X" +categories: ['endpoint-sec'] +compatibility: native +display_result: "Compatible" +link: https://news.sophos.com/en-us/2021/06/24/intercept-x-now-supports-windows-arm64/ +--- diff --git a/src/content/applications/SplunkUF.md b/src/content/applications/SplunkUF.md new file mode 100644 index 00000000..22ccc301 --- /dev/null +++ b/src/content/applications/SplunkUF.md @@ -0,0 +1,8 @@ +--- +name: "Splunk UF*" +categories: ['it-tools-vdi'] +compatibility: native +display_result: "Compatible" +version_from: "8.1" +link: https://www.splunk.com/en_us/download/universal-forwarder.html +--- diff --git a/src/content/applications/SymantecDLP.md b/src/content/applications/SymantecDLP.md new file mode 100644 index 00000000..0afcb08a --- /dev/null +++ b/src/content/applications/SymantecDLP.md @@ -0,0 +1,8 @@ +--- +name: "Symantec DLP" +categories: ['data-prot'] +compatibility: native +display_result: "Compatible" +version_from: "16.0 RU2" +link: https://knowledge.broadcom.com/external/article/185118/dlp-endpoint-agent-build-numbers-and-lat.html +--- diff --git a/src/content/applications/SymantecEP.md b/src/content/applications/SymantecEP.md new file mode 100644 index 00000000..967dc6d2 --- /dev/null +++ b/src/content/applications/SymantecEP.md @@ -0,0 +1,8 @@ +--- +name: "Symantec EP" +categories: ['endpoint-sec'] +compatibility: native +display_result: "Compatible" +version_from: "14.3 RU7" +link: https://knowledge.broadcom.com/external/article/273805/windows-arm-support-for-endpoint-protect.html +--- diff --git a/src/content/applications/SymantecWSS.md b/src/content/applications/SymantecWSS.md new file mode 100644 index 00000000..e3eab6b1 --- /dev/null +++ b/src/content/applications/SymantecWSS.md @@ -0,0 +1,8 @@ +--- +name: "Symantec WSS" +categories: ['data-prot'] +compatibility: native +display_result: "Compatible" +version_from: "9.1.1" +link: https://status.broadcom.com/services/cloud-secure-web-gateway/notices/syrdaiolx1nkf3b6-cloud-swg-wss-agent-infrastructure-maintenance-october-25-28-2024 +--- diff --git a/src/content/applications/TaniumThreatResponse.md b/src/content/applications/TaniumThreatResponse.md new file mode 100644 index 00000000..06f3ea56 --- /dev/null +++ b/src/content/applications/TaniumThreatResponse.md @@ -0,0 +1,7 @@ +--- +name: "Tanium Threat Response" +categories: ['data-prot'] +compatibility: native +display_result: "Compatible" +link: https://www.tanium.com/press-releases/tanium-platform-advances-threat-identification-capabilities-and-enhances-endpoint-reach/ +--- diff --git a/src/content/applications/TrendMicroApex.md b/src/content/applications/TrendMicroApex.md new file mode 100644 index 00000000..c789102e --- /dev/null +++ b/src/content/applications/TrendMicroApex.md @@ -0,0 +1,8 @@ +--- +name: "Trend Micro Apex" +categories: ['endpoint-sec'] +compatibility: native +display_result: "Compatible" +version_from: "20.0.0-6912" +link: https://www.trendmicro.com/en_us/business/products/endpoint-security.html +--- diff --git a/src/content/applications/UberAgent.md b/src/content/applications/UberAgent.md new file mode 100644 index 00000000..8ce4a8f2 --- /dev/null +++ b/src/content/applications/UberAgent.md @@ -0,0 +1,8 @@ +--- +name: "UberAgent" +categories: ['it'] +compatibility: native +display_result: "Compatible" +version_from: "7.3" +link: https://uberagent.com/download/uberagent/ +--- diff --git a/src/content/applications/VB-AudioVoicemeeter.md b/src/content/applications/VB-AudioVoicemeeter.md index 9f33d681..e77d2eda 100644 --- a/src/content/applications/VB-AudioVoicemeeter.md +++ b/src/content/applications/VB-AudioVoicemeeter.md @@ -3,6 +3,7 @@ name: "VB-Audio Voicemeeter" categories: ["audio"] compatibility: native display_result: "Compatible" +version_from: "1.1.1.8" link: https://download.vb-audio.com/Download_CABLE/VoicemeeterSetup_v1118.zip icon: Voicemeeter.png --- diff --git a/src/content/applications/VMWareWorkspaceOne.md b/src/content/applications/VMWareWorkspaceOne.md new file mode 100644 index 00000000..d5616414 --- /dev/null +++ b/src/content/applications/VMWareWorkspaceOne.md @@ -0,0 +1,8 @@ +--- +name: "VMWare WorkspaceOne" +categories: ['it'] +compatibility: native +display_result: "Compatible" +version_from: "2111" +link: https://support.broadcom.com/ +--- diff --git a/src/content/applications/VenafiCertificateManagement.md b/src/content/applications/VenafiCertificateManagement.md new file mode 100644 index 00000000..45136ec2 --- /dev/null +++ b/src/content/applications/VenafiCertificateManagement.md @@ -0,0 +1,7 @@ +--- +name: "Venafi Certificate Management" +categories: ['it-sec-tools'] +compatibility: emulation +display_result: "Compatible" +link: https://download.venafi.com/ +--- diff --git a/src/content/applications/WatchGuard.md b/src/content/applications/WatchGuard.md new file mode 100644 index 00000000..b6493795 --- /dev/null +++ b/src/content/applications/WatchGuard.md @@ -0,0 +1,7 @@ +--- +name: "WatchGuard" +categories: ['endpoint-sec'] +compatibility: native +display_result: "Compatible" +link: https://www.watchguard.com/help/docs/help-center/en-US/Content/en-US/Endpoint-Security/installation/download-client-agent-installer.html +--- diff --git a/src/content/applications/ZscalerZDX.md b/src/content/applications/ZscalerZDX.md new file mode 100644 index 00000000..78ccea1e --- /dev/null +++ b/src/content/applications/ZscalerZDX.md @@ -0,0 +1,8 @@ +--- +name: "Zscaler ZDX" +categories: ['vpn'] +compatibility: native +display_result: "Compatible" +version_from: "3.7.2.18" +link: https://help.zscaler.com/client-connector/understanding-zscaler-client-connector-app-downloads +--- From 7ea022df4bc62a6ee9671b04edcb5170b72ed5ac Mon Sep 17 00:00:00 2001 From: Alberto Ito Date: Tue, 26 Nov 2024 14:46:53 -0300 Subject: [PATCH 02/11] Added translated markdown files --- src/pages/ja/contributing.md | 180 ++++++++++++++++++++++++++++++++++ src/pages/ja/help.md | 53 ++++++++++ src/pages/ja/index.md | 32 ++++++ src/pages/ja/takedown.md | 9 ++ src/pages/ko/contributing.md | 182 +++++++++++++++++++++++++++++++++++ src/pages/ko/help.md | 53 ++++++++++ src/pages/ko/index.md | 32 ++++++ src/pages/ko/takedown.md | 9 ++ src/pages/zh/contributing.md | 182 +++++++++++++++++++++++++++++++++++ src/pages/zh/help.md | 53 ++++++++++ src/pages/zh/index.md | 32 ++++++ src/pages/zh/takedown.md | 9 ++ 12 files changed, 826 insertions(+) create mode 100644 src/pages/ja/contributing.md create mode 100644 src/pages/ja/help.md create mode 100644 src/pages/ja/index.md create mode 100644 src/pages/ja/takedown.md create mode 100644 src/pages/ko/contributing.md create mode 100644 src/pages/ko/help.md create mode 100644 src/pages/ko/index.md create mode 100644 src/pages/ko/takedown.md create mode 100644 src/pages/zh/contributing.md create mode 100644 src/pages/zh/help.md create mode 100644 src/pages/zh/index.md create mode 100644 src/pages/zh/takedown.md diff --git a/src/pages/ja/contributing.md b/src/pages/ja/contributing.md new file mode 100644 index 00000000..fc65584d --- /dev/null +++ b/src/pages/ja/contributing.md @@ -0,0 +1,180 @@ +--- +layout: ../../layouts/InfoLayout.astro +title: 貢献する +description: このサイトに貢献する方法 +--- + +# このサイトへの貢献 +- アプリケーション +- ゲーム + +## アプリケーション +アプリの貢献は、GitHubプロジェクトに直接行うか、便利なフォームプロセスを使用できます。 + +### Microsoft Formsを使用して貢献する方法(アプリ) + +以下のフォームにアプリリクエストを記入してください。このフォームを使用して、テストして追加する新しいアプリのリクエストをすることができます。また、アプリに関して何か間違っている場合や、自分の新しいアプリデータを提出する場合にも使用できます。技術的な経験がない限り、GitHubよりもMicrosoft Formsを通じて貢献することをお勧めします。下に、定義されたスキーマとカテゴリの定義についての詳細があります。 + + + +[ここをクリック](https://forms.office.com/r/JZ1ywk2FaJ)してMSフォームを直接開く + +### GitHubを使用して貢献する方法(アプリ) + +自分のGitHubアカウントが必要です。まだ持っていない場合は、https://github.com にアクセスし、ページの右上隅にある**サインアップ**をクリックして、指示に従ってください。 + +アカウントを作成したら、https://github.com/Linaro/works-on-woa/fork に移動して、このウェブサイトのリポジトリを*フォーク*します(つまり、自分のコピーを作成します)。 + +リポジトリをフォークしたら、`git clone`コマンドでコンピューターにクローンします。必要な場合は、https://docs.github.com/en/repositories/creating-and-managing-repositories/cloning-a-repository でさらにガイダンスを確認してください。 + +リポジトリをクローンしたら、ファイルに必要な変更を加えます。異なるファイルに必要な内容やオプションについては、以下のガイダンスを参照してください。助けが必要な場合は、https://github.com/Linaro/works-on-woa/issues/new でイシューを作成してください。できる限りお手伝いします。 + +変更を加えたら、自分のリポジトリに[コミット](https://github.com/git-guides/git-commit)し、[プッシュ](https://github.com/git-guides/git-push)します。 + +最後に、[プルリクエスト](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request-from-a-fork)を作成して、公式リポジトリに変更をマージしてもらうように依頼します。リクエストはレビューされ、承認されればサイトにマージされます。 + +**注意してください!** 変更をGitHubにプッシュする前に、ローカルでウェブサイトをビルドすることを**強く**お勧めします。これにより、サイトが正しくビルドされ、貢献にエラーがないことが保証されます。この手順は、READMEファイルの*開発者情報*セクションに記載されています。 + +#### ファイル内容の詳細 + +アプリケーションには、提出されたデータの一貫性を確保するための*スキーマ*があります。 + +各エントリは、`.md`ファイル拡張子の付いたファイルに保存されます。アプリケーションエントリは、`src/content/applications`の下に保存されます。 + +既存のエントリに関する独自のレポートを貢献する場合、それは適切に`src/content/user_reports_applications`または`src/content/user_reports_games`に保存されるべきです。 + +各ファイルは以下で構成されています: + +- 3つのダッシュ`---` +- 下記の詳細に従ったプロジェクト固有の情報 +- 3つのダッシュ`---` +- GitHub Markdown形式の追加ノート + +##### アプリケーションスキーマ + +アプリケーションエントリに格納される情報は、次のスキーマに従う必要があります: + +| フィールド | タイプ | 注記 | +|-|-|-| +| `name` | string | アプリケーションの名前です。 | +| `icon` | string | オプション。`public/icons` 相対のアイコンファイルのパス。最大サイズは512x512。可能であればSVGを使用してください。 | +| `categories` | list | アプリケーションが属する1つ以上のカテゴリのリスト。カテゴリのリストは `src/content/applications_categories` にあります。このフォルダ内のファイル名でカテゴリを参照します。 | +| `display_result` | enum | Arm互換性の表示:
Compatible: テストされたアプリケーションはWindows on Armで動作します
Unknown: ステータスは不明です
Unsupported: 現在、この値は使用されていません
Vendor Announced - Launching Soon: 現在、この値は使用されていません | +| `compatibility` | enum | Windows on Arm互換性:
Native: WoAネイティブサポートが利用可能
Emulation: x86/x64エミュレーションで動作
No: まだ移植されていない
Unknown: ステータスは不明 | +| `version_from` | string | 使用可能なバージョンです。

ソフトウェアがあるバージョンからコンパイル可能であるが、別のバージョンからのみ公開されている場合(例えば、Pythonはかなり早くからコンパイル可能でしたが、WoAリリースを開始したのは後からです)、ここには一般的にエンドユーザーが使用する公開バージョンを入力します。

コンパイル可能なバージョン(およびそれに関連する注意事項)は、自由形式でノートセクションに追加できます。 | +| `link` | URL | ソフトウェアのダウンロード先リンクまたはアプリケーションのメインウェブサイト。 | + +### アプリケーションユーザー報告スキーマ + +ユーザーは、このサイトに追加されたアプリケーションに関する自分の調査結果を追加できます。ファイルは**一意の**ファイル名(`.md` 拡張子付き)を持ち、内容は次のスキーマに従う必要があります: + +| フィールド | タイプ | 注記 | +|-|-|-| +| `reporter` | string | オプション。あなたの名前です。 | +| `application` | string | アプリケーションのファイル名から `.md` 拡張子を**含まない**名前です。 | +| `device_configuration` | string | オプション。レポートに影響を与える可能性のある構成に関する情報。 | +| `date_tested` | date | オプション。形式は `YYYY-MM-DD` です。 | +| `compatibility_details` | string | アプリケーションの動作に関するあなたの報告内容です。 | + +#### カテゴリ + +カテゴリリストは、角括弧`[` で始まり、1つ以上のカテゴリをカンマで区切り、角括弧 `]` で閉じられます。 + +カテゴリは、前述の適切なカテゴリフォルダ内の `.md` ファイル名と一致する必要があります。 + +## ゲーム +貢献は、GitHub プロジェクトに直接、または便利なフォームプロセスを通じて行うことができます。 + +### Microsoft Forms を使用して貢献する方法 (ゲーム) + +以下のフォームにゲームテストの詳細を入力してください。技術的な経験がある場合を除き、GitHub よりも Microsoft フォームでの貢献をお勧めします。定義されたスキーマおよびカテゴリ定義の詳細は、下にスクロールして確認してください。 + + + +### GitHub を使用して貢献する方法 (ゲーム) + +GitHub アカウントが必要です。まだアカウントをお持ちでない場合は、https://github.com にアクセスし、ページの右上隅にある **Sign up** をクリックし、指示に従って登録してください。 + +アカウントを取得したら、https://github.com/Linaro/works-on-woa/fork にアクセスして、この Web サイトのリポジトリを「フォーク」(つまり自分のコピーを作成)してください。 + +リポジトリをフォークしたら、`git clone` コマンドを使用してコンピュータにクローンします。詳細なガイダンスが必要な場合は、https://docs.github.com/en/repositories/creating-and-managing-repositories/cloning-a-repository を参照してください。 + +**注意:** リポジトリをローカルでビルドするには、WSL(Windows Subsystem for Linux)内にクローンする必要があります。 + +リポジトリをクローンしたら、ファイルに必要な変更を加えてください。必要に応じて、各ファイルの必要な内容とオプションについてのガイダンスが以下にあります。助けが必要な場合は、https://github.com/Linaro/works-on-woa/issues/new で問題を作成していただければ、可能な限りお手伝いいたします。 + +変更が完了したら、[コミット](https://github.com/git-guides/git-commit)してリポジトリに戻し、GitHub に[プッシュ](https://github.com/git-guides/git-push)します。 + +最後に、公式リポジトリにマージするために[プルリクエスト](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request-from-a-fork)を作成します。リクエストはレビューされ、承認されればサイトにマージされます。 + +**注意!** 変更を GitHub にプッシュする前に、コンピュータでローカルにサイトをビルドすることを強くお勧めします。これにより、サイトが正しくビルドされ、貢献内容にエラーがないことを確認できます。手順については、README ファイルの *Developer Info* セクションを参照してください。 + +### ファイル内容の詳細 + +ゲームに関しては、一貫性を確保するために*スキーマ*が定義されています。 + +各エントリは `.md` ファイル拡張子付きのファイルに保存されます。ゲームエントリは `src/content/games` に保存されます。 + +既存のエントリに関する自分の報告を投稿する場合は、`src/content/user_reports_games` に保存する必要があります。 + +各ファイルには以下が含まれます: + +- 3つのダッシュ `---` +- 以下に詳述するプロジェクト固有の情報 +- 3つのダッシュ `---` +- GitHub Markdown 形式での追加のメモ + +#### ゲームスキーマ + +| フィールド | 型 | 説明 | +|-|-|-| +| `name` | string | ゲームの名前。 | +| `icon` | string | 任意。アイコンファイルのパスを、`public/icons` に相対的に記述。最大512x512。可能であればSVGを使用。 | +| `categories` | list | ゲームが属する1つ以上のカテゴリのリスト。カテゴリの一覧は `src/content/gamess_categories` にあります。フォルダ内のファイル名で参照。 | +| `publisher` | string | 任意。ゲームの発行者名。 | +| `frame_rate` | string | 任意。ゲームのフレームレート(fps)。 | +| `device_configuration` | string | 任意。ゲームテストに使用したデバイス。 | +| `os_version` | string | 任意。ゲームテストに使用したOSバージョン。 | +| `driver_id` | string | 任意。ゲームテストに使用したグラフィックドライバーのID。 | +| `date_tested` | date | 任意。形式は `YYYY-MM-DD` | +| `compatibility` | enum | ゲームの動作状況。詳細はヘルプページを参照。 | +| `compatibility_details` | string | 任意。互換性に関する追加情報。 | +| `auto_super_resolution` | block | 任意。以下の例で構文を参照。 | +| - `compatibility` | enum | 任意。自動スーパー解像度機能との互換性を示す。opt-in は Windows 設定で機能を有効にする必要があり、out-of-box は設定変更なしで適用されることを意味します。 | +| - `fps_boost` | string | 任意。自動SRがゲームのフレームレートをどの程度向上させるか。 | +| - `opt-in steps` | string | 任意。opt-in のゲームに対する自動SRの有効化手順。 | +| `link` | URL | ソフトウェアをダウンロードできるリンク、またはアプリケーションの公式サイト。 | + +`auto_super_resolution` ブロックは任意ですが、存在する場合、`compatibility` 属性が**必須**です。ブロックの形式は以下のようになります: + +``` + auto_super_resolution: + compatibility: yes, out-of-box +``` + +#### ゲームユーザーレポートスキーマ + +ユーザーは、このサイトに追加されたゲームに関する自分の発見を追加できます。ファイルには**ユニーク**なファイル名(`.md`拡張子付き)を使用し、内容は次のスキーマに従う必要があります: + +| フィールド | 型 | 説明 | +|-|-|-| +| `reporter` | string | 任意。あなたの名前。 | +| `game` | string | ゲームのファイル名から取得した名前。`.md`拡張子を**除く** | +| `device_configuration` | string | 任意。使用したデバイスの名前。 | +| `date_tested` | date | 任意。形式は `YYYY-MM-DD` | +| `os_version` | string | 任意。システムのOSバージョン。 | +| `driver_id` | string | 任意。システムのグラフィックスドライバID。 | +| `compatibility` | enum | ゲームの動作状況。定義の詳細はヘルプページを参照してください。 | +| `compatibility_details` | string | アプリケーションがどのように動作したかに関するレポート。 | +| `auto_super_resolution` | block | 任意。 | +| - `compatibility` | enum | 自動スーパー解像度機能との互換性を示します。opt-in は、Windows設定でこの機能を有効にする必要があることを意味します。 | +| - `fps_boost` | string | 自動SRがゲームのフレームレートをどの程度向上させるか。 | +| - `opt-in steps` | string | 任意。opt-in のゲームに対する自動SRの有効化手順。 | + +ユーザーゲームレポートでは、自動スーパー解像度の互換性は `yes, opt-in`、`no` または `unknown` のみとなります。 + +#### カテゴリ + +ゲームのカテゴリリストは、開き角かっこ `[` で始まり、コンマで区切られた1つ以上のカテゴリが続き、閉じ角かっこ `]` で構成されます。 + +カテゴリは、前述した適切なカテゴリフォルダ内の `.md` ファイルのファイル名と一致する必要があります。 diff --git a/src/pages/ja/help.md b/src/pages/ja/help.md new file mode 100644 index 00000000..a7e00adb --- /dev/null +++ b/src/pages/ja/help.md @@ -0,0 +1,53 @@ +--- +layout: ../../layouts/InfoLayout.astro +title: ヘルプ +description: Windows on Arm 対応ソフトウェアウェブサイトのヘルプページ。 +--- + +# このサイトについてのヘルプ + +このウェブサイトは、多くのアプリケーションとゲームに関する情報と、それらが Windows on Arm で動作する際のステータスを提供します。 + +アプリケーションとゲームはカテゴリ別にグループ化され、複数のカテゴリで分類することができます。特定のカテゴリのエントリを見るには、エントリの詳細ページの **Categories** リンクからカテゴリを選択するか、検索バーの右側にあるカテゴリドロップダウンメニューから選択し、拡大鏡をクリックして検索を実行します。複数のカテゴリを同時に選択することができます。 + +アプリケーションの場合、**Compatibility** フィールドは次の値のいずれかです: + +| Value | Meaning | +| --------- | ------------------------------------- | +| Compatible| Windows on Arm (WoA) で動作します。 | +| Unknown | ステータスは不明です。詳細情報は開発者のウェブサイトを確認してください。| + +**Version From** フィールドは、Windows on Arm に対応している最初に知られている公開バージョンのアプリを示します。**Download** ボタンが利用可能な場合、クリックすると Microsoft Store の製品説明ページ、またはアプリのインストールを提供するウェブサイトに移動します。**Unknown** のアプリの場合、**Download** の代わりに **Website** ボタンが表示されます。**Website** ボタンをクリックすると、アプリ開発者の主要なウェブページに移動し、最新のステータスを確認し、Windows on Arm サポートをリクエストするために開発者に直接連絡することができます。 + +このウェブサイトに自分の貢献をする方法について、まだリストされていないアプリのために、または既存のアプリのステータス更新を提供するために、[貢献ガイド](/ja/contributing)をお読みください。 + +ゲームの場合、**Compatibility** フィールドは次の値のいずれかです: + +| Value | Meaning | +| ---------- | ------------------------------------- | +| perfect | 1080p 解像度で 60+ FPS で動作し、ゲーム体験に影響を与えるグリッチ/問題はありません。 | +| playable | 1080p 解像度で 30+ FPS で動作し、ゲーム体験に影響を与える最小限のグリッチ/問題があります。 | +| runs | 30 FPS 未満で動作し、ゲーム体験に影響を与えるバグがあります。 | +| unplayable | チート防止策やその他の失敗により動作しません。 | + +各ゲームでは、次のフィールドが表示されます。以下にそれらの意味を定義しています。 + +**Frame Rate:** ゲームのフレーム毎秒 + +**Device Configuration:** ゲームをテストするために使用したデバイス + +**OS Version:** ゲームがテストされた Windows OS バージョン + +**Driver ID:** ゲームがテストされたグラフィックスドライバー + +**Compatibility Details:** ゲームがどのように動作するかに関する追加情報 + +**Auto Super Resolution:** Auto SRはAIを使用してゲームの解像度をアップスケールし、向上したビジュアル品質でより良いFPSを提供します。 + +**Auto SR Compatability:** Auto SR は、設定を変更することなく動作します。オプトインとは、Windows 設定を介してゲームにオプトインする必要があることを意味します。 + +**Auto SR FPS Boost:** Auto SR を有効にした場合に期待できる FPS ブーストの量を説明します。 + +自動スーパ解像度に対応したゲームを見るには、ゲームページの検索バーの右側にある Auto SR ドロップダウンメニューから「yes, out-of-box」と「yes, opt-in」を選択してください。 + +このウェブサイトに自分の貢献をする方法について、まだリストされていないゲームのために、または既存のゲームに自分のレポートを追加するために、[貢献ガイド](/ja/contributing)をお読みください。 diff --git a/src/pages/ja/index.md b/src/pages/ja/index.md new file mode 100644 index 00000000..00442c28 --- /dev/null +++ b/src/pages/ja/index.md @@ -0,0 +1,32 @@ +--- +layout: ../../layouts/InfoLayout.astro +title: "ホームページ" +description: Windows on Arm 対応ソフトウェア +--- + +ようこそ、Windows on Arm で動作するサイトへ! + +このサイトは、Arm アーキテクチャで動作する Windows デバイス向けの多くのアプリとゲームの互換性情報の源です。今後、随時更新されます。 + +互換性の定義とサイトのナビゲーション方法についての詳細は、[ヘルプページ](/ja/help)を参照してください。 + +アプリやゲームをテストした結果を提供したい場合は、[貢献ガイド](/ja/contributing)をお読みいただき、GitHub のオープンソースリポジトリへのプルリクエストを提出する方法をお手伝いします。 + +この情報はガイドとして提供されていますが、ゲームが確実に動作することを保証するものではありません。結果はテストされていますが、特定のマシンや構成では動作しない可能性があります。結果が異なる場合は、ぜひ自身の発見をサイトに貢献してください。 + + diff --git a/src/pages/ja/takedown.md b/src/pages/ja/takedown.md new file mode 100644 index 00000000..fa2997a3 --- /dev/null +++ b/src/pages/ja/takedown.md @@ -0,0 +1,9 @@ +--- +layout: ../../layouts/InfoLayout.astro +title: タケダウン +description: Windows on Arm ready ウェブサイトからエントリを削除することに関する権利保持者向けの情報。 +--- + +# コンテンツ削除リクエスト + +このサイトからあなたの製品またはロゴを削除したい場合は、適切な情報を添えて [it-support@linaro.org](mailto:it-support@linaro.org) にメールしてください。 diff --git a/src/pages/ko/contributing.md b/src/pages/ko/contributing.md new file mode 100644 index 00000000..1c8c29b0 --- /dev/null +++ b/src/pages/ko/contributing.md @@ -0,0 +1,182 @@ +--- +layout: ../../layouts/InfoLayout.astro +title: 기여하기 +description: 이 사이트에 기여하는 방법 +--- + +# 이 사이트에 기여하기 +- 애플리케이션 +- 게임 + +## 애플리케이션 +애플리케이션 기여는 GitHub 프로젝트를 통해 직접 하거나, 편리한 폼 작성 방식으로 제출할 수 있습니다. + +### Microsoft Forms를 통한 기여 방법 (애플리케이션) + +아래의 양식을 작성하여 애플리케이션 요청을 제출하십시오. 이 양식을 통해 새로운 애플리케이션을 테스트 및 추가 요청하거나, 기존 애플리케이션에 대한 오류를 알리거나, 새 애플리케이션 데이터를 제출할 수 있습니다. 기술 경험이 없는 경우 GitHub보다는 Microsoft Form을 통해 기여하는 것을 권장합니다. 정의된 스키마와 카테고리 정의에 대한 자세한 내용은 아래로 스크롤하여 확인하십시오. + + + +[여기를 클릭하여](https://forms.office.com/r/JZ1ywk2FaJ) Microsoft 양식을 직접 열기 + +### GitHub를 통한 기여 방법 (애플리케이션) + +GitHub 계정이 필요합니다. 계정이 없다면 https://github.com 으로 이동하여, 페이지 오른쪽 상단의 **Sign up**을 클릭하고 지시에 따라 계정을 만드세요. + +계정이 생긴 후, https://github.com/Linaro/works-on-woa/fork 로 가서 이 사이트의 리포지토리를 *포크* (즉, 사본 만들기)하세요. + +포크가 완료되면, `git clone` 명령을 사용하여 컴퓨터에 리포지토리를 클론합니다. 추가 지침이 필요하면 https://docs.github.com/en/repositories/creating-and-managing-repositories/cloning-a-repository 를 참조하세요. + +클론한 리포지토리에서 파일에 필요한 변경 사항을 적용합니다. 각 파일에 필요한 필수 및 선택적 콘텐츠에 대한 가이드는 아래에서 확인할 수 있습니다. 도움이 필요하면 https://github.com/Linaro/works-on-woa/issues/new 에서 이슈를 생성해 주세요. 최선을 다해 도움을 드리겠습니다. + +변경 사항을 완료한 후 [커밋](https://github.com/git-guides/git-commit)하고, [푸시](https://github.com/git-guides/git-push)하여 GitHub에 반영합니다. + +마지막으로, 공식 리포지토리에 변경 사항을 병합하도록 요청하는 [풀 리퀘스트](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request-from-a-fork)를 만듭니다. 요청이 검토되며, 승인되면 사이트에 병합됩니다. + +**주의 사항!** 변경 사항을 GitHub에 반영하기 전에 로컬 컴퓨터에서 웹사이트를 빌드해보는 것이 **강력히** 권장됩니다. 이를 통해 사이트가 올바르게 빌드되며, 기여에 오류가 없는지 확인할 수 있습니다. 자세한 내용은 README 파일의 *개발자 정보* 섹션을 참조하세요. + +#### 파일 콘텐츠 세부 정보 + +기여 데이터의 일관성을 보장하기 위해 애플리케이션에는 정의된 *스키마*가 사용됩니다. + +각 항목은 `.md` 파일 확장자로 저장됩니다. 애플리케이션 항목은 `src/content/applications`에 저장됩니다. + +기존 항목에 대한 보고서를 기여하는 경우 적절히 `src/content/user_reports_applications` 또는 `src/content/user_reports_games`에 저장합니다. + +각 파일에는 다음이 포함됩니다: + +- 세 개의 대시 `---` +- 프로젝트별 세부 정보 +- 세 개의 대시 `---` +- GitHub Markdown 형식의 추가 메모 + +##### 애플리케이션 스키마 + +애플리케이션 항목에 저장된 정보는 다음 스키마를 따라야 합니다: + +| 필드 | 타입 | 참고 사항 | +|-|-|-| +| `name` | string | 애플리케이션의 이름입니다. | +| `icon` | string | 선택 사항. `public/icons` 에 상대적인 아이콘 파일 경로. 최대 512x512. 가능하면 SVG를 사용하세요. | +| `categories` | list | 애플리케이션이 속한 하나 이상의 카테고리 목록. 카테고리 목록은 `src/content/applications_categories` 에 있습니다. 이 폴더의 파일 이름으로 카테고리를 참조합니다. | +| `display_result` | enum | 표시된 Arm 호환성:
Compatible: 테스트된 앱이 Windows on Arm에서 작동합니다
Unknown: 상태를 알 수 없습니다
Unsupported: 현재 이 값은 사용되지 않습니다
Vendor Announced - Launching Soon: 현재 이 값은 사용되지 않습니다 | +| `compatibility` | enum | Windows on Arm 호환성:
Native: WoA 네이티브 지원이 가능
Emulation: x86/x64 에뮬레이션으로 작동
No: 아직 이식되지 않음
Unknown: 상태를 알 수 없음 | +| `version_from` | string | 사용할 수 있는 버전입니다.

소프트웨어가 특정 버전에서 컴파일할 수 있지만 다른 버전에서만 공개된 경우(예: Python은 상당히 일찍 컴파일할 수 있었지만 WoA 릴리스를 시작한 것은 나중이었음), 대부분의 최종 사용자가 원하는 공개 버전을 여기에 입력해야 합니다.

컴파일 가능한 버전(및 관련된 주의 사항)은 노트 섹션에 자유롭게 추가할 수 있습니다. | +| `link` | URL | 소프트웨어 다운로드 링크 또는 애플리케이션의 메인 웹사이트. | + +### 애플리케이션 사용자 보고 스키마 + +사용자는 이 사이트에 추가된 애플리케이션에 대한 자신의 발견 사항을 추가할 수 있습니다. 파일은 **고유한** 파일 이름(확장자는 `.md`)을 가져야 하며, 내용은 다음 스키마를 따라야 합니다: + +| 필드 | 타입 | 참고 사항 | +|-|-|-| +| `reporter` | string | 선택 사항. 사용자 이름입니다. | +| `application` | string | 애플리케이션 파일의 이름에서 `.md` 확장자를 **제외한** 이름입니다. | +| `device_configuration` | string | 선택 사항. 보고서에 영향을 미칠 수 있는 구성에 대한 정보입니다. | +| `date_tested` | date | 선택 사항. 형식은 `YYYY-MM-DD`입니다. | +| `compatibility_details` | string | 애플리케이션 실행에 대한 사용자 보고 내용입니다. | + +#### 카테고리 + +카테고리 목록은 대괄호 `[`로 시작하고, 쉼표로 구분된 하나 이상의 카테고리로 구성되며, 대괄호 `]`로 끝납니다. + +카테고리는 앞서 지정된 적절한 카테고리 폴더 내의 `.md` 파일 이름과 일치해야 합니다. + +## 게임 +GitHub 프로젝트에 직접 기여하거나, 편리한양식 프로세스를 통해 기여할 수 있습니다. + +### Microsoft Forms를 통한 기여 방법 (게임) + +아래 양식에 게임 테스트 정보를 작성하십시오. 기술적 경험이 없는 경우 Microsoft Forms를 통한 기여를 권장합니다. 정의된 스키마 및 카테고리 정의에 대한 자세한 내용은 아래로 스크롤하여 확인하십시오. + + + +[여기를 클릭](https://forms.office.com/pages/responsepage.aspx?id=v4j5cvGGr0GRqy180BHbR54qTg-u1FRHnQ3KYgdSD51UMDM4TFYzS1RUSUlHMjVRVkVUR0w5RlhJMC4u)하여 MS Forms를 직접 열기 + +### GitHub를 통한 기여 방법 (게임) + +개인 GitHub 계정이 필요합니다. 아직 계정이 없는 경우, https://github.com 에 접속하여 오른쪽 상단의 **가입하기**를 클릭한 후 지침에 따라 진행하십시오. + +계정을 얻은 후, https://github.com/Linaro/works-on-woa/fork 에 접속하여 이 웹사이트의 리포지토리를 *포크*(즉, 본인만의 사본 생성)하십시오. + +리포지토리를 포크한 후, `git clone` 명령어를 사용하여 컴퓨터에 클론하십시오. 자세한 가이드는 https://docs.github.com/en/repositories/creating-and-managing-repositories/cloning-a-repository 에서 확인할 수 있습니다. + +**주의:** 로컬에서 리포지토리를 빌드하려면, WSL (Windows Subsystem for Linux) 내에서 클론해야 합니다. + +리포지토리를 클론한 후, 파일에 필요한 변경을 가하십시오. 필요한 경우 아래에서 각 파일의 필수 및 선택적 콘텐츠에 대한 지침을 확인할 수 있습니다. 도움이 필요하면, https://github.com/Linaro/works-on-woa/issues/new 에 이슈를 작성해 주시면 가능한 한 돕겠습니다. + +변경을 완료한 후 [커밋](https://github.com/git-guides/git-commit)한 다음, [푸시](https://github.com/git-guides/git-push)하여 GitHub에 되돌려 놓습니다. + +마지막으로, 공식 리포지토리에 병합을 요청하는 [풀 리퀘스트](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request-from-a-fork)를 생성하십시오. 요청은 검토 후 승인되면 사이트에 병합됩니다. + +**주의!** 변경 사항을 GitHub에 푸시하기 전에 컴퓨터에서 로컬로 사이트를 빌드해 볼 것을 강력히 권장합니다. 이를 통해 사이트가 올바르게 빌드되고 기여 내용에 오류가 없는지 확인할 수 있습니다. 자세한 내용은 README 파일의 *개발자 정보* 섹션을 참조하십시오. + +### 파일 내용 세부 정보 + +게임의 경우 일관성을 유지하기 위해 *스키마*가 정의되어 있습니다. + +각 항목은 `.md` 파일 확장자를 가진 파일에 저장됩니다. 게임 항목은 `src/content/games`에 저장됩니다. + +기존 항목에 대한 본인의 보고서를 기여하는 경우, `src/content/user_reports_games`에 저장해야 합니다. + +각 파일에는 다음이 포함됩니다: + +- 3개의 대시 `---` +- 아래에 자세히 설명된 프로젝트 관련 정보 +- 3개의 대시 `---` +- GitHub Markdown 형식의 추가 메모 + +#### 게임 스키마 + +| 필드 | 유형 | 설명 | +|-|-|-| +| `name` | string | 게임의 이름입니다. | +| `icon` | string | 선택 사항입니다. `public/icons`에서 상대 경로로 사용될 아이콘 파일의 경로. 최대 512x512. 가능하다면 SVG를 사용하세요. | +| `categories` | list | 게임이 속한 하나 이상의 카테고리 목록입니다. 카테고리 목록은 `src/content/gamess_categories`에 있습니다. 폴더 내의 파일 이름으로 참조됩니다. | +| `publisher` | string | 선택 사항입니다. 게임의 배급사 이름입니다. | +| `frame_rate` | string | 선택 사항입니다. 게임의 프레임률입니다. | +| `device_configuration` | string | 선택 사항입니다. 게임을 테스트하는 데 사용된 장치입니다. | +| `os_version` | string | 선택 사항입니다. 게임 테스트에 사용된 OS 버전입니다. | +| `driver_id` | string | 선택 사항입니다. 게임 테스트에 사용된 그래픽 드라이버의 ID입니다. | +| `date_tested` | date | 선택 사항입니다. 형식은 `YYYY-MM-DD`입니다. | +| `compatibility` | enum | 게임의 실행 가능 여부. 정의에 대한 자세한 내용은 도움말 페이지를 참조하세요. | +| `compatibility_details` | string | 선택 사항입니다. 호환성에 대한 추가 정보입니다. | +| `auto_super_resolution` | block | 선택 사항입니다. 구문은 아래 예시를 참조하세요. | +| - `compatibility` | enum | 선택 사항입니다. 자동 슈퍼 해상도 기능과의 호환성을 나타냅니다. opt-in은 Windows 설정에서 기능을 활성화해야 하며, out-of-box는 설정 변경 없이 적용됨을 의미합니다. | +| - `fps_boost` | string | 선택 사항입니다. 자동 SR이 게임의 프레임 속도를 얼마나 높이는지. | +| - `opt-in steps` | string | 선택 사항입니다. opt-in 게임에 대한 자동 SR 활성화 단계입니다. | +| `link` | URL | 소프트웨어를 다운로드할 수 있는 링크 또는 애플리케이션의 공식 웹사이트입니다. | + +`auto_super_resolution` 블록은 선택 사항이지만, 존재할 경우 `compatibility` 속성이 **필수**입니다. 블록의 형식은 다음과 같습니다: + +``` + auto_super_resolution: + compatibility: yes, out-of-box +``` + +#### 게임 사용자 보고서 스키마 + +사용자는 이 사이트에 추가된 게임에 대한 자신의 발견을 추가할 수 있습니다. 파일에는 `.md` 확장자로 **고유한** 파일 이름이 있어야 하며, 내용은 다음 스키마를 따라야 합니다: + +| 필드 | 유형 | 설명 | +|-|-|-| +| `reporter` | string | 선택 사항입니다. 이름을 입력하세요. | +| `game` | string | 게임 파일의 이름에서 가져온 게임 이름. 즉, `.md` 확장자를 **제외** | +| `device_configuration` | string | 선택 사항입니다. 사용한 장치의 이름입니다. | +| `date_tested` | date | 선택 사항입니다. 형식은 `YYYY-MM-DD`입니다. | +| `os_version` | string | 선택 사항입니다. 시스템의 OS 버전입니다. | +| `driver_id` | string | 선택 사항입니다. 시스템의 그래픽 드라이버 ID입니다. | +| `compatibility` | enum | 게임의 실행 가능 여부입니다. 정의에 대한 자세한 내용은 도움말 페이지를 참조하세요. | +| `compatibility_details` | string | 응용 프로그램이 실행된 방식에 대한 보고서입니다. | +| `auto_super_resolution` | block | 선택 사항입니다. | +| - `compatibility` | enum | 자동 슈퍼 해상도 기능과의 호환성을 나타냅니다. opt-in은 Windows 설정에서 기능을 활성화해야 함을 의미합니다. | +| - `fps_boost` | string | 자동 SR이 게임의 프레임 속도를 얼마나 높이는지. | +| - `opt-in steps` | string | 선택 사항입니다. opt-in 게임에 대한 자동 SR 활성화 단계입니다. | + +사용자 게임 보고서에서는 자동 슈퍼 해상도 호환성이 `yes, opt-in` 또는 `no` 또는 `unknown`으로만 표시될 수 있습니다. + +#### 카테고리 + +게임 카테고리 목록은 대괄호 `[`로 시작하고, 쉼표로 구분된 하나 이상의 카테고리와 닫는 대괄호 `]`로 구성됩니다. + +카테고리는 이전에 지정된 적절한 카테고리 폴더의 `.md` 파일 이름과 일치해야 합니다. diff --git a/src/pages/ko/help.md b/src/pages/ko/help.md new file mode 100644 index 00000000..93312ea6 --- /dev/null +++ b/src/pages/ko/help.md @@ -0,0 +1,53 @@ +--- +layout: ../../layouts/InfoLayout.astro +title: 도움말 +description: Windows on Arm 대응 소프트웨어 웹사이트에 대한 도움말 페이지. +--- + +# 이 사이트에 대한 도움말 + +이 웹사이트는 여러 응용 프로그램 및 게임에 대한 정보와 Windows on Arm에서 실행되는 상태를 제공합니다. + +응용 프로그램과 게임은 카테고리별로 그룹화되며, 하나 이상의 카테고리로 분류될 수 있습니다. 특정 카테고리의 항목을 보려면, 항목의 세부 정보 페이지에 있는 **Categories** 링크에서 카테고리를 선택하거나 검색창 오른쪽에 있는 카테고리 드롭다운 메뉴에서 카테고리를 선택한 후 확대경을 클릭하여 검색을 수행합니다. 여러 카테고리를 동시에 선택할 수 있습니다. + +응용 프로그램의 경우, **Compatibility** 필드는 다음 값 중 하나일 수 있습니다: + +| Value | Meaning | +| --------- | ------------------------------------- | +| Compatible| Windows on Arm (WoA)에서 실행됩니다. | +| Unknown | 상태가 불분명합니다. 자세한 내용은 개발자 웹사이트를 확인하세요.| + +**Version From** 필드는 Windows on Arm과 호환되는 최초의 공개 버전을 나타냅니다. **Download** 버튼이 사용 가능할 경우 클릭하면 Microsoft Store 제품 설명 페이지 또는 앱 설치를 제공하는 웹 위치로 이동합니다. **Unknown** 앱의 경우 **Download** 대신 **Website** 버튼이 표시됩니다. **Website** 버튼을 클릭하면 앱 개발자의 주요 웹 페이지로 이동하여 최신 상태를 확인하고 Windows on Arm 지원을 요청하기 위해 개발자에게 직접 연락할 수 있습니다. + +이 웹사이트에 기여할 수 있는 방법에 대한 정보는 아직 목록에 없는 앱에 대해 기여하거나 기존 앱의 상태 업데이트를 제공하고자 할 경우, [기여 가이드](/ko/contributing)를 읽어주세요. + +게임의 경우, **Compatibility** 필드는 다음 값 중 하나일 수 있습니다: + +| Value | Meaning | +| ---------- | ------------------------------------- | +| perfect | 60+ FPS에서 1080p 해상도로 문제 없이 실행됩니다. | +| playable | 30+ FPS에서 1080p 해상도로 최소한의 문제로 실행됩니다. | +| runs | 30 FPS 이하로 실행되며 게임 경험에 영향을 미치는 버그가 있습니다. | +| unplayable | 치트 방지 또는 기타 오류로 인해 실행되지 않습니다. | + +각 게임에서는 다음 필드를 볼 수 있습니다. 아래에 이들의 의미를 정의했습니다. + +**Frame Rate:** 게임의 초당 프레임 수 + +**Device Configuration:** 게임을 테스트하는 데 사용한 장치 + +**OS Version:** 게임이 테스트된 Windows OS 버전 + +**Driver ID:** 게임이 테스트된 그래픽 드라이버 + +**Compatibility Details:** 게임이 어떻게 실행되는지에 대한 추가 정보 + +**Auto Super Resolution:** Auto SR은 AI를 사용하여 게임의 해상도를 업스케일하며, 향상된 비주얼 품질로 더 나은 FPS를 제공합니다. + +**Auto SR Compatability:** Auto SR이 기본 설정으로 작동하면 설정을 변경하지 않고도 실행됩니다. 옵트인(op-in)은 Windows 설정을 통해 게임에 옵트인해야 함을 의미합니다. + +**Auto SR FPS Boost:** Auto SR을 활성화했을 때 기대할 수 있는 FPS 부스트의 양을 설명합니다. + +자동 슈퍼 해상도와 호환되는 게임을 보려면 게임 페이지의 검색창 오른쪽에 있는 Auto SR 드롭다운 메뉴에서 "yes, out-of-box"와 "yes, opt-in" 항목을 선택하세요. + +이 웹사이트에 기여할 수 있는 방법에 대한 정보는 아직 목록에 없는 게임에 대해 기여하거나 기존 게임에 자신의 보고서를 추가하고자 할 경우, [기여 가이드](/ko/contributing)를 읽어주세요. diff --git a/src/pages/ko/index.md b/src/pages/ko/index.md new file mode 100644 index 00000000..80875795 --- /dev/null +++ b/src/pages/ko/index.md @@ -0,0 +1,32 @@ +--- +layout: ../../layouts/InfoLayout.astro +title: "홈페이지" +description: ARM에서 Windows에 적합한 소프트웨어 +--- + +Windows on Arm에서 작동하는 사이트에 오신 것을 환영합니다! + +이 사이트는 Arm 아키텍처에서 실행되는 Windows 장치의 많은 앱과 게임에 대한 호환성 정보의 출처입니다. 앞으로도 지속적으로 업데이트될 것입니다. + +호환성을 정의하는 방법과 사이트 탐색 방법에 대한 자세한 내용은 [도움말 페이지](/ko/help)를 참조하세요. + +앱이나 게임을 테스트하고 자신만의 결과를 기여하고 싶다면 [기여 가이드](/ko/contributing)를 읽고 GitHub의 오픈 소스 리포지토리에 풀 리퀘스트를 제출하는 방법을 알아보세요. + +이 정보는 가이드로 제공되지만 게임이 반드시 실행된다는 보장은 없습니다. 결과는 테스트되었지만 특정 기계와 구성에서 작동하지 않을 수 있습니다. 결과가 다르다면 자신의 발견을 사이트에 기여해 주시기 바랍니다. + + diff --git a/src/pages/ko/takedown.md b/src/pages/ko/takedown.md new file mode 100644 index 00000000..50d4c95b --- /dev/null +++ b/src/pages/ko/takedown.md @@ -0,0 +1,9 @@ +--- +layout: ../../layouts/InfoLayout.astro +title: 테이크다운 +description: ARM에서 Windows가 준비된 웹사이트에서 항목을 삭제하는 것과 관련된 권리 보유자를 위한 정보. +--- + +# 콘텐츠 삭제 요청 + +이 사이트에서 귀하의 제품이나 로고를 제거하려면 적절한 정보를 포함하여 [it-support@linaro.org](mailto:it-support@linaro.org)로 이메일을 보내주시기 바랍니다. diff --git a/src/pages/zh/contributing.md b/src/pages/zh/contributing.md new file mode 100644 index 00000000..dd92fb9d --- /dev/null +++ b/src/pages/zh/contributing.md @@ -0,0 +1,182 @@ +--- +layout: ../../layouts/InfoLayout.astro +title: 贡献 +description: 如何为此站点做出贡献 +--- + +# 为此站点做出贡献 +- 应用程序 +- 游戏 + +## 应用程序 +应用程序的贡献可以直接在GitHub 项目上完成,也可以通过便捷的表单流程提交。 + +### 通过 Microsoft Forms 进行贡献(应用程序) + +请填写以下表单并提交您的应用程序请求。您可以使用此表单请求测试并添加新的应用程序,告知我们某个应用程序的信息有误,或者提交您自己的新应用程序数据。我们建议没有技术经验的用户通过 Microsoft Form 而不是 GitHub 进行贡献。向下滚动查看有关定义的架构和类别定义的更多详细信息。 + + + +[点击此处](https://forms.office.com/r/JZ1ywk2FaJ)直接打开 Microsoft 表单 + +### 通过 GitHub 进行贡献(应用程序) + +您将需要一个 GitHub 账号。如果您还没有账号,请访问 https://github.com,点击页面右上角的**注册**,然后按照说明操作。 + +创建账号后,前往 https://github.com/Linaro/works-on-woa/fork *fork*(即复制)此站点的存储库。 + +完成 fork 后,使用 `git clone` 命令将其克隆到您的计算机。如果需要更多帮助,请参阅 https://docs.github.com/en/repositories/creating-and-managing-repositories/cloning-a-repository。 + +克隆存储库后,对文件进行必要的更改。有关每个文件所需的内容和选项的指导,请参阅下面的说明。如果需要帮助,请在 https://github.com/Linaro/works-on-woa/issues/new 上创建一个 issue,我们将尽力为您提供帮助。 + +更改完成后,将更改[提交](https://github.com/git-guides/git-commit)到您的存储库,然后将其[推送](https://github.com/git-guides/git-push)回 GitHub。 + +最后,创建一个[拉取请求](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request-from-a-fork)以请求将更改合并到官方存储库。您的请求将被审核,如果获得批准,将合并到站点。 + +**请注意!** 强烈建议您在将更改推送到 GitHub 之前在本地构建网站。这将确保站点正确构建,且您的贡献没有任何错误。请参阅 README 文件中的*开发者信息*部分了解如何执行此操作。 + +#### 文件内容详情 + +为了确保提交数据的一致性,应用程序使用了定义的*架构*。 + +每个条目都存储在 `.md` 文件扩展名的文件中。应用程序条目存储在 `src/content/applications` 下。 + +如果您贡献的内容是关于现有条目的报告,请将其适当存储在 `src/content/user_reports_applications` 或 `src/content/user_reports_games` 中。 + +每个文件包括: + +- 三个破折号`---` +- 以下项目特定的信息 +- 三个破折号`---` +- GitHub Markdown 格式的任何附加说明 + +##### 应用程序模式 + +存储在应用程序条目中的信息必须遵循以下模式: + +| 字段 | 类型 | 备注 | +|-|-|-| +| `name` | string | 应用程序的名称。 | +| `icon` | string | 可选。图标文件的路径,相对于 `public/icons`。最大尺寸为512x512。如有可能,请使用SVG格式。 | +| `categories` | list | 应用程序所属的一个或多个类别列表。类别列表位于 `src/content/applications_categories`。通过此文件夹中的文件名引用类别。 | +| `display_result` | enum | Arm兼容性显示:
Compatible: 测试的应用程序可以在Windows on Arm上运行
Unknown: 状态未知
Unsupported: 当前未使用此值
Vendor Announced - Launching Soon: 当前未使用此值 | +| `compatibility` | enum | Windows on Arm兼容性:
Native: 支持WoA原生
Emulation: 通过x86/x64仿真运行
No: 尚未移植
Unknown: 状态未知 | +| `version_from` | string | 软件可用的版本。

对于可以从一个版本编译的软件,但仅从另一个版本公开(例如,Python在WoA版本发布之前就可以编译),在此处输入通常用户可访问的公开版本。

可以在备注部分自由添加可编译的版本(及相关说明)。 | +| `link` | URL | 软件下载链接或应用程序的主网站。 | + +### 应用程序用户报告模式 + +用户可以添加关于已添加到此站点的应用程序的发现。文件必须有**唯一**的文件名(扩展名为 `.md`),并且内容必须遵循以下模式: + +| 字段 | 类型 | 备注 | +|-|-|-| +| `reporter` | string | 可选。您的姓名。 | +| `application` | string | 应用程序文件名中的名称,不包括 `.md` 扩展名。 | +| `device_configuration` | string | 可选。可能会影响报告的配置相关信息。 | +| `date_tested` | date | 可选。格式为 `YYYY-MM-DD`。 | +| `compatibility_details` | string | 您对应用程序运行情况的报告。 | + +#### 类别 + +类别列表以方括号 `[` 开始,由一个或多个逗号分隔的类别组成,并以方括号 `]` 结束。 + +类别必须与前面指定的适当类别文件夹中的 `.md` 文件名匹配。 + +## 游戏 +可以直接向GitHub 项目贡献,或使用方便的表单流程。 + +### 通过 Microsoft Forms 贡献(游戏) + +填写以下表单,输入游戏测试的详细信息。除非您有一些技术经验,否则建议您通过 Microsoft 表单进行贡献,而不是 GitHub。向下滚动查看定义的模式和类别定义的详细信息。 + + + +[点击此处](https://forms.office.com/pages/responsepage.aspx?id=v4j5cvGGr0GRqy180BHbR54qTg-u1FRHnQ3KYgdSD51UMDM4TFYzS1RUSUlHMjVRVkVUR0w5RlhJMC4u)直接打开 MS 表单 + +### 通过 GitHub 贡献(游戏) + +您需要拥有自己的 GitHub 帐户。如果您还没有,请访问 https://github.com,点击页面右上角的 **Sign up** 并按照说明操作。 + +创建账户后,访问 https://github.com/Linaro/works-on-woa/fork 将本网站的存储库*分叉*(即创建您自己的副本)。 + +分叉存储库后,使用 `git clone` 命令将其克隆到您的计算机。如果需要更多帮助,请访问 https://docs.github.com/en/repositories/creating-and-managing-repositories/cloning-a-repository。 + +**注意:** 您需要将存储库克隆到 WSL(Windows Subsystem for Linux)中。除非在 WSL 中,否则本地构建将失败。 + +克隆存储库后,按照需要对文件进行更改。每个文件的必要内容和可选内容的指导如下。如有需要,请在 https://github.com/Linaro/works-on-woa/issues/new 创建问题,我们会尽力提供帮助。 + +完成更改后,将更改 [提交](https://github.com/git-guides/git-commit)到您自己的存储库,然后[推送](https://github.com/git-guides/git-push)回 GitHub。 + +最后,创建一个[拉取请求](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request-from-a-fork)请求将您的更改合并到官方存储库。请求将会被审核,若获得批准,则合并到网站中。 + +**请注意!** 强烈建议您在将更改推送回 GitHub 之前,尝试在计算机上本地构建该网站。这将确保网站正确构建,并且您的贡献没有任何错误。有关说明,请参阅 README 文件中的*开发人员信息*部分。 + +### 文件内容详细信息 + +对于游戏,有一个定义的*模式*以确保数据一致性。 + +每个条目都存储在扩展名为 `.md` 的文件中。游戏条目存储在 `src/content/games` 中。 + +如果您要提交您对现有条目的报告,则应将其存储在 `src/content/user_reports_games` 中。 + +每个文件包含: + +- 3 个短划线 `---` +- 下文详述的项目特定信息 +- 3 个短划线 `---` +- 以 GitHub Markdown 格式添加的附加说明 + +#### 游戏模式 + +| 字段 | 类型 | 备注 | +|-|-|-| +| `name` | string | 游戏的名称。 | +| `icon` | string | 可选。相对于 `public/icons` 的图标文件路径。最大512x512。若可能,请使用SVG格式。 | +| `categories` | list | 游戏所属的一个或多个类别的列表。类别列表可在 `src/content/gamess_categories` 中找到。类别通过此文件夹中的文件名引用。 | +| `publisher` | string | 可选。游戏发行商的名称。 | +| `frame_rate` | string | 可选。游戏的帧数(FPS)。 | +| `device_configuration` | string | 可选。测试游戏时使用的设备。 | +| `os_version` | string | 可选。测试游戏时使用的操作系统版本。 | +| `driver_id` | string | 可选。测试游戏时使用的图形驱动程序ID。 | +| `date_tested` | date | 可选。格式为 `YYYY-MM-DD` | +| `compatibility` | enum | 游戏的运行情况。有关定义的更多信息,请参阅帮助页面。 | +| `compatibility_details` | string | 可选。关于兼容性的任何附加信息。 | +| `auto_super_resolution` | block | 可选。语法见以下示例。 | +| - `compatibility` | enum | 可选。表示与自动超级分辨率功能的兼容性。opt-in 意味着需要在 Windows 设置中启用此功能,而 out-of-box 意味着无需更改任何设置即可应用自动 SR。 | +| - `fps_boost` | string | 可选。自动 SR 对游戏帧速率的提升程度。 | +| - `opt-in steps` | string | 可选。为 opt-in 游戏启用自动 SR 的步骤。 | +| `link` | URL | 软件的下载链接或应用程序的官方网站。 | + +`auto_super_resolution` 块是可选的,但如果存在,则属性 `compatibility` **必须**存在。块的格式如下: + +``` + auto_super_resolution: + compatibility: yes, out-of-box +``` + +#### 游戏用户报告模式 + +用户可以添加有关已添加到本网站的游戏的个人发现。文件可以具有任何**唯一**的文件名(带有 `.md` 扩展名),内容必须遵循以下模式: + +| 字段 | 类型 | 备注 | +|-|-|-| +| `reporter` | string | 可选。您的姓名。 | +| `game` | string | 游戏的文件名中的名称,即**不含**`.md`扩展名 | +| `device_configuration` | string | 可选。您使用的设备名称。 | +| `date_tested` | date | 可选。格式为 `YYYY-MM-DD` | +| `os_version` | string | 可选。系统的操作系统版本。 | +| `driver_id` | string | 可选。系统的图形驱动程序ID。 | +| `compatibility` | enum | 游戏的运行情况。定义的更多信息请参阅帮助页面。 | +| `compatibility_details` | string | 您的应用运行报告。 | +| `auto_super_resolution` | block | 可选。 | +| - `compatibility` | enum | 表示与自动超级分辨率功能的兼容性。opt-in 意味着需要在 Windows 设置中启用此功能。 | +| - `fps_boost` | string | 自动 SR 对游戏帧速率的提升程度。 | +| - `opt-in steps` | string | 可选。为 opt-in 游戏启用自动 SR 的步骤。 | + +请注意,对于用户游戏报告,自动超级分辨率兼容性只能为 `yes, opt-in`、`no` 或 `unknown`。 + +#### 类别 + +游戏类别列表以方括号 `[` 开始,包含一个或多个以逗号分隔的类别,并以方括号 `]` 结束。 + +类别必须与前面指定的相应类别文件夹中的 `.md` 文件名匹配。 diff --git a/src/pages/zh/help.md b/src/pages/zh/help.md new file mode 100644 index 00000000..843924ed --- /dev/null +++ b/src/pages/zh/help.md @@ -0,0 +1,53 @@ +--- +layout: ../../layouts/InfoLayout.astro +title: 帮助 +description: 关于使用 Windows on Arm 兼容软件网站的帮助页面。 +--- + +# 关于本网站的帮助 + +本网站提供有关多个应用程序和游戏的信息,以及它们在 Windows on Arm 上运行的状态。 + +应用程序和游戏按类别分组,可以按多个类别进行分类。要查看给定类别的条目,请从条目详细信息页面上的 **Categories** 链接中选择类别,或从搜索栏右侧的类别下拉菜单中选择,然后点击放大镜以执行搜索。可以同时选择多个类别。 + +对于应用程序,**Compatibility** 字段可以是以下值之一: + +| Value | Meaning | +| --------- | ------------------------------------- | +| Compatible| 在 Windows on Arm (WoA) 上运行。 | +| Unknown | 状态未知。请查看开发者网站以获取更多信息。| + +**Version From** 字段显示与 Windows on Arm 兼容的首个已知公开版本的应用。当 **Download** 按钮可用时,点击将导航到 Microsoft Store 产品描述页面或提供应用安装的网页位置。对于 **Unknown** 的应用,将显示 **Website** 按钮而不是 **Download**。点击 **Website** 按钮将导航到应用开发者的主网页,您可以在此检查最新状态,并直接联系开发者请求 Windows on Arm 支持。 + +有关如何为此网站做出您自己的贡献的信息,无论是对于尚未列出的应用程序,还是提供现有应用程序的状态更新,请阅读 [贡献指南](/zh/contributing)。 + +对于游戏,**Compatibility** 字段可以是以下值之一: + +| Value | Meaning | +| ---------- | ------------------------------------- | +| perfect | 在 1080p 分辨率下以 60+ FPS 运行,没有影响游戏体验的故障/问题。 | +| playable | 在 1080p 分辨率下以 30+ FPS 运行,存在影响游戏体验的最小故障/问题。 | +| runs | 以低于 30 FPS 运行,并且可能存在影响游戏体验的错误。 | +| unplayable | 由于防作弊或其他故障而无法运行。 | + +在每个游戏中,您将看到以下字段。下面我们定义了它们的含义。 + +**Frame Rate:** 游戏的每秒帧数 + +**Device Configuration:** 用于测试游戏的设备 + +**OS Version:** 测试游戏的 Windows 操作系统版本 + +**Driver ID:** 测试游戏的图形驱动程序 + +**Compatibility Details:** 关于游戏运行情况的进一步信息 + +**Auto Super Resolution:** Auto SR 使用 AI 来提升游戏的分辨率,让您在游戏中获得更好的 FPS 和增强的视觉质量。 + +**Auto SR Compatability:** Auto SR 开箱即用意味着它可以在不更改任何设置的情况下运行。选择加入意味着您需要通过 Windows 设置选择加入游戏。 + +**Auto SR FPS Boost:** 描述启用 Auto SR 后您可以期望的 FPS 提升量。 + +要查看与自动超分辨率兼容的游戏,请从游戏页面搜索栏右侧的 Auto SR 下拉菜单中选择“yes, out-of-box”和“yes, opt-in”条目。 + +有关如何为此网站做出您自己的贡献的信息,无论是对于尚未列出的游戏,还是通过添加您自己的报告来贡献给现有游戏,请阅读 [贡献指南](/zh/contributing)。 diff --git a/src/pages/zh/index.md b/src/pages/zh/index.md new file mode 100644 index 00000000..9a4666be --- /dev/null +++ b/src/pages/zh/index.md @@ -0,0 +1,32 @@ +--- +layout: ../../layouts/InfoLayout.astro +title: "主页" +description: Windows on Arm 兼容软件 +--- + +欢迎来到 Works on Windows on Arm! + +该网站是关于运行在 Arm 架构的 Windows 设备上众多应用和游戏的兼容性信息的来源,并将随着时间不断更新。 + +有关我们如何定义兼容性以及如何导航网站的更多信息,请参阅 [帮助页面](/zh/help)。 + +如果您已经测试了应用程序或游戏并希望贡献自己的结果,请阅读 [贡献指南](/zh/contributing),以帮助您向 GitHub 上的开源存储库提交拉取请求。 + +这些信息旨在作为指导,但不绝对保证游戏会运行。结果已经过测试,但可能不适用于您的特定机器和配置。如果您的结果不同,请贡献您自己的发现到该网站。 + + diff --git a/src/pages/zh/takedown.md b/src/pages/zh/takedown.md new file mode 100644 index 00000000..df750787 --- /dev/null +++ b/src/pages/zh/takedown.md @@ -0,0 +1,9 @@ +--- +layout: ../../layouts/InfoLayout.astro +title: 删除请求 +description: 关于从 Windows on Arm 兼容网站中删除条目的权利持有者信息。 +--- + +# 内容删除请求 + +如果您希望从此站点中删除您的产品或徽标,请通过电子邮件发送适当的信息至 [it-support@linaro.org](mailto:it-support@linaro.org)。 From 755b7bfc96b88abfc186401a00efc6a1c4a2bf6a Mon Sep 17 00:00:00 2001 From: Alberto Ito <95650418+Alberto-Ito@users.noreply.github.com> Date: Thu, 28 Nov 2024 16:36:31 -0300 Subject: [PATCH 03/11] Add Astro internationalization routing Add i18next for locale variables Add lang content for controls Co-authored-by: Alberto Ito --- astro-i18next.config.mjs | 12 ++ astro.config.mjs | 11 +- package.json | 3 + public/locales/en/translation.json | 118 ++++++++++++++ public/locales/ja/translation.json | 118 ++++++++++++++ public/locales/ko/translation.json | 118 ++++++++++++++ public/locales/zh/translation.json | 118 ++++++++++++++ src/components/Common/BaseHead.astro | 4 +- src/components/Common/Breadcrumbs.astro | 12 +- src/components/Common/Footer.astro | 28 ++-- src/components/Common/Header.astro | 16 +- .../Projects/ApplicationDetails.astro | 15 +- .../Projects/ApplicationListing.astro | 10 +- src/components/Projects/GameDetails.astro | 30 ++-- src/components/Projects/UserReports.astro | 19 +-- src/components/Search/PageFind.tsx | 19 ++- src/components/Search/Results.tsx | 26 ++-- src/components/Search/SearchForm.astro | 4 +- src/config/i18nConfig.js | 5 + src/layouts/BaseLayout.astro | 8 +- src/layouts/InfoLayout.astro | 16 +- src/layouts/ProjectLayout.astro | 23 ++- .../{ => [lang]}/applications/[...slug].astro | 15 +- src/pages/[lang]/applications/index.astro | 52 +++++++ src/pages/[lang]/applications/search.astro | 26 ++++ .../[lang]/contributing/applications.astro | 143 +++++++++++++++++ src/pages/[lang]/contributing/games.astro | 147 ++++++++++++++++++ src/pages/{ => [lang]}/games/[...slug].astro | 14 +- src/pages/[lang]/games/index.astro | 23 +++ src/pages/[lang]/search/index.astro | 35 +++++ src/pages/applications/index.astro | 44 ------ src/pages/applications/search.astro | 15 -- src/pages/{ => en}/contributing.md | 2 +- src/pages/{ => en}/help.md | 6 +- src/pages/{ => en}/index.md | 10 +- src/pages/{ => en}/takedown.md | 2 +- src/pages/games/index.astro | 12 -- src/pages/index.astro | 15 ++ src/pages/search/index.astro | 22 --- src/util/updateLanguage.js | 17 ++ 40 files changed, 1122 insertions(+), 211 deletions(-) create mode 100644 astro-i18next.config.mjs create mode 100644 public/locales/en/translation.json create mode 100644 public/locales/ja/translation.json create mode 100644 public/locales/ko/translation.json create mode 100644 public/locales/zh/translation.json create mode 100644 src/config/i18nConfig.js rename src/pages/{ => [lang]}/applications/[...slug].astro (79%) create mode 100644 src/pages/[lang]/applications/index.astro create mode 100644 src/pages/[lang]/applications/search.astro create mode 100644 src/pages/[lang]/contributing/applications.astro create mode 100644 src/pages/[lang]/contributing/games.astro rename src/pages/{ => [lang]}/games/[...slug].astro (79%) create mode 100644 src/pages/[lang]/games/index.astro create mode 100644 src/pages/[lang]/search/index.astro delete mode 100644 src/pages/applications/index.astro delete mode 100644 src/pages/applications/search.astro rename src/pages/{ => en}/contributing.md (99%) rename src/pages/{ => en}/help.md (97%) rename src/pages/{ => en}/index.md (76%) rename src/pages/{ => en}/takedown.md (89%) delete mode 100644 src/pages/games/index.astro create mode 100644 src/pages/index.astro delete mode 100644 src/pages/search/index.astro create mode 100644 src/util/updateLanguage.js diff --git a/astro-i18next.config.mjs b/astro-i18next.config.mjs new file mode 100644 index 00000000..54951a73 --- /dev/null +++ b/astro-i18next.config.mjs @@ -0,0 +1,12 @@ +import { DEFAULT_LOCALE, LOCALES } from "./src/config/i18nConfig.js"; + +export default { + defaultLocale: DEFAULT_LOCALE, + locales: LOCALES, + load: ["server", "client"], + resourcesBasePath: "/locales", + showDefaultLocale: true, + i18nextServer: { + debug: true, + } +}; diff --git a/astro.config.mjs b/astro.config.mjs index 95bc39a3..09ce22b0 100644 --- a/astro.config.mjs +++ b/astro.config.mjs @@ -1,4 +1,5 @@ import { defineConfig } from "astro/config"; +import astroI18next from "astro-i18next"; import aws from "astro-sst"; import sitemap from "@astrojs/sitemap"; import tailwind from "@astrojs/tailwind"; @@ -6,7 +7,7 @@ import solidJs from "@astrojs/solid-js"; import pagefind from "./integrations/pagefind"; import auth from "./integrations/auth"; import { loadEnv } from "vite"; - +import { LOCALES, DEFAULT_LOCALE } from "./src/config/i18nConfig"; const { IS_PUBLIC, PRE_BUILD, CUSTOM_DOMAIN } = loadEnv( process.env.NODE_ENV, @@ -32,6 +33,7 @@ export default defineConfig({ applyBaseStyles: false, }), solidJs(), + astroI18next(), ], } : { @@ -65,5 +67,12 @@ export default defineConfig({ }, vite: { optimizeDeps: { exclude: ['auth:config'] }, + }, + i18n: { + defaultLocale: DEFAULT_LOCALE, + locales: LOCALES, + routing: { + prefixDefaultLocale: true, + } } }); diff --git a/package.json b/package.json index 7a3eec36..f3a3a50f 100644 --- a/package.json +++ b/package.json @@ -29,10 +29,13 @@ "@biscuit-auth/biscuit-wasm": "^0.4.0", "@solid-primitives/pagination": "^0.2.8", "astro": "4.4.5", + "astro-i18next": "^1.0.0-beta.21", "astro-pagefind": "^1.4.0", "astro-sst": "^2.40.3", "auth-astro": "^4.1.1", "dayjs": "^1.11.10", + "i18next": "^23.16.4", + "js-yaml": "^4.1.0", "sass": "^1.63.6", "set-cookie-parser": "^2.6.0", "solid-icons": "^1.1.0", diff --git a/public/locales/en/translation.json b/public/locales/en/translation.json new file mode 100644 index 00000000..436f2bd7 --- /dev/null +++ b/public/locales/en/translation.json @@ -0,0 +1,118 @@ +{ + "header": { + "main": "Windows on Arm Ready Software" + }, + "bradcrumbs": { + "home": "Home", + "contributing": "Contributing", + "applications": "Applications", + "search": "Search", + "games": "Games" + }, + "footer": { + "report_an_issue": "Report an issue", + "edit_on_github": "Edit on Github", + "legal": "Legal", + "contact": "Contact", + "help": "Help", + "takedown": "Content takedown request", + "copyright": "All product names, logos, brands, trademarks and registered trademarks are property of their respective owners. Accuracy of the data is not guaranteed by Linaro.", + "games_count": "games" + }, + "search": { + "search": "Search", + "clear_search": "Clear search", + "no_information_start": "There is no information in our data about that. Why not contact the developer on their web site, or complete a feedback request", + "no_information_here": "here", + "no_information_end": "for us to investigate." + }, + "applications": { + "info": "Below are some of the top apps that have been tested. Use the search bar to search for other tested apps.", + "search_button": "Search for more applications", + "search_placeholder": "Search for applications", + "search_instruction": "To begin searching, enter a search query and press enter, or choose a category", + "categories": "Categories", + "version_from": "Version From", + "download": "Download", + "report_last_updated": "Report last updated", + "website": "Website", + "more_info": "More Info" + }, + "games": { + "search_placeholder": "Search for games", + "user_reports": "User Reports", + "publisher": "Publisher", + "categories": "Categories", + "date_tested": "Date tested", + "frame_rate": "Frame Rate", + "device_configuration": "Device Configuration", + "os_build_number": "OS Build Number", + "driver_id": "Driver ID", + "auto_super_resolution": "Auto Super Resolution", + "compatible": "Compatible", + "enablement": "Enablement", + "fps_boost": "FPS Boost", + "opt_in_steps": "Opt In Steps", + "compatibility": "Compatibility", + "auto_sr": "Auto SR", + "link": "Link", + "notes": "Notes", + "details": "Details" + }, + "application_form": { + "title": "Application request form", + "description": "Please fill out the following information about the application compatibility.", + "app_name": "Name of App", + "publisher": "Publisher", + "report_type": { + "description": "What are you reporting?", + "request_test": "Request for this app to be tested", + "submit_update": "Submit new or updated app information" + }, + "app_category": { + "description": "App Category", + "instruction": "Select one or more categories from the list below. To select multiple options, hold 'Ctrl' while clicking", + "fetching_categories": "Fetching application categories. Please wait..." + }, + "download_url": "URL for app download, or developer site", + "displayed_arm_compatibility": "Displayed Arm compatibility?", + "earliest_compatible_version": "Earliest compatible version number", + "execution_compatibility": "Execution compatibility", + "icon": { + "description": "Icon URL", + "instruction": "Link to an app icon (512x512 max size, SVG preferred)" + }, + "submit_button": "Submit", + "submit_succeeded": "Application form successfully sent, thanks for your collaboration!", + "submit_failed": "An error occurred!" + }, + "game_form": { + "title": "Game request form", + "description": "Please fill out the following information about the game compatibility.", + "game_name": "Name of Game", + "game_category": { + "description": "Game Category", + "instruction": "Select one category from the list below.", + "fetching_categories": "Fetching game categories. Please wait..." + }, + "publisher": "Publisher", + "compatibility": { + "description": "Compatibility", + "perfect": "Perfect - Runs at 60+ FPS at 1080p resolution with no glitches / issues that affect gaming experience", + "playable": "Playable - Runs at 30+ FPS at 1080p resolution with minimal glitches/ issues that affect gaming experience", + "runs": "Runs - Runs at less than 30 FPS and/or with bugs that may affect gaming experience", + "unplayable": "Unplayable - Does not run due to anti-cheat or other failures" + }, + "device_configuration": "Device Configuration", + "date_tested": "Date tested", + "os_version": "Os Version", + "driver_id": "Driver ID", + "compatibility_details": "Compatibility Details", + "auto_super_resolution_compatibility": "Auto Super Resolution Compatibility", + "auto_super_resolution_fps_bost": "Auto Super Res FPS boost", + "your_name_gamertag": "Your name/gamertag", + "submit_button": "Submit", + "submit_succeeded": "Game form successfully sent, thanks for your collaboration!", + "submit_failed": "An error occurred!" + } +} diff --git a/public/locales/ja/translation.json b/public/locales/ja/translation.json new file mode 100644 index 00000000..5cc25cf6 --- /dev/null +++ b/public/locales/ja/translation.json @@ -0,0 +1,118 @@ +{ + "header": { + "main": "Arm向けのWindows対応ソフトウェア" + }, + "bradcrumbs": { + "home": "ホーム", + "contributing": "貢献", + "applications": "アプリケーション", + "search": "検索", + "games": "ゲーム" + }, + "footer": { + "report_an_issue": "問題を報告する", + "edit_on_github": "Githubで編集", + "legal": "法的事項", + "contact": "連絡先", + "help": "ヘルプ", + "takedown": "コンテンツ削除リクエスト", + "copyright": "すべての製品名、ロゴ、ブランド、商標、登録商標はそれぞれの所有者に帰属します。データの正確性はLinaroによって保証されません。", + "games_count": "ゲーム" + }, + "search": { + "search": "検索", + "clear_search": "検索をクリア", + "no_information_start": "その情報はデータにありません。開発者のウェブサイトで連絡してみるか、調査のために", + "no_information_here": "こちら", + "no_information_end": "からフィードバックリクエストを送信してください。" + }, + "applications": { + "info": "以下はテスト済みのトップアプリの一部です。検索バーを使用して他のテスト済みアプリを検索してください。", + "search_button": "他のアプリケーションを検索", + "search_placeholder": "アプリケーションを検索", + "search_instruction": "検索を開始するには、検索クエリを入力してEnterを押すか、カテゴリを選択してください", + "categories": "カテゴリ", + "version_from": "バージョン", + "download": "ダウンロード", + "report_last_updated": "レポートの最終更新日", + "website": "ウェブサイト", + "more_info": "詳細情報" + }, + "games": { + "search_placeholder": "ゲームを検索", + "user_reports": "ユーザーレポート", + "publisher": "発行者", + "categories": "カテゴリ", + "date_tested": "テスト日", + "frame_rate": "フレームレート", + "device_configuration": "デバイス構成", + "os_build_number": "OSビルド番号", + "driver_id": "ドライバーID", + "auto_super_resolution": "自動スーパー解像度", + "compatible": "互換性あり", + "enablement": "有効化", + "fps_boost": "FPSブースト", + "opt_in_steps": "オプトイン手順", + "compatibility": "互換性", + "auto_sr": "自動SR", + "link": "リンク", + "notes": "備考", + "details": "詳細" + }, + "application_form": { + "title": "アプリケーションリクエストフォーム", + "description": "アプリケーションの互換性に関する情報を以下に記入してください。", + "app_name": "アプリ名", + "publisher": "発行元", + "report_type": { + "description": "何を報告していますか?", + "request_test": "このアプリのテストをリクエスト", + "submit_update": "新しいまたは更新されたアプリ情報を提出" + }, + "app_category": { + "description": "アプリカテゴリー", + "instruction": "以下のリストから1つ以上のカテゴリーを選択してください。複数のオプションを選択するには、'Ctrl' を押しながらクリック", + "fetching_categories": "アプリカテゴリーを取得中です。しばらくお待ちください..." + }, + "download_url": "アプリダウンロード用URL、または開発者サイト", + "displayed_arm_compatibility": "表示されるARM互換性は?", + "earliest_compatible_version": "最初に互換性があるバージョン番号", + "execution_compatibility": "実行互換性", + "icon": { + "description": "アイコンURL", + "instruction": "アプリのアイコンへのリンク(最大512x512、SVGを推奨)" + }, + "submit_button": "送信", + "submit_succeeded": "アプリケーションフォームが正常に送信されました。ご協力ありがとうございます!", + "submit_failed": "エラーが発生しました!" + }, + "game_form": { + "title": "ゲームリクエストフォーム", + "description": "ゲームの互換性に関する以下の情報を記入してください。", + "game_name": "ゲーム名", + "game_category": { + "description": "ゲームカテゴリ", + "instruction": "下のリストから1つのカテゴリを選択してください。", + "fetching_categories": "ゲームカテゴリを取得中です。しばらくお待ちください..." + }, + "publisher": "出版社", + "compatibility": { + "description": "互換性", + "perfect": "Perfect - 1080p 解像度で 60 FPS 以上で動作し、ゲーム体験に影響を与えるグリッチや問題はありません", + "playable": "Playable - 1080p 解像度で 30 FPS 以上で動作し、ゲーム体験に最小限のグリッチや問題があります", + "runs": "Runs - 30 FPS 未満で動作し、ゲーム体験に影響を与えるバグがあります", + "unplayable": "Unplayable - アンチチートやその他の失敗により動作しません" + }, + "device_configuration": "デバイス構成", + "date_tested": "テスト日", + "os_version": "OS バージョン", + "driver_id": "ドライバー ID", + "compatibility_details": "互換性の詳細", + "auto_super_resolution_compatibility": "オートスーパー解像度互換性", + "auto_super_resolution_fps_bost": "オートスーパー解像度 FPS 向上", + "your_name_gamertag": "あなたの名前/ゲーマータグ", + "submit_button": "送信", + "submit_succeeded": "ゲームフォームが正常に送信されました。ご協力ありがとうございます!", + "submit_failed": "エラーが発生しました!" + } +} diff --git a/public/locales/ko/translation.json b/public/locales/ko/translation.json new file mode 100644 index 00000000..4ccc6def --- /dev/null +++ b/public/locales/ko/translation.json @@ -0,0 +1,118 @@ +{ + "header": { + "main": "Arm용 Windows 호환 소프트웨어" + }, + "bradcrumbs": { + "home": "홈", + "contributing": "기여", + "applications": "애플리케이션", + "search": "검색", + "games": "게임" + }, + "footer": { + "report_an_issue": "문제 보고", + "edit_on_github": "Github에서 편집", + "legal": "법적 고지", + "contact": "연락처", + "help": "도움말", + "takedown": "콘텐츠 삭제 요청", + "copyright": "모든 제품 이름, 로고, 브랜드, 상표 및 등록 상표는 해당 소유자의 재산입니다. 데이터의 정확성은 Linaro에 의해 보장되지 않습니다.", + "games_count": "게임" + }, + "search": { + "search": "검색", + "clear_search": "검색 지우기", + "no_information_start": "해당 정보는 데이터에 없습니다. 개발자의 웹사이트에서 문의하시거나 조사를 위해", + "no_information_here": "여기", + "no_information_end": "에서 피드백 요청을 완료해 주세요." + }, + "applications": { + "info": "아래는 테스트된 상위 앱 중 일부입니다. 검색창을 사용하여 다른 테스트된 앱을 검색하세요.", + "search_button": "더 많은 애플리케이션 검색", + "search_placeholder": "애플리케이션 검색", + "search_instruction": "검색을 시작하려면 검색어를 입력하고 Enter를 누르거나 카테고리를 선택하세요.", + "categories": "카테고리", + "version_from": "버전", + "download": "다운로드", + "report_last_updated": "보고서 마지막 업데이트", + "website": "웹사이트", + "more_info": "추가 정보" + }, + "games": { + "search_placeholder": "게임 검색", + "user_reports": "사용자 보고서", + "publisher": "배급사", + "categories": "카테고리", + "date_tested": "테스트 날짜", + "frame_rate": "프레임 속도", + "device_configuration": "장치 구성", + "os_build_number": "OS 빌드 번호", + "driver_id": "드라이버 ID", + "auto_super_resolution": "자동 슈퍼 해상도", + "compatible": "호환 가능", + "enablement": "활성화", + "fps_boost": "FPS 부스트", + "opt_in_steps": "옵트인 단계", + "compatibility": "호환성", + "auto_sr": "자동 SR", + "link": "링크", + "notes": "노트", + "details": "세부 정보" + }, + "application_form": { + "title": "애플리케이션 요청 양식", + "description": "애플리케이션 호환성에 대한 다음 정보를 작성하십시오.", + "app_name": "앱 이름", + "publisher": "발행자", + "report_type": { + "description": "무엇을 보고하고 있습니까?", + "request_test": "이 앱의 테스트 요청", + "submit_update": "새로운 또는 업데이트된 앱 정보 제출" + }, + "app_category": { + "description": "앱 카테고리", + "instruction": "아래 목록에서 하나 이상의 카테고리를 선택하십시오. 여러 옵션을 선택하려면 'Ctrl'을 누른 채로 클릭", + "fetching_categories": "애플리케이션 카테고리 가져오는 중. 잠시 기다려 주세요..." + }, + "download_url": "앱 다운로드 URL 또는 개발자 사이트", + "displayed_arm_compatibility": "표시된 ARM 호환성은?", + "earliest_compatible_version": "가장 오래된 호환 가능한 버전 번호", + "execution_compatibility": "실행 호환성", + "icon": { + "description": "아이콘 URL", + "instruction": "앱 아이콘 링크 (최대 512x512, SVG 권장)" + }, + "submit_button": "제출", + "submit_succeeded": "애플리케이션 양식이 성공적으로 제출되었습니다. 협조해 주셔서 감사합니다!", + "submit_failed": "오류가 발생했습니다!" + }, + "game_form": { + "title": "게임 요청 폼", + "description": "게임 호환성에 대한 다음 정보를 작성해주세요.", + "game_name": "게임 이름", + "game_category": { + "description": "게임 카테고리", + "instruction": "아래 목록에서 하나의 카테고리를 선택하세요.", + "fetching_categories": "게임 카테고리 가져오는 중. 잠시만 기다려 주세요..." + }, + "publisher": "출판사", + "compatibility": { + "description": "호환성", + "perfect": "Perfect - 1080p 해상도에서 60 FPS 이상으로 실행되며, 게임 경험에 영향을 미치는 글리치나 문제가 없습니다", + "playable": "Playable - 1080p 해상도에서 30 FPS 이상으로 실행되며, 게임 경험에 영향을 미치는 최소한의 글리치나 문제가 있습니다", + "runs": "Runs - 30 FPS 미만으로 실행되며, 게임 경험에 영향을 미칠 수 있는 버그가 있습니다", + "unplayable": "Unplayable - 안티치트 또는 기타 실패로 인해 실행되지 않습니다" + }, + "device_configuration": "디바이스 구성", + "date_tested": "테스트 날짜", + "os_version": "OS 버전", + "driver_id": "드라이버 ID", + "compatibility_details": "호환성 세부사항", + "auto_super_resolution_compatibility": "자동 슈퍼 해상도 호환성", + "auto_super_resolution_fps_bost": "자동 슈퍼 해상도 FPS 향상", + "your_name_gamertag": "이름/게이머 태그", + "submit_button": "제출", + "submit_succeeded": "게임 폼이 성공적으로 제출되었습니다. 협조해 주셔서 감사합니다!", + "submit_failed": "오류가 발생했습니다!" + } +} diff --git a/public/locales/zh/translation.json b/public/locales/zh/translation.json new file mode 100644 index 00000000..8d0f96f4 --- /dev/null +++ b/public/locales/zh/translation.json @@ -0,0 +1,118 @@ +{ + "header": { + "main": "适用于Arm的Windows就绪软件" + }, + "bradcrumbs": { + "home": "主页", + "contributing": "贡献", + "applications": "应用程序", + "search": "搜索", + "games": "游戏" + }, + "footer": { + "report_an_issue": "报告问题", + "edit_on_github": "在 Github 上编辑", + "legal": "法律声明", + "contact": "联系我们", + "help": "帮助", + "takedown": "内容删除请求", + "copyright": "所有产品名称、徽标、品牌、商标和注册商标均为其各自所有者的财产。数据的准确性不由 Linaro 保证。", + "games_count": "游戏" + }, + "search": { + "search": "搜索", + "clear_search": "清除搜索", + "no_information_start": "我们的数据中没有相关信息。为什么不联系开发者的网站,或者在", + "no_information_here": "这里", + "no_information_end": "提交反馈请求,以便我们进行调查呢?" + }, + "applications": { + "info": "以下是一些已测试的顶级应用。使用搜索栏搜索其他已测试的应用。", + "search_button": "搜索更多应用程序", + "search_placeholder": "搜索应用程序", + "search_instruction": "开始搜索,请输入搜索查询并按 Enter,或选择一个类别", + "categories": "类别", + "version_from": "版本", + "download": "下载", + "report_last_updated": "报告最后更新", + "website": "网站", + "more_info": "更多信息" + }, + "games": { + "search_placeholder": "搜索游戏", + "user_reports": "用户报告", + "publisher": "发行商", + "categories": "类别", + "date_tested": "测试日期", + "frame_rate": "帧率", + "device_configuration": "设备配置", + "os_build_number": "OS 构建编号", + "driver_id": "驱动程序 ID", + "auto_super_resolution": "自动超分辨率", + "compatible": "兼容", + "enablement": "启用", + "fps_boost": "FPS 提升", + "opt_in_steps": "选择加入步骤", + "compatibility": "兼容性", + "auto_sr": "自动 SR", + "link": "链接", + "notes": "备注", + "details": "详细信息" + }, + "application_form": { + "title": "应用请求表单", + "description": "请填写以下有关应用兼容性的信息。", + "app_name": "应用名称", + "publisher": "发布者", + "report_type": { + "description": "您在报告什么?", + "request_test": "请求测试此应用", + "submit_update": "提交新的或更新的应用信息" + }, + "app_category": { + "description": "应用类别", + "instruction": "从以下列表中选择一个或多个类别。要选择多个选项,请按住 'Ctrl' 然后点击", + "fetching_categories": "正在获取应用类别,请稍候..." + }, + "download_url": "应用下载 URL 或开发者网站", + "displayed_arm_compatibility": "显示的 ARM 兼容性?", + "earliest_compatible_version": "最早兼容的版本号", + "execution_compatibility": "执行兼容性", + "icon": { + "description": "图标 URL", + "instruction": "应用图标链接(最大 512x512,建议使用 SVG 格式)" + }, + "submit_button": "提交", + "submit_succeeded": "应用表单已成功提交,谢谢您的协作!", + "submit_failed": "发生错误!" + }, + "game_form": { + "title": "游戏请求表格", + "description": "请填写以下关于游戏兼容性的信息。", + "game_name": "游戏名称", + "game_category": { + "description": "游戏类别", + "instruction": "从下面的列表中选择一个类别。", + "fetching_categories": "正在获取游戏类别,请稍候..." + }, + "publisher": "发布者", + "compatibility": { + "description": "兼容性", + "perfect": "Perfect - 在 1080p 分辨率下 60 FPS 以上运行,没有任何影响游戏体验的故障或问题", + "playable": "Playable - 在 1080p 分辨率下 30 FPS 以上运行,存在影响游戏体验的最小故障或问题", + "runs": "Runs - 在低于 30 FPS 的情况下运行,或有可能影响游戏体验的错误", + "unplayable": "Unplayable - 由于反作弊或其他失败原因无法运行" + }, + "device_configuration": "设备配置", + "date_tested": "测试日期", + "os_version": "操作系统版本", + "driver_id": "驱动程序 ID", + "compatibility_details": "兼容性详细信息", + "auto_super_resolution_compatibility": "自动超分辨率兼容性", + "auto_super_resolution_fps_bost": "自动超分辨率 FPS 提升", + "your_name_gamertag": "您的名字/玩家标签", + "submit_button": "提交", + "submit_succeeded": "游戏表单成功提交,谢谢您的合作!", + "submit_failed": "发生错误!" + } +} diff --git a/src/components/Common/BaseHead.astro b/src/components/Common/BaseHead.astro index 283ad5fe..95360333 100644 --- a/src/components/Common/BaseHead.astro +++ b/src/components/Common/BaseHead.astro @@ -9,7 +9,7 @@ export interface Props { image?: string; } -const canonicalURL = new URL(Astro.url.pathname, Astro.site); +const canonicalURL = new URL(Astro.url.pathname, Astro.site).toString(); const { title, description } = Astro.props; import { AstroSeo } from "@astrolib/seo"; @@ -30,5 +30,5 @@ import { AstroSeo } from "@astrolib/seo"; diff --git a/src/components/Common/Breadcrumbs.astro b/src/components/Common/Breadcrumbs.astro index 51dca090..047924bf 100644 --- a/src/components/Common/Breadcrumbs.astro +++ b/src/components/Common/Breadcrumbs.astro @@ -1,15 +1,17 @@ --- +import { t } from "i18next"; + export type Breadcrumb = { title: string; href: string; }; type Props = { + language: string; breadcrumbs: Breadcrumb[]; }; -const { breadcrumbs } = Astro.props; - -console.log(Astro.url.pathname); +const { breadcrumbs, language } = Astro.props; +console.log(Astro.props); --- { @@ -18,10 +20,10 @@ console.log(Astro.url.pathname);
  1. - Home + {t('bradcrumbs.home')}
  2. {breadcrumbs.map((breadcrumb: Breadcrumb) => { diff --git a/src/components/Common/Footer.astro b/src/components/Common/Footer.astro index 8bc95cdb..240cae02 100644 --- a/src/components/Common/Footer.astro +++ b/src/components/Common/Footer.astro @@ -2,33 +2,37 @@ import { getCollection } from "astro:content"; import { Image } from "astro:assets"; import LinaroLogo from "../../assets/powered-by-linaro.svg"; -import type { CollectionEntry } from "astro:content"; +import { getRelativeLocaleUrl } from 'astro:i18n'; +import { DEFAULT_LOCALE } from "../../config/i18nConfig"; +import { t } from "i18next"; +const { language } = Astro.props; const today = new Date(); +const locale = language ?? DEFAULT_LOCALE; const links = [ { - text: "Report an issue", + text: t('footer.report_an_issue'), href: "https://github.com/Linaro/works-on-woa/issues/new", }, { - text: "Edit on Github", + text: t('footer.edit_on_github'), href: "https://github.com/Linaro/works-on-woa", }, { - text: "Legal", + text: t('footer.legal'), href: "https://www.linaro.org/legal/", }, { - text: "Contact", + text: t('footer.contact'), href: "https://www.linaro.org/contact/", }, { - text: "Help", - href: "/help/", + text: t('footer.help'), + href: getRelativeLocaleUrl(locale, "help"), }, { - text: "Content takedown request", - href: "/takedown/", + text: t('footer.takedown'), + href: getRelativeLocaleUrl(locale, "takedown"), }, ]; @@ -61,7 +65,7 @@ const path = Astro.url.pathname; return ( <> - {games.length} games + {games.length} {t('footer.games_count')} ); } @@ -88,8 +92,6 @@ const path = Astro.url.pathname;

    Copyright © {today.getFullYear()} - Linaro Limited. All product names, logos, brands, trademarks and registered trademarks - are property of their respective owners. Accuracy of the data is not guaranteed - by Linaro. + Linaro Limited. {t('footer.copyright')}

    diff --git a/src/components/Common/Header.astro b/src/components/Common/Header.astro index 8a627f53..22c5b8a9 100644 --- a/src/components/Common/Header.astro +++ b/src/components/Common/Header.astro @@ -1,9 +1,12 @@ --- import { getImage } from "astro:assets"; import WoaBanner from "../../assets/WoA-banner.png"; +import i18next, { t } from "i18next"; +import { LanguageSelector } from "astro-i18next/components"; const optimizedBanner = await getImage({ src: WoaBanner }); const bgUrl = `url('${optimizedBanner.src}')`; +const homeURL = `/${i18next.language}`; ---
    @@ -17,8 +20,19 @@ const bgUrl = `url('${optimizedBanner.src}')`;

    Windows on Arm Ready Software{t('header.main')}

    + +
    diff --git a/src/components/Projects/ApplicationDetails.astro b/src/components/Projects/ApplicationDetails.astro index 69ab072f..4672ce9f 100644 --- a/src/components/Projects/ApplicationDetails.astro +++ b/src/components/Projects/ApplicationDetails.astro @@ -1,7 +1,8 @@ --- import { getEntries } from "astro:content"; import { type CollectionEntry } from "astro:content"; -import { toTitleCase } from "../../util/formatting"; +import { t } from "i18next"; +import { updateLanguage } from "../../util/updateLanguage"; type Props = { application: CollectionEntry<"applications"> }; const { @@ -20,9 +21,11 @@ const { } = data; const { Content } = await render(); +const locale = updateLanguage(Astro.url); --- +
    - Version From: + {t('applications.version_from')}: {version_from} ) }
  3. - Categories: + {t('applications.categories')}: { categories.length > 0 ? ( categories.map((category, index) => ( @@ -103,7 +106,7 @@ const { Content } = await render();
  4. @@ -114,7 +117,7 @@ const { Content } = await render();
  5. @@ -125,7 +128,7 @@ const { Content } = await render();
  6. diff --git a/src/components/Projects/ApplicationListing.astro b/src/components/Projects/ApplicationListing.astro index 11f7babc..77e7ed6c 100644 --- a/src/components/Projects/ApplicationListing.astro +++ b/src/components/Projects/ApplicationListing.astro @@ -1,6 +1,9 @@ --- import type { CollectionEntry } from "astro:content"; import { getEntry } from "astro:content"; +import { updateLanguage } from "../../util/updateLanguage"; +import { t } from "i18next"; + type Props = CollectionEntry<"applications">; const { id, data, slug } = Astro.props; const { icon, name, categories } = data; @@ -10,7 +13,8 @@ const categoryPromises = categories.map(async (category) => getEntry("applications_categories", category.slug) ); const categoriesData = await Promise.all(categoryPromises); -const url = `/applications/${slug}/`; +const locale = updateLanguage(Astro.url); +const url = `/${locale}/applications/${slug}/`; ---
  7. - Version From:  + {t('applications.version_from')}:  {data.version_from}

    - Categories: + {t('applications.categories')}: { categoriesData.map((category) => ( diff --git a/src/components/Projects/GameDetails.astro b/src/components/Projects/GameDetails.astro index b3b3ca1e..cea076f6 100644 --- a/src/components/Projects/GameDetails.astro +++ b/src/components/Projects/GameDetails.astro @@ -3,6 +3,8 @@ import { getEntries } from "astro:content"; import { type CollectionEntry } from "astro:content"; import dayjs from "dayjs"; import { toTitleCase } from "../../util/formatting"; +import { t } from "i18next"; +import { updateLanguage } from "../../util/updateLanguage"; type Props = { game: CollectionEntry<"games"> }; const { @@ -26,10 +28,12 @@ const { } = data; const { Content } = await render(); +const locale = updateLanguage(Astro.url); ---

    +

    - Publisher: + {t('games.publisher')}: {publisher}

  8. ) }
  9. - Categories: + {t('games.categories')}: { categories.length > 0 ? ( categories.map((category, index) => ( @@ -89,7 +93,7 @@ const { Content } = await render(); { date_tested && (
  10. - Date tested: + {t('games.date_tested')}: {dayjs(date_tested).format("YYYY-MM-DD")}
  11. ) @@ -97,7 +101,7 @@ const { Content } = await render(); { frame_rate && (
  12. - Frame Rate: + {t('games.frame_rate')}: {frame_rate}
  13. ) @@ -105,7 +109,7 @@ const { Content } = await render(); { device_configuration && (
  14. - Device Configuration: + {t('games.device_configuration')}: {device_configuration}
  15. ) @@ -113,7 +117,7 @@ const { Content } = await render(); { os_version && (
  16. - OS Build Number: + {t('games.os_build_number')}: {os_version}
  17. ) @@ -121,7 +125,7 @@ const { Content } = await render(); { driver_id && (
  18. - Driver ID: + {t('games.driver_id')}: {driver_id}
  19. ) @@ -129,22 +133,22 @@ const { Content } = await render(); { auto_super_resolution && (
  20. -
    Auto Super Resolution:
    +
    {t('games.auto_super_resolution')}:
    • - Compatible: + {t('games.compatible')}: {auto_super_resolution.compatibility}
    • {auto_super_resolution.fps_boost && (
    • - FPS Boost: + {t('games.fps_boost')}: {auto_super_resolution.fps_boost}
    • )}
  21. - Opt In Steps: + {t('games.opt_in_steps')}:
    {auto_super_resolution.opt_in_steps.map((item) => (

    {item}

    @@ -157,7 +161,7 @@ const { Content } = await render(); { link && (
  22. - Link: + {t('games.link')}: {link} @@ -167,7 +171,7 @@ const { Content } = await render(); { (
  23. - Notes + {t('games.notes')}
    diff --git a/src/components/Projects/UserReports.astro b/src/components/Projects/UserReports.astro index 182766ba..aef730ed 100644 --- a/src/components/Projects/UserReports.astro +++ b/src/components/Projects/UserReports.astro @@ -1,6 +1,7 @@ --- import type { CollectionEntry } from "astro:content"; import dayjs from "dayjs"; +import { t } from "i18next"; type Props = { reports: CollectionEntry<`user_reports_${T}`>[]; @@ -13,7 +14,7 @@ console.log(reports); { reports?.length > 0 && (
    -

    User Reports

    +

    {t('games.user_reports')}

      {reports.map(({ data }: any) => (
    • @@ -46,43 +47,43 @@ console.log(reports); <> {data.device_configuration && (
    • - Device Configuration: + {t('games.device_configuration')}: {data.device_configuration}
    • )} {data.os_version && (
    • - OS Build Number: + {t('games.os_build_number')}: {data.os_version}
    • )} {data.driver_id && (
    • - Driver ID: + {t('games.driver_id')}: {data.driver_id}
    • )} {data.auto_super_resolution && (
    • - Auto Super Resolution:{" "} + {t('games.auto_super_resolution')}:{" "}
      • - Compatible: + {t('games.compatible')}: {data.auto_super_resolution.compatibility}
      • - Enablement: + {t('games.enablement')}: {data.auto_super_resolution.enablement}
      • {data.auto_super_resolution.fps_boost && (
      • - FPS Boost: + {t('games.fps_boost')}: {data.auto_super_resolution.fps_boost} @@ -108,7 +109,7 @@ console.log(reports); }}}
      • - Details: + {t('games.details')}:

        {data.compatibility_details}

      diff --git a/src/components/Search/PageFind.tsx b/src/components/Search/PageFind.tsx index addaf187..050a1f6f 100644 --- a/src/components/Search/PageFind.tsx +++ b/src/components/Search/PageFind.tsx @@ -1,6 +1,5 @@ import { Show, - createEffect, createMemo, createResource, createSignal, @@ -11,6 +10,8 @@ import SearchIcon from "./SearchIcon"; import ClearIcon from "./ClearIcon"; import type { JSX } from "solid-js/h/jsx-runtime"; import type { CollectionEntry, CollectionKey } from "astro:content"; +import { t } from "i18next"; +import { updateLanguage } from "../../util/updateLanguage"; const bundlePath = `${import.meta.env.BASE_URL}pagefind/`; const pagefind = await import(/* @vite-ignore */ `${bundlePath}pagefind.js`); @@ -56,6 +57,8 @@ export type Results = { }; }; +const locale = updateLanguage(window.location); + const fetchResults = async ({ query, filters, @@ -63,7 +66,6 @@ const fetchResults = async ({ query: string | null; filters: Filters; }) => { - let adjustedAutoSR: {[key: string]: string[]}= { "any": filters["auto_super_resolution.compatibility"] } @@ -76,7 +78,7 @@ const fetchResults = async ({ return await pagefind.debouncedSearch(); } - if(filters["auto_super_resolution.compatibility"] && filters["auto_super_resolution.compatibility"].includes("unknown")){ + if (filters["auto_super_resolution.compatibility"] && filters["auto_super_resolution.compatibility"].includes("unknown")){ adjustedAutoSR = { "not": ["yes, out-of-box", "yes, opt-in", "no"] } @@ -85,6 +87,7 @@ const fetchResults = async ({ return await pagefind.debouncedSearch(query, { filters: { ...filters, + "language": { any: locale }, "category": { any: filters.category }, "compatibility": { any: filters.compatibility }, "auto_super_resolution.compatibility": { @@ -107,10 +110,12 @@ const getQueryParams = ({ filters, query }: SearchQuery) => { const url = new URL( window.location.origin + "/" + + `${locale}/` + filters.type[0] + (filters.type[0] === "applications" ? "/search" : "") + "/" ); + if (query) url.searchParams.append("query", query); if (filters.category?.length > 0) { url.searchParams.append("category", filters.category.join(",")); @@ -257,7 +262,6 @@ const PageFind = ({ if (searchrun() === 2 ) { setSearchRun(0); - createEffect(() => console.log(searchrun)); } else { @@ -268,7 +272,6 @@ const PageFind = ({ const [results] = createResource(request, fetchResults); const [filterOptions] = createResource(request, fetchFilterOptions); - createEffect(() => console.log(results())); return (
      { return await result.data(); }; +const locale = updateLanguage(window.location); const PAGE_SIZE = 10; const AutoSRFormatMap: {[key: string]: string} = { @@ -98,7 +101,7 @@ const Result = ({

      - Categories: + {t('games.categories')}: {(cat: string) => ( @@ -118,14 +121,14 @@ const Result = ({

      - Version from:  + {t('applications.version_from')}:  {project()?.meta.version_from}

      - Categories: + {t('applications.categories')}: {(cat: string) => ( @@ -140,18 +143,18 @@ const Result = ({

      - Compatibility: + {t('games.compatibility')}: {project().filters.compatibility}

      - Auto SR: + {t('games.auto_sr')}: {formartAutoSR(project()?.filters["auto_super_resolution.compatibility"]) ?? "Unknown" }

      - Date Tested: + {t('games.date_tested')}: {dayjs(project()?.meta.date_tested).format("DD-MMM-YYYY")} @@ -191,7 +194,7 @@ const Results = ({ type: "applications" | "games"; searchRun: Accessor }) => { - const [paginatedResults, setPaginatedResults] = createSignal([]); + const [paginatedResults, setPaginatedResults] = createSignal([]); const pageCount = createMemo(() => { const totalResults = results()?.results.length; @@ -229,8 +232,6 @@ const Results = ({ setFilter(filter, selection, true); }; - console.log(search().filters) - return (

      @@ -275,12 +276,12 @@ const Results = ({ }>

      - There is no information in our data about that. Why not contact the developer on their web site, or complete a feedback request here for us to investigate. + {t('search.no_information_start')} {t('search.no_information_here')} {t('search.no_information_end')}

      @@ -292,8 +293,7 @@ const Results = ({ } >

      - To begin searching, enter a search query and press enter, or choose - a category. + {t('applications.search_instruction')}

      diff --git a/src/components/Search/SearchForm.astro b/src/components/Search/SearchForm.astro index 95c28df8..25ef2e42 100644 --- a/src/components/Search/SearchForm.astro +++ b/src/components/Search/SearchForm.astro @@ -1,5 +1,5 @@ --- -// import { Icon } from "astro-icon"; +import { t } from "i18next"; ---
      @@ -17,7 +17,7 @@
      {t('search.search')}
      diff --git a/src/config/i18nConfig.js b/src/config/i18nConfig.js new file mode 100644 index 00000000..32481bd5 --- /dev/null +++ b/src/config/i18nConfig.js @@ -0,0 +1,5 @@ +export const DEFAULT_LOCALE = 'en'; +export const JA_LOCALE = 'ja'; +export const KO_LOCALE = 'ko'; +export const ZH_LOCALE = 'zh'; +export const LOCALES = [DEFAULT_LOCALE, JA_LOCALE, KO_LOCALE, ZH_LOCALE]; diff --git a/src/layouts/BaseLayout.astro b/src/layouts/BaseLayout.astro index a174ee45..140071ff 100644 --- a/src/layouts/BaseLayout.astro +++ b/src/layouts/BaseLayout.astro @@ -4,21 +4,23 @@ import type { Breadcrumb } from "../components/Common/Breadcrumbs.astro"; import Breadcrumbs from "../components/Common/Breadcrumbs.astro"; import Footer from "../components/Common/Footer.astro"; import Header from "../components/Common/Header.astro"; +import { updateLanguage } from "../util/updateLanguage"; type Props = { title: string; description: string; breadcrumbs: Breadcrumb[] }; const props = Astro.props; +const locale = updateLanguage(Astro.url); --- - +
      - +
      -
      +
      diff --git a/src/layouts/InfoLayout.astro b/src/layouts/InfoLayout.astro index 72ad153f..ef41e5ec 100644 --- a/src/layouts/InfoLayout.astro +++ b/src/layouts/InfoLayout.astro @@ -1,12 +1,18 @@ --- -import "../styles/infopage.css"; import BaseLayout from "./BaseLayout.astro"; -const { frontmatter, file } = Astro.props; +import "../styles/infopage.css"; +import { LOCALES } from "../config/i18nConfig"; +import { t } from "i18next"; + +const { frontmatter } = Astro.props; +console.log("From InfoLayout"); console.log(Astro.props); -let title = frontmatter.title + " | Windows on Arm Ready Software"; +let title = frontmatter.title + " | " + t('header.main'); let breadcrumbs = [{ href: `${Astro.url.pathname}`, title: frontmatter.title }]; -if (frontmatter.title === "Homepage") { - title = "Windows on Arm Ready Software"; +const localeSegment = Astro.url.pathname.startsWith('/') ? Astro.url.pathname.replace(/\/$/, '').slice(1) : Astro.url.pathname; + +if (LOCALES.includes(localeSegment)) { + title = t('header.main'); breadcrumbs = []; } --- diff --git a/src/layouts/ProjectLayout.astro b/src/layouts/ProjectLayout.astro index f11917f4..99f787a4 100644 --- a/src/layouts/ProjectLayout.astro +++ b/src/layouts/ProjectLayout.astro @@ -1,12 +1,12 @@ --- import { getEntry, type CollectionEntry } from "astro:content"; -import BaseHead from "../components/Common/BaseHead.astro"; -import Footer from "../components/Common/Footer.astro"; import Search from "../components/Search/Search.astro"; import ProjectDetails from "../components/Projects/ProjectDetails.astro"; import dayjs from "dayjs"; import UserReports from "../components/Projects/UserReports.astro"; import BaseLayout from "./BaseLayout.astro"; +import { t } from "i18next"; +import { updateLanguage } from "../util/updateLanguage"; type Props = { project: CollectionEntry; @@ -15,21 +15,18 @@ type Props = { type: T; }; +const locale = updateLanguage(Astro.url); const { project, date, reports, type } = Astro.props; - -const { - data: { name }, -} = project; - -const title = type === "applications" ? "Applications" : "Games"; +const { data: { name } } = project; +const title = type === "applications" ? t('bradcrumbs.applications') : t('bradcrumbs.games'); --- {type === "games" && } @@ -40,7 +37,7 @@ const title = type === "applications" ? "Applications" : "Games";

      - Report last updated: { + {t('applications.report_last_updated')}: { date ? ( dayjs(date).format("DD MMM YYYY") ) : ( @@ -53,9 +50,9 @@ const title = type === "applications" ? "Applications" : "Games";

      { type === "applications" && ( - + ) diff --git a/src/pages/applications/[...slug].astro b/src/pages/[lang]/applications/[...slug].astro similarity index 79% rename from src/pages/applications/[...slug].astro rename to src/pages/[lang]/applications/[...slug].astro index bfa88df0..845e3b4b 100644 --- a/src/pages/applications/[...slug].astro +++ b/src/pages/[lang]/applications/[...slug].astro @@ -1,18 +1,21 @@ --- import { type CollectionEntry, getCollection, getEntry } from "astro:content"; -import ProjectLayout from "../../layouts/ProjectLayout.astro"; +import ProjectLayout from "../../../layouts/ProjectLayout.astro"; import { exec } from "node:child_process"; import { promisify } from "node:util"; +import i18next from "i18next"; +import { LOCALES } from "../../../config/i18nConfig"; const execAsync = promisify(exec); export async function getStaticPaths() { const projects = await getCollection("applications"); - - return projects.map((project) => ({ - params: { slug: project.slug }, - props: project, - })); + return LOCALES.flatMap(locale => + projects.map(project => ({ + params: { lang: locale, slug: project.slug }, + props: project, + })) + ); } const { slug } = Astro.params; diff --git a/src/pages/[lang]/applications/index.astro b/src/pages/[lang]/applications/index.astro new file mode 100644 index 00000000..f579b95d --- /dev/null +++ b/src/pages/[lang]/applications/index.astro @@ -0,0 +1,52 @@ +--- +import { getCollection, type CollectionEntry } from "astro:content"; +import BaseLayout from "../../../layouts/BaseLayout.astro"; +import ApplicationListing from "../../../components/Projects/ApplicationListing.astro"; +import { LOCALES } from "../../../config/i18nConfig"; +import { t } from "i18next"; +import { updateLanguage } from "../../../util/updateLanguage"; + +export function getStaticPaths() { + return LOCALES.map(locale => ({ + params: { lang: locale }, + })); +} + +const featuredApplications = await getCollection( + "applications", + ({ data }: CollectionEntry<"applications">) => { + return data.featured === true; + } +); + +const locale = updateLanguage(Astro.url); +--- + + +
      + {t('applications.info')} +
      + + + +
      +
        + { + featuredApplications.map((application) => ( + + )) + } +
      +
      +
      diff --git a/src/pages/[lang]/applications/search.astro b/src/pages/[lang]/applications/search.astro new file mode 100644 index 00000000..a9b293df --- /dev/null +++ b/src/pages/[lang]/applications/search.astro @@ -0,0 +1,26 @@ +--- +import SearchComponent from "../../../components/Search/Search.astro"; +import BaseLayout from "../../../layouts/BaseLayout.astro"; +import { LOCALES } from "../../../config/i18nConfig"; +import { updateLanguage } from "../../../util/updateLanguage"; +import { t } from "i18next"; + +export function getStaticPaths() { + return LOCALES.map(locale => ({ + params: { lang: locale }, + })); +} + +const locale = updateLanguage(Astro.url); +--- + + + + diff --git a/src/pages/[lang]/contributing/applications.astro b/src/pages/[lang]/contributing/applications.astro new file mode 100644 index 00000000..4e5d372e --- /dev/null +++ b/src/pages/[lang]/contributing/applications.astro @@ -0,0 +1,143 @@ +--- +import BaseLayout from "../../../layouts/BaseLayout.astro"; +import { LOCALES } from "../../../config/i18nConfig"; +import { updateLanguage } from "../../../util/updateLanguage"; +import { t } from "i18next"; + +export function getStaticPaths() { + return LOCALES.map(locale => ({ + params: { lang: locale }, + })); +} + +const locale = updateLanguage(Astro.url); +const recaptcha_url = `https://www.google.com/recaptcha/api.js?hl=${locale}`; +--- + + + + + + + +
      + +

      {t('application_form.app_category.fetching_categories')}

      +
      + +
      + + +
      + + \ No newline at end of file diff --git a/src/pages/[lang]/contributing/games.astro b/src/pages/[lang]/contributing/games.astro new file mode 100644 index 00000000..1b093eff --- /dev/null +++ b/src/pages/[lang]/contributing/games.astro @@ -0,0 +1,147 @@ +--- +import BaseLayout from "../../../layouts/BaseLayout.astro"; +import { LOCALES } from "../../../config/i18nConfig"; +import { updateLanguage } from "../../../util/updateLanguage"; +import { t } from "i18next"; + +export function getStaticPaths() { + return LOCALES.map(locale => ({ + params: { lang: locale }, + })); +} + +const locale = updateLanguage(Astro.url); +const recaptcha_url = `https://www.google.com/recaptcha/api.js?hl=${locale}`; +--- + + + + + + + +
      + +

      Fetching games categories. Please wait...

      +
      + +
      + + +
      + + + diff --git a/src/pages/games/[...slug].astro b/src/pages/[lang]/games/[...slug].astro similarity index 79% rename from src/pages/games/[...slug].astro rename to src/pages/[lang]/games/[...slug].astro index bb247669..014a581e 100644 --- a/src/pages/games/[...slug].astro +++ b/src/pages/[lang]/games/[...slug].astro @@ -1,18 +1,22 @@ --- import { type CollectionEntry, getCollection } from "astro:content"; -import ProjectLayout from "../../layouts/ProjectLayout.astro"; +import ProjectLayout from "../../../layouts/ProjectLayout.astro"; import { exec } from "node:child_process"; import { promisify } from "node:util"; import { getEntry } from "astro:content"; +import i18next from "i18next"; +import { LOCALES } from "../../../config/i18nConfig"; const execAsync = promisify(exec); export async function getStaticPaths() { const projects = await getCollection("games"); - return projects.map((project) => ({ - params: { slug: project.slug }, - props: project, - })); + return LOCALES.flatMap(locale => + projects.map(project => ({ + params: { lang: locale, slug: project.slug }, + props: project, + })) + ); } const { slug } = Astro.params; diff --git a/src/pages/[lang]/games/index.astro b/src/pages/[lang]/games/index.astro new file mode 100644 index 00000000..36327fe1 --- /dev/null +++ b/src/pages/[lang]/games/index.astro @@ -0,0 +1,23 @@ +--- +import Search from "../../../components/Search/Search.astro"; +import { LOCALES } from "../../../config/i18nConfig"; +import BaseLayout from "../../../layouts/BaseLayout.astro"; +import { updateLanguage } from "../../../util/updateLanguage"; +import { t } from "i18next"; + +export function getStaticPaths() { + return LOCALES.map(locale => ({ + params: { lang: locale }, + })); +} + +const locale = updateLanguage(Astro.url); +--- + + + + diff --git a/src/pages/[lang]/search/index.astro b/src/pages/[lang]/search/index.astro new file mode 100644 index 00000000..a0301e32 --- /dev/null +++ b/src/pages/[lang]/search/index.astro @@ -0,0 +1,35 @@ +--- +import BaseHead from "../../../components/Common/BaseHead.astro"; +import Header from "../../../components/Common/Header.astro"; +import Footer from "../../../components/Common/Footer.astro"; +import Search from "../../../components/Search/Search.astro"; +import { LOCALES } from "../../../config/i18nConfig"; +import i18next from "i18next"; + +export function getStaticPaths() { + return LOCALES.map(locale => ({ + params: { lang: locale }, + })); +} + +const locale = i18next.language; + +// Desestructura los parámetros de la URL +const { lang } = Astro.params; +--- + + + + + + +
      +
      + +
      +
      + + diff --git a/src/pages/applications/index.astro b/src/pages/applications/index.astro deleted file mode 100644 index 5062c0ad..00000000 --- a/src/pages/applications/index.astro +++ /dev/null @@ -1,44 +0,0 @@ ---- -import { getCollection, type CollectionEntry } from "astro:content"; -import BaseLayout from "../../layouts/BaseLayout.astro"; -import ApplicationListing from "../../components/Projects/ApplicationListing.astro"; -import Search from "../../components/Search/Search.astro"; - -const featuredApplications = await getCollection( - "applications", - ({ data }: CollectionEntry<"applications">) => { - return data.featured === true; - } -); ---- - - - - -
      - Below are some of the top apps that have been tested. Use the search bar to search for other tested apps. -
      - - - -
      -
        - { - featuredApplications.map((application) => ( - - )) - } -
      -
      - -
      diff --git a/src/pages/applications/search.astro b/src/pages/applications/search.astro deleted file mode 100644 index 09c17d40..00000000 --- a/src/pages/applications/search.astro +++ /dev/null @@ -1,15 +0,0 @@ ---- -import SearchComponent from "../../components/Search/Search.astro"; -import BaseLayout from "../../layouts/BaseLayout.astro"; ---- - - - - diff --git a/src/pages/contributing.md b/src/pages/en/contributing.md similarity index 99% rename from src/pages/contributing.md rename to src/pages/en/contributing.md index 50bbc67f..d2caef3f 100644 --- a/src/pages/contributing.md +++ b/src/pages/en/contributing.md @@ -1,5 +1,5 @@ --- -layout: ../layouts/InfoLayout.astro +layout: ../../layouts/InfoLayout.astro title: Contributing description: How to contribute to this site --- diff --git a/src/pages/help.md b/src/pages/en/help.md similarity index 97% rename from src/pages/help.md rename to src/pages/en/help.md index a3ee2fba..7dadb45f 100644 --- a/src/pages/help.md +++ b/src/pages/en/help.md @@ -1,5 +1,5 @@ --- -layout: ../layouts/InfoLayout.astro +layout: ../../layouts/InfoLayout.astro title: Help description: Help page for using the Windows on Arm Ready Software website. --- @@ -19,7 +19,7 @@ For applications, the **Compatibility** field can be one of the following values The **Version From** field shows the first known publicly available version of the app that is compatible with Windows on Arm. When a **Download** button is available, clicking will navigate to either the Microsoft Store product description page, or the a web location that offers the app install. For apps that are **Unknown**, the **Website** button will be shown in place of **Download**. Clicking the **Website** button will navigate to the app developers main web page so you can check the latest status, and contact the developer directly to request Windows on Arm support. -Information on how you can make your own contribution to this web site, either for an app that is not yet listed, or by providing status updates for an existing app, please read [Contributing](/contributing). +Information on how you can make your own contribution to this web site, either for an app that is not yet listed, or by providing status updates for an existing app, please read [Contributing](/en/contributing). For games, the **Compatibility** field can be one of the following values: @@ -50,4 +50,4 @@ In each game, you'll see the following fields. Below, we've defined what they me To see games that are compatible with Automatic Super Resolution, select the "yes, out-of-box," and "yes, opt-in" entries from the Auto SR drop-down menu found to the right of the search bar on the games page. -Information on how you can make your own contribution to this web site, either for a game that is not yet listed, or by adding your own report to an existing game, please read [Contributing](/contributing). +Information on how you can make your own contribution to this web site, either for a game that is not yet listed, or by adding your own report to an existing game, please read [Contributing](/en/contributing). diff --git a/src/pages/index.md b/src/pages/en/index.md similarity index 76% rename from src/pages/index.md rename to src/pages/en/index.md index 8e0e7c6d..05c12674 100644 --- a/src/pages/index.md +++ b/src/pages/en/index.md @@ -1,5 +1,5 @@ --- -layout: ../layouts/InfoLayout.astro +layout: ../../layouts/InfoLayout.astro title: "Homepage" description: Windows on Arm Ready Software --- @@ -8,9 +8,9 @@ Welcome to Works on Windows on Arm! This site is your source for compatibility information for many apps and games on Windows devices that run on Arm architecture and will be updated over time. -For more information on how we define compatible and how to navigate the site, refer to the [help page](/help). +For more information on how we define compatible and how to navigate the site, refer to the [help page](/en/help). -If you have tested apps or games and want to contribute your own results, please read the [contributing guide](/contributing) to help you to submit a Pull Request to the open source repository on GitHub. +If you have tested apps or games and want to contribute your own results, please read the [contributing guide](/en/contributing) to help you to submit a Pull Request to the open source repository on GitHub. The information is intended to serve as a guide, but does not absolutely guarantee that a game will run. The results have been tested, but may not work on your specific machine and configuration. If your results differ, please contribute to the site with your own findings. @@ -20,13 +20,13 @@ The information is intended to serve as a guide, but does not absolutely guarant
    • View ApplicationsView Applications
    • View GamesView Games
    diff --git a/src/pages/takedown.md b/src/pages/en/takedown.md similarity index 89% rename from src/pages/takedown.md rename to src/pages/en/takedown.md index 161f9058..76974f21 100644 --- a/src/pages/takedown.md +++ b/src/pages/en/takedown.md @@ -1,5 +1,5 @@ --- -layout: ../layouts/InfoLayout.astro +layout: ../../layouts/InfoLayout.astro title: Takedown description: Information for rightsholders regarding taking down entries from the Windows on Arm ready website. --- diff --git a/src/pages/games/index.astro b/src/pages/games/index.astro deleted file mode 100644 index 3d2ae699..00000000 --- a/src/pages/games/index.astro +++ /dev/null @@ -1,12 +0,0 @@ ---- -import Search from "../../components/Search/Search.astro"; -import BaseLayout from "../../layouts/BaseLayout.astro"; ---- - - - - diff --git a/src/pages/index.astro b/src/pages/index.astro new file mode 100644 index 00000000..a7dc60eb --- /dev/null +++ b/src/pages/index.astro @@ -0,0 +1,15 @@ +--- +import { DEFAULT_LOCALE } from "../config/i18nConfig"; +Astro.redirect(`/${DEFAULT_LOCALE}/`); +--- + + + + + + Redirecting... + + +

    Redirecting to the default locale...

    + + diff --git a/src/pages/search/index.astro b/src/pages/search/index.astro deleted file mode 100644 index 010484ae..00000000 --- a/src/pages/search/index.astro +++ /dev/null @@ -1,22 +0,0 @@ ---- -import BaseHead from "../../components/Common/BaseHead.astro"; -import Header from "../../components/Common/Header.astro"; -import Footer from "../../components/Common/Footer.astro"; -import Search from "../../components/Search/Search.astro"; ---- - - - - - - -
    -
    - -
    -
    - - diff --git a/src/util/updateLanguage.js b/src/util/updateLanguage.js new file mode 100644 index 00000000..84a94c42 --- /dev/null +++ b/src/util/updateLanguage.js @@ -0,0 +1,17 @@ +import i18next from 'i18next'; +import { DEFAULT_LOCALE, LOCALES } from '../config/i18nConfig'; + +export function updateLanguage(url) { + const urlFirstSegment = url.pathname.split('/').filter(Boolean)[0]; + let locale = DEFAULT_LOCALE; + + if (LOCALES.includes(urlFirstSegment)) { + locale = urlFirstSegment; + } + + if (locale !== i18next.language) { + i18next.changeLanguage(locale); + } + + return i18next.language; +} From b85325919d7b288ad3710ea87de8611d3bb37027 Mon Sep 17 00:00:00 2001 From: Gaspar Acevedo Zain <43762887+gasper-az@users.noreply.github.com> Date: Mon, 2 Dec 2024 11:40:58 -0300 Subject: [PATCH 04/11] [feat] Add AWS Lambdas as backend for PR creation --- aws-lambdas/.env_template | 15 + aws-lambdas/AppForm/index.mjs | 73 + aws-lambdas/GameForm/index.mjs | 51 + aws-lambdas/models/file-type.js | 4 + .../models/pull-request-template-data.js | 28 + aws-lambdas/package-lock.json | 1730 +++++++++++++++++ aws-lambdas/package.json | 18 + aws-lambdas/utils/config-manager.js | 89 + aws-lambdas/utils/email-manager.js | 75 + aws-lambdas/utils/octokit-manager.js | 131 ++ .../utils/pull-request-data-generator.js | 75 + aws-lambdas/utils/pull-request-manager.js | 48 + aws-lambdas/utils/recaptcha-validator.js | 20 + aws-lambdas/utils/request-validator.js | 51 + 14 files changed, 2408 insertions(+) create mode 100644 aws-lambdas/.env_template create mode 100644 aws-lambdas/AppForm/index.mjs create mode 100644 aws-lambdas/GameForm/index.mjs create mode 100644 aws-lambdas/models/file-type.js create mode 100644 aws-lambdas/models/pull-request-template-data.js create mode 100644 aws-lambdas/package-lock.json create mode 100644 aws-lambdas/package.json create mode 100644 aws-lambdas/utils/config-manager.js create mode 100644 aws-lambdas/utils/email-manager.js create mode 100644 aws-lambdas/utils/octokit-manager.js create mode 100644 aws-lambdas/utils/pull-request-data-generator.js create mode 100644 aws-lambdas/utils/pull-request-manager.js create mode 100644 aws-lambdas/utils/recaptcha-validator.js create mode 100644 aws-lambdas/utils/request-validator.js diff --git a/aws-lambdas/.env_template b/aws-lambdas/.env_template new file mode 100644 index 00000000..25f0d8ec --- /dev/null +++ b/aws-lambdas/.env_template @@ -0,0 +1,15 @@ +GITHUB_TOKEN= +GITHUB_OWNER= +GITHUB_REPO= +GITHUB_BASE_BRANCH= +GITHUB_APP_ID= +GITHUB_APP_INSTALLATION_ID= +GITHUB_APP_PK_BASE64=" { + console.log('Received event:', JSON.stringify(event, null, 2)); + + try { + const formData = JSON.parse(event.body); + + const refererError = RequestValidator.validateReferer(event.headers, process.env['ALLOWED_REFERER']); + if(!refererError) config = await configManager.loadConfig(FileType.Application); + const validationError = refererError === "" ? await RequestValidator.validateRequest(formData, FileType.Application, config.recaptchaV2VerifyUrl, config.recaptchaV2SecretKey) : 'Access forbidden'; + if (validationError) { + return { statusCode: validationError === 'Access forbidden' ? 403 : 400, headers: HEADERS, body: validationError }; + } + + switch (formData.requestType) { + case RequestTypes.RequestThisAppToBeTested: + await handleTestingRequest(formData); + break; + case RequestTypes.SubmitNewOrUpdatedAppInfo: + await handleSubmitOrUpdateRequest(formData); + break; + default: + return { statusCode: 400, headers: HEADERS, body: `Invalid request type: ${formData.requestType}` }; + } + + return { statusCode: 200, headers: HEADERS, body: 'Successfully processed request' }; + } catch (error) { + return handleError(error); + } +}; + +const handleTestingRequest = async (data) => { + const emailManager = new EmailManager(config.sendgridApiKey, config.senderEmail, config.recipientEmail); + console.log(`Sending email to test the application ${data.name}...`); + await emailManager.sendEmail(`[Request for testing app] - ${data.name}`, emailManager.generateAppTestEmailContent(data.name, data.publisher)); + console.log(`Email for testing application ${data.name} successfully sent`); +}; + +const handleSubmitOrUpdateRequest = async (data) => { + const pullRequestManager = new PullRequestManager(); + await pullRequestManager.createPullRequest(data, { + githubAppId: config.githubAppId, + githubAppInstallationId: config.githubAppInstallationId, + githubAppPkBase64: config.githubAppPkBase64, + githubOwner: config.githubOwner, + githubRepo: config.githubRepo, + githubBaseBranch: config.githubBaseBranch + }, FileType.Application); +}; + +const handleError = (error) => { + console.error(error); + return { statusCode: 500, headers: HEADERS, body: "An error occurred while processing your form submission." }; +}; diff --git a/aws-lambdas/GameForm/index.mjs b/aws-lambdas/GameForm/index.mjs new file mode 100644 index 00000000..5ca64b31 --- /dev/null +++ b/aws-lambdas/GameForm/index.mjs @@ -0,0 +1,51 @@ +import RequestValidator from './utils/request-validator.js'; +import ConfigManager from './utils/config-manager.js'; +import PullRequestManager from './utils/pull-request-manager.js'; +import { FileType } from "./models/file-type.js"; + +const configManager = new ConfigManager(); +let config; + +const HEADERS = { + 'Access-Control-Allow-Origin': '*', + 'Access-Control-Allow-Methods': 'GET, POST, OPTIONS', + 'Access-Control-Allow-Headers': 'Content-Type', +}; + +export const handler = async (event) => { + console.log('Received event:', JSON.stringify(event, null, 2)); + + try { + const formData = JSON.parse(event.body); + + const refererError = RequestValidator.validateReferer(event.headers, process.env['ALLOWED_REFERER']); + if(!refererError) config = await configManager.loadConfig(FileType.Game); + const validationError = refererError === "" ? await RequestValidator.validateRequest(formData, FileType.Game, config.recaptchaV2VerifyUrl, config.recaptchaV2SecretKey) : 'Access forbidden'; + if (validationError) { + return { statusCode: validationError === 'Access forbidden' ? 403 : 400, headers: HEADERS, body: validationError }; + } + + const pullRequestManager = new PullRequestManager(); + + await pullRequestManager.createPullRequest( + formData, + { + githubAppId: config.githubAppId, + githubAppInstallationId: config.githubAppInstallationId, + githubAppPkBase64: config.githubAppPkBase64, + githubOwner: config.githubOwner, + githubRepo: config.githubRepo, + githubBaseBranch: config.githubBaseBranch + }, + FileType.Game + ); + return { statusCode: 200, headers: HEADERS, body: 'Successfully processed request' }; + } catch (error) { + return handleError(error); + } +}; + +const handleError = (error) => { + console.error(error); + return { statusCode: 500, headers: HEADERS, body: "An error occurred while processing your form submission." }; +}; diff --git a/aws-lambdas/models/file-type.js b/aws-lambdas/models/file-type.js new file mode 100644 index 00000000..ab672565 --- /dev/null +++ b/aws-lambdas/models/file-type.js @@ -0,0 +1,4 @@ +export const FileType = Object.freeze({ + Application: "Application", + Game: "Game" +}); diff --git a/aws-lambdas/models/pull-request-template-data.js b/aws-lambdas/models/pull-request-template-data.js new file mode 100644 index 00000000..4803f871 --- /dev/null +++ b/aws-lambdas/models/pull-request-template-data.js @@ -0,0 +1,28 @@ +export const pullRequestTemplateData = { + applicationFileContentTemplate: template`---\nname: ${0}\ncategories: [${1}]\ncompatibility: ${2}\ndisplay_result: ${3}\nversion_from: ${4}\nlink: ${5}\nicon: ${6}\n---`, + applicationFilePathTemplate: template`src/content/applications/${0}.md`, + commitMessageTemplate: template`Add ${0}.md file`, + gameFileContentTemplate: template`---\nname: ${0}\ncategories: [${1}]\npublisher: ${2}\ncompatibility: ${3}\ncompatibility_details: ${4}\ndevice_configuration: ${5}\ndate_tested: ${6}\nos_version: ${7}\ndriver_id: ${8}${9}\n---`, + gameFileSubContentTemplate: template`\nauto_super_resolution:\n\tcompatibility: ${0}\n\tfps boost: ${1}`, + gameFilePathTemplate: template`src/content/games/${0}.md`, + headBaseBranchTemplate: template`heads/${0}`, + newBranchNameTemplate: template`feat/add-${0}-${1}-file-${2}`, // ex: feat/add-outlook-application-file-1234 + newBranchRefNameTemplate: template`refs/heads/${0}`, + pullRequestBodyTemplate: template`Incoming changes:\n- Add file for ${0} ${1} from ${2}\n- This data corresponds to a new ${1}\n\n**NOTE**: this Pull Request has been automatically generated.`, + pullRequestTitleTemplate: template`[Feature] Add file for ${0} ${1}`, // ex: [Feature] Add file for Outlook Application +}; + +// Tagged template function for creating templates with placeholders +// Usage: const value = template`list of values: ${0}, ${1}, {2}`; +// value("first", "second", "third"); // outputs: "list of values: first, second, third"; +function template(strings, ...keys) { + return (...values) => { + const dict = values[values.length - 1] || {}; + const result = [strings[0]]; + keys.forEach((key, i) => { + const value = Number.isInteger(key) ? values[key] : dict[key]; + result.push(value, strings[i + 1]); + }); + return result.join(""); + }; +} diff --git a/aws-lambdas/package-lock.json b/aws-lambdas/package-lock.json new file mode 100644 index 00000000..8d0634de --- /dev/null +++ b/aws-lambdas/package-lock.json @@ -0,0 +1,1730 @@ +{ + "name": "process-app-form-submission", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "process-app-form-submission", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "@aws-sdk/client-secrets-manager": "^3.682.0", + "@octokit/auth-app": "^7.1.2", + "@octokit/rest": "^21.0.2", + "@sendgrid/mail": "^8.1.4" + } + }, + "node_modules/@aws-crypto/sha256-browser": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-browser/-/sha256-browser-5.2.0.tgz", + "integrity": "sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw==", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/sha256-js": "^5.2.0", + "@aws-crypto/supports-web-crypto": "^5.2.0", + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "@aws-sdk/util-locate-window": "^3.0.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-crypto/sha256-browser/node_modules/@smithy/is-array-buffer": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz", + "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-crypto/sha256-browser/node_modules/@smithy/util-buffer-from": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz", + "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/is-array-buffer": "^2.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-crypto/sha256-browser/node_modules/@smithy/util-utf8": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz", + "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/util-buffer-from": "^2.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-crypto/sha256-js": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-js/-/sha256-js-5.2.0.tgz", + "integrity": "sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA==", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-crypto/supports-web-crypto": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/supports-web-crypto/-/supports-web-crypto-5.2.0.tgz", + "integrity": "sha512-iAvUotm021kM33eCdNfwIN//F77/IADDSs58i+MDaOqFrVjZo9bAal0NK7HurRuWLLpF1iLX7gbWrjHjeo+YFg==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-crypto/util": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/util/-/util-5.2.0.tgz", + "integrity": "sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "^3.222.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-crypto/util/node_modules/@smithy/is-array-buffer": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz", + "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-crypto/util/node_modules/@smithy/util-buffer-from": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz", + "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/is-array-buffer": "^2.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-crypto/util/node_modules/@smithy/util-utf8": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz", + "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/util-buffer-from": "^2.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/client-secrets-manager": { + "version": "3.682.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-secrets-manager/-/client-secrets-manager-3.682.0.tgz", + "integrity": "sha512-HViYeuDVtlZ59LmrzVJmZY8cNBsMNjcDOyNASUSqENkzF5PaL9J7co2Yqpz2pxoEG44i008KwBQzjJNYnYElHw==", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/client-sso-oidc": "3.682.0", + "@aws-sdk/client-sts": "3.682.0", + "@aws-sdk/core": "3.679.0", + "@aws-sdk/credential-provider-node": "3.682.0", + "@aws-sdk/middleware-host-header": "3.679.0", + "@aws-sdk/middleware-logger": "3.679.0", + "@aws-sdk/middleware-recursion-detection": "3.679.0", + "@aws-sdk/middleware-user-agent": "3.682.0", + "@aws-sdk/region-config-resolver": "3.679.0", + "@aws-sdk/types": "3.679.0", + "@aws-sdk/util-endpoints": "3.679.0", + "@aws-sdk/util-user-agent-browser": "3.679.0", + "@aws-sdk/util-user-agent-node": "3.682.0", + "@smithy/config-resolver": "^3.0.9", + "@smithy/core": "^2.4.8", + "@smithy/fetch-http-handler": "^3.2.9", + "@smithy/hash-node": "^3.0.7", + "@smithy/invalid-dependency": "^3.0.7", + "@smithy/middleware-content-length": "^3.0.9", + "@smithy/middleware-endpoint": "^3.1.4", + "@smithy/middleware-retry": "^3.0.23", + "@smithy/middleware-serde": "^3.0.7", + "@smithy/middleware-stack": "^3.0.7", + "@smithy/node-config-provider": "^3.1.8", + "@smithy/node-http-handler": "^3.2.4", + "@smithy/protocol-http": "^4.1.4", + "@smithy/smithy-client": "^3.4.0", + "@smithy/types": "^3.5.0", + "@smithy/url-parser": "^3.0.7", + "@smithy/util-base64": "^3.0.0", + "@smithy/util-body-length-browser": "^3.0.0", + "@smithy/util-body-length-node": "^3.0.0", + "@smithy/util-defaults-mode-browser": "^3.0.23", + "@smithy/util-defaults-mode-node": "^3.0.23", + "@smithy/util-endpoints": "^2.1.3", + "@smithy/util-middleware": "^3.0.7", + "@smithy/util-retry": "^3.0.7", + "@smithy/util-utf8": "^3.0.0", + "@types/uuid": "^9.0.1", + "tslib": "^2.6.2", + "uuid": "^9.0.1" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-sso": { + "version": "3.682.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.682.0.tgz", + "integrity": "sha512-PYH9RFUMYLFl66HSBq4tIx6fHViMLkhJHTYJoJONpBs+Td+NwVJ895AdLtDsBIhMS0YseCbPpuyjUCJgsUrwUw==", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "3.679.0", + "@aws-sdk/middleware-host-header": "3.679.0", + "@aws-sdk/middleware-logger": "3.679.0", + "@aws-sdk/middleware-recursion-detection": "3.679.0", + "@aws-sdk/middleware-user-agent": "3.682.0", + "@aws-sdk/region-config-resolver": "3.679.0", + "@aws-sdk/types": "3.679.0", + "@aws-sdk/util-endpoints": "3.679.0", + "@aws-sdk/util-user-agent-browser": "3.679.0", + "@aws-sdk/util-user-agent-node": "3.682.0", + "@smithy/config-resolver": "^3.0.9", + "@smithy/core": "^2.4.8", + "@smithy/fetch-http-handler": "^3.2.9", + "@smithy/hash-node": "^3.0.7", + "@smithy/invalid-dependency": "^3.0.7", + "@smithy/middleware-content-length": "^3.0.9", + "@smithy/middleware-endpoint": "^3.1.4", + "@smithy/middleware-retry": "^3.0.23", + "@smithy/middleware-serde": "^3.0.7", + "@smithy/middleware-stack": "^3.0.7", + "@smithy/node-config-provider": "^3.1.8", + "@smithy/node-http-handler": "^3.2.4", + "@smithy/protocol-http": "^4.1.4", + "@smithy/smithy-client": "^3.4.0", + "@smithy/types": "^3.5.0", + "@smithy/url-parser": "^3.0.7", + "@smithy/util-base64": "^3.0.0", + "@smithy/util-body-length-browser": "^3.0.0", + "@smithy/util-body-length-node": "^3.0.0", + "@smithy/util-defaults-mode-browser": "^3.0.23", + "@smithy/util-defaults-mode-node": "^3.0.23", + "@smithy/util-endpoints": "^2.1.3", + "@smithy/util-middleware": "^3.0.7", + "@smithy/util-retry": "^3.0.7", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-sso-oidc": { + "version": "3.682.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.682.0.tgz", + "integrity": "sha512-ZPZ7Y/r/w3nx/xpPzGSqSQsB090Xk5aZZOH+WBhTDn/pBEuim09BYXCLzvvxb7R7NnuoQdrTJiwimdJAhHl7ZQ==", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "3.679.0", + "@aws-sdk/credential-provider-node": "3.682.0", + "@aws-sdk/middleware-host-header": "3.679.0", + "@aws-sdk/middleware-logger": "3.679.0", + "@aws-sdk/middleware-recursion-detection": "3.679.0", + "@aws-sdk/middleware-user-agent": "3.682.0", + "@aws-sdk/region-config-resolver": "3.679.0", + "@aws-sdk/types": "3.679.0", + "@aws-sdk/util-endpoints": "3.679.0", + "@aws-sdk/util-user-agent-browser": "3.679.0", + "@aws-sdk/util-user-agent-node": "3.682.0", + "@smithy/config-resolver": "^3.0.9", + "@smithy/core": "^2.4.8", + "@smithy/fetch-http-handler": "^3.2.9", + "@smithy/hash-node": "^3.0.7", + "@smithy/invalid-dependency": "^3.0.7", + "@smithy/middleware-content-length": "^3.0.9", + "@smithy/middleware-endpoint": "^3.1.4", + "@smithy/middleware-retry": "^3.0.23", + "@smithy/middleware-serde": "^3.0.7", + "@smithy/middleware-stack": "^3.0.7", + "@smithy/node-config-provider": "^3.1.8", + "@smithy/node-http-handler": "^3.2.4", + "@smithy/protocol-http": "^4.1.4", + "@smithy/smithy-client": "^3.4.0", + "@smithy/types": "^3.5.0", + "@smithy/url-parser": "^3.0.7", + "@smithy/util-base64": "^3.0.0", + "@smithy/util-body-length-browser": "^3.0.0", + "@smithy/util-body-length-node": "^3.0.0", + "@smithy/util-defaults-mode-browser": "^3.0.23", + "@smithy/util-defaults-mode-node": "^3.0.23", + "@smithy/util-endpoints": "^2.1.3", + "@smithy/util-middleware": "^3.0.7", + "@smithy/util-retry": "^3.0.7", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "@aws-sdk/client-sts": "^3.682.0" + } + }, + "node_modules/@aws-sdk/client-sts": { + "version": "3.682.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.682.0.tgz", + "integrity": "sha512-xKuo4HksZ+F8m9DOfx/ZuWNhaPuqZFPwwy0xqcBT6sWH7OAuBjv/fnpOTzyQhpVTWddlf+ECtMAMrxjxuOExGQ==", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/client-sso-oidc": "3.682.0", + "@aws-sdk/core": "3.679.0", + "@aws-sdk/credential-provider-node": "3.682.0", + "@aws-sdk/middleware-host-header": "3.679.0", + "@aws-sdk/middleware-logger": "3.679.0", + "@aws-sdk/middleware-recursion-detection": "3.679.0", + "@aws-sdk/middleware-user-agent": "3.682.0", + "@aws-sdk/region-config-resolver": "3.679.0", + "@aws-sdk/types": "3.679.0", + "@aws-sdk/util-endpoints": "3.679.0", + "@aws-sdk/util-user-agent-browser": "3.679.0", + "@aws-sdk/util-user-agent-node": "3.682.0", + "@smithy/config-resolver": "^3.0.9", + "@smithy/core": "^2.4.8", + "@smithy/fetch-http-handler": "^3.2.9", + "@smithy/hash-node": "^3.0.7", + "@smithy/invalid-dependency": "^3.0.7", + "@smithy/middleware-content-length": "^3.0.9", + "@smithy/middleware-endpoint": "^3.1.4", + "@smithy/middleware-retry": "^3.0.23", + "@smithy/middleware-serde": "^3.0.7", + "@smithy/middleware-stack": "^3.0.7", + "@smithy/node-config-provider": "^3.1.8", + "@smithy/node-http-handler": "^3.2.4", + "@smithy/protocol-http": "^4.1.4", + "@smithy/smithy-client": "^3.4.0", + "@smithy/types": "^3.5.0", + "@smithy/url-parser": "^3.0.7", + "@smithy/util-base64": "^3.0.0", + "@smithy/util-body-length-browser": "^3.0.0", + "@smithy/util-body-length-node": "^3.0.0", + "@smithy/util-defaults-mode-browser": "^3.0.23", + "@smithy/util-defaults-mode-node": "^3.0.23", + "@smithy/util-endpoints": "^2.1.3", + "@smithy/util-middleware": "^3.0.7", + "@smithy/util-retry": "^3.0.7", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/core": { + "version": "3.679.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.679.0.tgz", + "integrity": "sha512-CS6PWGX8l4v/xyvX8RtXnBisdCa5+URzKd0L6GvHChype9qKUVxO/Gg6N/y43Hvg7MNWJt9FBPNWIxUB+byJwg==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.679.0", + "@smithy/core": "^2.4.8", + "@smithy/node-config-provider": "^3.1.8", + "@smithy/property-provider": "^3.1.7", + "@smithy/protocol-http": "^4.1.4", + "@smithy/signature-v4": "^4.2.0", + "@smithy/smithy-client": "^3.4.0", + "@smithy/types": "^3.5.0", + "@smithy/util-middleware": "^3.0.7", + "fast-xml-parser": "4.4.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-env": { + "version": "3.679.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.679.0.tgz", + "integrity": "sha512-EdlTYbzMm3G7VUNAMxr9S1nC1qUNqhKlAxFU8E7cKsAe8Bp29CD5HAs3POc56AVo9GC4yRIS+/mtlZSmrckzUA==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.679.0", + "@aws-sdk/types": "3.679.0", + "@smithy/property-provider": "^3.1.7", + "@smithy/types": "^3.5.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-http": { + "version": "3.679.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.679.0.tgz", + "integrity": "sha512-ZoKLubW5DqqV1/2a3TSn+9sSKg0T8SsYMt1JeirnuLJF0mCoYFUaWMyvxxKuxPoqvUsaycxKru4GkpJ10ltNBw==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.679.0", + "@aws-sdk/types": "3.679.0", + "@smithy/fetch-http-handler": "^3.2.9", + "@smithy/node-http-handler": "^3.2.4", + "@smithy/property-provider": "^3.1.7", + "@smithy/protocol-http": "^4.1.4", + "@smithy/smithy-client": "^3.4.0", + "@smithy/types": "^3.5.0", + "@smithy/util-stream": "^3.1.9", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-ini": { + "version": "3.682.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.682.0.tgz", + "integrity": "sha512-6eqWeHdK6EegAxqDdiCi215nT3QZPwukgWAYuVxNfJ/5m0/P7fAzF+D5kKVgByUvGJEbq/FEL8Fw7OBe64AA+g==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.679.0", + "@aws-sdk/credential-provider-env": "3.679.0", + "@aws-sdk/credential-provider-http": "3.679.0", + "@aws-sdk/credential-provider-process": "3.679.0", + "@aws-sdk/credential-provider-sso": "3.682.0", + "@aws-sdk/credential-provider-web-identity": "3.679.0", + "@aws-sdk/types": "3.679.0", + "@smithy/credential-provider-imds": "^3.2.4", + "@smithy/property-provider": "^3.1.7", + "@smithy/shared-ini-file-loader": "^3.1.8", + "@smithy/types": "^3.5.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "@aws-sdk/client-sts": "^3.682.0" + } + }, + "node_modules/@aws-sdk/credential-provider-node": { + "version": "3.682.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.682.0.tgz", + "integrity": "sha512-HSmDqZcBVZrTctHCT9m++vdlDfJ1ARI218qmZa+TZzzOFNpKWy6QyHMEra45GB9GnkkMmV6unoDSPMuN0AqcMg==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/credential-provider-env": "3.679.0", + "@aws-sdk/credential-provider-http": "3.679.0", + "@aws-sdk/credential-provider-ini": "3.682.0", + "@aws-sdk/credential-provider-process": "3.679.0", + "@aws-sdk/credential-provider-sso": "3.682.0", + "@aws-sdk/credential-provider-web-identity": "3.679.0", + "@aws-sdk/types": "3.679.0", + "@smithy/credential-provider-imds": "^3.2.4", + "@smithy/property-provider": "^3.1.7", + "@smithy/shared-ini-file-loader": "^3.1.8", + "@smithy/types": "^3.5.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-process": { + "version": "3.679.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.679.0.tgz", + "integrity": "sha512-u/p4TV8kQ0zJWDdZD4+vdQFTMhkDEJFws040Gm113VHa/Xo1SYOjbpvqeuFoz6VmM0bLvoOWjxB9MxnSQbwKpQ==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.679.0", + "@aws-sdk/types": "3.679.0", + "@smithy/property-provider": "^3.1.7", + "@smithy/shared-ini-file-loader": "^3.1.8", + "@smithy/types": "^3.5.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-sso": { + "version": "3.682.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.682.0.tgz", + "integrity": "sha512-h7IH1VsWgV6YAJSWWV6y8uaRjGqLY3iBpGZlXuTH/c236NMLaNv+WqCBLeBxkFGUb2WeQ+FUPEJDCD69rgLIkg==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/client-sso": "3.682.0", + "@aws-sdk/core": "3.679.0", + "@aws-sdk/token-providers": "3.679.0", + "@aws-sdk/types": "3.679.0", + "@smithy/property-provider": "^3.1.7", + "@smithy/shared-ini-file-loader": "^3.1.8", + "@smithy/types": "^3.5.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-web-identity": { + "version": "3.679.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.679.0.tgz", + "integrity": "sha512-a74tLccVznXCaBefWPSysUcLXYJiSkeUmQGtalNgJ1vGkE36W5l/8czFiiowdWdKWz7+x6xf0w+Kjkjlj42Ung==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.679.0", + "@aws-sdk/types": "3.679.0", + "@smithy/property-provider": "^3.1.7", + "@smithy/types": "^3.5.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "@aws-sdk/client-sts": "^3.679.0" + } + }, + "node_modules/@aws-sdk/middleware-host-header": { + "version": "3.679.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.679.0.tgz", + "integrity": "sha512-y176HuQ8JRY3hGX8rQzHDSbCl9P5Ny9l16z4xmaiLo+Qfte7ee4Yr3yaAKd7GFoJ3/Mhud2XZ37fR015MfYl2w==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.679.0", + "@smithy/protocol-http": "^4.1.4", + "@smithy/types": "^3.5.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-logger": { + "version": "3.679.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.679.0.tgz", + "integrity": "sha512-0vet8InEj7nvIvGKk+ch7bEF5SyZ7Us9U7YTEgXPrBNStKeRUsgwRm0ijPWWd0a3oz2okaEwXsFl7G/vI0XiEA==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.679.0", + "@smithy/types": "^3.5.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-recursion-detection": { + "version": "3.679.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.679.0.tgz", + "integrity": "sha512-sQoAZFsQiW/LL3DfKMYwBoGjYDEnMbA9WslWN8xneCmBAwKo6IcSksvYs23PP8XMIoBGe2I2J9BSr654XWygTQ==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.679.0", + "@smithy/protocol-http": "^4.1.4", + "@smithy/types": "^3.5.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-user-agent": { + "version": "3.682.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.682.0.tgz", + "integrity": "sha512-7TyvYR9HdGH1/Nq0eeApUTM4izB6rExiw87khVYuJwZHr6FmvIL1FsOVFro/4WlXa0lg4LiYOm/8H8dHv+fXTg==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.679.0", + "@aws-sdk/types": "3.679.0", + "@aws-sdk/util-endpoints": "3.679.0", + "@smithy/core": "^2.4.8", + "@smithy/protocol-http": "^4.1.4", + "@smithy/types": "^3.5.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/region-config-resolver": { + "version": "3.679.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.679.0.tgz", + "integrity": "sha512-Ybx54P8Tg6KKq5ck7uwdjiKif7n/8g1x+V0V9uTjBjRWqaIgiqzXwKWoPj6NCNkE7tJNtqI4JrNxp/3S3HvmRw==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.679.0", + "@smithy/node-config-provider": "^3.1.8", + "@smithy/types": "^3.5.0", + "@smithy/util-config-provider": "^3.0.0", + "@smithy/util-middleware": "^3.0.7", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/token-providers": { + "version": "3.679.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.679.0.tgz", + "integrity": "sha512-1/+Zso/x2jqgutKixYFQEGli0FELTgah6bm7aB+m2FAWH4Hz7+iMUsazg6nSWm714sG9G3h5u42Dmpvi9X6/hA==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.679.0", + "@smithy/property-provider": "^3.1.7", + "@smithy/shared-ini-file-loader": "^3.1.8", + "@smithy/types": "^3.5.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "@aws-sdk/client-sso-oidc": "^3.679.0" + } + }, + "node_modules/@aws-sdk/types": { + "version": "3.679.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.679.0.tgz", + "integrity": "sha512-NwVq8YvInxQdJ47+zz4fH3BRRLC6lL+WLkvr242PVBbUOLRyK/lkwHlfiKUoeVIMyK5NF+up6TRg71t/8Bny6Q==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^3.5.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/util-endpoints": { + "version": "3.679.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.679.0.tgz", + "integrity": "sha512-YL6s4Y/1zC45OvddvgE139fjeWSKKPgLlnfrvhVL7alNyY9n7beR4uhoDpNrt5mI6sn9qiBF17790o+xLAXjjg==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.679.0", + "@smithy/types": "^3.5.0", + "@smithy/util-endpoints": "^2.1.3", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/util-locate-window": { + "version": "3.679.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.679.0.tgz", + "integrity": "sha512-zKTd48/ZWrCplkXpYDABI74rQlbR0DNHs8nH95htfSLj9/mWRSwaGptoxwcihaq/77vi/fl2X3y0a1Bo8bt7RA==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/util-user-agent-browser": { + "version": "3.679.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.679.0.tgz", + "integrity": "sha512-CusSm2bTBG1kFypcsqU8COhnYc6zltobsqs3nRrvYqYaOqtMnuE46K4XTWpnzKgwDejgZGOE+WYyprtAxrPvmQ==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.679.0", + "@smithy/types": "^3.5.0", + "bowser": "^2.11.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-sdk/util-user-agent-node": { + "version": "3.682.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.682.0.tgz", + "integrity": "sha512-so5s+j0gPoTS0HM4HPL+G0ajk0T6cQAg8JXzRgvyiQAxqie+zGCZAV3VuVeMNWMVbzsgZl0pYZaatPFTLG/AxA==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/middleware-user-agent": "3.682.0", + "@aws-sdk/types": "3.679.0", + "@smithy/node-config-provider": "^3.1.8", + "@smithy/types": "^3.5.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "aws-crt": ">=1.0.0" + }, + "peerDependenciesMeta": { + "aws-crt": { + "optional": true + } + } + }, + "node_modules/@octokit/auth-app": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/@octokit/auth-app/-/auth-app-7.1.2.tgz", + "integrity": "sha512-5cfWRr1hr0w/EW3StFIIOkMtYhOyGZ6/R3T0xeN6UgC/uL5pIyeood9N/8Z7W4NZUdz2QK1Fv0oM/1AzTME3/Q==", + "license": "MIT", + "dependencies": { + "@octokit/auth-oauth-app": "^8.1.0", + "@octokit/auth-oauth-user": "^5.1.0", + "@octokit/request": "^9.1.1", + "@octokit/request-error": "^6.1.1", + "@octokit/types": "^13.4.1", + "lru-cache": "npm:@wolfy1339/lru-cache@^11.0.2-patch.1", + "universal-github-app-jwt": "^2.2.0", + "universal-user-agent": "^7.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/auth-oauth-app": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/@octokit/auth-oauth-app/-/auth-oauth-app-8.1.1.tgz", + "integrity": "sha512-5UtmxXAvU2wfcHIPPDWzVSAWXVJzG3NWsxb7zCFplCWEmMCArSZV0UQu5jw5goLQXbFyOr5onzEH37UJB3zQQg==", + "license": "MIT", + "dependencies": { + "@octokit/auth-oauth-device": "^7.0.0", + "@octokit/auth-oauth-user": "^5.0.1", + "@octokit/request": "^9.0.0", + "@octokit/types": "^13.0.0", + "universal-user-agent": "^7.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/auth-oauth-device": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@octokit/auth-oauth-device/-/auth-oauth-device-7.1.1.tgz", + "integrity": "sha512-HWl8lYueHonuyjrKKIup/1tiy0xcmQCdq5ikvMO1YwkNNkxb6DXfrPjrMYItNLyCP/o2H87WuijuE+SlBTT8eg==", + "license": "MIT", + "dependencies": { + "@octokit/oauth-methods": "^5.0.0", + "@octokit/request": "^9.0.0", + "@octokit/types": "^13.0.0", + "universal-user-agent": "^7.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/auth-oauth-user": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@octokit/auth-oauth-user/-/auth-oauth-user-5.1.1.tgz", + "integrity": "sha512-rRkMz0ErOppdvEfnemHJXgZ9vTPhBuC6yASeFaB7I2yLMd7QpjfrL1mnvRPlyKo+M6eeLxrKanXJ9Qte29SRsw==", + "license": "MIT", + "dependencies": { + "@octokit/auth-oauth-device": "^7.0.1", + "@octokit/oauth-methods": "^5.0.0", + "@octokit/request": "^9.0.1", + "@octokit/types": "^13.0.0", + "universal-user-agent": "^7.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/auth-token": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-5.1.1.tgz", + "integrity": "sha512-rh3G3wDO8J9wSjfI436JUKzHIxq8NaiL0tVeB2aXmG6p/9859aUOAjA9pmSPNGGZxfwmaJ9ozOJImuNVJdpvbA==", + "license": "MIT", + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/core": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-6.1.2.tgz", + "integrity": "sha512-hEb7Ma4cGJGEUNOAVmyfdB/3WirWMg5hDuNFVejGEDFqupeOysLc2sG6HJxY2etBp5YQu5Wtxwi020jS9xlUwg==", + "license": "MIT", + "dependencies": { + "@octokit/auth-token": "^5.0.0", + "@octokit/graphql": "^8.0.0", + "@octokit/request": "^9.0.0", + "@octokit/request-error": "^6.0.1", + "@octokit/types": "^13.0.0", + "before-after-hook": "^3.0.2", + "universal-user-agent": "^7.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/endpoint": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-10.1.1.tgz", + "integrity": "sha512-JYjh5rMOwXMJyUpj028cu0Gbp7qe/ihxfJMLc8VZBMMqSwLgOxDI1911gV4Enl1QSavAQNJcwmwBF9M0VvLh6Q==", + "license": "MIT", + "dependencies": { + "@octokit/types": "^13.0.0", + "universal-user-agent": "^7.0.2" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/graphql": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-8.1.1.tgz", + "integrity": "sha512-ukiRmuHTi6ebQx/HFRCXKbDlOh/7xEV6QUXaE7MJEKGNAncGI/STSbOkl12qVXZrfZdpXctx5O9X1AIaebiDBg==", + "license": "MIT", + "dependencies": { + "@octokit/request": "^9.0.0", + "@octokit/types": "^13.0.0", + "universal-user-agent": "^7.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/oauth-authorization-url": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@octokit/oauth-authorization-url/-/oauth-authorization-url-7.1.1.tgz", + "integrity": "sha512-ooXV8GBSabSWyhLUowlMIVd9l1s2nsOGQdlP2SQ4LnkEsGXzeCvbSbCPdZThXhEFzleGPwbapT0Sb+YhXRyjCA==", + "license": "MIT", + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/oauth-methods": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@octokit/oauth-methods/-/oauth-methods-5.1.2.tgz", + "integrity": "sha512-C5lglRD+sBlbrhCUTxgJAFjWgJlmTx5bQ7Ch0+2uqRjYv7Cfb5xpX4WuSC9UgQna3sqRGBL9EImX9PvTpMaQ7g==", + "license": "MIT", + "dependencies": { + "@octokit/oauth-authorization-url": "^7.0.0", + "@octokit/request": "^9.1.0", + "@octokit/request-error": "^6.1.0", + "@octokit/types": "^13.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/openapi-types": { + "version": "22.2.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-22.2.0.tgz", + "integrity": "sha512-QBhVjcUa9W7Wwhm6DBFu6ZZ+1/t/oYxqc2tp81Pi41YNuJinbFRx8B133qVOrAaBbF7D/m0Et6f9/pZt9Rc+tg==", + "license": "MIT" + }, + "node_modules/@octokit/plugin-paginate-rest": { + "version": "11.3.5", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-11.3.5.tgz", + "integrity": "sha512-cgwIRtKrpwhLoBi0CUNuY83DPGRMaWVjqVI/bGKsLJ4PzyWZNaEmhHroI2xlrVXkk6nFv0IsZpOp+ZWSWUS2AQ==", + "license": "MIT", + "dependencies": { + "@octokit/types": "^13.6.0" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "@octokit/core": ">=6" + } + }, + "node_modules/@octokit/plugin-request-log": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-5.3.1.tgz", + "integrity": "sha512-n/lNeCtq+9ofhC15xzmJCNKP2BWTv8Ih2TTy+jatNCCq/gQP/V7rK3fjIfuz0pDWDALO/o/4QY4hyOF6TQQFUw==", + "license": "MIT", + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "@octokit/core": ">=6" + } + }, + "node_modules/@octokit/plugin-rest-endpoint-methods": { + "version": "13.2.6", + "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-13.2.6.tgz", + "integrity": "sha512-wMsdyHMjSfKjGINkdGKki06VEkgdEldIGstIEyGX0wbYHGByOwN/KiM+hAAlUwAtPkP3gvXtVQA9L3ITdV2tVw==", + "license": "MIT", + "dependencies": { + "@octokit/types": "^13.6.1" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "@octokit/core": ">=6" + } + }, + "node_modules/@octokit/request": { + "version": "9.1.3", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-9.1.3.tgz", + "integrity": "sha512-V+TFhu5fdF3K58rs1pGUJIDH5RZLbZm5BI+MNF+6o/ssFNT4vWlCh/tVpF3NxGtP15HUxTTMUbsG5llAuU2CZA==", + "license": "MIT", + "dependencies": { + "@octokit/endpoint": "^10.0.0", + "@octokit/request-error": "^6.0.1", + "@octokit/types": "^13.1.0", + "universal-user-agent": "^7.0.2" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/request-error": { + "version": "6.1.5", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-6.1.5.tgz", + "integrity": "sha512-IlBTfGX8Yn/oFPMwSfvugfncK2EwRLjzbrpifNaMY8o/HTEAFqCA1FZxjD9cWvSKBHgrIhc4CSBIzMxiLsbzFQ==", + "license": "MIT", + "dependencies": { + "@octokit/types": "^13.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/rest": { + "version": "21.0.2", + "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-21.0.2.tgz", + "integrity": "sha512-+CiLisCoyWmYicH25y1cDfCrv41kRSvTq6pPWtRroRJzhsCZWZyCqGyI8foJT5LmScADSwRAnr/xo+eewL04wQ==", + "license": "MIT", + "dependencies": { + "@octokit/core": "^6.1.2", + "@octokit/plugin-paginate-rest": "^11.0.0", + "@octokit/plugin-request-log": "^5.3.1", + "@octokit/plugin-rest-endpoint-methods": "^13.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/types": { + "version": "13.6.1", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.6.1.tgz", + "integrity": "sha512-PHZE9Z+kWXb23Ndik8MKPirBPziOc0D2/3KH1P+6jK5nGWe96kadZuE4jev2/Jq7FvIfTlT2Ltg8Fv2x1v0a5g==", + "license": "MIT", + "dependencies": { + "@octokit/openapi-types": "^22.2.0" + } + }, + "node_modules/@sendgrid/client": { + "version": "8.1.4", + "resolved": "https://registry.npmjs.org/@sendgrid/client/-/client-8.1.4.tgz", + "integrity": "sha512-VxZoQ82MpxmjSXLR3ZAE2OWxvQIW2k2G24UeRPr/SYX8HqWLV/8UBN15T2WmjjnEb5XSmFImTJOKDzzSeKr9YQ==", + "license": "MIT", + "dependencies": { + "@sendgrid/helpers": "^8.0.0", + "axios": "^1.7.4" + }, + "engines": { + "node": ">=12.*" + } + }, + "node_modules/@sendgrid/helpers": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@sendgrid/helpers/-/helpers-8.0.0.tgz", + "integrity": "sha512-Ze7WuW2Xzy5GT5WRx+yEv89fsg/pgy3T1E3FS0QEx0/VvRmigMZ5qyVGhJz4SxomegDkzXv/i0aFPpHKN8qdAA==", + "license": "MIT", + "dependencies": { + "deepmerge": "^4.2.2" + }, + "engines": { + "node": ">= 12.0.0" + } + }, + "node_modules/@sendgrid/mail": { + "version": "8.1.4", + "resolved": "https://registry.npmjs.org/@sendgrid/mail/-/mail-8.1.4.tgz", + "integrity": "sha512-MUpIZykD9ARie8LElYCqbcBhGGMaA/E6I7fEcG7Hc2An26QJyLtwOaKQ3taGp8xO8BICPJrSKuYV4bDeAJKFGQ==", + "license": "MIT", + "dependencies": { + "@sendgrid/client": "^8.1.4", + "@sendgrid/helpers": "^8.0.0" + }, + "engines": { + "node": ">=12.*" + } + }, + "node_modules/@smithy/abort-controller": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-3.1.6.tgz", + "integrity": "sha512-0XuhuHQlEqbNQZp7QxxrFTdVWdwxch4vjxYgfInF91hZFkPxf9QDrdQka0KfxFMPqLNzSw0b95uGTrLliQUavQ==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^3.6.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/config-resolver": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-3.0.10.tgz", + "integrity": "sha512-Uh0Sz9gdUuz538nvkPiyv1DZRX9+D15EKDtnQP5rYVAzM/dnYk3P8cg73jcxyOitPgT3mE3OVj7ky7sibzHWkw==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/node-config-provider": "^3.1.9", + "@smithy/types": "^3.6.0", + "@smithy/util-config-provider": "^3.0.0", + "@smithy/util-middleware": "^3.0.8", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/core": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@smithy/core/-/core-2.5.1.tgz", + "integrity": "sha512-DujtuDA7BGEKExJ05W5OdxCoyekcKT3Rhg1ZGeiUWaz2BJIWXjZmsG/DIP4W48GHno7AQwRsaCb8NcBgH3QZpg==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/middleware-serde": "^3.0.8", + "@smithy/protocol-http": "^4.1.5", + "@smithy/types": "^3.6.0", + "@smithy/util-body-length-browser": "^3.0.0", + "@smithy/util-middleware": "^3.0.8", + "@smithy/util-stream": "^3.2.1", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/credential-provider-imds": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-3.2.5.tgz", + "integrity": "sha512-4FTQGAsuwqTzVMmiRVTn0RR9GrbRfkP0wfu/tXWVHd2LgNpTY0uglQpIScXK4NaEyXbB3JmZt8gfVqO50lP8wg==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/node-config-provider": "^3.1.9", + "@smithy/property-provider": "^3.1.8", + "@smithy/types": "^3.6.0", + "@smithy/url-parser": "^3.0.8", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/fetch-http-handler": { + "version": "3.2.9", + "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-3.2.9.tgz", + "integrity": "sha512-hYNVQOqhFQ6vOpenifFME546f0GfJn2OiQ3M0FDmuUu8V/Uiwy2wej7ZXxFBNqdx0R5DZAqWM1l6VRhGz8oE6A==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/protocol-http": "^4.1.4", + "@smithy/querystring-builder": "^3.0.7", + "@smithy/types": "^3.5.0", + "@smithy/util-base64": "^3.0.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@smithy/hash-node": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-3.0.8.tgz", + "integrity": "sha512-tlNQYbfpWXHimHqrvgo14DrMAgUBua/cNoz9fMYcDmYej7MAmUcjav/QKQbFc3NrcPxeJ7QClER4tWZmfwoPng==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^3.6.0", + "@smithy/util-buffer-from": "^3.0.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/invalid-dependency": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-3.0.8.tgz", + "integrity": "sha512-7Qynk6NWtTQhnGTTZwks++nJhQ1O54Mzi7fz4PqZOiYXb4Z1Flpb2yRvdALoggTS8xjtohWUM+RygOtB30YL3Q==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^3.6.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@smithy/is-array-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-3.0.0.tgz", + "integrity": "sha512-+Fsu6Q6C4RSJiy81Y8eApjEB5gVtM+oFKTffg+jSuwtvomJJrhUJBu2zS8wjXSgH/g1MKEWrzyChTBe6clb5FQ==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/middleware-content-length": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-3.0.10.tgz", + "integrity": "sha512-T4dIdCs1d/+/qMpwhJ1DzOhxCZjZHbHazEPJWdB4GDi2HjIZllVzeBEcdJUN0fomV8DURsgOyrbEUzg3vzTaOg==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/protocol-http": "^4.1.5", + "@smithy/types": "^3.6.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/middleware-endpoint": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-3.2.1.tgz", + "integrity": "sha512-wWO3xYmFm6WRW8VsEJ5oU6h7aosFXfszlz3Dj176pTij6o21oZnzkCLzShfmRaaCHDkBXWBdO0c4sQAvLFP6zA==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/core": "^2.5.1", + "@smithy/middleware-serde": "^3.0.8", + "@smithy/node-config-provider": "^3.1.9", + "@smithy/shared-ini-file-loader": "^3.1.9", + "@smithy/types": "^3.6.0", + "@smithy/url-parser": "^3.0.8", + "@smithy/util-middleware": "^3.0.8", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/middleware-retry": { + "version": "3.0.25", + "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-3.0.25.tgz", + "integrity": "sha512-m1F70cPaMBML4HiTgCw5I+jFNtjgz5z5UdGnUbG37vw6kh4UvizFYjqJGHvicfgKMkDL6mXwyPp5mhZg02g5sg==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/node-config-provider": "^3.1.9", + "@smithy/protocol-http": "^4.1.5", + "@smithy/service-error-classification": "^3.0.8", + "@smithy/smithy-client": "^3.4.2", + "@smithy/types": "^3.6.0", + "@smithy/util-middleware": "^3.0.8", + "@smithy/util-retry": "^3.0.8", + "tslib": "^2.6.2", + "uuid": "^9.0.1" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/middleware-serde": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-3.0.8.tgz", + "integrity": "sha512-Xg2jK9Wc/1g/MBMP/EUn2DLspN8LNt+GMe7cgF+Ty3vl+Zvu+VeZU5nmhveU+H8pxyTsjrAkci8NqY6OuvZnjA==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^3.6.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/middleware-stack": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-3.0.8.tgz", + "integrity": "sha512-d7ZuwvYgp1+3682Nx0MD3D/HtkmZd49N3JUndYWQXfRZrYEnCWYc8BHcNmVsPAp9gKvlurdg/mubE6b/rPS9MA==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^3.6.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/node-config-provider": { + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-3.1.9.tgz", + "integrity": "sha512-qRHoah49QJ71eemjuS/WhUXB+mpNtwHRWQr77J/m40ewBVVwvo52kYAmb7iuaECgGTTcYxHS4Wmewfwy++ueew==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/property-provider": "^3.1.8", + "@smithy/shared-ini-file-loader": "^3.1.9", + "@smithy/types": "^3.6.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/node-http-handler": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-3.2.5.tgz", + "integrity": "sha512-PkOwPNeKdvX/jCpn0A8n9/TyoxjGZB8WVoJmm9YzsnAgggTj4CrjpRHlTQw7dlLZ320n1mY1y+nTRUDViKi/3w==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/abort-controller": "^3.1.6", + "@smithy/protocol-http": "^4.1.5", + "@smithy/querystring-builder": "^3.0.8", + "@smithy/types": "^3.6.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/property-provider": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-3.1.8.tgz", + "integrity": "sha512-ukNUyo6rHmusG64lmkjFeXemwYuKge1BJ8CtpVKmrxQxc6rhUX0vebcptFA9MmrGsnLhwnnqeH83VTU9hwOpjA==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^3.6.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/protocol-http": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-4.1.5.tgz", + "integrity": "sha512-hsjtwpIemmCkm3ZV5fd/T0bPIugW1gJXwZ/hpuVubt2hEUApIoUTrf6qIdh9MAWlw0vjMrA1ztJLAwtNaZogvg==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^3.6.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/querystring-builder": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-3.0.8.tgz", + "integrity": "sha512-btYxGVqFUARbUrN6VhL9c3dnSviIwBYD9Rz1jHuN1hgh28Fpv2xjU1HeCeDJX68xctz7r4l1PBnFhGg1WBBPuA==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^3.6.0", + "@smithy/util-uri-escape": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/querystring-parser": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-3.0.8.tgz", + "integrity": "sha512-BtEk3FG7Ks64GAbt+JnKqwuobJNX8VmFLBsKIwWr1D60T426fGrV2L3YS5siOcUhhp6/Y6yhBw1PSPxA5p7qGg==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^3.6.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/service-error-classification": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-3.0.8.tgz", + "integrity": "sha512-uEC/kCCFto83bz5ZzapcrgGqHOh/0r69sZ2ZuHlgoD5kYgXJEThCoTuw/y1Ub3cE7aaKdznb+jD9xRPIfIwD7g==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^3.6.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/shared-ini-file-loader": { + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-3.1.9.tgz", + "integrity": "sha512-/+OsJRNtoRbtsX0UpSgWVxFZLsJHo/4sTr+kBg/J78sr7iC+tHeOvOJrS5hCpVQ6sWBbhWLp1UNiuMyZhE6pmA==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^3.6.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/signature-v4": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-4.2.1.tgz", + "integrity": "sha512-NsV1jF4EvmO5wqmaSzlnTVetemBS3FZHdyc5CExbDljcyJCEEkJr8ANu2JvtNbVg/9MvKAWV44kTrGS+Pi4INg==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/is-array-buffer": "^3.0.0", + "@smithy/protocol-http": "^4.1.5", + "@smithy/types": "^3.6.0", + "@smithy/util-hex-encoding": "^3.0.0", + "@smithy/util-middleware": "^3.0.8", + "@smithy/util-uri-escape": "^3.0.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/smithy-client": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-3.4.2.tgz", + "integrity": "sha512-dxw1BDxJiY9/zI3cBqfVrInij6ShjpV4fmGHesGZZUiP9OSE/EVfdwdRz0PgvkEvrZHpsj2htRaHJfftE8giBA==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/core": "^2.5.1", + "@smithy/middleware-endpoint": "^3.2.1", + "@smithy/middleware-stack": "^3.0.8", + "@smithy/protocol-http": "^4.1.5", + "@smithy/types": "^3.6.0", + "@smithy/util-stream": "^3.2.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/types": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.6.0.tgz", + "integrity": "sha512-8VXK/KzOHefoC65yRgCn5vG1cysPJjHnOVt9d0ybFQSmJgQj152vMn4EkYhGuaOmnnZvCPav/KnYyE6/KsNZ2w==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/url-parser": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-3.0.8.tgz", + "integrity": "sha512-4FdOhwpTW7jtSFWm7SpfLGKIBC9ZaTKG5nBF0wK24aoQKQyDIKUw3+KFWCQ9maMzrgTJIuOvOnsV2lLGW5XjTg==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/querystring-parser": "^3.0.8", + "@smithy/types": "^3.6.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@smithy/util-base64": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-3.0.0.tgz", + "integrity": "sha512-Kxvoh5Qtt0CDsfajiZOCpJxgtPHXOKwmM+Zy4waD43UoEMA+qPxxa98aE/7ZhdnBFZFXMOiBR5xbcaMhLtznQQ==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/util-buffer-from": "^3.0.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/util-body-length-browser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-body-length-browser/-/util-body-length-browser-3.0.0.tgz", + "integrity": "sha512-cbjJs2A1mLYmqmyVl80uoLTJhAcfzMOyPgjwAYusWKMdLeNtzmMz9YxNl3/jRLoxSS3wkqkf0jwNdtXWtyEBaQ==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + } + }, + "node_modules/@smithy/util-body-length-node": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-body-length-node/-/util-body-length-node-3.0.0.tgz", + "integrity": "sha512-Tj7pZ4bUloNUP6PzwhN7K386tmSmEET9QtQg0TgdNOnxhZvCssHji+oZTUIuzxECRfG8rdm2PMw2WCFs6eIYkA==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/util-buffer-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-3.0.0.tgz", + "integrity": "sha512-aEOHCgq5RWFbP+UDPvPot26EJHjOC+bRgse5A8V3FSShqd5E5UN4qc7zkwsvJPPAVsf73QwYcHN1/gt/rtLwQA==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/is-array-buffer": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/util-config-provider": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-config-provider/-/util-config-provider-3.0.0.tgz", + "integrity": "sha512-pbjk4s0fwq3Di/ANL+rCvJMKM5bzAQdE5S/6RL5NXgMExFAi6UgQMPOm5yPaIWPpr+EOXKXRonJ3FoxKf4mCJQ==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/util-defaults-mode-browser": { + "version": "3.0.25", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-3.0.25.tgz", + "integrity": "sha512-fRw7zymjIDt6XxIsLwfJfYUfbGoO9CmCJk6rjJ/X5cd20+d2Is7xjU5Kt/AiDt6hX8DAf5dztmfP5O82gR9emA==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/property-provider": "^3.1.8", + "@smithy/smithy-client": "^3.4.2", + "@smithy/types": "^3.6.0", + "bowser": "^2.11.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@smithy/util-defaults-mode-node": { + "version": "3.0.25", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-3.0.25.tgz", + "integrity": "sha512-H3BSZdBDiVZGzt8TG51Pd2FvFO0PAx/A0mJ0EH8a13KJ6iUCdYnw/Dk/MdC1kTd0eUuUGisDFaxXVXo4HHFL1g==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/config-resolver": "^3.0.10", + "@smithy/credential-provider-imds": "^3.2.5", + "@smithy/node-config-provider": "^3.1.9", + "@smithy/property-provider": "^3.1.8", + "@smithy/smithy-client": "^3.4.2", + "@smithy/types": "^3.6.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@smithy/util-endpoints": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-2.1.4.tgz", + "integrity": "sha512-kPt8j4emm7rdMWQyL0F89o92q10gvCUa6sBkBtDJ7nV2+P7wpXczzOfoDJ49CKXe5CCqb8dc1W+ZdLlrKzSAnQ==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/node-config-provider": "^3.1.9", + "@smithy/types": "^3.6.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/util-hex-encoding": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-3.0.0.tgz", + "integrity": "sha512-eFndh1WEK5YMUYvy3lPlVmYY/fZcQE1D8oSf41Id2vCeIkKJXPcYDCZD+4+xViI6b1XSd7tE+s5AmXzz5ilabQ==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/util-middleware": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-3.0.8.tgz", + "integrity": "sha512-p7iYAPaQjoeM+AKABpYWeDdtwQNxasr4aXQEA/OmbOaug9V0odRVDy3Wx4ci8soljE/JXQo+abV0qZpW8NX0yA==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^3.6.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/util-retry": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-3.0.8.tgz", + "integrity": "sha512-TCEhLnY581YJ+g1x0hapPz13JFqzmh/pMWL2KEFASC51qCfw3+Y47MrTmea4bUE5vsdxQ4F6/KFbUeSz22Q1ow==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/service-error-classification": "^3.0.8", + "@smithy/types": "^3.6.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/util-stream": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-3.2.1.tgz", + "integrity": "sha512-R3ufuzJRxSJbE58K9AEnL/uSZyVdHzud9wLS8tIbXclxKzoe09CRohj2xV8wpx5tj7ZbiJaKYcutMm1eYgz/0A==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/fetch-http-handler": "^4.0.0", + "@smithy/node-http-handler": "^3.2.5", + "@smithy/types": "^3.6.0", + "@smithy/util-base64": "^3.0.0", + "@smithy/util-buffer-from": "^3.0.0", + "@smithy/util-hex-encoding": "^3.0.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/util-stream/node_modules/@smithy/fetch-http-handler": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-4.0.0.tgz", + "integrity": "sha512-MLb1f5tbBO2X6K4lMEKJvxeLooyg7guq48C2zKr4qM7F2Gpkz4dc+hdSgu77pCJ76jVqFBjZczHYAs6dp15N+g==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/protocol-http": "^4.1.5", + "@smithy/querystring-builder": "^3.0.8", + "@smithy/types": "^3.6.0", + "@smithy/util-base64": "^3.0.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@smithy/util-uri-escape": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-3.0.0.tgz", + "integrity": "sha512-LqR7qYLgZTD7nWLBecUi4aqolw8Mhza9ArpNEQ881MJJIU2sE5iHCK6TdyqqzcDLy0OPe10IY4T8ctVdtynubg==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/util-utf8": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-3.0.0.tgz", + "integrity": "sha512-rUeT12bxFnplYDe815GXbq/oixEGHfRFFtcTF3YdDi/JaENIM6aSYYLJydG83UNzLXeRI5K8abYd/8Sp/QM0kA==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/util-buffer-from": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@types/uuid": { + "version": "9.0.8", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.8.tgz", + "integrity": "sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==", + "license": "MIT" + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, + "node_modules/axios": { + "version": "1.7.7", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz", + "integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/before-after-hook": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-3.0.2.tgz", + "integrity": "sha512-Nik3Sc0ncrMK4UUdXQmAnRtzmNQTAAXmXIopizwZ1W1t8QmfJj+zL4OA2I7XPTPW5z5TDqv4hRo/JzouDJnX3A==", + "license": "Apache-2.0" + }, + "node_modules/bowser": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.11.0.tgz", + "integrity": "sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA==", + "license": "MIT" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/fast-xml-parser": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.4.1.tgz", + "integrity": "sha512-xkjOecfnKGkSsOwtZ5Pz7Us/T6mrbPQrq0nh+aCO5V9nk5NLWmasAHumTKjiPJPWANe+kAZ84Jc8ooJkzZ88Sw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + }, + { + "type": "paypal", + "url": "https://paypal.me/naturalintelligence" + } + ], + "license": "MIT", + "dependencies": { + "strnum": "^1.0.5" + }, + "bin": { + "fxparser": "src/cli/cli.js" + } + }, + "node_modules/follow-redirects": { + "version": "1.15.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", + "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/form-data": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz", + "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/lru-cache": { + "name": "@wolfy1339/lru-cache", + "version": "11.0.2-patch.1", + "resolved": "https://registry.npmjs.org/@wolfy1339/lru-cache/-/lru-cache-11.0.2-patch.1.tgz", + "integrity": "sha512-BgYZfL2ADCXKOw2wJtkM3slhHotawWkgIRRxq4wEybnZQPjvAp71SPX35xepMykTw8gXlzWcWPTY31hlbnRsDA==", + "license": "ISC", + "engines": { + "node": "18 >=18.20 || 20 || >=22" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "license": "MIT" + }, + "node_modules/strnum": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz", + "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==", + "license": "MIT" + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/universal-github-app-jwt": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/universal-github-app-jwt/-/universal-github-app-jwt-2.2.0.tgz", + "integrity": "sha512-G5o6f95b5BggDGuUfKDApKaCgNYy2x7OdHY0zSMF081O0EJobw+1130VONhrA7ezGSV2FNOGyM+KQpQZAr9bIQ==", + "license": "MIT" + }, + "node_modules/universal-user-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-7.0.2.tgz", + "integrity": "sha512-0JCqzSKnStlRRQfCdowvqy3cy0Dvtlb8xecj/H8JFZuCze4rwjPZQOgvFvn0Ws/usCHQFGpyr+pB9adaGwXn4Q==", + "license": "ISC" + }, + "node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + } + } +} diff --git a/aws-lambdas/package.json b/aws-lambdas/package.json new file mode 100644 index 00000000..377ea4a8 --- /dev/null +++ b/aws-lambdas/package.json @@ -0,0 +1,18 @@ +{ + "name": "process-app-form-submission", + "version": "1.0.0", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "", + "license": "ISC", + "description": "", + "type": "module", + "dependencies": { + "@aws-sdk/client-secrets-manager": "^3.682.0", + "@octokit/auth-app": "^7.1.2", + "@octokit/rest": "^21.0.2", + "@sendgrid/mail": "^8.1.4" + } +} diff --git a/aws-lambdas/utils/config-manager.js b/aws-lambdas/utils/config-manager.js new file mode 100644 index 00000000..e93985bb --- /dev/null +++ b/aws-lambdas/utils/config-manager.js @@ -0,0 +1,89 @@ +import { SecretsManagerClient, GetSecretValueCommand } from "@aws-sdk/client-secrets-manager"; +import { FileType } from "../models/file-type.js"; + +export default class ConfigManager { + constructor() { + this.config = null; + } + + async loadConfig(fileType) { + if (this.config) return this.config; + + const baseConfigKeys = ["githubAppId", "githubAppInstallationId", "githubAppPkBase64", "githubOwner", "githubRepo", "githubBaseBranch", "recaptchaV2VerifyUrl", "recaptchaV2SecretKey"]; + const appSpecificKeys = ["sendgridApiKey", "senderEmail", "recipientEmail"]; + + let requiredKeys; + switch (fileType) { + case FileType.Application: + requiredKeys = [...baseConfigKeys, ...appSpecificKeys]; + break; + case FileType.Game: + requiredKeys = [...baseConfigKeys]; + break; + default: + throw new Error(`There is no configuration for the File Type: ${fileType}`); + } + + await this.loadBaseConfig(requiredKeys); + return this.config; + } + + async loadBaseConfig(requiredKeys) { + this.config = {}; + const missingEnvVars = []; + + requiredKeys.forEach((key) => { + const envVarName = toUpperSnakeCase(key); + const envValue = process.env[envVarName]; + if (envValue) { + this.config[key] = envValue; + } else { + missingEnvVars.push(key); + } + }); + + await this.loadSecrets(missingEnvVars); + } + + async loadSecrets(missingKeys) { + const keysRequiringSecrets = ["sendgridApiKey", "recaptchaV2SecretKey", "githubAppPkBase64"]; + const secretsToFetch = missingKeys.filter(key => keysRequiringSecrets.includes(key)); + + if (secretsToFetch.length === 0) return; + + const secrets = await this.getSecrets(); + const missingSecrets = []; + + secretsToFetch.forEach((key) => { + const secretKey = toUpperSnakeCase(key); + if (secrets[secretKey]) { + this.config[key] = secrets[secretKey]; + } else { + missingSecrets.push(secretKey); + } + }); + + if (missingSecrets.length > 0) { + throw new Error(`Missing required environment variables or secrets: ${missingSecrets.join(", ")}`); + } + } + + async getSecrets() { + if (!process.env['SECRET_NAME'] || !process.env['AWS_SECRET_REGION']) { + throw new Error("Environment variables SECRET_NAME and AWS_SECRET_REGION must be configured."); + } + + const client = new SecretsManagerClient({ region: process.env['AWS_SECRET_REGION'] }); + + const response = await client.send(new GetSecretValueCommand({ + SecretId: process.env['SECRET_NAME'], + VersionStage: "AWSCURRENT", + })); + + return JSON.parse(response.SecretString); + } +} + +function toUpperSnakeCase(str) { + return str.replace(/([a-z0-9])([A-Z])/g, '$1_$2').toUpperCase(); +} diff --git a/aws-lambdas/utils/email-manager.js b/aws-lambdas/utils/email-manager.js new file mode 100644 index 00000000..8546983c --- /dev/null +++ b/aws-lambdas/utils/email-manager.js @@ -0,0 +1,75 @@ +import sgMail from '@sendgrid/mail'; + +export default class EmailManager { + recipientEmail; + senderEmail; + sendgridApiKey; + + constructor(sendgridApiKey, senderEmail, recipientEmail) { + this.sendgridApiKey = sendgridApiKey; + this.senderEmail = senderEmail; + this.recipientEmail = recipientEmail; + this.validateConfigValues(); + this.initializeSendGrid(); + } + + validateConfigValues(){ + const missingOrInvalidValues = []; + + if (!this.sendgridApiKey || typeof this.sendgridApiKey !== 'string') { + missingOrInvalidValues.push("SendGrid API key"); + } + if (!this.senderEmail || typeof this.senderEmail !== 'string') { + missingOrInvalidValues.push("Sender email"); + } + if (!this.recipientEmail || typeof this.recipientEmail !== 'string') { + missingOrInvalidValues.push("Recipient email"); + } + + if (missingOrInvalidValues.length) { + throw new Error(`Missing or invalid config values for the EmailManager: ${missingOrInvalidValues.join(", ")}`); + } + } + + initializeSendGrid() { + sgMail.setApiKey(this.sendgridApiKey); + } + + + async sendEmail(subject, emailContent){ + await sgMail.send({ + to: this.recipientEmail, + from: this.senderEmail, + subject, + html: emailContent, + }); + } + + generateAppTestEmailContent(appName, publisher) { + return ` + + + + + + +
    +

    New App Test Request

    +

    We have received a request to test the following application:

    +

    App Name: ${appName}

    +

    Publisher: ${publisher || '-'}

    +

    Please proceed with the testing process at your earliest convenience.

    + +
    + + + `; + } +} diff --git a/aws-lambdas/utils/octokit-manager.js b/aws-lambdas/utils/octokit-manager.js new file mode 100644 index 00000000..b42c3118 --- /dev/null +++ b/aws-lambdas/utils/octokit-manager.js @@ -0,0 +1,131 @@ +import { Octokit } from "@octokit/rest"; +import { createAppAuth } from "@octokit/auth-app"; + +export default class OctokitManager { + constructor(params) { + this.owner = params.owner; + this.repo = params.repo; + + // PAT token authentication + if (params.accessToken) { + this.accessToken = params.accessToken; + + this.octokit = new Octokit({ + auth: this.accessToken + }); + } + + // GitHub App Authentication + if (params.appId && params.installationId && params.privateKey) { + this.appId = params.appId; + this.installationId = params.installationId; + this.privateKey = params.privateKey; + + this.octokit = new Octokit({ + authStrategy: createAppAuth, + auth: { + appId: this.appId, + installationId: this.installationId, + privateKey: this.privateKey + } + }); + } + } + + async createBranch(newBranch, sha) { + const { data } = await this.octokit.rest.git.createRef({ + owner: this.owner, + repo: this.repo, + ref: newBranch, + sha: sha, + headers: { + 'X-GitHub-Api-Version': '2022-11-28' + } + }); + + return data; + } + + async createTree(sha, message, path, content) { + const FILE_MODE_REGULAR = "100644"; + + const { data } = await this.octokit.git.createTree({ + owner: this.owner, + repo: this.repo, + tree: [ + { + path: path, + mode: FILE_MODE_REGULAR, + type: "commit", + content: content + } + ], + base_tree: sha, + message: message, + headers: { + 'X-GitHub-Api-Version': '2022-11-28' + } + }); + return data; + } + + + async getLastCommit(branch) { + const { data } = await this.octokit.rest.repos.getCommit({ + owner: this.owner, + repo: this.repo, + ref: branch, + headers: { + 'X-GitHub-Api-Version': '2022-11-28' + } + }); + + return data; + } + + async createCommit(sha, message, latestCommitSha, author) { + const { data } = await this.octokit.git.createCommit({ + owner: this.owner, + repo: this.repo, + tree: sha, + message: message, + parents: [latestCommitSha], + author: author, + headers: { + 'X-GitHub-Api-Version': '2022-11-28' + } + }); + + return data; + } + + async updateRef(ref, sha, force = true) { + const { data } = await this.octokit.git.updateRef({ + owner: this.owner, + repo: this.repo, + ref: ref, + sha: sha, + force: force, + headers: { + 'X-GitHub-Api-Version': '2022-11-28' + } + }); + + return data; + } + + async createPullRequest(title, body, head, base) { + const { data } = await this.octokit.pulls.create({ + owner: this.owner, + repo: this.repo, + title: title, + body: body, + head: head, + base: base, + headers: { + 'X-GitHub-Api-Version': '2022-11-28' + } + }); + return data; + } +} diff --git a/aws-lambdas/utils/pull-request-data-generator.js b/aws-lambdas/utils/pull-request-data-generator.js new file mode 100644 index 00000000..5a95bea3 --- /dev/null +++ b/aws-lambdas/utils/pull-request-data-generator.js @@ -0,0 +1,75 @@ +import { FileType } from "../models/file-type.js"; +import { pullRequestTemplateData } from "../models/pull-request-template-data.js"; + +export default class PullRequestDataGenerator { + constructor(params) { + this.templateData = params.templateData; + } + + getPullRequestData(params, fileType) { + const formattedData = {}; + + const appFormData = params.formData; + const gameFormData = params.formData; + const name = params.formData.name; + const publisher = params.formData.publisher; + const nameAlphanumeric = name.replace(/[^a-zA-Z0-9\s]/g,''); + const nameUnderscore = nameAlphanumeric.trim().replace(/\s/g, '_'); + const nameHyphen = nameAlphanumeric.trim().replace(/\s/g, '-'); + const type = fileType.toLowerCase(); + + formattedData.commitMessage = this.templateData.commitMessageTemplate(name); + formattedData.fileContent = fileType === FileType.Application + ? this.getFileContentForApps(appFormData) + : this.getFileContentForGames(gameFormData); + formattedData.filePath = fileType === FileType.Application + ? this.templateData.applicationFilePathTemplate(nameUnderscore) + : this.templateData.gameFilePathTemplate(nameUnderscore) + formattedData.headBaseBranchName = this.templateData.headBaseBranchTemplate(params.baseBranchName); + formattedData.newBranchName = this.templateData.newBranchNameTemplate(nameHyphen, type, params.randomNumber); + formattedData.newBranchRefName = this.templateData.newBranchRefNameTemplate(formattedData.newBranchName); + formattedData.pullRequestBody = this.templateData.pullRequestBodyTemplate(name, type, publisher); + formattedData.pullRequestTitle = this.templateData.pullRequestTitleTemplate(name, type); + + return formattedData; + } + + getFileContentForApps(appData) { + const noInfo = "N/A"; + + return this.templateData.applicationFileContentTemplate( + appData.name, + appData.appCategories ?? noInfo, + appData.executionCompatibility ?? noInfo, + appData.displayedArmCompatibility ?? noInfo, + appData.compatibleVersionNumber ?? noInfo, + appData.urlForDownload ?? noInfo, + appData.iconUrl ?? noInfo + ); + } + + getFileContentForGames(gameData) { + const noInfo = "N/A"; + + const subTemplate = (gameData.autoSuperResCompatibility || gameData.autoSuperResFPSboost) + ? this.templateData.gameFileSubContentTemplate( + gameData.autoSuperResCompatibility ?? noInfo, + gameData.autoSuperResFPSboost ?? noInfo + ) : ""; + + return this.templateData.gameFileContentTemplate( + gameData.name, + gameData.categories ?? noInfo, + gameData.publisher ?? noInfo, + gameData.compatibility ?? noInfo, + gameData.compatibilityDetails ?? noInfo, + gameData.deviceConfiguration ?? noInfo, + gameData.dateTasted ?? noInfo, + gameData.osVersion ?? noInfo, + gameData.driverId ?? noInfo, + subTemplate + ); + } +} + +export const pullRequestDataGenerator = new PullRequestDataGenerator({ templateData: pullRequestTemplateData }); diff --git a/aws-lambdas/utils/pull-request-manager.js b/aws-lambdas/utils/pull-request-manager.js new file mode 100644 index 00000000..c2be8388 --- /dev/null +++ b/aws-lambdas/utils/pull-request-manager.js @@ -0,0 +1,48 @@ +import OctokitManager from './octokit-manager.js'; +import { pullRequestDataGenerator } from "./pull-request-data-generator.js"; + +export default class PullRequestManager { + constructor() { } + + async createPullRequest (formData, gitHubRepositoryConfig, fileType) { + const octokitManager = new OctokitManager({ + owner: gitHubRepositoryConfig.githubOwner, + repo: gitHubRepositoryConfig.githubRepo, + appId: gitHubRepositoryConfig.githubAppId, + installationId: gitHubRepositoryConfig.githubAppInstallationId, + privateKey: Buffer.from(gitHubRepositoryConfig.githubAppPkBase64 , 'base64').toString('ascii') + }); + + const rndInt = this.randomIntFromInterval(1009, 10007); + + const pullRequestData = pullRequestDataGenerator.getPullRequestData({ + formData: formData, + baseBranchName: gitHubRepositoryConfig.githubBaseBranch, + randomNumber: rndInt + }, fileType); + + const author = { + name: "Works on WOA Bot", + email: "works.on.woa@noreply.com", + }; + + const getLastCommitResult = await octokitManager.getLastCommit(pullRequestData.headBaseBranchName); + const latestCommitSha = getLastCommitResult.sha; + const latestTreeSha = getLastCommitResult.commit.tree.sha; + + const createTreeResponse = await octokitManager.createTree(latestTreeSha, pullRequestData.commitMessage, pullRequestData.filePath, pullRequestData.fileContent); + const newTreeSha = createTreeResponse.sha; + + const createCommitResponse = await octokitManager.createCommit(newTreeSha, pullRequestData.commitMessage, latestCommitSha, author); + const newCommitSha = createCommitResponse.sha; + + await octokitManager.createBranch(pullRequestData.newBranchRefName, newCommitSha); + + await octokitManager.createPullRequest(pullRequestData.pullRequestTitle, pullRequestData.pullRequestBody, pullRequestData.newBranchName, gitHubRepositoryConfig.githubBaseBranch); + }; + + // min and max included + randomIntFromInterval(min, max) { + return Math.floor(Math.random() * (max - min + 1) + min); + } +} diff --git a/aws-lambdas/utils/recaptcha-validator.js b/aws-lambdas/utils/recaptcha-validator.js new file mode 100644 index 00000000..ac9a0aa6 --- /dev/null +++ b/aws-lambdas/utils/recaptcha-validator.js @@ -0,0 +1,20 @@ +export async function validateReCaptchaV2(host, secret, token) { + const url = new URL(host); + const params = { + secret: secret, + response: token + }; + + Object.entries(params).forEach(([k, v]) => url.searchParams.append(k, v)); + + const response = await fetch(url, { + method: "POST", + body: "", + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + } + }); + + const body = await response.json(); + return body.success ? "" : body["error-codes"].join(","); +} diff --git a/aws-lambdas/utils/request-validator.js b/aws-lambdas/utils/request-validator.js new file mode 100644 index 00000000..aeac6373 --- /dev/null +++ b/aws-lambdas/utils/request-validator.js @@ -0,0 +1,51 @@ +import { validateReCaptchaV2 } from "./recaptcha-validator.js"; +import { FileType } from "../models/file-type.js"; + +export default class RequestValidator { + static validateReferer(headers, allowedReferer) { + if (!allowedReferer) return ""; + + const referer = (headers['referer'] || headers['Referer'] || "").trim().toLowerCase(); + allowedReferer = allowedReferer.trim().toLowerCase(); + + return referer === allowedReferer ? "" : "Access forbidden: Invalid referer"; + } + + static async validateRequest(data, fileType, recaptchaV2VerifyUrl, recaptchaV2SecretKey) { + let error = this.validateFormData(data, fileType); + + if (error === "") { + error = await validateReCaptchaV2(recaptchaV2VerifyUrl, recaptchaV2SecretKey, data.token ?? ""); + } + + return error; + } + + static validateFormData(data, fileType) { + const missingFields = []; + + if (!data.name || data.name.trim() === "") { + missingFields.push("name"); + } + + if (fileType === FileType.Game) { + if (!data.categories) { + missingFields.push("categories"); + } + if (!data.compatibility) { + missingFields.push("compatibility"); + } + if (!data.dateTasted) { + missingFields.push("dateTasted"); + } + } else if (fileType !== FileType.Application) { + return `Invalid file type: ${fileType}`; + } + + if (missingFields.length > 0) { + return `Missing required fields: ${missingFields.join(", ")}`; + } + + return ""; + } +} From 5eed1ebe847227aed43271cf8511fd94b12662b9 Mon Sep 17 00:00:00 2001 From: Gaspar Acevedo Zain <43762887+gasper-az@users.noreply.github.com> Date: Mon, 2 Dec 2024 11:44:52 -0300 Subject: [PATCH 05/11] [feat] Modify contribution page to include web form for PR creation --- src/lib/applications.js | 109 +++++++++++++++++++++++++++++++++++ src/lib/common.js | 79 +++++++++++++++++++++++++ src/lib/games.js | 84 +++++++++++++++++++++++++++ src/pages/en/contributing.md | 18 +++--- src/pages/ja/contributing.md | 20 +++---- src/pages/ko/contributing.md | 22 +++---- src/pages/zh/contributing.md | 22 +++---- src/styles/global.css | 44 ++++++++++++++ 8 files changed, 347 insertions(+), 51 deletions(-) create mode 100644 src/lib/applications.js create mode 100644 src/lib/common.js create mode 100644 src/lib/games.js diff --git a/src/lib/applications.js b/src/lib/applications.js new file mode 100644 index 00000000..c61f892c --- /dev/null +++ b/src/lib/applications.js @@ -0,0 +1,109 @@ +import { ApiURLs, ErrorMessages, pageLoading, populateMultiSelect, showSuccessAlert, showErrorAlert } from './common'; + +const successAlertId = "success_alert"; +const errorAlertId = "error_alert"; +const errorAlertInnerElementId = "error_alert_info"; +const multiCategoriesElementId = "multi_categories"; +const categoriesUrl = `${ApiURLs.REPO_CONTENT}${ApiURLs.APPLICATIONS_CATEGORIES}`; + +//######################################## multi select ########################################// + +const multiCategoriesId = "multi_categories"; +const multiSelect = document.getElementById(multiCategoriesId); +multiSelect.addEventListener('change', (e) => { + let selectedOptions = []; + for (let options of multiSelect.selectedOptions) { + selectedOptions.push(options.value); + } + + document.getElementById('categories').value = selectedOptions.join(', '); +}); + +//######################################## Change form fields based on report type ########################################// + +const reportRadios = document.querySelectorAll('input[name="report"]'); +reportRadios.forEach((radio) => { + radio.addEventListener('click', (val) => { + let srcElem = val.srcElement; + + let reportInfoItems = document.querySelectorAll(".reportInfo"); + let display = srcElem.value === "submitNewOrUpdatedAppInfo" ? "block" : "none"; + + reportInfoItems.forEach((riItem) => { + riItem.style.display = display; + }) + }); +}); + +//######################################## Form submission ########################################// + +const form = document.getElementById("appForm"); +const formLocale = form.dataset.locale +form.addEventListener("submit", (e) => { + e.preventDefault(); + pageLoading(true); + + var captchaVerificationToken = grecaptcha.getResponse(); + if (captchaVerificationToken.length == 0) { + showSuccessAlert(successAlertId, false); + showErrorAlert(errorAlertId, errorAlertInnerElementId, true, ErrorMessages.MISSING_CAPTCHA_ERROR); + setTimeout(() => { + showErrorAlert(errorAlertId, errorAlertInnerElementId, false, ""); + }, 3000); + } else { + var data = new FormData(form) + fetch(`${import.meta.env.PUBLIC_API_HOST}${import.meta.env.PUBLIC_APPLICATION_API_ENDPOINT}`, { + method: "POST", + body: JSON.stringify({ + "name": data.get("name"), + "token": captchaVerificationToken, + "publisher": data.get("publisher"), + "requestType": data.get("report"), + "appCategories": data.get("categories") ?? "", + "urlForDownload": data.get("app_url") ?? "", + "displayedArmCompatibility": data.get("arm_compatibility") ?? "", + "compatibleVersionNumber": data.get("earliest_compt_version") ?? "", + "executionCompatibility": data.get("exec_compatibility") ?? "", + "iconUrl": data.get("icon_url") ?? "" + }), + headers: { + "Content-Type": "application/json", + "Accept": "application/json", + } + }).then((response) => { + if (response.status === 200) { + return response; + } else { + throw new Error(ErrorMessages.GENERIC_ERROR); + } + }).then((response) => { + pageLoading(false); + showSuccessAlert(successAlertId, true); + showErrorAlert(errorAlertId, errorAlertInnerElementId, false, ''); + setTimeout(() => { + window.location.href=`/${formLocale}/contributing` + }, 3000); + }).catch((error) => { + pageLoading(false); + showSuccessAlert(successAlertId, false); + showErrorAlert(errorAlertId, errorAlertInnerElementId, true, ErrorMessages.FETCH_ERROR); + setTimeout(() => { + showErrorAlert(errorAlertId, errorAlertInnerElementId, false, ''); + }, 3000); + }) + }; +}); + +//######################################## Loader ########################################// + +window.onload = (e) => { + populateMultiSelect(categoriesUrl, multiCategoriesElementId).then(() => { + setTimeout(showPage, 100); + }); +}; + +function showPage() { + pageLoading(false); + document.getElementById("fecthingApplicationCategoriesSubTitle").style.display = "none"; + document.getElementById("applicationCompatibilitySubTitle").style.display = "block"; +} diff --git a/src/lib/common.js b/src/lib/common.js new file mode 100644 index 00000000..a285d0e9 --- /dev/null +++ b/src/lib/common.js @@ -0,0 +1,79 @@ +import yaml from 'js-yaml'; + +export const ApiURLs = { + REPO_CONTENT: "https://api.github.com/repos/Linaro/works-on-woa/contents/src/content", + APPLICATIONS_CATEGORIES: "/applications_categories", + GAMES_CATEGORIES: "/games_categories" +}; + +export const ErrorMessages = { + GENERIC_ERROR: "An Error occurred", + FETCH_ERROR: "Failed to send data to the server", + MISSING_CAPTCHA_ERROR: "Please, validate the captcha" +}; + +//######################################## multi select ########################################// + +export async function fileDataFetcher(url) { + const response = await fetch(url); + const data = await response.json(); + + const files = data.filter(item => item.type === 'file' && item.name.endsWith('.md')); + + let categories = []; + for (const file of files) { + const fileContentResponse = await fetch(file.download_url); + const fileContent = await fileContentResponse.text(); + + const parsedContent = yaml.loadAll(fileContent); + categories.push(parsedContent[0].name); + } + + return categories; +} + +export async function populateMultiSelect(url, elementId) { + const elemList = await fileDataFetcher(url); + const multiSelect = document.getElementById(elementId); + + for (let elem of elemList) { + var opt = document.createElement('option'); + opt.value = elem; + opt.innerHTML = elem; + multiSelect.appendChild(opt); + } +} + +//######################################## Success and Error Alerts ########################################// + +export function showSuccessAlert(elementId, show) { + const success_alert = document.getElementById(elementId); + success_alert.style.display = show ? 'block' : 'none'; +} + +export function showErrorAlert(elementId, innerElementId, show, errorMsg) { + const error_alert = document.getElementById(elementId); + error_alert.style.display = show ? 'block' : 'none'; + + let errorResult = "An error occurred!"; + const error_alert_info = document.getElementById(innerElementId); + + if ((errorMsg ?? '') !== '') { + errorResult = ` ${errorMsg}`; + } + + error_alert_info.innerHTML = errorResult; +} + +export function pageLoading(isLoading) { + const loader = document.getElementById("loader"); + const mainDiv = document.getElementById("mainDiv"); + + if (isLoading) { + loader.style.display = "block"; + mainDiv.style.display = "none"; + } else { + loader.style.display = "none"; + mainDiv.style.display = "block"; + } +} diff --git a/src/lib/games.js b/src/lib/games.js new file mode 100644 index 00000000..d60ce925 --- /dev/null +++ b/src/lib/games.js @@ -0,0 +1,84 @@ +import { ApiURLs, ErrorMessages, pageLoading, populateMultiSelect, showSuccessAlert, showErrorAlert } from './common'; + +const successAlertId = "success_alert"; +const errorAlertId = "error_alert"; +const errorAlertInnerElementId = "error_alert_info"; +const gameCategoriesElementId = "categories"; +const categoriesUrl = `${String(ApiURLs.REPO_CONTENT)}${String(ApiURLs.GAMES_CATEGORIES)}`; + +//######################################## Form submission ########################################// + +const form = document.getElementById("gameForm"); +const formLocale = form.dataset.locale +form.addEventListener("submit", (e) => { + e.preventDefault(); + pageLoading(true); + + var captchaVerificationToken = grecaptcha.getResponse(); + if (captchaVerificationToken.length == 0) { + showSuccessAlert(successAlertId, false); + showErrorAlert(errorAlertId, errorAlertInnerElementId, true, ErrorMessages.MISSING_CAPTCHA_ERROR); + setTimeout(() => { + showErrorAlert(errorAlertId, errorAlertInnerElementId, false, ''); + }, 3000); + } else { + var data = new FormData(form); + fetch(`${import.meta.env.PUBLIC_API_HOST}${import.meta.env.PUBLIC_GAME_API_ENDPOINT}`, { + method: "POST", + body: JSON.stringify({ + "name": data.get("name"), + "token": captchaVerificationToken, + "publisher": data.get("publisher"), + "categories": data.get("categories") ?? "", + "compatibility": data.get("compatibility") ?? "", + "deviceConfiguration": data.get("device_configuration") ?? "", + "dateTasted": data.get("date_tested") ?? "", + "osVersion": data.get("os_version") ?? "", + "driverId": data.get("driver_id") ?? "", + "compatibilityDetails": data.get("compatibility_details") ?? "", + "autoSuperResCompatibility": data.get("asrc") ?? "", + "autoSuperResFPSboost": data.get("auto_super_res_boost") ?? "", + "nameOrGamerTag": data.get("gamertag") ?? "" + }), + headers: { + "Content-Type": "application/json", + "Accept": "application/json", + } + }).then((response) => { + if (response.status === 200) { + return response; + } else { + throw new Error(ErrorMessages.GENERIC_ERROR); + } + }).then((response) => { + pageLoading(false); + showSuccessAlert(successAlertId, true); + showErrorAlert(errorAlertId, errorAlertInnerElementId, false, ''); + setTimeout(() => { + window.location.href=`/${formLocale}/contributing` + }, 3000); + }).catch((error) => { + pageLoading(false); + showSuccessAlert(successAlertId, false); + showErrorAlert(errorAlertId, errorAlertInnerElementId, true, ErrorMessages.FETCH_ERROR); + setTimeout(() => { + showErrorAlert(errorAlertId, errorAlertInnerElementId, false, ''); + }, 3000); + }) + } +}); + +//######################################## Loader ########################################// + +window.onload = (e) => { + populateMultiSelect(categoriesUrl, gameCategoriesElementId).then(() => { + setTimeout(showPage, 100); + }); +}; + +function showPage() { + pageLoading(false); + document.getElementById("fecthingApplicationCategoriesSubTitle").style.display = "none"; + document.getElementById("gameCompatibilitySubTitle").style.display = "block"; + document.getElementById('date_tested').valueAsDate = new Date(); +} diff --git a/src/pages/en/contributing.md b/src/pages/en/contributing.md index d2caef3f..feb6826c 100644 --- a/src/pages/en/contributing.md +++ b/src/pages/en/contributing.md @@ -9,15 +9,13 @@ description: How to contribute to this site - Games ## Applications -Contributions for apps can be made directly to the github project or using a convenient form process. +Contributions for apps can be made directly to the github project or using a convenient form process. -### How to contribute via Microsoft Forms (apps) +### How to contribute via App request form -Fill out the below form with your App request. You can use this form for requesting a new app to be tested and added, to tell us where we have something wrong for an app, or to submit your own new app data. We recommend you contribute via the Microsoft Form and not via the Github unless you have some technical experience. Scroll down to see more details on the defined schema and category definitions. +Click the button 'App request form' and fill out the form with your App request. You can use this for requesting a new app to be tested and added, to tell us where we have something wrong for an app, or to submit your own new app data. We recommend you contribute via this form and not via the Github unless you have some technical experience. Scroll down to see more details on the defined schema and category definitions. - - -[Click here](https://forms.office.com/r/JZ1ywk2FaJ) to open the MS Form directly +App request form ### How to contribute via GitHub (apps) @@ -85,13 +83,11 @@ Categories must match the file name of an `.md` file in the appropriate categori ## Games Contributions can be made directly to the github project or using a convenient form process. -### How to contribute via Microsoft Forms (games) - -Fill out the below form with your game test details. We recommend you contribute via the Microsoft Form and not via the Github unless you have some technical experience. Scroll down to see more details on the defined schema and category definitions. +### How to contribute via Game request form - +Click the button 'Game request form' and fill out the below form with your game test details. We recommend you contribute via this form and not via the Github unless you have some technical experience. Scroll down to see more details on the defined schema and category definitions. -[Click here](https://forms.office.com/pages/responsepage.aspx?id=v4j5cvGGr0GRqy180BHbR54qTg-u1FRHnQ3KYgdSD51UMDM4TFYzS1RUSUlHMjVRVkVUR0w5RlhJMC4u) to open the MS Form directly +Game request form ### How to contribute via GitHub (games) diff --git a/src/pages/ja/contributing.md b/src/pages/ja/contributing.md index fc65584d..4e77935a 100644 --- a/src/pages/ja/contributing.md +++ b/src/pages/ja/contributing.md @@ -9,15 +9,12 @@ description: このサイトに貢献する方法 - ゲーム ## アプリケーション -アプリの貢献は、GitHubプロジェクトに直接行うか、便利なフォームプロセスを使用できます。 +アプリの貢献は、GitHubプロジェクトに直接行うか、便利なフォームプロセスを使用できます。 -### Microsoft Formsを使用して貢献する方法(アプリ) +### アプリリクエストフォームで貢献する方法 +「アプリリクエストフォーム」ボタンをクリックして、アプリリクエストのフォームに入力してください。このフォームを使用して、テストと追加が必要な新しいアプリのリクエストを行ったり、アプリの誤りを知らせたり、新しいアプリデータを提出することができます。技術的な経験がない場合は、Githubではなくこのフォームから貢献することをお勧めします。定義されたスキーマとカテゴリの詳細については、下にスクロールしてください。 -以下のフォームにアプリリクエストを記入してください。このフォームを使用して、テストして追加する新しいアプリのリクエストをすることができます。また、アプリに関して何か間違っている場合や、自分の新しいアプリデータを提出する場合にも使用できます。技術的な経験がない限り、GitHubよりもMicrosoft Formsを通じて貢献することをお勧めします。下に、定義されたスキーマとカテゴリの定義についての詳細があります。 - - - -[ここをクリック](https://forms.office.com/r/JZ1ywk2FaJ)してMSフォームを直接開く +アプリリクエストフォーム ### GitHubを使用して貢献する方法(アプリ) @@ -83,13 +80,12 @@ description: このサイトに貢献する方法 カテゴリは、前述の適切なカテゴリフォルダ内の `.md` ファイル名と一致する必要があります。 ## ゲーム -貢献は、GitHub プロジェクトに直接、または便利なフォームプロセスを通じて行うことができます。 - -### Microsoft Forms を使用して貢献する方法 (ゲーム) +貢献は、GitHub プロジェクトに直接、または便利なフォームプロセスを通じて行うことができます。 -以下のフォームにゲームテストの詳細を入力してください。技術的な経験がある場合を除き、GitHub よりも Microsoft フォームでの貢献をお勧めします。定義されたスキーマおよびカテゴリ定義の詳細は、下にスクロールして確認してください。 +### ゲームリクエストフォームで貢献する方法 +「ゲームリクエストフォーム」ボタンをクリックして、以下のフォームにゲームテストの詳細を入力してください。技術的な経験がない場合は、Githubではなくこのフォームから貢献することをお勧めします。定義されたスキーマとカテゴリの詳細については、下にスクロールしてください。 - +ゲームリクエストフォーム ### GitHub を使用して貢献する方法 (ゲーム) diff --git a/src/pages/ko/contributing.md b/src/pages/ko/contributing.md index 1c8c29b0..f1ce35e6 100644 --- a/src/pages/ko/contributing.md +++ b/src/pages/ko/contributing.md @@ -9,15 +9,12 @@ description: 이 사이트에 기여하는 방법 - 게임 ## 애플리케이션 -애플리케이션 기여는 GitHub 프로젝트를 통해 직접 하거나, 편리한 폼 작성 방식으로 제출할 수 있습니다. +애플리케이션 기여는 GitHub 프로젝트를 통해 직접 하거나, 편리한 폼 작성 방식으로 제출할 수 있습니다. -### Microsoft Forms를 통한 기여 방법 (애플리케이션) +### 앱 요청 양식을 통해 기여하는 방법 +‘앱 요청 양식’ 버튼을 클릭하고 앱 요청 양식을 작성하세요. 이 양식을 통해 테스트 및 추가할 새로운 앱을 요청하거나, 앱에 대한 오류를 알리거나, 새로운 앱 데이터를 제출할 수 있습니다. 기술 경험이 없는 경우, Github 대신 이 양식을 통해 기여하는 것을 권장합니다. 정의된 스키마와 카테고리 정의에 대한 자세한 내용은 아래로 스크롤하여 확인하세요. -아래의 양식을 작성하여 애플리케이션 요청을 제출하십시오. 이 양식을 통해 새로운 애플리케이션을 테스트 및 추가 요청하거나, 기존 애플리케이션에 대한 오류를 알리거나, 새 애플리케이션 데이터를 제출할 수 있습니다. 기술 경험이 없는 경우 GitHub보다는 Microsoft Form을 통해 기여하는 것을 권장합니다. 정의된 스키마와 카테고리 정의에 대한 자세한 내용은 아래로 스크롤하여 확인하십시오. - - - -[여기를 클릭하여](https://forms.office.com/r/JZ1ywk2FaJ) Microsoft 양식을 직접 열기 +앱 요청 양식 ### GitHub를 통한 기여 방법 (애플리케이션) @@ -83,15 +80,12 @@ GitHub 계정이 필요합니다. 계정이 없다면 https://github.com 으로 카테고리는 앞서 지정된 적절한 카테고리 폴더 내의 `.md` 파일 이름과 일치해야 합니다. ## 게임 -GitHub 프로젝트에 직접 기여하거나, 편리한양식 프로세스를 통해 기여할 수 있습니다. - -### Microsoft Forms를 통한 기여 방법 (게임) - -아래 양식에 게임 테스트 정보를 작성하십시오. 기술적 경험이 없는 경우 Microsoft Forms를 통한 기여를 권장합니다. 정의된 스키마 및 카테고리 정의에 대한 자세한 내용은 아래로 스크롤하여 확인하십시오. +GitHub 프로젝트에 직접 기여하거나, 편리한양식 프로세스를 통해 기여할 수 있습니다. - +### 게임 요청 양식을 통해 기여하는 방법 +‘게임 요청 양식’ 버튼을 클릭하고 아래의 게임 테스트 세부 정보를 입력하세요. 기술 경험이 없는 경우, Github 대신 이 양식을 통해 기여하는 것을 권장합니다. 정의된 스키마와 카테고리 정의에 대한 자세한 내용은 아래로 스크롤하여 확인하세요. -[여기를 클릭](https://forms.office.com/pages/responsepage.aspx?id=v4j5cvGGr0GRqy180BHbR54qTg-u1FRHnQ3KYgdSD51UMDM4TFYzS1RUSUlHMjVRVkVUR0w5RlhJMC4u)하여 MS Forms를 직접 열기 +게임 요청 양식 ### GitHub를 통한 기여 방법 (게임) diff --git a/src/pages/zh/contributing.md b/src/pages/zh/contributing.md index dd92fb9d..49bf8e96 100644 --- a/src/pages/zh/contributing.md +++ b/src/pages/zh/contributing.md @@ -9,15 +9,12 @@ description: 如何为此站点做出贡献 - 游戏 ## 应用程序 -应用程序的贡献可以直接在GitHub 项目上完成,也可以通过便捷的表单流程提交。 +应用程序的贡献可以直接在GitHub 项目上完成,也可以通过便捷的表单流程提交。 -### 通过 Microsoft Forms 进行贡献(应用程序) +### 通过应用请求表单贡献 +点击“应用请求表单”按钮,填写您的应用请求表单。您可以使用此表单请求测试并添加新应用、报告应用错误或提交新的应用数据。如果您没有技术经验,建议通过此表单而非Github进行贡献。向下滚动查看更多关于定义的架构和类别定义的详细信息。 -请填写以下表单并提交您的应用程序请求。您可以使用此表单请求测试并添加新的应用程序,告知我们某个应用程序的信息有误,或者提交您自己的新应用程序数据。我们建议没有技术经验的用户通过 Microsoft Form 而不是 GitHub 进行贡献。向下滚动查看有关定义的架构和类别定义的更多详细信息。 - - - -[点击此处](https://forms.office.com/r/JZ1ywk2FaJ)直接打开 Microsoft 表单 +应用请求表单 ### 通过 GitHub 进行贡献(应用程序) @@ -83,15 +80,12 @@ description: 如何为此站点做出贡献 类别必须与前面指定的适当类别文件夹中的 `.md` 文件名匹配。 ## 游戏 -可以直接向GitHub 项目贡献,或使用方便的表单流程。 - -### 通过 Microsoft Forms 贡献(游戏) - -填写以下表单,输入游戏测试的详细信息。除非您有一些技术经验,否则建议您通过 Microsoft 表单进行贡献,而不是 GitHub。向下滚动查看定义的模式和类别定义的详细信息。 +可以直接向GitHub 项目贡献,或使用方便的表单流程。 - +### 通过游戏请求表单贡献 +点击“游戏请求表单”按钮,填写以下表单中的游戏测试详情。如果您没有技术经验,建议通过此表单而非Github进行贡献。向下滚动查看更多关于定义的架构和类别定义的详细信息。 -[点击此处](https://forms.office.com/pages/responsepage.aspx?id=v4j5cvGGr0GRqy180BHbR54qTg-u1FRHnQ3KYgdSD51UMDM4TFYzS1RUSUlHMjVRVkVUR0w5RlhJMC4u)直接打开 MS 表单 +游戏请求表单 ### 通过 GitHub 贡献(游戏) diff --git a/src/styles/global.css b/src/styles/global.css index 4f5df8f9..f624ce9f 100644 --- a/src/styles/global.css +++ b/src/styles/global.css @@ -24,3 +24,47 @@ @apply flex items-center justify-center px-4 h-10 ml-0 leading-tight border bg-neutral-600 border-neutral-700 text-neutral-200 hover:bg-neutral-700 hover:text-white; } } + +#loader { + position: absolute; + left: 50%; + top: 50%; + z-index: 1; + width: 120px; + height: 120px; + margin: -76px 0 0 -76px; + border: 16px solid #f3f3f3; + border-radius: 50%; + border-top: 16px solid #3498db; + -webkit-animation: spin 2s linear infinite; + animation: spin 2s linear infinite; +} + +@-webkit-keyframes spin { + 0% { -webkit-transform: rotate(0deg); } + 100% { -webkit-transform: rotate(360deg); } +} + +@keyframes spin { + 0% { transform: rotate(0deg); } + 100% { transform: rotate(360deg); } +} + +/* Add animation to "page content" */ +.animate-bottom { + position: relative; + -webkit-animation-name: animatebottom; + -webkit-animation-duration: 1s; + animation-name: animatebottom; + animation-duration: 1s +} + +@-webkit-keyframes animatebottom { + from { bottom:-100px; opacity:0 } + to { bottom:0px; opacity:1 } +} + +@keyframes animatebottom { + from{ bottom:-100px; opacity:0 } + to{ bottom:0; opacity:1 } +} From 7c67c3ab3bdb4bcd4d74efb260cf2f7a3f5da83c Mon Sep 17 00:00:00 2001 From: Gaspar Acevedo Zain <43762887+gasper-az@users.noreply.github.com> Date: Mon, 2 Dec 2024 17:52:05 -0300 Subject: [PATCH 06/11] [feat] Update lambdas to create issue for App requests --- aws-lambdas/AppForm/index.mjs | 15 +++++++++---- .../models/pull-request-template-data.js | 5 +++++ aws-lambdas/utils/issue-data-generator.js | 22 +++++++++++++++++++ aws-lambdas/utils/issue-manager.js | 22 +++++++++++++++++++ aws-lambdas/utils/octokit-manager.js | 15 ++++++++++++- 5 files changed, 74 insertions(+), 5 deletions(-) create mode 100644 aws-lambdas/utils/issue-data-generator.js create mode 100644 aws-lambdas/utils/issue-manager.js diff --git a/aws-lambdas/AppForm/index.mjs b/aws-lambdas/AppForm/index.mjs index 2678950c..34cd13bc 100644 --- a/aws-lambdas/AppForm/index.mjs +++ b/aws-lambdas/AppForm/index.mjs @@ -2,6 +2,7 @@ import RequestValidator from './utils/request-validator.js'; import EmailManager from './utils/email-manager.js'; import ConfigManager from './utils/config-manager.js'; import PullRequestManager from './utils/pull-request-manager.js'; +import IssueManager from './utils/issue-manager.js'; import { FileType } from "./models/file-type.js"; const configManager = new ConfigManager(); @@ -49,10 +50,16 @@ export const handler = async (event) => { }; const handleTestingRequest = async (data) => { - const emailManager = new EmailManager(config.sendgridApiKey, config.senderEmail, config.recipientEmail); - console.log(`Sending email to test the application ${data.name}...`); - await emailManager.sendEmail(`[Request for testing app] - ${data.name}`, emailManager.generateAppTestEmailContent(data.name, data.publisher)); - console.log(`Email for testing application ${data.name} successfully sent`); + const issueManager = new IssueManager(); + console.log(`Creating Issue for ${data.name} from ${data.publisher}.`); + await issueManager.createIssue(data, { + githubAppId: config.githubAppId, + githubAppInstallationId: config.githubAppInstallationId, + githubAppPkBase64: config.githubAppPkBase64, + githubOwner: config.githubOwner, + githubRepo: config.githubRepo + }); + console.log(`Issue for ${data.name} from ${data.publisher} successfully created.`); }; const handleSubmitOrUpdateRequest = async (data) => { diff --git a/aws-lambdas/models/pull-request-template-data.js b/aws-lambdas/models/pull-request-template-data.js index 4803f871..d53d9754 100644 --- a/aws-lambdas/models/pull-request-template-data.js +++ b/aws-lambdas/models/pull-request-template-data.js @@ -12,6 +12,11 @@ export const pullRequestTemplateData = { pullRequestTitleTemplate: template`[Feature] Add file for ${0} ${1}`, // ex: [Feature] Add file for Outlook Application }; +export const issueTemplateData = { + title: template`[Request] Test ${0} application`, + body: template`This issue corresponds to a request to test the **${0}** application from **${1}**.\nPlease proceed with the testing process at your earliest convenience.\n**NOTE**: this Issue has been automatically generated.` +} + // Tagged template function for creating templates with placeholders // Usage: const value = template`list of values: ${0}, ${1}, {2}`; // value("first", "second", "third"); // outputs: "list of values: first, second, third"; diff --git a/aws-lambdas/utils/issue-data-generator.js b/aws-lambdas/utils/issue-data-generator.js new file mode 100644 index 00000000..0b8842bf --- /dev/null +++ b/aws-lambdas/utils/issue-data-generator.js @@ -0,0 +1,22 @@ +import { issueTemplateData } from "../models/pull-request-template-data.js"; + +export default class IssueDataGenerator { + constructor(params) { + this.templateData = params.templateData; + } + + getIssueData(params) { + const formattedData = {}; + + const name = params.formData.name; + const publisher = params.formData.publisher; + const nameAlphanumeric = name.replace(/[^a-zA-Z0-9\s]/g,''); + + formattedData.issueBody = this.templateData.body(name, publisher); + formattedData.issueTitle = this.templateData.title(nameAlphanumeric); + + return formattedData; + } +} + +export const issueDataGenerator = new IssueDataGenerator({ templateData: issueTemplateData }); \ No newline at end of file diff --git a/aws-lambdas/utils/issue-manager.js b/aws-lambdas/utils/issue-manager.js new file mode 100644 index 00000000..0c7fada6 --- /dev/null +++ b/aws-lambdas/utils/issue-manager.js @@ -0,0 +1,22 @@ +import OctokitManager from './octokit-manager.js'; +import { issueDataGenerator } from "./issue-data-generator.js"; + +export default class IssueManager { + constructor() {} + + async createIssue(formData, gitHubRepositoryConfig) { + const octokitManager = new OctokitManager({ + owner: gitHubRepositoryConfig.githubOwner, + repo: gitHubRepositoryConfig.githubRepo, + appId: gitHubRepositoryConfig.githubAppId, + installationId: gitHubRepositoryConfig.githubAppInstallationId, + privateKey: Buffer.from(gitHubRepositoryConfig.githubAppPkBase64 , 'base64').toString('ascii') + }); + + const issueData = issueDataGenerator.getIssueData({ + formData: formData + }); + + await octokitManager.createIssue(issueData.issueTitle, issueData.issueBody); + } +} \ No newline at end of file diff --git a/aws-lambdas/utils/octokit-manager.js b/aws-lambdas/utils/octokit-manager.js index b42c3118..0a46c75c 100644 --- a/aws-lambdas/utils/octokit-manager.js +++ b/aws-lambdas/utils/octokit-manager.js @@ -127,5 +127,18 @@ export default class OctokitManager { } }); return data; - } + } + + async createIssue(title, body) { + const { data } = await this.octokit.issues.create({ + owner: this.owner, + repo: this.repo, + title: title, + body: body, + headers: { + 'X-GitHub-Api-Version': '2022-11-28' + } + }); + return data; + } } From dbeaa666d646b77fc130c4f6aab9bbcef77b745d Mon Sep 17 00:00:00 2001 From: Gaspar Acevedo Zain <43762887+gasper-az@users.noreply.github.com> Date: Mon, 2 Dec 2024 17:52:19 -0300 Subject: [PATCH 07/11] [feedback] Apply feedback on contributing pages --- src/components/Common/Breadcrumbs.astro | 2 +- .../[lang]/contributing/applications.astro | 49 +++++++-------- src/pages/[lang]/contributing/games.astro | 59 ++++++++++--------- 3 files changed, 56 insertions(+), 54 deletions(-) diff --git a/src/components/Common/Breadcrumbs.astro b/src/components/Common/Breadcrumbs.astro index 047924bf..a8f1971d 100644 --- a/src/components/Common/Breadcrumbs.astro +++ b/src/components/Common/Breadcrumbs.astro @@ -21,7 +21,7 @@ console.log(Astro.props);
  24. {t('bradcrumbs.home')} diff --git a/src/pages/[lang]/contributing/applications.astro b/src/pages/[lang]/contributing/applications.astro index 4e5d372e..c8e5954a 100644 --- a/src/pages/[lang]/contributing/applications.astro +++ b/src/pages/[lang]/contributing/applications.astro @@ -57,25 +57,25 @@ const recaptcha_url = `https://www.google.com/recaptcha/api.js?hl=${locale}`;
  25. -
    - -

    {t('application_form.app_category.fetching_categories')}

    +
    + +

    {t('application_form.app_category.fetching_categories')}