From 5e3f1e0957b64ced96b97b069b5025024603aa0d Mon Sep 17 00:00:00 2001 From: Baptiste <68440638+Baptiiiiste@users.noreply.github.com> Date: Sat, 22 Nov 2025 16:23:06 +0100 Subject: [PATCH 01/15] UPD - Update translations to English and add support for English locale (#22) --- TODO.md | 1 + lib/i18n/routing.ts | 4 +- messages/en.json | 247 +++++++++++++++++++++++++++++++++++++++++ messages/fr-old.json | 258 ------------------------------------------- 4 files changed, 250 insertions(+), 260 deletions(-) create mode 100644 messages/en.json delete mode 100644 messages/fr-old.json diff --git a/TODO.md b/TODO.md index ec5ab5b..17837bc 100644 --- a/TODO.md +++ b/TODO.md @@ -14,6 +14,7 @@ - Handle stripe integration - Handle billing page - Handle plan selection +- Fix missing translations (Sidebar, disconnect button) # Future features - Auto deletion of requests after a certain period of time diff --git a/lib/i18n/routing.ts b/lib/i18n/routing.ts index bc8f0b1..6471c55 100644 --- a/lib/i18n/routing.ts +++ b/lib/i18n/routing.ts @@ -1,7 +1,7 @@ import { defineRouting } from 'next-intl/routing' export const routing = defineRouting({ - locales: ['fr'], - defaultLocale: 'fr', + locales: ['fr', 'en'], + defaultLocale: 'en', localePrefix: 'always', }) diff --git a/messages/en.json b/messages/en.json new file mode 100644 index 0000000..e52be6d --- /dev/null +++ b/messages/en.json @@ -0,0 +1,247 @@ +{ + "Configuration": { + "Plans": { + "FREE": "Free", + "PRO": "Pro", + "ADMIN": "Administrator", + "Upgrade": "Upgrade" + } + }, + "CopyButton": { + "Copy": "Copy", + "Copied": "Copied" + }, + "PricingPage": { + "Title": "Pricing", + "Description": "Plans and pricing", + "TODO": "The payment system has been disabled for the moment. The free plan has been temporarily upgraded to the Pro plan for all users." + }, + "LandingPage": { + "Buttons": { + "SignIn": "Sign in", + "CTA": "Get your webhook URL" + }, + "Slogan": { + "Part1": "Debug your webhooks with", + "Part2": "persistent storage" + }, + "Description": "Inspect payloads, replay requests, and monitor your webhooks in real-time. Never lose a webhook event again thanks to automatic persistence.", + "FeatureCards": { + "Feature1": { + "Title": "Inspect payloads", + "Description": "View full webhook payloads with syntax highlighting and search functionality." + }, + "Feature2": { + "Title": "Replay requests", + "Description": "Replay any webhook to your endpoint for easy testing and debugging." + }, + "Feature3": { + "Title": "Monitor in real-time", + "Description": "Track webhook delivery, response times, and success rates with live analytics." + } + }, + "Trusted": { + "Badge": "Trusted by developers", + "Title": "Built for developer workflows", + "Description": "Thousands of developers trust WPT to debug and monitor their webhook integrations." + }, + "Documentation": { + "Badge": "Platform features", + "Title": "Everything you need to test your webhooks", + "Description": "Powerful features designed for developers looking for reliable webhook testing and debugging tools.", + "Features": { + "Feature1": { + "Title": "Schedule your times", + "Description": "Explore your data, build your dashboard, and bring your team together." + }, + "Feature2": { + "Title": "From data to insights in minutes", + "Description": "Turn your raw data into actionable insights with powerful analytics tools." + }, + "Feature3": { + "Title": "Collaborate seamlessly", + "Description": "Work together in real-time with your team and share insights instantly." + } + } + }, + "Pricing": { + "Badge": "Plans and pricing", + "Title": "Simple and transparent pricing", + "Description": "Start testing your webhooks for free. Upgrade to Pro for advanced features and higher limits when you need them.", + "Billing": { + "Monthly": "Monthly", + "Annually": "Yearly", + "BilledMonthly": "per month", + "BilledAnnually": "per month, billed annually", + "Forever": "forever" + }, + "Plans": { + "FREE": "Perfect for testing and small projects.", + "PRO": "Advanced features.", + "Popular": "POPULAR" + }, + "Advantages": { + "RequestPerMonth": "requests per month", + "WebhookCount": "webhook", + "History": "days of request history", + "ReplayRequest": "Replay your requests" + }, + "CTA": { + "FREE": "Start for free", + "PRO": "Get started" + } + }, + "CTA": { + "FREE": "Start for free", + "Title": "Ready to transform your business?", + "Description": "Join thousands of companies optimizing their operations, managing their schedules, and growing with data-driven insights." + }, + "Footer": { + "Legal": "Legal Notice", + "AllRightsReserved": "All rights reserved", + "Terms": "Terms of Service", + "Privacy": "Privacy Policy" + }, + "FAQ": { + "Title": "Frequently Asked Questions", + "Description": "Explore your data, build your dashboard, and bring your team together." + } + }, + "Datatable": { + "LinesPerPage": "Rows per page", + "Amount": "{count, plural, one {# item} other {# items}}", + "PageNumber": "Page {page} of {pages}", + "NoData": "No results", + "NA": "N/A" + }, + "DeleteConfirmationModal": { + "Confirmation": "Confirmation", + "Cancel": "Cancel", + "Confirm": "Confirm", + "Error": "An error occurred" + }, + "Auth": { + "SignInPage": { + "Title": "Welcome back", + "Subtitle": "Sign in with your credentials", + "Methods": { + "Google": "Sign in with Google", + "Github": "Sign in with Github", + "Other": "Or sign in with" + }, + "Form": { + "Email": "Email address", + "Password": "Password", + "Submit": "Sign in", + "Errors": { + "InvalidCredentials": "Invalid credentials", + "GenericError": "An error occurred, please try again later" + } + }, + "Footer": { + "NoAccount": "Don't have an account? ", + "SignUp": "Sign up" + } + }, + "SignUpPage": { + "Title": "Welcome", + "Subtitle": "Sign up with your credentials", + "Methods": { + "Google": "Sign up with Google", + "Github": "Sign up with Github", + "Other": "Or sign up with" + }, + "Form": { + "Username": "Username", + "Email": "Email address", + "Password": "Password", + "Submit": "Sign up", + "Errors": { + "EmailAlreadyTaken": "This email address is already taken", + "GenericError": "An error occurred, please try again later" + } + }, + "Footer": { + "AlreadyHaveAccount": "Already have an account? ", + "SignIn": "Sign in" + } + }, + "Footer": { + "Title": "By signing in, you agree to our", + "Terms": "Terms of Service", + "AndConditions": " and our ", + "Privacy": "Privacy Policy" + } + }, + "DashboardPage": { + "Title": "Dashboard", + "Description": "General information", + "InfoCard": { + "RequestsCount": { + "Title": "Total Requests", + "Description": "Total number of requests made" + }, + "WebhooksCount": { + "Title": "Total Webhooks", + "Description": "Total number of webhooks created" + }, + "Plan": { + "Title": "Your Plan", + "Description": "Details of your current plan" + }, + "Webhooks": { + "Title": "My Webhooks", + "Description": "List of your active webhooks" + }, + "Requests": { + "Title": "Recent Request Activity", + "Description": "Number of requests over the last 7 days" + } + } + }, + "WebhookPage": { + "Title": "Webhooks", + "Description": "Webhook management", + "MaxWebhooks": "Number of webhooks for your plan", + "Usage": { + "Title": "How to use the webhook?", + "Description": "Copy your webhook URL below and use it in your application to send requests to it. Every request sent will be logged and displayed in the table below.", + "CurlIndication": "Usage example with curl" + }, + "Datatable": { + "Name": "Name", + "URL": "URL", + "RequestsCount": "Request count", + "DeleteMessage": "Are you sure you want to delete this webhook? This action is irreversible and will delete all related requests." + }, + "Errors": { + "404": "The webhook was not found", + "400": "Cannot delete the webhook, it is being used elsewhere", + "UNKNOWN": "An error occurred" + }, + "WebhookDetail": { + "Datatable": { + "Method": "Method", + "Origin": "Origin", + "Ip": "IP Address", + "DeleteMessage": "Are you sure you want to delete this request? This action is irreversible." + } + } + }, + "AdminPage": { + "Description": "Data management & statistics" + }, + "RequestDetailSheet": { + "Title": "Request Details #{requestId}", + "GlobalInfo": { + "Title": "General Information", + "Ip": "IP Address", + "Size": "Content size", + "UserAgent": "User-Agent", + "Origin": "Origin" + }, + "Headers": "Headers", + "Body": "Body", + "QueryParams": "Query Params" + } +} \ No newline at end of file diff --git a/messages/fr-old.json b/messages/fr-old.json deleted file mode 100644 index 489f7b0..0000000 --- a/messages/fr-old.json +++ /dev/null @@ -1,258 +0,0 @@ -{ - "Configuration": { - "Plans": { - "FREE": "Gratuit", - "PRO": "Pro", - "ADMIN": "Administrateur", - "Upgrade": "Améliorer" - } - }, - "CopyButton": { - "Copy": "Copier", - "Copied": "Copié" - }, - "LandingPage": { - "Buttons": { - "SignIn": "Sign in", - "CTA": "Get your webhook URL" - }, - "Slogan": { - "Part1": "Debug webhooks with", - "Part2": "persistent storage" - }, - "Description": { - "Part1": "Inspect payloads, replay requests, and monitor webhooks in real-time.", - "Part2": "Never lose a webhook event again with automatic persistence." - }, - "FeatureCards": { - "Feature1": { - "Title": "Inspect payloads", - "Description": "View complete webhook payloads with syntax highlighting and search capabilities." - }, - "Feature2": { - "Title": "Replay requests", - "Description": "Replay any webhook to your endpoint for testing and debugging purposes." - }, - "Feature3": { - "Title": "Monitor in real-time", - "Description": "Track webhook delivery, response times, and success rates with live analytics." - } - }, - "Trusted": { - "Badge": "Trusted by developers", - "Title": "Built for developer workflows", - "Description": { - "Part1": "Thousands of developers rely on", - "Part2": "to debug and monitor their webhook integrations." - } - }, - "Documentation": { - "Badge": "Platform features", - "Title": "Everything you need to test webhooks", - "Description": { - "Part1": "Powerful features designed for developers who need", - "Part2": "reliable webhook testing and debugging tools." - }, - "Features": { - "Feature1": { - "Title": "Plan your schedules", - "Description": "Explore your data, build your dashboard, bring your team together." - }, - "Feature2": { - "Title": "Data to insights in minutes", - "Description": "Transform raw data into actionable insights with powerful analytics tools." - }, - "Feature3": { - "Title": "Collaborate seamlessly", - "Description": "Work together in real-time with your team and share insights instantly." - } - } - }, - "Pricing": { - "Badge": "Plans & Pricing", - "Title": "Simple, transparent pricing", - "Description": { - "Part1": "Start testing webhooks for free. Upgrade to Pro for advanced features", - "Part2": "and higher limits when you need them." - }, - "Billing": { - "Monthly": "Monthly", - "Annually" : "Annualy", - "BilledMonthly": "per month", - "BilledAnnually": "per month, billed annually", - "Forever": "forever" - }, - "Plans": { - "FREE" : "Perfect for testing and small projects.", - "PRO": "Advanced features for production use.", - "Popular": "POPULAR" - }, - "Advantages": { - "RequestPerMonth": "requests per month", - "WebhookCount": "webhook", - "History": "day request history", - "ReplayRequest": "Replay your requests" - }, - "CTA": { - "FREE": "Start for free", - "PRO": "Get started" - } - }, - "CTA": { - "FREE": "Start for free", - "Title": "Ready to transform your business?", - "Description": { - "Part1": "Join thousands of businesses streamlining their operations", - "Part2": "managing schedules, and growing with data-driven insights." - } - }, - "Footer": { - "Legal": "Legal", - "AllRightsReserved": "All rights reserved", - "Terms": "Conditions d'utilisation", - "Privacy": "Politique de confidentialité" - }, - "FAQ": { - "Title": "Frequently Asked Questions", - "Description": { - "Part1": "Explore your data, build your dashboard,", - "Part2": "bring your team together." - } - } - }, - "Datatable" : { - "LinesPerPage": "Lignes par page", - "Amount": "{count, plural, one {# élément} other {# éléments}}", - "PageNumber": "Page {page} sur {pages}", - "NoData": "Aucun résultat", - "NA": "N/A" - }, - "DeleteConfirmationModal": { - "Confirmation": "Confirmation", - "Cancel": "Annuler", - "Confirm": "Confirmer", - "Error": "Une erreur est survenue" - }, - "Auth": { - "SignInPage": { - "Title": "Vous revoilà", - "Subtitle": "Connectez-vous avec vos identifiants", - "Methods": { - "Google": "Se connecter avec Google", - "Github": "Se connecter avec Github", - "Other": "Ou se connecter avec" - }, - "Form": { - "Email": "Adresse e-mail", - "Password": "Mot de passe", - "Submit": "Se connecter", - "Errors": { - "InvalidCredentials": "Identifiants invalides", - "GenericError": "Une erreur est survenue, veuillez réessayer plus tard" - } - }, - "Footer": { - "NoAccount": "Vous n'avez pas de compte ? ", - "SignUp": "S'inscrire" - } - }, - "SignUpPage": { - "Title": "Bienvenue", - "Subtitle": "Inscrivez-vous avec vos identifiants", - "Methods": { - "Google": "Se connecter avec Google", - "Github": "Se connecter avec Github", - "Other": "Ou s'inscrire avec" - }, - "Form": { - "Username": "Pseudo", - "Email": "Adresse e-mail", - "Password": "Mot de passe", - "Submit": "S'inscrire", - "Errors": { - "EmailAlreadyTaken": "Cette adresse e-mail est déjà utilisée", - "GenericError": "Une erreur est survenue, veuillez réessayer plus tard" - } - }, - "Footer": { - "AlreadyHaveAccount": "Vous avez déjà un compte ? ", - "SignIn": "Se connecter" - } - }, - "Footer": { - "Title": "En vous connectant, vous acceptez nos", - "Terms": "Conditions d'utilisation", - "AndConditions": " et notre ", - "Privacy": "Politique de confidentialité" - } - }, - "DashboardPage": { - "Description": "Informations générales", - "InfoCard": { - "RequestsCount": { - "Title": "Requêtes totales", - "Description": "Nombre total de requêtes effectuées" - }, - "WebhooksCount": { - "Title": "Webhooks totaux", - "Description": "Nombre total de webhooks créés" - }, - "Plan": { - "Title": "Votre plan", - "Description": "Détails de votre plan actuel" - }, - "Webhooks": { - "Title": "Mes webhooks", - "Description": "Liste de vos webhooks actifs" - }, - "Requests": { - "Title": "Activité récente des requêtes", - "Description": "Nombre de requêtes au cours des 7 derniers jours" - } - } - }, - "WebhookPage": { - "Description": "Gestion des webhooks", - "MaxWebhooks": "Nombre de webhooks pour votre plan", - "Usage" : { - "Title": "Comment utiliser le webhook ?", - "Description": "Copiez l'url de votre webhook ci-dessous et utilisez-la dans votre application pour y envoyer des requêtes. Chaque requête envoyée sera enregistrée et affichée dans le tableau ci-dessous.", - "CurlIndication": "Exemple d'utilisation avec curl" - }, - "Datatable" : { - "Name": "Nom", - "URL": "URL", - "RequestsCount": "Nombre de requêtes", - "DeleteMessage": "Êtes-vous sûr de vouloir supprimer ce webhook ? Cette action est irréversible et supprimera toutes les requêtes liées." - }, - "Errors": { - "404": "Le webhook n'a pas été trouvé" , - "400": "Impossible de supprimer le webhook, il est utilisé ailleurs", - "UNKNOWN": "Une erreur est survenue" - }, - "WebhookDetail": { - "Datatable": { - "Method": "Méthode", - "Origin": "Origine", - "Ip": "Adresse IP", - "DeleteMessage": "Êtes-vous sûr de vouloir supprimer cette requête ? Cette action est irréversible." - } - } - }, - "AdminPage": { - "Description": "Gestion des données & statistiques" - }, - "RequestDetailSheet": { - "Title": "Détails de la requête #{requestId}", - "GlobalInfo": { - "Title": "Informations générales", - "Ip": "Addresse IP", - "Size": "Taille du contenu", - "UserAgent": "User-Agent", - "Origin": "Origine" - }, - "Headers": "Headers", - "Body": "Body", - "QueryParams": "Query Params" - } -} From c45dab5c38194082fc77af81f29a87a9bdf5b091 Mon Sep 17 00:00:00 2001 From: Baptiiiiste Date: Mon, 1 Dec 2025 13:57:22 +0100 Subject: [PATCH 02/15] ADD - Implement SonarQube scan in CI workflow for code quality analysis --- .github/workflows/dev.yml | 42 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/.github/workflows/dev.yml b/.github/workflows/dev.yml index 6779975..eba89fe 100644 --- a/.github/workflows/dev.yml +++ b/.github/workflows/dev.yml @@ -43,6 +43,48 @@ jobs: - name: Build app run: pnpm build + # SonarQube Scan + sonar-scan: + needs: build-and-test + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Setup pnpm + uses: pnpm/action-setup@v3 + with: + version: 9 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: 20 + cache: 'pnpm' + + - name: Install dependencies + run: pnpm install --frozen-lockfile + + - name: Generate Prisma Client + run: pnpm prisma generate + + - name: Tests (with coverage report) + run: pnpm run test -- --coverage --coverage-reporters=lcov + + - name: SonarQube Scan + uses: SonarSource/sonarcloud-github-action@v2.2.0 + env: + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} + SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }} + with: + args: > + -Dsonar.projectKey=wpt + -Dsonar.projectName=WPT + -Dsonar.javascript.lcov.reportPaths=./coverage/lcov.info + # 2️⃣ Build & push Docker image docker-build-push: runs-on: ubuntu-latest From 04393a655cee6737452b95649b18da14df2c5f02 Mon Sep 17 00:00:00 2001 From: Baptiiiiste Date: Mon, 1 Dec 2025 14:02:13 +0100 Subject: [PATCH 03/15] UPD - Update CI workflow to allow tests to pass with no tests present --- .github/workflows/dev.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dev.yml b/.github/workflows/dev.yml index eba89fe..81f1b08 100644 --- a/.github/workflows/dev.yml +++ b/.github/workflows/dev.yml @@ -72,7 +72,7 @@ jobs: run: pnpm prisma generate - name: Tests (with coverage report) - run: pnpm run test -- --coverage --coverage-reporters=lcov + run: pnpm run test -- --coverage --coverage-reporters=lcov --passWithNoTests - name: SonarQube Scan uses: SonarSource/sonarcloud-github-action@v2.2.0 From 392b216a4f9b15e5a56d95b23da066adc3ad0907 Mon Sep 17 00:00:00 2001 From: Baptiiiiste Date: Mon, 1 Dec 2025 14:05:28 +0100 Subject: [PATCH 04/15] UPD - Update CI workflow to allow tests to pass with no tests present --- .github/workflows/dev.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dev.yml b/.github/workflows/dev.yml index 81f1b08..56d640f 100644 --- a/.github/workflows/dev.yml +++ b/.github/workflows/dev.yml @@ -72,7 +72,7 @@ jobs: run: pnpm prisma generate - name: Tests (with coverage report) - run: pnpm run test -- --coverage --coverage-reporters=lcov --passWithNoTests + run: pnpm exec jest --runInBand --coverage --coverage-reporters=lcov --passWithNoTests - name: SonarQube Scan uses: SonarSource/sonarcloud-github-action@v2.2.0 From 6426349138e2227eafa3cb63719b26fa83154ae3 Mon Sep 17 00:00:00 2001 From: Baptiiiiste Date: Mon, 1 Dec 2025 14:10:21 +0100 Subject: [PATCH 05/15] UPD - Update CI workflow to allow tests to pass with no tests present --- .github/workflows/dev.yml | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/.github/workflows/dev.yml b/.github/workflows/dev.yml index 56d640f..9cdbf96 100644 --- a/.github/workflows/dev.yml +++ b/.github/workflows/dev.yml @@ -12,7 +12,6 @@ on: - main jobs: - # 1️⃣ Build & tests build-and-test: runs-on: ubuntu-latest @@ -43,7 +42,6 @@ jobs: - name: Build app run: pnpm build - # SonarQube Scan sonar-scan: needs: build-and-test runs-on: ubuntu-latest @@ -81,11 +79,10 @@ jobs: SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }} with: args: > - -Dsonar.projectKey=wpt - -Dsonar.projectName=WPT - -Dsonar.javascript.lcov.reportPaths=./coverage/lcov.info + -sonar.projectKey=wpt + -sonar.projectName=WPT + -sonar.javascript.lcov.reportPaths=./coverage/lcov.info - # 2️⃣ Build & push Docker image docker-build-push: runs-on: ubuntu-latest needs: build-and-test @@ -127,7 +124,6 @@ jobs: build-args: | NEXT_PUBLIC_ENV=develop - # 3️⃣ Deploy DEV deploy-dev: runs-on: self-hosted needs: docker-build-push From 30c2025a9c4c00c0d2c8358140d6a4c809bbbdc5 Mon Sep 17 00:00:00 2001 From: Baptiiiiste Date: Mon, 1 Dec 2025 14:14:54 +0100 Subject: [PATCH 06/15] UPD - Update CI workflow to allow tests to pass with no tests present --- .github/workflows/dev.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/dev.yml b/.github/workflows/dev.yml index 9cdbf96..176e224 100644 --- a/.github/workflows/dev.yml +++ b/.github/workflows/dev.yml @@ -79,9 +79,10 @@ jobs: SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }} with: args: > - -sonar.projectKey=wpt - -sonar.projectName=WPT - -sonar.javascript.lcov.reportPaths=./coverage/lcov.info + -Dsonar.projectKey=wpt + -Dsonar.projectName=WPT + -Dsonar.organization=WPT + -Dsonar.javascript.lcov.reportPaths=./coverage/lcov.info docker-build-push: runs-on: ubuntu-latest From 6f6b6672ac424c84e99ecb7bd0c45db5d7c17af2 Mon Sep 17 00:00:00 2001 From: Baptiiiiste Date: Mon, 1 Dec 2025 14:22:56 +0100 Subject: [PATCH 07/15] UPD - Update CI workflow to allow tests to pass with no tests present --- .github/workflows/dev.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dev.yml b/.github/workflows/dev.yml index 176e224..feddcc0 100644 --- a/.github/workflows/dev.yml +++ b/.github/workflows/dev.yml @@ -79,7 +79,7 @@ jobs: SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }} with: args: > - -Dsonar.projectKey=wpt + -Dsonar.projectKey=WPT -Dsonar.projectName=WPT -Dsonar.organization=WPT -Dsonar.javascript.lcov.reportPaths=./coverage/lcov.info From c0010962b878c1a4aa1d8957e8b7748673e92c9b Mon Sep 17 00:00:00 2001 From: Baptiiiiste Date: Mon, 1 Dec 2025 14:25:37 +0100 Subject: [PATCH 08/15] UPD - Update CI workflow to allow tests to pass with no tests present --- .github/workflows/dev.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/dev.yml b/.github/workflows/dev.yml index feddcc0..7e63b35 100644 --- a/.github/workflows/dev.yml +++ b/.github/workflows/dev.yml @@ -73,7 +73,7 @@ jobs: run: pnpm exec jest --runInBand --coverage --coverage-reporters=lcov --passWithNoTests - name: SonarQube Scan - uses: SonarSource/sonarcloud-github-action@v2.2.0 + uses: SonarSource/sonar-scanner-action@master env: SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }} @@ -81,7 +81,6 @@ jobs: args: > -Dsonar.projectKey=WPT -Dsonar.projectName=WPT - -Dsonar.organization=WPT -Dsonar.javascript.lcov.reportPaths=./coverage/lcov.info docker-build-push: From 5badef1d787b75dc3045f69684b7c941bef9b302 Mon Sep 17 00:00:00 2001 From: Baptiiiiste Date: Mon, 1 Dec 2025 14:27:49 +0100 Subject: [PATCH 09/15] UPD - Update CI workflow to allow tests to pass with no tests present --- .github/workflows/dev.yml | 41 --------------------------------------- 1 file changed, 41 deletions(-) diff --git a/.github/workflows/dev.yml b/.github/workflows/dev.yml index 7e63b35..417626f 100644 --- a/.github/workflows/dev.yml +++ b/.github/workflows/dev.yml @@ -42,47 +42,6 @@ jobs: - name: Build app run: pnpm build - sonar-scan: - needs: build-and-test - runs-on: ubuntu-latest - - steps: - - name: Checkout code - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - - name: Setup pnpm - uses: pnpm/action-setup@v3 - with: - version: 9 - - - name: Setup Node.js - uses: actions/setup-node@v4 - with: - node-version: 20 - cache: 'pnpm' - - - name: Install dependencies - run: pnpm install --frozen-lockfile - - - name: Generate Prisma Client - run: pnpm prisma generate - - - name: Tests (with coverage report) - run: pnpm exec jest --runInBand --coverage --coverage-reporters=lcov --passWithNoTests - - - name: SonarQube Scan - uses: SonarSource/sonar-scanner-action@master - env: - SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} - SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }} - with: - args: > - -Dsonar.projectKey=WPT - -Dsonar.projectName=WPT - -Dsonar.javascript.lcov.reportPaths=./coverage/lcov.info - docker-build-push: runs-on: ubuntu-latest needs: build-and-test From d5e9ed679bb7d32e0291379741debe8cc724ea3b Mon Sep 17 00:00:00 2001 From: Baptiiiiste Date: Mon, 1 Dec 2025 14:27:49 +0100 Subject: [PATCH 10/15] UPD - Update CI workflow to allow tests to pass with no tests present --- .github/workflows/dev.yml | 41 --------------------------------------- 1 file changed, 41 deletions(-) diff --git a/.github/workflows/dev.yml b/.github/workflows/dev.yml index 7e63b35..417626f 100644 --- a/.github/workflows/dev.yml +++ b/.github/workflows/dev.yml @@ -42,47 +42,6 @@ jobs: - name: Build app run: pnpm build - sonar-scan: - needs: build-and-test - runs-on: ubuntu-latest - - steps: - - name: Checkout code - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - - name: Setup pnpm - uses: pnpm/action-setup@v3 - with: - version: 9 - - - name: Setup Node.js - uses: actions/setup-node@v4 - with: - node-version: 20 - cache: 'pnpm' - - - name: Install dependencies - run: pnpm install --frozen-lockfile - - - name: Generate Prisma Client - run: pnpm prisma generate - - - name: Tests (with coverage report) - run: pnpm exec jest --runInBand --coverage --coverage-reporters=lcov --passWithNoTests - - - name: SonarQube Scan - uses: SonarSource/sonar-scanner-action@master - env: - SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} - SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }} - with: - args: > - -Dsonar.projectKey=WPT - -Dsonar.projectName=WPT - -Dsonar.javascript.lcov.reportPaths=./coverage/lcov.info - docker-build-push: runs-on: ubuntu-latest needs: build-and-test From d80a16b076c92896dada3a55de93bbd0614dbb12 Mon Sep 17 00:00:00 2001 From: Baptiiiiste Date: Mon, 1 Dec 2025 14:30:33 +0100 Subject: [PATCH 11/15] UPD - Update CI workflow to allow tests to pass with no tests present --- .github/workflows/dev.yml | 41 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/.github/workflows/dev.yml b/.github/workflows/dev.yml index 417626f..c303499 100644 --- a/.github/workflows/dev.yml +++ b/.github/workflows/dev.yml @@ -42,6 +42,47 @@ jobs: - name: Build app run: pnpm build + sonar-scan: + needs: build-and-test + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Setup pnpm + uses: pnpm/action-setup@v3 + with: + version: 9 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: 20 + cache: 'pnpm' + + - name: Install dependencies + run: pnpm install --frozen-lockfile + + - name: Generate Prisma Client + run: pnpm prisma generate + + - name: Tests (with coverage report) + run: pnpm exec jest --runInBand --coverage --coverage-reporters=lcov --passWithNoTests + + - name: SonarQube Scan + uses: SonarSource/sonarqube-scan-action@7295e71c9583053f5bf40e9d4068a0c974603ec8 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} + SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }} + with: + args: + -Dsonar.projectKey=WPT +# -Dsonar.javascript.lcov.reportPaths=./coverage/lcov.info + docker-build-push: runs-on: ubuntu-latest needs: build-and-test From b70330c1782203ccc5ab63e5af5fca4919a2a141 Mon Sep 17 00:00:00 2001 From: Baptiiiiste Date: Mon, 1 Dec 2025 14:33:44 +0100 Subject: [PATCH 12/15] UPD - Update SonarQube scan action to use the latest master version --- .github/workflows/dev.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/dev.yml b/.github/workflows/dev.yml index c303499..cdabb0c 100644 --- a/.github/workflows/dev.yml +++ b/.github/workflows/dev.yml @@ -73,15 +73,15 @@ jobs: run: pnpm exec jest --runInBand --coverage --coverage-reporters=lcov --passWithNoTests - name: SonarQube Scan - uses: SonarSource/sonarqube-scan-action@7295e71c9583053f5bf40e9d4068a0c974603ec8 + uses: SonarSource/sonarqube-scan-action@master env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }} with: - args: + args: > -Dsonar.projectKey=WPT -# -Dsonar.javascript.lcov.reportPaths=./coverage/lcov.info + -Dsonar.javascript.lcov.reportPaths=./coverage/lcov.info docker-build-push: runs-on: ubuntu-latest From 4a93e0b7e2f0a916459ed61b243978a3200f44a4 Mon Sep 17 00:00:00 2001 From: Baptiiiiste Date: Mon, 1 Dec 2025 15:07:28 +0100 Subject: [PATCH 13/15] UPD - Remove commented sections from CI configuration files and add CICD documentation --- .github/workflows/dev.yml | 2 - .github/workflows/prod.yml | 3 - JulienPolycarpe-CICD.md | 197 +++++++++++++++++++++++++++++++++++++ 3 files changed, 197 insertions(+), 5 deletions(-) create mode 100644 JulienPolycarpe-CICD.md diff --git a/.github/workflows/dev.yml b/.github/workflows/dev.yml index cdabb0c..9f94786 100644 --- a/.github/workflows/dev.yml +++ b/.github/workflows/dev.yml @@ -147,8 +147,6 @@ jobs: echo "🔧 Deploying on DEV..." cd /home/baptiste/Dev/WPT/dev docker-compose pull - # stop + remove DEV containers ONLY (keeps volumes) docker-compose down - # recreate containers, reusing existing volumes docker-compose up -d --remove-orphans echo "🚀 Deployed in DEV!" \ No newline at end of file diff --git a/.github/workflows/prod.yml b/.github/workflows/prod.yml index 8761177..2baec03 100644 --- a/.github/workflows/prod.yml +++ b/.github/workflows/prod.yml @@ -6,7 +6,6 @@ on: - 'v*.*.*' jobs: - # 1️⃣ Build & tests build-and-test: runs-on: ubuntu-latest @@ -37,7 +36,6 @@ jobs: - name: Build app run: pnpm build - # 2️⃣ Build & push Docker image docker-build-push: runs-on: ubuntu-latest needs: build-and-test @@ -81,7 +79,6 @@ jobs: build-args: | NEXT_PUBLIC_ENV=production - # 3️⃣ Deploy PROD deploy-prod: runs-on: self-hosted needs: docker-build-push diff --git a/JulienPolycarpe-CICD.md b/JulienPolycarpe-CICD.md new file mode 100644 index 0000000..b4bf435 --- /dev/null +++ b/JulienPolycarpe-CICD.md @@ -0,0 +1,197 @@ +# CICD + +## CodeQL + +Added an automatic pipeline for CodeQL analysis on every push and merge-request to any branch. + +## Dev +[Pipeline for dev (.github/workflows/dev.yml)](./.github/workflows/dev.yml) + +On merge-request or push to `dev` and `main` branch: +- Build the application +- Run tests on the most important features [See tests (tests)](./tests) +- Run code quality checks on a private sonarqube server +- Build image using the Dockerfile and push Docker image to registry +- Deploy to staging environment on private server + +Test account for sonarqube: +- link: https://sonarqube.baptiiiste.com/dashboard?id=WPT&codeScope=overall +- user: user +- password: MySuperUser1234@ + +Docker compose on my server: +```yml +version: '3.8' +services: + wpt-dev_postgres: + image: postgres:16 + container_name: wpt-dev_postgres + restart: always + environment: + POSTGRES_USER: $POSTGRES_USER + POSTGRES_PASSWORD: $POSTGRES_PASSWORD + POSTGRES_DB: $POSTGRES_DB + volumes: + - wpt-dev_data:/var/lib/postgresql/data + networks: + - web + ports: + - "5432:5432" + healthcheck: + test: ["CMD-SHELL", "pg_isready -U $POSTGRES_USER -d $POSTGRES_DB"] + interval: 10s + timeout: 5s + retries: 5 + start_period: 30s + + wpt-dev_website: + image: ghcr.io/baptiiiiste/webhookpersistenttester:dev-latest + container_name: wpt-dev_website + restart: always + environment: + NODE_ENV: production + NEXTAUTH_URL: https://wpt-dev.baptiiiste.com + API_URL: https://wpt-dev.baptiiiste.com/api + NEXTAUTH_SECRET: $NEXTAUTH_SECRET + SALT_ROUNDS: "10" + AUTH_TRUST_HOST: "true" + GOOGLE_CLIENT_ID: $GOOGLE_CLIENT_ID + GOOGLE_CLIENT_SECRET: $GOOGLE_CLIENT_SECRET + DATABASE_URL: postgresql://$POSTGRES_USER:$POSTGRES_PASSWORD@wpt-dev_postgres:5432/$POSTGRES_db + networks: + - web + depends_on: + wpt-dev_postgres: + condition: service_healthy + labels: + - "traefik.enable=true" + - "traefik.http.routers.wpt-dev-ws.rule=Host(`wpt-dev.baptiiiste.com`)" + - "traefik.http.routers.wpt-dev-ws.entrypoints=websecure" + - "traefik.http.routers.wpt-dev-ws.tls.certresolver=letsencrypt" + - "traefik.http.services.wpt-dev-ws.loadbalancer.server.port=3000" + + adminer: + image: adminer + container_name: wpt-dev_adminer + restart: always + depends_on: + - wpt-dev_postgres + networks: + - web + environment: + ADMINER_DEFAULT_SERVER: wpt-dev_postgres + labels: + - "traefik.enable=true" + - "traefik.http.routers.wpt-dev-adminer.rule=Host(`adminer-wpt-dev.baptiiiste.com`)" + - "traefik.http.routers.wpt-dev-adminer.entrypoints=websecure" + - "traefik.http.routers.wpt-dev-adminer.tls.certresolver=letsencrypt" + - "traefik.http.services.wpt-dev-adminer.loadbalancer.server.port=8080" + +networks: + web: + external: true +volumes: + wpt-dev_data: +``` + +What is deployed here on my server: +- PostgreSQL database container +- Next.js application container +- Adminer container for database management + +Access the application here: +- link: https://wpt-dev.baptiiiste.com +- user: test@test.com +- password: Test@1234 + +## Prod +[Pipeline for prod (.github/workflows/prod.yml)](./.github/workflows/prod.yml) + +On create tag `v*.*.*`: +- Build the application +- Run tests on the most important features [See tests (./tests)](tests) +- Build image using the Dockerfile and push Docker image to registry +- Deploy to production environment on private server + +Docker compose on my server: +```yml +version: '3.8' +services: + wpt_postgres: + image: postgres:16 + container_name: wpt_postgres + restart: always + environment: + POSTGRES_USER: $POSTGRES_USER + POSTGRES_PASSWORD: $POSTGRES_PASSWORD + POSTGRES_DB: $POSTGRES_DB + volumes: + - wpt_data:/var/lib/postgresql/data + networks: + - web + ports: + - "5433:5432" + healthcheck: + test: ["CMD-SHELL", "pg_isready -U $POSTGRES_USER -d $POSTGRES_DB"] + interval: 10s + timeout: 5s + retries: 5 + start_period: 30s + + wpt_website: + image: ghcr.io/baptiiiiste/webhookpersistenttester:latest + container_name: wpt_website + restart: always + environment: + NODE_ENV: production + NEXTAUTH_URL: https://wpt.baptiiiste.com + API_URL: https://wpt.baptiiiste.com/api + NEXTAUTH_SECRET: $NEXTAUTH_SECRET + SALT_ROUNDS: "10" + AUTH_TRUST_HOST: "true" + GOOGLE_CLIENT_ID: $GOOGLE_CLIENT_ID + GOOGLE_CLIENT_SECRET: $GOOGLE_CLIENT_SECRET + DATABASE_URL: postgresql://$POSTGRES_USER:$POSTGRES_PASSWORD@wpt_postgres:5432/$POSTGRES_db + networks: + - web + ports: + - "3001:3000" + depends_on: + wpt_postgres: + condition: service_healthy + labels: + - "traefik.enable=true" + - "traefik.http.routers.wpt-ws.rule=Host(`wpt.baptiiiste.com`)" + - "traefik.http.routers.wpt-ws.entrypoints=websecure" + - "traefik.http.routers.wpt-ws.tls.certresolver=letsencrypt" + - "traefik.http.services.wpt-ws.loadbalancer.server.port=3000" + +networks: + web: + external: true +volumes: + wpt_data: +``` + +What is deployed here on my server: +- PostgreSQL database container +- Next.js application container + +Access the application here: +- link: https://wpt-dev.baptiiiste.com +- create your own account to test, with not sensitive information + +## Deployment on Private Server + +- Setup Github runners on private server +- Created a `docker-compose.yml` file for each environment (staging and production) +- Used the runner to pull the latest Docker image and restart the container + +Server architecture: +- Ubuntu server +- Portainer for container management +- Traefik as reverse proxy (application are using the `web` network that is linked to my domain) +- Docker and Docker Compose for containerization +- Let's Encrypt for SSL certificates + + From b804644710f46bd867a8a71a83a9562c0018e57f Mon Sep 17 00:00:00 2001 From: Baptiste <68440638+Baptiiiiste@users.noreply.github.com> Date: Sat, 6 Dec 2025 11:56:19 +0100 Subject: [PATCH 14/15] UPD - Update nextjs to prevent react 2 schell --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index bd2f4b4..f329df7 100644 --- a/package.json +++ b/package.json @@ -42,7 +42,7 @@ "eslint-plugin-prettier": "^5.5.3", "lucide-react": "^0.525.0", "mime-types": "^3.0.1", - "next": "15.4.7", + "next": "15.4.8", "next-auth": "5.0.0-beta.25", "next-intl": "^4.3.4", "prisma": "^6.12.0", @@ -75,4 +75,4 @@ "tsconfig-paths": "^4.2.0", "typescript": "^5.8.3" } -} \ No newline at end of file +} From ac4baf691a58a62ec86f9858144a08c01bcf00cb Mon Sep 17 00:00:00 2001 From: Baptiste Date: Sat, 6 Dec 2025 11:59:01 +0100 Subject: [PATCH 15/15] UPD - Update NextJS to prevent React2Shell exploit --- pnpm-lock.yaml | 103 +++++++++++++++++++++++-------------------------- 1 file changed, 49 insertions(+), 54 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5f91f63..33f68ed 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -96,14 +96,14 @@ importers: specifier: ^3.0.1 version: 3.0.1 next: - specifier: 15.4.7 - version: 15.4.7(@babel/core@7.28.5)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + specifier: 15.4.8 + version: 15.4.8(@babel/core@7.28.5)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) next-auth: specifier: 5.0.0-beta.25 - version: 5.0.0-beta.25(next@15.4.7(@babel/core@7.28.5)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react@19.1.0) + version: 5.0.0-beta.25(next@15.4.8(@babel/core@7.28.5)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react@19.1.0) next-intl: specifier: ^4.3.4 - version: 4.3.4(next@15.4.7(@babel/core@7.28.5)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react@19.1.0)(typescript@5.8.3) + version: 4.3.4(next@15.4.8(@babel/core@7.28.5)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react@19.1.0)(typescript@5.8.3) prisma: specifier: ^6.12.0 version: 6.12.0(typescript@5.8.3) @@ -735,56 +735,56 @@ packages: '@napi-rs/wasm-runtime@0.2.12': resolution: {integrity: sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==} - '@next/env@15.4.7': - resolution: {integrity: sha512-PrBIpO8oljZGTOe9HH0miix1w5MUiGJ/q83Jge03mHEE0E3pyqzAy2+l5G6aJDbXoobmxPJTVhbCuwlLtjSHwg==} + '@next/env@15.4.8': + resolution: {integrity: sha512-LydLa2MDI1NMrOFSkO54mTc8iIHSttj6R6dthITky9ylXV2gCGi0bHQjVCtLGRshdRPjyh2kXbxJukDtBWQZtQ==} '@next/eslint-plugin-next@15.4.2': resolution: {integrity: sha512-k0rjdWjXBY6tAOty1ckrMETE6Mx66d85NsgcAIdDp7/cXOsTJ93ywmbg3uUcpxX5TUHFEcCWI5mb8nPhwCe9jg==} - '@next/swc-darwin-arm64@15.4.7': - resolution: {integrity: sha512-2Dkb+VUTp9kHHkSqtws4fDl2Oxms29HcZBwFIda1X7Ztudzy7M6XF9HDS2dq85TmdN47VpuhjE+i6wgnIboVzQ==} + '@next/swc-darwin-arm64@15.4.8': + resolution: {integrity: sha512-Pf6zXp7yyQEn7sqMxur6+kYcywx5up1J849psyET7/8pG2gQTVMjU3NzgIt8SeEP5to3If/SaWmaA6H6ysBr1A==} engines: {node: '>= 10'} cpu: [arm64] os: [darwin] - '@next/swc-darwin-x64@15.4.7': - resolution: {integrity: sha512-qaMnEozKdWezlmh1OGDVFueFv2z9lWTcLvt7e39QA3YOvZHNpN2rLs/IQLwZaUiw2jSvxW07LxMCWtOqsWFNQg==} + '@next/swc-darwin-x64@15.4.8': + resolution: {integrity: sha512-xla6AOfz68a6kq3gRQccWEvFC/VRGJmA/QuSLENSO7CZX5WIEkSz7r1FdXUjtGCQ1c2M+ndUAH7opdfLK1PQbw==} engines: {node: '>= 10'} cpu: [x64] os: [darwin] - '@next/swc-linux-arm64-gnu@15.4.7': - resolution: {integrity: sha512-ny7lODPE7a15Qms8LZiN9wjNWIeI+iAZOFDOnv2pcHStncUr7cr9lD5XF81mdhrBXLUP9yT9RzlmSWKIazWoDw==} + '@next/swc-linux-arm64-gnu@15.4.8': + resolution: {integrity: sha512-y3fmp+1Px/SJD+5ntve5QLZnGLycsxsVPkTzAc3zUiXYSOlTPqT8ynfmt6tt4fSo1tAhDPmryXpYKEAcoAPDJw==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - '@next/swc-linux-arm64-musl@15.4.7': - resolution: {integrity: sha512-4SaCjlFR/2hGJqZLLWycccy1t+wBrE/vyJWnYaZJhUVHccpGLG5q0C+Xkw4iRzUIkE+/dr90MJRUym3s1+vO8A==} + '@next/swc-linux-arm64-musl@15.4.8': + resolution: {integrity: sha512-DX/L8VHzrr1CfwaVjBQr3GWCqNNFgyWJbeQ10Lx/phzbQo3JNAxUok1DZ8JHRGcL6PgMRgj6HylnLNndxn4Z6A==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - '@next/swc-linux-x64-gnu@15.4.7': - resolution: {integrity: sha512-2uNXjxvONyRidg00VwvlTYDwC9EgCGNzPAPYbttIATZRxmOZ3hllk/YYESzHZb65eyZfBR5g9xgCZjRAl9YYGg==} + '@next/swc-linux-x64-gnu@15.4.8': + resolution: {integrity: sha512-9fLAAXKAL3xEIFdKdzG5rUSvSiZTLLTCc6JKq1z04DR4zY7DbAPcRvNm3K1inVhTiQCs19ZRAgUerHiVKMZZIA==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - '@next/swc-linux-x64-musl@15.4.7': - resolution: {integrity: sha512-ceNbPjsFgLscYNGKSu4I6LYaadq2B8tcK116nVuInpHHdAWLWSwVK6CHNvCi0wVS9+TTArIFKJGsEyVD1H+4Kg==} + '@next/swc-linux-x64-musl@15.4.8': + resolution: {integrity: sha512-s45V7nfb5g7dbS7JK6XZDcapicVrMMvX2uYgOHP16QuKH/JA285oy6HcxlKqwUNaFY/UC6EvQ8QZUOo19cBKSA==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - '@next/swc-win32-arm64-msvc@15.4.7': - resolution: {integrity: sha512-pZyxmY1iHlZJ04LUL7Css8bNvsYAMYOY9JRwFA3HZgpaNKsJSowD09Vg2R9734GxAcLJc2KDQHSCR91uD6/AAw==} + '@next/swc-win32-arm64-msvc@15.4.8': + resolution: {integrity: sha512-KjgeQyOAq7t/HzAJcWPGA8X+4WY03uSCZ2Ekk98S9OgCFsb6lfBE3dbUzUuEQAN2THbwYgFfxX2yFTCMm8Kehw==} engines: {node: '>= 10'} cpu: [arm64] os: [win32] - '@next/swc-win32-x64-msvc@15.4.7': - resolution: {integrity: sha512-HjuwPJ7BeRzgl3KrjKqD2iDng0eQIpIReyhpF5r4yeAHFwWRuAhfW92rWv/r3qeQHEwHsLRzFDvMqRjyM5DI6A==} + '@next/swc-win32-x64-msvc@15.4.8': + resolution: {integrity: sha512-Exsmf/+42fWVnLMaZHzshukTBxZrSwuuLKFvqhGHJ+mC1AokqieLY/XzAl3jc/CqhXLqLY3RRjkKJ9YnLPcRWg==} engines: {node: '>= 10'} cpu: [x64] os: [win32] @@ -1977,9 +1977,6 @@ packages: resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} engines: {node: '>=10'} - caniuse-lite@1.0.30001727: - resolution: {integrity: sha512-pB68nIHmbN6L/4C6MH1DokyR3bYqFwjaSs/sWDHGj4CTcFtQUQMuJftVwWkXq7mNWOybD3KhUv3oWHoGxgP14Q==} - caniuse-lite@1.0.30001756: resolution: {integrity: sha512-4HnCNKbMLkLdhJz3TToeVWHSnfJvPaq6vu/eRP0Ahub/07n484XHhBF5AJoSGHdVrS8tKFauUQz8Bp9P7LVx7A==} @@ -3344,8 +3341,8 @@ packages: typescript: optional: true - next@15.4.7: - resolution: {integrity: sha512-OcqRugwF7n7mC8OSYjvsZhhG1AYSvulor1EIUsIkbbEbf1qoE5EbH36Swj8WhF4cHqmDgkiam3z1c1W0J1Wifg==} + next@15.4.8: + resolution: {integrity: sha512-jwOXTz/bo0Pvlf20FSb6VXVeWRssA2vbvq9SdrOPEg9x8E1B27C2rQtvriAn600o9hH61kjrVRexEffv3JybuA==} engines: {node: ^18.18.0 || ^19.8.0 || >= 20.0.0} hasBin: true peerDependencies: @@ -4910,34 +4907,34 @@ snapshots: '@tybys/wasm-util': 0.10.0 optional: true - '@next/env@15.4.7': {} + '@next/env@15.4.8': {} '@next/eslint-plugin-next@15.4.2': dependencies: fast-glob: 3.3.1 - '@next/swc-darwin-arm64@15.4.7': + '@next/swc-darwin-arm64@15.4.8': optional: true - '@next/swc-darwin-x64@15.4.7': + '@next/swc-darwin-x64@15.4.8': optional: true - '@next/swc-linux-arm64-gnu@15.4.7': + '@next/swc-linux-arm64-gnu@15.4.8': optional: true - '@next/swc-linux-arm64-musl@15.4.7': + '@next/swc-linux-arm64-musl@15.4.8': optional: true - '@next/swc-linux-x64-gnu@15.4.7': + '@next/swc-linux-x64-gnu@15.4.8': optional: true - '@next/swc-linux-x64-musl@15.4.7': + '@next/swc-linux-x64-musl@15.4.8': optional: true - '@next/swc-win32-arm64-msvc@15.4.7': + '@next/swc-win32-arm64-msvc@15.4.8': optional: true - '@next/swc-win32-x64-msvc@15.4.7': + '@next/swc-win32-x64-msvc@15.4.8': optional: true '@noble/hashes@1.8.0': {} @@ -6176,8 +6173,6 @@ snapshots: camelcase@6.3.0: {} - caniuse-lite@1.0.30001727: {} - caniuse-lite@1.0.30001756: {} chalk@4.1.2: @@ -7785,40 +7780,40 @@ snapshots: neo-async@2.6.2: {} - next-auth@5.0.0-beta.25(next@15.4.7(@babel/core@7.28.5)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react@19.1.0): + next-auth@5.0.0-beta.25(next@15.4.8(@babel/core@7.28.5)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react@19.1.0): dependencies: '@auth/core': 0.37.2 - next: 15.4.7(@babel/core@7.28.5)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + next: 15.4.8(@babel/core@7.28.5)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) react: 19.1.0 - next-intl@4.3.4(next@15.4.7(@babel/core@7.28.5)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react@19.1.0)(typescript@5.8.3): + next-intl@4.3.4(next@15.4.8(@babel/core@7.28.5)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react@19.1.0)(typescript@5.8.3): dependencies: '@formatjs/intl-localematcher': 0.5.10 negotiator: 1.0.0 - next: 15.4.7(@babel/core@7.28.5)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + next: 15.4.8(@babel/core@7.28.5)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) react: 19.1.0 use-intl: 4.3.4(react@19.1.0) optionalDependencies: typescript: 5.8.3 - next@15.4.7(@babel/core@7.28.5)(react-dom@19.1.0(react@19.1.0))(react@19.1.0): + next@15.4.8(@babel/core@7.28.5)(react-dom@19.1.0(react@19.1.0))(react@19.1.0): dependencies: - '@next/env': 15.4.7 + '@next/env': 15.4.8 '@swc/helpers': 0.5.15 - caniuse-lite: 1.0.30001727 + caniuse-lite: 1.0.30001756 postcss: 8.4.31 react: 19.1.0 react-dom: 19.1.0(react@19.1.0) styled-jsx: 5.1.6(@babel/core@7.28.5)(react@19.1.0) optionalDependencies: - '@next/swc-darwin-arm64': 15.4.7 - '@next/swc-darwin-x64': 15.4.7 - '@next/swc-linux-arm64-gnu': 15.4.7 - '@next/swc-linux-arm64-musl': 15.4.7 - '@next/swc-linux-x64-gnu': 15.4.7 - '@next/swc-linux-x64-musl': 15.4.7 - '@next/swc-win32-arm64-msvc': 15.4.7 - '@next/swc-win32-x64-msvc': 15.4.7 + '@next/swc-darwin-arm64': 15.4.8 + '@next/swc-darwin-x64': 15.4.8 + '@next/swc-linux-arm64-gnu': 15.4.8 + '@next/swc-linux-arm64-musl': 15.4.8 + '@next/swc-linux-x64-gnu': 15.4.8 + '@next/swc-linux-x64-musl': 15.4.8 + '@next/swc-win32-arm64-msvc': 15.4.8 + '@next/swc-win32-x64-msvc': 15.4.8 sharp: 0.34.3 transitivePeerDependencies: - '@babel/core' @@ -8263,7 +8258,7 @@ snapshots: dependencies: color: 4.2.3 detect-libc: 2.0.4 - semver: 7.7.2 + semver: 7.7.3 optionalDependencies: '@img/sharp-darwin-arm64': 0.34.3 '@img/sharp-darwin-x64': 0.34.3