fix(stalker): merge late connection saves

This commit is contained in:
4gray committed 2026-08-09 18:01:13 +02:00
1 parent ffae919cc8
commit 37575c8d88
10 files changed
+202 -29

No files matched your search

@@ -358,6 +358,39 @@ describe('AppStalkerPlaylistConnectionEditorService', () => {
);
});
it('returns an atomic connection-only merge for a post-navigation save', async () => {
const resolvedPlaylist = {
...draft,
title: 'Stale form title',
portalUrl: 'https://new.example.com/server/load.php',
isFullStalkerPortal: true,
stalkerSessionPatch: {
stalkerToken: 'NEW_TOKEN',
stalkerSessionIdentity: 'new-fingerprint',
},
};
const persistedPlaylist = {
...resolvedPlaylist,
title: 'Newer title',
epgUrls: ['https://new.example.com/epg.xml'],
};
stalkerSession.replaceSessionAfterEdit.mockResolvedValueOnce(
persistedPlaylist
);
await expect(
service.applyResolvedConnection(resolvedPlaylist, {
preserveCurrentMetadata: true,
})
).resolves.toEqual(persistedPlaylist);
expect(stalkerSession.replaceSessionAfterEdit).toHaveBeenCalledWith(
expect.objectContaining({ title: 'Stale form title' }),
expect.objectContaining({ playlistId: draft._id }),
{ preserveCurrentMetadata: true }
);
});
it('clears the session and stops full-portal runtime behavior after a resolved simple edit', async () => {
activePlaylist = {
...draft,
@@ -14,6 +14,7 @@ import {
STALKER_PLAYLIST_CONNECTION_EDITOR_STATUS,
type StalkerPlaylistConnectionEditor,
type StalkerPlaylistConnectionResult,
type StalkerResolvedConnectionApplyOptions,
} from '@iptvnator/playlist/shared/ui';
import {
normalizeStalkerPortalIdentity,
@@ -45,7 +46,10 @@ export class AppStalkerPlaylistConnectionEditorService implements StalkerPlaylis
private readonly translate = inject(TranslateService);
private readonly editFences = new Map<string, StalkerEditFence>();
async applyResolvedConnection(playlist: PlaylistMetaUpdate): Promise<void> {
async applyResolvedConnection(
playlist: PlaylistMetaUpdate,
options: StalkerResolvedConnectionApplyOptions = {}
): Promise<PlaylistMetaUpdate> {
// Edit discovery is newer and more authoritative than a lazy repair
// remembered for the previous connection. Applying that override to
// the resolved row could turn a credential-only A→A edit back into
@@ -55,11 +59,16 @@ export class AppStalkerPlaylistConnectionEditorService implements StalkerPlaylis
this.editFences.get(runtimePlaylist._id) ??
(await this.beginEditFence(runtimePlaylist));
try {
const persistedPlaylist =
await this.stalkerSession.replaceSessionAfterEdit(
runtimePlaylist,
fence
);
const persistedPlaylist = options.preserveCurrentMetadata
? await this.stalkerSession.replaceSessionAfterEdit(
runtimePlaylist,
fence,
options
)
: await this.stalkerSession.replaceSessionAfterEdit(
runtimePlaylist,
fence
);
this.portalRepair.commitPlaylistEdit(runtimePlaylist._id);
this.editFences.delete(runtimePlaylist._id);
@@ -71,6 +80,7 @@ export class AppStalkerPlaylistConnectionEditorService implements StalkerPlaylis
// other metadata absent from the form survive replacement.
await this.stalkerStore.setCurrentPlaylist(persistedPlaylist);
}
return persistedPlaylist;
} catch (error) {
this.releaseEditFence(runtimePlaylist._id, fence);
throw error;