@descope/angular-sdk 0.0.0-next-a6b67f6a-20231228 → 0.0.0-next-cc7eda17-20231228

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 (110) hide show
  1. package/.editorconfig +16 -0
  2. package/.eslintrc.json +40 -0
  3. package/.github/workflows/ci.yml +98 -0
  4. package/.github/workflows/publish-next.yml +43 -0
  5. package/.github/workflows/publish.yml +31 -0
  6. package/.github/workflows/release.yml +41 -0
  7. package/.husky/pre-commit +4 -0
  8. package/.prettierrc +8 -0
  9. package/.vscode/extensions.json +4 -0
  10. package/.vscode/launch.json +20 -0
  11. package/.vscode/settings.json +3 -0
  12. package/.vscode/tasks.json +42 -0
  13. package/angular.json +154 -0
  14. package/jest.config.js +17 -0
  15. package/package.json +1 -4
  16. package/projects/angular-sdk/.eslintrc.json +32 -0
  17. package/projects/angular-sdk/ng-package.json +8 -0
  18. package/projects/angular-sdk/src/environment.ts +3 -0
  19. package/projects/angular-sdk/src/lib/components/descope/descope.component.spec.ts +104 -0
  20. package/projects/angular-sdk/src/lib/components/descope/descope.component.ts +114 -0
  21. package/projects/angular-sdk/src/lib/components/sign-in-flow/sign-in-flow.component.html +15 -0
  22. package/projects/angular-sdk/src/lib/components/sign-in-flow/sign-in-flow.component.spec.ts +53 -0
  23. package/projects/angular-sdk/src/lib/components/sign-in-flow/sign-in-flow.component.ts +32 -0
  24. package/projects/angular-sdk/src/lib/components/sign-up-flow/sign-up-flow.component.html +15 -0
  25. package/projects/angular-sdk/src/lib/components/sign-up-flow/sign-up-flow.component.spec.ts +51 -0
  26. package/projects/angular-sdk/src/lib/components/sign-up-flow/sign-up-flow.component.ts +32 -0
  27. package/projects/angular-sdk/src/lib/components/sign-up-or-in-flow/sign-up-or-in-flow.component.html +15 -0
  28. package/projects/angular-sdk/src/lib/components/sign-up-or-in-flow/sign-up-or-in-flow.component.spec.ts +53 -0
  29. package/projects/angular-sdk/src/lib/components/sign-up-or-in-flow/sign-up-or-in-flow.component.ts +32 -0
  30. package/projects/angular-sdk/src/lib/descope-auth.module.ts +46 -0
  31. package/projects/angular-sdk/src/lib/services/descope-auth.guard.spec.ts +76 -0
  32. package/projects/angular-sdk/src/lib/services/descope-auth.guard.ts +16 -0
  33. package/projects/angular-sdk/src/lib/services/descope-auth.service.spec.ts +264 -0
  34. package/projects/angular-sdk/src/lib/services/descope-auth.service.ts +176 -0
  35. package/projects/angular-sdk/src/lib/services/descope.interceptor.spec.ts +102 -0
  36. package/projects/angular-sdk/src/lib/services/descope.interceptor.ts +76 -0
  37. package/projects/angular-sdk/src/lib/types/types.ts +10 -0
  38. package/projects/angular-sdk/src/lib/utils/constants.ts +8 -0
  39. package/projects/angular-sdk/src/lib/utils/helpers.spec.ts +103 -0
  40. package/projects/angular-sdk/src/lib/utils/helpers.ts +36 -0
  41. package/{dist/public-api.d.ts → projects/angular-sdk/src/public-api.ts} +4 -0
  42. package/projects/angular-sdk/tsconfig.lib.json +12 -0
  43. package/projects/angular-sdk/tsconfig.lib.prod.json +10 -0
  44. package/projects/angular-sdk/tsconfig.spec.json +11 -0
  45. package/projects/demo-app/.eslintrc.json +31 -0
  46. package/projects/demo-app/src/app/app-routing.module.ts +23 -0
  47. package/projects/demo-app/src/app/app.component.html +3 -0
  48. package/projects/demo-app/src/app/app.component.scss +16 -0
  49. package/projects/demo-app/src/app/app.component.spec.ts +37 -0
  50. package/projects/demo-app/src/app/app.component.ts +8 -0
  51. package/projects/demo-app/src/app/app.module.ts +52 -0
  52. package/projects/demo-app/src/app/home/home.component.html +23 -0
  53. package/projects/demo-app/src/app/home/home.component.scss +15 -0
  54. package/projects/demo-app/src/app/home/home.component.spec.ts +44 -0
  55. package/projects/demo-app/src/app/home/home.component.ts +61 -0
  56. package/projects/demo-app/src/app/interceptor/auth.interceptor.ts +20 -0
  57. package/projects/demo-app/src/app/login/login.component.html +12 -0
  58. package/projects/demo-app/src/app/login/login.component.spec.ts +42 -0
  59. package/projects/demo-app/src/app/login/login.component.ts +35 -0
  60. package/projects/demo-app/src/app/protected/protected.component.html +18 -0
  61. package/projects/demo-app/src/app/protected/protected.component.scss +8 -0
  62. package/projects/demo-app/src/app/protected/protected.component.spec.ts +42 -0
  63. package/projects/demo-app/src/app/protected/protected.component.ts +40 -0
  64. package/projects/demo-app/src/assets/.gitkeep +0 -0
  65. package/projects/demo-app/src/environments/conifg.ts +13 -0
  66. package/projects/demo-app/src/environments/environment.ts +19 -0
  67. package/projects/demo-app/src/favicon.ico +0 -0
  68. package/projects/demo-app/src/index.html +17 -0
  69. package/projects/demo-app/src/main.ts +7 -0
  70. package/projects/demo-app/src/styles.scss +21 -0
  71. package/projects/demo-app/tsconfig.app.json +10 -0
  72. package/projects/demo-app/tsconfig.spec.json +10 -0
  73. package/renovate.json +4 -0
  74. package/scripts/gitleaks/.gitleaks.toml +653 -0
  75. package/scripts/gitleaks/gitleaks.sh +34 -0
  76. package/scripts/setversion/setversion.js +20 -0
  77. package/setup-jest.ts +1 -0
  78. package/thirdPartyLicenseCollector_linux_amd64 +0 -0
  79. package/tsconfig.json +35 -0
  80. package/dist/environment.d.ts +0 -3
  81. package/dist/esm2022/descope-angular-sdk.mjs +0 -5
  82. package/dist/esm2022/environment.mjs +0 -4
  83. package/dist/esm2022/lib/components/descope/descope.component.mjs +0 -106
  84. package/dist/esm2022/lib/components/sign-in-flow/sign-in-flow.component.mjs +0 -40
  85. package/dist/esm2022/lib/components/sign-up-flow/sign-up-flow.component.mjs +0 -40
  86. package/dist/esm2022/lib/components/sign-up-or-in-flow/sign-up-or-in-flow.component.mjs +0 -40
  87. package/dist/esm2022/lib/descope-auth.module.mjs +0 -52
  88. package/dist/esm2022/lib/services/descope-auth.guard.mjs +0 -15
  89. package/dist/esm2022/lib/services/descope-auth.service.mjs +0 -139
  90. package/dist/esm2022/lib/services/descope.interceptor.mjs +0 -51
  91. package/dist/esm2022/lib/types/types.mjs +0 -6
  92. package/dist/esm2022/lib/utils/constants.mjs +0 -7
  93. package/dist/esm2022/lib/utils/helpers.mjs +0 -27
  94. package/dist/esm2022/public-api.mjs +0 -13
  95. package/dist/fesm2022/descope-angular-sdk.mjs +0 -500
  96. package/dist/fesm2022/descope-angular-sdk.mjs.map +0 -1
  97. package/dist/index.d.ts +0 -5
  98. package/dist/lib/components/descope/descope.component.d.ts +0 -32
  99. package/dist/lib/components/sign-in-flow/sign-in-flow.component.d.ts +0 -24
  100. package/dist/lib/components/sign-up-flow/sign-up-flow.component.d.ts +0 -24
  101. package/dist/lib/components/sign-up-or-in-flow/sign-up-or-in-flow.component.d.ts +0 -24
  102. package/dist/lib/descope-auth.module.d.ts +0 -14
  103. package/dist/lib/services/descope-auth.guard.d.ts +0 -2
  104. package/dist/lib/services/descope-auth.service.d.ts +0 -38
  105. package/dist/lib/services/descope.interceptor.d.ts +0 -2
  106. package/dist/lib/types/types.d.ts +0 -8
  107. package/dist/lib/utils/constants.d.ts +0 -5
  108. package/dist/lib/utils/helpers.d.ts +0 -5
  109. package/dist/package.json +0 -42
  110. /package/{dist → projects/angular-sdk}/README.md +0 -0
@@ -0,0 +1,103 @@
1
+ import { observabilify, Observablefied } from './helpers';
2
+ import { lastValueFrom, Observable } from 'rxjs';
3
+
4
+ describe('Helpers', () => {
5
+ describe('Observabilify', () => {
6
+ it('should not affect simple object', () => {
7
+ //GIVEN
8
+ const obj = {
9
+ field1: 'string',
10
+ field2: 123,
11
+ nested: {
12
+ field1: 'string',
13
+ field2: 123
14
+ }
15
+ };
16
+ type TestType = typeof obj;
17
+
18
+ //WHEN
19
+ const result: Observablefied<TestType> = observabilify<TestType>(obj);
20
+
21
+ //THEN
22
+ expect(result).toStrictEqual(obj);
23
+ });
24
+
25
+ it('should not affect simple object with non async functions', () => {
26
+ //GIVEN
27
+ const obj = {
28
+ field1: 'string',
29
+ field2: 123,
30
+ fn: (arg1: string, arg2: number): string => {
31
+ return arg1 + arg2.toString();
32
+ },
33
+ nested: {
34
+ fn2: (arg: string): string => {
35
+ return arg;
36
+ },
37
+ field1: 'string',
38
+ field2: 123
39
+ }
40
+ };
41
+ type TestType = typeof obj;
42
+ const expected1 = obj.fn('Test', 1);
43
+ const expected2 = obj.nested.fn2('Test');
44
+
45
+ //WHEN
46
+ const transformed: Observablefied<TestType> =
47
+ observabilify<TestType>(obj);
48
+ const actual1 = transformed.fn('Test', 1);
49
+ const actual2 = transformed.nested.fn2('Test');
50
+
51
+ //THEN
52
+ expect(expected1).toStrictEqual(actual1);
53
+ expect(expected2).toStrictEqual(actual2);
54
+ });
55
+
56
+ it('should transform async functions', async () => {
57
+ //GIVEN
58
+ const obj = {
59
+ field1: 'string',
60
+ field2: 123,
61
+ fn: (arg1: string, arg2: number): string => {
62
+ return arg1 + arg2.toString();
63
+ },
64
+ asyncFn: (arg1: string, arg2: number): Promise<string> => {
65
+ return Promise.resolve(arg1 + arg2.toString());
66
+ },
67
+ nested: {
68
+ fn2: (arg: string) => {
69
+ return arg;
70
+ },
71
+ asyncFn: (arg: string): Promise<string> => {
72
+ return Promise.resolve(arg);
73
+ },
74
+ field1: 'string',
75
+ field2: 123
76
+ }
77
+ };
78
+ type TestType = typeof obj;
79
+ const expected1 = obj.fn('Test', 1);
80
+ const expected2 = obj.nested.fn2('Test');
81
+ const expected3 = await obj.asyncFn('Test', 1);
82
+ const expected4 = await obj.nested.asyncFn('Test');
83
+
84
+ //WHEN
85
+ const transformed: Observablefied<TestType> =
86
+ observabilify<TestType>(obj);
87
+ const actual1 = transformed.fn('Test', 1);
88
+ const actual2 = transformed.nested.fn2('Test');
89
+ const actual3Async = transformed.asyncFn('Test', 1);
90
+ const actual3 = await lastValueFrom(actual3Async);
91
+ const actual4Async = transformed.nested.asyncFn('Test');
92
+ const actual4 = await lastValueFrom(actual4Async);
93
+
94
+ //THEN
95
+ expect(expected1).toStrictEqual(actual1);
96
+ expect(expected2).toStrictEqual(actual2);
97
+ expect(actual3Async).toBeInstanceOf(Observable);
98
+ expect(actual4Async).toBeInstanceOf(Observable);
99
+ expect(expected3).toStrictEqual(actual3);
100
+ expect(expected4).toStrictEqual(actual4);
101
+ });
102
+ });
103
+ });
@@ -0,0 +1,36 @@
1
+ import { from, Observable } from 'rxjs';
2
+
3
+ export type Observablefied<T> = {
4
+ [K in keyof T]: T[K] extends (...args: infer Args) => Promise<infer R>
5
+ ? (...args: Args) => Observable<R>
6
+ : T[K] extends (...args: infer Args) => infer R
7
+ ? (...args: Args) => R
8
+ : T[K] extends object
9
+ ? Observablefied<T[K]>
10
+ : T[K];
11
+ };
12
+
13
+ export function observabilify<T>(value: T): Observablefied<T> {
14
+ /* eslint-disable @typescript-eslint/no-explicit-any */
15
+ const observableValue: any = {};
16
+
17
+ for (const key in value) {
18
+ if (typeof value[key] === 'function') {
19
+ const fn = value[key] as (...args: unknown[]) => unknown;
20
+ observableValue[key] = (...args: unknown[]) => {
21
+ const fnResult = fn(...args);
22
+ if (fnResult instanceof Promise) {
23
+ return from(fnResult);
24
+ } else {
25
+ return fnResult;
26
+ }
27
+ };
28
+ } else if (typeof value[key] === 'object' && value[key] !== null) {
29
+ observableValue[key] = observabilify(value[key]);
30
+ } else {
31
+ observableValue[key] = value[key];
32
+ }
33
+ }
34
+
35
+ return observableValue as Observablefied<T>;
36
+ }
@@ -1,3 +1,7 @@
1
+ /*
2
+ * Public API Surface of angular-sdk
3
+ */
4
+
1
5
  export * from './lib/services/descope-auth.service';
2
6
  export * from './lib/services/descope-auth.guard';
3
7
  export * from './lib/services/descope.interceptor';
@@ -0,0 +1,12 @@
1
+ /* To learn more about this file see: https://angular.io/config/tsconfig. */
2
+ {
3
+ "extends": "../../tsconfig.json",
4
+ "compilerOptions": {
5
+ "outDir": "../../out-tsc/lib",
6
+ "declaration": true,
7
+ "declarationMap": true,
8
+ "inlineSources": true,
9
+ "types": []
10
+ },
11
+ "exclude": ["**/*.spec.ts"]
12
+ }
@@ -0,0 +1,10 @@
1
+ /* To learn more about this file see: https://angular.io/config/tsconfig. */
2
+ {
3
+ "extends": "./tsconfig.lib.json",
4
+ "compilerOptions": {
5
+ "declarationMap": false
6
+ },
7
+ "angularCompilerOptions": {
8
+ "compilationMode": "partial"
9
+ }
10
+ }
@@ -0,0 +1,11 @@
1
+ /* To learn more about this file see: https://angular.io/config/tsconfig. */
2
+ {
3
+ "extends": "../../tsconfig.json",
4
+ "compilerOptions": {
5
+ "outDir": "../../out-tsc/spec",
6
+ "types": ["jest"],
7
+ "esModuleInterop": true,
8
+ "emitDecoratorMetadata": true
9
+ },
10
+ "include": ["**/*.spec.ts", "**/*.d.ts"]
11
+ }
@@ -0,0 +1,31 @@
1
+ {
2
+ "extends": "../../.eslintrc.json",
3
+ "ignorePatterns": ["!**/*"],
4
+ "overrides": [
5
+ {
6
+ "files": ["*.ts"],
7
+ "rules": {
8
+ "@angular-eslint/directive-selector": [
9
+ "error",
10
+ {
11
+ "type": "attribute",
12
+ "prefix": "app",
13
+ "style": "camelCase"
14
+ }
15
+ ],
16
+ "@angular-eslint/component-selector": [
17
+ "error",
18
+ {
19
+ "type": "element",
20
+ "prefix": "app",
21
+ "style": "kebab-case"
22
+ }
23
+ ]
24
+ }
25
+ },
26
+ {
27
+ "files": ["*.html"],
28
+ "rules": {}
29
+ }
30
+ ]
31
+ }
@@ -0,0 +1,23 @@
1
+ import { NgModule } from '@angular/core';
2
+ import { RouterModule, Routes } from '@angular/router';
3
+ import { HomeComponent } from './home/home.component';
4
+ import { ProtectedComponent } from './protected/protected.component';
5
+ import { descopeAuthGuard } from '../../../angular-sdk/src/lib/services/descope-auth.guard';
6
+ import { LoginComponent } from './login/login.component';
7
+
8
+ const routes: Routes = [
9
+ {
10
+ path: 'step-up',
11
+ component: ProtectedComponent,
12
+ canActivate: [descopeAuthGuard],
13
+ data: { descopeFallbackUrl: '/' }
14
+ },
15
+ { path: 'login', component: LoginComponent },
16
+ { path: '**', component: HomeComponent }
17
+ ];
18
+
19
+ @NgModule({
20
+ imports: [RouterModule.forRoot(routes, { enableTracing: false })],
21
+ exports: [RouterModule]
22
+ })
23
+ export class AppRoutingModule {}
@@ -0,0 +1,3 @@
1
+ <main>
2
+ <router-outlet></router-outlet>
3
+ </main>
@@ -0,0 +1,16 @@
1
+ :host {
2
+ height: 100vh;
3
+ position: relative;
4
+ }
5
+ main {
6
+ border-radius: 10px;
7
+ margin: auto;
8
+ border: 1px solid lightgray;
9
+ padding: 20px;
10
+ max-width: 400px;
11
+ box-shadow: 13px 13px 20px #cbced1, -13px -13px 20px #fff;
12
+ background: #ecf0f3;
13
+ position: relative;
14
+ top: 50%;
15
+ transform: translateY(-50%);
16
+ }
@@ -0,0 +1,37 @@
1
+ import { TestBed } from '@angular/core/testing';
2
+ import { RouterTestingModule } from '@angular/router/testing';
3
+ import { AppComponent } from './app.component';
4
+ import createSdk from '@descope/web-js-sdk';
5
+ import mocked = jest.mocked;
6
+ import { DescopeAuthConfig } from '../../../angular-sdk/src/lib/types/types';
7
+
8
+ jest.mock('@descope/web-js-sdk');
9
+
10
+ describe('AppComponent', () => {
11
+ let mockedCreateSdk: jest.Mock;
12
+ const onSessionTokenChangeSpy = jest.fn();
13
+ const onUserChangeSpy = jest.fn();
14
+
15
+ beforeEach(() => {
16
+ mockedCreateSdk = mocked(createSdk);
17
+ mockedCreateSdk.mockReturnValue({
18
+ onSessionTokenChange: onSessionTokenChangeSpy,
19
+ onUserChange: onUserChangeSpy
20
+ });
21
+
22
+ TestBed.configureTestingModule({
23
+ imports: [RouterTestingModule],
24
+ providers: [
25
+ DescopeAuthConfig,
26
+ { provide: DescopeAuthConfig, useValue: { projectId: 'test' } }
27
+ ],
28
+ declarations: [AppComponent]
29
+ });
30
+ });
31
+
32
+ it('should create the app', () => {
33
+ const fixture = TestBed.createComponent(AppComponent);
34
+ const app = fixture.componentInstance;
35
+ expect(app).toBeTruthy();
36
+ });
37
+ });
@@ -0,0 +1,8 @@
1
+ import { Component } from '@angular/core';
2
+
3
+ @Component({
4
+ selector: 'app-root',
5
+ templateUrl: './app.component.html',
6
+ styleUrls: ['./app.component.scss']
7
+ })
8
+ export class AppComponent {}
@@ -0,0 +1,52 @@
1
+ import { APP_INITIALIZER, NgModule } from '@angular/core';
2
+ import { BrowserModule } from '@angular/platform-browser';
3
+
4
+ import { AppRoutingModule } from './app-routing.module';
5
+ import { AppComponent } from './app.component';
6
+ import { DescopeAuthModule } from '../../../angular-sdk/src/lib/descope-auth.module';
7
+ import { HomeComponent } from './home/home.component';
8
+ import { ProtectedComponent } from './protected/protected.component';
9
+ import { environment } from '../environments/environment';
10
+ import { DescopeAuthService } from 'projects/angular-sdk/src/public-api';
11
+ import { zip } from 'rxjs';
12
+ import { LoginComponent } from './login/login.component';
13
+ import {
14
+ HttpClientModule,
15
+ provideHttpClient,
16
+ withInterceptors
17
+ } from '@angular/common/http';
18
+ import { descopeInterceptor } from '../../../angular-sdk/src/lib/services/descope.interceptor';
19
+
20
+ export function initializeApp(authService: DescopeAuthService) {
21
+ return () => zip([authService.refreshSession(), authService.refreshUser()]);
22
+ }
23
+
24
+ @NgModule({
25
+ declarations: [
26
+ AppComponent,
27
+ HomeComponent,
28
+ ProtectedComponent,
29
+ LoginComponent
30
+ ],
31
+ imports: [
32
+ BrowserModule,
33
+ AppRoutingModule,
34
+ HttpClientModule,
35
+ DescopeAuthModule.forRoot({
36
+ projectId: environment.descopeProjectId,
37
+ baseUrl: environment.descopeBaseUrl || '',
38
+ sessionTokenViaCookie: false
39
+ })
40
+ ],
41
+ providers: [
42
+ {
43
+ provide: APP_INITIALIZER,
44
+ useFactory: initializeApp,
45
+ deps: [DescopeAuthService],
46
+ multi: true
47
+ },
48
+ provideHttpClient(withInterceptors([descopeInterceptor]))
49
+ ],
50
+ bootstrap: [AppComponent]
51
+ })
52
+ export class AppModule {}
@@ -0,0 +1,23 @@
1
+ <h2>ANGULAR SDK DEMO APP</h2>
2
+ <button *ngIf="!isAuthenticated" (click)="login()">LOGIN</button>
3
+ <ng-container *ngIf="isAuthenticated">
4
+ <h3>Hello {{ userName }}</h3>
5
+ <div>
6
+ Roles:
7
+ <ng-container *ngIf="roles && roles.length; else noRoles">
8
+ {{ roles }}
9
+ </ng-container>
10
+ <ng-template #noRoles>N/A</ng-template>
11
+ </div>
12
+ <button
13
+ *ngIf="backendUrl.length > 0"
14
+ class="action-button"
15
+ (click)="fetchData()"
16
+ >
17
+ FETCH DATA
18
+ </button>
19
+ <button *ngIf="stepUpConfigured" class="action-button" (click)="stepUp()">
20
+ STEP UP
21
+ </button>
22
+ <button class="logout-button" (click)="logout()">LOGOUT</button>
23
+ </ng-container>
@@ -0,0 +1,15 @@
1
+ :host {
2
+ display: flex;
3
+ justify-content: center;
4
+ align-items: center;
5
+ flex-direction: column;
6
+ }
7
+ .action-button {
8
+ border: 1px solid #00ace1;
9
+ background-color: white;
10
+ color: #00ace1;
11
+ margin-bottom: 1rem;
12
+ &:first-of-type {
13
+ margin-top: 1rem;
14
+ }
15
+ }
@@ -0,0 +1,44 @@
1
+ import { ComponentFixture, TestBed } from '@angular/core/testing';
2
+
3
+ import { HomeComponent } from './home.component';
4
+ import createSdk from '@descope/web-js-sdk';
5
+ import mocked = jest.mocked;
6
+ import { NO_ERRORS_SCHEMA } from '@angular/core';
7
+ import { DescopeAuthConfig } from '../../../../angular-sdk/src/lib/types/types';
8
+ import { HttpClientTestingModule } from '@angular/common/http/testing';
9
+
10
+ jest.mock('@descope/web-js-sdk');
11
+
12
+ describe('HomeComponent', () => {
13
+ let component: HomeComponent;
14
+ let fixture: ComponentFixture<HomeComponent>;
15
+
16
+ let mockedCreateSdk: jest.Mock;
17
+ const onSessionTokenChangeSpy = jest.fn();
18
+ const onUserChangeSpy = jest.fn();
19
+
20
+ beforeEach(() => {
21
+ mockedCreateSdk = mocked(createSdk);
22
+ mockedCreateSdk.mockReturnValue({
23
+ onSessionTokenChange: onSessionTokenChangeSpy,
24
+ onUserChange: onUserChangeSpy
25
+ });
26
+
27
+ TestBed.configureTestingModule({
28
+ imports: [HttpClientTestingModule],
29
+ schemas: [NO_ERRORS_SCHEMA],
30
+ declarations: [HomeComponent],
31
+ providers: [
32
+ DescopeAuthConfig,
33
+ { provide: DescopeAuthConfig, useValue: { projectId: 'test' } }
34
+ ]
35
+ });
36
+ fixture = TestBed.createComponent(HomeComponent);
37
+ component = fixture.componentInstance;
38
+ fixture.detectChanges();
39
+ });
40
+
41
+ it('should create', () => {
42
+ expect(component).toBeTruthy();
43
+ });
44
+ });
@@ -0,0 +1,61 @@
1
+ import { Component, OnInit } from '@angular/core';
2
+ import { DescopeAuthService } from '../../../../angular-sdk/src/lib/services/descope-auth.service';
3
+ import { Router } from '@angular/router';
4
+ import { environment } from '../../environments/environment';
5
+ import { HttpClient } from '@angular/common/http';
6
+
7
+ @Component({
8
+ selector: 'app-home',
9
+ templateUrl: './home.component.html',
10
+ styleUrls: ['./home.component.scss']
11
+ })
12
+ export class HomeComponent implements OnInit {
13
+ projectId: string = environment.descopeProjectId;
14
+ isAuthenticated: boolean = false;
15
+ roles: string[] = [];
16
+ userName: string = '';
17
+ stepUpConfigured = (environment.descopeStepUpFlowId ?? '').length > 0;
18
+ backendUrl = environment.backendUrl ?? '';
19
+
20
+ constructor(
21
+ private router: Router,
22
+ private httpClient: HttpClient,
23
+ private authService: DescopeAuthService
24
+ ) {}
25
+
26
+ ngOnInit() {
27
+ this.authService.session$.subscribe((session) => {
28
+ this.isAuthenticated = session.isAuthenticated;
29
+ if (session.sessionToken) {
30
+ this.roles = this.authService.getJwtRoles(session.sessionToken);
31
+ }
32
+ });
33
+ this.authService.user$.subscribe((descopeUser) => {
34
+ if (descopeUser.user) {
35
+ this.userName = descopeUser.user.name ?? '';
36
+ }
37
+ });
38
+ }
39
+
40
+ login() {
41
+ this.router.navigate(['/login']).catch((err) => console.error(err));
42
+ }
43
+
44
+ logout() {
45
+ this.authService.descopeSdk.logout();
46
+ }
47
+
48
+ fetchData() {
49
+ if (this.backendUrl) {
50
+ this.httpClient
51
+ .get(this.backendUrl, { responseType: 'text' })
52
+ .subscribe((data) => alert(data));
53
+ } else {
54
+ console.warn('Please setup backendUrl in your environment');
55
+ }
56
+ }
57
+
58
+ stepUp() {
59
+ this.router.navigate(['/step-up']).catch((err) => console.error(err));
60
+ }
61
+ }
@@ -0,0 +1,20 @@
1
+ import {
2
+ HttpHandlerFn,
3
+ HttpInterceptorFn,
4
+ HttpRequest
5
+ } from '@angular/common/http';
6
+ import { inject } from '@angular/core';
7
+ import { DescopeAuthService } from '../../../../angular-sdk/src/lib/services/descope-auth.service';
8
+
9
+ export const authenticationInterceptor: HttpInterceptorFn = (
10
+ req: HttpRequest<unknown>,
11
+ next: HttpHandlerFn
12
+ ) => {
13
+ const authService = inject(DescopeAuthService);
14
+ const sessionToken = authService.getSessionToken();
15
+ const modifiedReq = req.clone({
16
+ headers: req.headers.set('Authorization', `Bearer ${sessionToken}`)
17
+ });
18
+
19
+ return next(modifiedReq);
20
+ };
@@ -0,0 +1,12 @@
1
+ <descope
2
+ (success)="onSuccess()"
3
+ (error)="onError()"
4
+ [theme]="theme"
5
+ [flowId]="flowId"
6
+ [locale]="locale"
7
+ [redirectUrl]="redirectUrl"
8
+ [telemetryKey]="telemetryKey"
9
+ [tenant]="tenantId"
10
+ [debug]="debugMode"
11
+ [errorTransformer]="errorTransformer"
12
+ ></descope>
@@ -0,0 +1,42 @@
1
+ import { ComponentFixture, TestBed } from '@angular/core/testing';
2
+
3
+ import { LoginComponent } from './login.component';
4
+ import createSdk from '@descope/web-js-sdk';
5
+ import { NO_ERRORS_SCHEMA } from '@angular/core';
6
+ import { DescopeAuthConfig } from '../../../../angular-sdk/src/lib/types/types';
7
+ import mocked = jest.mocked;
8
+
9
+ jest.mock('@descope/web-js-sdk');
10
+
11
+ describe('LoginComponent', () => {
12
+ let component: LoginComponent;
13
+ let fixture: ComponentFixture<LoginComponent>;
14
+
15
+ let mockedCreateSdk: jest.Mock;
16
+ const onSessionTokenChangeSpy = jest.fn();
17
+ const onUserChangeSpy = jest.fn();
18
+
19
+ beforeEach(() => {
20
+ mockedCreateSdk = mocked(createSdk);
21
+ mockedCreateSdk.mockReturnValue({
22
+ onSessionTokenChange: onSessionTokenChangeSpy,
23
+ onUserChange: onUserChangeSpy
24
+ });
25
+
26
+ TestBed.configureTestingModule({
27
+ schemas: [NO_ERRORS_SCHEMA],
28
+ declarations: [LoginComponent],
29
+ providers: [
30
+ DescopeAuthConfig,
31
+ { provide: DescopeAuthConfig, useValue: { projectId: 'test' } }
32
+ ]
33
+ });
34
+ fixture = TestBed.createComponent(LoginComponent);
35
+ component = fixture.componentInstance;
36
+ fixture.detectChanges();
37
+ });
38
+
39
+ it('should create', () => {
40
+ expect(component).toBeTruthy();
41
+ });
42
+ });
@@ -0,0 +1,35 @@
1
+ import { Component } from '@angular/core';
2
+ import { environment } from '../../environments/environment';
3
+ import { Router } from '@angular/router';
4
+
5
+ @Component({
6
+ selector: 'app-login',
7
+ templateUrl: './login.component.html'
8
+ })
9
+ export class LoginComponent {
10
+ flowId = environment.descopeFlowId ?? 'sign-up-or-in';
11
+ theme = (environment.descopeTheme as 'light' | 'dark' | 'os') ?? 'os';
12
+ telemetryKey = environment.descopeTelemetryKey ?? '';
13
+ debugMode = environment.descopeDebugMode ?? false;
14
+ tenantId = environment.descopeTenantId ?? '';
15
+ locale = environment.descopeLocale ?? '';
16
+ redirectUrl = environment.descopeRedirectUrl ?? '';
17
+
18
+ constructor(private router: Router) {}
19
+
20
+ errorTransformer = (error: { text: string; type: string }): string => {
21
+ const translationMap: { [key: string]: string } = {
22
+ SAMLStartFailed: 'Failed to start SAML flow'
23
+ };
24
+ return translationMap[error.type] || error.text;
25
+ };
26
+
27
+ onSuccess() {
28
+ console.log('SUCCESSFULLY LOGGED IN FROM WEB COMPONENT');
29
+ this.router.navigate(['/']).catch((err) => console.error(err));
30
+ }
31
+
32
+ onError() {
33
+ console.log('ERROR FROM LOG IN FLOW FROM WEB COMPONENT');
34
+ }
35
+ }
@@ -0,0 +1,18 @@
1
+ <descope
2
+ *ngIf="!stepUpSuccess"
3
+ (success)="onSuccess()"
4
+ (error)="onError()"
5
+ [theme]="theme"
6
+ [flowId]="flowId"
7
+ [locale]="locale"
8
+ [redirectUrl]="redirectUrl"
9
+ [telemetryKey]="telemetryKey"
10
+ [tenant]="tenantId"
11
+ [debug]="debugMode"
12
+ [errorTransformer]="errorTransformer"
13
+ ></descope>
14
+
15
+ <ng-container *ngIf="stepUpSuccess">
16
+ <h2>STEP UP SUCCESS</h2>
17
+ <button (click)="goBack()">GO BACK</button>
18
+ </ng-container>
@@ -0,0 +1,8 @@
1
+ :host {
2
+ height: 100%;
3
+ display: flex;
4
+ justify-content: center;
5
+ align-items: center;
6
+ flex-direction: column;
7
+ gap: 20px;
8
+ }