mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-14 21:26:15 -08:00
feat(services): server kind for the playlist storage backend
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
872d8edc68
commit
ab2eef26d2
2 files changed
+59
-2
No files matched your search
@@ -41,4 +41,30 @@ describe('PlaylistStorageBackend', () => {
|
||||
expect(backend.kind()).toBe('indexeddb');
|
||||
expect(backend.documentStore()).toBeNull();
|
||||
});
|
||||
|
||||
it('prefers the server store once it is set', () => {
|
||||
testWindow.electron = undefined;
|
||||
const backend = create(false);
|
||||
const store = { dbGetAppPlaylists: jest.fn() } as never;
|
||||
|
||||
backend.useServerStore(store);
|
||||
|
||||
expect(backend.kind()).toBe('server');
|
||||
expect(backend.documentStore()).toBe(store);
|
||||
});
|
||||
|
||||
it('falls back to browser storage while an override task runs', async () => {
|
||||
testWindow.electron = undefined;
|
||||
const backend = create(false);
|
||||
backend.useServerStore({ dbGetAppPlaylists: jest.fn() } as never);
|
||||
|
||||
const seen = await backend.runWithBrowserStorage(async () => [
|
||||
backend.kind(),
|
||||
backend.usesBrowserStorageOverride(),
|
||||
]);
|
||||
|
||||
expect(seen).toEqual(['indexeddb', true]);
|
||||
expect(backend.kind()).toBe('server');
|
||||
expect(backend.usesBrowserStorageOverride()).toBe(false);
|
||||
});
|
||||
});
|
||||
@@ -28,20 +28,51 @@ export type PlaylistDocumentStore = Pick<
|
||||
>
|
||||
>;
|
||||
|
||||
export type PlaylistStorageKind = 'electron' | 'indexeddb';
|
||||
export type PlaylistStorageKind = 'electron' | 'server' | 'indexeddb';
|
||||
|
||||
/** Single place that decides where `PlaylistsService` persists playlists. */
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class PlaylistStorageBackend {
|
||||
private readonly runtime = inject(RuntimeCapabilitiesService);
|
||||
private serverStore: PlaylistDocumentStore | null = null;
|
||||
private browserOverrideDepth = 0;
|
||||
|
||||
/** Server mode: set once by the server storage session at startup. */
|
||||
useServerStore(store: PlaylistDocumentStore): void {
|
||||
this.serverStore = store;
|
||||
}
|
||||
|
||||
usesBrowserStorageOverride(): boolean {
|
||||
return this.browserOverrideDepth > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs `task` against browser storage although server mode is active.
|
||||
* Only the migration export uses it, inside a modal flow.
|
||||
*/
|
||||
async runWithBrowserStorage<T>(task: () => Promise<T>): Promise<T> {
|
||||
this.browserOverrideDepth += 1;
|
||||
try {
|
||||
return await task();
|
||||
} finally {
|
||||
this.browserOverrideDepth -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
kind(): PlaylistStorageKind {
|
||||
if (this.serverStore && this.browserOverrideDepth === 0) {
|
||||
return 'server';
|
||||
}
|
||||
return this.runtime.supportsSqlite ? 'electron' : 'indexeddb';
|
||||
}
|
||||
|
||||
/** The document store for `kind()`, or `null` for IndexedDB. */
|
||||
documentStore(): PlaylistDocumentStore | null {
|
||||
if (this.kind() !== 'electron' || typeof window === 'undefined') {
|
||||
const kind = this.kind();
|
||||
if (kind === 'server') {
|
||||
return this.serverStore;
|
||||
}
|
||||
if (kind !== 'electron' || typeof window === 'undefined') {
|
||||
return null;
|
||||
}
|
||||
return (window.electron as PlaylistDocumentStore | undefined) ?? null;
|
||||
|
||||
Reference in new issue
Block a user