Compare commits
26 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 646d615e76 | |||
| 51409099fc | |||
| 22cd20e639 | |||
| e7cc1c8ca5 | |||
| 0ccb15a929 | |||
| a94ddcfbb2 | |||
| d3a9af140c | |||
| 0dc3ba0da4 | |||
| 1a94465dba | |||
| 7e256025ea | |||
| e843de42da | |||
| 4d1b2231e3 | |||
| 71f47f9037 | |||
| 79d41b6a73 | |||
| 6b7236ba97 | |||
| 40a95b5353 | |||
| 7329e00125 | |||
| 94be60ba4e | |||
| a8bc039c02 | |||
| 653deb7995 | |||
| 61f65107f2 | |||
| 664f165234 | |||
| f07e44016a | |||
| cc3ec8f0c2 | |||
| c9db75c945 | |||
| bb8665212a |
12
.dockerignore
Normal file
12
.dockerignore
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
node_modules
|
||||||
|
.next
|
||||||
|
.git
|
||||||
|
.npmrc
|
||||||
|
dist
|
||||||
|
build
|
||||||
|
out
|
||||||
|
coverage
|
||||||
|
.vercel
|
||||||
|
.turbo
|
||||||
|
*.log
|
||||||
|
.DS_Store
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
name: Code Quality
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [main]
|
|
||||||
pull_request:
|
|
||||||
branches: [main]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
lint-and-build:
|
|
||||||
runs-on: docker
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Install pnpm
|
|
||||||
uses: pnpm/action-setup@v4
|
|
||||||
with:
|
|
||||||
version: 10
|
|
||||||
|
|
||||||
- name: Set up Node.js
|
|
||||||
uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node_version: 20
|
|
||||||
cache: 'pnpm'
|
|
||||||
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install --frozen-lockfile
|
|
||||||
env:
|
|
||||||
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
||||||
|
|
||||||
- name: Lint
|
|
||||||
run: pnpm lint
|
|
||||||
|
|
||||||
- name: Test
|
|
||||||
run: pnpm test
|
|
||||||
|
|
||||||
- name: Build
|
|
||||||
run: pnpm build
|
|
||||||
156
.gitea/workflows/pipeline.yml
Normal file
156
.gitea/workflows/pipeline.yml
Normal file
@@ -0,0 +1,156 @@
|
|||||||
|
name: Monorepo Pipeline
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- 'v*'
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.workflow }}-${{ github.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
qa:
|
||||||
|
name: 🧪 Quality Assurance
|
||||||
|
runs-on: docker
|
||||||
|
container:
|
||||||
|
image: catthehacker/ubuntu:act-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Install pnpm
|
||||||
|
uses: pnpm/action-setup@v4
|
||||||
|
with:
|
||||||
|
version: 10
|
||||||
|
|
||||||
|
- name: Set up Node.js
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node_version: 20
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
env:
|
||||||
|
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||||
|
|
||||||
|
- name: Lint
|
||||||
|
run: pnpm lint
|
||||||
|
|
||||||
|
- name: Test
|
||||||
|
run: pnpm test
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
run: pnpm build
|
||||||
|
|
||||||
|
release:
|
||||||
|
name: 🚀 Release
|
||||||
|
needs: qa
|
||||||
|
if: startsWith(github.ref, 'refs/tags/v')
|
||||||
|
runs-on: docker
|
||||||
|
container:
|
||||||
|
image: catthehacker/ubuntu:act-latest
|
||||||
|
env:
|
||||||
|
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Install pnpm
|
||||||
|
uses: pnpm/action-setup@v4
|
||||||
|
with:
|
||||||
|
version: 10
|
||||||
|
|
||||||
|
- name: Set up Node.js
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node_version: 20
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
|
||||||
|
- name: 🏷️ Release Packages (Tag-Driven)
|
||||||
|
run: |
|
||||||
|
echo "🏷️ Tag detected [${{ github.ref_name }}], performing sync release..."
|
||||||
|
pnpm sync-versions
|
||||||
|
pnpm release:tag
|
||||||
|
|
||||||
|
build-images:
|
||||||
|
name: 🐳 Build & Push Images
|
||||||
|
needs: qa
|
||||||
|
if: startsWith(github.ref, 'refs/tags/v')
|
||||||
|
runs-on: docker
|
||||||
|
container:
|
||||||
|
image: catthehacker/ubuntu:act-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: 🐳 Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v3
|
||||||
|
|
||||||
|
- name: 🔐 Registry Login
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
registry: registry.infra.mintel.me
|
||||||
|
username: ${{ secrets.REGISTRY_USER }}
|
||||||
|
password: ${{ secrets.REGISTRY_PASS }}
|
||||||
|
|
||||||
|
- name: 🏗️ Build & Push Nextjs Build-Base
|
||||||
|
uses: docker/build-push-action@v5
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
file: packages/infra/docker/Dockerfile.nextjs
|
||||||
|
platforms: linux/arm64
|
||||||
|
pull: true
|
||||||
|
push: true
|
||||||
|
secrets: |
|
||||||
|
NPM_TOKEN=${{ secrets.NPM_TOKEN }}
|
||||||
|
tags: |
|
||||||
|
registry.infra.mintel.me/mintel/nextjs:${{ github.ref_name }}
|
||||||
|
registry.infra.mintel.me/mintel/nextjs:latest
|
||||||
|
|
||||||
|
- name: 🏗️ Build & Push Production Runtime
|
||||||
|
uses: docker/build-push-action@v5
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
file: packages/infra/docker/Dockerfile.runtime
|
||||||
|
platforms: linux/arm64
|
||||||
|
pull: true
|
||||||
|
push: true
|
||||||
|
secrets: |
|
||||||
|
NPM_TOKEN=${{ secrets.NPM_TOKEN }}
|
||||||
|
tags: |
|
||||||
|
registry.infra.mintel.me/mintel/runtime:${{ github.ref_name }}
|
||||||
|
registry.infra.mintel.me/mintel/runtime:latest
|
||||||
|
|
||||||
|
- name: 🏗️ Build & Push Gatekeeper (Product)
|
||||||
|
uses: docker/build-push-action@v5
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
file: packages/infra/docker/Dockerfile.gatekeeper
|
||||||
|
platforms: linux/arm64
|
||||||
|
pull: true
|
||||||
|
push: true
|
||||||
|
secrets: |
|
||||||
|
NPM_TOKEN=${{ secrets.NPM_TOKEN }}
|
||||||
|
tags: |
|
||||||
|
registry.infra.mintel.me/mintel/gatekeeper:${{ github.ref_name }}
|
||||||
|
registry.infra.mintel.me/mintel/gatekeeper:latest
|
||||||
|
|
||||||
|
- name: 🏗️ Build & Push Directus (Base)
|
||||||
|
uses: docker/build-push-action@v5
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
file: packages/infra/docker/Dockerfile.directus
|
||||||
|
platforms: linux/arm64
|
||||||
|
pull: true
|
||||||
|
push: true
|
||||||
|
secrets: |
|
||||||
|
NPM_TOKEN=${{ secrets.NPM_TOKEN }}
|
||||||
|
tags: |
|
||||||
|
registry.infra.mintel.me/mintel/directus:${{ github.ref_name }}
|
||||||
|
registry.infra.mintel.me/mintel/directus:latest
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
name: Release Packages
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
tags:
|
|
||||||
- 'v*'
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
release:
|
|
||||||
runs-on: docker
|
|
||||||
env:
|
|
||||||
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
fetch-depth: 0
|
|
||||||
|
|
||||||
- name: Install pnpm
|
|
||||||
uses: pnpm/action-setup@v4
|
|
||||||
with:
|
|
||||||
version: 10
|
|
||||||
|
|
||||||
- name: Set up Node.js
|
|
||||||
uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node_version: 20
|
|
||||||
cache: 'pnpm'
|
|
||||||
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install --frozen-lockfile
|
|
||||||
|
|
||||||
- name: Release Packages
|
|
||||||
run: |
|
|
||||||
if [[ "${{ github.ref_type }}" == "tag" ]]; then
|
|
||||||
echo "🏷️ Tag detected, performing sync release..."
|
|
||||||
pnpm sync-versions
|
|
||||||
pnpm release:tag
|
|
||||||
else
|
|
||||||
echo "🚀 Push detected, looking for changesets..."
|
|
||||||
pnpm release
|
|
||||||
fi
|
|
||||||
31
apps/sample-website/.env.example
Normal file
31
apps/sample-website/.env.example
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
# Project
|
||||||
|
PROJECT_NAME=sample-website
|
||||||
|
PROJECT_COLOR=#82ed20
|
||||||
|
|
||||||
|
# Authentication
|
||||||
|
GATEKEEPER_PASSWORD=mintel
|
||||||
|
AUTH_COOKIE_NAME=mintel_gatekeeper_session
|
||||||
|
|
||||||
|
# Host Config (Local)
|
||||||
|
TRAEFIK_HOST=sample-website.localhost
|
||||||
|
DIRECTUS_HOST=cms.sample-website.localhost
|
||||||
|
|
||||||
|
# Next.js
|
||||||
|
NEXT_PUBLIC_BASE_URL=http://sample-website.localhost
|
||||||
|
|
||||||
|
# Directus
|
||||||
|
DIRECTUS_URL=http://localhost:8055
|
||||||
|
DIRECTUS_KEY=sample-key-123
|
||||||
|
DIRECTUS_SECRET=sample-secret-123
|
||||||
|
DIRECTUS_ADMIN_EMAIL=admin@mintel.me
|
||||||
|
DIRECTUS_ADMIN_PASSWORD=mintel-admin-pass
|
||||||
|
DIRECTUS_DB_NAME=directus
|
||||||
|
DIRECTUS_DB_USER=directus
|
||||||
|
DIRECTUS_DB_PASSWORD=mintel-db-pass
|
||||||
|
|
||||||
|
# Sentry / Glitchtip
|
||||||
|
SENTRY_DSN=
|
||||||
|
|
||||||
|
# Analytics (Umami)
|
||||||
|
NEXT_PUBLIC_UMAMI_WEBSITE_ID=
|
||||||
|
NEXT_PUBLIC_UMAMI_SCRIPT_URL=https://analytics.infra.mintel.me/script.js
|
||||||
34
apps/sample-website/.gitignore
vendored
Normal file
34
apps/sample-website/.gitignore
vendored
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
# dependencies
|
||||||
|
/node_modules
|
||||||
|
/.pnpm-debug.log*
|
||||||
|
|
||||||
|
# next.js
|
||||||
|
/.next/
|
||||||
|
/out/
|
||||||
|
|
||||||
|
# production
|
||||||
|
/build
|
||||||
|
|
||||||
|
# misc
|
||||||
|
.DS_Store
|
||||||
|
*.pem
|
||||||
|
|
||||||
|
# debug
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
|
||||||
|
# local env files
|
||||||
|
.env*.local
|
||||||
|
|
||||||
|
# vercel
|
||||||
|
.vercel
|
||||||
|
|
||||||
|
# typescript
|
||||||
|
*.tsbuildinfo
|
||||||
|
next-env.d.ts
|
||||||
|
|
||||||
|
# directus
|
||||||
|
/directus/uploads
|
||||||
|
/directus/extensions
|
||||||
|
/.env
|
||||||
38
apps/sample-website/Dockerfile
Normal file
38
apps/sample-website/Dockerfile
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
# Start from the pre-built Nextjs Base image
|
||||||
|
FROM registry.infra.mintel.me/mintel/nextjs:latest AS builder
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Build-time environment variables for Next.js
|
||||||
|
ARG NEXT_PUBLIC_BASE_URL
|
||||||
|
ARG NEXT_PUBLIC_UMAMI_WEBSITE_ID
|
||||||
|
ARG NEXT_PUBLIC_UMAMI_SCRIPT_URL
|
||||||
|
ARG NEXT_PUBLIC_TARGET
|
||||||
|
ARG DIRECTUS_URL
|
||||||
|
|
||||||
|
ENV NEXT_PUBLIC_BASE_URL=$NEXT_PUBLIC_BASE_URL
|
||||||
|
ENV NEXT_PUBLIC_UMAMI_WEBSITE_ID=$NEXT_PUBLIC_UMAMI_WEBSITE_ID
|
||||||
|
ENV NEXT_PUBLIC_UMAMI_SCRIPT_URL=$NEXT_PUBLIC_UMAMI_SCRIPT_URL
|
||||||
|
ENV NEXT_PUBLIC_TARGET=$NEXT_PUBLIC_TARGET
|
||||||
|
ENV DIRECTUS_URL=$DIRECTUS_URL
|
||||||
|
|
||||||
|
# Build the specific application
|
||||||
|
RUN pnpm --filter sample-website build
|
||||||
|
|
||||||
|
# Production runner image
|
||||||
|
FROM registry.infra.mintel.me/mintel/runtime:latest AS runner
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
COPY --from=builder /app/apps/sample-website/public ./apps/sample-website/public
|
||||||
|
|
||||||
|
# Set the correct permission for prerender cache
|
||||||
|
RUN mkdir -p apps/sample-website/.next && chown nextjs:nodejs apps/sample-website/.next
|
||||||
|
|
||||||
|
# Copy standalone output and static files from the monorepo path
|
||||||
|
COPY --from=builder --chown=nextjs:nodejs /app/apps/sample-website/.next/standalone ./
|
||||||
|
COPY --from=builder --chown=nextjs:nodejs /app/apps/sample-website/.next/static ./apps/sample-website/.next/static
|
||||||
|
|
||||||
|
USER nextjs
|
||||||
|
|
||||||
|
# server.js in monorepo standalone is created for each app
|
||||||
|
CMD ["node", "apps/sample-website/server.js"]
|
||||||
0
apps/sample-website/directus/extensions/.gitkeep
Normal file
0
apps/sample-website/directus/extensions/.gitkeep
Normal file
0
apps/sample-website/directus/uploads/.gitkeep
Normal file
0
apps/sample-website/directus/uploads/.gitkeep
Normal file
71
apps/sample-website/docker-compose.yml
Normal file
71
apps/sample-website/docker-compose.yml
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
services:
|
||||||
|
app:
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
args:
|
||||||
|
NEXT_PUBLIC_BASE_URL: ${NEXT_PUBLIC_BASE_URL:-http://localhost:3000}
|
||||||
|
NEXT_PUBLIC_UMAMI_WEBSITE_ID: ${NEXT_PUBLIC_UMAMI_WEBSITE_ID}
|
||||||
|
NEXT_PUBLIC_UMAMI_SCRIPT_URL: ${NEXT_PUBLIC_UMAMI_SCRIPT_URL}
|
||||||
|
NEXT_PUBLIC_TARGET: ${TARGET:-development}
|
||||||
|
DIRECTUS_URL: ${DIRECTUS_URL:-http://directus:8055}
|
||||||
|
restart: always
|
||||||
|
networks:
|
||||||
|
- infra
|
||||||
|
env_file:
|
||||||
|
- .env
|
||||||
|
ports:
|
||||||
|
- "3000:3000"
|
||||||
|
labels:
|
||||||
|
- "traefik.enable=true"
|
||||||
|
- "traefik.http.routers.sample-website.rule=Host(`${TRAEFIK_HOST:-sample-website.localhost}`)"
|
||||||
|
- "traefik.http.services.sample-website.loadbalancer.server.port=3000"
|
||||||
|
|
||||||
|
directus:
|
||||||
|
image: registry.infra.mintel.me/mintel/directus:latest
|
||||||
|
restart: always
|
||||||
|
networks:
|
||||||
|
- infra
|
||||||
|
env_file:
|
||||||
|
- .env
|
||||||
|
environment:
|
||||||
|
KEY: ${DIRECTUS_KEY:-mintel-key}
|
||||||
|
SECRET: ${DIRECTUS_SECRET:-mintel-secret}
|
||||||
|
ADMIN_EMAIL: ${DIRECTUS_ADMIN_EMAIL:-admin@mintel.me}
|
||||||
|
ADMIN_PASSWORD: ${DIRECTUS_ADMIN_PASSWORD:-mintel-admin}
|
||||||
|
DB_CLIENT: 'pg'
|
||||||
|
DB_HOST: 'directus-db'
|
||||||
|
DB_PORT: '5432'
|
||||||
|
DB_DATABASE: ${DIRECTUS_DB_NAME:-directus}
|
||||||
|
DB_USER: ${DIRECTUS_DB_USER:-directus}
|
||||||
|
DB_PASSWORD: ${DIRECTUS_DB_PASSWORD:-mintel-db-pass}
|
||||||
|
WEBSOCKETS_ENABLED: 'true'
|
||||||
|
PUBLIC_URL: ${DIRECTUS_URL:-http://localhost:8055}
|
||||||
|
ports:
|
||||||
|
- "8055:8055"
|
||||||
|
volumes:
|
||||||
|
- ./directus/uploads:/directus/uploads
|
||||||
|
- ./directus/extensions:/directus/extensions
|
||||||
|
labels:
|
||||||
|
- "traefik.enable=true"
|
||||||
|
- "traefik.http.routers.sample-website-directus.rule=Host(`${DIRECTUS_HOST:-cms.sample-website.localhost}`)"
|
||||||
|
- "traefik.http.services.sample-website-directus.loadbalancer.server.port=8055"
|
||||||
|
|
||||||
|
directus-db:
|
||||||
|
image: postgres:15-alpine
|
||||||
|
restart: always
|
||||||
|
networks:
|
||||||
|
- infra
|
||||||
|
environment:
|
||||||
|
POSTGRES_DB: ${DIRECTUS_DB_NAME:-directus}
|
||||||
|
POSTGRES_USER: ${DIRECTUS_DB_USER:-directus}
|
||||||
|
POSTGRES_PASSWORD: ${DIRECTUS_DB_PASSWORD:-mintel-db-pass}
|
||||||
|
volumes:
|
||||||
|
- directus-db-data:/var/lib/postgresql/data
|
||||||
|
|
||||||
|
networks:
|
||||||
|
infra:
|
||||||
|
external: true
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
directus-db-data:
|
||||||
5
apps/sample-website/messages/en.json
Normal file
5
apps/sample-website/messages/en.json
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"Index": {
|
||||||
|
"title": "Welcome"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,25 +4,36 @@
|
|||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "next dev",
|
"dev": "mintel dev",
|
||||||
|
"dev:local": "mintel dev --local",
|
||||||
"build": "next build",
|
"build": "next build",
|
||||||
"start": "next start",
|
"start": "next start",
|
||||||
"lint": "next lint",
|
"lint": "next lint",
|
||||||
"test": "vitest run"
|
"typecheck": "tsc --noEmit",
|
||||||
|
"test": "vitest run --passWithNoTests",
|
||||||
|
"cms:bootstrap": "mintel directus bootstrap",
|
||||||
|
"cms:push:testing": "mintel directus sync push testing",
|
||||||
|
"cms:pull:testing": "mintel directus sync pull testing",
|
||||||
|
"cms:push:staging": "mintel directus sync push staging",
|
||||||
|
"cms:pull:staging": "mintel directus sync pull staging",
|
||||||
|
"cms:push:prod": "mintel directus sync push production",
|
||||||
|
"cms:pull:prod": "mintel directus sync pull production",
|
||||||
|
"pagespeed:test": "mintel pagespeed"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@mintel/next-utils": "workspace:*",
|
||||||
"next": "15.1.6",
|
"next": "15.1.6",
|
||||||
|
"next-intl": "^4.8.2",
|
||||||
"react": "^19.0.0",
|
"react": "^19.0.0",
|
||||||
"react-dom": "^19.0.0",
|
"react-dom": "^19.0.0"
|
||||||
"@mintel/next-utils": "workspace:*"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@mintel/eslint-config": "workspace:*",
|
||||||
|
"@mintel/next-config": "workspace:*",
|
||||||
|
"@mintel/tsconfig": "workspace:*",
|
||||||
"@types/node": "^20.0.0",
|
"@types/node": "^20.0.0",
|
||||||
"@types/react": "^19.0.0",
|
"@types/react": "^19.0.0",
|
||||||
"@types/react-dom": "^19.0.0",
|
"@types/react-dom": "^19.0.0",
|
||||||
"typescript": "^5.0.0",
|
"typescript": "^5.0.0"
|
||||||
"@mintel/tsconfig": "workspace:*",
|
|
||||||
"@mintel/eslint-config": "workspace:*",
|
|
||||||
"@mintel/next-config": "workspace:*"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
7
apps/sample-website/src/i18n/request.ts
Normal file
7
apps/sample-website/src/i18n/request.ts
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
import { createMintelI18nRequestConfig } from "@mintel/next-utils";
|
||||||
|
|
||||||
|
export default createMintelI18nRequestConfig(
|
||||||
|
["en"],
|
||||||
|
"en",
|
||||||
|
(locale) => import(`../../messages/${locale}.json`),
|
||||||
|
);
|
||||||
@@ -10,7 +10,76 @@ const program = new Command();
|
|||||||
program
|
program
|
||||||
.name("mintel")
|
.name("mintel")
|
||||||
.description("CLI for Mintel monorepo management")
|
.description("CLI for Mintel monorepo management")
|
||||||
.version("1.0.0");
|
.version("1.0.1");
|
||||||
|
|
||||||
|
program
|
||||||
|
.command("dev")
|
||||||
|
.description("Start the development environment (Docker stack)")
|
||||||
|
.option("-l, --local", "Run Next.js locally instead of in Docker")
|
||||||
|
.action(async (options) => {
|
||||||
|
const { execSync } = await import("child_process");
|
||||||
|
console.log(chalk.blue("🚀 Starting Development Environment..."));
|
||||||
|
|
||||||
|
if (options.local) {
|
||||||
|
console.log(chalk.cyan("Running Next.js locally..."));
|
||||||
|
execSync("next dev", { stdio: "inherit" });
|
||||||
|
} else {
|
||||||
|
console.log(chalk.cyan("Starting Docker stack (App, Directus, DB)..."));
|
||||||
|
// Ensure network exists
|
||||||
|
try {
|
||||||
|
execSync("docker network create infra", { stdio: "ignore" });
|
||||||
|
} catch (e) {}
|
||||||
|
|
||||||
|
console.log(
|
||||||
|
chalk.yellow(`
|
||||||
|
📱 App: http://localhost:3000
|
||||||
|
🗄️ CMS: http://localhost:8055/admin
|
||||||
|
🚦 Traefik: http://localhost:8080
|
||||||
|
`),
|
||||||
|
);
|
||||||
|
execSync(
|
||||||
|
"docker-compose down --remove-orphans && docker-compose up app directus directus-db",
|
||||||
|
{ stdio: "inherit" },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const directus = program
|
||||||
|
.command("directus")
|
||||||
|
.description("Directus management commands");
|
||||||
|
|
||||||
|
directus
|
||||||
|
.command("bootstrap")
|
||||||
|
.description("Setup Directus branding and settings")
|
||||||
|
.action(async () => {
|
||||||
|
const { execSync } = await import("child_process");
|
||||||
|
console.log(chalk.blue("🎨 Bootstrapping Directus..."));
|
||||||
|
execSync("npx tsx --env-file=.env scripts/setup-directus.ts", {
|
||||||
|
stdio: "inherit",
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
directus
|
||||||
|
.command("sync <action> <env>")
|
||||||
|
.description("Sync Directus data (push/pull) for a specific environment")
|
||||||
|
.action(async (action, env) => {
|
||||||
|
const { execSync } = await import("child_process");
|
||||||
|
console.log(
|
||||||
|
chalk.blue(`📥 Executing Directus sync: ${action} -> ${env}...`),
|
||||||
|
);
|
||||||
|
execSync(`./scripts/sync-directus.sh ${action} ${env}`, {
|
||||||
|
stdio: "inherit",
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
program
|
||||||
|
.command("pagespeed")
|
||||||
|
.description("Run PageSpeed (Lighthouse) tests")
|
||||||
|
.action(async () => {
|
||||||
|
const { execSync } = await import("child_process");
|
||||||
|
console.log(chalk.blue("⚡ Running PageSpeed tests..."));
|
||||||
|
execSync("npx tsx ./scripts/pagespeed-sitemap.ts", { stdio: "inherit" });
|
||||||
|
});
|
||||||
|
|
||||||
program
|
program
|
||||||
.command("init <path>")
|
.command("init <path>")
|
||||||
@@ -34,10 +103,21 @@ program
|
|||||||
private: true,
|
private: true,
|
||||||
type: "module",
|
type: "module",
|
||||||
scripts: {
|
scripts: {
|
||||||
dev: "next dev",
|
dev: "mintel dev",
|
||||||
|
"dev:local": "mintel dev --local",
|
||||||
build: "next build",
|
build: "next build",
|
||||||
start: "next start",
|
start: "next start",
|
||||||
lint: "next lint",
|
lint: "next lint",
|
||||||
|
typecheck: "tsc --noEmit",
|
||||||
|
test: "vitest run --passWithNoTests",
|
||||||
|
"directus:bootstrap": "mintel directus bootstrap",
|
||||||
|
"directus:push:testing": "mintel directus sync push testing",
|
||||||
|
"directus:pull:testing": "mintel directus sync pull testing",
|
||||||
|
"directus:push:staging": "mintel directus sync push staging",
|
||||||
|
"directus:pull:staging": "mintel directus sync pull staging",
|
||||||
|
"directus:push:prod": "mintel directus sync push production",
|
||||||
|
"directus:pull:prod": "mintel directus sync pull production",
|
||||||
|
"pagespeed:test": "mintel pagespeed",
|
||||||
},
|
},
|
||||||
dependencies: {
|
dependencies: {
|
||||||
next: "15.1.6",
|
next: "15.1.6",
|
||||||
@@ -238,34 +318,56 @@ export default function Home() {
|
|||||||
// Copy infra templates
|
// Copy infra templates
|
||||||
const infraPath = path.resolve(__dirname, "../../infra");
|
const infraPath = path.resolve(__dirname, "../../infra");
|
||||||
if (await fs.pathExists(infraPath)) {
|
if (await fs.pathExists(infraPath)) {
|
||||||
await fs.copy(
|
// Setup Dockerfile from template
|
||||||
path.join(infraPath, "docker/Dockerfile.nextjs"),
|
const templatePath = path.join(
|
||||||
path.join(fullPath, "Dockerfile"),
|
infraPath,
|
||||||
|
"docker/Dockerfile.app-template",
|
||||||
);
|
);
|
||||||
await fs.copy(
|
if (await fs.pathExists(templatePath)) {
|
||||||
path.join(infraPath, "docker/docker-compose.template.yml"),
|
let dockerfile = await fs.readFile(templatePath, "utf8");
|
||||||
path.join(fullPath, "docker-compose.yml"),
|
dockerfile = dockerfile.replace(/\$\{APP_NAME:-app\}/g, projectName);
|
||||||
|
await fs.writeFile(path.join(fullPath, "Dockerfile"), dockerfile);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setup docker-compose from template
|
||||||
|
const composeTemplatePath = path.join(
|
||||||
|
infraPath,
|
||||||
|
"docker/docker-compose.template.yml",
|
||||||
);
|
);
|
||||||
|
if (await fs.pathExists(composeTemplatePath)) {
|
||||||
|
let compose = await fs.readFile(composeTemplatePath, "utf8");
|
||||||
|
compose = compose.replace(/\$\{APP_NAME:-app\}/g, projectName);
|
||||||
|
compose = compose.replace(/\$\{PROJECT_NAME:-app\}/g, projectName);
|
||||||
|
await fs.writeFile(
|
||||||
|
path.join(fullPath, "docker-compose.yml"),
|
||||||
|
compose,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
await fs.ensureDir(path.join(fullPath, ".gitea/workflows"));
|
await fs.ensureDir(path.join(fullPath, ".gitea/workflows"));
|
||||||
await fs.copy(
|
const deployActionPath = path.join(
|
||||||
path.join(infraPath, "gitea/deploy-action.yml"),
|
infraPath,
|
||||||
path.join(fullPath, ".gitea/workflows/deploy.yml"),
|
"gitea/deploy-action.yml",
|
||||||
);
|
);
|
||||||
|
if (await fs.pathExists(deployActionPath)) {
|
||||||
|
await fs.copy(
|
||||||
|
deployActionPath,
|
||||||
|
path.join(fullPath, ".gitea/workflows/deploy.yml"),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Create Directus structure
|
// Create Directus structure
|
||||||
await fs.ensureDir(path.join(fullPath, "directus/uploads"));
|
await fs.ensureDir(path.join(fullPath, "directus/uploads"));
|
||||||
await fs.ensureDir(path.join(fullPath, "directus/extensions"));
|
await fs.ensureDir(path.join(fullPath, "directus/extensions"));
|
||||||
await fs.writeFile(
|
await fs.writeFile(path.join(fullPath, "directus/uploads/.gitkeep"), "");
|
||||||
path.join(fullPath, "directus/uploads/.gitkeep"),
|
await fs.writeFile(
|
||||||
"",
|
path.join(fullPath, "directus/extensions/.gitkeep"),
|
||||||
);
|
"",
|
||||||
await fs.writeFile(
|
);
|
||||||
path.join(fullPath, "directus/extensions/.gitkeep"),
|
|
||||||
"",
|
|
||||||
);
|
|
||||||
|
|
||||||
// Create .env.example
|
// Create .env.example
|
||||||
const envExample = `# Project
|
const envExample = `# Project
|
||||||
PROJECT_NAME=${projectName}
|
PROJECT_NAME=${projectName}
|
||||||
PROJECT_COLOR=#82ed20
|
PROJECT_COLOR=#82ed20
|
||||||
|
|
||||||
@@ -297,14 +399,13 @@ SENTRY_DSN=
|
|||||||
NEXT_PUBLIC_UMAMI_WEBSITE_ID=
|
NEXT_PUBLIC_UMAMI_WEBSITE_ID=
|
||||||
NEXT_PUBLIC_UMAMI_SCRIPT_URL=https://analytics.infra.mintel.me/script.js
|
NEXT_PUBLIC_UMAMI_SCRIPT_URL=https://analytics.infra.mintel.me/script.js
|
||||||
`;
|
`;
|
||||||
await fs.writeFile(path.join(fullPath, ".env.example"), envExample);
|
await fs.writeFile(path.join(fullPath, ".env.example"), envExample);
|
||||||
|
|
||||||
// Copy premium templates (globals.css, lib/directus.ts, scripts/setup-directus.ts)
|
// Copy premium templates (globals.css, lib/directus.ts, scripts/setup-directus.ts)
|
||||||
const templatePath = path.join(infraPath, "templates/website");
|
const templatePath = path.join(infraPath, "templates/website");
|
||||||
if (await fs.pathExists(templatePath)) {
|
if (await fs.pathExists(templatePath)) {
|
||||||
console.log(chalk.blue("Applying premium templates..."));
|
console.log(chalk.blue("Applying premium templates..."));
|
||||||
await fs.copy(templatePath, fullPath, { overwrite: true });
|
await fs.copy(templatePath, fullPath, { overwrite: true });
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(
|
console.log(
|
||||||
|
|||||||
@@ -2,6 +2,9 @@ import js from "@eslint/js";
|
|||||||
import tseslint from "typescript-eslint";
|
import tseslint from "typescript-eslint";
|
||||||
|
|
||||||
export default tseslint.config(
|
export default tseslint.config(
|
||||||
|
{
|
||||||
|
ignores: ["**/dist/**", "**/node_modules/**", "**/.next/**"],
|
||||||
|
},
|
||||||
js.configs.recommended,
|
js.configs.recommended,
|
||||||
...tseslint.configs.recommended,
|
...tseslint.configs.recommended,
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -10,15 +10,31 @@ const compat = new FlatCompat({
|
|||||||
});
|
});
|
||||||
|
|
||||||
export const nextConfig = [
|
export const nextConfig = [
|
||||||
|
{
|
||||||
|
ignores: [
|
||||||
|
"**/dist/**",
|
||||||
|
"**/build/**",
|
||||||
|
"**/out/**",
|
||||||
|
"**/coverage/**",
|
||||||
|
"**/.next/**",
|
||||||
|
"**/node_modules/**",
|
||||||
|
"**/.gitea/**",
|
||||||
|
"**/.changeset/**",
|
||||||
|
"**/.vercel/**",
|
||||||
|
],
|
||||||
|
},
|
||||||
...compat.extends("next/core-web-vitals", "next/typescript"),
|
...compat.extends("next/core-web-vitals", "next/typescript"),
|
||||||
{
|
{
|
||||||
rules: {
|
rules: {
|
||||||
"@typescript-eslint/no-explicit-any": "off",
|
"@typescript-eslint/no-explicit-any": "off",
|
||||||
"@typescript-eslint/no-unused-vars": ["warn", { "argsIgnorePattern": "^_" }],
|
"@typescript-eslint/no-unused-vars": [
|
||||||
|
"warn",
|
||||||
|
{ argsIgnorePattern: "^_" },
|
||||||
|
],
|
||||||
"@typescript-eslint/no-require-imports": "off",
|
"@typescript-eslint/no-require-imports": "off",
|
||||||
"prefer-const": "warn",
|
"prefer-const": "warn",
|
||||||
"react/no-unescaped-entities": "off",
|
"react/no-unescaped-entities": "off",
|
||||||
"@next/next/no-img-element": "warn"
|
"@next/next/no-img-element": "warn",
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
];
|
];
|
||||||
|
|||||||
5
packages/gatekeeper/messages/en.json
Normal file
5
packages/gatekeeper/messages/en.json
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"LoginPage": {
|
||||||
|
"title": "Gatekeeper"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,9 +11,11 @@
|
|||||||
"test": "vitest run"
|
"test": "vitest run"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@mintel/next-utils": "workspace:*",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
"lucide-react": "^0.474.0",
|
"lucide-react": "^0.474.0",
|
||||||
"next": "15.1.6",
|
"next": "15.1.6",
|
||||||
|
"next-intl": "^4.8.2",
|
||||||
"react": "^19.0.0",
|
"react": "^19.0.0",
|
||||||
"react-dom": "^19.0.0",
|
"react-dom": "^19.0.0",
|
||||||
"tailwind-merge": "^2.6.0"
|
"tailwind-merge": "^2.6.0"
|
||||||
|
|||||||
7
packages/gatekeeper/src/i18n/request.ts
Normal file
7
packages/gatekeeper/src/i18n/request.ts
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
import { createMintelI18nRequestConfig } from "@mintel/next-utils";
|
||||||
|
|
||||||
|
export default createMintelI18nRequestConfig(
|
||||||
|
["en"],
|
||||||
|
"en",
|
||||||
|
(locale) => import(`../../messages/${locale}.json`),
|
||||||
|
);
|
||||||
@@ -1,8 +1,10 @@
|
|||||||
export default {
|
const config = {
|
||||||
extends: ["@commitlint/config-conventional"],
|
extends: ["@commitlint/config-conventional"],
|
||||||
rules: {
|
rules: {
|
||||||
"header-max-length": [2, "always", 150],
|
"header-max-length": [2, "always", 250],
|
||||||
"subject-case": [0],
|
"subject-case": [0],
|
||||||
"subject-full-stop": [0],
|
"subject-full-stop": [0],
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export default config;
|
||||||
|
|||||||
@@ -1,4 +1,22 @@
|
|||||||
export default {
|
import path from "path";
|
||||||
"*.{js,jsx,ts,tsx}": ["eslint --fix", "prettier --write"],
|
|
||||||
|
const buildLintCommand = (filenames) => {
|
||||||
|
const isNext =
|
||||||
|
process.env.npm_package_devDependencies_next ||
|
||||||
|
process.env.npm_package_dependencies_next;
|
||||||
|
|
||||||
|
if (isNext) {
|
||||||
|
return `next lint --fix --file ${filenames
|
||||||
|
.map((f) => path.relative(process.cwd(), f))
|
||||||
|
.join(" --file ")}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return "eslint --fix";
|
||||||
|
};
|
||||||
|
|
||||||
|
const config = {
|
||||||
|
"*.{js,jsx,ts,tsx}": [buildLintCommand, "prettier --write"],
|
||||||
"*.{json,md,css,scss}": ["prettier --write"],
|
"*.{json,md,css,scss}": ["prettier --write"],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export default config;
|
||||||
|
|||||||
33
packages/infra/docker/Dockerfile.app-template
Normal file
33
packages/infra/docker/Dockerfile.app-template
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
# Start from the pre-built Nextjs Base image
|
||||||
|
FROM registry.infra.mintel.me/mintel/nextjs:latest AS builder
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Build-time environment variables for Next.js
|
||||||
|
ARG NEXT_PUBLIC_BASE_URL
|
||||||
|
ARG NEXT_PUBLIC_UMAMI_WEBSITE_ID
|
||||||
|
ARG NEXT_PUBLIC_UMAMI_SCRIPT_URL
|
||||||
|
ARG NEXT_PUBLIC_TARGET
|
||||||
|
ARG DIRECTUS_URL
|
||||||
|
|
||||||
|
ENV NEXT_PUBLIC_BASE_URL=$NEXT_PUBLIC_BASE_URL
|
||||||
|
ENV NEXT_PUBLIC_UMAMI_WEBSITE_ID=$NEXT_PUBLIC_UMAMI_WEBSITE_ID
|
||||||
|
ENV NEXT_PUBLIC_UMAMI_SCRIPT_URL=$NEXT_PUBLIC_UMAMI_SCRIPT_URL
|
||||||
|
ENV NEXT_PUBLIC_TARGET=$NEXT_PUBLIC_TARGET
|
||||||
|
ENV DIRECTUS_URL=$DIRECTUS_URL
|
||||||
|
|
||||||
|
# Build the specific application
|
||||||
|
RUN pnpm --filter ${APP_NAME:-app} build
|
||||||
|
|
||||||
|
# Production runner image
|
||||||
|
FROM registry.infra.mintel.me/mintel/runtime:latest AS runner
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Copy standalone output and static files
|
||||||
|
COPY --from=builder --chown=nextjs:nodejs /app/apps/${APP_NAME:-app}/public ./apps/${APP_NAME:-app}/public
|
||||||
|
COPY --from=builder --chown=nextjs:nodejs /app/apps/${APP_NAME:-app}/.next/standalone ./
|
||||||
|
COPY --from=builder --chown=nextjs:nodejs /app/apps/${APP_NAME:-app}/.next/static ./apps/${APP_NAME:-app}/.next/static
|
||||||
|
|
||||||
|
USER nextjs
|
||||||
|
|
||||||
|
CMD ["node", "apps/${APP_NAME:-app}/server.js"]
|
||||||
12
packages/infra/docker/Dockerfile.directus
Normal file
12
packages/infra/docker/Dockerfile.directus
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
FROM directus/directus:11
|
||||||
|
|
||||||
|
# Add any custom extensions or configurations here if needed
|
||||||
|
# COPY ./extensions /directus/extensions
|
||||||
|
|
||||||
|
# Default environment for optimized production use
|
||||||
|
ENV LOGGER_LEVEL="info"
|
||||||
|
ENV WEBSOCKETS_ENABLED="true"
|
||||||
|
|
||||||
|
# Health check
|
||||||
|
HEALTHCHECK --interval=30s --timeout=30s --start-period=5s --retries=3 \
|
||||||
|
CMD curl -f http://localhost:8055/health || exit 1
|
||||||
@@ -1,47 +1,37 @@
|
|||||||
FROM node:20-alpine AS base
|
# Step 1: Builder stage
|
||||||
|
FROM node:20-alpine AS builder
|
||||||
# Install dependencies only when needed
|
RUN apk add --no-cache libc6-compat curl
|
||||||
FROM base AS deps
|
|
||||||
RUN apk add --no-cache libc6-compat
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
RUN corepack enable pnpm
|
||||||
|
|
||||||
# Install dependencies
|
# Copy source (honoring .dockerignore)
|
||||||
COPY package.json pnpm-lock.yaml* ./
|
|
||||||
RUN corepack enable pnpm && pnpm i --frozen-lockfile
|
|
||||||
|
|
||||||
# Rebuild the source code only when needed
|
|
||||||
FROM base AS builder
|
|
||||||
WORKDIR /app
|
|
||||||
COPY --from=deps /app/node_modules ./node_modules
|
|
||||||
COPY . .
|
COPY . .
|
||||||
|
|
||||||
ENV NEXT_TELEMETRY_DISABLED=1
|
# Use a secret for NPM_TOKEN to authenticate with private registry
|
||||||
|
RUN --mount=type=cache,target=/root/.local/share/pnpm/store/v3 \
|
||||||
|
--mount=type=secret,id=NPM_TOKEN \
|
||||||
|
export NPM_TOKEN=$(cat /run/secrets/NPM_TOKEN) && \
|
||||||
|
pnpm i --frozen-lockfile
|
||||||
|
|
||||||
# Build the application
|
# Build Gatekeeper and its dependencies
|
||||||
RUN corepack enable pnpm && pnpm run build
|
RUN pnpm --filter @mintel/gatekeeper... build
|
||||||
|
RUN mkdir -p packages/gatekeeper/public
|
||||||
|
|
||||||
# Production image, copy all the files and run next
|
# Step 2: Runner stage
|
||||||
FROM base AS runner
|
FROM node:20-alpine AS runner
|
||||||
|
RUN apk add --no-cache libc6-compat curl
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
RUN apk add --no-cache curl
|
|
||||||
|
|
||||||
ENV NODE_ENV=production
|
ENV NODE_ENV=production
|
||||||
ENV NEXT_TELEMETRY_DISABLED=1
|
|
||||||
|
|
||||||
RUN addgroup --system --gid 1001 nodejs
|
RUN addgroup --system --gid 1001 nodejs
|
||||||
RUN adduser --system --uid 1001 nextjs
|
RUN adduser --system --uid 1001 nextjs
|
||||||
|
|
||||||
# Automatically leverage output traces to reduce image size
|
COPY --from=builder /app/packages/gatekeeper/public ./packages/gatekeeper/public
|
||||||
# https://nextjs.org/docs/advanced-features/output-file-tracing
|
COPY --from=builder /app/packages/gatekeeper/.next/standalone ./
|
||||||
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
|
COPY --from=builder /app/packages/gatekeeper/.next/static ./packages/gatekeeper/.next/static
|
||||||
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
|
|
||||||
|
|
||||||
USER nextjs
|
USER nextjs
|
||||||
|
|
||||||
EXPOSE 3000
|
EXPOSE 3000
|
||||||
|
|
||||||
ENV PORT=3000
|
ENV PORT=3000
|
||||||
ENV HOSTNAME="0.0.0.0"
|
ENV HOSTNAME="0.0.0.0"
|
||||||
|
|
||||||
CMD ["node", "server.js"]
|
CMD ["node", "packages/gatekeeper/server.js"]
|
||||||
|
|||||||
@@ -1,66 +1,19 @@
|
|||||||
FROM node:20-alpine AS base
|
# Step 1: Builder image
|
||||||
|
FROM node:20-alpine AS builder
|
||||||
# Install dependencies only when needed
|
|
||||||
FROM base AS deps
|
|
||||||
RUN apk add --no-cache libc6-compat curl
|
RUN apk add --no-cache libc6-compat curl
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
RUN corepack enable pnpm
|
||||||
|
|
||||||
# Install dependencies based on the preferred package manager
|
# Step 2: Install dependencies
|
||||||
COPY package.json package-lock.json* pnpm-lock.yaml* ./
|
# We copy everything first because we have a .dockerignore
|
||||||
RUN if [ -f pnpm-lock.yaml ]; then corepack enable pnpm && pnpm i --frozen-lockfile; \
|
# and we need the workspace structure for pnpm to work correctly
|
||||||
elif [ -f package-lock.json ]; then npm ci; \
|
|
||||||
else npm i; fi
|
|
||||||
|
|
||||||
# Rebuild the source code only when needed
|
|
||||||
FROM base AS builder
|
|
||||||
WORKDIR /app
|
|
||||||
COPY --from=deps /app/node_modules ./node_modules
|
|
||||||
COPY . .
|
COPY . .
|
||||||
|
|
||||||
# Next.js collects completely anonymous telemetry data about general usage.
|
# Use a secret for NPM_TOKEN to authenticate with private registry
|
||||||
ENV NEXT_TELEMETRY_DISABLED=1
|
RUN --mount=type=cache,target=/root/.local/share/pnpm/store/v3 \
|
||||||
|
--mount=type=secret,id=NPM_TOKEN \
|
||||||
|
export NPM_TOKEN=$(cat /run/secrets/NPM_TOKEN) && \
|
||||||
|
pnpm i --frozen-lockfile
|
||||||
|
|
||||||
# Build-time environment variables for Next.js
|
# Step 3: Build shared packages
|
||||||
ARG NEXT_PUBLIC_BASE_URL
|
RUN pnpm --filter "./packages/*" -r build
|
||||||
ARG NEXT_PUBLIC_UMAMI_WEBSITE_ID
|
|
||||||
ARG NEXT_PUBLIC_UMAMI_SCRIPT_URL
|
|
||||||
|
|
||||||
ENV NEXT_PUBLIC_BASE_URL=$NEXT_PUBLIC_BASE_URL
|
|
||||||
ENV NEXT_PUBLIC_UMAMI_WEBSITE_ID=$NEXT_PUBLIC_UMAMI_WEBSITE_ID
|
|
||||||
ENV NEXT_PUBLIC_UMAMI_SCRIPT_URL=$NEXT_PUBLIC_UMAMI_SCRIPT_URL
|
|
||||||
|
|
||||||
# Build the application
|
|
||||||
RUN if [ -f pnpm-lock.yaml ]; then corepack enable pnpm && pnpm run build; \
|
|
||||||
else npm run build; fi
|
|
||||||
|
|
||||||
# Production image, copy all the files and run next
|
|
||||||
FROM base AS runner
|
|
||||||
WORKDIR /app
|
|
||||||
|
|
||||||
# Install curl for health checks
|
|
||||||
RUN apk add --no-cache curl
|
|
||||||
|
|
||||||
ENV NODE_ENV=production
|
|
||||||
ENV NEXT_TELEMETRY_DISABLED=1
|
|
||||||
|
|
||||||
RUN addgroup --system --gid 1001 nodejs
|
|
||||||
RUN adduser --system --uid 1001 nextjs
|
|
||||||
|
|
||||||
COPY --from=builder /app/public ./public
|
|
||||||
|
|
||||||
# Set the correct permission for prerender cache
|
|
||||||
RUN mkdir .next
|
|
||||||
RUN chown nextjs:nodejs .next
|
|
||||||
|
|
||||||
# Automatically leverage output traces to reduce image size
|
|
||||||
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
|
|
||||||
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
|
|
||||||
|
|
||||||
USER nextjs
|
|
||||||
|
|
||||||
EXPOSE 3000
|
|
||||||
|
|
||||||
ENV PORT=3000
|
|
||||||
ENV HOSTNAME="0.0.0.0"
|
|
||||||
|
|
||||||
CMD ["node", "server.js"]
|
|
||||||
|
|||||||
19
packages/infra/docker/Dockerfile.runtime
Normal file
19
packages/infra/docker/Dockerfile.runtime
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
FROM node:20-alpine
|
||||||
|
|
||||||
|
# Install essential production utilities
|
||||||
|
RUN apk add --no-cache curl libc6-compat
|
||||||
|
|
||||||
|
# Set standard production environment
|
||||||
|
ENV NODE_ENV=production
|
||||||
|
ENV NEXT_TELEMETRY_DISABLED=1
|
||||||
|
ENV PORT=3000
|
||||||
|
ENV HOSTNAME="0.0.0.0"
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Create non-root user for security
|
||||||
|
RUN addgroup --system --gid 1001 nodejs && \
|
||||||
|
adduser --system --uid 1001 nextjs
|
||||||
|
|
||||||
|
# Expose the default Next.js port
|
||||||
|
EXPOSE 3000
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
services:
|
services:
|
||||||
app:
|
app:
|
||||||
image: registry.infra.mintel.me/mintel/${APP_NAME:-app}:${IMAGE_TAG:-latest}
|
|
||||||
restart: always
|
restart: always
|
||||||
networks:
|
networks:
|
||||||
- infra
|
- infra
|
||||||
@@ -40,7 +39,6 @@ services:
|
|||||||
|
|
||||||
gatekeeper:
|
gatekeeper:
|
||||||
image: registry.infra.mintel.me/mintel/gatekeeper:${IMAGE_TAG:-latest}
|
image: registry.infra.mintel.me/mintel/gatekeeper:${IMAGE_TAG:-latest}
|
||||||
container_name: ${PROJECT_NAME}-gatekeeper
|
|
||||||
restart: always
|
restart: always
|
||||||
networks:
|
networks:
|
||||||
- infra
|
- infra
|
||||||
@@ -55,7 +53,7 @@ services:
|
|||||||
- "traefik.http.services.${PROJECT_NAME}-gatekeeper.loadbalancer.server.port=3000"
|
- "traefik.http.services.${PROJECT_NAME}-gatekeeper.loadbalancer.server.port=3000"
|
||||||
|
|
||||||
directus:
|
directus:
|
||||||
image: directus/directus:11
|
image: registry.infra.mintel.me/mintel/directus:latest
|
||||||
restart: always
|
restart: always
|
||||||
networks:
|
networks:
|
||||||
- infra
|
- infra
|
||||||
|
|||||||
@@ -24,6 +24,8 @@ jobs:
|
|||||||
prepare:
|
prepare:
|
||||||
name: 🔍 Prepare Environment
|
name: 🔍 Prepare Environment
|
||||||
runs-on: docker
|
runs-on: docker
|
||||||
|
container:
|
||||||
|
image: catthehacker/ubuntu:act-latest
|
||||||
outputs:
|
outputs:
|
||||||
target: ${{ steps.determine.outputs.target }}
|
target: ${{ steps.determine.outputs.target }}
|
||||||
image_tag: ${{ steps.determine.outputs.image_tag }}
|
image_tag: ${{ steps.determine.outputs.image_tag }}
|
||||||
@@ -39,17 +41,23 @@ jobs:
|
|||||||
short_sha: ${{ steps.determine.outputs.short_sha }}
|
short_sha: ${{ steps.determine.outputs.short_sha }}
|
||||||
commit_msg: ${{ steps.determine.outputs.commit_msg }}
|
commit_msg: ${{ steps.determine.outputs.commit_msg }}
|
||||||
steps:
|
steps:
|
||||||
|
- name: 🧹 Maintenance (High Density Cleanup)
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
echo "Purging old build layers and dangling images..."
|
||||||
|
docker image prune -f
|
||||||
|
docker builder prune -f --filter "until=6h"
|
||||||
|
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 2
|
||||||
|
|
||||||
- name: 🔍 Environment & Version ermitteln
|
- name: 🔍 Environment & Version ermitteln
|
||||||
id: determine
|
id: determine
|
||||||
run: |
|
run: |
|
||||||
TAG="${{ github.ref_name }}"
|
TAG="${{ github.ref_name }}"
|
||||||
SHORT_SHA="${{ github.sha }}"
|
SHORT_SHA=$(echo "${{ github.sha }}" | cut -c1-9)
|
||||||
SHORT_SHA="${SHORT_SHA:0:9}"
|
|
||||||
COMMIT_MSG=$(git log -1 --pretty=%s || echo "No commit message available")
|
COMMIT_MSG=$(git log -1 --pretty=%s || echo "No commit message available")
|
||||||
|
|
||||||
# Base Domain (e.g. example.com)
|
# Base Domain (e.g. example.com)
|
||||||
@@ -79,7 +87,6 @@ jobs:
|
|||||||
TARGET="production"
|
TARGET="production"
|
||||||
IMAGE_TAG="$TAG"
|
IMAGE_TAG="$TAG"
|
||||||
ENV_FILE=".env.prod"
|
ENV_FILE=".env.prod"
|
||||||
TRAEFIK_HOST="\${DOMAIN_BASE}, www.\${DOMAIN_BASE}" # Note: Host() backticks usually needed in compose
|
|
||||||
TRAEFIK_HOST="\`\${DOMAIN_BASE}\`, \`www.\${DOMAIN_BASE}\`"
|
TRAEFIK_HOST="\`\${DOMAIN_BASE}\`, \`www.\${DOMAIN_BASE}\`"
|
||||||
NEXT_PUBLIC_BASE_URL="https://\${DOMAIN_BASE}"
|
NEXT_PUBLIC_BASE_URL="https://\${DOMAIN_BASE}"
|
||||||
DIRECTUS_URL="https://cms.\${DOMAIN_BASE}"
|
DIRECTUS_URL="https://cms.\${DOMAIN_BASE}"
|
||||||
@@ -88,7 +95,7 @@ jobs:
|
|||||||
IS_PROD="true"
|
IS_PROD="true"
|
||||||
GOTIFY_TITLE="🚀 Production-Release"
|
GOTIFY_TITLE="🚀 Production-Release"
|
||||||
GOTIFY_PRIORITY=6
|
GOTIFY_PRIORITY=6
|
||||||
elif [[ "$TAG" =~ -rc\. || "$TAG" =~ -beta\. || "$TAG" =~ -alpha\. ]]; then
|
elif [[ "$TAG" =~ -rc || "$TAG" =~ -beta || "$TAG" =~ -alpha ]]; then
|
||||||
TARGET="staging"
|
TARGET="staging"
|
||||||
IMAGE_TAG="$TAG"
|
IMAGE_TAG="$TAG"
|
||||||
ENV_FILE=".env.staging"
|
ENV_FILE=".env.staging"
|
||||||
@@ -107,19 +114,21 @@ jobs:
|
|||||||
TARGET="skip"
|
TARGET="skip"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "target=$TARGET" >> $GITHUB_OUTPUT
|
{
|
||||||
echo "image_tag=$IMAGE_TAG" >> $GITHUB_OUTPUT
|
echo "target=$TARGET"
|
||||||
echo "env_file=$ENV_FILE" >> $GITHUB_OUTPUT
|
echo "image_tag=$IMAGE_TAG"
|
||||||
echo "traefik_host=$TRAEFIK_HOST" >> $GITHUB_OUTPUT
|
echo "env_file=$ENV_FILE"
|
||||||
echo "next_public_base_url=$NEXT_PUBLIC_BASE_URL" >> $GITHUB_OUTPUT
|
echo "traefik_host=$TRAEFIK_HOST"
|
||||||
echo "directus_url=$DIRECTUS_URL" >> $GITHUB_OUTPUT
|
echo "next_public_base_url=$NEXT_PUBLIC_BASE_URL"
|
||||||
echo "directus_host=$DIRECTUS_HOST" >> $GITHUB_OUTPUT
|
echo "directus_url=$DIRECTUS_URL"
|
||||||
echo "project_name=$PROJECT_NAME" >> $GITHUB_OUTPUT
|
echo "directus_host=$DIRECTUS_HOST"
|
||||||
echo "is_prod=$IS_PROD" >> $GITHUB_OUTPUT
|
echo "project_name=$PROJECT_NAME"
|
||||||
echo "gotify_title=$GOTIFY_TITLE" >> $GITHUB_OUTPUT
|
echo "is_prod=$IS_PROD"
|
||||||
echo "gotify_priority=$GOTIFY_PRIORITY" >> $GITHUB_OUTPUT
|
echo "gotify_title=$GOTIFY_TITLE"
|
||||||
echo "short_sha=$SHORT_SHA" >> $GITHUB_OUTPUT
|
echo "gotify_priority=$GOTIFY_PRIORITY"
|
||||||
echo "commit_msg=$COMMIT_MSG" >> $GITHUB_OUTPUT
|
echo "short_sha=$SHORT_SHA"
|
||||||
|
echo "commit_msg=$COMMIT_MSG"
|
||||||
|
} >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
# ──────────────────────────────────────────────────────────────────────────────
|
# ──────────────────────────────────────────────────────────────────────────────
|
||||||
# JOB 2: Quality Assurance (Lint & Test)
|
# JOB 2: Quality Assurance (Lint & Test)
|
||||||
@@ -129,6 +138,8 @@ jobs:
|
|||||||
needs: prepare
|
needs: prepare
|
||||||
if: needs.prepare.outputs.target != 'skip'
|
if: needs.prepare.outputs.target != 'skip'
|
||||||
runs-on: docker
|
runs-on: docker
|
||||||
|
container:
|
||||||
|
image: catthehacker/ubuntu:act-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
@@ -137,17 +148,23 @@ jobs:
|
|||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 20
|
node-version: 20
|
||||||
cache: 'npm'
|
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: npm ci
|
run: npm ci
|
||||||
|
|
||||||
- name: 🧪 Run Checks
|
- name: 🧪 Run Checks in Parallel
|
||||||
if: github.event.inputs.skip_long_checks != 'true'
|
if: github.event.inputs.skip_long_checks != 'true'
|
||||||
run: |
|
run: |
|
||||||
npm run lint
|
npm run lint &
|
||||||
npm run typecheck
|
LINT_PID=$!
|
||||||
npm run test
|
npm run typecheck &
|
||||||
|
TYPE_PID=$!
|
||||||
|
npm run test &
|
||||||
|
TEST_PID=$!
|
||||||
|
|
||||||
|
wait $LINT_PID || exit 1
|
||||||
|
wait $TYPE_PID || exit 1
|
||||||
|
wait $TEST_PID || exit 1
|
||||||
|
|
||||||
# ──────────────────────────────────────────────────────────────────────────────
|
# ──────────────────────────────────────────────────────────────────────────────
|
||||||
# JOB 3: Build & Push
|
# JOB 3: Build & Push
|
||||||
@@ -157,25 +174,38 @@ jobs:
|
|||||||
needs: prepare
|
needs: prepare
|
||||||
if: needs.prepare.outputs.target != 'skip'
|
if: needs.prepare.outputs.target != 'skip'
|
||||||
runs-on: docker
|
runs-on: docker
|
||||||
|
container:
|
||||||
|
image: catthehacker/ubuntu:act-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: 🐳 Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v3
|
||||||
|
|
||||||
- name: 🔐 Registry Login
|
- name: 🔐 Registry Login
|
||||||
run: |
|
uses: docker/login-action@v3
|
||||||
echo "${{ secrets.REGISTRY_PASS }}" | docker login registry.infra.mintel.me -u "${{ secrets.REGISTRY_USER }}" --password-stdin
|
with:
|
||||||
|
registry: registry.infra.mintel.me
|
||||||
|
username: ${{ secrets.REGISTRY_USER }}
|
||||||
|
password: ${{ secrets.REGISTRY_PASS }}
|
||||||
|
|
||||||
- name: 🏗️ Docker Build & Push
|
- name: 🏗️ Docker Build & Push
|
||||||
env:
|
uses: docker/build-push-action@v5
|
||||||
IMAGE_TAG: ${{ needs.prepare.outputs.image_tag }}
|
with:
|
||||||
NEXT_PUBLIC_BASE_URL: ${{ needs.prepare.outputs.next_public_base_url }}
|
context: .
|
||||||
run: |
|
file: packages/infra/docker/Dockerfile.nextjs
|
||||||
docker buildx build \
|
platforms: linux/arm64
|
||||||
--pull \
|
pull: true
|
||||||
--platform linux/arm64 \
|
build-args: |
|
||||||
--build-arg NEXT_PUBLIC_BASE_URL="$NEXT_PUBLIC_BASE_URL" \
|
NEXT_PUBLIC_BASE_URL=${{ needs.prepare.outputs.next_public_base_url }}
|
||||||
-t registry.infra.mintel.me/mintel/${{ github.event.repository.name }}:$IMAGE_TAG \
|
NEXT_PUBLIC_TARGET=${{ needs.prepare.outputs.target }}
|
||||||
--push .
|
push: true
|
||||||
|
secrets: |
|
||||||
|
NPM_TOKEN=${{ secrets.NPM_TOKEN }}
|
||||||
|
tags: registry.infra.mintel.me/mintel/${{ github.event.repository.name }}:${{ needs.prepare.outputs.image_tag }}
|
||||||
|
cache-from: type=registry,ref=registry.infra.mintel.me/mintel/${{ github.event.repository.name }}:buildcache
|
||||||
|
cache-to: type=registry,ref=registry.infra.mintel.me/mintel/${{ github.event.repository.name }}:buildcache,mode=max
|
||||||
|
|
||||||
# ──────────────────────────────────────────────────────────────────────────────
|
# ──────────────────────────────────────────────────────────────────────────────
|
||||||
# JOB 4: Deploy
|
# JOB 4: Deploy
|
||||||
@@ -185,18 +215,18 @@ jobs:
|
|||||||
needs: [prepare, build, qa]
|
needs: [prepare, build, qa]
|
||||||
if: needs.prepare.outputs.target != 'skip'
|
if: needs.prepare.outputs.target != 'skip'
|
||||||
runs-on: docker
|
runs-on: docker
|
||||||
|
container:
|
||||||
|
image: catthehacker/ubuntu:act-latest
|
||||||
env:
|
env:
|
||||||
TARGET: ${{ needs.prepare.outputs.target }}
|
TARGET: ${{ needs.prepare.outputs.target }}
|
||||||
|
IMAGE_TAG: ${{ needs.prepare.outputs.image_tag }}
|
||||||
|
PROJECT_NAME: ${{ needs.prepare.outputs.project_name }}
|
||||||
|
ENV_FILE: ${{ needs.prepare.outputs.env_file }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: 🚀 Deploy via SSH
|
- name: 🚀 Deploy via SSH
|
||||||
env:
|
|
||||||
IMAGE_TAG: ${{ needs.prepare.outputs.image_tag }}
|
|
||||||
ENV_FILE: ${{ needs.prepare.outputs.env_file }}
|
|
||||||
TRAEFIK_HOST: ${{ needs.prepare.outputs.traefik_host }}
|
|
||||||
PROJECT_NAME: ${{ needs.prepare.outputs.project_name }}
|
|
||||||
run: |
|
run: |
|
||||||
mkdir -p ~/.ssh
|
mkdir -p ~/.ssh
|
||||||
echo "${{ secrets.SSH_KEY }}" > ~/.ssh/id_ed25519
|
echo "${{ secrets.SSH_KEY }}" > ~/.ssh/id_ed25519
|
||||||
@@ -208,12 +238,13 @@ jobs:
|
|||||||
# Generated by CI - $TARGET - $(date -u)
|
# Generated by CI - $TARGET - $(date -u)
|
||||||
NODE_ENV=production
|
NODE_ENV=production
|
||||||
IMAGE_TAG=$IMAGE_TAG
|
IMAGE_TAG=$IMAGE_TAG
|
||||||
TRAEFIK_HOST=$TRAEFIK_HOST
|
TRAEFIK_HOST=${{ needs.prepare.outputs.traefik_host }}
|
||||||
PROJECT_NAME=$PROJECT_NAME
|
PROJECT_NAME=$PROJECT_NAME
|
||||||
ENV_FILE=$ENV_FILE
|
ENV_FILE=$ENV_FILE
|
||||||
|
|
||||||
# App Config
|
# App Config
|
||||||
NEXT_PUBLIC_BASE_URL=${{ needs.prepare.outputs.next_public_base_url }}
|
NEXT_PUBLIC_BASE_URL=${{ needs.prepare.outputs.next_public_base_url }}
|
||||||
|
NEXT_PUBLIC_TARGET=$TARGET
|
||||||
|
|
||||||
# Directus Config
|
# Directus Config
|
||||||
DIRECTUS_URL=${{ needs.prepare.outputs.directus_url }}
|
DIRECTUS_URL=${{ needs.prepare.outputs.directus_url }}
|
||||||
@@ -237,10 +268,11 @@ jobs:
|
|||||||
ssh root@${{ secrets.SSH_HOST }} IMAGE_TAG="$IMAGE_TAG" ENV_FILE="$ENV_FILE" PROJECT_NAME="$PROJECT_NAME" bash << 'EOF'
|
ssh root@${{ secrets.SSH_HOST }} IMAGE_TAG="$IMAGE_TAG" ENV_FILE="$ENV_FILE" PROJECT_NAME="$PROJECT_NAME" bash << 'EOF'
|
||||||
set -e
|
set -e
|
||||||
cd "/home/deploy/sites/${{ github.event.repository.name }}"
|
cd "/home/deploy/sites/${{ github.event.repository.name }}"
|
||||||
|
chmod 600 "$ENV_FILE"
|
||||||
echo "${{ secrets.REGISTRY_PASS }}" | docker login registry.infra.mintel.me -u "${{ secrets.REGISTRY_USER }}" --password-stdin
|
echo "${{ secrets.REGISTRY_PASS }}" | docker login registry.infra.mintel.me -u "${{ secrets.REGISTRY_USER }}" --password-stdin
|
||||||
docker compose -p "$PROJECT_NAME" --env-file "$ENV_FILE" pull
|
docker compose -p "$PROJECT_NAME" --env-file "$ENV_FILE" pull
|
||||||
docker compose -p "$PROJECT_NAME" --env-file "$ENV_FILE" up -d --remove-orphans
|
docker compose -p "$PROJECT_NAME" --env-file "$ENV_FILE" up -d --remove-orphans
|
||||||
docker system prune -f --filter "until=168h"
|
docker system prune -f --filter "until=24h"
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
# ──────────────────────────────────────────────────────────────────────────────
|
# ──────────────────────────────────────────────────────────────────────────────
|
||||||
@@ -251,11 +283,25 @@ jobs:
|
|||||||
needs: [prepare, deploy]
|
needs: [prepare, deploy]
|
||||||
if: always()
|
if: always()
|
||||||
runs-on: docker
|
runs-on: docker
|
||||||
|
container:
|
||||||
|
image: catthehacker/ubuntu:act-latest
|
||||||
steps:
|
steps:
|
||||||
- name: 🔔 Gotify
|
- name: 🔔 Gotify - Success
|
||||||
if: needs.deploy.result == 'success'
|
if: needs.deploy.result == 'success'
|
||||||
run: |
|
run: |
|
||||||
curl -s -k -X POST "${{ secrets.GOTIFY_URL }}/message?token=${{ secrets.GOTIFY_TOKEN }}" \
|
curl -s -k -X POST "${{ secrets.GOTIFY_URL }}/message?token=${{ secrets.GOTIFY_TOKEN }}" \
|
||||||
-F "title=${{ needs.prepare.outputs.gotify_title }}" \
|
-F "title=${{ needs.prepare.outputs.gotify_title }}" \
|
||||||
-F "message=Erfolgreich deployt auf **${{ needs.prepare.outputs.target }}**" \
|
-F "message=Erfolgreich deployt auf **${{ needs.prepare.outputs.target }}**\n\nVersion: **${{ needs.prepare.outputs.image_tag }}**\nCommit: ${{ needs.prepare.outputs.short_sha }}\nRun: ${{ github.run_id }}" \
|
||||||
-F "priority=4" || true
|
-F "priority=4" || true
|
||||||
|
|
||||||
|
- name: 🔔 Gotify - Failure
|
||||||
|
if: |
|
||||||
|
needs.prepare.result == 'failure' ||
|
||||||
|
needs.qa.result == 'failure' ||
|
||||||
|
needs.build.result == 'failure' ||
|
||||||
|
needs.deploy.result == 'failure'
|
||||||
|
run: |
|
||||||
|
curl -s -k -X POST "${{ secrets.GOTIFY_URL }}/message?token=${{ secrets.GOTIFY_TOKEN }}" \
|
||||||
|
-F "title=❌ Deployment FEHLGESCHLAGEN – ${{ github.event.repository.name }}" \
|
||||||
|
-F "message=**Fehler beim Deploy auf ${{ needs.prepare.outputs.target || 'unknown' }}**\n\nRun: ${{ github.run_id }}\nBitte Logs prüfen!" \
|
||||||
|
-F "priority=8" || true
|
||||||
|
|||||||
60
packages/infra/scripts/prune-registry.sh
Normal file
60
packages/infra/scripts/prune-registry.sh
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Configuration
|
||||||
|
REGISTRY_DATA="/opt/infra/registry/data/docker/registry/v2"
|
||||||
|
KEEP_TAGS=3
|
||||||
|
|
||||||
|
echo "🏥 Starting Aggressive Registry & Docker Maintenance..."
|
||||||
|
|
||||||
|
# 1. Prune Registry Tags (Filesystem level)
|
||||||
|
for repo_dir in "$REGISTRY_DATA/repositories/mintel/"*; do
|
||||||
|
repo_name=$(basename "$repo_dir")
|
||||||
|
tags_dir="$repo_dir/_manifests/tags"
|
||||||
|
|
||||||
|
if [ -d "$tags_dir" ]; then
|
||||||
|
echo "🔍 Processing repository: mintel/$repo_name"
|
||||||
|
|
||||||
|
# Prune main-* tags
|
||||||
|
echo " 📦 Pruning main tags..."
|
||||||
|
main_tags=$(ls -dt "$tags_dir"/main-* 2>/dev/null || true)
|
||||||
|
count=0
|
||||||
|
for tag_path in $main_tags; do
|
||||||
|
((++count))
|
||||||
|
if [ $count -gt $KEEP_TAGS ]; then
|
||||||
|
echo " 🗑️ Deleting old main tag: $(basename "$tag_path")"
|
||||||
|
rm -rf "$tag_path"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Prune version tags (v* and rc*)
|
||||||
|
echo " 🏷️ Pruning version tags..."
|
||||||
|
version_tags=$(ls -dt "$tags_dir"/v1* 2>/dev/null || true)
|
||||||
|
count=0
|
||||||
|
for tag_path in $version_tags; do
|
||||||
|
((++count))
|
||||||
|
if [ $count -gt $KEEP_TAGS ]; then
|
||||||
|
echo " 🗑️ Deleting old version tag: $(basename "$tag_path")"
|
||||||
|
rm -rf "$tag_path"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Always prune buildcache (as it rebuilds quickly)
|
||||||
|
if [ -d "$tags_dir/buildcache" ]; then
|
||||||
|
echo " 🧹 Deleting buildcache tag"
|
||||||
|
rm -rf "$tags_dir/buildcache"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# 2. Run Garbage Collection
|
||||||
|
echo "♻️ Running Registry Garbage Collection..."
|
||||||
|
docker exec registry-registry-1 bin/registry garbage-collect /etc/docker/registry/config.yml
|
||||||
|
|
||||||
|
# 3. Prune Host Docker resources (Shorter window: 24h)
|
||||||
|
echo "🧹 Pruning Host Docker resources..."
|
||||||
|
docker system prune -af --filter "until=24h"
|
||||||
|
docker volume prune -f
|
||||||
|
|
||||||
|
echo "✅ Maintenance complete!"
|
||||||
|
df -h /
|
||||||
68
packages/infra/scripts/sync-directus.sh
Normal file
68
packages/infra/scripts/sync-directus.sh
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Mintel Directus Sync Engine
|
||||||
|
# Synchronizes Directus Data (Postgres + Uploads) between Local and Remote
|
||||||
|
|
||||||
|
REMOTE_HOST="${SSH_HOST:-root@alpha.mintel.me}"
|
||||||
|
ACTION=$1
|
||||||
|
ENV=$2
|
||||||
|
|
||||||
|
# Help
|
||||||
|
if [ -z "$ACTION" ] || [ -z "$ENV" ]; then
|
||||||
|
echo "Usage: mintel-sync [push|pull] [testing|staging|production]"
|
||||||
|
echo ""
|
||||||
|
echo "Commands:"
|
||||||
|
echo " push Sync LOCAL data -> REMOTE"
|
||||||
|
echo " pull Sync REMOTE data -> LOCAL"
|
||||||
|
echo ""
|
||||||
|
echo "Environments:"
|
||||||
|
echo " testing, staging, production"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
PRJ_ID=$(jq -r .name package.json | sed 's/@mintel\///')
|
||||||
|
case $ENV in
|
||||||
|
testing) PROJECT_NAME="${PRJ_ID}-testing"; ENV_FILE=".env.testing" ;;
|
||||||
|
staging) PROJECT_NAME="${PRJ_ID}-staging"; ENV_FILE=".env.staging" ;;
|
||||||
|
production) PROJECT_NAME="${PRJ_ID}-prod"; ENV_FILE=".env.prod" ;;
|
||||||
|
*) echo "❌ Invalid environment: $ENV"; exit 1 ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
REMOTE_DIR="/home/deploy/sites/${PRJ_ID}.com"
|
||||||
|
|
||||||
|
# DB Details
|
||||||
|
DB_USER="directus"
|
||||||
|
DB_NAME="directus"
|
||||||
|
|
||||||
|
echo "🔍 Detecting local database..."
|
||||||
|
LOCAL_DB_CONTAINER=$(docker compose ps -q directus-db)
|
||||||
|
if [ -z "$LOCAL_DB_CONTAINER" ]; then
|
||||||
|
echo "❌ Local directus-db container not found. Running?"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$ACTION" == "push" ]; then
|
||||||
|
echo "🚀 Pushing LOCAL -> $ENV ($PROJECT_NAME)..."
|
||||||
|
docker exec "$LOCAL_DB_CONTAINER" pg_dump -U "$DB_USER" --clean --if-exists --no-owner --no-privileges "$DB_NAME" > dump.sql
|
||||||
|
scp dump.sql "$REMOTE_HOST:$REMOTE_DIR/dump.sql"
|
||||||
|
|
||||||
|
REMOTE_DB_CONTAINER=$(ssh "$REMOTE_HOST" "cd $REMOTE_DIR && docker compose -p $PROJECT_NAME ps -q directus-db")
|
||||||
|
ssh "$REMOTE_HOST" "docker exec -i $REMOTE_DB_CONTAINER psql -U $DB_USER $DB_NAME < $REMOTE_DIR/dump.sql"
|
||||||
|
|
||||||
|
rsync -avz --progress ./directus/uploads/ "$REMOTE_HOST:$REMOTE_DIR/directus/uploads/"
|
||||||
|
rm dump.sql
|
||||||
|
ssh "$REMOTE_HOST" "rm $REMOTE_DIR/dump.sql"
|
||||||
|
echo "✨ Push complete!"
|
||||||
|
|
||||||
|
elif [ "$ACTION" == "pull" ]; then
|
||||||
|
echo "📥 Pulling $ENV -> LOCAL..."
|
||||||
|
REMOTE_DB_CONTAINER=$(ssh "$REMOTE_HOST" "cd $REMOTE_DIR && docker compose -p $PROJECT_NAME ps -q directus-db")
|
||||||
|
ssh "$REMOTE_HOST" "docker exec $REMOTE_DB_CONTAINER pg_dump -U $DB_USER --clean --if-exists --no-owner --no-privileges $DB_NAME > $REMOTE_DIR/dump.sql"
|
||||||
|
scp "$REMOTE_HOST:$REMOTE_DIR/dump.sql" dump.sql
|
||||||
|
|
||||||
|
docker exec -i "$LOCAL_DB_CONTAINER" psql -U "$DB_USER" "$DB_NAME" < dump.sql
|
||||||
|
rsync -avz --progress "$REMOTE_HOST:$REMOTE_DIR/directus/uploads/" ./directus/uploads/
|
||||||
|
rm dump.sql
|
||||||
|
ssh "$REMOTE_HOST" "rm $REMOTE_DIR/dump.sql"
|
||||||
|
echo "✨ Pull complete!"
|
||||||
|
fi
|
||||||
5
packages/infra/templates/website/.gitignore
vendored
5
packages/infra/templates/website/.gitignore
vendored
@@ -27,3 +27,8 @@ yarn-error.log*
|
|||||||
# typescript
|
# typescript
|
||||||
*.tsbuildinfo
|
*.tsbuildinfo
|
||||||
next-env.d.ts
|
next-env.d.ts
|
||||||
|
|
||||||
|
# directus
|
||||||
|
/directus/uploads
|
||||||
|
/directus/extensions
|
||||||
|
/.env
|
||||||
|
|||||||
@@ -1,18 +1,46 @@
|
|||||||
import client, { ensureAuthenticated } from "../src/lib/directus";
|
import {
|
||||||
|
createMintelDirectusClient,
|
||||||
|
ensureDirectusAuthenticated,
|
||||||
|
} from "@mintel/next-utils";
|
||||||
import { updateSettings } from "@directus/sdk";
|
import { updateSettings } from "@directus/sdk";
|
||||||
|
|
||||||
|
const client = createMintelDirectusClient();
|
||||||
|
|
||||||
async function setupBranding() {
|
async function setupBranding() {
|
||||||
console.log("🎨 Setup Directus Branding...");
|
const prjName = process.env.PROJECT_NAME || "Mintel Project";
|
||||||
await ensureAuthenticated();
|
const prjColor = process.env.PROJECT_COLOR || "#82ed20";
|
||||||
|
|
||||||
|
console.log(`🎨 Setup Directus Branding for ${prjName}...`);
|
||||||
|
await ensureDirectusAuthenticated(client);
|
||||||
|
|
||||||
|
const cssInjection = `
|
||||||
|
<style>
|
||||||
|
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap');
|
||||||
|
body, .v-app { font-family: 'Inter', sans-serif !important; }
|
||||||
|
.public-view .v-card {
|
||||||
|
backdrop-filter: blur(20px);
|
||||||
|
border-radius: 32px !important;
|
||||||
|
box-shadow: 0 50px 100px -20px rgba(0, 0, 0, 0.4) !important;
|
||||||
|
}
|
||||||
|
.v-navigation-drawer { background: #000c24 !important; }
|
||||||
|
</style>
|
||||||
|
<div style="font-family: 'Inter', sans-serif; text-align: center; margin-top: 24px;">
|
||||||
|
<p style="color: rgba(255,255,255,0.7); font-size: 14px; margin-bottom: 4px; font-weight: 500;">MINTEL INFRASTRUCTURE ENGINE</p>
|
||||||
|
<h1 style="color: #ffffff; font-size: 18px; font-weight: 700; margin: 0;">${prjName.toUpperCase()} <span style="color: ${prjColor};">RELIABILITY.</span></h1>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await client.request(
|
await client.request(
|
||||||
updateSettings({
|
updateSettings({
|
||||||
project_name: process.env.PROJECT_NAME || "Mintel Project",
|
project_name: prjName,
|
||||||
project_color: process.env.PROJECT_COLOR || "#82ed20",
|
project_color: prjColor,
|
||||||
|
public_note: cssInjection,
|
||||||
theme_light_overrides: {
|
theme_light_overrides: {
|
||||||
primary: process.env.PROJECT_COLOR || "#82ed20",
|
primary: prjColor,
|
||||||
borderRadius: "16px",
|
borderRadius: "16px",
|
||||||
|
navigationBackground: "#000c24",
|
||||||
|
navigationForeground: "#ffffff",
|
||||||
},
|
},
|
||||||
} as any),
|
} as any),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,46 +1,71 @@
|
|||||||
import createNextIntlPlugin from 'next-intl/plugin';
|
import createNextIntlPlugin from "next-intl/plugin";
|
||||||
import { withSentryConfig } from '@sentry/nextjs';
|
import { withSentryConfig } from "@sentry/nextjs";
|
||||||
|
import fs from "node:fs";
|
||||||
const withNextIntl = createNextIntlPlugin();
|
import path from "node:path";
|
||||||
|
|
||||||
/** @type {import('next').NextConfig} */
|
/** @type {import('next').NextConfig} */
|
||||||
export const baseNextConfig = {
|
export const baseNextConfig = {
|
||||||
output: 'standalone',
|
output: "standalone",
|
||||||
images: {
|
images: {
|
||||||
dangerouslyAllowSVG: true,
|
dangerouslyAllowSVG: true,
|
||||||
contentDispositionType: 'attachment',
|
contentDispositionType: "attachment",
|
||||||
contentSecurityPolicy: "default-src 'self'; script-src 'none'; sandbox;",
|
contentSecurityPolicy: "default-src 'self'; script-src 'none'; sandbox;",
|
||||||
},
|
},
|
||||||
async rewrites() {
|
async rewrites() {
|
||||||
const umamiUrl = (process.env.NEXT_PUBLIC_UMAMI_SCRIPT_URL || 'https://analytics.infra.mintel.me').replace('/script.js', '');
|
const umamiUrl = (
|
||||||
|
process.env.NEXT_PUBLIC_UMAMI_SCRIPT_URL ||
|
||||||
|
"https://analytics.infra.mintel.me"
|
||||||
|
).replace("/script.js", "");
|
||||||
const glitchtipUrl = process.env.SENTRY_DSN
|
const glitchtipUrl = process.env.SENTRY_DSN
|
||||||
? new URL(process.env.SENTRY_DSN).origin
|
? new URL(process.env.SENTRY_DSN).origin
|
||||||
: 'https://errors.infra.mintel.me';
|
: "https://errors.infra.mintel.me";
|
||||||
|
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
source: '/stats/:path*',
|
source: "/stats/:path*",
|
||||||
destination: `${umamiUrl}/:path*`,
|
destination: `${umamiUrl}/:path*`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
source: '/errors/:path*',
|
source: "/errors/:path*",
|
||||||
destination: `${glitchtipUrl}/:path*`,
|
destination: `${glitchtipUrl}/:path*`,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export default (config) => {
|
const withMintelConfig = (config) => {
|
||||||
const nextIntlConfig = withNextIntl({ ...baseNextConfig, ...config });
|
const i18nPaths = [
|
||||||
|
"src/i18n/request.ts",
|
||||||
|
"src/i18n/request.tsx",
|
||||||
|
"i18n/request.ts",
|
||||||
|
"i18n/request.tsx",
|
||||||
|
"src/i18n.ts",
|
||||||
|
"src/i18n.tsx",
|
||||||
|
"i18n.ts",
|
||||||
|
"i18n.tsx",
|
||||||
|
];
|
||||||
|
|
||||||
|
const hasI18nConfig = i18nPaths.some((p) =>
|
||||||
|
fs.existsSync(path.resolve(process.cwd(), p)),
|
||||||
|
);
|
||||||
|
|
||||||
|
let nextConfig = { ...baseNextConfig, ...config };
|
||||||
|
|
||||||
|
if (hasI18nConfig) {
|
||||||
|
const withNextIntl = createNextIntlPlugin();
|
||||||
|
nextConfig = withNextIntl(nextConfig);
|
||||||
|
}
|
||||||
|
|
||||||
return withSentryConfig(
|
return withSentryConfig(
|
||||||
nextIntlConfig,
|
nextConfig,
|
||||||
{
|
{
|
||||||
silent: !process.env.CI,
|
silent: !process.env.CI,
|
||||||
treeshake: { removeDebugLogging: true },
|
treeshake: { removeDebugLogging: true },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
authToken: undefined,
|
authToken: undefined,
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export default withMintelConfig;
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"next-intl": "^3.0.0",
|
"next-intl": "^4.8.2",
|
||||||
"@sentry/nextjs": "^8.0.0"
|
"@sentry/nextjs": "^8.0.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@directus/sdk": "^21.0.0",
|
"@directus/sdk": "^21.0.0",
|
||||||
"next": "15.1.6",
|
"next": "15.1.6",
|
||||||
"next-intl": "^3.0.0",
|
"next-intl": "^4.8.2",
|
||||||
"zod": "^3.0.0"
|
"zod": "^3.0.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { describe, it, expect } from "vitest";
|
import { describe, it, expect } from "vitest";
|
||||||
import { isValidLang } from "../src/index";
|
import { isValidLang } from "./lang";
|
||||||
|
|
||||||
describe("next-utils", () => {
|
describe("next-utils", () => {
|
||||||
it("should validate languages correctly", () => {
|
it("should validate languages correctly", () => {
|
||||||
|
|||||||
@@ -30,12 +30,7 @@ export async function rateLimit(
|
|||||||
submissions[identifier] = now;
|
submissions[identifier] = now;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const languages = ["en", "de"] as const;
|
export * from "./lang";
|
||||||
export type Lang = (typeof languages)[number];
|
|
||||||
|
|
||||||
export function isValidLang(lang: string): lang is Lang {
|
|
||||||
return (languages as readonly string[]).includes(lang);
|
|
||||||
}
|
|
||||||
|
|
||||||
export * from "./i18n";
|
export * from "./i18n";
|
||||||
export * from "./env";
|
export * from "./env";
|
||||||
|
|||||||
6
packages/next-utils/src/lang.ts
Normal file
6
packages/next-utils/src/lang.ts
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
export const languages = ["en", "de"] as const;
|
||||||
|
export type Lang = (typeof languages)[number];
|
||||||
|
|
||||||
|
export function isValidLang(lang: string): lang is Lang {
|
||||||
|
return (languages as readonly string[]).includes(lang);
|
||||||
|
}
|
||||||
408
pnpm-lock.yaml
generated
408
pnpm-lock.yaml
generated
@@ -86,6 +86,9 @@ importers:
|
|||||||
next:
|
next:
|
||||||
specifier: 15.1.6
|
specifier: 15.1.6
|
||||||
version: 15.1.6(@babel/core@7.28.6)(@opentelemetry/api@1.9.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
|
version: 15.1.6(@babel/core@7.28.6)(@opentelemetry/api@1.9.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
|
||||||
|
next-intl:
|
||||||
|
specifier: ^4.8.2
|
||||||
|
version: 4.8.2(next@15.1.6(@babel/core@7.28.6)(@opentelemetry/api@1.9.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react@19.2.4)(typescript@5.9.3)
|
||||||
react:
|
react:
|
||||||
specifier: ^19.0.0
|
specifier: ^19.0.0
|
||||||
version: 19.2.4
|
version: 19.2.4
|
||||||
@@ -141,7 +144,7 @@ importers:
|
|||||||
version: 2.4.9
|
version: 2.4.9
|
||||||
tsup:
|
tsup:
|
||||||
specifier: ^8.0.0
|
specifier: ^8.0.0
|
||||||
version: 8.5.1(jiti@2.6.1)(postcss@8.5.6)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.2)
|
version: 8.5.1(@swc/core@1.15.11)(jiti@2.6.1)(postcss@8.5.6)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.2)
|
||||||
typescript:
|
typescript:
|
||||||
specifier: ^5.0.0
|
specifier: ^5.0.0
|
||||||
version: 5.9.3
|
version: 5.9.3
|
||||||
@@ -163,6 +166,9 @@ importers:
|
|||||||
|
|
||||||
packages/gatekeeper:
|
packages/gatekeeper:
|
||||||
dependencies:
|
dependencies:
|
||||||
|
'@mintel/next-utils':
|
||||||
|
specifier: workspace:*
|
||||||
|
version: link:../next-utils
|
||||||
clsx:
|
clsx:
|
||||||
specifier: ^2.1.1
|
specifier: ^2.1.1
|
||||||
version: 2.1.1
|
version: 2.1.1
|
||||||
@@ -172,6 +178,9 @@ importers:
|
|||||||
next:
|
next:
|
||||||
specifier: 15.1.6
|
specifier: 15.1.6
|
||||||
version: 15.1.6(@babel/core@7.28.6)(@opentelemetry/api@1.9.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
|
version: 15.1.6(@babel/core@7.28.6)(@opentelemetry/api@1.9.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
|
||||||
|
next-intl:
|
||||||
|
specifier: ^4.8.2
|
||||||
|
version: 4.8.2(next@15.1.6(@babel/core@7.28.6)(@opentelemetry/api@1.9.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react@19.2.4)(typescript@5.9.3)
|
||||||
react:
|
react:
|
||||||
specifier: ^19.0.0
|
specifier: ^19.0.0
|
||||||
version: 19.2.4
|
version: 19.2.4
|
||||||
@@ -240,8 +249,8 @@ importers:
|
|||||||
specifier: ^8.0.0
|
specifier: ^8.0.0
|
||||||
version: 8.55.0(@opentelemetry/context-async-hooks@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/core@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/instrumentation@0.57.2(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(next@15.1.6(@babel/core@7.28.6)(@opentelemetry/api@1.9.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react@19.2.4)(webpack@5.104.1)
|
version: 8.55.0(@opentelemetry/context-async-hooks@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/core@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/instrumentation@0.57.2(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(next@15.1.6(@babel/core@7.28.6)(@opentelemetry/api@1.9.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react@19.2.4)(webpack@5.104.1)
|
||||||
next-intl:
|
next-intl:
|
||||||
specifier: ^3.0.0
|
specifier: ^4.8.2
|
||||||
version: 3.26.5(next@15.1.6(@babel/core@7.28.6)(@opentelemetry/api@1.9.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react@19.2.4)
|
version: 4.8.2(next@15.1.6(@babel/core@7.28.6)(@opentelemetry/api@1.9.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react@19.2.4)(typescript@5.9.3)
|
||||||
|
|
||||||
packages/next-utils:
|
packages/next-utils:
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -252,8 +261,8 @@ importers:
|
|||||||
specifier: 15.1.6
|
specifier: 15.1.6
|
||||||
version: 15.1.6(@babel/core@7.28.6)(@opentelemetry/api@1.9.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
|
version: 15.1.6(@babel/core@7.28.6)(@opentelemetry/api@1.9.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
|
||||||
next-intl:
|
next-intl:
|
||||||
specifier: ^3.0.0
|
specifier: ^4.8.2
|
||||||
version: 3.26.5(next@15.1.6(@babel/core@7.28.6)(@opentelemetry/api@1.9.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react@19.2.4)
|
version: 4.8.2(next@15.1.6(@babel/core@7.28.6)(@opentelemetry/api@1.9.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react@19.2.4)(typescript@5.9.3)
|
||||||
zod:
|
zod:
|
||||||
specifier: ^3.0.0
|
specifier: ^3.0.0
|
||||||
version: 3.25.76
|
version: 3.25.76
|
||||||
@@ -269,7 +278,7 @@ importers:
|
|||||||
version: 9.39.2(jiti@2.6.1)
|
version: 9.39.2(jiti@2.6.1)
|
||||||
tsup:
|
tsup:
|
||||||
specifier: ^8.0.0
|
specifier: ^8.0.0
|
||||||
version: 8.5.1(jiti@2.6.1)(postcss@8.5.6)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.2)
|
version: 8.5.1(@swc/core@1.15.11)(jiti@2.6.1)(postcss@8.5.6)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.2)
|
||||||
typescript:
|
typescript:
|
||||||
specifier: ^5.0.0
|
specifier: ^5.0.0
|
||||||
version: 5.9.3
|
version: 5.9.3
|
||||||
@@ -755,23 +764,23 @@ packages:
|
|||||||
'@noble/hashes':
|
'@noble/hashes':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@formatjs/ecma402-abstract@2.3.6':
|
'@formatjs/ecma402-abstract@3.1.1':
|
||||||
resolution: {integrity: sha512-HJnTFeRM2kVFVr5gr5kH1XP6K0JcJtE7Lzvtr3FS/so5f1kpsqqqxy5JF+FRaO6H2qmcMfAUIox7AJteieRtVw==}
|
resolution: {integrity: sha512-jhZbTwda+2tcNrs4kKvxrPLPjx8QsBCLCUgrrJ/S+G9YrGHWLhAyFMMBHJBnBoOwuLHd7L14FgYudviKaxkO2Q==}
|
||||||
|
|
||||||
'@formatjs/fast-memoize@2.2.7':
|
'@formatjs/fast-memoize@3.1.0':
|
||||||
resolution: {integrity: sha512-Yabmi9nSvyOMrlSeGGWDiH7rf3a7sIwplbvo/dlz9WCIjzIQAfy1RMf4S0X3yG724n5Ghu2GmEl5NJIV6O9sZQ==}
|
resolution: {integrity: sha512-b5mvSWCI+XVKiz5WhnBCY3RJ4ZwfjAidU0yVlKa3d3MSgKmH1hC3tBGEAtYyN5mqL7N0G5x0BOUYyO8CEupWgg==}
|
||||||
|
|
||||||
'@formatjs/icu-messageformat-parser@2.11.4':
|
'@formatjs/icu-messageformat-parser@3.5.1':
|
||||||
resolution: {integrity: sha512-7kR78cRrPNB4fjGFZg3Rmj5aah8rQj9KPzuLsmcSn4ipLXQvC04keycTI1F7kJYDwIXtT2+7IDEto842CfZBtw==}
|
resolution: {integrity: sha512-sSDmSvmmoVQ92XqWb499KrIhv/vLisJU8ITFrx7T7NZHUmMY7EL9xgRowAosaljhqnj/5iufG24QrdzB6X3ItA==}
|
||||||
|
|
||||||
'@formatjs/icu-skeleton-parser@1.8.16':
|
'@formatjs/icu-skeleton-parser@2.1.1':
|
||||||
resolution: {integrity: sha512-H13E9Xl+PxBd8D5/6TVUluSpxGNvFSlN/b3coUp0e0JpuWXXnQDiavIpY3NnvSp4xhEMoXyyBvVfdFX8jglOHQ==}
|
resolution: {integrity: sha512-PSFABlcNefjI6yyk8f7nyX1DC7NHmq6WaCHZLySEXBrXuLOB2f935YsnzuPjlz+ibhb9yWTdPeVX1OVcj24w2Q==}
|
||||||
|
|
||||||
'@formatjs/intl-localematcher@0.5.10':
|
'@formatjs/intl-localematcher@0.5.10':
|
||||||
resolution: {integrity: sha512-af3qATX+m4Rnd9+wHcjJ4w2ijq+rAVP3CCinJQvFv1kgSu1W6jypUmvleJxcewdxmutM8dmIRZFxO/IQBZmP2Q==}
|
resolution: {integrity: sha512-af3qATX+m4Rnd9+wHcjJ4w2ijq+rAVP3CCinJQvFv1kgSu1W6jypUmvleJxcewdxmutM8dmIRZFxO/IQBZmP2Q==}
|
||||||
|
|
||||||
'@formatjs/intl-localematcher@0.6.2':
|
'@formatjs/intl-localematcher@0.8.1':
|
||||||
resolution: {integrity: sha512-XOMO2Hupl0wdd172Y06h6kLpBz6Dv+J4okPLl4LPtzbr8f66WbIoy4ev98EBuZ6ZK4h5ydTN6XneT4QVpD7cdA==}
|
resolution: {integrity: sha512-xwEuwQFdtSq1UKtQnyTZWC+eHdv7Uygoa+H2k/9uzBVQjDyp9r20LNDNKedWXll7FssT3GRHvqsdJGYSUWqYFA==}
|
||||||
|
|
||||||
'@humanfs/core@0.19.1':
|
'@humanfs/core@0.19.1':
|
||||||
resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==}
|
resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==}
|
||||||
@@ -1225,6 +1234,88 @@ packages:
|
|||||||
peerDependencies:
|
peerDependencies:
|
||||||
'@opentelemetry/api': ^1.1.0
|
'@opentelemetry/api': ^1.1.0
|
||||||
|
|
||||||
|
'@parcel/watcher-android-arm64@2.5.6':
|
||||||
|
resolution: {integrity: sha512-YQxSS34tPF/6ZG7r/Ih9xy+kP/WwediEUsqmtf0cuCV5TPPKw/PQHRhueUo6JdeFJaqV3pyjm0GdYjZotbRt/A==}
|
||||||
|
engines: {node: '>= 10.0.0'}
|
||||||
|
cpu: [arm64]
|
||||||
|
os: [android]
|
||||||
|
|
||||||
|
'@parcel/watcher-darwin-arm64@2.5.6':
|
||||||
|
resolution: {integrity: sha512-Z2ZdrnwyXvvvdtRHLmM4knydIdU9adO3D4n/0cVipF3rRiwP+3/sfzpAwA/qKFL6i1ModaabkU7IbpeMBgiVEA==}
|
||||||
|
engines: {node: '>= 10.0.0'}
|
||||||
|
cpu: [arm64]
|
||||||
|
os: [darwin]
|
||||||
|
|
||||||
|
'@parcel/watcher-darwin-x64@2.5.6':
|
||||||
|
resolution: {integrity: sha512-HgvOf3W9dhithcwOWX9uDZyn1lW9R+7tPZ4sug+NGrGIo4Rk1hAXLEbcH1TQSqxts0NYXXlOWqVpvS1SFS4fRg==}
|
||||||
|
engines: {node: '>= 10.0.0'}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [darwin]
|
||||||
|
|
||||||
|
'@parcel/watcher-freebsd-x64@2.5.6':
|
||||||
|
resolution: {integrity: sha512-vJVi8yd/qzJxEKHkeemh7w3YAn6RJCtYlE4HPMoVnCpIXEzSrxErBW5SJBgKLbXU3WdIpkjBTeUNtyBVn8TRng==}
|
||||||
|
engines: {node: '>= 10.0.0'}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [freebsd]
|
||||||
|
|
||||||
|
'@parcel/watcher-linux-arm-glibc@2.5.6':
|
||||||
|
resolution: {integrity: sha512-9JiYfB6h6BgV50CCfasfLf/uvOcJskMSwcdH1PHH9rvS1IrNy8zad6IUVPVUfmXr+u+Km9IxcfMLzgdOudz9EQ==}
|
||||||
|
engines: {node: '>= 10.0.0'}
|
||||||
|
cpu: [arm]
|
||||||
|
os: [linux]
|
||||||
|
|
||||||
|
'@parcel/watcher-linux-arm-musl@2.5.6':
|
||||||
|
resolution: {integrity: sha512-Ve3gUCG57nuUUSyjBq/MAM0CzArtuIOxsBdQ+ftz6ho8n7s1i9E1Nmk/xmP323r2YL0SONs1EuwqBp2u1k5fxg==}
|
||||||
|
engines: {node: '>= 10.0.0'}
|
||||||
|
cpu: [arm]
|
||||||
|
os: [linux]
|
||||||
|
|
||||||
|
'@parcel/watcher-linux-arm64-glibc@2.5.6':
|
||||||
|
resolution: {integrity: sha512-f2g/DT3NhGPdBmMWYoxixqYr3v/UXcmLOYy16Bx0TM20Tchduwr4EaCbmxh1321TABqPGDpS8D/ggOTaljijOA==}
|
||||||
|
engines: {node: '>= 10.0.0'}
|
||||||
|
cpu: [arm64]
|
||||||
|
os: [linux]
|
||||||
|
|
||||||
|
'@parcel/watcher-linux-arm64-musl@2.5.6':
|
||||||
|
resolution: {integrity: sha512-qb6naMDGlbCwdhLj6hgoVKJl2odL34z2sqkC7Z6kzir8b5W65WYDpLB6R06KabvZdgoHI/zxke4b3zR0wAbDTA==}
|
||||||
|
engines: {node: '>= 10.0.0'}
|
||||||
|
cpu: [arm64]
|
||||||
|
os: [linux]
|
||||||
|
|
||||||
|
'@parcel/watcher-linux-x64-glibc@2.5.6':
|
||||||
|
resolution: {integrity: sha512-kbT5wvNQlx7NaGjzPFu8nVIW1rWqV780O7ZtkjuWaPUgpv2NMFpjYERVi0UYj1msZNyCzGlaCWEtzc+exjMGbQ==}
|
||||||
|
engines: {node: '>= 10.0.0'}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [linux]
|
||||||
|
|
||||||
|
'@parcel/watcher-linux-x64-musl@2.5.6':
|
||||||
|
resolution: {integrity: sha512-1JRFeC+h7RdXwldHzTsmdtYR/Ku8SylLgTU/reMuqdVD7CtLwf0VR1FqeprZ0eHQkO0vqsbvFLXUmYm/uNKJBg==}
|
||||||
|
engines: {node: '>= 10.0.0'}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [linux]
|
||||||
|
|
||||||
|
'@parcel/watcher-win32-arm64@2.5.6':
|
||||||
|
resolution: {integrity: sha512-3ukyebjc6eGlw9yRt678DxVF7rjXatWiHvTXqphZLvo7aC5NdEgFufVwjFfY51ijYEWpXbqF5jtrK275z52D4Q==}
|
||||||
|
engines: {node: '>= 10.0.0'}
|
||||||
|
cpu: [arm64]
|
||||||
|
os: [win32]
|
||||||
|
|
||||||
|
'@parcel/watcher-win32-ia32@2.5.6':
|
||||||
|
resolution: {integrity: sha512-k35yLp1ZMwwee3Ez/pxBi5cf4AoBKYXj00CZ80jUz5h8prpiaQsiRPKQMxoLstNuqe2vR4RNPEAEcjEFzhEz/g==}
|
||||||
|
engines: {node: '>= 10.0.0'}
|
||||||
|
cpu: [ia32]
|
||||||
|
os: [win32]
|
||||||
|
|
||||||
|
'@parcel/watcher-win32-x64@2.5.6':
|
||||||
|
resolution: {integrity: sha512-hbQlYcCq5dlAX9Qx+kFb0FHue6vbjlf0FrNzSKdYK2APUf7tGfGxQCk2ihEREmbR6ZMc0MVAD5RIX/41gpUzTw==}
|
||||||
|
engines: {node: '>= 10.0.0'}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [win32]
|
||||||
|
|
||||||
|
'@parcel/watcher@2.5.6':
|
||||||
|
resolution: {integrity: sha512-tmmZ3lQxAe/k/+rNnXQRawJ4NjxO2hqiOLTHvWchtGZULp4RyFeh6aU4XdOYBFe2KE1oShQTv4AblOs2iOrNnQ==}
|
||||||
|
engines: {node: '>= 10.0.0'}
|
||||||
|
|
||||||
'@prisma/instrumentation@5.22.0':
|
'@prisma/instrumentation@5.22.0':
|
||||||
resolution: {integrity: sha512-LxccF392NN37ISGxIurUljZSh1YWnphO34V5a0+T7FVQG2u9bhAXRTJpgmQ3483woVhkraQZFF7cbRrpbw/F4Q==}
|
resolution: {integrity: sha512-LxccF392NN37ISGxIurUljZSh1YWnphO34V5a0+T7FVQG2u9bhAXRTJpgmQ3483woVhkraQZFF7cbRrpbw/F4Q==}
|
||||||
|
|
||||||
@@ -1380,6 +1471,9 @@ packages:
|
|||||||
'@rushstack/eslint-patch@1.15.0':
|
'@rushstack/eslint-patch@1.15.0':
|
||||||
resolution: {integrity: sha512-ojSshQPKwVvSMR8yT2L/QtUkV5SXi/IfDiJ4/8d6UbTPjiHVmxZzUAzGD8Tzks1b9+qQkZa0isUOvYObedITaw==}
|
resolution: {integrity: sha512-ojSshQPKwVvSMR8yT2L/QtUkV5SXi/IfDiJ4/8d6UbTPjiHVmxZzUAzGD8Tzks1b9+qQkZa0isUOvYObedITaw==}
|
||||||
|
|
||||||
|
'@schummar/icu-type-parser@1.21.5':
|
||||||
|
resolution: {integrity: sha512-bXHSaW5jRTmke9Vd0h5P7BtWZG9Znqb8gSDxZnxaGSJnGwPLDPfS+3g0BKzeWqzgZPsIVZkM7m2tbo18cm5HBw==}
|
||||||
|
|
||||||
'@sentry-internal/browser-utils@8.55.0':
|
'@sentry-internal/browser-utils@8.55.0':
|
||||||
resolution: {integrity: sha512-ROgqtQfpH/82AQIpESPqPQe0UyWywKJsmVIqi3c5Fh+zkds5LUxnssTj3yNd1x+kxaPDVB023jAP+3ibNgeNDw==}
|
resolution: {integrity: sha512-ROgqtQfpH/82AQIpESPqPQe0UyWywKJsmVIqi3c5Fh+zkds5LUxnssTj3yNd1x+kxaPDVB023jAP+3ibNgeNDw==}
|
||||||
engines: {node: '>=14.18'}
|
engines: {node: '>=14.18'}
|
||||||
@@ -1498,12 +1592,84 @@ packages:
|
|||||||
'@standard-schema/spec@1.1.0':
|
'@standard-schema/spec@1.1.0':
|
||||||
resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==}
|
resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==}
|
||||||
|
|
||||||
|
'@swc/core-darwin-arm64@1.15.11':
|
||||||
|
resolution: {integrity: sha512-QoIupRWVH8AF1TgxYyeA5nS18dtqMuxNwchjBIwJo3RdwLEFiJq6onOx9JAxHtuPwUkIVuU2Xbp+jCJ7Vzmgtg==}
|
||||||
|
engines: {node: '>=10'}
|
||||||
|
cpu: [arm64]
|
||||||
|
os: [darwin]
|
||||||
|
|
||||||
|
'@swc/core-darwin-x64@1.15.11':
|
||||||
|
resolution: {integrity: sha512-S52Gu1QtPSfBYDiejlcfp9GlN+NjTZBRRNsz8PNwBgSE626/FUf2PcllVUix7jqkoMC+t0rS8t+2/aSWlMuQtA==}
|
||||||
|
engines: {node: '>=10'}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [darwin]
|
||||||
|
|
||||||
|
'@swc/core-linux-arm-gnueabihf@1.15.11':
|
||||||
|
resolution: {integrity: sha512-lXJs8oXo6Z4yCpimpQ8vPeCjkgoHu5NoMvmJZ8qxDyU99KVdg6KwU9H79vzrmB+HfH+dCZ7JGMqMF//f8Cfvdg==}
|
||||||
|
engines: {node: '>=10'}
|
||||||
|
cpu: [arm]
|
||||||
|
os: [linux]
|
||||||
|
|
||||||
|
'@swc/core-linux-arm64-gnu@1.15.11':
|
||||||
|
resolution: {integrity: sha512-chRsz1K52/vj8Mfq/QOugVphlKPWlMh10V99qfH41hbGvwAU6xSPd681upO4bKiOr9+mRIZZW+EfJqY42ZzRyA==}
|
||||||
|
engines: {node: '>=10'}
|
||||||
|
cpu: [arm64]
|
||||||
|
os: [linux]
|
||||||
|
|
||||||
|
'@swc/core-linux-arm64-musl@1.15.11':
|
||||||
|
resolution: {integrity: sha512-PYftgsTaGnfDK4m6/dty9ryK1FbLk+LosDJ/RJR2nkXGc8rd+WenXIlvHjWULiBVnS1RsjHHOXmTS4nDhe0v0w==}
|
||||||
|
engines: {node: '>=10'}
|
||||||
|
cpu: [arm64]
|
||||||
|
os: [linux]
|
||||||
|
|
||||||
|
'@swc/core-linux-x64-gnu@1.15.11':
|
||||||
|
resolution: {integrity: sha512-DKtnJKIHiZdARyTKiX7zdRjiDS1KihkQWatQiCHMv+zc2sfwb4Glrodx2VLOX4rsa92NLR0Sw8WLcPEMFY1szQ==}
|
||||||
|
engines: {node: '>=10'}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [linux]
|
||||||
|
|
||||||
|
'@swc/core-linux-x64-musl@1.15.11':
|
||||||
|
resolution: {integrity: sha512-mUjjntHj4+8WBaiDe5UwRNHuEzLjIWBTSGTw0JT9+C9/Yyuh4KQqlcEQ3ro6GkHmBGXBFpGIj/o5VMyRWfVfWw==}
|
||||||
|
engines: {node: '>=10'}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [linux]
|
||||||
|
|
||||||
|
'@swc/core-win32-arm64-msvc@1.15.11':
|
||||||
|
resolution: {integrity: sha512-ZkNNG5zL49YpaFzfl6fskNOSxtcZ5uOYmWBkY4wVAvgbSAQzLRVBp+xArGWh2oXlY/WgL99zQSGTv7RI5E6nzA==}
|
||||||
|
engines: {node: '>=10'}
|
||||||
|
cpu: [arm64]
|
||||||
|
os: [win32]
|
||||||
|
|
||||||
|
'@swc/core-win32-ia32-msvc@1.15.11':
|
||||||
|
resolution: {integrity: sha512-6XnzORkZCQzvTQ6cPrU7iaT9+i145oLwnin8JrfsLG41wl26+5cNQ2XV3zcbrnFEV6esjOceom9YO1w9mGJByw==}
|
||||||
|
engines: {node: '>=10'}
|
||||||
|
cpu: [ia32]
|
||||||
|
os: [win32]
|
||||||
|
|
||||||
|
'@swc/core-win32-x64-msvc@1.15.11':
|
||||||
|
resolution: {integrity: sha512-IQ2n6af7XKLL6P1gIeZACskSxK8jWtoKpJWLZmdXTDj1MGzktUy4i+FvpdtxFmJWNavRWH1VmTr6kAubRDHeKw==}
|
||||||
|
engines: {node: '>=10'}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [win32]
|
||||||
|
|
||||||
|
'@swc/core@1.15.11':
|
||||||
|
resolution: {integrity: sha512-iLmLTodbYxU39HhMPaMUooPwO/zqJWvsqkrXv1ZI38rMb048p6N7qtAtTp37sw9NzSrvH6oli8EdDygo09IZ/w==}
|
||||||
|
engines: {node: '>=10'}
|
||||||
|
peerDependencies:
|
||||||
|
'@swc/helpers': '>=0.5.17'
|
||||||
|
peerDependenciesMeta:
|
||||||
|
'@swc/helpers':
|
||||||
|
optional: true
|
||||||
|
|
||||||
'@swc/counter@0.1.3':
|
'@swc/counter@0.1.3':
|
||||||
resolution: {integrity: sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==}
|
resolution: {integrity: sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==}
|
||||||
|
|
||||||
'@swc/helpers@0.5.15':
|
'@swc/helpers@0.5.15':
|
||||||
resolution: {integrity: sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==}
|
resolution: {integrity: sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==}
|
||||||
|
|
||||||
|
'@swc/types@0.1.25':
|
||||||
|
resolution: {integrity: sha512-iAoY/qRhNH8a/hBvm3zKj9qQ4oc2+3w1unPJa2XvTK3XjeLXtzcCingVPw/9e5mn1+0yPqxcBGp9Jf0pkfMb1g==}
|
||||||
|
|
||||||
'@testing-library/dom@10.4.1':
|
'@testing-library/dom@10.4.1':
|
||||||
resolution: {integrity: sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==}
|
resolution: {integrity: sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
@@ -2842,6 +3008,9 @@ packages:
|
|||||||
resolution: {integrity: sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==}
|
resolution: {integrity: sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
|
|
||||||
|
icu-minify@4.8.2:
|
||||||
|
resolution: {integrity: sha512-LHBQV+skKkjZSPd590pZ7ZAHftUgda3eFjeuNwA8/15L8T8loCNBktKQyTlkodAU86KovFXeg/9WntlAo5wA5A==}
|
||||||
|
|
||||||
ignore@5.3.2:
|
ignore@5.3.2:
|
||||||
resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==}
|
resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==}
|
||||||
engines: {node: '>= 4'}
|
engines: {node: '>= 4'}
|
||||||
@@ -2876,8 +3045,8 @@ packages:
|
|||||||
resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==}
|
resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
|
|
||||||
intl-messageformat@10.7.18:
|
intl-messageformat@11.1.2:
|
||||||
resolution: {integrity: sha512-m3Ofv/X/tV8Y3tHXLohcuVuhWKo7BBq62cqY15etqmLxg2DZ34AGGgQDeR+SCta2+zICb1NX83af0GJmbQ1++g==}
|
resolution: {integrity: sha512-ucSrQmZGAxfiBHfBRXW/k7UC8MaGFlEj4Ry1tKiDcmgwQm1y3EDl40u+4VNHYomxJQMJi9NEI3riDRlth96jKg==}
|
||||||
|
|
||||||
is-array-buffer@3.0.5:
|
is-array-buffer@3.0.5:
|
||||||
resolution: {integrity: sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==}
|
resolution: {integrity: sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==}
|
||||||
@@ -3307,11 +3476,18 @@ packages:
|
|||||||
neo-async@2.6.2:
|
neo-async@2.6.2:
|
||||||
resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==}
|
resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==}
|
||||||
|
|
||||||
next-intl@3.26.5:
|
next-intl-swc-plugin-extractor@4.8.2:
|
||||||
resolution: {integrity: sha512-EQlCIfY0jOhRldiFxwSXG+ImwkQtDEfQeSOEQp6ieAGSLWGlgjdb/Ck/O7wMfC430ZHGeUKVKax8KGusTPKCgg==}
|
resolution: {integrity: sha512-sHDs36L1VZmFHj3tPHsD+KZJtnsRudHlNvT0ieIe3iFVn5OpGLTxW3d/Zc/2LXSj5GpGuR6wQeikbhFjU9tMQQ==}
|
||||||
|
|
||||||
|
next-intl@4.8.2:
|
||||||
|
resolution: {integrity: sha512-GuuwyvyEI49/oehQbBXEoY8KSIYCzmfMLhmIwhMXTb+yeBmly1PnJcpgph3KczQ+HTJMXwXCmkizgtT8jBMf3A==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
next: ^10.0.0 || ^11.0.0 || ^12.0.0 || ^13.0.0 || ^14.0.0 || ^15.0.0
|
next: ^12.0.0 || ^13.0.0 || ^14.0.0 || ^15.0.0 || ^16.0.0
|
||||||
react: ^16.8.0 || ^17.0.0 || ^18.0.0 || >=19.0.0-rc <19.0.0 || ^19.0.0
|
react: ^16.8.0 || ^17.0.0 || ^18.0.0 || >=19.0.0-rc <19.0.0 || ^19.0.0
|
||||||
|
typescript: ^5.0.0
|
||||||
|
peerDependenciesMeta:
|
||||||
|
typescript:
|
||||||
|
optional: true
|
||||||
|
|
||||||
next@15.1.6:
|
next@15.1.6:
|
||||||
resolution: {integrity: sha512-Hch4wzbaX0vKQtalpXvUiw5sYivBy4cm5rzUKrBnUB/y436LGrvOUqYvlSeNVCWFO/770gDlltR9gqZH62ct4Q==}
|
resolution: {integrity: sha512-Hch4wzbaX0vKQtalpXvUiw5sYivBy4cm5rzUKrBnUB/y436LGrvOUqYvlSeNVCWFO/770gDlltR9gqZH62ct4Q==}
|
||||||
@@ -3334,6 +3510,9 @@ packages:
|
|||||||
sass:
|
sass:
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
node-addon-api@7.1.1:
|
||||||
|
resolution: {integrity: sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==}
|
||||||
|
|
||||||
node-fetch@2.7.0:
|
node-fetch@2.7.0:
|
||||||
resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==}
|
resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==}
|
||||||
engines: {node: 4.x || >=6.0.0}
|
engines: {node: 4.x || >=6.0.0}
|
||||||
@@ -3510,6 +3689,9 @@ packages:
|
|||||||
pkg-types@1.3.1:
|
pkg-types@1.3.1:
|
||||||
resolution: {integrity: sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==}
|
resolution: {integrity: sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==}
|
||||||
|
|
||||||
|
po-parser@2.1.1:
|
||||||
|
resolution: {integrity: sha512-ECF4zHLbUItpUgE3OTtLKlPjeBN+fKEczj2zYjDfCGOzicNs0GK3Vg2IoAYwx7LH/XYw43fZQP6xnZ4TkNxSLQ==}
|
||||||
|
|
||||||
possible-typed-array-names@1.1.0:
|
possible-typed-array-names@1.1.0:
|
||||||
resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==}
|
resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
@@ -4171,10 +4353,10 @@ packages:
|
|||||||
uri-js@4.4.1:
|
uri-js@4.4.1:
|
||||||
resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==}
|
resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==}
|
||||||
|
|
||||||
use-intl@3.26.5:
|
use-intl@4.8.2:
|
||||||
resolution: {integrity: sha512-OdsJnC/znPvHCHLQH/duvQNXnP1w0hPfS+tkSi3mAbfjYBGh4JnyfdwkQBfIVf7t8gs9eSX/CntxUMvtKdG2MQ==}
|
resolution: {integrity: sha512-3VNXZgDnPFqhIYosQ9W1Hc6K5q+ZelMfawNbexdwL/dY7BTHbceLUBX5Eeex9lgogxTp0pf1SjHuhYNAjr9H3g==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
react: ^16.8.0 || ^17.0.0 || ^18.0.0 || >=19.0.0-rc <19.0.0 || ^19.0.0
|
react: ^17.0.0 || ^18.0.0 || >=19.0.0-rc <19.0.0 || ^19.0.0
|
||||||
|
|
||||||
util-deprecate@1.0.2:
|
util-deprecate@1.0.2:
|
||||||
resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
|
resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
|
||||||
@@ -4957,34 +5139,35 @@ snapshots:
|
|||||||
|
|
||||||
'@exodus/bytes@1.10.0': {}
|
'@exodus/bytes@1.10.0': {}
|
||||||
|
|
||||||
'@formatjs/ecma402-abstract@2.3.6':
|
'@formatjs/ecma402-abstract@3.1.1':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@formatjs/fast-memoize': 2.2.7
|
'@formatjs/fast-memoize': 3.1.0
|
||||||
'@formatjs/intl-localematcher': 0.6.2
|
'@formatjs/intl-localematcher': 0.8.1
|
||||||
decimal.js: 10.6.0
|
decimal.js: 10.6.0
|
||||||
tslib: 2.8.1
|
tslib: 2.8.1
|
||||||
|
|
||||||
'@formatjs/fast-memoize@2.2.7':
|
'@formatjs/fast-memoize@3.1.0':
|
||||||
dependencies:
|
dependencies:
|
||||||
tslib: 2.8.1
|
tslib: 2.8.1
|
||||||
|
|
||||||
'@formatjs/icu-messageformat-parser@2.11.4':
|
'@formatjs/icu-messageformat-parser@3.5.1':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@formatjs/ecma402-abstract': 2.3.6
|
'@formatjs/ecma402-abstract': 3.1.1
|
||||||
'@formatjs/icu-skeleton-parser': 1.8.16
|
'@formatjs/icu-skeleton-parser': 2.1.1
|
||||||
tslib: 2.8.1
|
tslib: 2.8.1
|
||||||
|
|
||||||
'@formatjs/icu-skeleton-parser@1.8.16':
|
'@formatjs/icu-skeleton-parser@2.1.1':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@formatjs/ecma402-abstract': 2.3.6
|
'@formatjs/ecma402-abstract': 3.1.1
|
||||||
tslib: 2.8.1
|
tslib: 2.8.1
|
||||||
|
|
||||||
'@formatjs/intl-localematcher@0.5.10':
|
'@formatjs/intl-localematcher@0.5.10':
|
||||||
dependencies:
|
dependencies:
|
||||||
tslib: 2.8.1
|
tslib: 2.8.1
|
||||||
|
|
||||||
'@formatjs/intl-localematcher@0.6.2':
|
'@formatjs/intl-localematcher@0.8.1':
|
||||||
dependencies:
|
dependencies:
|
||||||
|
'@formatjs/fast-memoize': 3.1.0
|
||||||
tslib: 2.8.1
|
tslib: 2.8.1
|
||||||
|
|
||||||
'@humanfs/core@0.19.1': {}
|
'@humanfs/core@0.19.1': {}
|
||||||
@@ -5464,6 +5647,66 @@ snapshots:
|
|||||||
'@opentelemetry/api': 1.9.0
|
'@opentelemetry/api': 1.9.0
|
||||||
'@opentelemetry/core': 1.30.1(@opentelemetry/api@1.9.0)
|
'@opentelemetry/core': 1.30.1(@opentelemetry/api@1.9.0)
|
||||||
|
|
||||||
|
'@parcel/watcher-android-arm64@2.5.6':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@parcel/watcher-darwin-arm64@2.5.6':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@parcel/watcher-darwin-x64@2.5.6':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@parcel/watcher-freebsd-x64@2.5.6':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@parcel/watcher-linux-arm-glibc@2.5.6':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@parcel/watcher-linux-arm-musl@2.5.6':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@parcel/watcher-linux-arm64-glibc@2.5.6':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@parcel/watcher-linux-arm64-musl@2.5.6':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@parcel/watcher-linux-x64-glibc@2.5.6':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@parcel/watcher-linux-x64-musl@2.5.6':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@parcel/watcher-win32-arm64@2.5.6':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@parcel/watcher-win32-ia32@2.5.6':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@parcel/watcher-win32-x64@2.5.6':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@parcel/watcher@2.5.6':
|
||||||
|
dependencies:
|
||||||
|
detect-libc: 2.1.2
|
||||||
|
is-glob: 4.0.3
|
||||||
|
node-addon-api: 7.1.1
|
||||||
|
picomatch: 4.0.3
|
||||||
|
optionalDependencies:
|
||||||
|
'@parcel/watcher-android-arm64': 2.5.6
|
||||||
|
'@parcel/watcher-darwin-arm64': 2.5.6
|
||||||
|
'@parcel/watcher-darwin-x64': 2.5.6
|
||||||
|
'@parcel/watcher-freebsd-x64': 2.5.6
|
||||||
|
'@parcel/watcher-linux-arm-glibc': 2.5.6
|
||||||
|
'@parcel/watcher-linux-arm-musl': 2.5.6
|
||||||
|
'@parcel/watcher-linux-arm64-glibc': 2.5.6
|
||||||
|
'@parcel/watcher-linux-arm64-musl': 2.5.6
|
||||||
|
'@parcel/watcher-linux-x64-glibc': 2.5.6
|
||||||
|
'@parcel/watcher-linux-x64-musl': 2.5.6
|
||||||
|
'@parcel/watcher-win32-arm64': 2.5.6
|
||||||
|
'@parcel/watcher-win32-ia32': 2.5.6
|
||||||
|
'@parcel/watcher-win32-x64': 2.5.6
|
||||||
|
|
||||||
'@prisma/instrumentation@5.22.0':
|
'@prisma/instrumentation@5.22.0':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@opentelemetry/api': 1.9.0
|
'@opentelemetry/api': 1.9.0
|
||||||
@@ -5573,6 +5816,8 @@ snapshots:
|
|||||||
|
|
||||||
'@rushstack/eslint-patch@1.15.0': {}
|
'@rushstack/eslint-patch@1.15.0': {}
|
||||||
|
|
||||||
|
'@schummar/icu-type-parser@1.21.5': {}
|
||||||
|
|
||||||
'@sentry-internal/browser-utils@8.55.0':
|
'@sentry-internal/browser-utils@8.55.0':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@sentry/core': 8.55.0
|
'@sentry/core': 8.55.0
|
||||||
@@ -5758,12 +6003,62 @@ snapshots:
|
|||||||
|
|
||||||
'@standard-schema/spec@1.1.0': {}
|
'@standard-schema/spec@1.1.0': {}
|
||||||
|
|
||||||
|
'@swc/core-darwin-arm64@1.15.11':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@swc/core-darwin-x64@1.15.11':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@swc/core-linux-arm-gnueabihf@1.15.11':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@swc/core-linux-arm64-gnu@1.15.11':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@swc/core-linux-arm64-musl@1.15.11':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@swc/core-linux-x64-gnu@1.15.11':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@swc/core-linux-x64-musl@1.15.11':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@swc/core-win32-arm64-msvc@1.15.11':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@swc/core-win32-ia32-msvc@1.15.11':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@swc/core-win32-x64-msvc@1.15.11':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@swc/core@1.15.11':
|
||||||
|
dependencies:
|
||||||
|
'@swc/counter': 0.1.3
|
||||||
|
'@swc/types': 0.1.25
|
||||||
|
optionalDependencies:
|
||||||
|
'@swc/core-darwin-arm64': 1.15.11
|
||||||
|
'@swc/core-darwin-x64': 1.15.11
|
||||||
|
'@swc/core-linux-arm-gnueabihf': 1.15.11
|
||||||
|
'@swc/core-linux-arm64-gnu': 1.15.11
|
||||||
|
'@swc/core-linux-arm64-musl': 1.15.11
|
||||||
|
'@swc/core-linux-x64-gnu': 1.15.11
|
||||||
|
'@swc/core-linux-x64-musl': 1.15.11
|
||||||
|
'@swc/core-win32-arm64-msvc': 1.15.11
|
||||||
|
'@swc/core-win32-ia32-msvc': 1.15.11
|
||||||
|
'@swc/core-win32-x64-msvc': 1.15.11
|
||||||
|
|
||||||
'@swc/counter@0.1.3': {}
|
'@swc/counter@0.1.3': {}
|
||||||
|
|
||||||
'@swc/helpers@0.5.15':
|
'@swc/helpers@0.5.15':
|
||||||
dependencies:
|
dependencies:
|
||||||
tslib: 2.8.1
|
tslib: 2.8.1
|
||||||
|
|
||||||
|
'@swc/types@0.1.25':
|
||||||
|
dependencies:
|
||||||
|
'@swc/counter': 0.1.3
|
||||||
|
|
||||||
'@testing-library/dom@10.4.1':
|
'@testing-library/dom@10.4.1':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/code-frame': 7.28.6
|
'@babel/code-frame': 7.28.6
|
||||||
@@ -6640,8 +6935,7 @@ snapshots:
|
|||||||
|
|
||||||
detect-indent@6.1.0: {}
|
detect-indent@6.1.0: {}
|
||||||
|
|
||||||
detect-libc@2.1.2:
|
detect-libc@2.1.2: {}
|
||||||
optional: true
|
|
||||||
|
|
||||||
didyoumean@1.2.2: {}
|
didyoumean@1.2.2: {}
|
||||||
|
|
||||||
@@ -7340,6 +7634,10 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
safer-buffer: 2.1.2
|
safer-buffer: 2.1.2
|
||||||
|
|
||||||
|
icu-minify@4.8.2:
|
||||||
|
dependencies:
|
||||||
|
'@formatjs/icu-messageformat-parser': 3.5.1
|
||||||
|
|
||||||
ignore@5.3.2: {}
|
ignore@5.3.2: {}
|
||||||
|
|
||||||
ignore@7.0.5: {}
|
ignore@7.0.5: {}
|
||||||
@@ -7370,11 +7668,11 @@ snapshots:
|
|||||||
hasown: 2.0.2
|
hasown: 2.0.2
|
||||||
side-channel: 1.1.0
|
side-channel: 1.1.0
|
||||||
|
|
||||||
intl-messageformat@10.7.18:
|
intl-messageformat@11.1.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@formatjs/ecma402-abstract': 2.3.6
|
'@formatjs/ecma402-abstract': 3.1.1
|
||||||
'@formatjs/fast-memoize': 2.2.7
|
'@formatjs/fast-memoize': 3.1.0
|
||||||
'@formatjs/icu-messageformat-parser': 2.11.4
|
'@formatjs/icu-messageformat-parser': 3.5.1
|
||||||
tslib: 2.8.1
|
tslib: 2.8.1
|
||||||
|
|
||||||
is-array-buffer@3.0.5:
|
is-array-buffer@3.0.5:
|
||||||
@@ -7789,13 +8087,24 @@ snapshots:
|
|||||||
|
|
||||||
neo-async@2.6.2: {}
|
neo-async@2.6.2: {}
|
||||||
|
|
||||||
next-intl@3.26.5(next@15.1.6(@babel/core@7.28.6)(@opentelemetry/api@1.9.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react@19.2.4):
|
next-intl-swc-plugin-extractor@4.8.2: {}
|
||||||
|
|
||||||
|
next-intl@4.8.2(next@15.1.6(@babel/core@7.28.6)(@opentelemetry/api@1.9.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react@19.2.4)(typescript@5.9.3):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@formatjs/intl-localematcher': 0.5.10
|
'@formatjs/intl-localematcher': 0.5.10
|
||||||
|
'@parcel/watcher': 2.5.6
|
||||||
|
'@swc/core': 1.15.11
|
||||||
|
icu-minify: 4.8.2
|
||||||
negotiator: 1.0.0
|
negotiator: 1.0.0
|
||||||
next: 15.1.6(@babel/core@7.28.6)(@opentelemetry/api@1.9.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
|
next: 15.1.6(@babel/core@7.28.6)(@opentelemetry/api@1.9.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
|
||||||
|
next-intl-swc-plugin-extractor: 4.8.2
|
||||||
|
po-parser: 2.1.1
|
||||||
react: 19.2.4
|
react: 19.2.4
|
||||||
use-intl: 3.26.5(react@19.2.4)
|
use-intl: 4.8.2(react@19.2.4)
|
||||||
|
optionalDependencies:
|
||||||
|
typescript: 5.9.3
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- '@swc/helpers'
|
||||||
|
|
||||||
next@15.1.6(@babel/core@7.28.6)(@opentelemetry/api@1.9.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4):
|
next@15.1.6(@babel/core@7.28.6)(@opentelemetry/api@1.9.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4):
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -7823,6 +8132,8 @@ snapshots:
|
|||||||
- '@babel/core'
|
- '@babel/core'
|
||||||
- babel-plugin-macros
|
- babel-plugin-macros
|
||||||
|
|
||||||
|
node-addon-api@7.1.1: {}
|
||||||
|
|
||||||
node-fetch@2.7.0:
|
node-fetch@2.7.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
whatwg-url: 5.0.0
|
whatwg-url: 5.0.0
|
||||||
@@ -7988,6 +8299,8 @@ snapshots:
|
|||||||
mlly: 1.8.0
|
mlly: 1.8.0
|
||||||
pathe: 2.0.3
|
pathe: 2.0.3
|
||||||
|
|
||||||
|
po-parser@2.1.1: {}
|
||||||
|
|
||||||
possible-typed-array-names@1.1.0: {}
|
possible-typed-array-names@1.1.0: {}
|
||||||
|
|
||||||
postcss-import@15.1.0(postcss@8.5.6):
|
postcss-import@15.1.0(postcss@8.5.6):
|
||||||
@@ -8636,7 +8949,7 @@ snapshots:
|
|||||||
|
|
||||||
tslib@2.8.1: {}
|
tslib@2.8.1: {}
|
||||||
|
|
||||||
tsup@8.5.1(jiti@2.6.1)(postcss@8.5.6)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.2):
|
tsup@8.5.1(@swc/core@1.15.11)(jiti@2.6.1)(postcss@8.5.6)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.2):
|
||||||
dependencies:
|
dependencies:
|
||||||
bundle-require: 5.1.0(esbuild@0.27.2)
|
bundle-require: 5.1.0(esbuild@0.27.2)
|
||||||
cac: 6.7.14
|
cac: 6.7.14
|
||||||
@@ -8656,6 +8969,7 @@ snapshots:
|
|||||||
tinyglobby: 0.2.15
|
tinyglobby: 0.2.15
|
||||||
tree-kill: 1.2.2
|
tree-kill: 1.2.2
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
|
'@swc/core': 1.15.11
|
||||||
postcss: 8.5.6
|
postcss: 8.5.6
|
||||||
typescript: 5.9.3
|
typescript: 5.9.3
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
@@ -8779,10 +9093,12 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
punycode: 2.3.1
|
punycode: 2.3.1
|
||||||
|
|
||||||
use-intl@3.26.5(react@19.2.4):
|
use-intl@4.8.2(react@19.2.4):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@formatjs/fast-memoize': 2.2.7
|
'@formatjs/fast-memoize': 3.1.0
|
||||||
intl-messageformat: 10.7.18
|
'@schummar/icu-type-parser': 1.21.5
|
||||||
|
icu-minify: 4.8.2
|
||||||
|
intl-messageformat: 11.1.2
|
||||||
react: 19.2.4
|
react: 19.2.4
|
||||||
|
|
||||||
util-deprecate@1.0.2: {}
|
util-deprecate@1.0.2: {}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import * as fs from "fs";
|
import * as fs from "fs";
|
||||||
import * as path from "path";
|
import * as path from "path";
|
||||||
import { execSync } from "child_process";
|
|
||||||
|
|
||||||
const tag = process.env.GITHUB_REF_NAME || process.env.TAG;
|
const tag = process.env.GITHUB_REF_NAME || process.env.TAG;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user