diff --git a/.github/workflows/dev.yml b/.github/workflows/dev.yml index 6779975..9f94786 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,47 @@ jobs: - name: Build app run: pnpm build - # 2️⃣ Build & push Docker image + 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@master + 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 @@ -85,7 +124,6 @@ jobs: build-args: | NEXT_PUBLIC_ENV=develop - # 3️⃣ Deploy DEV deploy-dev: runs-on: self-hosted needs: docker-build-push @@ -109,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 + + 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" - } -} 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 +} 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