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,297 @@
|
|
|
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/constants/index.ts
|
|
62
|
+
var SESSION_STORAGE_KEY = "joopSession";
|
|
63
|
+
|
|
64
|
+
// src/session/session-timeout.service.ts
|
|
65
|
+
var JoopSessionTimeoutService = class {
|
|
66
|
+
constructor(_auth, _profile, _aes, _scope) {
|
|
67
|
+
this._auth = _auth;
|
|
68
|
+
this._profile = _profile;
|
|
69
|
+
this._aes = _aes;
|
|
70
|
+
this._scope = _scope;
|
|
71
|
+
}
|
|
72
|
+
_auth;
|
|
73
|
+
_profile;
|
|
74
|
+
_aes;
|
|
75
|
+
_scope;
|
|
76
|
+
_event$ = new JoopSubject();
|
|
77
|
+
_mainTimer;
|
|
78
|
+
_waitTimer;
|
|
79
|
+
_phase = "idle";
|
|
80
|
+
_isSessionExtended = false;
|
|
81
|
+
/** Subscribe to session events (warning / logout). */
|
|
82
|
+
events$() {
|
|
83
|
+
return this._event$.asObservable();
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Called after each API response to reset / start the countdown.
|
|
87
|
+
* Pass the set of service IDs that should NOT reset the timer.
|
|
88
|
+
*/
|
|
89
|
+
tick(currentServiceId, ignoreServices = []) {
|
|
90
|
+
const session = this._profile.timeoutInfo?.session;
|
|
91
|
+
if (!session?.enable) return;
|
|
92
|
+
if (!this._auth.isLoggedIn()) return;
|
|
93
|
+
const allIgnored = [...ignoreServices];
|
|
94
|
+
const shouldIgnore = allIgnored.includes(currentServiceId) && !this._isSessionExtended;
|
|
95
|
+
if (shouldIgnore) return;
|
|
96
|
+
this._isSessionExtended = false;
|
|
97
|
+
this._startMainTimer(session.timeout, session.waitTimeout);
|
|
98
|
+
}
|
|
99
|
+
/** User clicked "stay logged in" — reset timer without counting as a new request. */
|
|
100
|
+
extendSession() {
|
|
101
|
+
this._isSessionExtended = true;
|
|
102
|
+
const session = this._profile.timeoutInfo?.session;
|
|
103
|
+
if (session) this._startMainTimer(session.timeout, session.waitTimeout);
|
|
104
|
+
}
|
|
105
|
+
/** Clear all timers and fully reset session state. */
|
|
106
|
+
clearSession() {
|
|
107
|
+
this._stop();
|
|
108
|
+
this._profile.clearSession();
|
|
109
|
+
this._aes.clearKeys();
|
|
110
|
+
this._scope.clearPage();
|
|
111
|
+
this._scope.clearSession();
|
|
112
|
+
this._auth.logout();
|
|
113
|
+
this._phase = "idle";
|
|
114
|
+
if (typeof localStorage !== "undefined") {
|
|
115
|
+
localStorage.removeItem(SESSION_STORAGE_KEY);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
// ─────────── private ───────────
|
|
119
|
+
_startMainTimer(timeout, waitTimeout) {
|
|
120
|
+
this._stop();
|
|
121
|
+
this._phase = "idle";
|
|
122
|
+
this._mainTimer = setTimeout(() => {
|
|
123
|
+
this._phase = "waiting";
|
|
124
|
+
this._event$.next({ type: "warning" });
|
|
125
|
+
this._waitTimer = setTimeout(() => {
|
|
126
|
+
this._phase = "expired";
|
|
127
|
+
this._event$.next({ type: "logout" });
|
|
128
|
+
}, waitTimeout);
|
|
129
|
+
}, timeout);
|
|
130
|
+
}
|
|
131
|
+
_stop() {
|
|
132
|
+
clearTimeout(this._mainTimer);
|
|
133
|
+
clearTimeout(this._waitTimer);
|
|
134
|
+
this._mainTimer = void 0;
|
|
135
|
+
this._waitTimer = void 0;
|
|
136
|
+
}
|
|
137
|
+
get phase() {
|
|
138
|
+
return this._phase;
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
// src/session/multi-tab-sync.service.ts
|
|
143
|
+
var JoopMultiTabSync = class {
|
|
144
|
+
_channel = null;
|
|
145
|
+
_tabId = crypto.randomUUID();
|
|
146
|
+
_subject = new JoopSubject();
|
|
147
|
+
constructor(channelName = "joop-session-sync") {
|
|
148
|
+
if (typeof BroadcastChannel !== "undefined") {
|
|
149
|
+
this._channel = new BroadcastChannel(channelName);
|
|
150
|
+
this._channel.onmessage = (e) => {
|
|
151
|
+
if (e.data.sourceTabId !== this._tabId) this._subject.next(e.data);
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
events$() {
|
|
156
|
+
return this._subject.asObservable();
|
|
157
|
+
}
|
|
158
|
+
get tabId() {
|
|
159
|
+
return this._tabId;
|
|
160
|
+
}
|
|
161
|
+
isSupported() {
|
|
162
|
+
return this._channel !== null;
|
|
163
|
+
}
|
|
164
|
+
broadcast(type, payload) {
|
|
165
|
+
this._channel?.postMessage({ type, payload, sourceTabId: this._tabId });
|
|
166
|
+
}
|
|
167
|
+
destroy() {
|
|
168
|
+
this._channel?.close();
|
|
169
|
+
this._channel = null;
|
|
170
|
+
}
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
// src/session/concurrent-session.service.ts
|
|
174
|
+
var JoopConcurrentSessionService = class {
|
|
175
|
+
constructor(_channelName = "joop-concurrent-session", _heartbeatMs = 5e3) {
|
|
176
|
+
this._channelName = _channelName;
|
|
177
|
+
this._heartbeatMs = _heartbeatMs;
|
|
178
|
+
}
|
|
179
|
+
_channelName;
|
|
180
|
+
_heartbeatMs;
|
|
181
|
+
_sessionId = crypto.randomUUID();
|
|
182
|
+
_channel = null;
|
|
183
|
+
_heartbeatTimer = null;
|
|
184
|
+
_subject = new JoopSubject();
|
|
185
|
+
events$() {
|
|
186
|
+
return this._subject.asObservable();
|
|
187
|
+
}
|
|
188
|
+
get sessionId() {
|
|
189
|
+
return this._sessionId;
|
|
190
|
+
}
|
|
191
|
+
start() {
|
|
192
|
+
if (typeof BroadcastChannel === "undefined") return;
|
|
193
|
+
this._channel = new BroadcastChannel(this._channelName);
|
|
194
|
+
this._channel.onmessage = (e) => {
|
|
195
|
+
if (e.data.sessionId !== this._sessionId) {
|
|
196
|
+
this._subject.next({ type: "duplicate-detected", sessionId: e.data.sessionId, timestamp: Date.now() });
|
|
197
|
+
}
|
|
198
|
+
};
|
|
199
|
+
this._heartbeatTimer = setInterval(() => {
|
|
200
|
+
this._channel?.postMessage({ type: "heartbeat", sessionId: this._sessionId, timestamp: Date.now() });
|
|
201
|
+
}, this._heartbeatMs);
|
|
202
|
+
}
|
|
203
|
+
stop() {
|
|
204
|
+
if (this._heartbeatTimer) {
|
|
205
|
+
clearInterval(this._heartbeatTimer);
|
|
206
|
+
this._heartbeatTimer = null;
|
|
207
|
+
}
|
|
208
|
+
this._channel?.close();
|
|
209
|
+
this._channel = null;
|
|
210
|
+
}
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
// src/session/idle.service.ts
|
|
214
|
+
var DEFAULT_EVENTS = ["mousemove", "keydown", "mousedown", "scroll", "touchstart", "wheel"];
|
|
215
|
+
var JoopIdleService = class {
|
|
216
|
+
_state$ = new JoopBehaviorSubject("active");
|
|
217
|
+
_idleTimer = null;
|
|
218
|
+
_expiredTimer = null;
|
|
219
|
+
_listeners = [];
|
|
220
|
+
_cfg = null;
|
|
221
|
+
_lastActivity = Date.now();
|
|
222
|
+
start(config) {
|
|
223
|
+
this.stop();
|
|
224
|
+
this._cfg = config;
|
|
225
|
+
this._state$.next("active");
|
|
226
|
+
const events = config.events ?? DEFAULT_EVENTS;
|
|
227
|
+
const reset = () => this._reset();
|
|
228
|
+
for (const ev of events) {
|
|
229
|
+
document.addEventListener(ev, reset, { passive: true });
|
|
230
|
+
this._listeners.push(() => document.removeEventListener(ev, reset));
|
|
231
|
+
}
|
|
232
|
+
this._scheduleIdle();
|
|
233
|
+
}
|
|
234
|
+
stop() {
|
|
235
|
+
this._clearTimers();
|
|
236
|
+
for (const remove of this._listeners) remove();
|
|
237
|
+
this._listeners = [];
|
|
238
|
+
this._cfg = null;
|
|
239
|
+
this._state$.next("active");
|
|
240
|
+
}
|
|
241
|
+
reset() {
|
|
242
|
+
this._reset();
|
|
243
|
+
}
|
|
244
|
+
isIdle() {
|
|
245
|
+
return this._state$.getValue() !== "active";
|
|
246
|
+
}
|
|
247
|
+
getState() {
|
|
248
|
+
return this._state$.getValue();
|
|
249
|
+
}
|
|
250
|
+
idleMs() {
|
|
251
|
+
return Date.now() - this._lastActivity;
|
|
252
|
+
}
|
|
253
|
+
state$() {
|
|
254
|
+
return this._state$.asObservable();
|
|
255
|
+
}
|
|
256
|
+
onIdle(handler) {
|
|
257
|
+
return this._state$.subscribe((s) => s === "idle" && handler());
|
|
258
|
+
}
|
|
259
|
+
onActive(handler) {
|
|
260
|
+
return this._state$.subscribe((s) => s === "active" && handler());
|
|
261
|
+
}
|
|
262
|
+
onExpired(handler) {
|
|
263
|
+
return this._state$.subscribe((s) => s === "expired" && handler());
|
|
264
|
+
}
|
|
265
|
+
_reset() {
|
|
266
|
+
this._lastActivity = Date.now();
|
|
267
|
+
if (this._state$.getValue() !== "active") this._state$.next("active");
|
|
268
|
+
this._clearTimers();
|
|
269
|
+
this._scheduleIdle();
|
|
270
|
+
}
|
|
271
|
+
_scheduleIdle() {
|
|
272
|
+
if (!this._cfg) return;
|
|
273
|
+
this._idleTimer = setTimeout(() => {
|
|
274
|
+
this._state$.next("idle");
|
|
275
|
+
if (this._cfg?.expiredMs) {
|
|
276
|
+
this._expiredTimer = setTimeout(() => this._state$.next("expired"), this._cfg.expiredMs);
|
|
277
|
+
}
|
|
278
|
+
}, this._cfg.idleMs);
|
|
279
|
+
}
|
|
280
|
+
_clearTimers() {
|
|
281
|
+
if (this._idleTimer) {
|
|
282
|
+
clearTimeout(this._idleTimer);
|
|
283
|
+
this._idleTimer = null;
|
|
284
|
+
}
|
|
285
|
+
if (this._expiredTimer) {
|
|
286
|
+
clearTimeout(this._expiredTimer);
|
|
287
|
+
this._expiredTimer = null;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
};
|
|
291
|
+
|
|
292
|
+
exports.JoopConcurrentSessionService = JoopConcurrentSessionService;
|
|
293
|
+
exports.JoopIdleService = JoopIdleService;
|
|
294
|
+
exports.JoopMultiTabSync = JoopMultiTabSync;
|
|
295
|
+
exports.JoopSessionTimeoutService = JoopSessionTimeoutService;
|
|
296
|
+
//# sourceMappingURL=index.js.map
|
|
297
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/events/index.ts","../../src/constants/index.ts","../../src/session/session-timeout.service.ts","../../src/session/multi-tab-sync.service.ts","../../src/session/concurrent-session.service.ts","../../src/session/idle.service.ts"],"names":[],"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","export const DEFAULT_REQUEST_TIMEOUT = 30000;\nexport const DEFAULT_SESSION_TIMEOUT = 300000;\nexport const DEFAULT_SESSION_WAIT_TIMEOUT = 60000;\nexport const PAGE_TOKEN_KEY = 'pageToken';\nexport const DECRYPTION_FAILED = 'Response decryption failed';\nexport const SESSION_STORAGE_KEY = 'joopSession';\n","import { JoopSubject, JoopObservable } from '../events';\nimport { JoopAuthService } from '../auth/auth.service';\nimport { JoopClientProfile } from '../profile/client-profile.service';\nimport { JoopAesService } from '../encryption/aes.service';\nimport { JoopScopeMapService } from '../storage/scope-map.service';\nimport { JoopScopeType } from '../enums';\nimport { SESSION_STORAGE_KEY } from '../constants';\n\ntype SessionPhase = 'idle' | 'waiting' | 'expired';\n\nexport interface JoopSessionEvent {\n type: 'warning' | 'logout';\n}\n\n/**\n * Framework-agnostic session timeout manager.\n *\n * Two-stage model:\n * 1. After `timeout` ms of inactivity → emits 'warning' event (show a dialog)\n * 2. After an additional `waitTimeout` ms → emits 'logout' event (force logout)\n *\n * The host app is responsible for showing the warning UI and calling\n * `extendSession()` if the user responds. When 'logout' fires, call `clearSession()`.\n */\nexport class JoopSessionTimeoutService {\n private readonly _event$ = new JoopSubject<JoopSessionEvent>();\n private _mainTimer: ReturnType<typeof setTimeout> | undefined;\n private _waitTimer: ReturnType<typeof setTimeout> | undefined;\n private _phase: SessionPhase = 'idle';\n private _isSessionExtended = false;\n\n constructor(\n private readonly _auth: JoopAuthService,\n private readonly _profile: JoopClientProfile,\n private readonly _aes: JoopAesService,\n private readonly _scope: JoopScopeMapService\n ) {}\n\n /** Subscribe to session events (warning / logout). */\n events$(): JoopObservable<JoopSessionEvent> {\n return this._event$.asObservable();\n }\n\n /**\n * Called after each API response to reset / start the countdown.\n * Pass the set of service IDs that should NOT reset the timer.\n */\n tick(currentServiceId: string, ignoreServices: string[] = []): void {\n const session = this._profile.timeoutInfo?.session;\n if (!session?.enable) return;\n if (!this._auth.isLoggedIn()) return;\n\n const allIgnored = [...ignoreServices];\n const shouldIgnore = allIgnored.includes(currentServiceId) && !this._isSessionExtended;\n if (shouldIgnore) return;\n\n this._isSessionExtended = false;\n this._startMainTimer(session.timeout, session.waitTimeout);\n }\n\n /** User clicked \"stay logged in\" — reset timer without counting as a new request. */\n extendSession(): void {\n this._isSessionExtended = true;\n const session = this._profile.timeoutInfo?.session;\n if (session) this._startMainTimer(session.timeout, session.waitTimeout);\n }\n\n /** Clear all timers and fully reset session state. */\n clearSession(): void {\n this._stop();\n this._profile.clearSession();\n this._aes.clearKeys();\n this._scope.clearPage();\n this._scope.clearSession();\n this._auth.logout();\n this._phase = 'idle';\n if (typeof localStorage !== 'undefined') {\n localStorage.removeItem(SESSION_STORAGE_KEY);\n }\n }\n\n // ─────────── private ───────────\n\n private _startMainTimer(timeout: number, waitTimeout: number): void {\n this._stop();\n this._phase = 'idle';\n this._mainTimer = setTimeout(() => {\n this._phase = 'waiting';\n this._event$.next({ type: 'warning' });\n this._waitTimer = setTimeout(() => {\n this._phase = 'expired';\n this._event$.next({ type: 'logout' });\n }, waitTimeout);\n }, timeout);\n }\n\n private _stop(): void {\n clearTimeout(this._mainTimer);\n clearTimeout(this._waitTimer);\n this._mainTimer = undefined;\n this._waitTimer = undefined;\n }\n\n get phase(): SessionPhase { return this._phase; }\n}\n","import { JoopSubject } from '../events';\n\nexport type JoopTabEventType = 'logout' | 'login' | 'session-warning' | 'token-refresh' | 'custom';\n\nexport interface JoopTabEvent {\n type: JoopTabEventType;\n payload?: unknown;\n sourceTabId: string;\n}\n\nexport class JoopMultiTabSync {\n private _channel: BroadcastChannel | null = null;\n private _tabId = crypto.randomUUID();\n private _subject = new JoopSubject<JoopTabEvent>();\n\n constructor(channelName = 'joop-session-sync') {\n if (typeof BroadcastChannel !== 'undefined') {\n this._channel = new BroadcastChannel(channelName);\n this._channel.onmessage = (e: MessageEvent<JoopTabEvent>) => {\n if (e.data.sourceTabId !== this._tabId) this._subject.next(e.data);\n };\n }\n }\n\n events$() { return this._subject.asObservable(); }\n get tabId(): string { return this._tabId; }\n isSupported(): boolean { return this._channel !== null; }\n\n broadcast(type: JoopTabEventType, payload?: unknown): void {\n this._channel?.postMessage({ type, payload, sourceTabId: this._tabId } satisfies JoopTabEvent);\n }\n\n destroy(): void { this._channel?.close(); this._channel = null; }\n}\n","import { JoopSubject } from '../events';\n\nexport interface JoopConcurrentSessionEvent {\n type: 'duplicate-detected' | 'heartbeat';\n sessionId: string;\n timestamp: number;\n}\n\nexport class JoopConcurrentSessionService {\n private _sessionId = crypto.randomUUID();\n private _channel: BroadcastChannel | null = null;\n private _heartbeatTimer: ReturnType<typeof setInterval> | null = null;\n private _subject = new JoopSubject<JoopConcurrentSessionEvent>();\n\n constructor(\n private readonly _channelName = 'joop-concurrent-session',\n private readonly _heartbeatMs = 5_000\n ) {}\n\n events$() { return this._subject.asObservable(); }\n get sessionId(): string { return this._sessionId; }\n\n start(): void {\n if (typeof BroadcastChannel === 'undefined') return;\n this._channel = new BroadcastChannel(this._channelName);\n this._channel.onmessage = (e: MessageEvent<JoopConcurrentSessionEvent>) => {\n if (e.data.sessionId !== this._sessionId) {\n this._subject.next({ type: 'duplicate-detected', sessionId: e.data.sessionId, timestamp: Date.now() });\n }\n };\n this._heartbeatTimer = setInterval(() => {\n this._channel?.postMessage({ type: 'heartbeat', sessionId: this._sessionId, timestamp: Date.now() });\n }, this._heartbeatMs);\n }\n\n stop(): void {\n if (this._heartbeatTimer) { clearInterval(this._heartbeatTimer); this._heartbeatTimer = null; }\n this._channel?.close();\n this._channel = null;\n }\n}\n","import { JoopBehaviorSubject } from '../events';\n\nexport type JoopIdleState = 'active' | 'idle' | 'expired';\n\nexport interface JoopIdleConfig {\n idleMs: number; // ms of inactivity before idle\n expiredMs?: number; // ms after idle before expired (optional)\n events?: string[]; // DOM events to reset the timer\n}\n\nconst DEFAULT_EVENTS = ['mousemove', 'keydown', 'mousedown', 'scroll', 'touchstart', 'wheel'];\n\nexport class JoopIdleService {\n private _state$ = new JoopBehaviorSubject<JoopIdleState>('active');\n private _idleTimer: ReturnType<typeof setTimeout> | null = null;\n private _expiredTimer: ReturnType<typeof setTimeout> | null = null;\n private _listeners: Array<() => void> = [];\n private _cfg: JoopIdleConfig | null = null;\n private _lastActivity = Date.now();\n\n start(config: JoopIdleConfig): void {\n this.stop();\n this._cfg = config;\n this._state$.next('active');\n const events = config.events ?? DEFAULT_EVENTS;\n const reset = () => this._reset();\n for (const ev of events) {\n document.addEventListener(ev, reset, { passive: true });\n this._listeners.push(() => document.removeEventListener(ev, reset));\n }\n this._scheduleIdle();\n }\n\n stop(): void {\n this._clearTimers();\n for (const remove of this._listeners) remove();\n this._listeners = [];\n this._cfg = null;\n this._state$.next('active');\n }\n\n reset(): void { this._reset(); }\n isIdle(): boolean { return this._state$.getValue() !== 'active'; }\n getState(): JoopIdleState { return this._state$.getValue(); }\n idleMs(): number { return Date.now() - this._lastActivity; }\n state$() { return this._state$.asObservable(); }\n\n onIdle(handler: () => void): () => void {\n return this._state$.subscribe(s => s === 'idle' && handler());\n }\n\n onActive(handler: () => void): () => void {\n return this._state$.subscribe(s => s === 'active' && handler());\n }\n\n onExpired(handler: () => void): () => void {\n return this._state$.subscribe(s => s === 'expired' && handler());\n }\n\n private _reset(): void {\n this._lastActivity = Date.now();\n if (this._state$.getValue() !== 'active') this._state$.next('active');\n this._clearTimers();\n this._scheduleIdle();\n }\n\n private _scheduleIdle(): void {\n if (!this._cfg) return;\n this._idleTimer = setTimeout(() => {\n this._state$.next('idle');\n if (this._cfg?.expiredMs) {\n this._expiredTimer = setTimeout(() => this._state$.next('expired'), this._cfg.expiredMs);\n }\n }, this._cfg.idleMs);\n }\n\n private _clearTimers(): void {\n if (this._idleTimer) { clearTimeout(this._idleTimer); this._idleTimer = null; }\n if (this._expiredTimer) { clearTimeout(this._expiredTimer); this._expiredTimer = null; }\n }\n}\n"]}
|
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
// src/events/index.ts
|
|
2
|
+
var JoopSubject = class {
|
|
3
|
+
_listeners = [];
|
|
4
|
+
subscribe(listener) {
|
|
5
|
+
this._listeners.push(listener);
|
|
6
|
+
return () => {
|
|
7
|
+
this._listeners = this._listeners.filter((l) => l !== listener);
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
next(value) {
|
|
11
|
+
for (const listener of this._listeners) {
|
|
12
|
+
listener(value);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
asObservable() {
|
|
16
|
+
return new JoopObservable((listener) => this.subscribe(listener));
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
var JoopBehaviorSubject = class extends JoopSubject {
|
|
20
|
+
_value;
|
|
21
|
+
constructor(initialValue) {
|
|
22
|
+
super();
|
|
23
|
+
this._value = initialValue;
|
|
24
|
+
}
|
|
25
|
+
getValue() {
|
|
26
|
+
return this._value;
|
|
27
|
+
}
|
|
28
|
+
next(value) {
|
|
29
|
+
this._value = value;
|
|
30
|
+
super.next(value);
|
|
31
|
+
}
|
|
32
|
+
subscribe(listener) {
|
|
33
|
+
listener(this._value);
|
|
34
|
+
return super.subscribe(listener);
|
|
35
|
+
}
|
|
36
|
+
asObservable() {
|
|
37
|
+
return new JoopObservable((listener) => this.subscribe(listener));
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
var JoopObservable = class {
|
|
41
|
+
constructor(_subscribeFn) {
|
|
42
|
+
this._subscribeFn = _subscribeFn;
|
|
43
|
+
}
|
|
44
|
+
_subscribeFn;
|
|
45
|
+
subscribe(listener) {
|
|
46
|
+
return this._subscribeFn(listener);
|
|
47
|
+
}
|
|
48
|
+
/** Returns the current value without subscribing (only meaningful for BehaviorSubject-backed observables). */
|
|
49
|
+
getOnce() {
|
|
50
|
+
let result;
|
|
51
|
+
const unsub = this.subscribe((v) => {
|
|
52
|
+
result = v;
|
|
53
|
+
});
|
|
54
|
+
unsub();
|
|
55
|
+
return result;
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
// src/constants/index.ts
|
|
60
|
+
var SESSION_STORAGE_KEY = "joopSession";
|
|
61
|
+
|
|
62
|
+
// src/session/session-timeout.service.ts
|
|
63
|
+
var JoopSessionTimeoutService = class {
|
|
64
|
+
constructor(_auth, _profile, _aes, _scope) {
|
|
65
|
+
this._auth = _auth;
|
|
66
|
+
this._profile = _profile;
|
|
67
|
+
this._aes = _aes;
|
|
68
|
+
this._scope = _scope;
|
|
69
|
+
}
|
|
70
|
+
_auth;
|
|
71
|
+
_profile;
|
|
72
|
+
_aes;
|
|
73
|
+
_scope;
|
|
74
|
+
_event$ = new JoopSubject();
|
|
75
|
+
_mainTimer;
|
|
76
|
+
_waitTimer;
|
|
77
|
+
_phase = "idle";
|
|
78
|
+
_isSessionExtended = false;
|
|
79
|
+
/** Subscribe to session events (warning / logout). */
|
|
80
|
+
events$() {
|
|
81
|
+
return this._event$.asObservable();
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Called after each API response to reset / start the countdown.
|
|
85
|
+
* Pass the set of service IDs that should NOT reset the timer.
|
|
86
|
+
*/
|
|
87
|
+
tick(currentServiceId, ignoreServices = []) {
|
|
88
|
+
const session = this._profile.timeoutInfo?.session;
|
|
89
|
+
if (!session?.enable) return;
|
|
90
|
+
if (!this._auth.isLoggedIn()) return;
|
|
91
|
+
const allIgnored = [...ignoreServices];
|
|
92
|
+
const shouldIgnore = allIgnored.includes(currentServiceId) && !this._isSessionExtended;
|
|
93
|
+
if (shouldIgnore) return;
|
|
94
|
+
this._isSessionExtended = false;
|
|
95
|
+
this._startMainTimer(session.timeout, session.waitTimeout);
|
|
96
|
+
}
|
|
97
|
+
/** User clicked "stay logged in" — reset timer without counting as a new request. */
|
|
98
|
+
extendSession() {
|
|
99
|
+
this._isSessionExtended = true;
|
|
100
|
+
const session = this._profile.timeoutInfo?.session;
|
|
101
|
+
if (session) this._startMainTimer(session.timeout, session.waitTimeout);
|
|
102
|
+
}
|
|
103
|
+
/** Clear all timers and fully reset session state. */
|
|
104
|
+
clearSession() {
|
|
105
|
+
this._stop();
|
|
106
|
+
this._profile.clearSession();
|
|
107
|
+
this._aes.clearKeys();
|
|
108
|
+
this._scope.clearPage();
|
|
109
|
+
this._scope.clearSession();
|
|
110
|
+
this._auth.logout();
|
|
111
|
+
this._phase = "idle";
|
|
112
|
+
if (typeof localStorage !== "undefined") {
|
|
113
|
+
localStorage.removeItem(SESSION_STORAGE_KEY);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
// ─────────── private ───────────
|
|
117
|
+
_startMainTimer(timeout, waitTimeout) {
|
|
118
|
+
this._stop();
|
|
119
|
+
this._phase = "idle";
|
|
120
|
+
this._mainTimer = setTimeout(() => {
|
|
121
|
+
this._phase = "waiting";
|
|
122
|
+
this._event$.next({ type: "warning" });
|
|
123
|
+
this._waitTimer = setTimeout(() => {
|
|
124
|
+
this._phase = "expired";
|
|
125
|
+
this._event$.next({ type: "logout" });
|
|
126
|
+
}, waitTimeout);
|
|
127
|
+
}, timeout);
|
|
128
|
+
}
|
|
129
|
+
_stop() {
|
|
130
|
+
clearTimeout(this._mainTimer);
|
|
131
|
+
clearTimeout(this._waitTimer);
|
|
132
|
+
this._mainTimer = void 0;
|
|
133
|
+
this._waitTimer = void 0;
|
|
134
|
+
}
|
|
135
|
+
get phase() {
|
|
136
|
+
return this._phase;
|
|
137
|
+
}
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
// src/session/multi-tab-sync.service.ts
|
|
141
|
+
var JoopMultiTabSync = class {
|
|
142
|
+
_channel = null;
|
|
143
|
+
_tabId = crypto.randomUUID();
|
|
144
|
+
_subject = new JoopSubject();
|
|
145
|
+
constructor(channelName = "joop-session-sync") {
|
|
146
|
+
if (typeof BroadcastChannel !== "undefined") {
|
|
147
|
+
this._channel = new BroadcastChannel(channelName);
|
|
148
|
+
this._channel.onmessage = (e) => {
|
|
149
|
+
if (e.data.sourceTabId !== this._tabId) this._subject.next(e.data);
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
events$() {
|
|
154
|
+
return this._subject.asObservable();
|
|
155
|
+
}
|
|
156
|
+
get tabId() {
|
|
157
|
+
return this._tabId;
|
|
158
|
+
}
|
|
159
|
+
isSupported() {
|
|
160
|
+
return this._channel !== null;
|
|
161
|
+
}
|
|
162
|
+
broadcast(type, payload) {
|
|
163
|
+
this._channel?.postMessage({ type, payload, sourceTabId: this._tabId });
|
|
164
|
+
}
|
|
165
|
+
destroy() {
|
|
166
|
+
this._channel?.close();
|
|
167
|
+
this._channel = null;
|
|
168
|
+
}
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
// src/session/concurrent-session.service.ts
|
|
172
|
+
var JoopConcurrentSessionService = class {
|
|
173
|
+
constructor(_channelName = "joop-concurrent-session", _heartbeatMs = 5e3) {
|
|
174
|
+
this._channelName = _channelName;
|
|
175
|
+
this._heartbeatMs = _heartbeatMs;
|
|
176
|
+
}
|
|
177
|
+
_channelName;
|
|
178
|
+
_heartbeatMs;
|
|
179
|
+
_sessionId = crypto.randomUUID();
|
|
180
|
+
_channel = null;
|
|
181
|
+
_heartbeatTimer = null;
|
|
182
|
+
_subject = new JoopSubject();
|
|
183
|
+
events$() {
|
|
184
|
+
return this._subject.asObservable();
|
|
185
|
+
}
|
|
186
|
+
get sessionId() {
|
|
187
|
+
return this._sessionId;
|
|
188
|
+
}
|
|
189
|
+
start() {
|
|
190
|
+
if (typeof BroadcastChannel === "undefined") return;
|
|
191
|
+
this._channel = new BroadcastChannel(this._channelName);
|
|
192
|
+
this._channel.onmessage = (e) => {
|
|
193
|
+
if (e.data.sessionId !== this._sessionId) {
|
|
194
|
+
this._subject.next({ type: "duplicate-detected", sessionId: e.data.sessionId, timestamp: Date.now() });
|
|
195
|
+
}
|
|
196
|
+
};
|
|
197
|
+
this._heartbeatTimer = setInterval(() => {
|
|
198
|
+
this._channel?.postMessage({ type: "heartbeat", sessionId: this._sessionId, timestamp: Date.now() });
|
|
199
|
+
}, this._heartbeatMs);
|
|
200
|
+
}
|
|
201
|
+
stop() {
|
|
202
|
+
if (this._heartbeatTimer) {
|
|
203
|
+
clearInterval(this._heartbeatTimer);
|
|
204
|
+
this._heartbeatTimer = null;
|
|
205
|
+
}
|
|
206
|
+
this._channel?.close();
|
|
207
|
+
this._channel = null;
|
|
208
|
+
}
|
|
209
|
+
};
|
|
210
|
+
|
|
211
|
+
// src/session/idle.service.ts
|
|
212
|
+
var DEFAULT_EVENTS = ["mousemove", "keydown", "mousedown", "scroll", "touchstart", "wheel"];
|
|
213
|
+
var JoopIdleService = class {
|
|
214
|
+
_state$ = new JoopBehaviorSubject("active");
|
|
215
|
+
_idleTimer = null;
|
|
216
|
+
_expiredTimer = null;
|
|
217
|
+
_listeners = [];
|
|
218
|
+
_cfg = null;
|
|
219
|
+
_lastActivity = Date.now();
|
|
220
|
+
start(config) {
|
|
221
|
+
this.stop();
|
|
222
|
+
this._cfg = config;
|
|
223
|
+
this._state$.next("active");
|
|
224
|
+
const events = config.events ?? DEFAULT_EVENTS;
|
|
225
|
+
const reset = () => this._reset();
|
|
226
|
+
for (const ev of events) {
|
|
227
|
+
document.addEventListener(ev, reset, { passive: true });
|
|
228
|
+
this._listeners.push(() => document.removeEventListener(ev, reset));
|
|
229
|
+
}
|
|
230
|
+
this._scheduleIdle();
|
|
231
|
+
}
|
|
232
|
+
stop() {
|
|
233
|
+
this._clearTimers();
|
|
234
|
+
for (const remove of this._listeners) remove();
|
|
235
|
+
this._listeners = [];
|
|
236
|
+
this._cfg = null;
|
|
237
|
+
this._state$.next("active");
|
|
238
|
+
}
|
|
239
|
+
reset() {
|
|
240
|
+
this._reset();
|
|
241
|
+
}
|
|
242
|
+
isIdle() {
|
|
243
|
+
return this._state$.getValue() !== "active";
|
|
244
|
+
}
|
|
245
|
+
getState() {
|
|
246
|
+
return this._state$.getValue();
|
|
247
|
+
}
|
|
248
|
+
idleMs() {
|
|
249
|
+
return Date.now() - this._lastActivity;
|
|
250
|
+
}
|
|
251
|
+
state$() {
|
|
252
|
+
return this._state$.asObservable();
|
|
253
|
+
}
|
|
254
|
+
onIdle(handler) {
|
|
255
|
+
return this._state$.subscribe((s) => s === "idle" && handler());
|
|
256
|
+
}
|
|
257
|
+
onActive(handler) {
|
|
258
|
+
return this._state$.subscribe((s) => s === "active" && handler());
|
|
259
|
+
}
|
|
260
|
+
onExpired(handler) {
|
|
261
|
+
return this._state$.subscribe((s) => s === "expired" && handler());
|
|
262
|
+
}
|
|
263
|
+
_reset() {
|
|
264
|
+
this._lastActivity = Date.now();
|
|
265
|
+
if (this._state$.getValue() !== "active") this._state$.next("active");
|
|
266
|
+
this._clearTimers();
|
|
267
|
+
this._scheduleIdle();
|
|
268
|
+
}
|
|
269
|
+
_scheduleIdle() {
|
|
270
|
+
if (!this._cfg) return;
|
|
271
|
+
this._idleTimer = setTimeout(() => {
|
|
272
|
+
this._state$.next("idle");
|
|
273
|
+
if (this._cfg?.expiredMs) {
|
|
274
|
+
this._expiredTimer = setTimeout(() => this._state$.next("expired"), this._cfg.expiredMs);
|
|
275
|
+
}
|
|
276
|
+
}, this._cfg.idleMs);
|
|
277
|
+
}
|
|
278
|
+
_clearTimers() {
|
|
279
|
+
if (this._idleTimer) {
|
|
280
|
+
clearTimeout(this._idleTimer);
|
|
281
|
+
this._idleTimer = null;
|
|
282
|
+
}
|
|
283
|
+
if (this._expiredTimer) {
|
|
284
|
+
clearTimeout(this._expiredTimer);
|
|
285
|
+
this._expiredTimer = null;
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
};
|
|
289
|
+
|
|
290
|
+
export { JoopConcurrentSessionService, JoopIdleService, JoopMultiTabSync, JoopSessionTimeoutService };
|
|
291
|
+
//# sourceMappingURL=index.mjs.map
|
|
292
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/events/index.ts","../../src/constants/index.ts","../../src/session/session-timeout.service.ts","../../src/session/multi-tab-sync.service.ts","../../src/session/concurrent-session.service.ts","../../src/session/idle.service.ts"],"names":[],"mappings":"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","file":"index.mjs","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","export const DEFAULT_REQUEST_TIMEOUT = 30000;\nexport const DEFAULT_SESSION_TIMEOUT = 300000;\nexport const DEFAULT_SESSION_WAIT_TIMEOUT = 60000;\nexport const PAGE_TOKEN_KEY = 'pageToken';\nexport const DECRYPTION_FAILED = 'Response decryption failed';\nexport const SESSION_STORAGE_KEY = 'joopSession';\n","import { JoopSubject, JoopObservable } from '../events';\nimport { JoopAuthService } from '../auth/auth.service';\nimport { JoopClientProfile } from '../profile/client-profile.service';\nimport { JoopAesService } from '../encryption/aes.service';\nimport { JoopScopeMapService } from '../storage/scope-map.service';\nimport { JoopScopeType } from '../enums';\nimport { SESSION_STORAGE_KEY } from '../constants';\n\ntype SessionPhase = 'idle' | 'waiting' | 'expired';\n\nexport interface JoopSessionEvent {\n type: 'warning' | 'logout';\n}\n\n/**\n * Framework-agnostic session timeout manager.\n *\n * Two-stage model:\n * 1. After `timeout` ms of inactivity → emits 'warning' event (show a dialog)\n * 2. After an additional `waitTimeout` ms → emits 'logout' event (force logout)\n *\n * The host app is responsible for showing the warning UI and calling\n * `extendSession()` if the user responds. When 'logout' fires, call `clearSession()`.\n */\nexport class JoopSessionTimeoutService {\n private readonly _event$ = new JoopSubject<JoopSessionEvent>();\n private _mainTimer: ReturnType<typeof setTimeout> | undefined;\n private _waitTimer: ReturnType<typeof setTimeout> | undefined;\n private _phase: SessionPhase = 'idle';\n private _isSessionExtended = false;\n\n constructor(\n private readonly _auth: JoopAuthService,\n private readonly _profile: JoopClientProfile,\n private readonly _aes: JoopAesService,\n private readonly _scope: JoopScopeMapService\n ) {}\n\n /** Subscribe to session events (warning / logout). */\n events$(): JoopObservable<JoopSessionEvent> {\n return this._event$.asObservable();\n }\n\n /**\n * Called after each API response to reset / start the countdown.\n * Pass the set of service IDs that should NOT reset the timer.\n */\n tick(currentServiceId: string, ignoreServices: string[] = []): void {\n const session = this._profile.timeoutInfo?.session;\n if (!session?.enable) return;\n if (!this._auth.isLoggedIn()) return;\n\n const allIgnored = [...ignoreServices];\n const shouldIgnore = allIgnored.includes(currentServiceId) && !this._isSessionExtended;\n if (shouldIgnore) return;\n\n this._isSessionExtended = false;\n this._startMainTimer(session.timeout, session.waitTimeout);\n }\n\n /** User clicked \"stay logged in\" — reset timer without counting as a new request. */\n extendSession(): void {\n this._isSessionExtended = true;\n const session = this._profile.timeoutInfo?.session;\n if (session) this._startMainTimer(session.timeout, session.waitTimeout);\n }\n\n /** Clear all timers and fully reset session state. */\n clearSession(): void {\n this._stop();\n this._profile.clearSession();\n this._aes.clearKeys();\n this._scope.clearPage();\n this._scope.clearSession();\n this._auth.logout();\n this._phase = 'idle';\n if (typeof localStorage !== 'undefined') {\n localStorage.removeItem(SESSION_STORAGE_KEY);\n }\n }\n\n // ─────────── private ───────────\n\n private _startMainTimer(timeout: number, waitTimeout: number): void {\n this._stop();\n this._phase = 'idle';\n this._mainTimer = setTimeout(() => {\n this._phase = 'waiting';\n this._event$.next({ type: 'warning' });\n this._waitTimer = setTimeout(() => {\n this._phase = 'expired';\n this._event$.next({ type: 'logout' });\n }, waitTimeout);\n }, timeout);\n }\n\n private _stop(): void {\n clearTimeout(this._mainTimer);\n clearTimeout(this._waitTimer);\n this._mainTimer = undefined;\n this._waitTimer = undefined;\n }\n\n get phase(): SessionPhase { return this._phase; }\n}\n","import { JoopSubject } from '../events';\n\nexport type JoopTabEventType = 'logout' | 'login' | 'session-warning' | 'token-refresh' | 'custom';\n\nexport interface JoopTabEvent {\n type: JoopTabEventType;\n payload?: unknown;\n sourceTabId: string;\n}\n\nexport class JoopMultiTabSync {\n private _channel: BroadcastChannel | null = null;\n private _tabId = crypto.randomUUID();\n private _subject = new JoopSubject<JoopTabEvent>();\n\n constructor(channelName = 'joop-session-sync') {\n if (typeof BroadcastChannel !== 'undefined') {\n this._channel = new BroadcastChannel(channelName);\n this._channel.onmessage = (e: MessageEvent<JoopTabEvent>) => {\n if (e.data.sourceTabId !== this._tabId) this._subject.next(e.data);\n };\n }\n }\n\n events$() { return this._subject.asObservable(); }\n get tabId(): string { return this._tabId; }\n isSupported(): boolean { return this._channel !== null; }\n\n broadcast(type: JoopTabEventType, payload?: unknown): void {\n this._channel?.postMessage({ type, payload, sourceTabId: this._tabId } satisfies JoopTabEvent);\n }\n\n destroy(): void { this._channel?.close(); this._channel = null; }\n}\n","import { JoopSubject } from '../events';\n\nexport interface JoopConcurrentSessionEvent {\n type: 'duplicate-detected' | 'heartbeat';\n sessionId: string;\n timestamp: number;\n}\n\nexport class JoopConcurrentSessionService {\n private _sessionId = crypto.randomUUID();\n private _channel: BroadcastChannel | null = null;\n private _heartbeatTimer: ReturnType<typeof setInterval> | null = null;\n private _subject = new JoopSubject<JoopConcurrentSessionEvent>();\n\n constructor(\n private readonly _channelName = 'joop-concurrent-session',\n private readonly _heartbeatMs = 5_000\n ) {}\n\n events$() { return this._subject.asObservable(); }\n get sessionId(): string { return this._sessionId; }\n\n start(): void {\n if (typeof BroadcastChannel === 'undefined') return;\n this._channel = new BroadcastChannel(this._channelName);\n this._channel.onmessage = (e: MessageEvent<JoopConcurrentSessionEvent>) => {\n if (e.data.sessionId !== this._sessionId) {\n this._subject.next({ type: 'duplicate-detected', sessionId: e.data.sessionId, timestamp: Date.now() });\n }\n };\n this._heartbeatTimer = setInterval(() => {\n this._channel?.postMessage({ type: 'heartbeat', sessionId: this._sessionId, timestamp: Date.now() });\n }, this._heartbeatMs);\n }\n\n stop(): void {\n if (this._heartbeatTimer) { clearInterval(this._heartbeatTimer); this._heartbeatTimer = null; }\n this._channel?.close();\n this._channel = null;\n }\n}\n","import { JoopBehaviorSubject } from '../events';\n\nexport type JoopIdleState = 'active' | 'idle' | 'expired';\n\nexport interface JoopIdleConfig {\n idleMs: number; // ms of inactivity before idle\n expiredMs?: number; // ms after idle before expired (optional)\n events?: string[]; // DOM events to reset the timer\n}\n\nconst DEFAULT_EVENTS = ['mousemove', 'keydown', 'mousedown', 'scroll', 'touchstart', 'wheel'];\n\nexport class JoopIdleService {\n private _state$ = new JoopBehaviorSubject<JoopIdleState>('active');\n private _idleTimer: ReturnType<typeof setTimeout> | null = null;\n private _expiredTimer: ReturnType<typeof setTimeout> | null = null;\n private _listeners: Array<() => void> = [];\n private _cfg: JoopIdleConfig | null = null;\n private _lastActivity = Date.now();\n\n start(config: JoopIdleConfig): void {\n this.stop();\n this._cfg = config;\n this._state$.next('active');\n const events = config.events ?? DEFAULT_EVENTS;\n const reset = () => this._reset();\n for (const ev of events) {\n document.addEventListener(ev, reset, { passive: true });\n this._listeners.push(() => document.removeEventListener(ev, reset));\n }\n this._scheduleIdle();\n }\n\n stop(): void {\n this._clearTimers();\n for (const remove of this._listeners) remove();\n this._listeners = [];\n this._cfg = null;\n this._state$.next('active');\n }\n\n reset(): void { this._reset(); }\n isIdle(): boolean { return this._state$.getValue() !== 'active'; }\n getState(): JoopIdleState { return this._state$.getValue(); }\n idleMs(): number { return Date.now() - this._lastActivity; }\n state$() { return this._state$.asObservable(); }\n\n onIdle(handler: () => void): () => void {\n return this._state$.subscribe(s => s === 'idle' && handler());\n }\n\n onActive(handler: () => void): () => void {\n return this._state$.subscribe(s => s === 'active' && handler());\n }\n\n onExpired(handler: () => void): () => void {\n return this._state$.subscribe(s => s === 'expired' && handler());\n }\n\n private _reset(): void {\n this._lastActivity = Date.now();\n if (this._state$.getValue() !== 'active') this._state$.next('active');\n this._clearTimers();\n this._scheduleIdle();\n }\n\n private _scheduleIdle(): void {\n if (!this._cfg) return;\n this._idleTimer = setTimeout(() => {\n this._state$.next('idle');\n if (this._cfg?.expiredMs) {\n this._expiredTimer = setTimeout(() => this._state$.next('expired'), this._cfg.expiredMs);\n }\n }, this._cfg.idleMs);\n }\n\n private _clearTimers(): void {\n if (this._idleTimer) { clearTimeout(this._idleTimer); this._idleTimer = null; }\n if (this._expiredTimer) { clearTimeout(this._expiredTimer); this._expiredTimer = null; }\n }\n}\n"]}
|