@descope/angular-sdk 0.0.0-next-e6e5cd95-20231226

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 (83) hide show
  1. package/.editorconfig +16 -0
  2. package/.eslintrc.json +40 -0
  3. package/.github/workflows/ci.yml +99 -0
  4. package/.github/workflows/publish-next.yml +40 -0
  5. package/.github/workflows/publish.yml +28 -0
  6. package/.github/workflows/release.yml +46 -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/LICENSE +21 -0
  14. package/README.md +460 -0
  15. package/angular.json +154 -0
  16. package/jest.config.js +17 -0
  17. package/package.json +66 -0
  18. package/projects/angular-sdk/.eslintrc.json +32 -0
  19. package/projects/angular-sdk/README.md +25 -0
  20. package/projects/angular-sdk/ng-package.json +8 -0
  21. package/projects/angular-sdk/package.json +20 -0
  22. package/projects/angular-sdk/src/environment.ts +3 -0
  23. package/projects/angular-sdk/src/lib/components/descope/descope.component.spec.ts +104 -0
  24. package/projects/angular-sdk/src/lib/components/descope/descope.component.ts +114 -0
  25. package/projects/angular-sdk/src/lib/components/sign-in-flow/sign-in-flow.component.html +15 -0
  26. package/projects/angular-sdk/src/lib/components/sign-in-flow/sign-in-flow.component.spec.ts +53 -0
  27. package/projects/angular-sdk/src/lib/components/sign-in-flow/sign-in-flow.component.ts +32 -0
  28. package/projects/angular-sdk/src/lib/components/sign-up-flow/sign-up-flow.component.html +15 -0
  29. package/projects/angular-sdk/src/lib/components/sign-up-flow/sign-up-flow.component.spec.ts +51 -0
  30. package/projects/angular-sdk/src/lib/components/sign-up-flow/sign-up-flow.component.ts +32 -0
  31. package/projects/angular-sdk/src/lib/components/sign-up-or-in-flow/sign-up-or-in-flow.component.html +15 -0
  32. package/projects/angular-sdk/src/lib/components/sign-up-or-in-flow/sign-up-or-in-flow.component.spec.ts +53 -0
  33. package/projects/angular-sdk/src/lib/components/sign-up-or-in-flow/sign-up-or-in-flow.component.ts +32 -0
  34. package/projects/angular-sdk/src/lib/descope-auth.module.ts +46 -0
  35. package/projects/angular-sdk/src/lib/services/descope-auth.guard.spec.ts +76 -0
  36. package/projects/angular-sdk/src/lib/services/descope-auth.guard.ts +16 -0
  37. package/projects/angular-sdk/src/lib/services/descope-auth.service.spec.ts +264 -0
  38. package/projects/angular-sdk/src/lib/services/descope-auth.service.ts +176 -0
  39. package/projects/angular-sdk/src/lib/services/descope.interceptor.spec.ts +102 -0
  40. package/projects/angular-sdk/src/lib/services/descope.interceptor.ts +76 -0
  41. package/projects/angular-sdk/src/lib/types/types.ts +10 -0
  42. package/projects/angular-sdk/src/lib/utils/constants.ts +8 -0
  43. package/projects/angular-sdk/src/lib/utils/helpers.spec.ts +103 -0
  44. package/projects/angular-sdk/src/lib/utils/helpers.ts +36 -0
  45. package/projects/angular-sdk/src/public-api.ts +13 -0
  46. package/projects/angular-sdk/tsconfig.lib.json +12 -0
  47. package/projects/angular-sdk/tsconfig.lib.prod.json +10 -0
  48. package/projects/angular-sdk/tsconfig.spec.json +11 -0
  49. package/projects/demo-app/.eslintrc.json +31 -0
  50. package/projects/demo-app/src/app/app-routing.module.ts +23 -0
  51. package/projects/demo-app/src/app/app.component.html +3 -0
  52. package/projects/demo-app/src/app/app.component.scss +16 -0
  53. package/projects/demo-app/src/app/app.component.spec.ts +37 -0
  54. package/projects/demo-app/src/app/app.component.ts +8 -0
  55. package/projects/demo-app/src/app/app.module.ts +52 -0
  56. package/projects/demo-app/src/app/home/home.component.html +23 -0
  57. package/projects/demo-app/src/app/home/home.component.scss +15 -0
  58. package/projects/demo-app/src/app/home/home.component.spec.ts +44 -0
  59. package/projects/demo-app/src/app/home/home.component.ts +61 -0
  60. package/projects/demo-app/src/app/interceptor/auth.interceptor.ts +20 -0
  61. package/projects/demo-app/src/app/login/login.component.html +12 -0
  62. package/projects/demo-app/src/app/login/login.component.spec.ts +42 -0
  63. package/projects/demo-app/src/app/login/login.component.ts +35 -0
  64. package/projects/demo-app/src/app/protected/protected.component.html +18 -0
  65. package/projects/demo-app/src/app/protected/protected.component.scss +8 -0
  66. package/projects/demo-app/src/app/protected/protected.component.spec.ts +42 -0
  67. package/projects/demo-app/src/app/protected/protected.component.ts +40 -0
  68. package/projects/demo-app/src/assets/.gitkeep +0 -0
  69. package/projects/demo-app/src/environments/conifg.ts +13 -0
  70. package/projects/demo-app/src/environments/environment.ts +19 -0
  71. package/projects/demo-app/src/favicon.ico +0 -0
  72. package/projects/demo-app/src/index.html +17 -0
  73. package/projects/demo-app/src/main.ts +7 -0
  74. package/projects/demo-app/src/styles.scss +21 -0
  75. package/projects/demo-app/tsconfig.app.json +10 -0
  76. package/projects/demo-app/tsconfig.spec.json +10 -0
  77. package/renovate.json +4 -0
  78. package/scripts/gitleaks/.gitleaks.toml +653 -0
  79. package/scripts/gitleaks/gitleaks.sh +34 -0
  80. package/scripts/setversion/setversion.js +20 -0
  81. package/setup-jest.ts +1 -0
  82. package/thirdPartyLicenseCollector_linux_amd64 +0 -0
  83. package/tsconfig.json +35 -0
@@ -0,0 +1,32 @@
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": "lib",
13
+ "style": "camelCase"
14
+ }
15
+ ],
16
+ "@angular-eslint/component-selector": [
17
+ "error",
18
+ {
19
+ "type": "element",
20
+ "prefix": "",
21
+ "style": "kebab-case"
22
+ }
23
+ ],
24
+ "@angular-eslint/no-output-native": "off"
25
+ }
26
+ },
27
+ {
28
+ "files": ["*.html"],
29
+ "rules": {}
30
+ }
31
+ ]
32
+ }
@@ -0,0 +1,25 @@
1
+ # AngularSdk
2
+
3
+ This library was generated with [Angular CLI](https://github.com/angular/angular-cli) version 16.2.0.
4
+
5
+ ## Code scaffolding
6
+
7
+ Run `ng generate component component-name --project angular-sdk` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module --project angular-sdk`.
8
+
9
+ > Note: Don't forget to add `--project angular-sdk` or else it will be added to the default project in your `angular.json` file.
10
+
11
+ ## Build
12
+
13
+ Run `ng build angular-sdk` to build the project. The build artifacts will be stored in the `dist/` directory.
14
+
15
+ ## Publishing
16
+
17
+ After building your library with `ng build angular-sdk`, go to the dist folder `cd dist/angular-sdk` and run `npm publish`.
18
+
19
+ ## Running unit tests
20
+
21
+ Run `ng test angular-sdk` to execute the unit tests via [Karma](https://karma-runner.github.io).
22
+
23
+ ## Further help
24
+
25
+ To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI Overview and Command Reference](https://angular.io/cli) page.
@@ -0,0 +1,8 @@
1
+ {
2
+ "$schema": "../../node_modules/ng-packagr/ng-package.schema.json",
3
+ "dest": "../../dist/angular-sdk",
4
+ "lib": {
5
+ "entryFile": "src/public-api.ts"
6
+ },
7
+ "allowedNonPeerDependencies": ["@descope/web-component"]
8
+ }
@@ -0,0 +1,20 @@
1
+ {
2
+ "name": "angular-sdk",
3
+ "version": "0.0.1",
4
+ "engines": {
5
+ "node": "^16.14.0 || ^18.10.0",
6
+ "npm": ">= 8.1.0"
7
+ },
8
+ "peerDependencies": {
9
+ "@angular/common": ">=16.0.0",
10
+ "@angular/core": ">=16.0.0"
11
+ },
12
+ "dependencies": {
13
+ "tslib": "^2.3.0",
14
+ "@descope/web-component": "3.0.0"
15
+ },
16
+ "optionalDependencies": {
17
+ "@descope/web-js-sdk": ">=1"
18
+ },
19
+ "sideEffects": false
20
+ }
@@ -0,0 +1,3 @@
1
+ export const environment = {
2
+ buildVersion: '0.0.0' // Placeholder, replaced by pre-build script (setversion.js)
3
+ };
@@ -0,0 +1,104 @@
1
+ import { ComponentFixture, TestBed } from '@angular/core/testing';
2
+
3
+ import { DescopeComponent } from './descope.component';
4
+ import createSdk from '@descope/web-js-sdk';
5
+ import { DescopeAuthConfig } from '../../types/types';
6
+ import { CUSTOM_ELEMENTS_SCHEMA, EventEmitter } from '@angular/core';
7
+ import mocked = jest.mocked;
8
+
9
+ jest.mock('@descope/web-js-sdk');
10
+ //Mock DescopeWebComponent
11
+ jest.mock('@descope/web-component', () => {
12
+ return jest.fn(() => {
13
+ // Create a mock DOM element
14
+ return document.createElement('descope-wc');
15
+ });
16
+ });
17
+
18
+ describe('DescopeComponent', () => {
19
+ let component: DescopeComponent;
20
+ let fixture: ComponentFixture<DescopeComponent>;
21
+ let mockedCreateSdk: jest.Mock;
22
+ const onSessionTokenChangeSpy = jest.fn();
23
+ const onUserChangeSpy = jest.fn();
24
+ const afterRequestHooksSpy = jest.fn();
25
+ const mockConfig: DescopeAuthConfig = {
26
+ projectId: 'someProject'
27
+ };
28
+
29
+ beforeEach(() => {
30
+ mockedCreateSdk = mocked(createSdk);
31
+
32
+ mockedCreateSdk.mockReturnValue({
33
+ onSessionTokenChange: onSessionTokenChangeSpy,
34
+ onUserChange: onUserChangeSpy,
35
+ httpClient: {
36
+ hooks: {
37
+ afterRequest: afterRequestHooksSpy
38
+ }
39
+ }
40
+ });
41
+
42
+ TestBed.configureTestingModule({
43
+ schemas: [CUSTOM_ELEMENTS_SCHEMA],
44
+ providers: [
45
+ DescopeAuthConfig,
46
+ { provide: DescopeAuthConfig, useValue: mockConfig }
47
+ ]
48
+ });
49
+
50
+ fixture = TestBed.createComponent(DescopeComponent);
51
+ component = fixture.componentInstance;
52
+ component.projectId = '123';
53
+ component.flowId = 'sign-in';
54
+ component.locale = 'en-US';
55
+ component.success = new EventEmitter<void>();
56
+ component.error = new EventEmitter<void>();
57
+ component.logger = { info: jest.fn(), error: jest.fn(), warn: jest.fn() };
58
+ component.errorTransformer = jest.fn();
59
+ fixture.detectChanges();
60
+ });
61
+
62
+ it('should create', () => {
63
+ expect(component).toBeTruthy();
64
+ const html: HTMLElement = fixture.nativeElement;
65
+ const webComponentHtml = html.querySelector('descope-wc');
66
+ expect(webComponentHtml).toBeDefined();
67
+ });
68
+
69
+ it('should correctly setup attributes based on inputs', () => {
70
+ const html: HTMLElement = fixture.nativeElement;
71
+ const webComponentHtml = html.querySelector('descope-wc')!;
72
+ expect(webComponentHtml.getAttribute('project-id')).toStrictEqual('123');
73
+ expect(webComponentHtml.getAttribute('flow-id')).toStrictEqual('sign-in');
74
+ expect(webComponentHtml.getAttribute('locale')).toStrictEqual('en-US');
75
+ expect(webComponentHtml.getAttribute('logger')).toBeDefined();
76
+ expect(webComponentHtml.getAttribute('error-transformer')).toBeDefined();
77
+ expect(webComponentHtml.getAttribute('redirect-url')).toBeNull();
78
+ });
79
+
80
+ it('should emit success when web component emits success', () => {
81
+ const html: HTMLElement = fixture.nativeElement;
82
+ const webComponentHtml = html.querySelector('descope-wc')!;
83
+
84
+ component.success.subscribe(() => {
85
+ expect(true).toBeTruthy();
86
+ expect(afterRequestHooksSpy).toHaveBeenCalled();
87
+ });
88
+ webComponentHtml.dispatchEvent(
89
+ new CustomEvent('success', {
90
+ detail: { user: { name: 'user1' }, sessionJwt: 'session1' }
91
+ })
92
+ );
93
+ });
94
+
95
+ it('should emit error when web component emits error', () => {
96
+ const html: HTMLElement = fixture.nativeElement;
97
+ const webComponentHtml = html.querySelector('descope-wc')!;
98
+
99
+ component.error.subscribe(() => {
100
+ expect(true).toBeTruthy();
101
+ });
102
+ webComponentHtml.dispatchEvent(new CustomEvent('error'));
103
+ });
104
+ });
@@ -0,0 +1,114 @@
1
+ import {
2
+ Component,
3
+ ElementRef,
4
+ EventEmitter,
5
+ Input,
6
+ OnChanges,
7
+ OnInit,
8
+ Output
9
+ } from '@angular/core';
10
+ import DescopeWebComponent from '@descope/web-component';
11
+ import DescopeWc, { ILogger } from '@descope/web-component';
12
+ import { DescopeAuthService } from '../../services/descope-auth.service';
13
+ import { from } from 'rxjs';
14
+ import { baseHeaders } from '../../utils/constants';
15
+ import { DescopeAuthConfig } from '../../types/types';
16
+
17
+ @Component({
18
+ selector: 'descope[flowId]',
19
+ standalone: true,
20
+ template: ''
21
+ })
22
+ export class DescopeComponent implements OnInit, OnChanges {
23
+ projectId: string;
24
+ @Input() flowId: string;
25
+
26
+ @Input() locale: string;
27
+ @Input() theme: 'light' | 'dark' | 'os';
28
+ @Input() tenant: string;
29
+ @Input() telemetryKey: string;
30
+ @Input() redirectUrl: string;
31
+ @Input() autoFocus: true | false | 'skipFirstScreen';
32
+
33
+ @Input() debug: boolean;
34
+ @Input() errorTransformer: (error: { text: string; type: string }) => string;
35
+ @Input() logger: ILogger;
36
+
37
+ @Output() success: EventEmitter<void> = new EventEmitter<void>();
38
+ @Output() error: EventEmitter<void> = new EventEmitter<void>();
39
+
40
+ private readonly webComponent: DescopeWebComponent =
41
+ new DescopeWebComponent();
42
+
43
+ constructor(
44
+ private elementRef: ElementRef,
45
+ private authService: DescopeAuthService,
46
+ descopeConfig: DescopeAuthConfig
47
+ ) {
48
+ this.projectId = descopeConfig.projectId;
49
+ }
50
+
51
+ ngOnInit() {
52
+ DescopeWc.sdkConfigOverrides = { baseHeaders };
53
+ this.setupWebComponent();
54
+ this.elementRef.nativeElement.appendChild(this.webComponent);
55
+ }
56
+
57
+ ngOnChanges(): void {
58
+ this.setupWebComponent();
59
+ }
60
+
61
+ private setupWebComponent() {
62
+ this.webComponent.setAttribute('project-id', this.projectId);
63
+ this.webComponent.setAttribute('flow-id', this.flowId);
64
+ if (this.locale) {
65
+ this.webComponent.setAttribute('locale', this.locale);
66
+ }
67
+ if (this.theme) {
68
+ this.webComponent.setAttribute('theme', this.theme);
69
+ }
70
+ if (this.tenant) {
71
+ this.webComponent.setAttribute('tenant', this.tenant);
72
+ }
73
+ if (this.telemetryKey) {
74
+ this.webComponent.setAttribute('telemetryKey', this.telemetryKey);
75
+ }
76
+ if (this.redirectUrl) {
77
+ this.webComponent.setAttribute('redirect-url', this.redirectUrl);
78
+ }
79
+ if (this.autoFocus) {
80
+ this.webComponent.setAttribute('auto-focus', this.autoFocus.toString());
81
+ }
82
+ if (this.debug) {
83
+ this.webComponent.setAttribute('debug', this.debug.toString());
84
+ }
85
+
86
+ if (this.errorTransformer) {
87
+ this.webComponent.errorTransformer = this.errorTransformer;
88
+ }
89
+
90
+ if (this.logger) {
91
+ this.webComponent.logger = this.logger;
92
+ }
93
+
94
+ if (this.success) {
95
+ this.webComponent.addEventListener('success', (e: Event) => {
96
+ from(
97
+ this.authService.descopeSdk.httpClient.hooks?.afterRequest!(
98
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
99
+ {} as any,
100
+ new Response(JSON.stringify((e as CustomEvent).detail))
101
+ ) as Promise<unknown>
102
+ ).subscribe(() => {
103
+ this.success?.emit();
104
+ });
105
+ });
106
+ }
107
+
108
+ if (this.error) {
109
+ this.webComponent.addEventListener('error', () => {
110
+ this.error?.emit();
111
+ });
112
+ }
113
+ }
114
+ }
@@ -0,0 +1,15 @@
1
+ <descope
2
+ (success)="success.emit()"
3
+ (error)="error.emit()"
4
+ flowId="sign-in"
5
+ [locale]="locale"
6
+ [theme]="theme"
7
+ [tenant]="tenant"
8
+ [telemetryKey]="telemetryKey"
9
+ [redirectUrl]="redirectUrl"
10
+ [autoFocus]="autoFocus"
11
+ [debug]="debug"
12
+ [errorTransformer]="errorTransformer"
13
+ [logger]="logger"
14
+ >
15
+ </descope>
@@ -0,0 +1,53 @@
1
+ import { ComponentFixture, TestBed } from '@angular/core/testing';
2
+ import { SignInFlowComponent } from './sign-in-flow.component';
3
+ import { ngMocks } from 'ng-mocks';
4
+ import { DescopeComponent } from '../descope/descope.component';
5
+ import { DescopeAuthConfig } from '../../types/types';
6
+ import createSdk from '@descope/web-js-sdk';
7
+ import mocked = jest.mocked;
8
+
9
+ jest.mock('@descope/web-js-sdk');
10
+ jest.mock('@descope/web-component', () => {
11
+ return jest.fn(() => {
12
+ // Create a mock DOM element
13
+ return document.createElement('descope-wc');
14
+ });
15
+ });
16
+
17
+ describe('SignInFlowComponent', () => {
18
+ let component: SignInFlowComponent;
19
+ let fixture: ComponentFixture<SignInFlowComponent>;
20
+ let mockedCreateSdk: jest.Mock;
21
+
22
+ beforeEach(() => {
23
+ mockedCreateSdk = mocked(createSdk);
24
+
25
+ mockedCreateSdk.mockReturnValue({
26
+ onSessionTokenChange: jest.fn(),
27
+ onUserChange: jest.fn()
28
+ });
29
+
30
+ TestBed.configureTestingModule({
31
+ providers: [
32
+ DescopeAuthConfig,
33
+ {
34
+ provide: DescopeAuthConfig,
35
+ useValue: {
36
+ projectId: 'someProject'
37
+ }
38
+ }
39
+ ]
40
+ });
41
+
42
+ fixture = TestBed.createComponent(SignInFlowComponent);
43
+ component = fixture.componentInstance;
44
+ fixture.detectChanges();
45
+ });
46
+
47
+ it('should create and be correctly configured', () => {
48
+ expect(component).toBeTruthy();
49
+ const mockComponent =
50
+ ngMocks.find<DescopeComponent>('[flowId=sign-in]').componentInstance;
51
+ expect(mockComponent.flowId).toStrictEqual('sign-in');
52
+ });
53
+ });
@@ -0,0 +1,32 @@
1
+ import { Component, EventEmitter, Input, Output } from '@angular/core';
2
+ import { ILogger } from '@descope/web-component';
3
+ import { DescopeComponent } from '../descope/descope.component';
4
+ import { DescopeAuthConfig } from '../../types/types';
5
+
6
+ @Component({
7
+ selector: 'descope-sign-in-flow',
8
+ standalone: true,
9
+ imports: [DescopeComponent],
10
+ templateUrl: './sign-in-flow.component.html'
11
+ })
12
+ export class SignInFlowComponent {
13
+ projectId: string;
14
+
15
+ @Input() locale: string;
16
+ @Input() theme: 'light' | 'dark' | 'os';
17
+ @Input() tenant: string;
18
+ @Input() telemetryKey: string;
19
+ @Input() redirectUrl: string;
20
+ @Input() autoFocus: true | false | 'skipFirstScreen';
21
+
22
+ @Input() debug: boolean;
23
+ @Input() errorTransformer: (error: { text: string; type: string }) => string;
24
+ @Input() logger: ILogger;
25
+
26
+ @Output() success: EventEmitter<void> = new EventEmitter<void>();
27
+ @Output() error: EventEmitter<void> = new EventEmitter<void>();
28
+
29
+ constructor(descopeConfig: DescopeAuthConfig) {
30
+ this.projectId = descopeConfig.projectId;
31
+ }
32
+ }
@@ -0,0 +1,15 @@
1
+ <descope
2
+ (success)="success.emit()"
3
+ (error)="error.emit()"
4
+ flowId="sign-up"
5
+ [locale]="locale"
6
+ [theme]="theme"
7
+ [tenant]="tenant"
8
+ [telemetryKey]="telemetryKey"
9
+ [redirectUrl]="redirectUrl"
10
+ [autoFocus]="autoFocus"
11
+ [debug]="debug"
12
+ [errorTransformer]="errorTransformer"
13
+ [logger]="logger"
14
+ >
15
+ </descope>
@@ -0,0 +1,51 @@
1
+ import { ComponentFixture, TestBed } from '@angular/core/testing';
2
+ import { SignUpFlowComponent } from './sign-up-flow.component';
3
+ import { DescopeComponent } from '../descope/descope.component';
4
+ import { ngMocks } from 'ng-mocks';
5
+ import createSdk from '@descope/web-js-sdk';
6
+ import { DescopeAuthConfig } from '../../types/types';
7
+ import mocked = jest.mocked;
8
+
9
+ jest.mock('@descope/web-js-sdk');
10
+ jest.mock('@descope/web-component', () => {
11
+ return jest.fn(() => {
12
+ // Create a mock DOM element
13
+ return document.createElement('descope-wc');
14
+ });
15
+ });
16
+ describe('SignUpFlowComponent', () => {
17
+ let component: SignUpFlowComponent;
18
+ let fixture: ComponentFixture<SignUpFlowComponent>;
19
+ let mockedCreateSdk: jest.Mock;
20
+
21
+ beforeEach(() => {
22
+ mockedCreateSdk = mocked(createSdk);
23
+
24
+ mockedCreateSdk.mockReturnValue({
25
+ onSessionTokenChange: jest.fn(),
26
+ onUserChange: jest.fn()
27
+ });
28
+
29
+ TestBed.configureTestingModule({
30
+ providers: [
31
+ DescopeAuthConfig,
32
+ {
33
+ provide: DescopeAuthConfig,
34
+ useValue: {
35
+ projectId: 'someProject'
36
+ }
37
+ }
38
+ ]
39
+ });
40
+ fixture = TestBed.createComponent(SignUpFlowComponent);
41
+ component = fixture.componentInstance;
42
+ fixture.detectChanges();
43
+ });
44
+
45
+ it('should create and be correctly configured', () => {
46
+ expect(component).toBeTruthy();
47
+ const mockComponent =
48
+ ngMocks.find<DescopeComponent>('[flowId=sign-up]').componentInstance;
49
+ expect(mockComponent.flowId).toStrictEqual('sign-up');
50
+ });
51
+ });
@@ -0,0 +1,32 @@
1
+ import { Component, EventEmitter, Input, Output } from '@angular/core';
2
+ import { ILogger } from '@descope/web-component';
3
+ import { DescopeComponent } from '../descope/descope.component';
4
+ import { DescopeAuthConfig } from '../../types/types';
5
+
6
+ @Component({
7
+ selector: 'descope-sign-up-flow',
8
+ standalone: true,
9
+ imports: [DescopeComponent],
10
+ templateUrl: './sign-up-flow.component.html'
11
+ })
12
+ export class SignUpFlowComponent {
13
+ projectId: string;
14
+
15
+ @Input() locale: string;
16
+ @Input() theme: 'light' | 'dark' | 'os';
17
+ @Input() tenant: string;
18
+ @Input() telemetryKey: string;
19
+ @Input() redirectUrl: string;
20
+ @Input() autoFocus: true | false | 'skipFirstScreen';
21
+
22
+ @Input() debug: boolean;
23
+ @Input() errorTransformer: (error: { text: string; type: string }) => string;
24
+ @Input() logger: ILogger;
25
+
26
+ @Output() success: EventEmitter<void> = new EventEmitter<void>();
27
+ @Output() error: EventEmitter<void> = new EventEmitter<void>();
28
+
29
+ constructor(descopeConfig: DescopeAuthConfig) {
30
+ this.projectId = descopeConfig.projectId;
31
+ }
32
+ }
@@ -0,0 +1,15 @@
1
+ <descope
2
+ (success)="success.emit()"
3
+ (error)="error.emit()"
4
+ flowId="sign-up-or-in"
5
+ [locale]="locale"
6
+ [theme]="theme"
7
+ [tenant]="tenant"
8
+ [telemetryKey]="telemetryKey"
9
+ [redirectUrl]="redirectUrl"
10
+ [autoFocus]="autoFocus"
11
+ [debug]="debug"
12
+ [errorTransformer]="errorTransformer"
13
+ [logger]="logger"
14
+ >
15
+ </descope>
@@ -0,0 +1,53 @@
1
+ import { ComponentFixture, TestBed } from '@angular/core/testing';
2
+ import { SignUpOrInFlowComponent } from './sign-up-or-in-flow.component';
3
+ import { DescopeComponent } from '../descope/descope.component';
4
+ import { ngMocks } from 'ng-mocks';
5
+ import createSdk from '@descope/web-js-sdk';
6
+ import { DescopeAuthConfig } from '../../types/types';
7
+ import mocked = jest.mocked;
8
+
9
+ jest.mock('@descope/web-js-sdk');
10
+ jest.mock('@descope/web-component', () => {
11
+ return jest.fn(() => {
12
+ // Create a mock DOM element
13
+ return document.createElement('descope-wc');
14
+ });
15
+ });
16
+ describe('SignUpOrInFlowComponent', () => {
17
+ let component: SignUpOrInFlowComponent;
18
+ let fixture: ComponentFixture<SignUpOrInFlowComponent>;
19
+ let mockedCreateSdk: jest.Mock;
20
+
21
+ beforeEach(() => {
22
+ mockedCreateSdk = mocked(createSdk);
23
+
24
+ mockedCreateSdk.mockReturnValue({
25
+ onSessionTokenChange: jest.fn(),
26
+ onUserChange: jest.fn()
27
+ });
28
+
29
+ TestBed.configureTestingModule({
30
+ providers: [
31
+ DescopeAuthConfig,
32
+ {
33
+ provide: DescopeAuthConfig,
34
+ useValue: {
35
+ projectId: 'someProject'
36
+ }
37
+ }
38
+ ]
39
+ });
40
+
41
+ fixture = TestBed.createComponent(SignUpOrInFlowComponent);
42
+ component = fixture.componentInstance;
43
+ fixture.detectChanges();
44
+ });
45
+
46
+ it('should create and be correctly configured', () => {
47
+ expect(component).toBeTruthy();
48
+ const mockComponent = ngMocks.find<DescopeComponent>(
49
+ '[flowId=sign-up-or-in]'
50
+ ).componentInstance;
51
+ expect(mockComponent.flowId).toStrictEqual('sign-up-or-in');
52
+ });
53
+ });
@@ -0,0 +1,32 @@
1
+ import { Component, EventEmitter, Input, Output } from '@angular/core';
2
+ import { ILogger } from '@descope/web-component';
3
+ import { DescopeComponent } from '../descope/descope.component';
4
+ import { DescopeAuthConfig } from '../../types/types';
5
+
6
+ @Component({
7
+ selector: 'descope-sign-up-or-in-flow',
8
+ standalone: true,
9
+ imports: [DescopeComponent],
10
+ templateUrl: './sign-up-or-in-flow.component.html'
11
+ })
12
+ export class SignUpOrInFlowComponent {
13
+ projectId: string;
14
+
15
+ @Input() locale: string;
16
+ @Input() theme: 'light' | 'dark' | 'os';
17
+ @Input() tenant: string;
18
+ @Input() telemetryKey: string;
19
+ @Input() redirectUrl: string;
20
+ @Input() autoFocus: true | false | 'skipFirstScreen';
21
+
22
+ @Input() debug: boolean;
23
+ @Input() errorTransformer: (error: { text: string; type: string }) => string;
24
+ @Input() logger: ILogger;
25
+
26
+ @Output() success: EventEmitter<void> = new EventEmitter<void>();
27
+ @Output() error: EventEmitter<void> = new EventEmitter<void>();
28
+
29
+ constructor(descopeConfig: DescopeAuthConfig) {
30
+ this.projectId = descopeConfig.projectId;
31
+ }
32
+ }
@@ -0,0 +1,46 @@
1
+ import {
2
+ CUSTOM_ELEMENTS_SCHEMA,
3
+ ModuleWithProviders,
4
+ NgModule,
5
+ Optional,
6
+ SkipSelf
7
+ } from '@angular/core';
8
+ import { DescopeComponent } from './components/descope/descope.component';
9
+ import { SignInFlowComponent } from './components/sign-in-flow/sign-in-flow.component';
10
+ import { SignUpFlowComponent } from './components/sign-up-flow/sign-up-flow.component';
11
+ import { SignUpOrInFlowComponent } from './components/sign-up-or-in-flow/sign-up-or-in-flow.component';
12
+ import { DescopeAuthConfig } from './types/types';
13
+
14
+ @NgModule({
15
+ schemas: [CUSTOM_ELEMENTS_SCHEMA],
16
+ imports: [
17
+ DescopeComponent,
18
+ SignInFlowComponent,
19
+ SignUpFlowComponent,
20
+ SignUpOrInFlowComponent
21
+ ],
22
+ exports: [
23
+ DescopeComponent,
24
+ SignInFlowComponent,
25
+ SignUpFlowComponent,
26
+ SignUpOrInFlowComponent
27
+ ]
28
+ })
29
+ export class DescopeAuthModule {
30
+ constructor(@Optional() @SkipSelf() parentModule?: DescopeAuthModule) {
31
+ if (parentModule) {
32
+ throw new Error(
33
+ 'DescopeAuthModule is already loaded. Import it only once'
34
+ );
35
+ }
36
+ }
37
+
38
+ static forRoot(
39
+ config?: DescopeAuthConfig
40
+ ): ModuleWithProviders<DescopeAuthModule> {
41
+ return {
42
+ ngModule: DescopeAuthModule,
43
+ providers: [{ provide: DescopeAuthConfig, useValue: config }]
44
+ };
45
+ }
46
+ }