@abgov/nx-adsp 12.5.0 → 12.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abgov/nx-adsp",
3
- "version": "12.5.0",
3
+ "version": "12.6.0",
4
4
  "license": "Apache-2.0",
5
5
  "main": "src/index.js",
6
6
  "description": "Government of Alberta - Nx plugin for ADSP apps.",
@@ -0,0 +1,96 @@
1
+ # AGENTS.md — <%= projectName %>
2
+
3
+ Angular 19 frontend for the Alberta Digital Service Platform (ADSP).
4
+ Generated by `nx g @abgov/nx-adsp:angular-app`.
5
+
6
+ ## Stack
7
+
8
+ - **UI**: Angular 19 standalone + GoA design system (`@abgov/angular-components` — `Goab*` components)
9
+ - **Auth**: `keycloak-angular` with `keycloak-js`
10
+ - **Router**: Angular Router with `createAuthGuard` from `keycloak-angular`
11
+
12
+ ## Key files
13
+
14
+ | File | Purpose |
15
+ |------|---------|
16
+ | `src/main.ts` | Entry — bootstraps `AppComponent` with `appConfig`, imports `zone.js` |
17
+ | `src/app/app.config.ts` | `provideKeycloak` (PKCE, silent SSO), `provideRouter`, `provideHttpClient` |
18
+ | `src/app/app.component.ts` | Shell — auth state, hero banner background workaround, public API call |
19
+ | `src/app/app.routes.ts` | Routes — `/protected` with `createAuthGuard` |
20
+ | `src/app/protected/protected.component.ts` | Protected route — shows authenticated user info |
21
+ | `src/environments/environment.ts` | Access URL, realm, client ID — pre-set from ADSP tenant |
22
+
23
+ ## Auth pattern
24
+
25
+ ```typescript
26
+ import Keycloak from 'keycloak-js';
27
+ import { inject } from '@angular/core';
28
+
29
+ private keycloak = inject(Keycloak); // provided by provideKeycloak in app.config.ts
30
+
31
+ this.keycloak.authenticated // boolean
32
+ this.keycloak.tokenParsed?.['name'] // user display name
33
+ this.keycloak.login()
34
+ this.keycloak.logout({ redirectUri: window.location.origin })
35
+ ```
36
+
37
+ Route guard using `createAuthGuard` from `keycloak-angular`:
38
+
39
+ ```typescript
40
+ const authGuard = createAuthGuard(async (_route, _state, { authenticated, keycloak }) => {
41
+ if (authenticated) return true;
42
+ await keycloak.login({ redirectUri: window.location.href });
43
+ return false;
44
+ });
45
+ ```
46
+
47
+ ## GoA design system
48
+
49
+ Components are imported from `@abgov/angular-components` with the `Goab` prefix
50
+ and added to each standalone component's `imports` array:
51
+
52
+ ```typescript
53
+ import { GoabButton, GoabAppHeader } from '@abgov/angular-components';
54
+
55
+ @Component({ imports: [GoabButton, GoabAppHeader], ... })
56
+ ```
57
+
58
+ **Known limitation:** `GoabHeroBanner.backgroundUrl` does not bind reliably via
59
+ Angular's template binding due to an `@if(isReady)` timing issue inside the
60
+ component wrapper. Use `MutationObserver` to set the property directly after
61
+ the inner `<goa-hero-banner>` element appears — see `app.component.ts` for the
62
+ established pattern.
63
+
64
+ ## Backend API calls (mean / proxy setup)
65
+
66
+ If `proxy.conf.json` exists at the project root, API calls are proxied to the
67
+ backend service in development. Use relative `/api/` paths — do not hardcode
68
+ the service URL:
69
+
70
+ ```typescript
71
+ // ✓ correct — works through proxy in dev, nginx in production
72
+ this.http.get('/api/v1/my-resource')
73
+
74
+ // ✗ wrong — bypasses proxy, won't work in production
75
+ this.http.get('http://localhost:3333/my-service/v1/my-resource')
76
+ ```
77
+
78
+ `includeBearerTokenInterceptor` (configured in `app.config.ts`) automatically
79
+ attaches the Keycloak access token to all outgoing HTTP requests.
80
+ In production, `nginx.conf` contains the same proxy rule routing `/api/` to
81
+ the backend service hostname.
82
+
83
+ ## Adding a new route
84
+
85
+ 1. Create `src/app/my-feature/my-feature.component.ts` as a standalone component
86
+ 2. Add the route to `src/app/app.routes.ts`
87
+ 3. Add required `Goab*` components to the new component's `imports` array
88
+
89
+ ## What NOT to change
90
+
91
+ - `app.config.ts` — `provideKeycloak` initialises keycloak-js once; do not
92
+ create a second Keycloak instance elsewhere
93
+ - `silent-check-sso.html` — served from `public/`; required for keycloak-js
94
+ silent SSO check on page load
95
+ - `environments/environment.ts` — access URL and realm are pre-configured for
96
+ the ADSP tenant; override at runtime via environment variables
@@ -0,0 +1,76 @@
1
+ # AGENTS.md — <%= projectName %>
2
+
3
+ Node/Express backend service for the Alberta Digital Service Platform (ADSP).
4
+ Generated by `nx g @abgov/nx-adsp:express-service`.
5
+
6
+ ## Stack
7
+
8
+ - **Runtime**: Node.js + Express
9
+ - **Auth**: passport.js with tenant strategy from `@abgov/adsp-service-sdk`
10
+ - **Config**: `envalid` with `.env` file (see `src/environment.ts`)
11
+ - **SDK**: `@abgov/adsp-service-sdk` — provides service registration, auth,
12
+ event publishing, configuration management, and service discovery
13
+
14
+ ## Key files
15
+
16
+ | File | Purpose |
17
+ |------|---------|
18
+ | `src/main.ts` | App entry — SDK init, middleware, routes, server start |
19
+ | `src/environment.ts` | Validated env config with defaults pre-set from ADSP tenant |
20
+
21
+ ## SDK capabilities
22
+
23
+ `initializeService()` returns `capabilities`:
24
+
25
+ ```typescript
26
+ const { logger, tenantStrategy, traceHandler, configurationHandler,
27
+ healthCheck, directory, tokenProvider, eventService } = capabilities;
28
+ ```
29
+
30
+ To resolve another ADSP service URL:
31
+
32
+ ```typescript
33
+ const url = await directory.getServiceUrl(AdspId.parse('urn:ads:platform:file-service'));
34
+ ```
35
+
36
+ To call another service with an access token:
37
+
38
+ ```typescript
39
+ const token = await tokenProvider.getAccessToken();
40
+ ```
41
+
42
+ ## Adding routes
43
+
44
+ Add route handlers in `main.ts` under the `/<%= projectName %>/v1` path prefix:
45
+
46
+ ```typescript
47
+ app.get('/<%= projectName %>/v1/my-resource', (req, res) => {
48
+ const user = req.user; // null for anonymous, populated for authenticated
49
+ res.json({ ... });
50
+ });
51
+ ```
52
+
53
+ `passport.authenticate(['tenant', 'anonymous'])` is applied to the entire
54
+ `/<%= projectName %>/v1` prefix — check `req.user` inside handlers to
55
+ distinguish authenticated from anonymous access.
56
+
57
+ ## Frontend proxy integration (mern / mean stacks)
58
+
59
+ When this service is paired with a React or Angular frontend via the `mern` or
60
+ `mean` generators, the frontend proxies `/api/` to this service:
61
+
62
+ - **Dev** (webpack / Vite): `/api/v1/my-resource` → `/<%= projectName %>/v1/my-resource` on `localhost:3333`
63
+ - **Production** (nginx): same rewrite via the nginx proxy block in the frontend app
64
+
65
+ All API routes in this service live under `/<%= projectName %>/v1/`. The proxy
66
+ rewrites the frontend's `/api/` prefix to `/<%= projectName %>/` before the
67
+ request reaches Express, so `/<%= projectName %>/v1/public` maps to the
68
+ frontend's `/api/v1/public`.
69
+
70
+ ## What NOT to change
71
+
72
+ - `initializeService(...)` config — `CLIENT_ID` and `CLIENT_SECRET` are read
73
+ from environment; do not hardcode credentials
74
+ - The passport strategy setup — the tenant strategy handles JWT validation
75
+ - `configurationHandler` on the API path — provides configuration service
76
+ integration; keep it applied before route handlers
@@ -0,0 +1,76 @@
1
+ # AGENTS.md — <%= projectName %>
2
+
3
+ React frontend for the Alberta Digital Service Platform (ADSP).
4
+ Generated by `nx g @abgov/nx-adsp:react-app`.
5
+
6
+ ## Stack
7
+
8
+ - **UI**: React 18 + GoA design system (`@abgov/react-components` — `Goab*` components)
9
+ - **Auth**: `keycloak-js` via Redux Toolkit slice (`src/app/user.slice.ts`)
10
+ - **State**: Redux Toolkit — store in `src/store.ts`
11
+ - **Router**: React Router v6
12
+
13
+ ## Key files
14
+
15
+ | File | Purpose |
16
+ |------|---------|
17
+ | `src/main.tsx` | Entry — Redux Provider, BrowserRouter, dispatches `initializeUser()` after render |
18
+ | `src/app/user.slice.ts` | Keycloak auth — login, logout, token refresh, `getAccessToken()` |
19
+ | `src/app/start.slice.ts` | Example public/private API calls |
20
+ | `src/app/config.slice.ts` | Loads ADSP directory service endpoints on startup |
21
+ | `src/app/intake.slice.ts` | Application domain state — extend this for your feature |
22
+ | `src/store.ts` | Redux store — add new slices here |
23
+ | `src/environments/environment.ts` | Access URL, realm, client ID — pre-set from ADSP tenant |
24
+
25
+ ## Auth pattern
26
+
27
+ ```typescript
28
+ import { getAccessToken, loginUser, logoutUser, userSelector } from './user.slice';
29
+
30
+ // In a component:
31
+ const { authenticated, name } = useSelector(userSelector);
32
+ dispatch(loginUser()); // redirects to Keycloak
33
+ dispatch(logoutUser()); // redirects to Keycloak logout
34
+
35
+ // In a thunk (for authenticated API calls):
36
+ const token = await getAccessToken(); // refreshes token if needed
37
+ ```
38
+
39
+ ## GoA design system
40
+
41
+ Components are imported from `@abgov/react-components` with the `Goab` prefix:
42
+
43
+ ```typescript
44
+ import { GoabButton, GoabAppHeader, GoabButtonGroup } from '@abgov/react-components';
45
+ ```
46
+
47
+ ## Adding a new Redux slice
48
+
49
+ 1. Create `src/app/my-feature.slice.ts` using `createSlice` / `createAsyncThunk`
50
+ 2. Export the reducer and add it to `src/store.ts`
51
+
52
+ ## Backend API calls (mern / proxy setup)
53
+
54
+ If `proxy.conf.json` exists at the project root, API calls are proxied to the
55
+ backend service in development. Use relative `/api/` paths — do not hardcode
56
+ the service URL:
57
+
58
+ ```typescript
59
+ // ✓ correct — works through proxy in dev, nginx in production
60
+ const response = await fetch('/api/v1/my-resource');
61
+
62
+ // ✗ wrong — bypasses proxy, won't work in production
63
+ const response = await fetch('http://localhost:3333/my-service/v1/my-resource');
64
+ ```
65
+
66
+ In production, `nginx.conf` contains the same proxy rule routing `/api/` to
67
+ the backend service hostname.
68
+
69
+ ## What NOT to change
70
+
71
+ - `user.slice.ts` — keycloak-js is initialised once per app lifecycle; do not
72
+ create a second Keycloak instance
73
+ - `environments/environment.ts` — access URL and realm are pre-configured for
74
+ the ADSP tenant; override at runtime via deployment config
75
+ - `silent-check-sso.html` — required for keycloak-js silent SSO; must be served
76
+ from the app root