import { EMPTY_HIT_STATS, EMPTY_VISITOR_STATS, DEFAULT_PUBLISH_STATE, DEFAULT_REPLY_TEMPLATES, buildDefaultPodcastChecklist, } from './config.js' export const state = { cachedSiteContent: null, cachedDraftSiteContent: null, publishState: { ...DEFAULT_PUBLISH_STATE }, hitStats: { ...EMPTY_HIT_STATS }, hitStatsWritePromise: Promise.resolve(), lastHitStatsWrite: { ok: true, at: null, error: null }, visitorStats: { ...EMPTY_VISITOR_STATS }, visitorStatsWritePromise: Promise.resolve(), lastVisitorStatsWrite: { ok: true, at: null, error: null }, contactSubmissions: [], contactSubmissionsWritePromise: Promise.resolve(), questions: [], questionsWritePromise: Promise.resolve(), draftQuestions: null, draftQuestionsWritePromise: Promise.resolve(), replyTemplates: [...DEFAULT_REPLY_TEMPLATES], replyTemplatesWritePromise: Promise.resolve(), replyHistory: [], replyHistoryWritePromise: Promise.resolve(), podcastChecklist: buildDefaultPodcastChecklist(), podcastChecklistWritePromise: Promise.resolve(), studyUsers: [], studyUsersWritePromise: Promise.resolve(), studyCommunityPosts: [], studyCommunityWritePromise: Promise.resolve(), studyReminders: { users: {}, updatedAt: new Date().toISOString() }, studyRemindersWritePromise: Promise.resolve(), studyComments: [], studyCommentsWritePromise: Promise.resolve(), studyCertificates: [], studyCertificatesWritePromise: Promise.resolve(), // episodeScripts: { [episodeNumber]: { text, title, filename, uploadedAt } } episodeScripts: {}, episodeScriptsWritePromise: Promise.resolve(), downloadCounts: {}, downloadCountsWritePromise: Promise.resolve(), // episodePlays: { [title]: { total: number, byDay: { [YYYY-MM-DD]: number } } } episodePlays: {}, episodePlaysWritePromise: Promise.resolve(), // analyticsEvents: aggregated engagement data from frontend events // { // scrollDepth: { [path]: { 25: n, 50: n, 75: n, 90: n } } // timeOnPage: { [path]: { totalSeconds: n, count: n } } // outboundClicks: { [url]: n } // utmSources: { [utm_source]: n } // searchQueries: { [query]: n } // notFound: { [path]: n } // audioEvents: { [title]: { pauses: n, completions: n, totalListenSeconds: n } } // } analyticsEvents: { scrollDepth: {}, timeOnPage: {}, outboundClicks: {}, utmSources: {}, searchQueries: {}, notFound: {}, audioEvents: {}, }, analyticsEventsWritePromise: Promise.resolve(), // qrCodes: Array<{ id, slug, label, destination, createdAt }> // qrScans: Array<{ id, qrId, slug, scannedAt, ip, userAgent }> qrCodes: [], qrScans: [], qrCodesWritePromise: Promise.resolve(), emailSettings: { signature: 'Grace and peace,\nVerse by Verse with Nate' }, emailSettingsWritePromise: Promise.resolve(), calendarEvents: [], calendarEventsWritePromise: Promise.resolve(), auditLog: [], auditLogWritePromise: Promise.resolve(), webhooks: [], webhooksWritePromise: Promise.resolve(), lastBackupStatus: { ok: true, at: null, error: null, file: null }, lastCachePurgeStatus: { ok: true, at: null, error: null }, lastDeployHookStatus: { ok: true, at: null, error: null }, // In-memory caches (not persisted between restarts) studyNotesCache: new Map(), // userId -> { [sectionId]: string } studyNotesWriteQueues: new Map(), // userId -> Promise studyProgressCache: new Map(), // userId -> { byStudy: ... } studyProgressWriteQueues: new Map(), // userId -> Promise studySessions: new Map(), studyTotpPendingTokens: new Map(), emailOtpStore: new Map(), titusDownloadTokens: new Map(), contactSubmitCooldownByEmail: new Map(), resendEmailSubmissionIndex: new Map(), }