joopjs 2.0.5 → 2.1.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.
Files changed (146) hide show
  1. package/.claude/skills/auth.md +235 -0
  2. package/.claude/skills/banking.md +377 -0
  3. package/.claude/skills/encryption.md +265 -0
  4. package/.claude/skills/finance.md +248 -0
  5. package/.claude/skills/observables.md +270 -0
  6. package/.claude/skills/security.md +240 -0
  7. package/.claude/skills/setup.md +196 -0
  8. package/.cursor/rules/joopjs.mdc +150 -0
  9. package/.github/copilot-instructions.md +143 -0
  10. package/.windsurf/rules/joopjs.md +226 -0
  11. package/CHANGELOG.md +81 -0
  12. package/README.md +47 -7
  13. package/ai-rules/AGENTS.md +241 -0
  14. package/ai-rules/GEMINI.md +183 -0
  15. package/dist/ai/index.js +15 -3
  16. package/dist/ai/index.js.map +1 -1
  17. package/dist/ai/index.mjs +15 -3
  18. package/dist/ai/index.mjs.map +1 -1
  19. package/dist/analytics/index.js +10 -2
  20. package/dist/analytics/index.js.map +1 -1
  21. package/dist/analytics/index.mjs +10 -2
  22. package/dist/analytics/index.mjs.map +1 -1
  23. package/dist/angular/index.d.mts +98 -27
  24. package/dist/angular/index.d.ts +98 -27
  25. package/dist/angular/index.js +44 -0
  26. package/dist/angular/index.js.map +1 -1
  27. package/dist/angular/index.mjs +39 -1
  28. package/dist/angular/index.mjs.map +1 -1
  29. package/dist/api/index.js +15 -3
  30. package/dist/api/index.js.map +1 -1
  31. package/dist/api/index.mjs +15 -3
  32. package/dist/api/index.mjs.map +1 -1
  33. package/dist/auth/index.js +15 -3
  34. package/dist/auth/index.js.map +1 -1
  35. package/dist/auth/index.mjs +15 -3
  36. package/dist/auth/index.mjs.map +1 -1
  37. package/dist/banking/index.js +15 -3
  38. package/dist/banking/index.js.map +1 -1
  39. package/dist/banking/index.mjs +15 -3
  40. package/dist/banking/index.mjs.map +1 -1
  41. package/dist/cache/index.js +15 -3
  42. package/dist/cache/index.js.map +1 -1
  43. package/dist/cache/index.mjs +15 -3
  44. package/dist/cache/index.mjs.map +1 -1
  45. package/dist/{index-DFqEoX_l.d.ts → consent.service-CIHNtx9h.d.ts} +1 -2
  46. package/dist/{index-B_ksKpS1.d.mts → consent.service-DQ-JAEJx.d.mts} +1 -2
  47. package/dist/core/index.d.mts +34 -1
  48. package/dist/core/index.d.ts +34 -1
  49. package/dist/core/index.js +56 -5
  50. package/dist/core/index.js.map +1 -1
  51. package/dist/core/index.mjs +54 -6
  52. package/dist/core/index.mjs.map +1 -1
  53. package/dist/deeplink/index.js +15 -3
  54. package/dist/deeplink/index.js.map +1 -1
  55. package/dist/deeplink/index.mjs +15 -3
  56. package/dist/deeplink/index.mjs.map +1 -1
  57. package/dist/device/index.js +15 -3
  58. package/dist/device/index.js.map +1 -1
  59. package/dist/device/index.mjs +15 -3
  60. package/dist/device/index.mjs.map +1 -1
  61. package/dist/forms/index.js +15 -3
  62. package/dist/forms/index.js.map +1 -1
  63. package/dist/forms/index.mjs +15 -3
  64. package/dist/forms/index.mjs.map +1 -1
  65. package/dist/i18n/index.js +15 -3
  66. package/dist/i18n/index.js.map +1 -1
  67. package/dist/i18n/index.mjs +15 -3
  68. package/dist/i18n/index.mjs.map +1 -1
  69. package/dist/index.d.mts +2 -2
  70. package/dist/index.d.ts +2 -2
  71. package/dist/index.js +50 -8
  72. package/dist/index.js.map +1 -1
  73. package/dist/index.mjs +50 -8
  74. package/dist/index.mjs.map +1 -1
  75. package/dist/{joop-CA3DMeOO.d.ts → joop-Dim2yEKG.d.ts} +1 -1
  76. package/dist/{joop-Bx7Iwj5p.d.mts → joop-GkQw13f9.d.mts} +1 -1
  77. package/dist/native-bridge/index.js +10 -2
  78. package/dist/native-bridge/index.js.map +1 -1
  79. package/dist/native-bridge/index.mjs +10 -2
  80. package/dist/native-bridge/index.mjs.map +1 -1
  81. package/dist/network/index.js +15 -3
  82. package/dist/network/index.js.map +1 -1
  83. package/dist/network/index.mjs +15 -3
  84. package/dist/network/index.mjs.map +1 -1
  85. package/dist/observability/index.js +15 -3
  86. package/dist/observability/index.js.map +1 -1
  87. package/dist/observability/index.mjs +15 -3
  88. package/dist/observability/index.mjs.map +1 -1
  89. package/dist/pwa/index.js +15 -3
  90. package/dist/pwa/index.js.map +1 -1
  91. package/dist/pwa/index.mjs +15 -3
  92. package/dist/pwa/index.mjs.map +1 -1
  93. package/dist/react/index.d.mts +2 -2
  94. package/dist/react/index.d.ts +2 -2
  95. package/dist/react/index.js +15 -3
  96. package/dist/react/index.js.map +1 -1
  97. package/dist/react/index.mjs +15 -3
  98. package/dist/react/index.mjs.map +1 -1
  99. package/dist/router/index.js +15 -3
  100. package/dist/router/index.js.map +1 -1
  101. package/dist/router/index.mjs +15 -3
  102. package/dist/router/index.mjs.map +1 -1
  103. package/dist/security/index.js +15 -3
  104. package/dist/security/index.js.map +1 -1
  105. package/dist/security/index.mjs +15 -3
  106. package/dist/security/index.mjs.map +1 -1
  107. package/dist/session/index.js +15 -3
  108. package/dist/session/index.js.map +1 -1
  109. package/dist/session/index.mjs +15 -3
  110. package/dist/session/index.mjs.map +1 -1
  111. package/dist/state/index.js +15 -3
  112. package/dist/state/index.js.map +1 -1
  113. package/dist/state/index.mjs +15 -3
  114. package/dist/state/index.mjs.map +1 -1
  115. package/dist/storage/index.js +15 -3
  116. package/dist/storage/index.js.map +1 -1
  117. package/dist/storage/index.mjs +15 -3
  118. package/dist/storage/index.mjs.map +1 -1
  119. package/dist/sync/index.js +15 -3
  120. package/dist/sync/index.js.map +1 -1
  121. package/dist/sync/index.mjs +15 -3
  122. package/dist/sync/index.mjs.map +1 -1
  123. package/dist/theme/index.js +15 -3
  124. package/dist/theme/index.js.map +1 -1
  125. package/dist/theme/index.mjs +15 -3
  126. package/dist/theme/index.mjs.map +1 -1
  127. package/dist/ui/index.js +15 -3
  128. package/dist/ui/index.js.map +1 -1
  129. package/dist/ui/index.mjs +15 -3
  130. package/dist/ui/index.mjs.map +1 -1
  131. package/dist/utilities/index.js +46 -4
  132. package/dist/utilities/index.js.map +1 -1
  133. package/dist/utilities/index.mjs +46 -4
  134. package/dist/utilities/index.mjs.map +1 -1
  135. package/dist/vue/index.d.mts +2 -2
  136. package/dist/vue/index.d.ts +2 -2
  137. package/dist/vue/index.js +15 -3
  138. package/dist/vue/index.js.map +1 -1
  139. package/dist/vue/index.mjs +15 -3
  140. package/dist/vue/index.mjs.map +1 -1
  141. package/dist/workflow/index.js +15 -3
  142. package/dist/workflow/index.js.map +1 -1
  143. package/dist/workflow/index.mjs +15 -3
  144. package/dist/workflow/index.mjs.map +1 -1
  145. package/package.json +96 -32
  146. package/scripts/setup-ai.mjs +133 -0
@@ -1 +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"]}
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 * Reports a subscriber that threw during emission, without aborting delivery\n * to the remaining subscribers. Defaults to console.error; override to route\n * to your own logger (e.g. in a banking app where dropped events matter).\n */\nlet _onListenerError: (error: unknown) => void = (error) => {\n // eslint-disable-next-line no-console\n console.error('[joopjs] a subject subscriber threw during emission:', error);\n};\n\n/** Override how subscriber errors are reported during emission. */\nexport function setSubjectErrorHandler(handler: (error: unknown) => void): void {\n _onListenerError = handler;\n}\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 // Snapshot so a subscribe()/unsubscribe() triggered by a listener can't\n // disturb this emission, and isolate each listener so one that throws\n // doesn't deprive later subscribers of the value.\n const listeners = this._listeners.slice();\n for (const listener of listeners) {\n try {\n listener(value);\n } catch (error) {\n _onListenerError(error);\n }\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 try {\n listener(this._value);\n } catch (error) {\n _onListenerError(error);\n }\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"]}
@@ -1,4 +1,7 @@
1
1
  // src/events/index.ts
2
+ var _onListenerError = (error) => {
3
+ console.error("[joopjs] a subject subscriber threw during emission:", error);
4
+ };
2
5
  var JoopSubject = class {
3
6
  _listeners = [];
4
7
  subscribe(listener) {
@@ -8,8 +11,13 @@ var JoopSubject = class {
8
11
  };
9
12
  }
10
13
  next(value) {
11
- for (const listener of this._listeners) {
12
- listener(value);
14
+ const listeners = this._listeners.slice();
15
+ for (const listener of listeners) {
16
+ try {
17
+ listener(value);
18
+ } catch (error) {
19
+ _onListenerError(error);
20
+ }
13
21
  }
14
22
  }
15
23
  asObservable() {
@@ -30,7 +38,11 @@ var JoopBehaviorSubject = class extends JoopSubject {
30
38
  super.next(value);
31
39
  }
32
40
  subscribe(listener) {
33
- listener(this._value);
41
+ try {
42
+ listener(this._value);
43
+ } catch (error) {
44
+ _onListenerError(error);
45
+ }
34
46
  return super.subscribe(listener);
35
47
  }
36
48
  asObservable() {
@@ -1 +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"]}
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 * Reports a subscriber that threw during emission, without aborting delivery\n * to the remaining subscribers. Defaults to console.error; override to route\n * to your own logger (e.g. in a banking app where dropped events matter).\n */\nlet _onListenerError: (error: unknown) => void = (error) => {\n // eslint-disable-next-line no-console\n console.error('[joopjs] a subject subscriber threw during emission:', error);\n};\n\n/** Override how subscriber errors are reported during emission. */\nexport function setSubjectErrorHandler(handler: (error: unknown) => void): void {\n _onListenerError = handler;\n}\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 // Snapshot so a subscribe()/unsubscribe() triggered by a listener can't\n // disturb this emission, and isolate each listener so one that throws\n // doesn't deprive later subscribers of the value.\n const listeners = this._listeners.slice();\n for (const listener of listeners) {\n try {\n listener(value);\n } catch (error) {\n _onListenerError(error);\n }\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 try {\n listener(this._value);\n } catch (error) {\n _onListenerError(error);\n }\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"]}
@@ -1,6 +1,9 @@
1
1
  'use strict';
2
2
 
3
3
  // src/events/index.ts
4
+ var _onListenerError = (error) => {
5
+ console.error("[joopjs] a subject subscriber threw during emission:", error);
6
+ };
4
7
  var JoopSubject = class {
5
8
  _listeners = [];
6
9
  subscribe(listener) {
@@ -10,8 +13,13 @@ var JoopSubject = class {
10
13
  };
11
14
  }
12
15
  next(value) {
13
- for (const listener of this._listeners) {
14
- listener(value);
16
+ const listeners = this._listeners.slice();
17
+ for (const listener of listeners) {
18
+ try {
19
+ listener(value);
20
+ } catch (error) {
21
+ _onListenerError(error);
22
+ }
15
23
  }
16
24
  }
17
25
  asObservable() {
@@ -32,7 +40,11 @@ var JoopBehaviorSubject = class extends JoopSubject {
32
40
  super.next(value);
33
41
  }
34
42
  subscribe(listener) {
35
- listener(this._value);
43
+ try {
44
+ listener(this._value);
45
+ } catch (error) {
46
+ _onListenerError(error);
47
+ }
36
48
  return super.subscribe(listener);
37
49
  }
38
50
  asObservable() {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/events/index.ts","../../src/state/observable-store.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","import { JoopBehaviorSubject } from '../events';\n\nexport type JoopReducer<S> = (state: S, payload: unknown) => S;\n\nexport interface JoopStoreConfig<S> {\n state: S;\n reducers?: Record<string, JoopReducer<S>>;\n maxHistory?: number;\n}\n\nexport interface JoopAction {\n type: string;\n payload?: unknown;\n}\n\nexport class JoopStore<S extends Record<string, unknown>> {\n private _state$: JoopBehaviorSubject<S>;\n private _reducers: Record<string, JoopReducer<S>>;\n private _history: S[];\n private _future: S[] = [];\n private _maxHistory: number;\n\n constructor(config: JoopStoreConfig<S>) {\n this._state$ = new JoopBehaviorSubject<S>(config.state);\n this._reducers = config.reducers ?? {};\n this._maxHistory = config.maxHistory ?? 50;\n this._history = [config.state];\n }\n\n getState(): S { return this._state$.getValue(); }\n\n dispatch(type: string, payload?: unknown): void {\n const reducer = this._reducers[type];\n if (!reducer) throw new Error(`JoopStore: no reducer for action '${type}'`);\n\n const current = this._state$.getValue();\n const next = reducer(current, payload);\n if (next === current) return;\n\n this._history.push(current);\n if (this._history.length > this._maxHistory) this._history.shift();\n this._future = [];\n this._state$.next(next);\n }\n\n /** Add a reducer after construction */\n addReducer(type: string, reducer: JoopReducer<S>): void { this._reducers[type] = reducer; }\n\n /** Observable of the entire state */\n state$() { return this._state$.asObservable(); }\n\n /** Observable of a derived slice — only emits when the selected value changes */\n select<T>(selector: (state: S) => T) {\n let lastValue: T | typeof _UNSET = _UNSET;\n const subject = new JoopBehaviorSubject<T>(selector(this.getState()));\n this._state$.subscribe(s => {\n const v = selector(s);\n if (v !== lastValue) { lastValue = v; subject.next(v); }\n });\n return subject.asObservable();\n }\n\n subscribe(handler: (state: S) => void): () => void {\n return this._state$.subscribe(handler);\n }\n\n undo(): void {\n if (!this.canUndo()) return;\n const prev = this._history.pop()!;\n this._future.push(this._state$.getValue());\n this._state$.next(prev);\n }\n\n redo(): void {\n if (!this.canRedo()) return;\n const next = this._future.pop()!;\n this._history.push(this._state$.getValue());\n this._state$.next(next);\n }\n\n canUndo(): boolean { return this._history.length > 1; }\n canRedo(): boolean { return this._future.length > 0; }\n\n reset(): void {\n const initial = this._history[0];\n this._history = [initial];\n this._future = [];\n this._state$.next(initial);\n }\n}\n\nconst _UNSET = Symbol('unset');\n\nexport function createStore<S extends Record<string, unknown>>(config: JoopStoreConfig<S>): JoopStore<S> {\n return new JoopStore(config);\n}\n\n// ─── Slice helper ───────────────────────────────────────────────────────────\n\nexport interface JoopSliceConfig<S, K extends keyof S> {\n key: K;\n reducers: Record<string, (slice: S[K], payload: unknown) => S[K]>;\n}\n\n/** Creates reducers scoped to a sub-key of the store state */\nexport function createSlice<S extends Record<string, unknown>, K extends keyof S>(\n cfg: JoopSliceConfig<S, K>\n): Record<string, JoopReducer<S>> {\n const out: Record<string, JoopReducer<S>> = {};\n for (const [type, reducer] of Object.entries(cfg.reducers)) {\n out[`${String(cfg.key)}/${type}`] = (state, payload) => ({\n ...state,\n [cfg.key]: reducer(state[cfg.key] as S[K], payload),\n });\n }\n return out;\n}\n"]}
1
+ {"version":3,"sources":["../../src/events/index.ts","../../src/state/observable-store.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 * Reports a subscriber that threw during emission, without aborting delivery\n * to the remaining subscribers. Defaults to console.error; override to route\n * to your own logger (e.g. in a banking app where dropped events matter).\n */\nlet _onListenerError: (error: unknown) => void = (error) => {\n // eslint-disable-next-line no-console\n console.error('[joopjs] a subject subscriber threw during emission:', error);\n};\n\n/** Override how subscriber errors are reported during emission. */\nexport function setSubjectErrorHandler(handler: (error: unknown) => void): void {\n _onListenerError = handler;\n}\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 // Snapshot so a subscribe()/unsubscribe() triggered by a listener can't\n // disturb this emission, and isolate each listener so one that throws\n // doesn't deprive later subscribers of the value.\n const listeners = this._listeners.slice();\n for (const listener of listeners) {\n try {\n listener(value);\n } catch (error) {\n _onListenerError(error);\n }\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 try {\n listener(this._value);\n } catch (error) {\n _onListenerError(error);\n }\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 } from '../events';\n\nexport type JoopReducer<S> = (state: S, payload: unknown) => S;\n\nexport interface JoopStoreConfig<S> {\n state: S;\n reducers?: Record<string, JoopReducer<S>>;\n maxHistory?: number;\n}\n\nexport interface JoopAction {\n type: string;\n payload?: unknown;\n}\n\nexport class JoopStore<S extends Record<string, unknown>> {\n private _state$: JoopBehaviorSubject<S>;\n private _reducers: Record<string, JoopReducer<S>>;\n private _history: S[];\n private _future: S[] = [];\n private _maxHistory: number;\n\n constructor(config: JoopStoreConfig<S>) {\n this._state$ = new JoopBehaviorSubject<S>(config.state);\n this._reducers = config.reducers ?? {};\n this._maxHistory = config.maxHistory ?? 50;\n this._history = [config.state];\n }\n\n getState(): S { return this._state$.getValue(); }\n\n dispatch(type: string, payload?: unknown): void {\n const reducer = this._reducers[type];\n if (!reducer) throw new Error(`JoopStore: no reducer for action '${type}'`);\n\n const current = this._state$.getValue();\n const next = reducer(current, payload);\n if (next === current) return;\n\n this._history.push(current);\n if (this._history.length > this._maxHistory) this._history.shift();\n this._future = [];\n this._state$.next(next);\n }\n\n /** Add a reducer after construction */\n addReducer(type: string, reducer: JoopReducer<S>): void { this._reducers[type] = reducer; }\n\n /** Observable of the entire state */\n state$() { return this._state$.asObservable(); }\n\n /** Observable of a derived slice — only emits when the selected value changes */\n select<T>(selector: (state: S) => T) {\n let lastValue: T | typeof _UNSET = _UNSET;\n const subject = new JoopBehaviorSubject<T>(selector(this.getState()));\n this._state$.subscribe(s => {\n const v = selector(s);\n if (v !== lastValue) { lastValue = v; subject.next(v); }\n });\n return subject.asObservable();\n }\n\n subscribe(handler: (state: S) => void): () => void {\n return this._state$.subscribe(handler);\n }\n\n undo(): void {\n if (!this.canUndo()) return;\n const prev = this._history.pop()!;\n this._future.push(this._state$.getValue());\n this._state$.next(prev);\n }\n\n redo(): void {\n if (!this.canRedo()) return;\n const next = this._future.pop()!;\n this._history.push(this._state$.getValue());\n this._state$.next(next);\n }\n\n canUndo(): boolean { return this._history.length > 1; }\n canRedo(): boolean { return this._future.length > 0; }\n\n reset(): void {\n const initial = this._history[0];\n this._history = [initial];\n this._future = [];\n this._state$.next(initial);\n }\n}\n\nconst _UNSET = Symbol('unset');\n\nexport function createStore<S extends Record<string, unknown>>(config: JoopStoreConfig<S>): JoopStore<S> {\n return new JoopStore(config);\n}\n\n// ─── Slice helper ───────────────────────────────────────────────────────────\n\nexport interface JoopSliceConfig<S, K extends keyof S> {\n key: K;\n reducers: Record<string, (slice: S[K], payload: unknown) => S[K]>;\n}\n\n/** Creates reducers scoped to a sub-key of the store state */\nexport function createSlice<S extends Record<string, unknown>, K extends keyof S>(\n cfg: JoopSliceConfig<S, K>\n): Record<string, JoopReducer<S>> {\n const out: Record<string, JoopReducer<S>> = {};\n for (const [type, reducer] of Object.entries(cfg.reducers)) {\n out[`${String(cfg.key)}/${type}`] = (state, payload) => ({\n ...state,\n [cfg.key]: reducer(state[cfg.key] as S[K], payload),\n });\n }\n return out;\n}\n"]}
@@ -1,4 +1,7 @@
1
1
  // src/events/index.ts
2
+ var _onListenerError = (error) => {
3
+ console.error("[joopjs] a subject subscriber threw during emission:", error);
4
+ };
2
5
  var JoopSubject = class {
3
6
  _listeners = [];
4
7
  subscribe(listener) {
@@ -8,8 +11,13 @@ var JoopSubject = class {
8
11
  };
9
12
  }
10
13
  next(value) {
11
- for (const listener of this._listeners) {
12
- listener(value);
14
+ const listeners = this._listeners.slice();
15
+ for (const listener of listeners) {
16
+ try {
17
+ listener(value);
18
+ } catch (error) {
19
+ _onListenerError(error);
20
+ }
13
21
  }
14
22
  }
15
23
  asObservable() {
@@ -30,7 +38,11 @@ var JoopBehaviorSubject = class extends JoopSubject {
30
38
  super.next(value);
31
39
  }
32
40
  subscribe(listener) {
33
- listener(this._value);
41
+ try {
42
+ listener(this._value);
43
+ } catch (error) {
44
+ _onListenerError(error);
45
+ }
34
46
  return super.subscribe(listener);
35
47
  }
36
48
  asObservable() {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/events/index.ts","../../src/state/observable-store.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","import { JoopBehaviorSubject } from '../events';\n\nexport type JoopReducer<S> = (state: S, payload: unknown) => S;\n\nexport interface JoopStoreConfig<S> {\n state: S;\n reducers?: Record<string, JoopReducer<S>>;\n maxHistory?: number;\n}\n\nexport interface JoopAction {\n type: string;\n payload?: unknown;\n}\n\nexport class JoopStore<S extends Record<string, unknown>> {\n private _state$: JoopBehaviorSubject<S>;\n private _reducers: Record<string, JoopReducer<S>>;\n private _history: S[];\n private _future: S[] = [];\n private _maxHistory: number;\n\n constructor(config: JoopStoreConfig<S>) {\n this._state$ = new JoopBehaviorSubject<S>(config.state);\n this._reducers = config.reducers ?? {};\n this._maxHistory = config.maxHistory ?? 50;\n this._history = [config.state];\n }\n\n getState(): S { return this._state$.getValue(); }\n\n dispatch(type: string, payload?: unknown): void {\n const reducer = this._reducers[type];\n if (!reducer) throw new Error(`JoopStore: no reducer for action '${type}'`);\n\n const current = this._state$.getValue();\n const next = reducer(current, payload);\n if (next === current) return;\n\n this._history.push(current);\n if (this._history.length > this._maxHistory) this._history.shift();\n this._future = [];\n this._state$.next(next);\n }\n\n /** Add a reducer after construction */\n addReducer(type: string, reducer: JoopReducer<S>): void { this._reducers[type] = reducer; }\n\n /** Observable of the entire state */\n state$() { return this._state$.asObservable(); }\n\n /** Observable of a derived slice — only emits when the selected value changes */\n select<T>(selector: (state: S) => T) {\n let lastValue: T | typeof _UNSET = _UNSET;\n const subject = new JoopBehaviorSubject<T>(selector(this.getState()));\n this._state$.subscribe(s => {\n const v = selector(s);\n if (v !== lastValue) { lastValue = v; subject.next(v); }\n });\n return subject.asObservable();\n }\n\n subscribe(handler: (state: S) => void): () => void {\n return this._state$.subscribe(handler);\n }\n\n undo(): void {\n if (!this.canUndo()) return;\n const prev = this._history.pop()!;\n this._future.push(this._state$.getValue());\n this._state$.next(prev);\n }\n\n redo(): void {\n if (!this.canRedo()) return;\n const next = this._future.pop()!;\n this._history.push(this._state$.getValue());\n this._state$.next(next);\n }\n\n canUndo(): boolean { return this._history.length > 1; }\n canRedo(): boolean { return this._future.length > 0; }\n\n reset(): void {\n const initial = this._history[0];\n this._history = [initial];\n this._future = [];\n this._state$.next(initial);\n }\n}\n\nconst _UNSET = Symbol('unset');\n\nexport function createStore<S extends Record<string, unknown>>(config: JoopStoreConfig<S>): JoopStore<S> {\n return new JoopStore(config);\n}\n\n// ─── Slice helper ───────────────────────────────────────────────────────────\n\nexport interface JoopSliceConfig<S, K extends keyof S> {\n key: K;\n reducers: Record<string, (slice: S[K], payload: unknown) => S[K]>;\n}\n\n/** Creates reducers scoped to a sub-key of the store state */\nexport function createSlice<S extends Record<string, unknown>, K extends keyof S>(\n cfg: JoopSliceConfig<S, K>\n): Record<string, JoopReducer<S>> {\n const out: Record<string, JoopReducer<S>> = {};\n for (const [type, reducer] of Object.entries(cfg.reducers)) {\n out[`${String(cfg.key)}/${type}`] = (state, payload) => ({\n ...state,\n [cfg.key]: reducer(state[cfg.key] as S[K], payload),\n });\n }\n return out;\n}\n"]}
1
+ {"version":3,"sources":["../../src/events/index.ts","../../src/state/observable-store.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 * Reports a subscriber that threw during emission, without aborting delivery\n * to the remaining subscribers. Defaults to console.error; override to route\n * to your own logger (e.g. in a banking app where dropped events matter).\n */\nlet _onListenerError: (error: unknown) => void = (error) => {\n // eslint-disable-next-line no-console\n console.error('[joopjs] a subject subscriber threw during emission:', error);\n};\n\n/** Override how subscriber errors are reported during emission. */\nexport function setSubjectErrorHandler(handler: (error: unknown) => void): void {\n _onListenerError = handler;\n}\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 // Snapshot so a subscribe()/unsubscribe() triggered by a listener can't\n // disturb this emission, and isolate each listener so one that throws\n // doesn't deprive later subscribers of the value.\n const listeners = this._listeners.slice();\n for (const listener of listeners) {\n try {\n listener(value);\n } catch (error) {\n _onListenerError(error);\n }\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 try {\n listener(this._value);\n } catch (error) {\n _onListenerError(error);\n }\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 } from '../events';\n\nexport type JoopReducer<S> = (state: S, payload: unknown) => S;\n\nexport interface JoopStoreConfig<S> {\n state: S;\n reducers?: Record<string, JoopReducer<S>>;\n maxHistory?: number;\n}\n\nexport interface JoopAction {\n type: string;\n payload?: unknown;\n}\n\nexport class JoopStore<S extends Record<string, unknown>> {\n private _state$: JoopBehaviorSubject<S>;\n private _reducers: Record<string, JoopReducer<S>>;\n private _history: S[];\n private _future: S[] = [];\n private _maxHistory: number;\n\n constructor(config: JoopStoreConfig<S>) {\n this._state$ = new JoopBehaviorSubject<S>(config.state);\n this._reducers = config.reducers ?? {};\n this._maxHistory = config.maxHistory ?? 50;\n this._history = [config.state];\n }\n\n getState(): S { return this._state$.getValue(); }\n\n dispatch(type: string, payload?: unknown): void {\n const reducer = this._reducers[type];\n if (!reducer) throw new Error(`JoopStore: no reducer for action '${type}'`);\n\n const current = this._state$.getValue();\n const next = reducer(current, payload);\n if (next === current) return;\n\n this._history.push(current);\n if (this._history.length > this._maxHistory) this._history.shift();\n this._future = [];\n this._state$.next(next);\n }\n\n /** Add a reducer after construction */\n addReducer(type: string, reducer: JoopReducer<S>): void { this._reducers[type] = reducer; }\n\n /** Observable of the entire state */\n state$() { return this._state$.asObservable(); }\n\n /** Observable of a derived slice — only emits when the selected value changes */\n select<T>(selector: (state: S) => T) {\n let lastValue: T | typeof _UNSET = _UNSET;\n const subject = new JoopBehaviorSubject<T>(selector(this.getState()));\n this._state$.subscribe(s => {\n const v = selector(s);\n if (v !== lastValue) { lastValue = v; subject.next(v); }\n });\n return subject.asObservable();\n }\n\n subscribe(handler: (state: S) => void): () => void {\n return this._state$.subscribe(handler);\n }\n\n undo(): void {\n if (!this.canUndo()) return;\n const prev = this._history.pop()!;\n this._future.push(this._state$.getValue());\n this._state$.next(prev);\n }\n\n redo(): void {\n if (!this.canRedo()) return;\n const next = this._future.pop()!;\n this._history.push(this._state$.getValue());\n this._state$.next(next);\n }\n\n canUndo(): boolean { return this._history.length > 1; }\n canRedo(): boolean { return this._future.length > 0; }\n\n reset(): void {\n const initial = this._history[0];\n this._history = [initial];\n this._future = [];\n this._state$.next(initial);\n }\n}\n\nconst _UNSET = Symbol('unset');\n\nexport function createStore<S extends Record<string, unknown>>(config: JoopStoreConfig<S>): JoopStore<S> {\n return new JoopStore(config);\n}\n\n// ─── Slice helper ───────────────────────────────────────────────────────────\n\nexport interface JoopSliceConfig<S, K extends keyof S> {\n key: K;\n reducers: Record<string, (slice: S[K], payload: unknown) => S[K]>;\n}\n\n/** Creates reducers scoped to a sub-key of the store state */\nexport function createSlice<S extends Record<string, unknown>, K extends keyof S>(\n cfg: JoopSliceConfig<S, K>\n): Record<string, JoopReducer<S>> {\n const out: Record<string, JoopReducer<S>> = {};\n for (const [type, reducer] of Object.entries(cfg.reducers)) {\n out[`${String(cfg.key)}/${type}`] = (state, payload) => ({\n ...state,\n [cfg.key]: reducer(state[cfg.key] as S[K], payload),\n });\n }\n return out;\n}\n"]}
@@ -39,6 +39,9 @@ var JoopScopeMapService = class {
39
39
  };
40
40
 
41
41
  // src/events/index.ts
42
+ var _onListenerError = (error) => {
43
+ console.error("[joopjs] a subject subscriber threw during emission:", error);
44
+ };
42
45
  var JoopSubject = class {
43
46
  _listeners = [];
44
47
  subscribe(listener) {
@@ -48,8 +51,13 @@ var JoopSubject = class {
48
51
  };
49
52
  }
50
53
  next(value) {
51
- for (const listener of this._listeners) {
52
- listener(value);
54
+ const listeners = this._listeners.slice();
55
+ for (const listener of listeners) {
56
+ try {
57
+ listener(value);
58
+ } catch (error) {
59
+ _onListenerError(error);
60
+ }
53
61
  }
54
62
  }
55
63
  asObservable() {
@@ -70,7 +78,11 @@ var JoopBehaviorSubject = class extends JoopSubject {
70
78
  super.next(value);
71
79
  }
72
80
  subscribe(listener) {
73
- listener(this._value);
81
+ try {
82
+ listener(this._value);
83
+ } catch (error) {
84
+ _onListenerError(error);
85
+ }
74
86
  return super.subscribe(listener);
75
87
  }
76
88
  asObservable() {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/storage/scope-map.service.ts","../../src/events/index.ts","../../src/storage/data-storage.service.ts","../../src/storage/indexed-db.service.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import { JoopScopeType } from '../enums';\n\n/**\n * Four-scope in-memory store.\n *\n * | Scope | Lifetime |\n * |---------|--------------------------------|\n * | app | Entire app session |\n * | page | Current page / flow |\n * | screen | Current screen / component |\n * | session | Browser session (survives nav) |\n */\nexport class JoopScopeMapService {\n private _appMap: Record<string, any> = {};\n private _pageMap: Record<string, any> = {};\n private _screenMap: Record<string, any> = {};\n private _sessionMap: Record<string, any> = {};\n\n getMap(scope: JoopScopeType): Record<string, any> {\n switch (scope) {\n case JoopScopeType.App: return this._appMap;\n case JoopScopeType.Page: return this._pageMap;\n case JoopScopeType.Screen: return this._screenMap;\n case JoopScopeType.Session: return this._sessionMap;\n }\n }\n\n clearScreen(): void { this._screenMap = {}; }\n clearPage(): void { this._pageMap = {}; }\n clearSession(): void { this._sessionMap = {}; }\n clearApp(): void { this._appMap = {}; }\n\n clearAll(): void {\n this._appMap = {};\n this._pageMap = {};\n this._screenMap = {};\n this._sessionMap = {};\n }\n}\n","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, JoopObservable } from '../events';\nimport { JoopScopeType } from '../enums';\nimport { JoopScopeMapService } from './scope-map.service';\n\nexport class JoopDataStorage {\n private _menuSubject = new JoopBehaviorSubject<{ menuObj: any[] } | null>(null);\n\n constructor(private readonly _scopeMap: JoopScopeMapService) {}\n\n /** Store a value in the given scope under the given key. */\n set(scope: JoopScopeType, key: string, value: any): void {\n const map = this._scopeMap.getMap(scope);\n map[key] = value;\n }\n\n /** Retrieve a typed value from the given scope. Returns null if not found. */\n get<T>(scope: JoopScopeType, key: string): T | null {\n return this._scopeMap.getMap(scope)[key] ?? null;\n }\n\n /** Remove a single key from the given scope. */\n remove(scope: JoopScopeType, key: string): void {\n delete this._scopeMap.getMap(scope)[key];\n }\n\n /** Retrieve the entire map for a scope (reference, not clone). */\n getScope<T extends Record<string, any>>(scope: JoopScopeType): T {\n return this._scopeMap.getMap(scope) as T;\n }\n\n setMenuData(data: { menuObj: any[] }): void {\n this._menuSubject.next(data);\n }\n\n clearMenuData(): void {\n this._menuSubject.next(null);\n }\n\n menuData$(): JoopObservable<{ menuObj: any[] } | null> {\n return this._menuSubject.asObservable();\n }\n\n getMenuData(): { menuObj: any[] } | null {\n return this._menuSubject.getValue();\n }\n}\n","import { JoopBehaviorSubject } from '../events';\n\nexport interface JoopIdbStoreSchema {\n name: string;\n keyPath?: string;\n autoIncrement?: boolean;\n indexes?: Array<{ name: string; keyPath: string | string[]; unique?: boolean }>;\n}\n\nexport interface JoopIdbConfig {\n name: string;\n version: number;\n stores: JoopIdbStoreSchema[];\n}\n\nexport class JoopIndexedDbService {\n private _db: IDBDatabase | null = null;\n private _ready$ = new JoopBehaviorSubject<boolean>(false);\n\n async open(config: JoopIdbConfig): Promise<void> {\n return new Promise((resolve, reject) => {\n const req = indexedDB.open(config.name, config.version);\n req.onupgradeneeded = (e) => {\n const db = (e.target as IDBOpenDBRequest).result;\n for (const store of config.stores) {\n if (!db.objectStoreNames.contains(store.name)) {\n const os = db.createObjectStore(store.name, { keyPath: store.keyPath, autoIncrement: store.autoIncrement });\n for (const idx of store.indexes ?? []) os.createIndex(idx.name, idx.keyPath, { unique: idx.unique ?? false });\n }\n }\n };\n req.onsuccess = (e) => { this._db = (e.target as IDBOpenDBRequest).result; this._ready$.next(true); resolve(); };\n req.onerror = () => reject(req.error);\n });\n }\n\n close(): void { this._db?.close(); this._db = null; this._ready$.next(false); }\n isOpen(): boolean { return this._db !== null; }\n ready$() { return this._ready$.asObservable(); }\n\n private _store(storeName: string, mode: IDBTransactionMode): IDBObjectStore {\n if (!this._db) throw new Error('JoopIndexedDb: not open');\n return this._db.transaction(storeName, mode).objectStore(storeName);\n }\n\n async get<T>(store: string, key: IDBValidKey): Promise<T | null> {\n return new Promise((res, rej) => {\n const req = this._store(store, 'readonly').get(key);\n req.onsuccess = () => res((req.result as T) ?? null);\n req.onerror = () => rej(req.error);\n });\n }\n\n async set(store: string, value: unknown, key?: IDBValidKey): Promise<IDBValidKey> {\n return new Promise((res, rej) => {\n const req = key !== undefined ? this._store(store, 'readwrite').put(value, key) : this._store(store, 'readwrite').put(value);\n req.onsuccess = () => res(req.result);\n req.onerror = () => rej(req.error);\n });\n }\n\n async delete(store: string, key: IDBValidKey): Promise<void> {\n return new Promise((res, rej) => {\n const req = this._store(store, 'readwrite').delete(key);\n req.onsuccess = () => res();\n req.onerror = () => rej(req.error);\n });\n }\n\n async getAll<T>(store: string): Promise<T[]> {\n return new Promise((res, rej) => {\n const req = this._store(store, 'readonly').getAll();\n req.onsuccess = () => res(req.result as T[]);\n req.onerror = () => rej(req.error);\n });\n }\n\n async getAllKeys(store: string): Promise<IDBValidKey[]> {\n return new Promise((res, rej) => {\n const req = this._store(store, 'readonly').getAllKeys();\n req.onsuccess = () => res(req.result);\n req.onerror = () => rej(req.error);\n });\n }\n\n async query<T>(store: string, indexName: string, range: IDBKeyRange): Promise<T[]> {\n return new Promise((res, rej) => {\n const req = this._store(store, 'readonly').index(indexName).getAll(range);\n req.onsuccess = () => res(req.result as T[]);\n req.onerror = () => rej(req.error);\n });\n }\n\n async count(store: string, range?: IDBKeyRange): Promise<number> {\n return new Promise((res, rej) => {\n const req = range ? this._store(store, 'readonly').count(range) : this._store(store, 'readonly').count();\n req.onsuccess = () => res(req.result);\n req.onerror = () => rej(req.error);\n });\n }\n\n async clear(store: string): Promise<void> {\n return new Promise((res, rej) => {\n const req = this._store(store, 'readwrite').clear();\n req.onsuccess = () => res();\n req.onerror = () => rej(req.error);\n });\n }\n\n async bulkSet(store: string, items: unknown[]): Promise<void> {\n if (!this._db) throw new Error('JoopIndexedDb: not open');\n return new Promise((res, rej) => {\n const tx = this._db!.transaction(store, 'readwrite');\n const os = tx.objectStore(store);\n for (const item of items) os.put(item);\n tx.oncomplete = () => res();\n tx.onerror = () => rej(tx.error);\n });\n }\n\n async deleteDatabase(name: string): Promise<void> {\n this.close();\n return new Promise((res, rej) => {\n const req = indexedDB.deleteDatabase(name);\n req.onsuccess = () => res();\n req.onerror = () => rej(req.error);\n });\n }\n}\n"]}
1
+ {"version":3,"sources":["../../src/storage/scope-map.service.ts","../../src/events/index.ts","../../src/storage/data-storage.service.ts","../../src/storage/indexed-db.service.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import { JoopScopeType } from '../enums';\n\n/**\n * Four-scope in-memory store.\n *\n * | Scope | Lifetime |\n * |---------|--------------------------------|\n * | app | Entire app session |\n * | page | Current page / flow |\n * | screen | Current screen / component |\n * | session | Browser session (survives nav) |\n */\nexport class JoopScopeMapService {\n private _appMap: Record<string, any> = {};\n private _pageMap: Record<string, any> = {};\n private _screenMap: Record<string, any> = {};\n private _sessionMap: Record<string, any> = {};\n\n getMap(scope: JoopScopeType): Record<string, any> {\n switch (scope) {\n case JoopScopeType.App: return this._appMap;\n case JoopScopeType.Page: return this._pageMap;\n case JoopScopeType.Screen: return this._screenMap;\n case JoopScopeType.Session: return this._sessionMap;\n }\n }\n\n clearScreen(): void { this._screenMap = {}; }\n clearPage(): void { this._pageMap = {}; }\n clearSession(): void { this._sessionMap = {}; }\n clearApp(): void { this._appMap = {}; }\n\n clearAll(): void {\n this._appMap = {};\n this._pageMap = {};\n this._screenMap = {};\n this._sessionMap = {};\n }\n}\n","export type Unsubscribe = () => void;\nexport type Listener<T> = (value: T) => void;\n\n/**\n * Reports a subscriber that threw during emission, without aborting delivery\n * to the remaining subscribers. Defaults to console.error; override to route\n * to your own logger (e.g. in a banking app where dropped events matter).\n */\nlet _onListenerError: (error: unknown) => void = (error) => {\n // eslint-disable-next-line no-console\n console.error('[joopjs] a subject subscriber threw during emission:', error);\n};\n\n/** Override how subscriber errors are reported during emission. */\nexport function setSubjectErrorHandler(handler: (error: unknown) => void): void {\n _onListenerError = handler;\n}\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 // Snapshot so a subscribe()/unsubscribe() triggered by a listener can't\n // disturb this emission, and isolate each listener so one that throws\n // doesn't deprive later subscribers of the value.\n const listeners = this._listeners.slice();\n for (const listener of listeners) {\n try {\n listener(value);\n } catch (error) {\n _onListenerError(error);\n }\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 try {\n listener(this._value);\n } catch (error) {\n _onListenerError(error);\n }\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, JoopObservable } from '../events';\nimport { JoopScopeType } from '../enums';\nimport { JoopScopeMapService } from './scope-map.service';\n\nexport class JoopDataStorage {\n private _menuSubject = new JoopBehaviorSubject<{ menuObj: any[] } | null>(null);\n\n constructor(private readonly _scopeMap: JoopScopeMapService) {}\n\n /** Store a value in the given scope under the given key. */\n set(scope: JoopScopeType, key: string, value: any): void {\n const map = this._scopeMap.getMap(scope);\n map[key] = value;\n }\n\n /** Retrieve a typed value from the given scope. Returns null if not found. */\n get<T>(scope: JoopScopeType, key: string): T | null {\n return this._scopeMap.getMap(scope)[key] ?? null;\n }\n\n /** Remove a single key from the given scope. */\n remove(scope: JoopScopeType, key: string): void {\n delete this._scopeMap.getMap(scope)[key];\n }\n\n /** Retrieve the entire map for a scope (reference, not clone). */\n getScope<T extends Record<string, any>>(scope: JoopScopeType): T {\n return this._scopeMap.getMap(scope) as T;\n }\n\n setMenuData(data: { menuObj: any[] }): void {\n this._menuSubject.next(data);\n }\n\n clearMenuData(): void {\n this._menuSubject.next(null);\n }\n\n menuData$(): JoopObservable<{ menuObj: any[] } | null> {\n return this._menuSubject.asObservable();\n }\n\n getMenuData(): { menuObj: any[] } | null {\n return this._menuSubject.getValue();\n }\n}\n","import { JoopBehaviorSubject } from '../events';\n\nexport interface JoopIdbStoreSchema {\n name: string;\n keyPath?: string;\n autoIncrement?: boolean;\n indexes?: Array<{ name: string; keyPath: string | string[]; unique?: boolean }>;\n}\n\nexport interface JoopIdbConfig {\n name: string;\n version: number;\n stores: JoopIdbStoreSchema[];\n}\n\nexport class JoopIndexedDbService {\n private _db: IDBDatabase | null = null;\n private _ready$ = new JoopBehaviorSubject<boolean>(false);\n\n async open(config: JoopIdbConfig): Promise<void> {\n return new Promise((resolve, reject) => {\n const req = indexedDB.open(config.name, config.version);\n req.onupgradeneeded = (e) => {\n const db = (e.target as IDBOpenDBRequest).result;\n for (const store of config.stores) {\n if (!db.objectStoreNames.contains(store.name)) {\n const os = db.createObjectStore(store.name, { keyPath: store.keyPath, autoIncrement: store.autoIncrement });\n for (const idx of store.indexes ?? []) os.createIndex(idx.name, idx.keyPath, { unique: idx.unique ?? false });\n }\n }\n };\n req.onsuccess = (e) => { this._db = (e.target as IDBOpenDBRequest).result; this._ready$.next(true); resolve(); };\n req.onerror = () => reject(req.error);\n });\n }\n\n close(): void { this._db?.close(); this._db = null; this._ready$.next(false); }\n isOpen(): boolean { return this._db !== null; }\n ready$() { return this._ready$.asObservable(); }\n\n private _store(storeName: string, mode: IDBTransactionMode): IDBObjectStore {\n if (!this._db) throw new Error('JoopIndexedDb: not open');\n return this._db.transaction(storeName, mode).objectStore(storeName);\n }\n\n async get<T>(store: string, key: IDBValidKey): Promise<T | null> {\n return new Promise((res, rej) => {\n const req = this._store(store, 'readonly').get(key);\n req.onsuccess = () => res((req.result as T) ?? null);\n req.onerror = () => rej(req.error);\n });\n }\n\n async set(store: string, value: unknown, key?: IDBValidKey): Promise<IDBValidKey> {\n return new Promise((res, rej) => {\n const req = key !== undefined ? this._store(store, 'readwrite').put(value, key) : this._store(store, 'readwrite').put(value);\n req.onsuccess = () => res(req.result);\n req.onerror = () => rej(req.error);\n });\n }\n\n async delete(store: string, key: IDBValidKey): Promise<void> {\n return new Promise((res, rej) => {\n const req = this._store(store, 'readwrite').delete(key);\n req.onsuccess = () => res();\n req.onerror = () => rej(req.error);\n });\n }\n\n async getAll<T>(store: string): Promise<T[]> {\n return new Promise((res, rej) => {\n const req = this._store(store, 'readonly').getAll();\n req.onsuccess = () => res(req.result as T[]);\n req.onerror = () => rej(req.error);\n });\n }\n\n async getAllKeys(store: string): Promise<IDBValidKey[]> {\n return new Promise((res, rej) => {\n const req = this._store(store, 'readonly').getAllKeys();\n req.onsuccess = () => res(req.result);\n req.onerror = () => rej(req.error);\n });\n }\n\n async query<T>(store: string, indexName: string, range: IDBKeyRange): Promise<T[]> {\n return new Promise((res, rej) => {\n const req = this._store(store, 'readonly').index(indexName).getAll(range);\n req.onsuccess = () => res(req.result as T[]);\n req.onerror = () => rej(req.error);\n });\n }\n\n async count(store: string, range?: IDBKeyRange): Promise<number> {\n return new Promise((res, rej) => {\n const req = range ? this._store(store, 'readonly').count(range) : this._store(store, 'readonly').count();\n req.onsuccess = () => res(req.result);\n req.onerror = () => rej(req.error);\n });\n }\n\n async clear(store: string): Promise<void> {\n return new Promise((res, rej) => {\n const req = this._store(store, 'readwrite').clear();\n req.onsuccess = () => res();\n req.onerror = () => rej(req.error);\n });\n }\n\n async bulkSet(store: string, items: unknown[]): Promise<void> {\n if (!this._db) throw new Error('JoopIndexedDb: not open');\n return new Promise((res, rej) => {\n const tx = this._db!.transaction(store, 'readwrite');\n const os = tx.objectStore(store);\n for (const item of items) os.put(item);\n tx.oncomplete = () => res();\n tx.onerror = () => rej(tx.error);\n });\n }\n\n async deleteDatabase(name: string): Promise<void> {\n this.close();\n return new Promise((res, rej) => {\n const req = indexedDB.deleteDatabase(name);\n req.onsuccess = () => res();\n req.onerror = () => rej(req.error);\n });\n }\n}\n"]}
@@ -37,6 +37,9 @@ var JoopScopeMapService = class {
37
37
  };
38
38
 
39
39
  // src/events/index.ts
40
+ var _onListenerError = (error) => {
41
+ console.error("[joopjs] a subject subscriber threw during emission:", error);
42
+ };
40
43
  var JoopSubject = class {
41
44
  _listeners = [];
42
45
  subscribe(listener) {
@@ -46,8 +49,13 @@ var JoopSubject = class {
46
49
  };
47
50
  }
48
51
  next(value) {
49
- for (const listener of this._listeners) {
50
- listener(value);
52
+ const listeners = this._listeners.slice();
53
+ for (const listener of listeners) {
54
+ try {
55
+ listener(value);
56
+ } catch (error) {
57
+ _onListenerError(error);
58
+ }
51
59
  }
52
60
  }
53
61
  asObservable() {
@@ -68,7 +76,11 @@ var JoopBehaviorSubject = class extends JoopSubject {
68
76
  super.next(value);
69
77
  }
70
78
  subscribe(listener) {
71
- listener(this._value);
79
+ try {
80
+ listener(this._value);
81
+ } catch (error) {
82
+ _onListenerError(error);
83
+ }
72
84
  return super.subscribe(listener);
73
85
  }
74
86
  asObservable() {