From baea9f2b577c208bd42680027748637f9f00ba09 Mon Sep 17 00:00:00 2001 From: mihretue Date: Tue, 25 Aug 2026 19:04:27 +0000 Subject: [PATCH] chore(dev): serve the portal on 3000 for the Fayda redirect MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Fayda redirect URI registered for local testing is http://localhost:3000/callback, matched exactly by the provider, so the portal has to be the thing listening there. Its dev and preview servers move from 4200 to 3000 and the API moves to 3001. Every hardcoded fallback to http://localhost:3000/api follows — six copies of the same default across libs/api, libs/auth, the portal and the backoffice — otherwise a developer without a .env would have had the app calling itself. e2e is unaffected: it binds its own ports (3011/4302/4303) explicitly. --- .env.example | 15 ++++++++------- .../certificate-designer/config/designer.ts | 2 +- apps/backoffice/vite.config.mts | 2 +- apps/e2e/README.md | 2 +- .../certificates/pages/CertificatesPage.tsx | 2 +- apps/portal/vite.config.mts | 9 ++++++--- .../src/lib/base-api/base-query-with-reauth.ts | 2 +- .../lib/features/licensing/licensing.helpers.ts | 2 +- libs/api/src/lib/session/index.ts | 2 +- libs/auth/src/lib/components/AuthBootstrap.tsx | 2 +- libs/auth/src/lib/utils/refresh-token.ts | 2 +- 11 files changed, 23 insertions(+), 19 deletions(-) diff --git a/.env.example b/.env.example index abf8c4034..05b61e286 100644 --- a/.env.example +++ b/.env.example @@ -12,8 +12,10 @@ # frontend never speaks to Fayda directly. # Base URL of the emaapi backend, including the /api prefix. -# Defaults to http://localhost:3000/api when unset. -VITE_BASE_API_URL=http://localhost:3000/api +# 3001, not 3000: the portal itself takes 3000 in development, because that is +# the port in the Fayda redirect URI registered for local testing. Set PORT=3001 +# in emaapi's .env to match. +VITE_BASE_API_URL=http://localhost:3001/api # Serve fixture data instead of calling the API. Any value other than "true" # uses the real backend. @@ -23,7 +25,7 @@ VITE_USE_MOCKS=false # Host ports published by docker-compose.yml. It also expects per-app env files # at apps/portal/.env and apps/backoffice/.env, which can each be a copy of this # file. Ignored when running the Vite dev servers, which serve the portal on -# 4200 and the backoffice on 4201. +# 3000 and the backoffice on 4201. # EMA_PORTAL_PORT=8021 # EMA_BACKOFFICE_PORT=8022 @@ -32,7 +34,6 @@ VITE_USE_MOCKS=false # page at /callback and /signup/fayda/callback, and whichever path is registered # with Fayda must match the API's FAYDA_REDIRECT_URI exactly. # -# The value being registered first is http://localhost:3000/callback, which is -# also emaapi's default port — so when testing that redirect, serve the portal -# on 3000 (`npx nx serve portal --port 3000`) and move the API elsewhere, or -# register a URI that points at the port the portal actually runs on. +# The value being registered first is http://localhost:3000/callback, so the +# portal's dev server now listens on 3000 and emaapi moves to 3001. Nothing +# extra to run — `nx serve portal` already binds the right port. diff --git a/apps/backoffice/src/app/features/certificate-designer/config/designer.ts b/apps/backoffice/src/app/features/certificate-designer/config/designer.ts index f6fd5abae..07d22cd74 100644 --- a/apps/backoffice/src/app/features/certificate-designer/config/designer.ts +++ b/apps/backoffice/src/app/features/certificate-designer/config/designer.ts @@ -3,7 +3,7 @@ import type { Bilingual, LicenseCategory, LicenseTemplate, LicenseType } from '@ /** Same resolution — and same fallback — the shared RTK Query baseQuery uses. */ export const API_BASE_URL = (import.meta as { env?: Record }).env?.['VITE_BASE_API_URL'] ?? - 'http://localhost:3000/api'; + 'http://localhost:3001/api'; export const STATUS_COLOR: Record = { DRAFT: 'gray', diff --git a/apps/backoffice/vite.config.mts b/apps/backoffice/vite.config.mts index 97ed5cae3..be6f4eef9 100644 --- a/apps/backoffice/vite.config.mts +++ b/apps/backoffice/vite.config.mts @@ -17,7 +17,7 @@ export default defineConfig({ // port: 4201, // proxy: { // '/api': { -// target: 'http://localhost:3000', // change from 'https://ema-api-dev.triaplc.com' +// target: 'http://localhost:3001', // change from 'https://ema-api-dev.triaplc.com' // changeOrigin: true, // }, // }, diff --git a/apps/e2e/README.md b/apps/e2e/README.md index cfec73a58..86c75a6da 100644 --- a/apps/e2e/README.md +++ b/apps/e2e/README.md @@ -22,7 +22,7 @@ own ports, against its own database: | Backoffice | 4303 | same | | Database | — | `ema_e2e` | -This is deliberate. A developer's stack is usually already up on 3000/4200/4201, +This is deliberate. A developer's stack is usually already up on 3000/3001/4201, and `dev/start.sh` **rewrites** `emaapi/apps/server/emaapi/.env` and the apps' `.env.local` on every run — a suite that read those files would point at whichever stack was started last. The API is launched with `DATABASE_NAME`, diff --git a/apps/portal/src/app/features/certificates/pages/CertificatesPage.tsx b/apps/portal/src/app/features/certificates/pages/CertificatesPage.tsx index c15fa983b..edbe6f516 100644 --- a/apps/portal/src/app/features/certificates/pages/CertificatesPage.tsx +++ b/apps/portal/src/app/features/certificates/pages/CertificatesPage.tsx @@ -122,7 +122,7 @@ function formatDate(value: string | null | undefined): string { const API_BASE = (import.meta as { env?: Record }).env?.['VITE_BASE_API_URL'] ?? - 'http://localhost:3000/api'; + 'http://localhost:3001/api'; async function generateCertificate(profileId: string): Promise { const token = authStorage.getToken(); diff --git a/apps/portal/vite.config.mts b/apps/portal/vite.config.mts index 4e08b10fe..6487e7752 100644 --- a/apps/portal/vite.config.mts +++ b/apps/portal/vite.config.mts @@ -9,17 +9,20 @@ export default defineConfig({ // built-in default. envDir: '../../', cacheDir: '../../node_modules/.vite/apps/portal', - server: { port: 4200, host: 'localhost' }, + // 3000, not the usual 4200: the Fayda redirect URI registered for local + // testing is http://localhost:3000/callback, and the provider matches it + // exactly. The API moves to 3001 to make room. + server: { port: 3000, host: 'localhost' }, // server: { // port: 4200, // proxy: { // '/api': { -// target: 'http://localhost:3000', // change from 'https://ema-api-dev.triaplc.com' +// target: 'http://localhost:3001', // change from 'https://ema-api-dev.triaplc.com' // changeOrigin: true, // }, // }, // }, - preview: { port: 4200, host: 'localhost' }, + preview: { port: 3000, host: 'localhost' }, plugins: [react(), nxViteTsPaths()], resolve: { dedupe: ['react', 'react-dom', 'react-router-dom', '@tanstack/react-query'], diff --git a/libs/api/src/lib/base-api/base-query-with-reauth.ts b/libs/api/src/lib/base-api/base-query-with-reauth.ts index c47336cd8..6f27c1b4f 100644 --- a/libs/api/src/lib/base-api/base-query-with-reauth.ts +++ b/libs/api/src/lib/base-api/base-query-with-reauth.ts @@ -5,7 +5,7 @@ import { resolveSessionContext } from "../session"; export const BASE_API_URL = (import.meta as { env?: Record }).env?.[ "VITE_BASE_API_URL" - ] ?? "http://localhost:3000/api"; + ] ?? "http://localhost:3001/api"; let _onTokenExpired: (() => Promise) | null = null; let _onAuthFailure: (() => void) | null = null; diff --git a/libs/api/src/lib/features/licensing/licensing.helpers.ts b/libs/api/src/lib/features/licensing/licensing.helpers.ts index ecb0218d4..c74eabbc6 100644 --- a/libs/api/src/lib/features/licensing/licensing.helpers.ts +++ b/libs/api/src/lib/features/licensing/licensing.helpers.ts @@ -12,7 +12,7 @@ import type { const BASE_API_URL = (import.meta as { env?: Record }).env?.['VITE_BASE_API_URL'] ?? - 'http://localhost:3000/api'; + 'http://localhost:3001/api'; /** * Uploads a document straight to the API. diff --git a/libs/api/src/lib/session/index.ts b/libs/api/src/lib/session/index.ts index 69277fd91..f907697ab 100644 --- a/libs/api/src/lib/session/index.ts +++ b/libs/api/src/lib/session/index.ts @@ -11,7 +11,7 @@ export const SESSION_HEADER_KEYS = { * Which app this bundle is, so it reads its own session and no one else's. * * Set by each app's store via `configureSessionScope`. Cookies ignore the - * port, so `localhost:4200` and `localhost:4201` share one jar: without a + * port, so `localhost:3000` and `localhost:4201` share one jar: without a * scope the backoffice would happily authenticate as whoever last signed into * the portal, and render a staff console with an applicant's permissions. */ diff --git a/libs/auth/src/lib/components/AuthBootstrap.tsx b/libs/auth/src/lib/components/AuthBootstrap.tsx index 251db18c0..afabc2988 100644 --- a/libs/auth/src/lib/components/AuthBootstrap.tsx +++ b/libs/auth/src/lib/components/AuthBootstrap.tsx @@ -8,7 +8,7 @@ import type { AuthUser } from '../types/auth.types'; const BASE_API_URL = (import.meta as { env?: Record }).env?.['VITE_BASE_API_URL'] ?? - 'http://localhost:3000/api'; + 'http://localhost:3001/api'; /** * Restores the signed-in session before the router renders. diff --git a/libs/auth/src/lib/utils/refresh-token.ts b/libs/auth/src/lib/utils/refresh-token.ts index 4b6997f8a..1d5312593 100644 --- a/libs/auth/src/lib/utils/refresh-token.ts +++ b/libs/auth/src/lib/utils/refresh-token.ts @@ -3,7 +3,7 @@ import { authStorage } from "./auth-storage"; const BASE_API_URL = (import.meta as { env?: Record }).env?.[ "VITE_BASE_API_URL" - ] ?? "http://localhost:3000/api"; + ] ?? "http://localhost:3001/api"; interface RefreshResponse { token: string;