joopjs 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +678 -0
- package/README.md +583 -0
- package/dist/a11y.service-C-DQQfgO.d.mts +143 -0
- package/dist/a11y.service-CauEJrJe.d.ts +143 -0
- package/dist/adapters-B6slG6hQ.d.mts +84 -0
- package/dist/adapters-B6slG6hQ.d.ts +84 -0
- package/dist/aes.service-CkoupAww.d.mts +95 -0
- package/dist/aes.service-CkoupAww.d.ts +95 -0
- package/dist/ai/index.d.mts +99 -0
- package/dist/ai/index.d.ts +99 -0
- package/dist/ai/index.js +307 -0
- package/dist/ai/index.js.map +1 -0
- package/dist/ai/index.mjs +304 -0
- package/dist/ai/index.mjs.map +1 -0
- package/dist/analytics/index.d.mts +42 -0
- package/dist/analytics/index.d.ts +42 -0
- package/dist/analytics/index.js +139 -0
- package/dist/analytics/index.js.map +1 -0
- package/dist/analytics/index.mjs +136 -0
- package/dist/analytics/index.mjs.map +1 -0
- package/dist/angular/index.d.mts +148 -0
- package/dist/angular/index.d.ts +148 -0
- package/dist/angular/index.js +122 -0
- package/dist/angular/index.js.map +1 -0
- package/dist/angular/index.mjs +101 -0
- package/dist/angular/index.mjs.map +1 -0
- package/dist/api/index.d.mts +128 -0
- package/dist/api/index.d.ts +128 -0
- package/dist/api/index.js +1358 -0
- package/dist/api/index.js.map +1 -0
- package/dist/api/index.mjs +1332 -0
- package/dist/api/index.mjs.map +1 -0
- package/dist/auth/index.d.mts +105 -0
- package/dist/auth/index.d.ts +105 -0
- package/dist/auth/index.js +989 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/auth/index.mjs +979 -0
- package/dist/auth/index.mjs.map +1 -0
- package/dist/auth.service-DNVB-L4U.d.mts +16 -0
- package/dist/auth.service-PjUUSUIt.d.ts +16 -0
- package/dist/banking/index.d.mts +1530 -0
- package/dist/banking/index.d.ts +1530 -0
- package/dist/banking/index.js +4739 -0
- package/dist/banking/index.js.map +1 -0
- package/dist/banking/index.mjs +4661 -0
- package/dist/banking/index.mjs.map +1 -0
- package/dist/cache/index.d.mts +40 -0
- package/dist/cache/index.d.ts +40 -0
- package/dist/cache/index.js +174 -0
- package/dist/cache/index.js.map +1 -0
- package/dist/cache/index.mjs +172 -0
- package/dist/cache/index.mjs.map +1 -0
- package/dist/client-profile.service-BuPeXVp5.d.mts +28 -0
- package/dist/client-profile.service-D5bRRYQp.d.ts +28 -0
- package/dist/config.models-Cqg04fAQ.d.mts +84 -0
- package/dist/config.models-Cqg04fAQ.d.ts +84 -0
- package/dist/config.service-CrCvI-JS.d.ts +31 -0
- package/dist/config.service-Cz4QQLlf.d.mts +31 -0
- package/dist/core/index.d.mts +4 -0
- package/dist/core/index.d.ts +4 -0
- package/dist/core/index.js +631 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/index.mjs +619 -0
- package/dist/core/index.mjs.map +1 -0
- package/dist/crypto-utils-DriNhLdx.d.mts +30 -0
- package/dist/crypto-utils-DriNhLdx.d.ts +30 -0
- package/dist/data-storage.service-DT6xaTxE.d.ts +51 -0
- package/dist/data-storage.service-LvhGRCmw.d.mts +51 -0
- package/dist/deeplink/index.d.mts +39 -0
- package/dist/deeplink/index.d.ts +39 -0
- package/dist/deeplink/index.js +268 -0
- package/dist/deeplink/index.js.map +1 -0
- package/dist/deeplink/index.mjs +265 -0
- package/dist/deeplink/index.mjs.map +1 -0
- package/dist/deeplink.service-Ctd5u243.d.mts +35 -0
- package/dist/deeplink.service-uUuTnY9_.d.ts +35 -0
- package/dist/dev/index.d.mts +20 -0
- package/dist/dev/index.d.ts +20 -0
- package/dist/dev/index.js +51 -0
- package/dist/dev/index.js.map +1 -0
- package/dist/dev/index.mjs +49 -0
- package/dist/dev/index.mjs.map +1 -0
- package/dist/device/index.d.mts +108 -0
- package/dist/device/index.d.ts +108 -0
- package/dist/device/index.js +960 -0
- package/dist/device/index.js.map +1 -0
- package/dist/device/index.mjs +951 -0
- package/dist/device/index.mjs.map +1 -0
- package/dist/differential-privacy-BcAv1G80.d.mts +210 -0
- package/dist/differential-privacy-C8mAUjZr.d.ts +210 -0
- package/dist/encryption/index.d.mts +75 -0
- package/dist/encryption/index.d.ts +75 -0
- package/dist/encryption/index.js +605 -0
- package/dist/encryption/index.js.map +1 -0
- package/dist/encryption/index.mjs +598 -0
- package/dist/encryption/index.mjs.map +1 -0
- package/dist/form-validator-3tkmzr_o.d.mts +72 -0
- package/dist/form-validator-3tkmzr_o.d.ts +72 -0
- package/dist/forms/index.d.mts +59 -0
- package/dist/forms/index.d.ts +59 -0
- package/dist/forms/index.js +446 -0
- package/dist/forms/index.js.map +1 -0
- package/dist/forms/index.mjs +442 -0
- package/dist/forms/index.mjs.map +1 -0
- package/dist/i18n/index.d.mts +37 -0
- package/dist/i18n/index.d.ts +37 -0
- package/dist/i18n/index.js +147 -0
- package/dist/i18n/index.js.map +1 -0
- package/dist/i18n/index.mjs +145 -0
- package/dist/i18n/index.mjs.map +1 -0
- package/dist/idempotency.service-_6LqhivP.d.mts +372 -0
- package/dist/idempotency.service-eOKoISRD.d.ts +372 -0
- package/dist/index-B_ksKpS1.d.mts +202 -0
- package/dist/index-CqDKWTUP.d.mts +28 -0
- package/dist/index-CqDKWTUP.d.ts +28 -0
- package/dist/index-DFqEoX_l.d.ts +202 -0
- package/dist/index-Dz0gOur2.d.mts +36 -0
- package/dist/index-Dz0gOur2.d.ts +36 -0
- package/dist/index.d.mts +1336 -0
- package/dist/index.d.ts +1336 -0
- package/dist/index.js +19464 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +19155 -0
- package/dist/index.mjs.map +1 -0
- package/dist/india/index.d.mts +75 -0
- package/dist/india/index.d.ts +75 -0
- package/dist/india/index.js +325 -0
- package/dist/india/index.js.map +1 -0
- package/dist/india/index.mjs +303 -0
- package/dist/india/index.mjs.map +1 -0
- package/dist/joop-Bx7Iwj5p.d.mts +155 -0
- package/dist/joop-CA3DMeOO.d.ts +155 -0
- package/dist/native-bridge/index.d.mts +27 -0
- package/dist/native-bridge/index.d.ts +27 -0
- package/dist/native-bridge/index.js +98 -0
- package/dist/native-bridge/index.js.map +1 -0
- package/dist/native-bridge/index.mjs +96 -0
- package/dist/native-bridge/index.mjs.map +1 -0
- package/dist/network/index.d.mts +85 -0
- package/dist/network/index.d.ts +85 -0
- package/dist/network/index.js +454 -0
- package/dist/network/index.js.map +1 -0
- package/dist/network/index.mjs +451 -0
- package/dist/network/index.mjs.map +1 -0
- package/dist/network-monitor-BIwPSXme.d.mts +179 -0
- package/dist/network-monitor-Bqp2hvZr.d.ts +179 -0
- package/dist/notification.service-Dm4fvfZf.d.mts +25 -0
- package/dist/notification.service-tEMKatWJ.d.ts +25 -0
- package/dist/observability/index.d.mts +179 -0
- package/dist/observability/index.d.ts +179 -0
- package/dist/observability/index.js +559 -0
- package/dist/observability/index.js.map +1 -0
- package/dist/observability/index.mjs +552 -0
- package/dist/observability/index.mjs.map +1 -0
- package/dist/oidc-client-DIJcClmB.d.mts +190 -0
- package/dist/oidc-client-DxhyE59t.d.ts +190 -0
- package/dist/platform/index.d.mts +73 -0
- package/dist/platform/index.d.ts +73 -0
- package/dist/platform/index.js +127 -0
- package/dist/platform/index.js.map +1 -0
- package/dist/platform/index.mjs +125 -0
- package/dist/platform/index.mjs.map +1 -0
- package/dist/pwa/index.d.mts +31 -0
- package/dist/pwa/index.d.ts +31 -0
- package/dist/pwa/index.js +247 -0
- package/dist/pwa/index.js.map +1 -0
- package/dist/pwa/index.mjs +244 -0
- package/dist/pwa/index.mjs.map +1 -0
- package/dist/react/index.d.mts +133 -0
- package/dist/react/index.d.ts +133 -0
- package/dist/react/index.js +632 -0
- package/dist/react/index.js.map +1 -0
- package/dist/react/index.mjs +630 -0
- package/dist/react/index.mjs.map +1 -0
- package/dist/router/index.d.mts +39 -0
- package/dist/router/index.d.ts +39 -0
- package/dist/router/index.js +168 -0
- package/dist/router/index.js.map +1 -0
- package/dist/router/index.mjs +166 -0
- package/dist/router/index.mjs.map +1 -0
- package/dist/security/index.d.mts +206 -0
- package/dist/security/index.d.ts +206 -0
- package/dist/security/index.js +1297 -0
- package/dist/security/index.js.map +1 -0
- package/dist/security/index.mjs +1285 -0
- package/dist/security/index.mjs.map +1 -0
- package/dist/session/index.d.mts +115 -0
- package/dist/session/index.d.ts +115 -0
- package/dist/session/index.js +297 -0
- package/dist/session/index.js.map +1 -0
- package/dist/session/index.mjs +292 -0
- package/dist/session/index.mjs.map +1 -0
- package/dist/state/index.d.mts +43 -0
- package/dist/state/index.d.ts +43 -0
- package/dist/state/index.js +156 -0
- package/dist/state/index.js.map +1 -0
- package/dist/state/index.mjs +152 -0
- package/dist/state/index.mjs.map +1 -0
- package/dist/statement-parser-BHQtXwCM.d.ts +260 -0
- package/dist/statement-parser-C2qNmb49.d.mts +260 -0
- package/dist/storage/index.d.mts +40 -0
- package/dist/storage/index.d.ts +40 -0
- package/dist/storage/index.js +256 -0
- package/dist/storage/index.js.map +1 -0
- package/dist/storage/index.mjs +252 -0
- package/dist/storage/index.mjs.map +1 -0
- package/dist/sync/index.d.mts +69 -0
- package/dist/sync/index.d.ts +69 -0
- package/dist/sync/index.js +330 -0
- package/dist/sync/index.js.map +1 -0
- package/dist/sync/index.mjs +323 -0
- package/dist/sync/index.mjs.map +1 -0
- package/dist/sync-engine-DCIMRG5s.d.ts +61 -0
- package/dist/sync-engine-DZqyKHkK.d.mts +61 -0
- package/dist/theme/index.d.mts +53 -0
- package/dist/theme/index.d.ts +53 -0
- package/dist/theme/index.js +169 -0
- package/dist/theme/index.js.map +1 -0
- package/dist/theme/index.mjs +167 -0
- package/dist/theme/index.mjs.map +1 -0
- package/dist/ui/index.d.mts +66 -0
- package/dist/ui/index.d.ts +66 -0
- package/dist/ui/index.js +811 -0
- package/dist/ui/index.js.map +1 -0
- package/dist/ui/index.mjs +803 -0
- package/dist/ui/index.mjs.map +1 -0
- package/dist/utilities/index.d.mts +199 -0
- package/dist/utilities/index.d.ts +199 -0
- package/dist/utilities/index.js +1991 -0
- package/dist/utilities/index.js.map +1 -0
- package/dist/utilities/index.mjs +1923 -0
- package/dist/utilities/index.mjs.map +1 -0
- package/dist/validation/index.d.mts +60 -0
- package/dist/validation/index.d.ts +60 -0
- package/dist/validation/index.js +460 -0
- package/dist/validation/index.js.map +1 -0
- package/dist/validation/index.mjs +455 -0
- package/dist/validation/index.mjs.map +1 -0
- package/dist/vue/index.d.mts +135 -0
- package/dist/vue/index.d.ts +135 -0
- package/dist/vue/index.js +621 -0
- package/dist/vue/index.js.map +1 -0
- package/dist/vue/index.mjs +619 -0
- package/dist/vue/index.mjs.map +1 -0
- package/dist/watermark.service-Detur5tq.d.ts +235 -0
- package/dist/watermark.service-QNegMeQZ.d.mts +235 -0
- package/dist/workers/index.d.mts +42 -0
- package/dist/workers/index.d.ts +42 -0
- package/dist/workers/index.js +359 -0
- package/dist/workers/index.js.map +1 -0
- package/dist/workers/index.mjs +356 -0
- package/dist/workers/index.mjs.map +1 -0
- package/dist/workflow/index.d.mts +99 -0
- package/dist/workflow/index.d.ts +99 -0
- package/dist/workflow/index.js +282 -0
- package/dist/workflow/index.js.map +1 -0
- package/dist/workflow/index.mjs +279 -0
- package/dist/workflow/index.mjs.map +1 -0
- package/package.json +226 -0
|
@@ -0,0 +1,559 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// src/events/index.ts
|
|
4
|
+
var JoopSubject = class {
|
|
5
|
+
_listeners = [];
|
|
6
|
+
subscribe(listener) {
|
|
7
|
+
this._listeners.push(listener);
|
|
8
|
+
return () => {
|
|
9
|
+
this._listeners = this._listeners.filter((l) => l !== listener);
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
next(value) {
|
|
13
|
+
for (const listener of this._listeners) {
|
|
14
|
+
listener(value);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
asObservable() {
|
|
18
|
+
return new JoopObservable((listener) => this.subscribe(listener));
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
var JoopBehaviorSubject = class extends JoopSubject {
|
|
22
|
+
_value;
|
|
23
|
+
constructor(initialValue) {
|
|
24
|
+
super();
|
|
25
|
+
this._value = initialValue;
|
|
26
|
+
}
|
|
27
|
+
getValue() {
|
|
28
|
+
return this._value;
|
|
29
|
+
}
|
|
30
|
+
next(value) {
|
|
31
|
+
this._value = value;
|
|
32
|
+
super.next(value);
|
|
33
|
+
}
|
|
34
|
+
subscribe(listener) {
|
|
35
|
+
listener(this._value);
|
|
36
|
+
return super.subscribe(listener);
|
|
37
|
+
}
|
|
38
|
+
asObservable() {
|
|
39
|
+
return new JoopObservable((listener) => this.subscribe(listener));
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
var JoopObservable = class {
|
|
43
|
+
constructor(_subscribeFn) {
|
|
44
|
+
this._subscribeFn = _subscribeFn;
|
|
45
|
+
}
|
|
46
|
+
_subscribeFn;
|
|
47
|
+
subscribe(listener) {
|
|
48
|
+
return this._subscribeFn(listener);
|
|
49
|
+
}
|
|
50
|
+
/** Returns the current value without subscribing (only meaningful for BehaviorSubject-backed observables). */
|
|
51
|
+
getOnce() {
|
|
52
|
+
let result;
|
|
53
|
+
const unsub = this.subscribe((v) => {
|
|
54
|
+
result = v;
|
|
55
|
+
});
|
|
56
|
+
unsub();
|
|
57
|
+
return result;
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
// src/observability/web-vitals.ts
|
|
62
|
+
var THRESHOLDS = {
|
|
63
|
+
lcp: [2500, 4e3],
|
|
64
|
+
fid: [100, 300],
|
|
65
|
+
inp: [200, 500],
|
|
66
|
+
cls: [0.1, 0.25],
|
|
67
|
+
ttfb: [800, 1800],
|
|
68
|
+
fcp: [1800, 3e3]
|
|
69
|
+
};
|
|
70
|
+
var JoopWebVitals = class {
|
|
71
|
+
_vitals = {};
|
|
72
|
+
_vitals$ = new JoopSubject();
|
|
73
|
+
_snapshot$ = new JoopBehaviorSubject(this._buildSnapshot());
|
|
74
|
+
_observers = [];
|
|
75
|
+
_running = false;
|
|
76
|
+
start() {
|
|
77
|
+
if (this._running || typeof PerformanceObserver === "undefined") return;
|
|
78
|
+
this._running = true;
|
|
79
|
+
this._observeLCP();
|
|
80
|
+
this._observeFID();
|
|
81
|
+
this._observeINP();
|
|
82
|
+
this._observeCLS();
|
|
83
|
+
this._observeTTFB();
|
|
84
|
+
this._observeFCP();
|
|
85
|
+
}
|
|
86
|
+
stop() {
|
|
87
|
+
this._running = false;
|
|
88
|
+
for (const obs of this._observers) {
|
|
89
|
+
try {
|
|
90
|
+
obs.disconnect();
|
|
91
|
+
} catch {
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
this._observers = [];
|
|
95
|
+
}
|
|
96
|
+
snapshot() {
|
|
97
|
+
return this._buildSnapshot();
|
|
98
|
+
}
|
|
99
|
+
vitals$() {
|
|
100
|
+
return this._vitals$.asObservable();
|
|
101
|
+
}
|
|
102
|
+
snapshot$() {
|
|
103
|
+
return this._snapshot$.asObservable();
|
|
104
|
+
}
|
|
105
|
+
getLCP() {
|
|
106
|
+
return this._vitals.lcp ?? null;
|
|
107
|
+
}
|
|
108
|
+
getCLS() {
|
|
109
|
+
return this._vitals.cls ?? null;
|
|
110
|
+
}
|
|
111
|
+
getINP() {
|
|
112
|
+
return this._vitals.inp ?? null;
|
|
113
|
+
}
|
|
114
|
+
getTTFB() {
|
|
115
|
+
return this._vitals.ttfb ?? null;
|
|
116
|
+
}
|
|
117
|
+
getFCP() {
|
|
118
|
+
return this._vitals.fcp ?? null;
|
|
119
|
+
}
|
|
120
|
+
getFID() {
|
|
121
|
+
return this._vitals.fid ?? null;
|
|
122
|
+
}
|
|
123
|
+
getRating(metric) {
|
|
124
|
+
const value = this._vitals[metric];
|
|
125
|
+
return _rate(metric, value ?? null);
|
|
126
|
+
}
|
|
127
|
+
_record(metric, value) {
|
|
128
|
+
this._vitals[metric] = value;
|
|
129
|
+
const rating = _rate(metric, value);
|
|
130
|
+
this._vitals$.next({ metric, value, rating });
|
|
131
|
+
this._snapshot$.next(this._buildSnapshot());
|
|
132
|
+
}
|
|
133
|
+
_observe(types, callback) {
|
|
134
|
+
try {
|
|
135
|
+
const obs = new PerformanceObserver(callback);
|
|
136
|
+
obs.observe({ type: types[0], buffered: true });
|
|
137
|
+
this._observers.push(obs);
|
|
138
|
+
} catch {
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
_observeLCP() {
|
|
142
|
+
this._observe(["largest-contentful-paint"], (list) => {
|
|
143
|
+
const entries = list.getEntries();
|
|
144
|
+
if (entries.length) this._record("lcp", entries[entries.length - 1].renderTime || entries[entries.length - 1].loadTime || entries[entries.length - 1].startTime);
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
_observeFID() {
|
|
148
|
+
this._observe(["first-input"], (list) => {
|
|
149
|
+
const e = list.getEntries()[0];
|
|
150
|
+
if (e && e.processingStart) this._record("fid", e.processingStart - e.startTime);
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
_observeINP() {
|
|
154
|
+
this._observe(["event"], (list) => {
|
|
155
|
+
let max = this._vitals.inp ?? 0;
|
|
156
|
+
for (const e of list.getEntries()) {
|
|
157
|
+
const entry = e;
|
|
158
|
+
if (entry.processingEnd) max = Math.max(max, entry.processingEnd - entry.startTime);
|
|
159
|
+
}
|
|
160
|
+
if (max > 0) this._record("inp", max);
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
_observeCLS() {
|
|
164
|
+
let clsValue = 0;
|
|
165
|
+
let sessionStart = 0;
|
|
166
|
+
let lastEntry = 0;
|
|
167
|
+
this._observe(["layout-shift"], (list) => {
|
|
168
|
+
for (const e of list.getEntries()) {
|
|
169
|
+
const entry = e;
|
|
170
|
+
if (entry.hadRecentInput) continue;
|
|
171
|
+
if (lastEntry > 0 && entry.startTime - lastEntry > 1e3) {
|
|
172
|
+
if (entry.startTime - sessionStart > 5e3) {
|
|
173
|
+
clsValue = 0;
|
|
174
|
+
sessionStart = entry.startTime;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
if (lastEntry === 0) sessionStart = entry.startTime;
|
|
178
|
+
clsValue += entry.value ?? 0;
|
|
179
|
+
lastEntry = entry.startTime;
|
|
180
|
+
this._record("cls", clsValue);
|
|
181
|
+
}
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
_observeTTFB() {
|
|
185
|
+
const nav = performance.getEntriesByType?.("navigation")?.[0];
|
|
186
|
+
if (nav?.responseStart) this._record("ttfb", nav.responseStart);
|
|
187
|
+
this._observe(["navigation"], (list) => {
|
|
188
|
+
const e = list.getEntries()[0];
|
|
189
|
+
if (e?.responseStart) this._record("ttfb", e.responseStart);
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
_observeFCP() {
|
|
193
|
+
this._observe(["paint"], (list) => {
|
|
194
|
+
const e = list.getEntries().find((e2) => e2.name === "first-contentful-paint");
|
|
195
|
+
if (e) this._record("fcp", e.startTime);
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
_buildSnapshot() {
|
|
199
|
+
return {
|
|
200
|
+
lcp: this._vitals.lcp ?? null,
|
|
201
|
+
fid: this._vitals.fid ?? null,
|
|
202
|
+
inp: this._vitals.inp ?? null,
|
|
203
|
+
cls: this._vitals.cls ?? null,
|
|
204
|
+
ttfb: this._vitals.ttfb ?? null,
|
|
205
|
+
fcp: this._vitals.fcp ?? null,
|
|
206
|
+
capturedAt: Date.now()
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
};
|
|
210
|
+
function _rate(metric, value) {
|
|
211
|
+
if (value === null) return "good";
|
|
212
|
+
const [good, poor] = THRESHOLDS[metric] ?? [Infinity, Infinity];
|
|
213
|
+
return value <= good ? "good" : value <= poor ? "needs-improvement" : "poor";
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// src/observability/session-recorder.ts
|
|
217
|
+
var JoopSessionRecorder = class {
|
|
218
|
+
_events = [];
|
|
219
|
+
_running = false;
|
|
220
|
+
_paused = false;
|
|
221
|
+
_startedAt = 0;
|
|
222
|
+
_opts = {
|
|
223
|
+
maskSelectors: [],
|
|
224
|
+
ignoreSelectors: [],
|
|
225
|
+
redactInputs: true,
|
|
226
|
+
maxEvents: 1e4,
|
|
227
|
+
captureScroll: true,
|
|
228
|
+
captureResize: true
|
|
229
|
+
};
|
|
230
|
+
_cleanup = [];
|
|
231
|
+
_mutationObserver = null;
|
|
232
|
+
_scrollTimer = null;
|
|
233
|
+
start(options = {}) {
|
|
234
|
+
if (this._running) return;
|
|
235
|
+
this._opts = { ...this._opts, ...options };
|
|
236
|
+
this._running = true;
|
|
237
|
+
this._paused = false;
|
|
238
|
+
this._events = [];
|
|
239
|
+
this._startedAt = Date.now();
|
|
240
|
+
this._attachListeners();
|
|
241
|
+
}
|
|
242
|
+
pause() {
|
|
243
|
+
this._paused = true;
|
|
244
|
+
}
|
|
245
|
+
resume() {
|
|
246
|
+
this._paused = false;
|
|
247
|
+
}
|
|
248
|
+
stop() {
|
|
249
|
+
this._running = false;
|
|
250
|
+
this._paused = false;
|
|
251
|
+
this._detach();
|
|
252
|
+
return {
|
|
253
|
+
startedAt: this._startedAt,
|
|
254
|
+
stoppedAt: Date.now(),
|
|
255
|
+
events: [...this._events],
|
|
256
|
+
url: typeof location !== "undefined" ? location.href : "",
|
|
257
|
+
userAgent: typeof navigator !== "undefined" ? navigator.userAgent : ""
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
events() {
|
|
261
|
+
return [...this._events];
|
|
262
|
+
}
|
|
263
|
+
export(format = "json") {
|
|
264
|
+
const record = {
|
|
265
|
+
startedAt: this._startedAt,
|
|
266
|
+
stoppedAt: Date.now(),
|
|
267
|
+
events: this._events,
|
|
268
|
+
url: typeof location !== "undefined" ? location.href : "",
|
|
269
|
+
userAgent: typeof navigator !== "undefined" ? navigator.userAgent : ""
|
|
270
|
+
};
|
|
271
|
+
const json = JSON.stringify(record);
|
|
272
|
+
if (format === "compressed") {
|
|
273
|
+
try {
|
|
274
|
+
return btoa(json);
|
|
275
|
+
} catch {
|
|
276
|
+
return json;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
return json;
|
|
280
|
+
}
|
|
281
|
+
addEvent(type, data) {
|
|
282
|
+
this._push({ type, timestamp: Date.now(), data });
|
|
283
|
+
}
|
|
284
|
+
_push(event) {
|
|
285
|
+
if (!this._running || this._paused) return;
|
|
286
|
+
if (this._events.length >= this._opts.maxEvents) this._events.shift();
|
|
287
|
+
this._events.push(event);
|
|
288
|
+
}
|
|
289
|
+
_attachListeners() {
|
|
290
|
+
this._mutationObserver = new MutationObserver((mutations) => {
|
|
291
|
+
for (const m of mutations) {
|
|
292
|
+
if (this._shouldIgnore(m.target)) continue;
|
|
293
|
+
this._push({ type: "dom-mutation", timestamp: Date.now(), selector: _selector(m.target), data: { addedNodes: m.addedNodes.length, removedNodes: m.removedNodes.length, type: m.type } });
|
|
294
|
+
}
|
|
295
|
+
});
|
|
296
|
+
this._mutationObserver.observe(document.documentElement, { childList: true, subtree: true, attributes: true, characterData: false, attributeFilter: ["class", "style", "hidden", "disabled"] });
|
|
297
|
+
const onClick = (e) => {
|
|
298
|
+
const el = e.target;
|
|
299
|
+
if (this._shouldIgnore(el)) return;
|
|
300
|
+
this._push({ type: "click", timestamp: Date.now(), selector: _selector(el) });
|
|
301
|
+
};
|
|
302
|
+
document.addEventListener("click", onClick, { capture: true });
|
|
303
|
+
this._cleanup.push(() => document.removeEventListener("click", onClick, { capture: true }));
|
|
304
|
+
const onInput = (e) => {
|
|
305
|
+
const el = e.target;
|
|
306
|
+
if (this._shouldIgnore(el)) return;
|
|
307
|
+
const redact = this._opts.redactInputs && (el.type === "password" || el.dataset?.pii !== void 0 || this._opts.maskSelectors.some((s) => el.matches(s)));
|
|
308
|
+
this._push({ type: "input", timestamp: Date.now(), selector: _selector(el), value: redact ? "***" : void 0 });
|
|
309
|
+
};
|
|
310
|
+
document.addEventListener("input", onInput, { capture: true });
|
|
311
|
+
this._cleanup.push(() => document.removeEventListener("input", onInput, { capture: true }));
|
|
312
|
+
if (this._opts.captureScroll) {
|
|
313
|
+
const onScroll = () => {
|
|
314
|
+
if (this._scrollTimer) return;
|
|
315
|
+
this._scrollTimer = setTimeout(() => {
|
|
316
|
+
this._scrollTimer = null;
|
|
317
|
+
this._push({ type: "scroll", timestamp: Date.now(), data: { x: window.scrollX, y: window.scrollY } });
|
|
318
|
+
}, 250);
|
|
319
|
+
};
|
|
320
|
+
window.addEventListener("scroll", onScroll, { passive: true });
|
|
321
|
+
this._cleanup.push(() => window.removeEventListener("scroll", onScroll));
|
|
322
|
+
}
|
|
323
|
+
if (this._opts.captureResize) {
|
|
324
|
+
let resizeTimer = null;
|
|
325
|
+
const onResize = () => {
|
|
326
|
+
if (resizeTimer) return;
|
|
327
|
+
resizeTimer = setTimeout(() => {
|
|
328
|
+
resizeTimer = null;
|
|
329
|
+
this._push({ type: "resize", timestamp: Date.now(), data: { w: window.innerWidth, h: window.innerHeight } });
|
|
330
|
+
}, 250);
|
|
331
|
+
};
|
|
332
|
+
window.addEventListener("resize", onResize, { passive: true });
|
|
333
|
+
this._cleanup.push(() => window.removeEventListener("resize", onResize));
|
|
334
|
+
}
|
|
335
|
+
const onPop = () => this._push({ type: "navigation", timestamp: Date.now(), data: { url: location.href } });
|
|
336
|
+
window.addEventListener("popstate", onPop);
|
|
337
|
+
this._cleanup.push(() => window.removeEventListener("popstate", onPop));
|
|
338
|
+
}
|
|
339
|
+
_detach() {
|
|
340
|
+
this._mutationObserver?.disconnect();
|
|
341
|
+
this._mutationObserver = null;
|
|
342
|
+
for (const fn of this._cleanup) fn();
|
|
343
|
+
this._cleanup = [];
|
|
344
|
+
}
|
|
345
|
+
_shouldIgnore(el) {
|
|
346
|
+
if (!el) return false;
|
|
347
|
+
return this._opts.ignoreSelectors.some((s) => {
|
|
348
|
+
try {
|
|
349
|
+
return el.matches?.(s);
|
|
350
|
+
} catch {
|
|
351
|
+
return false;
|
|
352
|
+
}
|
|
353
|
+
});
|
|
354
|
+
}
|
|
355
|
+
};
|
|
356
|
+
function _selector(el) {
|
|
357
|
+
if (!el) return "";
|
|
358
|
+
const parts = [];
|
|
359
|
+
let current = el;
|
|
360
|
+
while (current && current !== document.body && parts.length < 4) {
|
|
361
|
+
let part = current.tagName.toLowerCase();
|
|
362
|
+
if (current.id) {
|
|
363
|
+
parts.unshift(`#${current.id}`);
|
|
364
|
+
break;
|
|
365
|
+
}
|
|
366
|
+
if (current.className) part += "." + Array.from(current.classList).slice(0, 2).join(".");
|
|
367
|
+
parts.unshift(part);
|
|
368
|
+
current = current.parentElement;
|
|
369
|
+
}
|
|
370
|
+
return parts.join(" > ");
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
// src/observability/correlation.service.ts
|
|
374
|
+
var JoopCorrelationService = class {
|
|
375
|
+
_correlationId = "";
|
|
376
|
+
_requestId = "";
|
|
377
|
+
newCorrelation() {
|
|
378
|
+
this._correlationId = crypto.randomUUID();
|
|
379
|
+
return this._correlationId;
|
|
380
|
+
}
|
|
381
|
+
newRequest() {
|
|
382
|
+
this._requestId = crypto.randomUUID();
|
|
383
|
+
return this._requestId;
|
|
384
|
+
}
|
|
385
|
+
getCorrelationId() {
|
|
386
|
+
return this._correlationId;
|
|
387
|
+
}
|
|
388
|
+
getRequestId() {
|
|
389
|
+
return this._requestId;
|
|
390
|
+
}
|
|
391
|
+
headers() {
|
|
392
|
+
const h = {};
|
|
393
|
+
if (this._correlationId) h["X-Correlation-ID"] = this._correlationId;
|
|
394
|
+
if (this._requestId) h["X-Request-ID"] = this._requestId;
|
|
395
|
+
return h;
|
|
396
|
+
}
|
|
397
|
+
clear() {
|
|
398
|
+
this._correlationId = "";
|
|
399
|
+
this._requestId = "";
|
|
400
|
+
}
|
|
401
|
+
};
|
|
402
|
+
|
|
403
|
+
// src/observability/audit-log.service.ts
|
|
404
|
+
var JoopAuditLog = class {
|
|
405
|
+
constructor(_maxEntries = 500) {
|
|
406
|
+
this._maxEntries = _maxEntries;
|
|
407
|
+
}
|
|
408
|
+
_maxEntries;
|
|
409
|
+
_entries = [];
|
|
410
|
+
_listeners = [];
|
|
411
|
+
record(action, options = {}) {
|
|
412
|
+
const entry = {
|
|
413
|
+
id: crypto.randomUUID(),
|
|
414
|
+
action,
|
|
415
|
+
timestamp: Date.now(),
|
|
416
|
+
success: options.success ?? true,
|
|
417
|
+
...options
|
|
418
|
+
};
|
|
419
|
+
this._entries.push(entry);
|
|
420
|
+
if (this._entries.length > this._maxEntries) this._entries = this._entries.slice(-this._maxEntries);
|
|
421
|
+
this._listeners.forEach((l) => l(entry));
|
|
422
|
+
return entry;
|
|
423
|
+
}
|
|
424
|
+
getAll() {
|
|
425
|
+
return [...this._entries];
|
|
426
|
+
}
|
|
427
|
+
getByAction(action) {
|
|
428
|
+
return this._entries.filter((e) => e.action === action);
|
|
429
|
+
}
|
|
430
|
+
getBySession(sessionId) {
|
|
431
|
+
return this._entries.filter((e) => e.sessionId === sessionId);
|
|
432
|
+
}
|
|
433
|
+
getByUser(userId) {
|
|
434
|
+
return this._entries.filter((e) => e.userId === userId);
|
|
435
|
+
}
|
|
436
|
+
onRecord(listener) {
|
|
437
|
+
this._listeners.push(listener);
|
|
438
|
+
return () => {
|
|
439
|
+
this._listeners = this._listeners.filter((l) => l !== listener);
|
|
440
|
+
};
|
|
441
|
+
}
|
|
442
|
+
clear() {
|
|
443
|
+
this._entries = [];
|
|
444
|
+
}
|
|
445
|
+
export() {
|
|
446
|
+
return JSON.stringify(this._entries, null, 2);
|
|
447
|
+
}
|
|
448
|
+
};
|
|
449
|
+
|
|
450
|
+
// src/observability/performance.service.ts
|
|
451
|
+
var JoopPerformanceService = class {
|
|
452
|
+
_marks = /* @__PURE__ */ new Map();
|
|
453
|
+
_completed = [];
|
|
454
|
+
mark(name, metadata) {
|
|
455
|
+
this._marks.set(name, { name, startTime: performance.now(), metadata });
|
|
456
|
+
}
|
|
457
|
+
measure(name) {
|
|
458
|
+
const mark = this._marks.get(name);
|
|
459
|
+
if (!mark) return null;
|
|
460
|
+
const endTime = performance.now();
|
|
461
|
+
const entry = { ...mark, endTime, duration: endTime - mark.startTime };
|
|
462
|
+
this._marks.delete(name);
|
|
463
|
+
this._completed.push(entry);
|
|
464
|
+
return entry;
|
|
465
|
+
}
|
|
466
|
+
async timeAsync(name, fn) {
|
|
467
|
+
this.mark(name);
|
|
468
|
+
try {
|
|
469
|
+
const result = await fn();
|
|
470
|
+
this.measure(name);
|
|
471
|
+
return result;
|
|
472
|
+
} catch (err) {
|
|
473
|
+
this.measure(name);
|
|
474
|
+
throw err;
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
timeSync(name, fn) {
|
|
478
|
+
this.mark(name);
|
|
479
|
+
try {
|
|
480
|
+
const result = fn();
|
|
481
|
+
this.measure(name);
|
|
482
|
+
return result;
|
|
483
|
+
} catch (err) {
|
|
484
|
+
this.measure(name);
|
|
485
|
+
throw err;
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
getCompleted() {
|
|
489
|
+
return [...this._completed];
|
|
490
|
+
}
|
|
491
|
+
getByName(name) {
|
|
492
|
+
return this._completed.filter((m) => m.name === name);
|
|
493
|
+
}
|
|
494
|
+
getAverage(name) {
|
|
495
|
+
const entries = this._completed.filter((m) => m.name === name && m.duration !== void 0);
|
|
496
|
+
if (!entries.length) return null;
|
|
497
|
+
return entries.reduce((sum, m) => sum + m.duration, 0) / entries.length;
|
|
498
|
+
}
|
|
499
|
+
clear() {
|
|
500
|
+
this._marks.clear();
|
|
501
|
+
this._completed = [];
|
|
502
|
+
}
|
|
503
|
+
};
|
|
504
|
+
|
|
505
|
+
// src/observability/error-reporter.service.ts
|
|
506
|
+
var JoopErrorReporter = class {
|
|
507
|
+
_handlers = [];
|
|
508
|
+
_userId = "";
|
|
509
|
+
_sessionId = "";
|
|
510
|
+
_context = {};
|
|
511
|
+
setUser(userId) {
|
|
512
|
+
this._userId = userId;
|
|
513
|
+
}
|
|
514
|
+
setSession(sessionId) {
|
|
515
|
+
this._sessionId = sessionId;
|
|
516
|
+
}
|
|
517
|
+
setContext(ctx) {
|
|
518
|
+
this._context = { ...this._context, ...ctx };
|
|
519
|
+
}
|
|
520
|
+
addHandler(handler) {
|
|
521
|
+
this._handlers.push(handler);
|
|
522
|
+
return () => {
|
|
523
|
+
this._handlers = this._handlers.filter((h) => h !== handler);
|
|
524
|
+
};
|
|
525
|
+
}
|
|
526
|
+
capture(error, extra) {
|
|
527
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
528
|
+
const report = {
|
|
529
|
+
id: crypto.randomUUID(),
|
|
530
|
+
message: err.message,
|
|
531
|
+
stack: err.stack,
|
|
532
|
+
context: { ...this._context, ...extra },
|
|
533
|
+
timestamp: Date.now(),
|
|
534
|
+
...this._userId ? { userId: this._userId } : {},
|
|
535
|
+
...this._sessionId ? { sessionId: this._sessionId } : {}
|
|
536
|
+
};
|
|
537
|
+
this._handlers.forEach((h) => Promise.resolve(h(report)).catch(() => {
|
|
538
|
+
}));
|
|
539
|
+
return report;
|
|
540
|
+
}
|
|
541
|
+
captureMessage(message, extra) {
|
|
542
|
+
return this.capture(new Error(message), extra);
|
|
543
|
+
}
|
|
544
|
+
clear() {
|
|
545
|
+
this._handlers = [];
|
|
546
|
+
this._userId = "";
|
|
547
|
+
this._sessionId = "";
|
|
548
|
+
this._context = {};
|
|
549
|
+
}
|
|
550
|
+
};
|
|
551
|
+
|
|
552
|
+
exports.JoopAuditLog = JoopAuditLog;
|
|
553
|
+
exports.JoopCorrelationService = JoopCorrelationService;
|
|
554
|
+
exports.JoopErrorReporter = JoopErrorReporter;
|
|
555
|
+
exports.JoopPerformanceService = JoopPerformanceService;
|
|
556
|
+
exports.JoopSessionRecorder = JoopSessionRecorder;
|
|
557
|
+
exports.JoopWebVitals = JoopWebVitals;
|
|
558
|
+
//# sourceMappingURL=index.js.map
|
|
559
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/events/index.ts","../../src/observability/web-vitals.ts","../../src/observability/session-recorder.ts","../../src/observability/correlation.service.ts","../../src/observability/audit-log.service.ts","../../src/observability/performance.service.ts","../../src/observability/error-reporter.service.ts"],"names":["e"],"mappings":"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","file":"index.js","sourcesContent":["export type Unsubscribe = () => void;\nexport type Listener<T> = (value: T) => void;\n\n/**\n * Lightweight pub/sub subject — emits to all current subscribers.\n * Replaces RxJS Subject without pulling in the full RxJS dependency.\n */\nexport class JoopSubject<T> {\n private _listeners: Listener<T>[] = [];\n\n subscribe(listener: Listener<T>): Unsubscribe {\n this._listeners.push(listener);\n return () => {\n this._listeners = this._listeners.filter(l => l !== listener);\n };\n }\n\n next(value: T): void {\n for (const listener of this._listeners) {\n listener(value);\n }\n }\n\n asObservable(): JoopObservable<T> {\n return new JoopObservable<T>(listener => this.subscribe(listener));\n }\n}\n\n/**\n * Stateful subject — replays the current value to any new subscriber immediately.\n * Replaces RxJS BehaviorSubject.\n */\nexport class JoopBehaviorSubject<T> extends JoopSubject<T> {\n private _value: T;\n\n constructor(initialValue: T) {\n super();\n this._value = initialValue;\n }\n\n getValue(): T {\n return this._value;\n }\n\n override next(value: T): void {\n this._value = value;\n super.next(value);\n }\n\n override subscribe(listener: Listener<T>): Unsubscribe {\n listener(this._value);\n return super.subscribe(listener);\n }\n\n override asObservable(): JoopObservable<T> {\n return new JoopObservable<T>(listener => this.subscribe(listener));\n }\n}\n\n/**\n * Read-only observable handle returned from asObservable().\n */\nexport class JoopObservable<T> {\n constructor(private _subscribeFn: (listener: Listener<T>) => Unsubscribe) {}\n\n subscribe(listener: Listener<T>): Unsubscribe {\n return this._subscribeFn(listener);\n }\n\n /** Returns the current value without subscribing (only meaningful for BehaviorSubject-backed observables). */\n getOnce(): T | undefined {\n let result: T | undefined;\n const unsub = this.subscribe(v => { result = v; });\n unsub();\n return result;\n }\n}\n","import { JoopBehaviorSubject, JoopSubject } from '../events';\n\nexport interface JoopVitalsSnapshot {\n lcp: number | null; // Largest Contentful Paint (ms)\n fid: number | null; // First Input Delay (ms) — deprecated, use INP\n inp: number | null; // Interaction to Next Paint (ms)\n cls: number | null; // Cumulative Layout Shift (score)\n ttfb: number | null; // Time to First Byte (ms)\n fcp: number | null; // First Contentful Paint (ms)\n capturedAt: number;\n}\n\nexport interface JoopVitalUpdate {\n metric: keyof Omit<JoopVitalsSnapshot, 'capturedAt'>;\n value: number;\n rating: 'good' | 'needs-improvement' | 'poor';\n}\n\n// Thresholds per https://web.dev/vitals/\nconst THRESHOLDS: Record<string, [number, number]> = {\n lcp: [2500, 4000],\n fid: [100, 300],\n inp: [200, 500],\n cls: [0.1, 0.25],\n ttfb: [800, 1800],\n fcp: [1800, 3000],\n};\n\nexport class JoopWebVitals {\n private _vitals: Partial<JoopVitalsSnapshot> = {};\n private _vitals$ = new JoopSubject<JoopVitalUpdate>();\n private _snapshot$ = new JoopBehaviorSubject<JoopVitalsSnapshot>(this._buildSnapshot());\n private _observers: PerformanceObserver[] = [];\n private _running = false;\n\n start(): void {\n if (this._running || typeof PerformanceObserver === 'undefined') return;\n this._running = true;\n this._observeLCP();\n this._observeFID();\n this._observeINP();\n this._observeCLS();\n this._observeTTFB();\n this._observeFCP();\n }\n\n stop(): void {\n this._running = false;\n for (const obs of this._observers) { try { obs.disconnect(); } catch {} }\n this._observers = [];\n }\n\n snapshot(): JoopVitalsSnapshot { return this._buildSnapshot(); }\n vitals$() { return this._vitals$.asObservable(); }\n snapshot$() { return this._snapshot$.asObservable(); }\n\n getLCP(): number | null { return this._vitals.lcp ?? null; }\n getCLS(): number | null { return this._vitals.cls ?? null; }\n getINP(): number | null { return this._vitals.inp ?? null; }\n getTTFB(): number | null { return this._vitals.ttfb ?? null; }\n getFCP(): number | null { return this._vitals.fcp ?? null; }\n getFID(): number | null { return this._vitals.fid ?? null; }\n\n getRating(metric: string): 'good' | 'needs-improvement' | 'poor' {\n const value = (this._vitals as Record<string, number | null>)[metric];\n return _rate(metric, value ?? null);\n }\n\n private _record(metric: keyof Omit<JoopVitalsSnapshot, 'capturedAt'>, value: number): void {\n (this._vitals as Record<string, number>)[metric] = value;\n const rating = _rate(metric as string, value);\n this._vitals$.next({ metric, value, rating });\n this._snapshot$.next(this._buildSnapshot());\n }\n\n private _observe(types: string[], callback: (list: PerformanceObserverEntryList) => void): void {\n try {\n const obs = new PerformanceObserver(callback);\n obs.observe({ type: types[0], buffered: true });\n this._observers.push(obs);\n } catch {}\n }\n\n private _observeLCP(): void {\n this._observe(['largest-contentful-paint'], list => {\n const entries = list.getEntries();\n if (entries.length) this._record('lcp', (entries[entries.length - 1] as PerformanceEntry & { renderTime?: number; loadTime?: number }).renderTime || (entries[entries.length - 1] as PerformanceEntry & { renderTime?: number; loadTime?: number }).loadTime || entries[entries.length - 1].startTime);\n });\n }\n\n private _observeFID(): void {\n this._observe(['first-input'], list => {\n const e = list.getEntries()[0] as PerformanceEntry & { processingStart?: number };\n if (e && e.processingStart) this._record('fid', e.processingStart - e.startTime);\n });\n }\n\n private _observeINP(): void {\n this._observe(['event'], list => {\n let max = this._vitals.inp ?? 0;\n for (const e of list.getEntries()) {\n const entry = e as PerformanceEntry & { processingEnd?: number };\n if (entry.processingEnd) max = Math.max(max, entry.processingEnd - entry.startTime);\n }\n if (max > 0) this._record('inp', max);\n });\n }\n\n private _observeCLS(): void {\n let clsValue = 0;\n let sessionStart = 0;\n let lastEntry = 0;\n this._observe(['layout-shift'], list => {\n for (const e of list.getEntries()) {\n const entry = e as PerformanceEntry & { hadRecentInput?: boolean; value?: number };\n if (entry.hadRecentInput) continue;\n if (lastEntry > 0 && (entry.startTime - lastEntry) > 1000) {\n if (entry.startTime - sessionStart > 5000) { clsValue = 0; sessionStart = entry.startTime; }\n }\n if (lastEntry === 0) sessionStart = entry.startTime;\n clsValue += entry.value ?? 0;\n lastEntry = entry.startTime;\n this._record('cls', clsValue);\n }\n });\n }\n\n private _observeTTFB(): void {\n const nav = performance.getEntriesByType?.('navigation')?.[0] as PerformanceEntry & { responseStart?: number };\n if (nav?.responseStart) this._record('ttfb', nav.responseStart);\n this._observe(['navigation'], list => {\n const e = list.getEntries()[0] as PerformanceEntry & { responseStart?: number };\n if (e?.responseStart) this._record('ttfb', e.responseStart);\n });\n }\n\n private _observeFCP(): void {\n this._observe(['paint'], list => {\n const e = list.getEntries().find(e => e.name === 'first-contentful-paint');\n if (e) this._record('fcp', e.startTime);\n });\n }\n\n private _buildSnapshot(): JoopVitalsSnapshot {\n return {\n lcp: this._vitals.lcp ?? null,\n fid: this._vitals.fid ?? null,\n inp: this._vitals.inp ?? null,\n cls: this._vitals.cls ?? null,\n ttfb: this._vitals.ttfb ?? null,\n fcp: this._vitals.fcp ?? null,\n capturedAt: Date.now(),\n };\n }\n}\n\nfunction _rate(metric: string, value: number | null): 'good' | 'needs-improvement' | 'poor' {\n if (value === null) return 'good';\n const [good, poor] = THRESHOLDS[metric] ?? [Infinity, Infinity];\n return value <= good ? 'good' : value <= poor ? 'needs-improvement' : 'poor';\n}\n","export type JoopRecordedEventType = 'dom-mutation' | 'click' | 'input' | 'scroll' | 'resize' | 'navigation' | 'custom';\n\nexport interface JoopRecordedEvent {\n type: JoopRecordedEventType;\n timestamp: number;\n selector?: string;\n value?: string;\n data?: Record<string, unknown>;\n}\n\nexport interface JoopSessionRecord {\n startedAt: number;\n stoppedAt: number;\n events: JoopRecordedEvent[];\n url: string;\n userAgent: string;\n}\n\nexport interface JoopSessionRecorderOptions {\n maskSelectors?: string[]; // CSS selectors to mask (replace with ***)\n ignoreSelectors?: string[]; // CSS selectors to ignore entirely\n redactInputs?: boolean; // auto-redact password + [data-pii] inputs\n maxEvents?: number;\n captureScroll?: boolean;\n captureResize?: boolean;\n}\n\nexport class JoopSessionRecorder {\n private _events: JoopRecordedEvent[] = [];\n private _running = false;\n private _paused = false;\n private _startedAt = 0;\n private _opts: Required<JoopSessionRecorderOptions> = {\n maskSelectors: [], ignoreSelectors: [],\n redactInputs: true, maxEvents: 10000,\n captureScroll: true, captureResize: true,\n };\n private _cleanup: Array<() => void> = [];\n private _mutationObserver: MutationObserver | null = null;\n private _scrollTimer: ReturnType<typeof setTimeout> | null = null;\n\n start(options: JoopSessionRecorderOptions = {}): void {\n if (this._running) return;\n this._opts = { ...this._opts, ...options };\n this._running = true; this._paused = false;\n this._events = []; this._startedAt = Date.now();\n this._attachListeners();\n }\n\n pause(): void { this._paused = true; }\n resume(): void { this._paused = false; }\n\n stop(): JoopSessionRecord {\n this._running = false; this._paused = false;\n this._detach();\n return {\n startedAt: this._startedAt, stoppedAt: Date.now(),\n events: [...this._events],\n url: typeof location !== 'undefined' ? location.href : '',\n userAgent: typeof navigator !== 'undefined' ? navigator.userAgent : '',\n };\n }\n\n events(): JoopRecordedEvent[] { return [...this._events]; }\n\n export(format: 'json' | 'compressed' = 'json'): string {\n const record: JoopSessionRecord = {\n startedAt: this._startedAt, stoppedAt: Date.now(),\n events: this._events, url: typeof location !== 'undefined' ? location.href : '', userAgent: typeof navigator !== 'undefined' ? navigator.userAgent : '',\n };\n const json = JSON.stringify(record);\n if (format === 'compressed') {\n try { return btoa(json); } catch { return json; }\n }\n return json;\n }\n\n addEvent(type: JoopRecordedEventType, data?: Record<string, unknown>): void {\n this._push({ type, timestamp: Date.now(), data });\n }\n\n private _push(event: JoopRecordedEvent): void {\n if (!this._running || this._paused) return;\n if (this._events.length >= this._opts.maxEvents) this._events.shift();\n this._events.push(event);\n }\n\n private _attachListeners(): void {\n // DOM mutations\n this._mutationObserver = new MutationObserver(mutations => {\n for (const m of mutations) {\n if (this._shouldIgnore(m.target as Element)) continue;\n this._push({ type: 'dom-mutation', timestamp: Date.now(), selector: _selector(m.target as Element), data: { addedNodes: m.addedNodes.length, removedNodes: m.removedNodes.length, type: m.type } });\n }\n });\n this._mutationObserver.observe(document.documentElement, { childList: true, subtree: true, attributes: true, characterData: false, attributeFilter: ['class', 'style', 'hidden', 'disabled'] });\n\n // Click\n const onClick = (e: MouseEvent) => {\n const el = e.target as Element;\n if (this._shouldIgnore(el)) return;\n this._push({ type: 'click', timestamp: Date.now(), selector: _selector(el) });\n };\n document.addEventListener('click', onClick, { capture: true });\n this._cleanup.push(() => document.removeEventListener('click', onClick, { capture: true }));\n\n // Input\n const onInput = (e: Event) => {\n const el = e.target as HTMLInputElement;\n if (this._shouldIgnore(el)) return;\n const redact = this._opts.redactInputs && (el.type === 'password' || el.dataset?.pii !== undefined || this._opts.maskSelectors.some(s => el.matches(s)));\n this._push({ type: 'input', timestamp: Date.now(), selector: _selector(el), value: redact ? '***' : undefined });\n };\n document.addEventListener('input', onInput, { capture: true });\n this._cleanup.push(() => document.removeEventListener('input', onInput, { capture: true }));\n\n // Scroll (throttled)\n if (this._opts.captureScroll) {\n const onScroll = () => {\n if (this._scrollTimer) return;\n this._scrollTimer = setTimeout(() => {\n this._scrollTimer = null;\n this._push({ type: 'scroll', timestamp: Date.now(), data: { x: window.scrollX, y: window.scrollY } });\n }, 250);\n };\n window.addEventListener('scroll', onScroll, { passive: true });\n this._cleanup.push(() => window.removeEventListener('scroll', onScroll));\n }\n\n // Resize (throttled)\n if (this._opts.captureResize) {\n let resizeTimer: ReturnType<typeof setTimeout> | null = null;\n const onResize = () => {\n if (resizeTimer) return;\n resizeTimer = setTimeout(() => {\n resizeTimer = null;\n this._push({ type: 'resize', timestamp: Date.now(), data: { w: window.innerWidth, h: window.innerHeight } });\n }, 250);\n };\n window.addEventListener('resize', onResize, { passive: true });\n this._cleanup.push(() => window.removeEventListener('resize', onResize));\n }\n\n // Navigation\n const onPop = () => this._push({ type: 'navigation', timestamp: Date.now(), data: { url: location.href } });\n window.addEventListener('popstate', onPop);\n this._cleanup.push(() => window.removeEventListener('popstate', onPop));\n }\n\n private _detach(): void {\n this._mutationObserver?.disconnect(); this._mutationObserver = null;\n for (const fn of this._cleanup) fn();\n this._cleanup = [];\n }\n\n private _shouldIgnore(el: Element | null): boolean {\n if (!el) return false;\n return this._opts.ignoreSelectors.some(s => { try { return el.matches?.(s); } catch { return false; } });\n }\n}\n\nfunction _selector(el: Element | null): string {\n if (!el) return '';\n const parts: string[] = [];\n let current: Element | null = el;\n while (current && current !== document.body && parts.length < 4) {\n let part = current.tagName.toLowerCase();\n if (current.id) { parts.unshift(`#${current.id}`); break; }\n if (current.className) part += '.' + Array.from(current.classList).slice(0, 2).join('.');\n parts.unshift(part);\n current = current.parentElement;\n }\n return parts.join(' > ');\n}\n","export class JoopCorrelationService {\n private _correlationId = '';\n private _requestId = '';\n\n newCorrelation(): string {\n this._correlationId = crypto.randomUUID();\n return this._correlationId;\n }\n\n newRequest(): string {\n this._requestId = crypto.randomUUID();\n return this._requestId;\n }\n\n getCorrelationId(): string { return this._correlationId; }\n getRequestId(): string { return this._requestId; }\n\n headers(): Record<string, string> {\n const h: Record<string, string> = {};\n if (this._correlationId) h['X-Correlation-ID'] = this._correlationId;\n if (this._requestId) h['X-Request-ID'] = this._requestId;\n return h;\n }\n\n clear(): void { this._correlationId = ''; this._requestId = ''; }\n}\n","export type JoopAuditAction =\n | 'login' | 'logout' | 'session-timeout' | 'session-extended'\n | 'transfer-initiated' | 'transfer-confirmed' | 'transfer-failed'\n | 'profile-updated' | 'password-changed' | 'settings-changed'\n | 'document-viewed' | 'statement-downloaded' | 'otp-sent' | 'otp-verified'\n | 'biometric-registered' | 'biometric-authenticated'\n | string;\n\nexport interface JoopAuditEntry {\n id: string;\n action: JoopAuditAction;\n timestamp: number;\n userId?: string;\n sessionId?: string;\n correlationId?: string;\n metadata?: Record<string, unknown>;\n success: boolean;\n}\n\nexport type JoopAuditListener = (entry: JoopAuditEntry) => void;\n\nexport class JoopAuditLog {\n private _entries: JoopAuditEntry[] = [];\n private _listeners: JoopAuditListener[] = [];\n\n constructor(private _maxEntries = 500) {}\n\n record(action: JoopAuditAction, options: {\n userId?: string;\n sessionId?: string;\n correlationId?: string;\n metadata?: Record<string, unknown>;\n success?: boolean;\n } = {}): JoopAuditEntry {\n const entry: JoopAuditEntry = {\n id: crypto.randomUUID(),\n action,\n timestamp: Date.now(),\n success: options.success ?? true,\n ...options,\n };\n this._entries.push(entry);\n if (this._entries.length > this._maxEntries) this._entries = this._entries.slice(-this._maxEntries);\n this._listeners.forEach(l => l(entry));\n return entry;\n }\n\n getAll(): JoopAuditEntry[] { return [...this._entries]; }\n getByAction(action: JoopAuditAction): JoopAuditEntry[] { return this._entries.filter(e => e.action === action); }\n getBySession(sessionId: string): JoopAuditEntry[] { return this._entries.filter(e => e.sessionId === sessionId); }\n getByUser(userId: string): JoopAuditEntry[] { return this._entries.filter(e => e.userId === userId); }\n\n onRecord(listener: JoopAuditListener): () => void {\n this._listeners.push(listener);\n return () => { this._listeners = this._listeners.filter(l => l !== listener); };\n }\n\n clear(): void { this._entries = []; }\n export(): string { return JSON.stringify(this._entries, null, 2); }\n}\n","export interface JoopPerfMark {\n name: string;\n startTime: number;\n endTime?: number;\n duration?: number;\n metadata?: Record<string, unknown>;\n}\n\nexport class JoopPerformanceService {\n private _marks = new Map<string, JoopPerfMark>();\n private _completed: JoopPerfMark[] = [];\n\n mark(name: string, metadata?: Record<string, unknown>): void {\n this._marks.set(name, { name, startTime: performance.now(), metadata });\n }\n\n measure(name: string): JoopPerfMark | null {\n const mark = this._marks.get(name);\n if (!mark) return null;\n const endTime = performance.now();\n const entry: JoopPerfMark = { ...mark, endTime, duration: endTime - mark.startTime };\n this._marks.delete(name);\n this._completed.push(entry);\n return entry;\n }\n\n async timeAsync<T>(name: string, fn: () => Promise<T>): Promise<T> {\n this.mark(name);\n try {\n const result = await fn();\n this.measure(name);\n return result;\n } catch (err) {\n this.measure(name);\n throw err;\n }\n }\n\n timeSync<T>(name: string, fn: () => T): T {\n this.mark(name);\n try {\n const result = fn();\n this.measure(name);\n return result;\n } catch (err) {\n this.measure(name);\n throw err;\n }\n }\n\n getCompleted(): JoopPerfMark[] { return [...this._completed]; }\n getByName(name: string): JoopPerfMark[] { return this._completed.filter(m => m.name === name); }\n\n getAverage(name: string): number | null {\n const entries = this._completed.filter(m => m.name === name && m.duration !== undefined);\n if (!entries.length) return null;\n return entries.reduce((sum, m) => sum + m.duration!, 0) / entries.length;\n }\n\n clear(): void { this._marks.clear(); this._completed = []; }\n}\n","export interface JoopErrorReport {\n id: string;\n message: string;\n stack?: string;\n context?: Record<string, unknown>;\n timestamp: number;\n userId?: string;\n sessionId?: string;\n}\n\nexport type JoopErrorHandler = (report: JoopErrorReport) => void | Promise<void>;\n\nexport class JoopErrorReporter {\n private _handlers: JoopErrorHandler[] = [];\n private _userId = '';\n private _sessionId = '';\n private _context: Record<string, unknown> = {};\n\n setUser(userId: string): void { this._userId = userId; }\n setSession(sessionId: string): void { this._sessionId = sessionId; }\n setContext(ctx: Record<string, unknown>): void { this._context = { ...this._context, ...ctx }; }\n\n addHandler(handler: JoopErrorHandler): () => void {\n this._handlers.push(handler);\n return () => { this._handlers = this._handlers.filter(h => h !== handler); };\n }\n\n capture(error: unknown, extra?: Record<string, unknown>): JoopErrorReport {\n const err = error instanceof Error ? error : new Error(String(error));\n const report: JoopErrorReport = {\n id: crypto.randomUUID(),\n message: err.message,\n stack: err.stack,\n context: { ...this._context, ...extra },\n timestamp: Date.now(),\n ...(this._userId ? { userId: this._userId } : {}),\n ...(this._sessionId ? { sessionId: this._sessionId } : {}),\n };\n this._handlers.forEach(h => Promise.resolve(h(report)).catch(() => {}));\n return report;\n }\n\n captureMessage(message: string, extra?: Record<string, unknown>): JoopErrorReport {\n return this.capture(new Error(message), extra);\n }\n\n clear(): void {\n this._handlers = [];\n this._userId = '';\n this._sessionId = '';\n this._context = {};\n }\n}\n"]}
|