@tracetail/angular 2.3.3

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/README.md ADDED
@@ -0,0 +1,201 @@
1
+ # @tracetail/angular
2
+
3
+ Official Angular SDK for TraceTail - Enterprise Browser Fingerprinting with over 99.5% accuracy.
4
+
5
+ ## Features
6
+
7
+ - 🎯 **Over 99.5% Accuracy** - Industry-leading browser fingerprinting
8
+ - ⚡ **<25ms Performance** - Lightning-fast fingerprint generation
9
+ - 🛡️ **Fraud Detection** - Built-in risk scoring and fraud prevention
10
+ - 🔄 **Real-time Updates** - Live visitor tracking and analytics
11
+ - 📦 **27KB Bundle** - Lightweight and optimized
12
+ - 🏗️ **Angular 14+** - Full support for modern Angular versions
13
+
14
+ ## Installation
15
+
16
+ ```bash
17
+ npm install @tracetail/angular
18
+ ```
19
+
20
+ ## Quick Start
21
+
22
+ ### 1. Import TraceTailModule
23
+
24
+ ```typescript
25
+ import { TraceTailModule } from '@tracetail/angular';
26
+
27
+ @NgModule({
28
+ imports: [
29
+ TraceTailModule.forRoot({
30
+ apiKey: 'your-api-key-here',
31
+ config: {
32
+ enhanced: true
33
+ }
34
+ })
35
+ ]
36
+ })
37
+ export class AppModule { }
38
+ ```
39
+
40
+ ### 2. Use in Components
41
+
42
+ ```typescript
43
+ import { TraceTailService } from '@tracetail/angular';
44
+
45
+ @Component({
46
+ template: `
47
+ <div *ngIf="fingerprint$ | async as fp">
48
+ Visitor: {{ fp.visitorId }}
49
+ Risk: {{ fp.riskScore }}
50
+ </div>
51
+ `
52
+ })
53
+ export class MyComponent {
54
+ fingerprint$ = this.traceTail.fingerprint$;
55
+
56
+ constructor(private traceTail: TraceTailService) {}
57
+ }
58
+ ```
59
+
60
+ ## Features
61
+
62
+ ### 🔐 Fraud Detection Guard
63
+
64
+ Protect routes from high-risk visitors:
65
+
66
+ ```typescript
67
+ const routes: Routes = [
68
+ {
69
+ path: 'checkout',
70
+ component: CheckoutComponent,
71
+ canActivate: [FraudProtectionGuard],
72
+ data: { maxRiskScore: 0.5 }
73
+ }
74
+ ];
75
+ ```
76
+
77
+ ### 🎨 Fraud Detection Directive
78
+
79
+ Apply fraud detection to any element:
80
+
81
+ ```html
82
+ <button
83
+ appFraudDetection="high"
84
+ [disableOnRisk]="true"
85
+ class="purchase-btn"
86
+ >
87
+ Complete Purchase
88
+ </button>
89
+ ```
90
+
91
+ ### 🔄 HTTP Interceptor
92
+
93
+ Automatically add visitor ID to all API requests:
94
+
95
+ ```typescript
96
+ // Automatically included when using forRoot()
97
+ // Adds X-TraceTail-Visitor-ID header to requests
98
+ ```
99
+
100
+ ### 📊 Event Tracking
101
+
102
+ Track user actions with fraud detection:
103
+
104
+ ```typescript
105
+ async onLogin(credentials: any) {
106
+ const result = await this.traceTail.trackEvent('login', {
107
+ username: credentials.username
108
+ });
109
+
110
+ if (result.fraudulent) {
111
+ // Handle fraud
112
+ }
113
+ }
114
+ ```
115
+
116
+ ## API Reference
117
+
118
+ ### TraceTailService
119
+
120
+ - `fingerprint$: Observable<Fingerprint>` - Current fingerprint data
121
+ - `loading$: Observable<boolean>` - Loading state
122
+ - `error$: Observable<Error>` - Error state
123
+ - `getFingerprint(): Promise<Fingerprint>` - Get fingerprint as promise
124
+ - `trackEvent(event, data?): Promise<TrackingResult>` - Track events
125
+ - `checkFraud(data): Promise<FraudResult>` - Check fraud risk
126
+ - `retry(): void` - Retry fingerprinting
127
+ - `refresh(): Promise<void>` - Force refresh
128
+
129
+ ### Types
130
+
131
+ ```typescript
132
+ interface Fingerprint {
133
+ visitorId: string;
134
+ confidence: number; // 0-1
135
+ riskScore: number; // 0-1
136
+ fraudulent: boolean;
137
+ signals: SignalData;
138
+ timestamp: Date;
139
+ }
140
+ ```
141
+
142
+ ## Examples
143
+
144
+ ### Authentication Protection
145
+
146
+ ```typescript
147
+ @Component({
148
+ template: `
149
+ <form (ngSubmit)="login()">
150
+ <div *ngIf="(riskScore$ | async) > 0.7" class="warning">
151
+ High risk detected - additional verification required
152
+ </div>
153
+ <!-- form fields -->
154
+ </form>
155
+ `
156
+ })
157
+ export class LoginComponent {
158
+ riskScore$ = this.traceTail.fingerprint$.pipe(
159
+ map(fp => fp?.riskScore || 0)
160
+ );
161
+
162
+ constructor(private traceTail: TraceTailService) {}
163
+
164
+ async login() {
165
+ const fp = await this.traceTail.getFingerprint();
166
+ if (fp.riskScore > 0.7) {
167
+ // Require 2FA
168
+ }
169
+ }
170
+ }
171
+ ```
172
+
173
+ ### Personalization
174
+
175
+ ```typescript
176
+ @Injectable()
177
+ export class PersonalizationService {
178
+ preferences$ = this.traceTail.fingerprint$.pipe(
179
+ switchMap(fp => fp ?
180
+ this.http.get(`/api/preferences/${fp.visitorId}`) :
181
+ of(null)
182
+ )
183
+ );
184
+
185
+ constructor(
186
+ private traceTail: TraceTailService,
187
+ private http: HttpClient
188
+ ) {}
189
+ }
190
+ ```
191
+
192
+ ## Support
193
+
194
+ - 📚 [Documentation](https://docs.tracetail.com/angular)
195
+ - 💬 [Discord Community](https://discord.gg/tracetail)
196
+ - 📧 [Email Support](mailto:support@tracetail.com)
197
+ - 🐛 [Issue Tracker](https://github.com/tracetail/tracetail/issues)
198
+
199
+ ## License
200
+
201
+ MIT - see [LICENSE](LICENSE) for details.
package/dist/README.md ADDED
@@ -0,0 +1,201 @@
1
+ # @tracetail/angular
2
+
3
+ Official Angular SDK for TraceTail - Enterprise Browser Fingerprinting with over 99.5% accuracy.
4
+
5
+ ## Features
6
+
7
+ - 🎯 **Over 99.5% Accuracy** - Industry-leading browser fingerprinting
8
+ - ⚡ **<25ms Performance** - Lightning-fast fingerprint generation
9
+ - 🛡️ **Fraud Detection** - Built-in risk scoring and fraud prevention
10
+ - 🔄 **Real-time Updates** - Live visitor tracking and analytics
11
+ - 📦 **27KB Bundle** - Lightweight and optimized
12
+ - 🏗️ **Angular 14+** - Full support for modern Angular versions
13
+
14
+ ## Installation
15
+
16
+ ```bash
17
+ npm install @tracetail/angular
18
+ ```
19
+
20
+ ## Quick Start
21
+
22
+ ### 1. Import TraceTailModule
23
+
24
+ ```typescript
25
+ import { TraceTailModule } from '@tracetail/angular';
26
+
27
+ @NgModule({
28
+ imports: [
29
+ TraceTailModule.forRoot({
30
+ apiKey: 'your-api-key-here',
31
+ config: {
32
+ enhanced: true
33
+ }
34
+ })
35
+ ]
36
+ })
37
+ export class AppModule { }
38
+ ```
39
+
40
+ ### 2. Use in Components
41
+
42
+ ```typescript
43
+ import { TraceTailService } from '@tracetail/angular';
44
+
45
+ @Component({
46
+ template: `
47
+ <div *ngIf="fingerprint$ | async as fp">
48
+ Visitor: {{ fp.visitorId }}
49
+ Risk: {{ fp.riskScore }}
50
+ </div>
51
+ `
52
+ })
53
+ export class MyComponent {
54
+ fingerprint$ = this.traceTail.fingerprint$;
55
+
56
+ constructor(private traceTail: TraceTailService) {}
57
+ }
58
+ ```
59
+
60
+ ## Features
61
+
62
+ ### 🔐 Fraud Detection Guard
63
+
64
+ Protect routes from high-risk visitors:
65
+
66
+ ```typescript
67
+ const routes: Routes = [
68
+ {
69
+ path: 'checkout',
70
+ component: CheckoutComponent,
71
+ canActivate: [FraudProtectionGuard],
72
+ data: { maxRiskScore: 0.5 }
73
+ }
74
+ ];
75
+ ```
76
+
77
+ ### 🎨 Fraud Detection Directive
78
+
79
+ Apply fraud detection to any element:
80
+
81
+ ```html
82
+ <button
83
+ appFraudDetection="high"
84
+ [disableOnRisk]="true"
85
+ class="purchase-btn"
86
+ >
87
+ Complete Purchase
88
+ </button>
89
+ ```
90
+
91
+ ### 🔄 HTTP Interceptor
92
+
93
+ Automatically add visitor ID to all API requests:
94
+
95
+ ```typescript
96
+ // Automatically included when using forRoot()
97
+ // Adds X-TraceTail-Visitor-ID header to requests
98
+ ```
99
+
100
+ ### 📊 Event Tracking
101
+
102
+ Track user actions with fraud detection:
103
+
104
+ ```typescript
105
+ async onLogin(credentials: any) {
106
+ const result = await this.traceTail.trackEvent('login', {
107
+ username: credentials.username
108
+ });
109
+
110
+ if (result.fraudulent) {
111
+ // Handle fraud
112
+ }
113
+ }
114
+ ```
115
+
116
+ ## API Reference
117
+
118
+ ### TraceTailService
119
+
120
+ - `fingerprint$: Observable<Fingerprint>` - Current fingerprint data
121
+ - `loading$: Observable<boolean>` - Loading state
122
+ - `error$: Observable<Error>` - Error state
123
+ - `getFingerprint(): Promise<Fingerprint>` - Get fingerprint as promise
124
+ - `trackEvent(event, data?): Promise<TrackingResult>` - Track events
125
+ - `checkFraud(data): Promise<FraudResult>` - Check fraud risk
126
+ - `retry(): void` - Retry fingerprinting
127
+ - `refresh(): Promise<void>` - Force refresh
128
+
129
+ ### Types
130
+
131
+ ```typescript
132
+ interface Fingerprint {
133
+ visitorId: string;
134
+ confidence: number; // 0-1
135
+ riskScore: number; // 0-1
136
+ fraudulent: boolean;
137
+ signals: SignalData;
138
+ timestamp: Date;
139
+ }
140
+ ```
141
+
142
+ ## Examples
143
+
144
+ ### Authentication Protection
145
+
146
+ ```typescript
147
+ @Component({
148
+ template: `
149
+ <form (ngSubmit)="login()">
150
+ <div *ngIf="(riskScore$ | async) > 0.7" class="warning">
151
+ High risk detected - additional verification required
152
+ </div>
153
+ <!-- form fields -->
154
+ </form>
155
+ `
156
+ })
157
+ export class LoginComponent {
158
+ riskScore$ = this.traceTail.fingerprint$.pipe(
159
+ map(fp => fp?.riskScore || 0)
160
+ );
161
+
162
+ constructor(private traceTail: TraceTailService) {}
163
+
164
+ async login() {
165
+ const fp = await this.traceTail.getFingerprint();
166
+ if (fp.riskScore > 0.7) {
167
+ // Require 2FA
168
+ }
169
+ }
170
+ }
171
+ ```
172
+
173
+ ### Personalization
174
+
175
+ ```typescript
176
+ @Injectable()
177
+ export class PersonalizationService {
178
+ preferences$ = this.traceTail.fingerprint$.pipe(
179
+ switchMap(fp => fp ?
180
+ this.http.get(`/api/preferences/${fp.visitorId}`) :
181
+ of(null)
182
+ )
183
+ );
184
+
185
+ constructor(
186
+ private traceTail: TraceTailService,
187
+ private http: HttpClient
188
+ ) {}
189
+ }
190
+ ```
191
+
192
+ ## Support
193
+
194
+ - 📚 [Documentation](https://docs.tracetail.com/angular)
195
+ - 💬 [Discord Community](https://discord.gg/tracetail)
196
+ - 📧 [Email Support](mailto:support@tracetail.com)
197
+ - 🐛 [Issue Tracker](https://github.com/tracetail/tracetail/issues)
198
+
199
+ ## License
200
+
201
+ MIT - see [LICENSE](LICENSE) for details.
@@ -0,0 +1,77 @@
1
+ import { Directive, Input } from '@angular/core';
2
+ import * as i0 from "@angular/core";
3
+ import * as i1 from "../tracetail.service";
4
+ export class FraudDetectionDirective {
5
+ el;
6
+ traceTail;
7
+ appFraudDetection = 'medium';
8
+ disableOnRisk = true;
9
+ cssClass = 'high-risk';
10
+ subscription = null;
11
+ constructor(el, traceTail) {
12
+ this.el = el;
13
+ this.traceTail = traceTail;
14
+ }
15
+ ngOnInit() {
16
+ this.subscription = this.traceTail.fingerprint$.subscribe(fingerprint => {
17
+ if (!fingerprint)
18
+ return;
19
+ const thresholds = {
20
+ low: 0.3,
21
+ medium: 0.5,
22
+ high: 0.7
23
+ };
24
+ const threshold = thresholds[this.appFraudDetection];
25
+ const isHighRisk = fingerprint.riskScore > threshold;
26
+ // Apply or remove CSS class
27
+ if (isHighRisk) {
28
+ this.el.nativeElement.classList.add(this.cssClass);
29
+ // Optionally disable the element
30
+ if (this.disableOnRisk && this.isFormElement()) {
31
+ this.el.nativeElement.setAttribute('disabled', 'true');
32
+ this.el.nativeElement.setAttribute('title', 'High fraud risk detected');
33
+ }
34
+ }
35
+ else {
36
+ this.el.nativeElement.classList.remove(this.cssClass);
37
+ if (this.disableOnRisk && this.isFormElement()) {
38
+ this.el.nativeElement.removeAttribute('disabled');
39
+ this.el.nativeElement.removeAttribute('title');
40
+ }
41
+ }
42
+ // Emit custom event
43
+ this.el.nativeElement.dispatchEvent(new CustomEvent('fraudStatusChange', {
44
+ detail: {
45
+ isHighRisk,
46
+ riskScore: fingerprint.riskScore,
47
+ threshold
48
+ },
49
+ bubbles: true
50
+ }));
51
+ });
52
+ }
53
+ ngOnDestroy() {
54
+ if (this.subscription) {
55
+ this.subscription.unsubscribe();
56
+ }
57
+ }
58
+ isFormElement() {
59
+ const tagName = this.el.nativeElement.tagName.toLowerCase();
60
+ return ['input', 'button', 'select', 'textarea', 'form'].includes(tagName);
61
+ }
62
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: FraudDetectionDirective, deps: [{ token: i0.ElementRef }, { token: i1.TraceTailService }], target: i0.ɵɵFactoryTarget.Directive });
63
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.3.12", type: FraudDetectionDirective, selector: "[appFraudDetection]", inputs: { appFraudDetection: "appFraudDetection", disableOnRisk: "disableOnRisk", cssClass: "cssClass" }, ngImport: i0 });
64
+ }
65
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: FraudDetectionDirective, decorators: [{
66
+ type: Directive,
67
+ args: [{
68
+ selector: '[appFraudDetection]'
69
+ }]
70
+ }], ctorParameters: () => [{ type: i0.ElementRef }, { type: i1.TraceTailService }], propDecorators: { appFraudDetection: [{
71
+ type: Input
72
+ }], disableOnRisk: [{
73
+ type: Input
74
+ }], cssClass: [{
75
+ type: Input
76
+ }] } });
77
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZnJhdWQtZGV0ZWN0aW9uLmRpcmVjdGl2ZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9saWIvZGlyZWN0aXZlcy9mcmF1ZC1kZXRlY3Rpb24uZGlyZWN0aXZlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFDTCxTQUFTLEVBQ1QsS0FBSyxFQUlOLE1BQU0sZUFBZSxDQUFDOzs7QUFPdkIsTUFBTSxPQUFPLHVCQUF1QjtJQVF4QjtJQUNBO0lBUkQsaUJBQWlCLEdBQThCLFFBQVEsQ0FBQztJQUN4RCxhQUFhLEdBQUcsSUFBSSxDQUFDO0lBQ3JCLFFBQVEsR0FBRyxXQUFXLENBQUM7SUFFeEIsWUFBWSxHQUF3QixJQUFJLENBQUM7SUFFakQsWUFDVSxFQUEyQixFQUMzQixTQUEyQjtRQUQzQixPQUFFLEdBQUYsRUFBRSxDQUF5QjtRQUMzQixjQUFTLEdBQVQsU0FBUyxDQUFrQjtJQUNsQyxDQUFDO0lBRUosUUFBUTtRQUNOLElBQUksQ0FBQyxZQUFZLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxZQUFZLENBQUMsU0FBUyxDQUFDLFdBQVcsQ0FBQyxFQUFFO1lBQ3RFLElBQUksQ0FBQyxXQUFXO2dCQUFFLE9BQU87WUFFekIsTUFBTSxVQUFVLEdBQUc7Z0JBQ2pCLEdBQUcsRUFBRSxHQUFHO2dCQUNSLE1BQU0sRUFBRSxHQUFHO2dCQUNYLElBQUksRUFBRSxHQUFHO2FBQ1YsQ0FBQztZQUVGLE1BQU0sU0FBUyxHQUFHLFVBQVUsQ0FBQyxJQUFJLENBQUMsaUJBQWlCLENBQUMsQ0FBQztZQUNyRCxNQUFNLFVBQVUsR0FBRyxXQUFXLENBQUMsU0FBUyxHQUFHLFNBQVMsQ0FBQztZQUVyRCw0QkFBNEI7WUFDNUIsSUFBSSxVQUFVLEVBQUU7Z0JBQ2QsSUFBSSxDQUFDLEVBQUUsQ0FBQyxhQUFhLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUM7Z0JBRW5ELGlDQUFpQztnQkFDakMsSUFBSSxJQUFJLENBQUMsYUFBYSxJQUFJLElBQUksQ0FBQyxhQUFhLEVBQUUsRUFBRTtvQkFDOUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxhQUFhLENBQUMsWUFBWSxDQUFDLFVBQVUsRUFBRSxNQUFNLENBQUMsQ0FBQztvQkFDdkQsSUFBSSxDQUFDLEVBQUUsQ0FBQyxhQUFhLENBQUMsWUFBWSxDQUFDLE9BQU8sRUFBRSwwQkFBMEIsQ0FBQyxDQUFDO2lCQUN6RTthQUNGO2lCQUFNO2dCQUNMLElBQUksQ0FBQyxFQUFFLENBQUMsYUFBYSxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDO2dCQUV0RCxJQUFJLElBQUksQ0FBQyxhQUFhLElBQUksSUFBSSxDQUFDLGFBQWEsRUFBRSxFQUFFO29CQUM5QyxJQUFJLENBQUMsRUFBRSxDQUFDLGFBQWEsQ0FBQyxlQUFlLENBQUMsVUFBVSxDQUFDLENBQUM7b0JBQ2xELElBQUksQ0FBQyxFQUFFLENBQUMsYUFBYSxDQUFDLGVBQWUsQ0FBQyxPQUFPLENBQUMsQ0FBQztpQkFDaEQ7YUFDRjtZQUVELG9CQUFvQjtZQUNwQixJQUFJLENBQUMsRUFBRSxDQUFDLGFBQWEsQ0FBQyxhQUFhLENBQUMsSUFBSSxXQUFXLENBQUMsbUJBQW1CLEVBQUU7Z0JBQ3ZFLE1BQU0sRUFBRTtvQkFDTixVQUFVO29CQUNWLFNBQVMsRUFBRSxXQUFXLENBQUMsU0FBUztvQkFDaEMsU0FBUztpQkFDVjtnQkFDRCxPQUFPLEVBQUUsSUFBSTthQUNkLENBQUMsQ0FBQyxDQUFDO1FBQ04sQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDO0lBRUQsV0FBVztRQUNULElBQUksSUFBSSxDQUFDLFlBQVksRUFBRTtZQUNyQixJQUFJLENBQUMsWUFBWSxDQUFDLFdBQVcsRUFBRSxDQUFDO1NBQ2pDO0lBQ0gsQ0FBQztJQUVPLGFBQWE7UUFDbkIsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLEVBQUUsQ0FBQyxhQUFhLENBQUMsT0FBTyxDQUFDLFdBQVcsRUFBRSxDQUFDO1FBQzVELE9BQU8sQ0FBQyxPQUFPLEVBQUUsUUFBUSxFQUFFLFFBQVEsRUFBRSxVQUFVLEVBQUUsTUFBTSxDQUFDLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQzdFLENBQUM7d0dBaEVVLHVCQUF1Qjs0RkFBdkIsdUJBQXVCOzs0RkFBdkIsdUJBQXVCO2tCQUhuQyxTQUFTO21CQUFDO29CQUNULFFBQVEsRUFBRSxxQkFBcUI7aUJBQ2hDOzhHQUVVLGlCQUFpQjtzQkFBekIsS0FBSztnQkFDRyxhQUFhO3NCQUFyQixLQUFLO2dCQUNHLFFBQVE7c0JBQWhCLEtBQUsiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBcbiAgRGlyZWN0aXZlLCBcbiAgSW5wdXQsIFxuICBFbGVtZW50UmVmLCBcbiAgT25Jbml0LCBcbiAgT25EZXN0cm95IFxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IFN1YnNjcmlwdGlvbiB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgVHJhY2VUYWlsU2VydmljZSB9IGZyb20gJy4uL3RyYWNldGFpbC5zZXJ2aWNlJztcblxuQERpcmVjdGl2ZSh7XG4gIHNlbGVjdG9yOiAnW2FwcEZyYXVkRGV0ZWN0aW9uXSdcbn0pXG5leHBvcnQgY2xhc3MgRnJhdWREZXRlY3Rpb25EaXJlY3RpdmUgaW1wbGVtZW50cyBPbkluaXQsIE9uRGVzdHJveSB7XG4gIEBJbnB1dCgpIGFwcEZyYXVkRGV0ZWN0aW9uOiAnbG93JyB8ICdtZWRpdW0nIHwgJ2hpZ2gnID0gJ21lZGl1bSc7XG4gIEBJbnB1dCgpIGRpc2FibGVPblJpc2sgPSB0cnVlO1xuICBASW5wdXQoKSBjc3NDbGFzcyA9ICdoaWdoLXJpc2snO1xuXG4gIHByaXZhdGUgc3Vic2NyaXB0aW9uOiBTdWJzY3JpcHRpb24gfCBudWxsID0gbnVsbDtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIGVsOiBFbGVtZW50UmVmPEhUTUxFbGVtZW50PixcbiAgICBwcml2YXRlIHRyYWNlVGFpbDogVHJhY2VUYWlsU2VydmljZVxuICApIHt9XG5cbiAgbmdPbkluaXQoKTogdm9pZCB7XG4gICAgdGhpcy5zdWJzY3JpcHRpb24gPSB0aGlzLnRyYWNlVGFpbC5maW5nZXJwcmludCQuc3Vic2NyaWJlKGZpbmdlcnByaW50ID0+IHtcbiAgICAgIGlmICghZmluZ2VycHJpbnQpIHJldHVybjtcblxuICAgICAgY29uc3QgdGhyZXNob2xkcyA9IHtcbiAgICAgICAgbG93OiAwLjMsXG4gICAgICAgIG1lZGl1bTogMC41LFxuICAgICAgICBoaWdoOiAwLjdcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHRocmVzaG9sZCA9IHRocmVzaG9sZHNbdGhpcy5hcHBGcmF1ZERldGVjdGlvbl07XG4gICAgICBjb25zdCBpc0hpZ2hSaXNrID0gZmluZ2VycHJpbnQucmlza1Njb3JlID4gdGhyZXNob2xkO1xuXG4gICAgICAvLyBBcHBseSBvciByZW1vdmUgQ1NTIGNsYXNzXG4gICAgICBpZiAoaXNIaWdoUmlzaykge1xuICAgICAgICB0aGlzLmVsLm5hdGl2ZUVsZW1lbnQuY2xhc3NMaXN0LmFkZCh0aGlzLmNzc0NsYXNzKTtcbiAgICAgICAgXG4gICAgICAgIC8vIE9wdGlvbmFsbHkgZGlzYWJsZSB0aGUgZWxlbWVudFxuICAgICAgICBpZiAodGhpcy5kaXNhYmxlT25SaXNrICYmIHRoaXMuaXNGb3JtRWxlbWVudCgpKSB7XG4gICAgICAgICAgdGhpcy5lbC5uYXRpdmVFbGVtZW50LnNldEF0dHJpYnV0ZSgnZGlzYWJsZWQnLCAndHJ1ZScpO1xuICAgICAgICAgIHRoaXMuZWwubmF0aXZlRWxlbWVudC5zZXRBdHRyaWJ1dGUoJ3RpdGxlJywgJ0hpZ2ggZnJhdWQgcmlzayBkZXRlY3RlZCcpO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLmVsLm5hdGl2ZUVsZW1lbnQuY2xhc3NMaXN0LnJlbW92ZSh0aGlzLmNzc0NsYXNzKTtcbiAgICAgICAgXG4gICAgICAgIGlmICh0aGlzLmRpc2FibGVPblJpc2sgJiYgdGhpcy5pc0Zvcm1FbGVtZW50KCkpIHtcbiAgICAgICAgICB0aGlzLmVsLm5hdGl2ZUVsZW1lbnQucmVtb3ZlQXR0cmlidXRlKCdkaXNhYmxlZCcpO1xuICAgICAgICAgIHRoaXMuZWwubmF0aXZlRWxlbWVudC5yZW1vdmVBdHRyaWJ1dGUoJ3RpdGxlJyk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgLy8gRW1pdCBjdXN0b20gZXZlbnRcbiAgICAgIHRoaXMuZWwubmF0aXZlRWxlbWVudC5kaXNwYXRjaEV2ZW50KG5ldyBDdXN0b21FdmVudCgnZnJhdWRTdGF0dXNDaGFuZ2UnLCB7XG4gICAgICAgIGRldGFpbDoge1xuICAgICAgICAgIGlzSGlnaFJpc2ssXG4gICAgICAgICAgcmlza1Njb3JlOiBmaW5nZXJwcmludC5yaXNrU2NvcmUsXG4gICAgICAgICAgdGhyZXNob2xkXG4gICAgICAgIH0sXG4gICAgICAgIGJ1YmJsZXM6IHRydWVcbiAgICAgIH0pKTtcbiAgICB9KTtcbiAgfVxuXG4gIG5nT25EZXN0cm95KCk6IHZvaWQge1xuICAgIGlmICh0aGlzLnN1YnNjcmlwdGlvbikge1xuICAgICAgdGhpcy5zdWJzY3JpcHRpb24udW5zdWJzY3JpYmUoKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGlzRm9ybUVsZW1lbnQoKTogYm9vbGVhbiB7XG4gICAgY29uc3QgdGFnTmFtZSA9IHRoaXMuZWwubmF0aXZlRWxlbWVudC50YWdOYW1lLnRvTG93ZXJDYXNlKCk7XG4gICAgcmV0dXJuIFsnaW5wdXQnLCAnYnV0dG9uJywgJ3NlbGVjdCcsICd0ZXh0YXJlYScsICdmb3JtJ10uaW5jbHVkZXModGFnTmFtZSk7XG4gIH1cbn0iXX0=
@@ -0,0 +1,51 @@
1
+ import { Injectable } from '@angular/core';
2
+ import { map, take } from 'rxjs/operators';
3
+ import * as i0 from "@angular/core";
4
+ import * as i1 from "../tracetail.service";
5
+ import * as i2 from "@angular/router";
6
+ export class FraudProtectionGuard {
7
+ traceTail;
8
+ router;
9
+ constructor(traceTail, router) {
10
+ this.traceTail = traceTail;
11
+ this.router = router;
12
+ }
13
+ canActivate(route, state) {
14
+ // Get risk threshold from route data or use default
15
+ const maxRiskScore = route.data['maxRiskScore'] ?? 0.7;
16
+ const verificationUrl = route.data['verificationUrl'] ?? '/verify';
17
+ return this.traceTail.fingerprint$.pipe(take(1), map(fingerprint => {
18
+ if (!fingerprint) {
19
+ // No fingerprint yet, allow but monitor
20
+ console.warn('No fingerprint available for fraud check');
21
+ return true;
22
+ }
23
+ // Check if user is fraudulent or high risk
24
+ if (fingerprint.fraudulent || fingerprint.riskScore > maxRiskScore) {
25
+ console.warn('High risk user blocked:', {
26
+ visitorId: fingerprint.visitorId,
27
+ riskScore: fingerprint.riskScore,
28
+ fraudulent: fingerprint.fraudulent
29
+ });
30
+ // Redirect to verification page
31
+ return this.router.createUrlTree([verificationUrl], {
32
+ queryParams: {
33
+ reason: fingerprint.fraudulent ? 'fraud' : 'risk',
34
+ returnUrl: state.url
35
+ }
36
+ });
37
+ }
38
+ // User is safe, allow access
39
+ return true;
40
+ }));
41
+ }
42
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: FraudProtectionGuard, deps: [{ token: i1.TraceTailService }, { token: i2.Router }], target: i0.ɵɵFactoryTarget.Injectable });
43
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: FraudProtectionGuard, providedIn: 'root' });
44
+ }
45
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: FraudProtectionGuard, decorators: [{
46
+ type: Injectable,
47
+ args: [{
48
+ providedIn: 'root'
49
+ }]
50
+ }], ctorParameters: () => [{ type: i1.TraceTailService }, { type: i2.Router }] });
51
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZnJhdWQtcHJvdGVjdGlvbi5ndWFyZC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9saWIvZ3VhcmRzL2ZyYXVkLXByb3RlY3Rpb24uZ3VhcmQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQVMzQyxPQUFPLEVBQUUsR0FBRyxFQUFFLElBQUksRUFBRSxNQUFNLGdCQUFnQixDQUFDOzs7O0FBTTNDLE1BQU0sT0FBTyxvQkFBb0I7SUFFckI7SUFDQTtJQUZWLFlBQ1UsU0FBMkIsRUFDM0IsTUFBYztRQURkLGNBQVMsR0FBVCxTQUFTLENBQWtCO1FBQzNCLFdBQU0sR0FBTixNQUFNLENBQVE7SUFDckIsQ0FBQztJQUVKLFdBQVcsQ0FDVCxLQUE2QixFQUM3QixLQUEwQjtRQUUxQixvREFBb0Q7UUFDcEQsTUFBTSxZQUFZLEdBQUcsS0FBSyxDQUFDLElBQUksQ0FBQyxjQUFjLENBQUMsSUFBSSxHQUFHLENBQUM7UUFDdkQsTUFBTSxlQUFlLEdBQUcsS0FBSyxDQUFDLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxJQUFJLFNBQVMsQ0FBQztRQUVuRSxPQUFPLElBQUksQ0FBQyxTQUFTLENBQUMsWUFBWSxDQUFDLElBQUksQ0FDckMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUNQLEdBQUcsQ0FBQyxXQUFXLENBQUMsRUFBRTtZQUNoQixJQUFJLENBQUMsV0FBVyxFQUFFO2dCQUNoQix3Q0FBd0M7Z0JBQ3hDLE9BQU8sQ0FBQyxJQUFJLENBQUMsMENBQTBDLENBQUMsQ0FBQztnQkFDekQsT0FBTyxJQUFJLENBQUM7YUFDYjtZQUVELDJDQUEyQztZQUMzQyxJQUFJLFdBQVcsQ0FBQyxVQUFVLElBQUksV0FBVyxDQUFDLFNBQVMsR0FBRyxZQUFZLEVBQUU7Z0JBQ2xFLE9BQU8sQ0FBQyxJQUFJLENBQUMseUJBQXlCLEVBQUU7b0JBQ3RDLFNBQVMsRUFBRSxXQUFXLENBQUMsU0FBUztvQkFDaEMsU0FBUyxFQUFFLFdBQVcsQ0FBQyxTQUFTO29CQUNoQyxVQUFVLEVBQUUsV0FBVyxDQUFDLFVBQVU7aUJBQ25DLENBQUMsQ0FBQztnQkFFSCxnQ0FBZ0M7Z0JBQ2hDLE9BQU8sSUFBSSxDQUFDLE1BQU0sQ0FBQyxhQUFhLENBQUMsQ0FBQyxlQUFlLENBQUMsRUFBRTtvQkFDbEQsV0FBVyxFQUFFO3dCQUNYLE1BQU0sRUFBRSxXQUFXLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLE1BQU07d0JBQ2pELFNBQVMsRUFBRSxLQUFLLENBQUMsR0FBRztxQkFDckI7aUJBQ0YsQ0FBQyxDQUFDO2FBQ0o7WUFFRCw2QkFBNkI7WUFDN0IsT0FBTyxJQUFJLENBQUM7UUFDZCxDQUFDLENBQUMsQ0FDSCxDQUFDO0lBQ0osQ0FBQzt3R0E1Q1Usb0JBQW9COzRHQUFwQixvQkFBb0IsY0FGbkIsTUFBTTs7NEZBRVAsb0JBQW9CO2tCQUhoQyxVQUFVO21CQUFDO29CQUNWLFVBQVUsRUFBRSxNQUFNO2lCQUNuQiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEluamVjdGFibGUgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7XG4gIENhbkFjdGl2YXRlLFxuICBBY3RpdmF0ZWRSb3V0ZVNuYXBzaG90LFxuICBSb3V0ZXJTdGF0ZVNuYXBzaG90LFxuICBSb3V0ZXIsXG4gIFVybFRyZWVcbn0gZnJvbSAnQGFuZ3VsYXIvcm91dGVyJztcbmltcG9ydCB7IE9ic2VydmFibGUgfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IG1hcCwgdGFrZSB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcbmltcG9ydCB7IFRyYWNlVGFpbFNlcnZpY2UgfSBmcm9tICcuLi90cmFjZXRhaWwuc2VydmljZSc7XG5cbkBJbmplY3RhYmxlKHtcbiAgcHJvdmlkZWRJbjogJ3Jvb3QnXG59KVxuZXhwb3J0IGNsYXNzIEZyYXVkUHJvdGVjdGlvbkd1YXJkIGltcGxlbWVudHMgQ2FuQWN0aXZhdGUge1xuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIHRyYWNlVGFpbDogVHJhY2VUYWlsU2VydmljZSxcbiAgICBwcml2YXRlIHJvdXRlcjogUm91dGVyXG4gICkge31cblxuICBjYW5BY3RpdmF0ZShcbiAgICByb3V0ZTogQWN0aXZhdGVkUm91dGVTbmFwc2hvdCxcbiAgICBzdGF0ZTogUm91dGVyU3RhdGVTbmFwc2hvdFxuICApOiBPYnNlcnZhYmxlPGJvb2xlYW4gfCBVcmxUcmVlPiB7XG4gICAgLy8gR2V0IHJpc2sgdGhyZXNob2xkIGZyb20gcm91dGUgZGF0YSBvciB1c2UgZGVmYXVsdFxuICAgIGNvbnN0IG1heFJpc2tTY29yZSA9IHJvdXRlLmRhdGFbJ21heFJpc2tTY29yZSddID8/IDAuNztcbiAgICBjb25zdCB2ZXJpZmljYXRpb25VcmwgPSByb3V0ZS5kYXRhWyd2ZXJpZmljYXRpb25VcmwnXSA/PyAnL3ZlcmlmeSc7XG5cbiAgICByZXR1cm4gdGhpcy50cmFjZVRhaWwuZmluZ2VycHJpbnQkLnBpcGUoXG4gICAgICB0YWtlKDEpLFxuICAgICAgbWFwKGZpbmdlcnByaW50ID0+IHtcbiAgICAgICAgaWYgKCFmaW5nZXJwcmludCkge1xuICAgICAgICAgIC8vIE5vIGZpbmdlcnByaW50IHlldCwgYWxsb3cgYnV0IG1vbml0b3JcbiAgICAgICAgICBjb25zb2xlLndhcm4oJ05vIGZpbmdlcnByaW50IGF2YWlsYWJsZSBmb3IgZnJhdWQgY2hlY2snKTtcbiAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIENoZWNrIGlmIHVzZXIgaXMgZnJhdWR1bGVudCBvciBoaWdoIHJpc2tcbiAgICAgICAgaWYgKGZpbmdlcnByaW50LmZyYXVkdWxlbnQgfHwgZmluZ2VycHJpbnQucmlza1Njb3JlID4gbWF4Umlza1Njb3JlKSB7XG4gICAgICAgICAgY29uc29sZS53YXJuKCdIaWdoIHJpc2sgdXNlciBibG9ja2VkOicsIHtcbiAgICAgICAgICAgIHZpc2l0b3JJZDogZmluZ2VycHJpbnQudmlzaXRvcklkLFxuICAgICAgICAgICAgcmlza1Njb3JlOiBmaW5nZXJwcmludC5yaXNrU2NvcmUsXG4gICAgICAgICAgICBmcmF1ZHVsZW50OiBmaW5nZXJwcmludC5mcmF1ZHVsZW50XG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgICAvLyBSZWRpcmVjdCB0byB2ZXJpZmljYXRpb24gcGFnZVxuICAgICAgICAgIHJldHVybiB0aGlzLnJvdXRlci5jcmVhdGVVcmxUcmVlKFt2ZXJpZmljYXRpb25VcmxdLCB7XG4gICAgICAgICAgICBxdWVyeVBhcmFtczoge1xuICAgICAgICAgICAgICByZWFzb246IGZpbmdlcnByaW50LmZyYXVkdWxlbnQgPyAnZnJhdWQnIDogJ3Jpc2snLFxuICAgICAgICAgICAgICByZXR1cm5Vcmw6IHN0YXRlLnVybFxuICAgICAgICAgICAgfVxuICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gVXNlciBpcyBzYWZlLCBhbGxvdyBhY2Nlc3NcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9KVxuICAgICk7XG4gIH1cbn0iXX0=
@@ -0,0 +1,32 @@
1
+ import { Injectable } from '@angular/core';
2
+ import { switchMap, take } from 'rxjs/operators';
3
+ import * as i0 from "@angular/core";
4
+ import * as i1 from "../tracetail.service";
5
+ export class TraceTailInterceptor {
6
+ traceTail;
7
+ constructor(traceTail) {
8
+ this.traceTail = traceTail;
9
+ }
10
+ intercept(req, next) {
11
+ // Skip TraceTail API requests to prevent circular dependency
12
+ if (req.url.includes('api.tracetail.com')) {
13
+ return next.handle(req);
14
+ }
15
+ return this.traceTail.fingerprint$.pipe(take(1), switchMap(fingerprint => {
16
+ // Clone the request and add TraceTail headers
17
+ const modifiedReq = req.clone({
18
+ headers: req.headers
19
+ .set('X-TraceTail-Visitor-ID', fingerprint?.visitorId || 'unknown')
20
+ .set('X-TraceTail-Risk-Score', fingerprint?.riskScore?.toString() || '0')
21
+ .set('X-TraceTail-Confidence', fingerprint?.confidence?.toString() || '0')
22
+ });
23
+ return next.handle(modifiedReq);
24
+ }));
25
+ }
26
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: TraceTailInterceptor, deps: [{ token: i1.TraceTailService }], target: i0.ɵɵFactoryTarget.Injectable });
27
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: TraceTailInterceptor });
28
+ }
29
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: TraceTailInterceptor, decorators: [{
30
+ type: Injectable
31
+ }], ctorParameters: () => [{ type: i1.TraceTailService }] });
32
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJhY2V0YWlsLmludGVyY2VwdG9yLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2xpYi9pbnRlcmNlcHRvcnMvdHJhY2V0YWlsLmludGVyY2VwdG9yLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFRM0MsT0FBTyxFQUFFLFNBQVMsRUFBRSxJQUFJLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQzs7O0FBSWpELE1BQU0sT0FBTyxvQkFBb0I7SUFDWDtJQUFwQixZQUFvQixTQUEyQjtRQUEzQixjQUFTLEdBQVQsU0FBUyxDQUFrQjtJQUFHLENBQUM7SUFFbkQsU0FBUyxDQUNQLEdBQXFCLEVBQ3JCLElBQWlCO1FBRWpCLDZEQUE2RDtRQUM3RCxJQUFJLEdBQUcsQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDLG1CQUFtQixDQUFDLEVBQUU7WUFDekMsT0FBTyxJQUFJLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1NBQ3pCO1FBRUQsT0FBTyxJQUFJLENBQUMsU0FBUyxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQ3JDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFDUCxTQUFTLENBQUMsV0FBVyxDQUFDLEVBQUU7WUFDdEIsOENBQThDO1lBQzlDLE1BQU0sV0FBVyxHQUFHLEdBQUcsQ0FBQyxLQUFLLENBQUM7Z0JBQzVCLE9BQU8sRUFBRSxHQUFHLENBQUMsT0FBTztxQkFDakIsR0FBRyxDQUFDLHdCQUF3QixFQUFFLFdBQVcsRUFBRSxTQUFTLElBQUksU0FBUyxDQUFDO3FCQUNsRSxHQUFHLENBQUMsd0JBQXdCLEVBQUUsV0FBVyxFQUFFLFNBQVMsRUFBRSxRQUFRLEVBQUUsSUFBSSxHQUFHLENBQUM7cUJBQ3hFLEdBQUcsQ0FBQyx3QkFBd0IsRUFBRSxXQUFXLEVBQUUsVUFBVSxFQUFFLFFBQVEsRUFBRSxJQUFJLEdBQUcsQ0FBQzthQUM3RSxDQUFDLENBQUM7WUFFSCxPQUFPLElBQUksQ0FBQyxNQUFNLENBQUMsV0FBVyxDQUFDLENBQUM7UUFDbEMsQ0FBQyxDQUFDLENBQ0gsQ0FBQztJQUNKLENBQUM7d0dBMUJVLG9CQUFvQjs0R0FBcEIsb0JBQW9COzs0RkFBcEIsb0JBQW9CO2tCQURoQyxVQUFVIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSW5qZWN0YWJsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHtcbiAgSHR0cEludGVyY2VwdG9yLFxuICBIdHRwUmVxdWVzdCxcbiAgSHR0cEhhbmRsZXIsXG4gIEh0dHBFdmVudFxufSBmcm9tICdAYW5ndWxhci9jb21tb24vaHR0cCc7XG5pbXBvcnQgeyBPYnNlcnZhYmxlIH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyBzd2l0Y2hNYXAsIHRha2UgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5pbXBvcnQgeyBUcmFjZVRhaWxTZXJ2aWNlIH0gZnJvbSAnLi4vdHJhY2V0YWlsLnNlcnZpY2UnO1xuXG5ASW5qZWN0YWJsZSgpXG5leHBvcnQgY2xhc3MgVHJhY2VUYWlsSW50ZXJjZXB0b3IgaW1wbGVtZW50cyBIdHRwSW50ZXJjZXB0b3Ige1xuICBjb25zdHJ1Y3Rvcihwcml2YXRlIHRyYWNlVGFpbDogVHJhY2VUYWlsU2VydmljZSkge31cblxuICBpbnRlcmNlcHQoXG4gICAgcmVxOiBIdHRwUmVxdWVzdDxhbnk+LCBcbiAgICBuZXh0OiBIdHRwSGFuZGxlclxuICApOiBPYnNlcnZhYmxlPEh0dHBFdmVudDxhbnk+PiB7XG4gICAgLy8gU2tpcCBUcmFjZVRhaWwgQVBJIHJlcXVlc3RzIHRvIHByZXZlbnQgY2lyY3VsYXIgZGVwZW5kZW5jeVxuICAgIGlmIChyZXEudXJsLmluY2x1ZGVzKCdhcGkudHJhY2V0YWlsLmNvbScpKSB7XG4gICAgICByZXR1cm4gbmV4dC5oYW5kbGUocmVxKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy50cmFjZVRhaWwuZmluZ2VycHJpbnQkLnBpcGUoXG4gICAgICB0YWtlKDEpLFxuICAgICAgc3dpdGNoTWFwKGZpbmdlcnByaW50ID0+IHtcbiAgICAgICAgLy8gQ2xvbmUgdGhlIHJlcXVlc3QgYW5kIGFkZCBUcmFjZVRhaWwgaGVhZGVyc1xuICAgICAgICBjb25zdCBtb2RpZmllZFJlcSA9IHJlcS5jbG9uZSh7XG4gICAgICAgICAgaGVhZGVyczogcmVxLmhlYWRlcnNcbiAgICAgICAgICAgIC5zZXQoJ1gtVHJhY2VUYWlsLVZpc2l0b3ItSUQnLCBmaW5nZXJwcmludD8udmlzaXRvcklkIHx8ICd1bmtub3duJylcbiAgICAgICAgICAgIC5zZXQoJ1gtVHJhY2VUYWlsLVJpc2stU2NvcmUnLCBmaW5nZXJwcmludD8ucmlza1Njb3JlPy50b1N0cmluZygpIHx8ICcwJylcbiAgICAgICAgICAgIC5zZXQoJ1gtVHJhY2VUYWlsLUNvbmZpZGVuY2UnLCBmaW5nZXJwcmludD8uY29uZmlkZW5jZT8udG9TdHJpbmcoKSB8fCAnMCcpXG4gICAgICAgIH0pO1xuXG4gICAgICAgIHJldHVybiBuZXh0LmhhbmRsZShtb2RpZmllZFJlcSk7XG4gICAgICB9KVxuICAgICk7XG4gIH1cbn0iXX0=
@@ -0,0 +1,11 @@
1
+ import { InjectionToken } from '@angular/core';
2
+ export const TRACETAIL_CONFIG = new InjectionToken('TRACETAIL_CONFIG');
3
+ export const DEFAULT_CONFIG = {
4
+ config: {
5
+ enhanced: true,
6
+ timeout: 5000,
7
+ endpoint: 'https://api.tracetail.com',
8
+ testMode: false
9
+ }
10
+ };
11
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJhY2V0YWlsLmNvbmZpZy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9saWIvdHJhY2V0YWlsLmNvbmZpZy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBRy9DLE1BQU0sQ0FBQyxNQUFNLGdCQUFnQixHQUFHLElBQUksY0FBYyxDQUFrQixrQkFBa0IsQ0FBQyxDQUFDO0FBRXhGLE1BQU0sQ0FBQyxNQUFNLGNBQWMsR0FBNkI7SUFDdEQsTUFBTSxFQUFFO1FBQ04sUUFBUSxFQUFFLElBQUk7UUFDZCxPQUFPLEVBQUUsSUFBSTtRQUNiLFFBQVEsRUFBRSwyQkFBMkI7UUFDckMsUUFBUSxFQUFFLEtBQUs7S0FDaEI7Q0FDRixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSW5qZWN0aW9uVG9rZW4gfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IFRyYWNlVGFpbENvbmZpZyB9IGZyb20gJy4vdHJhY2V0YWlsLnR5cGVzJztcblxuZXhwb3J0IGNvbnN0IFRSQUNFVEFJTF9DT05GSUcgPSBuZXcgSW5qZWN0aW9uVG9rZW48VHJhY2VUYWlsQ29uZmlnPignVFJBQ0VUQUlMX0NPTkZJRycpO1xuXG5leHBvcnQgY29uc3QgREVGQVVMVF9DT05GSUc6IFBhcnRpYWw8VHJhY2VUYWlsQ29uZmlnPiA9IHtcbiAgY29uZmlnOiB7XG4gICAgZW5oYW5jZWQ6IHRydWUsXG4gICAgdGltZW91dDogNTAwMCxcbiAgICBlbmRwb2ludDogJ2h0dHBzOi8vYXBpLnRyYWNldGFpbC5jb20nLFxuICAgIHRlc3RNb2RlOiBmYWxzZVxuICB9XG59OyJdfQ==
@@ -0,0 +1,56 @@
1
+ import { NgModule } from '@angular/core';
2
+ import { CommonModule } from '@angular/common';
3
+ import { HTTP_INTERCEPTORS } from '@angular/common/http';
4
+ import { TraceTailService } from './tracetail.service';
5
+ import { TRACETAIL_CONFIG, DEFAULT_CONFIG } from './tracetail.config';
6
+ import { FraudDetectionDirective } from './directives/fraud-detection.directive';
7
+ import { TraceTailInterceptor } from './interceptors/tracetail.interceptor';
8
+ import * as i0 from "@angular/core";
9
+ export class TraceTailModule {
10
+ static forRoot(config) {
11
+ return {
12
+ ngModule: TraceTailModule,
13
+ providers: [
14
+ {
15
+ provide: TRACETAIL_CONFIG,
16
+ useValue: { ...DEFAULT_CONFIG, ...config }
17
+ },
18
+ TraceTailService,
19
+ {
20
+ provide: HTTP_INTERCEPTORS,
21
+ useClass: TraceTailInterceptor,
22
+ multi: true
23
+ }
24
+ ]
25
+ };
26
+ }
27
+ static forFeature(config) {
28
+ return {
29
+ ngModule: TraceTailModule,
30
+ providers: config ? [
31
+ {
32
+ provide: TRACETAIL_CONFIG,
33
+ useValue: { ...DEFAULT_CONFIG, ...config }
34
+ }
35
+ ] : []
36
+ };
37
+ }
38
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: TraceTailModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
39
+ static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "17.3.12", ngImport: i0, type: TraceTailModule, declarations: [FraudDetectionDirective], imports: [CommonModule], exports: [FraudDetectionDirective] });
40
+ static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: TraceTailModule, imports: [CommonModule] });
41
+ }
42
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: TraceTailModule, decorators: [{
43
+ type: NgModule,
44
+ args: [{
45
+ declarations: [
46
+ FraudDetectionDirective
47
+ ],
48
+ imports: [
49
+ CommonModule
50
+ ],
51
+ exports: [
52
+ FraudDetectionDirective
53
+ ]
54
+ }]
55
+ }] });
56
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJhY2V0YWlsLm1vZHVsZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9saWIvdHJhY2V0YWlsLm1vZHVsZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsUUFBUSxFQUF1QixNQUFNLGVBQWUsQ0FBQztBQUM5RCxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDL0MsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFDekQsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFFdkQsT0FBTyxFQUFFLGdCQUFnQixFQUFFLGNBQWMsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBQ3RFLE9BQU8sRUFBRSx1QkFBdUIsRUFBRSxNQUFNLHdDQUF3QyxDQUFDO0FBQ2pGLE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxNQUFNLHNDQUFzQyxDQUFDOztBQWE1RSxNQUFNLE9BQU8sZUFBZTtJQUMxQixNQUFNLENBQUMsT0FBTyxDQUFDLE1BQXVCO1FBQ3BDLE9BQU87WUFDTCxRQUFRLEVBQUUsZUFBZTtZQUN6QixTQUFTLEVBQUU7Z0JBQ1Q7b0JBQ0UsT0FBTyxFQUFFLGdCQUFnQjtvQkFDekIsUUFBUSxFQUFFLEVBQUUsR0FBRyxjQUFjLEVBQUUsR0FBRyxNQUFNLEVBQUU7aUJBQzNDO2dCQUNELGdCQUFnQjtnQkFDaEI7b0JBQ0UsT0FBTyxFQUFFLGlCQUFpQjtvQkFDMUIsUUFBUSxFQUFFLG9CQUFvQjtvQkFDOUIsS0FBSyxFQUFFLElBQUk7aUJBQ1o7YUFDRjtTQUNGLENBQUM7SUFDSixDQUFDO0lBRUQsTUFBTSxDQUFDLFVBQVUsQ0FBQyxNQUFpQztRQUNqRCxPQUFPO1lBQ0wsUUFBUSxFQUFFLGVBQWU7WUFDekIsU0FBUyxFQUFFLE1BQU0sQ0FBQyxDQUFDLENBQUM7Z0JBQ2xCO29CQUNFLE9BQU8sRUFBRSxnQkFBZ0I7b0JBQ3pCLFFBQVEsRUFBRSxFQUFFLEdBQUcsY0FBYyxFQUFFLEdBQUcsTUFBTSxFQUFFO2lCQUMzQzthQUNGLENBQUMsQ0FBQyxDQUFDLEVBQUU7U0FDUCxDQUFDO0lBQ0osQ0FBQzt3R0E3QlUsZUFBZTt5R0FBZixlQUFlLGlCQVR4Qix1QkFBdUIsYUFHdkIsWUFBWSxhQUdaLHVCQUF1Qjt5R0FHZCxlQUFlLFlBTnhCLFlBQVk7OzRGQU1ILGVBQWU7a0JBWDNCLFFBQVE7bUJBQUM7b0JBQ1IsWUFBWSxFQUFFO3dCQUNaLHVCQUF1QjtxQkFDeEI7b0JBQ0QsT0FBTyxFQUFFO3dCQUNQLFlBQVk7cUJBQ2I7b0JBQ0QsT0FBTyxFQUFFO3dCQUNQLHVCQUF1QjtxQkFDeEI7aUJBQ0YiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBOZ01vZHVsZSwgTW9kdWxlV2l0aFByb3ZpZGVycyB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQ29tbW9uTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcbmltcG9ydCB7IEhUVFBfSU5URVJDRVBUT1JTIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uL2h0dHAnO1xuaW1wb3J0IHsgVHJhY2VUYWlsU2VydmljZSB9IGZyb20gJy4vdHJhY2V0YWlsLnNlcnZpY2UnO1xuaW1wb3J0IHsgVHJhY2VUYWlsQ29uZmlnIH0gZnJvbSAnLi90cmFjZXRhaWwudHlwZXMnO1xuaW1wb3J0IHsgVFJBQ0VUQUlMX0NPTkZJRywgREVGQVVMVF9DT05GSUcgfSBmcm9tICcuL3RyYWNldGFpbC5jb25maWcnO1xuaW1wb3J0IHsgRnJhdWREZXRlY3Rpb25EaXJlY3RpdmUgfSBmcm9tICcuL2RpcmVjdGl2ZXMvZnJhdWQtZGV0ZWN0aW9uLmRpcmVjdGl2ZSc7XG5pbXBvcnQgeyBUcmFjZVRhaWxJbnRlcmNlcHRvciB9IGZyb20gJy4vaW50ZXJjZXB0b3JzL3RyYWNldGFpbC5pbnRlcmNlcHRvcic7XG5cbkBOZ01vZHVsZSh7XG4gIGRlY2xhcmF0aW9uczogW1xuICAgIEZyYXVkRGV0ZWN0aW9uRGlyZWN0aXZlXG4gIF0sXG4gIGltcG9ydHM6IFtcbiAgICBDb21tb25Nb2R1bGVcbiAgXSxcbiAgZXhwb3J0czogW1xuICAgIEZyYXVkRGV0ZWN0aW9uRGlyZWN0aXZlXG4gIF1cbn0pXG5leHBvcnQgY2xhc3MgVHJhY2VUYWlsTW9kdWxlIHtcbiAgc3RhdGljIGZvclJvb3QoY29uZmlnOiBUcmFjZVRhaWxDb25maWcpOiBNb2R1bGVXaXRoUHJvdmlkZXJzPFRyYWNlVGFpbE1vZHVsZT4ge1xuICAgIHJldHVybiB7XG4gICAgICBuZ01vZHVsZTogVHJhY2VUYWlsTW9kdWxlLFxuICAgICAgcHJvdmlkZXJzOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBwcm92aWRlOiBUUkFDRVRBSUxfQ09ORklHLFxuICAgICAgICAgIHVzZVZhbHVlOiB7IC4uLkRFRkFVTFRfQ09ORklHLCAuLi5jb25maWcgfVxuICAgICAgICB9LFxuICAgICAgICBUcmFjZVRhaWxTZXJ2aWNlLFxuICAgICAgICB7XG4gICAgICAgICAgcHJvdmlkZTogSFRUUF9JTlRFUkNFUFRPUlMsXG4gICAgICAgICAgdXNlQ2xhc3M6IFRyYWNlVGFpbEludGVyY2VwdG9yLFxuICAgICAgICAgIG11bHRpOiB0cnVlXG4gICAgICAgIH1cbiAgICAgIF1cbiAgICB9O1xuICB9XG5cbiAgc3RhdGljIGZvckZlYXR1cmUoY29uZmlnPzogUGFydGlhbDxUcmFjZVRhaWxDb25maWc+KTogTW9kdWxlV2l0aFByb3ZpZGVyczxUcmFjZVRhaWxNb2R1bGU+IHtcbiAgICByZXR1cm4ge1xuICAgICAgbmdNb2R1bGU6IFRyYWNlVGFpbE1vZHVsZSxcbiAgICAgIHByb3ZpZGVyczogY29uZmlnID8gW1xuICAgICAgICB7XG4gICAgICAgICAgcHJvdmlkZTogVFJBQ0VUQUlMX0NPTkZJRyxcbiAgICAgICAgICB1c2VWYWx1ZTogeyAuLi5ERUZBVUxUX0NPTkZJRywgLi4uY29uZmlnIH1cbiAgICAgICAgfVxuICAgICAgXSA6IFtdXG4gICAgfTtcbiAgfVxufSJdfQ==