feat: Phase 3+4 — security hardening + polish + offline + Electron push
Phase 3 (security): - P3.1: Feature gate server-side enforcement (403 on disabled features) - P3.2: Unified auth error interceptor (401→logout) - P3.3: Store-level state isolation via StoreSnapshot contract (added message-list-tabs + task stores to snapshot/restore cycle) - P3.4: Push event bus extraction — email-store no longer imports calendar/contact/filter/file stores directly - P1.3: Auth localStorage AES-GCM encryption via custom Zustand adapter Phase 4 (polish): - P4.1: Offline write queue — pending operations in localStorage, auto-retry on reconnect, offline-queue-indicator banner - P4.2: Identity spoofing — fromOverrideEmail domain validation - P4.3: WebSocket push for Electron via main-process IPC bridge (ws package with Authorization headers)
This commit is contained in:
@@ -0,0 +1,38 @@
|
||||
import type { IJMAPClient } from '@/lib/jmap/client-interface';
|
||||
|
||||
type JmapTypeHandler = (client: IJMAPClient, accountChanges: Record<string, string>) => Promise<void>;
|
||||
|
||||
const handlers = new Map<string, JmapTypeHandler[]>();
|
||||
|
||||
export function registerPushHandler(jmapType: string, handler: JmapTypeHandler): () => void {
|
||||
const list = handlers.get(jmapType) ?? [];
|
||||
list.push(handler);
|
||||
handlers.set(jmapType, list);
|
||||
return () => {
|
||||
const current = handlers.get(jmapType);
|
||||
if (!current) return;
|
||||
const idx = current.indexOf(handler);
|
||||
if (idx >= 0) current.splice(idx, 1);
|
||||
if (current.length === 0) handlers.delete(jmapType);
|
||||
};
|
||||
}
|
||||
|
||||
export async function dispatchPushEvent(
|
||||
client: IJMAPClient,
|
||||
changed: Record<string, Record<string, string>>,
|
||||
accountId: string,
|
||||
): Promise<void> {
|
||||
const accountChanges = changed[accountId];
|
||||
|
||||
for (const [jmapType, typeHandlers] of handlers) {
|
||||
if (accountChanges?.[jmapType]) {
|
||||
for (const handler of typeHandlers) {
|
||||
try {
|
||||
await handler(client, accountChanges);
|
||||
} catch (error) {
|
||||
console.error(`Push handler for ${jmapType} failed:`, error);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user