diff --git a/.env.development b/.env.development index fbd5d135e..a14ce51f9 100644 --- a/.env.development +++ b/.env.development @@ -23,8 +23,9 @@ API_HOST=0.0.0.0 # Website Configuration # ========================================== NEXT_PUBLIC_GRIDPILOT_MODE=alpha -NEXT_PUBLIC_SITE_URL=http://localhost:3001 -NEXT_PUBLIC_API_URL=http://localhost:3000 +NEXT_PUBLIC_SITE_URL=http://localhost:3000 +NEXT_PUBLIC_API_URL=http://localhost:3001 +NEXT_PUBLIC_API_BASE_URL=http://localhost:3001 NEXT_PUBLIC_DISCORD_URL=https://discord.gg/your-invite-code NEXT_TELEMETRY_DISABLED=1 diff --git a/apps/api/Dockerfile.dev b/apps/api/Dockerfile.dev index b6e7036b9..fd935162b 100644 --- a/apps/api/Dockerfile.dev +++ b/apps/api/Dockerfile.dev @@ -2,25 +2,13 @@ FROM node:20-alpine WORKDIR /app -# Install bash for better shell capabilities +ENV NPM_CONFIG_FUND=false \ + NPM_CONFIG_AUDIT=false \ + NPM_CONFIG_UPDATE_NOTIFIER=false + RUN apk add --no-cache bash -# Copy package manifests and install dependencies (incl. workspaces) -COPY package.json package-lock.json ./ -COPY apps/api/package.json apps/api/package.json -RUN npm ci --workspaces --include-workspace-root -RUN find ./node_modules -name "ts-node-dev" -print || true # Debugging line - -# Copy sources for development (monorepo) -COPY apps/api apps/api/ -COPY core core/ -COPY adapters adapters/ -COPY apps/api/tsconfig.json apps/api/ -COPY tsconfig.base.json ./ - EXPOSE 3000 EXPOSE 9229 -# Command to run the NestJS application in development with hot-reloading -# Run from the correct workspace context -CMD ["npm", "run", "start:dev", "--workspace=@gridpilot/api"] +CMD ["sh", "-lc", "npm run start:dev --workspace=@gridpilot/api"] diff --git a/apps/api/src/domain/league/presenters/LeagueScoringPresetsPresenter.ts b/apps/api/src/domain/league/presenters/LeagueScoringPresetsPresenter.ts index aa53d0e27..381235cee 100644 --- a/apps/api/src/domain/league/presenters/LeagueScoringPresetsPresenter.ts +++ b/apps/api/src/domain/league/presenters/LeagueScoringPresetsPresenter.ts @@ -1,5 +1,5 @@ import type { UseCaseOutputPort } from '@core/shared/application/UseCaseOutputPort'; -import type { ListLeagueScoringPresetsResult, LeagueScoringPreset } from '@core/racing/application/use-cases/ListLeagueScoringPresetsUseCase'; +import type { ListLeagueScoringPresetsResult } from '@core/racing/application/use-cases/ListLeagueScoringPresetsUseCase'; import type { LeagueScoringPresetsDTO } from '../dtos/LeagueScoringPresetsDTO'; export type LeagueScoringPresetsViewModel = LeagueScoringPresetsDTO; diff --git a/apps/api/src/domain/sponsor/SponsorProviders.ts b/apps/api/src/domain/sponsor/SponsorProviders.ts index e90f72c0c..caee31451 100644 --- a/apps/api/src/domain/sponsor/SponsorProviders.ts +++ b/apps/api/src/domain/sponsor/SponsorProviders.ts @@ -2,7 +2,7 @@ import { Provider } from '@nestjs/common'; import { SponsorService } from './SponsorService'; // Import core interfaces -import { NotificationService } from '@core/notifications/application/ports/NotificationService'; +import type { NotificationService } from '@core/notifications/application/ports/NotificationService'; import type { IPaymentRepository } from '@core/payments/domain/repositories/IPaymentRepository'; import type { IWalletRepository } from '@core/payments/domain/repositories/IWalletRepository'; // Remove the missing import @@ -170,7 +170,7 @@ export const SponsorProviders: Provider[] = [ { provide: NOTIFICATION_SERVICE_TOKEN, useFactory: (logger: Logger): NotificationService => ({ - async sendNotification(command: any): Promise { + async sendNotification(command: Parameters[0]): Promise { logger.info('[InMemoryNotificationService] sendNotification', { command }); }, }), diff --git a/apps/website/Dockerfile.dev b/apps/website/Dockerfile.dev index 963c78d2c..3b8ab9824 100644 --- a/apps/website/Dockerfile.dev +++ b/apps/website/Dockerfile.dev @@ -2,23 +2,12 @@ FROM node:20-alpine WORKDIR /app -# Install bash for better shell capabilities +ENV NPM_CONFIG_FUND=false \ + NPM_CONFIG_AUDIT=false \ + NPM_CONFIG_UPDATE_NOTIFIER=false + RUN apk add --no-cache bash -# Copy package manifests and install dependencies (incl. workspaces) -COPY package.json package-lock.json ./ -COPY apps/website/package.json apps/website/package.json -RUN npm ci --workspaces --include-workspace-root -RUN find ./node_modules -name "next" -print || true # Debugging line - -# Copy sources for development (monorepo) -COPY apps/website apps/website/ -COPY core core/ -COPY adapters adapters/ -COPY scripts scripts/ -COPY tsconfig.base.json ./ - EXPOSE 3000 -# Run from the correct workspace context -CMD ["npm", "run", "dev", "--workspace=@gridpilot/website"] \ No newline at end of file +CMD ["sh", "-lc", "npm run dev --workspace=@gridpilot/website"] \ No newline at end of file diff --git a/apps/website/app/page.tsx b/apps/website/app/page.tsx index 3263ef467..32e3a1e2a 100644 --- a/apps/website/app/page.tsx +++ b/apps/website/app/page.tsx @@ -17,7 +17,10 @@ import Button from '@/components/ui/Button'; import { ServiceFactory } from '@/lib/services/ServiceFactory'; export default async function HomePage() { - const baseUrl = process.env.NEXT_PUBLIC_API_BASE_URL || 'http://localhost:3001'; + const baseUrl = + process.env.API_BASE_URL ?? + process.env.NEXT_PUBLIC_API_BASE_URL ?? + 'http://api:3000'; const serviceFactory = new ServiceFactory(baseUrl); const sessionService = serviceFactory.createSessionService(); const landingService = serviceFactory.createLandingService(); diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml index 6b4cd2f01..a417b2105 100644 --- a/docker-compose.dev.yml +++ b/docker-compose.dev.yml @@ -1,5 +1,30 @@ services: + deps: + image: node:20-alpine + working_dir: /app + env_file: + - .env.development + environment: + - NODE_ENV=development + - NPM_CONFIG_FUND=false + - NPM_CONFIG_AUDIT=false + - NPM_CONFIG_UPDATE_NOTIFIER=false + volumes: + - ./:/app + - dev_node_modules:/app/node_modules + - dev_npm_cache:/root/.npm + command: + [ + "sh", + "-lc", + "set -e; LOCK_HASH=\"$$(sha1sum package-lock.json | awk '{print $$1}')\"; MARKER=\"node_modules/.gridpilot_lock_hash_dev\"; if [ -f \"$$MARKER\" ] && [ \"$$(cat \"$$MARKER\")\" = \"$$LOCK_HASH\" ]; then echo \"[deps] node_modules up-to-date\"; else echo \"[deps] installing api+website deps (slow first time)\"; npm install --no-package-lock --workspace=./apps/api --workspace=./apps/website --include-workspace-root --no-audit --fund=false --prefer-offline; node -e \"require.resolve('ts-node-dev')\"; node -e \"require.resolve('next')\"; echo \"$$LOCK_HASH\" > \"$$MARKER\"; fi", + ] + networks: + - gridpilot-network + restart: "no" + api: + image: gridpilot-api-dev build: context: . dockerfile: apps/api/Dockerfile.dev @@ -8,21 +33,29 @@ services: environment: - NODE_ENV=development ports: - - "3000:3000" + - "3001:3000" - "9229:9229" volumes: - - ./apps/api:/app/apps/api - - ./core:/app/core - - ./adapters:/app/adapters - - ./tsconfig.base.json:/app/tsconfig.base.json:ro + - ./:/app + - dev_node_modules:/app/node_modules + - dev_npm_cache:/root/.npm + command: ["sh", "-lc", "npm run start:dev --workspace=@gridpilot/api"] depends_on: + deps: + condition: service_completed_successfully db: condition: service_healthy networks: - gridpilot-network restart: unless-stopped + healthcheck: + test: ["CMD", "node", "-e", "fetch('http://localhost:3000/health').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))"] + interval: 5s + timeout: 5s + retries: 10 website: + image: gridpilot-website-dev build: context: . dockerfile: apps/website/Dockerfile.dev @@ -30,14 +63,20 @@ services: - .env.development environment: - NEXT_TELEMETRY_DISABLED=1 + - NODE_ENV=development + - API_BASE_URL=http://api:3000 ports: - - "3001:3000" + - "3000:3000" volumes: - - ./apps/website:/app/apps/website - - ./core:/app/core - - ./adapters:/app/adapters - - ./scripts:/app/scripts - - ./tsconfig.base.json:/app/tsconfig.base.json:ro + - ./:/app + - dev_node_modules:/app/node_modules + - dev_npm_cache:/root/.npm + command: ["sh", "-lc", "npm run dev --workspace=@gridpilot/website"] + depends_on: + deps: + condition: service_completed_successfully + api: + condition: service_healthy networks: - gridpilot-network restart: unless-stopped @@ -65,3 +104,5 @@ networks: volumes: dev_db_data: + dev_node_modules: + dev_npm_cache: diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml index 7e286db2a..bc6fa0a13 100644 --- a/docker-compose.prod.yml +++ b/docker-compose.prod.yml @@ -1,6 +1,7 @@ services: api: + image: gridpilot-api-prod build: context: . dockerfile: apps/api/Dockerfile.prod @@ -39,6 +40,7 @@ services: max-file: "3" website: + image: gridpilot-website-prod build: context: . dockerfile: apps/website/Dockerfile.prod diff --git a/package.json b/package.json index 558ee6c30..dffee34f4 100644 --- a/package.json +++ b/package.json @@ -77,18 +77,18 @@ "deploy:website:prod": "npx vercel deploy --prod", "dev": "echo 'Development server placeholder - to be configured'", "lint": "npx eslint apps/api/src --ext .ts,.tsx --max-warnings 0", - "docker:dev": "docker-compose -f docker-compose.dev.yml up", - "docker:dev:build": "docker-compose -f docker-compose.dev.yml up --build", - "docker:dev:clean": "docker-compose -f docker-compose.dev.yml down -v", - "docker:dev:down": "docker-compose -f docker-compose.dev.yml down", - "docker:dev:logs": "docker-compose -f docker-compose.dev.yml logs -f", + "docker:dev": "COMPOSE_PARALLEL_LIMIT=1 docker-compose -p gridpilot-dev -f docker-compose.dev.yml up", + "docker:dev:build": "COMPOSE_PARALLEL_LIMIT=1 docker-compose -p gridpilot-dev -f docker-compose.dev.yml up --build", + "docker:dev:clean": "docker-compose -p gridpilot-dev -f docker-compose.dev.yml down -v", + "docker:dev:down": "docker-compose -p gridpilot-dev -f docker-compose.dev.yml down", + "docker:dev:logs": "docker-compose -p gridpilot-dev -f docker-compose.dev.yml logs -f", "docker:e2e:down": "docker-compose -f docker/docker-compose.e2e.yml down", "docker:e2e:up": "docker-compose -f docker/docker-compose.e2e.yml up -d", - "docker:prod": "docker-compose -f docker-compose.prod.yml up -d", - "docker:prod:build": "docker-compose -f docker-compose.prod.yml up -d --build", - "docker:prod:clean": "docker-compose -f docker-compose.prod.yml down -v", - "docker:prod:down": "docker-compose -f docker-compose.prod.yml down", - "docker:prod:logs": "docker-compose -f docker-compose.prod.yml logs -f", + "docker:prod": "docker-compose -p gridpilot-prod -f docker-compose.prod.yml up -d", + "docker:prod:build": "docker-compose -p gridpilot-prod -f docker-compose.prod.yml up -d --build", + "docker:prod:clean": "docker-compose -p gridpilot-prod -f docker-compose.prod.yml down -v", + "docker:prod:down": "docker-compose -p gridpilot-prod -f docker-compose.prod.yml down", + "docker:prod:logs": "docker-compose -p gridpilot-prod -f docker-compose.prod.yml logs -f", "dom:process": "npx tsx scripts/dom-export/processWorkflows.ts", "env:website:merge": "node scripts/merge-website-env.js", "generate-templates": "npx tsx scripts/generate-templates/index.ts",