@abgov/nx-adsp 12.4.0 → 12.5.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.
Files changed (48) hide show
  1. package/generators.json +6 -0
  2. package/package.json +1 -1
  3. package/src/generators/angular-app/angular-app.js +22 -7
  4. package/src/generators/angular-app/angular-app.js.map +1 -1
  5. package/src/generators/angular-app/files/nginx.conf__tmpl__ +14 -7
  6. package/src/generators/angular-app/files/src/app/app.component.css__tmpl__ +10 -54
  7. package/src/generators/angular-app/files/src/app/app.component.html__tmpl__ +18 -49
  8. package/src/generators/angular-app/files/src/app/app.component.spec.ts__tmpl__ +22 -27
  9. package/src/generators/angular-app/files/src/app/app.component.ts__tmpl__ +60 -20
  10. package/src/generators/angular-app/files/src/app/app.config.ts__tmpl__ +27 -0
  11. package/src/generators/angular-app/files/src/app/app.routes.ts__tmpl__ +10 -31
  12. package/src/generators/angular-app/files/src/app/home/home.component.html__tmpl__ +1 -3
  13. package/src/generators/angular-app/files/src/app/home/home.component.ts__tmpl__ +9 -23
  14. package/src/generators/angular-app/files/src/app/protected/protected.component.html__tmpl__ +2 -2
  15. package/src/generators/angular-app/files/src/app/protected/protected.component.spec.ts__tmpl__ +27 -43
  16. package/src/generators/angular-app/files/src/app/protected/protected.component.ts__tmpl__ +15 -15
  17. package/src/generators/angular-app/files/src/app/services/auth-guard.service.ts__tmpl__ +12 -21
  18. package/src/generators/angular-app/files/src/environments/environment.ts__tmpl__ +2 -11
  19. package/src/generators/angular-app/files/src/index.html__tmpl__ +3 -9
  20. package/src/generators/angular-app/files/src/main.ts__tmpl__ +8 -12
  21. package/src/generators/angular-app/files/src/silent-check-sso.html__tmpl__ +5 -0
  22. package/src/generators/angular-app/files/src/styles.css__tmpl__ +2 -2
  23. package/src/generators/mean/mean.d.ts +3 -0
  24. package/src/generators/mean/mean.js +30 -0
  25. package/src/generators/mean/mean.js.map +1 -0
  26. package/src/generators/mean/mean.spec.ts +38 -0
  27. package/src/generators/mean/schema.d.ts +11 -0
  28. package/src/generators/mean/schema.json +26 -0
  29. package/src/generators/mern/mern.js +5 -21
  30. package/src/generators/mern/mern.js.map +1 -1
  31. package/src/generators/mern/schema.d.ts +0 -4
  32. package/src/generators/react-app/files/nginx.conf__tmpl__ +18 -7
  33. package/src/generators/react-app/react-app.js +6 -0
  34. package/src/generators/react-app/react-app.js.map +1 -1
  35. package/src/generators/angular-app/files/src/app/app.module.ts__tmpl__ +0 -47
  36. package/src/generators/angular-app/files/src/app/auth-callback/auth-callback.component.css__tmpl__ +0 -13
  37. package/src/generators/angular-app/files/src/app/auth-callback/auth-callback.component.html__tmpl__ +0 -12
  38. package/src/generators/angular-app/files/src/app/auth-callback/auth-callback.component.spec.ts__tmpl__ +0 -33
  39. package/src/generators/angular-app/files/src/app/auth-callback/auth-callback.component.ts__tmpl__ +0 -48
  40. package/src/generators/angular-app/files/src/app/auth.interceptor.ts__tmpl__ +0 -24
  41. package/src/generators/angular-app/files/src/app/logout/logout.component.html__tmpl__ +0 -1
  42. package/src/generators/angular-app/files/src/app/logout/logout.component.ts__tmpl__ +0 -9
  43. package/src/generators/angular-app/files/src/app/services/auth.service.ts__tmpl__ +0 -57
  44. package/src/generators/angular-app/files/src/app/tenant.service.ts__tmpl__ +0 -19
  45. package/src/generators/angular-app/files/src/environments/config.ts__tmpl__ +0 -21
  46. /package/src/generators/angular-app/files/{src → public}/assets/banner.jpg +0 -0
  47. /package/src/generators/angular-app/files/{src → public}/assets/github-1.svg +0 -0
  48. /package/src/generators/angular-app/files/{src → public}/favicon.ico +0 -0
package/generators.json CHANGED
@@ -43,6 +43,12 @@
43
43
  "factory": "./src/generators/angular-app/angular-app",
44
44
  "schema": "./src/generators/angular-app/schema.json",
45
45
  "description": "Generator that creates a Angular based frontend application."
46
+ },
47
+ "mean": {
48
+ "factory": "./src/generators/mean/mean",
49
+ "schema": "./src/generators/mean/schema.json",
50
+ "description": "Generator that creates a MEAN fullstack solution.",
51
+ "hidden": true
46
52
  }
47
53
  }
48
54
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abgov/nx-adsp",
3
- "version": "12.4.0",
3
+ "version": "12.5.0",
4
4
  "license": "Apache-2.0",
5
5
  "main": "src/index.js",
6
6
  "description": "Government of Alberta - Nx plugin for ADSP apps.",
@@ -56,6 +56,7 @@ function removeFiles(host, options) {
56
56
  }
57
57
  function default_1(host, options) {
58
58
  return tslib_1.__awaiter(this, void 0, void 0, function* () {
59
+ var _a, _b;
59
60
  const normalizedOptions = yield normalizeOptions(host, options);
60
61
  const { applicationGenerator: initAngular } = yield Promise.resolve().then(() => require('@nx/angular/generators'));
61
62
  yield initAngular(host, {
@@ -64,17 +65,31 @@ function default_1(host, options) {
64
65
  linter: 'none',
65
66
  directory: `apps/${options.name}`
66
67
  });
67
- (0, devkit_1.addDependenciesToPackageJson)(host, {}, {
68
- '@abgov/angular-components': '^3.0.0',
69
- '@abgov/web-components': '^1.19.0',
70
- 'oidc-client': '~1.11.5',
71
- });
68
+ (0, devkit_1.addDependenciesToPackageJson)(host, {
69
+ '@abgov/angular-components': '5.2.1',
70
+ '@abgov/design-tokens': '1.8.0',
71
+ '@abgov/ui-components-common': '^2.0.0',
72
+ '@abgov/web-components': '1.39.3',
73
+ 'keycloak-angular': '^19.0.2',
74
+ 'keycloak-js': '^23.0.7',
75
+ 'zone.js': '~0.15.0',
76
+ }, {});
72
77
  const addedProxy = addFiles(host, normalizedOptions);
73
- removeFiles(host, normalizedOptions);
78
+ // @nx/angular generates app.ts/html/css/spec.ts (new naming) and nx-welcome.ts;
79
+ // our templates use app.component.* and don't use nx-welcome.
80
+ for (const file of ['app.ts', 'app.html', 'app.css', 'app.spec.ts', 'nx-welcome.ts']) {
81
+ host.delete(`${normalizedOptions.projectRoot}/src/app/${file}`);
82
+ }
74
83
  const layout = (0, devkit_1.getWorkspaceLayout)(host);
75
84
  const config = (0, devkit_1.readProjectConfiguration)(host, options.name);
76
- config.targets.build.options = Object.assign(Object.assign({}, config.targets.build.options), { assets: [
85
+ // Remove the generated fileReplacements for production — single environment.ts
86
+ // is pre-populated from tenant config at generation time.
87
+ if ((_b = (_a = config.targets.build.configurations) === null || _a === void 0 ? void 0 : _a.production) === null || _b === void 0 ? void 0 : _b.fileReplacements) {
88
+ delete config.targets.build.configurations.production.fileReplacements;
89
+ }
90
+ config.targets.build.options = Object.assign(Object.assign({}, config.targets.build.options), { polyfills: ['zone.js'], assets: [
77
91
  ...config.targets.build.options.assets,
92
+ `${normalizedOptions.projectRoot}/src/silent-check-sso.html`,
78
93
  {
79
94
  glob: 'nginx.conf',
80
95
  input: `${layout.appsDir}/${options.name}`,
@@ -1 +1 @@
1
- {"version":3,"file":"angular-app.js","sourceRoot":"","sources":["../../../../../../packages/nx-adsp/src/generators/angular-app/angular-app.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"angular-app.js","sourceRoot":"","sources":["../../../../../../packages/nx-adsp/src/generators/angular-app/angular-app.ts"],"names":[],"mappings":"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"}
@@ -1,25 +1,32 @@
1
1
  events {
2
- worker_connections 1024;
2
+ worker_connections 1024;
3
3
  }
4
- http{
4
+
5
+ http {
5
6
  sendfile on;
6
7
  include mime.types;
7
8
  default_type application/octet-stream;
8
9
 
10
+ gzip on;
11
+ gzip_types text/plain text/css application/javascript application/json image/svg+xml font/woff2;
12
+ gzip_min_length 1000;
13
+
9
14
  server {
10
-
11
15
  listen 8080;
12
16
  root /opt/app-root/src;
13
17
  index index.html;
14
18
 
15
-
16
- location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {
19
+ add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
20
+ add_header X-Content-Type-Options "nosniff" always;
21
+ add_header X-Frame-Options "SAMEORIGIN" always;
22
+ add_header Referrer-Policy "strict-origin-when-cross-origin" always;
23
+
24
+ location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
17
25
  expires 30d;
18
26
  add_header Cache-Control "public, no-transform";
19
- }
27
+ }
20
28
 
21
29
  location / {
22
- gzip on;
23
30
  try_files $uri /index.html;
24
31
  }
25
32
  <% nginxProxies.forEach(function(nginxProxy){ %>
@@ -1,36 +1,16 @@
1
- .container {
2
- width: 100%;
3
- margin: 0 auto;
4
- padding: 0;
1
+ .app {
2
+ margin: 0;
5
3
  }
6
4
 
7
- @media (min-width: 640px) {
8
- .container {
9
- margin: 0 auto;
10
- padding: 3rem 1rem;
11
- width: 640px;
12
- }
5
+ main {
6
+ display: grid;
7
+ grid-template-columns: repeat(6, auto);
13
8
  }
14
- @media (min-width: 768px) {
15
- .container {
16
- margin: 0 auto;
17
- padding: 3rem 1rem;
18
- width: 768px;
19
- }
20
- }
21
- @media (min-width: 1024px) {
22
- .container {
23
- padding: 3rem 1rem;
24
- margin: 0 auto;
25
- width: 1024px;
26
- }
27
- }
28
- @media (min-width: 1280px) {
29
- .container {
30
- padding: 3rem 1rem;
31
- margin: 0 auto;
32
- width: 1280px;
33
- }
9
+
10
+ section {
11
+ grid-column: 2 / span 2;
12
+ margin-top: 40px;
13
+ margin-bottom: 40px;
34
14
  }
35
15
 
36
16
  .nextSteps {
@@ -42,27 +22,3 @@
42
22
  margin-bottom: 0;
43
23
  line-height: 50px;
44
24
  }
45
-
46
- .nextSteps li button {
47
- margin: 20px 0 0 10px;
48
- }
49
-
50
-
51
- .footer {
52
- background-color: #f1f1f1;
53
- padding-top: 56px;
54
- padding-bottom: 56px;
55
- padding-left: 150px;
56
- padding-right: 150px;
57
- display: flex;
58
- flex-direction: row;
59
- flex-wrap: wrap;
60
- border-bottom: 16px solid #0081a2;
61
- }
62
-
63
- @media (max-width: 767px) {
64
- /* On small screens, the nav menu spans the full width of the screen. Leave a space for it. */
65
- .body-content {
66
- padding-top: 50px;
67
- }
68
- }
@@ -1,58 +1,27 @@
1
1
  <div class="app">
2
- <goa-microsite-header type="alpha"></goa-microsite-header>
3
- <goa-app-header heading="Digital Service Example" url="/"></goa-app-header>
4
- <goa-hero-banner
5
- backgroundUrl="../assets/banner.jpg"
6
- heading="Quick start of a digital service"
7
- >
8
- </goa-hero-banner>
9
- <main class="container">
2
+ <goab-microsite-header type="alpha"></goab-microsite-header>
3
+ <goab-app-header url="/" heading="<%= projectName %>">
4
+ <goab-button-group alignment="end">
5
+ @if (userName) { <span>{{ userName }}</span> }
6
+ @if (!isLoggedIn) {
7
+ <goab-button type="tertiary" (onClick)="login()">Sign in</goab-button>
8
+ } @else {
9
+ <goab-button type="tertiary" (onClick)="logout()">Sign out</goab-button>
10
+ }
11
+ </goab-button-group>
12
+ </goab-app-header>
13
+ <goab-hero-banner #heroBanner heading="<%= projectName %>"></goab-hero-banner>
14
+ <main>
10
15
  <section>
11
16
  <h2>Welcome to {{ title }}!</h2>
12
- <p>
13
- Don't panic. Start editing the project to build your digital service.
14
- </p>
17
+ <p>Don't panic. Start editing the project to build your digital service.</p>
15
18
  <h3>A few things you might want to do next:</h3>
16
19
  <ul class="nextSteps">
17
- <li>Create the 'my-app' client in your realm to let users sign in</li>
18
- <li>
19
- Make requests to the backend API by either updating nginx.conf or
20
- enabling CORS on the API.
21
- </li>
22
- <li>Add requests to public API resources:</li>
23
- <li>Add requests to private API resources:</li>
20
+ <li>Register the '<%= projectName %>' client in your realm and set CLIENT_SECRET.</li>
21
+ <li>Add requests to public API resources: {{ publicResource }}</li>
22
+ <li>Add requests to private API resources: {{ privateResource }}</li>
24
23
  </ul>
25
24
  </section>
26
- <div class="container-fluid">
27
- <div class="row">
28
- <h3><a routerLink="/">Home</a> | <a routerLink="/protected">Admin Area</a></h3>
29
- <div *ngIf="isLoggedIn(); else elseBlock">
30
- <goa-button (click)="logout()">
31
- Sign Out
32
- </goa-button>
33
- </div>
34
- <ng-template #elseBlock>
35
- <goa-button (click)="login()">
36
- Sign In
37
- </goa-button>
38
- </ng-template>
39
- <div class="col-sm-12 body-content">
40
- <router-outlet></router-outlet>
41
- </div>
42
- </div>
43
- </div>
25
+ <router-outlet></router-outlet>
44
26
  </main>
45
- <footer class="footer">
46
- <div class="goa-socialconnect">
47
- <div class="goa-title">Connect with us on</div>
48
- <ul>
49
- <div>
50
- <img src="./assets/github-1.svg" height="15px" />
51
- <a href="https://github.com/abgov" rel="noreferrer" target="_blank">
52
- GitHub
53
- </a>
54
- </div>
55
- </ul>
56
- </div>
57
- </footer>
58
27
  </div>
@@ -1,44 +1,39 @@
1
- import { TestBed, getTestBed } from '@angular/core/testing';
1
+ import { ElementRef } from '@angular/core';
2
+ import { TestBed } from '@angular/core/testing';
3
+ import { provideRouter } from '@angular/router';
4
+ import { GoabAppHeader, GoabButton, GoabButtonGroup, GoabHeroBanner, GoabMicrositeHeader } from '@abgov/angular-components';
5
+ import Keycloak from 'keycloak-js';
2
6
  import { AppComponent } from './app.component';
3
- import { AngularComponentsModule } from '@abgov/angular-components';
4
- import { RouterTestingModule } from '@angular/router/testing';
5
- import {
6
- BrowserDynamicTestingModule,
7
- platformBrowserDynamicTesting
8
- } from "@angular/platform-browser-dynamic/testing";
9
-
10
7
 
11
8
  describe('AppComponent', () => {
12
- beforeAll( ()=> {
13
- TestBed.initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting());
14
- });
15
- beforeEach(async () => {
16
- let envData = {"production":false,"access":{"url":"https://testurl.com","realm":"123","client_id":"urn:ads:platform:tenant-admin-app"},"tenantApi":{"host":"http://localhost:3333","endpoints":{"tenantNameByRealm":"/api/tenant/v1/realm"}}}
9
+ const keycloakMock = {
10
+ authenticated: false,
11
+ tokenParsed: null,
12
+ login: jasmine.createSpy('login'),
13
+ logout: jasmine.createSpy('logout'),
14
+ };
17
15
 
18
- localStorage.setItem('envData', JSON.stringify(envData));
16
+ beforeEach(async () => {
19
17
  await TestBed.configureTestingModule({
20
- declarations: [AppComponent],
21
- imports: [AngularComponentsModule, RouterTestingModule],
18
+ imports: [AppComponent, GoabAppHeader, GoabButton, GoabButtonGroup, GoabHeroBanner, GoabMicrositeHeader],
19
+ providers: [
20
+ provideRouter([]),
21
+ { provide: Keycloak, useValue: keycloakMock },
22
+ { provide: ElementRef, useValue: { nativeElement: { querySelector: () => null } } },
23
+ ],
22
24
  }).compileComponents();
23
25
  });
24
26
 
25
27
  it('should create the app', () => {
26
28
  const fixture = TestBed.createComponent(AppComponent);
27
- const app = fixture.componentInstance;
28
- expect(app).toBeTruthy();
29
- });
30
-
31
- it(`should have as title '<%= projectName %>'`, () => {
32
- const fixture = TestBed.createComponent(AppComponent);
33
- const app = fixture.componentInstance;
34
- expect(app.title).toEqual('<%= projectName %>');
29
+ expect(fixture.componentInstance).toBeTruthy();
35
30
  });
36
31
 
37
- it('should render title', () => {
32
+ it('should have welcome heading', () => {
38
33
  const fixture = TestBed.createComponent(AppComponent);
39
34
  fixture.detectChanges();
40
- const compiled = fixture.nativeElement;
41
- expect(compiled.querySelector('h2').textContent).toContain(
35
+ const compiled = fixture.nativeElement as HTMLElement;
36
+ expect(compiled.querySelector('h2')?.textContent).toContain(
42
37
  'Welcome to <%= projectName %>!'
43
38
  );
44
39
  });
@@ -1,36 +1,76 @@
1
- import { Component, OnDestroy, OnInit } from '@angular/core';
2
- import { AuthService } from './services/auth.service';
3
- import { environment } from '../environments/environment'
4
-
1
+ import { AfterViewInit, Component, ElementRef, inject, OnDestroy, OnInit, ViewChild } from '@angular/core';
2
+ import { HttpClient } from '@angular/common/http';
3
+ import { RouterOutlet } from '@angular/router';
4
+ import {
5
+ GoabAppHeader,
6
+ GoabButton,
7
+ GoabButtonGroup,
8
+ GoabHeroBanner,
9
+ GoabMicrositeHeader,
10
+ } from '@abgov/angular-components';
11
+ import Keycloak from 'keycloak-js';
12
+ import { getAccessToken } from './user.slice';
5
13
 
6
14
  @Component({
7
- selector: '<%= projectName %>-app-root',
15
+ selector: '<%= projectName %>-root',
16
+ standalone: true,
17
+ imports: [RouterOutlet, GoabAppHeader, GoabButton, GoabButtonGroup, GoabHeroBanner, GoabMicrositeHeader],
8
18
  templateUrl: './app.component.html',
9
- styleUrls: ['./app.component.css'],
19
+ styleUrl: './app.component.css',
10
20
  })
21
+ export class AppComponent implements OnInit, AfterViewInit, OnDestroy {
22
+ title = '<%= projectName %>';
11
23
 
12
- export class AppComponent implements OnInit, OnDestroy {
13
- title = "<%= projectName %>";
24
+ @ViewChild('heroBanner', { read: ElementRef, static: false }) heroBannerRef!: ElementRef;
14
25
 
15
- constructor(private authService: AuthService) {}
26
+ private http = inject(HttpClient);
27
+ private keycloak = inject(Keycloak);
28
+ private heroObserver?: MutationObserver;
16
29
 
17
- isLoggedIn(): boolean {
18
- return this.authService.isLoggedIn()
19
- }
30
+ publicResource = 'Not retrieved';
31
+ privateResource = 'Not retrieved';
32
+
33
+ get isLoggedIn(): boolean { return this.keycloak.authenticated ?? false; }
34
+ get userName(): string { return (this.keycloak.tokenParsed?.['name'] as string) ?? ''; }
20
35
 
21
- logout() {
22
- if (this.authService.isLoggedIn()) {
23
- this.authService.logout();
36
+ ngOnInit() {
37
+ this.http.get<{ message: string }>('/api/v1/public').subscribe({
38
+ next: (data) => (this.publicResource = data.message),
39
+ error: () => (this.publicResource = 'Error loading data'),
40
+ });
41
+ if (this.isLoggedIn) {
42
+ getAccessToken().then((token) => {
43
+ this.http.get<{ message: string }>('/api/v1/private', {
44
+ headers: { Authorization: `Bearer ${token}` },
45
+ }).subscribe({
46
+ next: (data) => (this.privateResource = data.message),
47
+ error: () => (this.privateResource = 'Error loading data'),
48
+ });
49
+ });
24
50
  }
25
51
  }
26
52
 
27
- login() {
28
- if (!this.authService.isLoggedIn()) {
29
- this.authService.startAuthentication();
53
+ ngAfterViewInit() {
54
+ const host = this.heroBannerRef?.nativeElement;
55
+ if (!host) return;
56
+ const setBackground = (inner: Element) => {
57
+ (inner as any).backgroundurl = '/assets/banner.jpg';
58
+ this.heroObserver?.disconnect();
59
+ };
60
+ const existing = host.querySelector('goa-hero-banner');
61
+ if (existing) {
62
+ setBackground(existing);
63
+ } else {
64
+ this.heroObserver = new MutationObserver(() => {
65
+ const inner = host.querySelector('goa-hero-banner');
66
+ if (inner) setBackground(inner);
67
+ });
68
+ this.heroObserver.observe(host, { childList: true, subtree: true });
30
69
  }
31
70
  }
32
71
 
33
- ngOnInit() {}
72
+ ngOnDestroy() { this.heroObserver?.disconnect(); }
34
73
 
35
- ngOnDestroy(): void {}
74
+ login() { this.keycloak.login(); }
75
+ logout() { this.keycloak.logout({ redirectUri: window.location.origin }); }
36
76
  }
@@ -0,0 +1,27 @@
1
+ import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core';
2
+ import { provideRouter } from '@angular/router';
3
+ import { provideHttpClient, withInterceptors } from '@angular/common/http';
4
+ import { includeBearerTokenInterceptor, provideKeycloak } from 'keycloak-angular';
5
+
6
+ import { routes } from './app.routes';
7
+ import { environment } from '../environments/environment';
8
+
9
+ export const appConfig: ApplicationConfig = {
10
+ providers: [
11
+ provideZoneChangeDetection({ eventCoalescing: true }),
12
+ provideRouter(routes),
13
+ provideHttpClient(withInterceptors([includeBearerTokenInterceptor])),
14
+ provideKeycloak({
15
+ config: {
16
+ url: environment.access.url,
17
+ realm: environment.access.realm,
18
+ clientId: environment.access.client_id,
19
+ },
20
+ initOptions: {
21
+ onLoad: 'check-sso',
22
+ pkceMethod: 'S256',
23
+ silentCheckSsoRedirectUri: `${window.location.origin}/silent-check-sso.html`,
24
+ },
25
+ }),
26
+ ],
27
+ };
@@ -1,34 +1,13 @@
1
- import { LogoutComponent } from './logout/logout.component';
2
- import { NgModule } from '@angular/core';
3
- import { Routes, RouterModule } from '@angular/router';
4
- import { HomeComponent } from './home/home.component';
1
+ import { Routes } from '@angular/router';
2
+ import { createAuthGuard } from 'keycloak-angular';
5
3
  import { ProtectedComponent } from './protected/protected.component';
6
- import { AuthGuardService } from './services/auth-guard.service';
7
- import { AuthCallbackComponent } from './auth-callback/auth-callback.component';
8
4
 
9
- const routes: Routes = [
10
- {
11
- path: '',
12
- component: HomeComponent,
13
- children: [],
14
- },
15
- {
16
- path: 'protected',
17
- component: ProtectedComponent,
18
- canActivate: [AuthGuardService],
19
- },
20
- {
21
- path: 'auth-callback',
22
- component: AuthCallbackComponent,
23
- },
24
- {
25
- path: 'signout/callback',
26
- component: LogoutComponent,
27
- },
28
- ];
5
+ const authGuard = createAuthGuard(async (_route, _state, { authenticated, keycloak }) => {
6
+ if (authenticated) return true;
7
+ await keycloak.login({ redirectUri: window.location.href });
8
+ return false;
9
+ });
29
10
 
30
- @NgModule({
31
- imports: [RouterModule.forRoot(routes)],
32
- exports: [RouterModule],
33
- })
34
- export class AppRoutingModule {}
11
+ export const routes: Routes = [
12
+ { path: 'protected', component: ProtectedComponent, canActivate: [authGuard] },
13
+ ];
@@ -1,5 +1,3 @@
1
1
  <hr />
2
2
  <h1>Public Area</h1>
3
- <div>Making a Public API call to uptime endpoint</div>
4
- <div>Uptime of API in seconds: {{uptime}}</div>
5
-
3
+ <p>Public API response: {{ publicMessage() }}</p>
@@ -1,33 +1,19 @@
1
- import { Component, OnInit } from '@angular/core';
1
+ import { Component, inject, OnInit, signal } from '@angular/core';
2
2
  import { HttpClient } from '@angular/common/http';
3
3
 
4
4
  @Component({
5
- selector: '<%= projectName %>-app-logout',
5
+ selector: '<%= projectName %>-home',
6
+ standalone: true,
6
7
  templateUrl: 'home.component.html',
7
8
  })
8
9
  export class HomeComponent implements OnInit {
9
- constructor(private http: HttpClient) {}
10
- public uptime = 0;
11
-
12
- private getHealthUrl = `${this.configData().tenantApi.host}/health`;
13
-
14
- getHealth() {
15
- const uptimePromise = this.http.get(this.getHealthUrl);
16
-
17
- uptimePromise.subscribe(
18
- (data: any) => {
19
- this.uptime = data.uptime;
20
- },
21
- (err) => console.error(err),
22
- () => console.log('done loading uptime')
23
- );
24
- }
25
-
26
- configData () {
27
- return JSON.parse(localStorage.getItem('envData') || "\"\"");
28
- }
10
+ private http = inject(HttpClient);
11
+ publicMessage = signal('Not retrieved');
29
12
 
30
13
  ngOnInit() {
31
- this.getHealth();
14
+ this.http.get<{ message: string }>('/api/v1/public').subscribe({
15
+ next: (data) => this.publicMessage.set(data.message),
16
+ error: () => this.publicMessage.set('Error loading data'),
17
+ });
32
18
  }
33
19
  }
@@ -1,4 +1,4 @@
1
1
  <hr />
2
2
  <h1>Admin Area</h1>
3
- <div>Making a Protected API call to tenant endpoint using access token</div>
4
- <div>Tenant Name: {{tenant.name}}</div>
3
+ <p>Welcome, {{ userName }}.</p>
4
+ <p>Private API response: {{ privateMessage() }}</p>