From 8fa0ea70b26ee4c22bddf78ce53bf47b31569fce Mon Sep 17 00:00:00 2001 From: PS Date: Mon, 4 Nov 2024 12:40:20 +0100 Subject: [PATCH] max history & unregister reset --- packages/core/src/boot.ts | 3 ++ packages/core/src/event/Observable.ts | 41 +++++++++++-------- .../src/event/__tests__/ObservableSpec.ts | 30 ++++++++++++-- packages/core/src/router/ServerRouter.ts | 1 - 4 files changed, 52 insertions(+), 23 deletions(-) diff --git a/packages/core/src/boot.ts b/packages/core/src/boot.ts index 772edd1d1..fdbd93cba 100644 --- a/packages/core/src/boot.ts +++ b/packages/core/src/boot.ts @@ -148,6 +148,9 @@ export interface Settings { $Page: { $Render: PageRendererSettings; }; + $Observable?: { + maxHistoryLength: number; + }; } /** diff --git a/packages/core/src/event/Observable.ts b/packages/core/src/event/Observable.ts index cd67204d0..dde31db4d 100644 --- a/packages/core/src/event/Observable.ts +++ b/packages/core/src/event/Observable.ts @@ -3,23 +3,28 @@ import { DispatcherEventsMap, DispatcherListener, } from './Dispatcher'; +import { Settings } from '../boot'; import { Dependencies } from '../oc/ObjectContainer'; -import { RendererEvents } from '../page/renderer/RendererEvents'; import { RouterEvents } from '../router/RouterEvents'; export class Observable { protected _dispatcher: Dispatcher; protected _observers: Map, Set>>; protected _activityHistory: Map; - protected _pageResetEvents: Set; + protected _persistentEvents: Set; + protected _settings: Settings['$Observable']; - static $dependencies: Dependencies = ['$Dispatcher']; + static $dependencies: Dependencies = [ + '$Dispatcher', + '?$Settings.$Observable', + ]; - constructor(dispatcher: Dispatcher) { + constructor(dispatcher: Dispatcher, settings?: Settings['$Observable']) { this._dispatcher = dispatcher; this._observers = new Map(); this._activityHistory = new Map(); - this._pageResetEvents = new Set(); + this._persistentEvents = new Set(); + this._settings = settings; this.clear(); } @@ -35,19 +40,11 @@ export class Observable { clear() { this._observers.clear(); this._activityHistory.clear(); - this._pageResetEvents.clear(); - - Object.values(RouterEvents).forEach(event => - this._pageResetEvents.add(event) - ); - - Object.values(RendererEvents).forEach(event => - this._pageResetEvents.add(event) - ); + this._persistentEvents.clear(); } - registerPageReset(event: keyof DispatcherEventsMap | string) { - this._pageResetEvents.add(event); + unregisterPageReset(event: keyof DispatcherEventsMap | string) { + this._persistentEvents.add(event); } subscribe( @@ -98,8 +95,10 @@ export class Observable { _handleDispatcherEvent(event: string, data: any) { if (event === RouterEvents.BEFORE_HANDLE_ROUTE) { - for (const pageResetEvent of this._pageResetEvents) { - this._activityHistory.delete(pageResetEvent); + for (const [eventKey] of this._activityHistory) { + if (!this._persistentEvents.has(eventKey)) { + this._activityHistory.delete(eventKey); + } } } @@ -108,6 +107,12 @@ export class Observable { } this._activityHistory.get(event)!.push(data); + this._activityHistory.set( + event, + this._activityHistory + .get(event)! + .splice(-(this._settings?.maxHistoryLength || 10)) + ); if (!this._observers.has(event)) { return; diff --git a/packages/core/src/event/__tests__/ObservableSpec.ts b/packages/core/src/event/__tests__/ObservableSpec.ts index c2028cdda..80d5894d3 100644 --- a/packages/core/src/event/__tests__/ObservableSpec.ts +++ b/packages/core/src/event/__tests__/ObservableSpec.ts @@ -67,6 +67,22 @@ describe('ima.core.event.Observable', () => { expect(observer).toHaveBeenLastCalledWith({ 3: 4 }); }); + it('should subscribe to event and get data if already mrkev fired multiple times', () => { + const observable2 = new Observable(dispatcher, { maxHistoryLength: 2 }); + observable2.init(); + + dispatcher.fire(event, eventData); + dispatcher.fire(event, { 1: 2 }); + dispatcher.fire(event, { 3: 4 }); + + const observer = jest.fn(); + observable2.subscribe(event, observer); + + expect(observer).not.toHaveBeenCalledWith(eventData); + expect(observer).toHaveBeenCalledWith({ 1: 2 }); + expect(observer).toHaveBeenLastCalledWith({ 3: 4 }); + }); + it('should work with scope', () => { class Foo { foo = jest.fn(); @@ -101,26 +117,32 @@ describe('ima.core.event.Observable', () => { observer.mockClear(); observable.unsubscribe(event, observer); - dispatcher.fire(event, { foor: 'bar' }); + dispatcher.fire(event, { foo: 'bar' }); expect(observer).not.toHaveBeenCalled(); expect(observable['_observers'].get(event)?.size).toBe(0); }); }); - it('should reset page events', () => { - observable.registerPageReset(event); + it('should reset only page events', () => { + observable.unregisterPageReset(event); dispatcher.fire(event, eventData); + dispatcher.fire('foo', 'bar'); dispatcher.fire(RouterEvents.BEFORE_HANDLE_ROUTE, { bhr: true }); const eventObserver = jest.fn(); observable.subscribe(event, eventObserver); - expect(eventObserver).not.toHaveBeenCalledWith(eventData); + expect(eventObserver).toHaveBeenCalledWith(eventData); const bhrObserver = jest.fn(); observable.subscribe(RouterEvents.BEFORE_HANDLE_ROUTE, bhrObserver); expect(bhrObserver).toHaveBeenCalledWith({ bhr: true }); + + const fooObserver = jest.fn(); + observable.subscribe('foo', fooObserver); + + expect(fooObserver).not.toHaveBeenCalled(); }); }); diff --git a/packages/core/src/router/ServerRouter.ts b/packages/core/src/router/ServerRouter.ts index 09b3df3b6..85a56a56b 100644 --- a/packages/core/src/router/ServerRouter.ts +++ b/packages/core/src/router/ServerRouter.ts @@ -26,7 +26,6 @@ export class ServerRouter extends AbstractRouter { Request, Response, '?$Settings.$Router.middlewareTimeout', - '?$Settings.$Router.isSPARouted', ]; }