Skip to main content

Client development

The web client (apps/client, package @eudiplo/client) is an Angular application with standalone components and Angular Material. It talks to the backend only through the generated @eudiplo/sdk-core client.

Commands​

Run from the repository root:

pnpm --filter @eudiplo/sdk-core build # once, and after regenerating the SDK
pnpm dev:client # ng serve on http://localhost:4200
pnpm --filter @eudiplo/client build
pnpm --filter @eudiplo/client test # unit tests (Vitest), watch mode
pnpm --filter @eudiplo/client lint # ESLint (ng lint)
pnpm --filter @eudiplo/client format # Prettier; format:check only checks

dev, build, watch and test first run pnpm gen:api, which regenerates src/app/utils/schemas.json (git-ignored). The JSON editors validate configuration against these schemas.

Sign in at http://localhost:4200 with the backend URL and a client id and secret, for example AUTH_CLIENT_ID / AUTH_CLIENT_SECRET from apps/backend/.env.

Calling the backend​

Use the generated functions of @eudiplo/sdk-core (for example tenantControllerGetTenant); do not call HttpClient with hand-written URLs. core/api.service.ts configures the SDK client with the instance URL and the access token.

When you add or change a backend endpoint, regenerate the SDK with the backend running and rebuild it:

pnpm gen:sdk # reads http://localhost:3000/api/docs-json and builds the SDK

Commit the regenerated packages/eudiplo-sdk-core/src/api together with the backend change.

Folder map​

apps/client/src/
├── app/
│ ├── app.config.ts, app.routes.ts # providers and top-level routes
│ ├── core/ # API service (SDK setup), OIDC service, auth interceptor
│ ├── services/ # environment, theme, version check, Grafana links, JWT helpers
│ ├── guards/ # auth.guard.ts, roles.guard.ts
│ ├── common/ # shared base list component and small utilities
│ ├── utils/ # reusable UI: editor, image field, webhook config, schema validation
│ ├── login/, dashboard/, settings/
│ ├── issuance/ # credential configs, issuance config, offers, attribute providers
│ ├── presentation/ # presentation configs and requests
│ ├── session-management/, session-config/
│ ├── key-management/, trust-list/, status-list-config/, status-list-management/
│ ├── registrar/, schema/, webhook-endpoint/, config-portability/
│ ├── tenants/, users/, admin/ # tenants and clients, users, activity log
│ └── types/
├── environments/
└── test-setup.ts # shared unit-test setup

Features follow a list / show / create pattern (*-list/, *-show/, *-create/) with routes in a *.routes.ts file and a feature service that wraps the SDK calls. Forms use Reactive Forms.

Tests​

Unit tests use Vitest through the @angular/build:unit-test builder (angular.json: runner vitest, isolate: true, setup file src/test-setup.ts). Spec files sit next to the component as *.spec.ts. CI runs them in the Build Client job:

pnpm --filter @eudiplo/client test --watch=false

src/test-setup.ts provides in-memory localStorage/sessionStorage, a matchMedia stub and a never-settling fetch for the SDK client. To assert API calls, stub fetch and inspect the requests; the Angular builder cannot intercept vi.mock('@eudiplo/sdk-core').

Browser tests use Playwright and live in apps/client/e2e/. They are not run in CI. pnpm --filter @eudiplo/client e2e starts the backend (pnpm run dev in apps/backend) and ng serve, or reuses running servers. Sign-in uses a tenant client from E2E_TENANT_CLIENT_ID / E2E_TENANT_CLIENT_SECRET, read from the environment or apps/backend/.env; E2E_ALLOW_ROOT_FALLBACK=true falls back to AUTH_CLIENT_ID / AUTH_CLIENT_SECRET.

Version check​

After sign-in the client compares its build (env.js) with the backend's GET /api/version. Different revisions, or releases that differ in more than the patch version, show a warning banner. Local builds without version information are not checked.