From 7e3034da8d3515665750d5e18a5bfffa350e145f Mon Sep 17 00:00:00 2001 From: Bernd Rodler Date: Fri, 7 Aug 2026 12:37:16 +0200 Subject: [PATCH] test: update recurrence expansion test + fix TS/Lint errors --- lib/__tests__/recurrence-expansion.test.ts | 4 ++-- lib/jmap/client.ts | 5 +++-- lib/jmap/types.ts | 1 + lib/oauth/token-exchange.ts | 2 +- package-lock.json | 4 ++-- stores/settings-store.ts | 8 +++----- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/lib/__tests__/recurrence-expansion.test.ts b/lib/__tests__/recurrence-expansion.test.ts index 71e829f8..77760f52 100644 --- a/lib/__tests__/recurrence-expansion.test.ts +++ b/lib/__tests__/recurrence-expansion.test.ts @@ -456,8 +456,8 @@ describe('expandRecurringEvents', () => { recurrenceRules: [rule({ '@type': 'RecurrenceRule', frequency: 'daily' })], }); const result = expand(event, '2025-01-06T00:00:00', '2025-01-08T00:00:00'); - expect(result[0].id).toBe('evt1:2025-01-06T09:00:00'); - expect(result[1].id).toBe('evt1:2025-01-07T09:00:00'); + expect(result[0].id).toBe('evt1::occurrence::2025-01-06T09:00:00'); + expect(result[1].id).toBe('evt1::occurrence::2025-01-07T09:00:00'); }); it('preserves originalId pointing to master', () => { diff --git a/lib/jmap/client.ts b/lib/jmap/client.ts index f18a2323..afc48315 100644 --- a/lib/jmap/client.ts +++ b/lib/jmap/client.ts @@ -6096,6 +6096,7 @@ export class JMAPClient implements IJMAPClient { private wsReconnectAttempts: number = 0; private wsConsecutiveFailures: number = 0; private wsPermanentlyDisabled: boolean = false; + private _statesPromise: Promise | null = null; private wsHeartbeatTimer: NodeJS.Timeout | null = null; private lastWSActivity: number = 0; @@ -6177,7 +6178,7 @@ export class JMAPClient implements IJMAPClient { // entirely: SSE only streams changes from the moment it connects // onward (no catch-up on connect), so the one thing that CAN catch up // is a diff against a state snapshot taken before the gap started. - void this.fetchCurrentStates(); + this._statesPromise = this.fetchCurrentStates(); // Not confirmed either way whether this server's WebSocket push fans // out to shared/secondary accounts or, like Stalwart's SSE, covers the // primary account only - keep the same secondary poll running under @@ -6321,7 +6322,7 @@ export class JMAPClient implements IJMAPClient { * original 31s-worst-case ladder did. */ private async reconcileAfterWebSocketFallback(): Promise { - await this._stateSnapshotPromise; + await this._statesPromise; await this.checkForStateChanges(); const eventSourceUrl = this.getEventSourceUrl(); diff --git a/lib/jmap/types.ts b/lib/jmap/types.ts index 7ebdbfff..0fbb82a6 100644 --- a/lib/jmap/types.ts +++ b/lib/jmap/types.ts @@ -800,6 +800,7 @@ export interface StateChange { Calendar?: string; CalendarEvent?: string; SieveScript?: string; + FileNode?: string; }; }; } diff --git a/lib/oauth/token-exchange.ts b/lib/oauth/token-exchange.ts index ebc099e6..c807a6f5 100644 --- a/lib/oauth/token-exchange.ts +++ b/lib/oauth/token-exchange.ts @@ -121,7 +121,7 @@ export async function exchangeCodeForTokens( const tokens = await tokenResponse.json(); if (!tokens.access_token) { - const { access_token, refresh_token, ...safeTokens } = tokens; + const { access_token: _at, refresh_token: _rt, ...safeTokens } = tokens; logger.error('Token response missing access_token', { response: JSON.stringify(safeTokens).substring(0, 500) }); throw new Error('Invalid token response'); } diff --git a/package-lock.json b/package-lock.json index d976188c..6c7789e1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,11 +1,11 @@ { - "name": "bulwark-webmail", + "name": "vncmail-plus", "version": "1.7.8", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "bulwark-webmail", + "name": "vncmail-plus", "version": "1.7.8", "license": "AGPL-3.0-only", "dependencies": { diff --git a/stores/settings-store.ts b/stores/settings-store.ts index 2ff44c17..1b6a8aa6 100644 --- a/stores/settings-store.ts +++ b/stores/settings-store.ts @@ -2,6 +2,7 @@ import { create } from 'zustand'; import { persist } from 'zustand/middleware'; import { useThemeStore } from './theme-store'; import { useLocaleStore } from './locale-store'; +import { usePolicyStore } from './policy-store'; import type { NotificationSoundChoice } from '@/lib/notification-sound'; import { apiFetch } from '@/lib/browser-navigation'; import { @@ -645,11 +646,8 @@ export const useSettingsStore = create()( updateSetting: (key, value, opts?: { force?: boolean }) => { if (!opts?.force) { - try { - const { usePolicyStore } = require('./policy-store'); - const locked = usePolicyStore.getState().isSettingLocked(key); - if (locked) return; - } catch { /* policy store may not be loaded yet */ } + const locked = usePolicyStore.getState().isSettingLocked(key); + if (locked) return; } set({ [key]: value });