UNPKG

react-query-external-sync

Version:

A tool for syncing React Query state to an external Dev Tools

289 lines 10.3 kB
/** * Helper function for controlled logging * Only shows logs when enableLogs is true * Always shows warnings and errors regardless of enableLogs setting */ export function log(message, enableLogs, type = "log") { if (!enableLogs) return; switch (type) { case "warn": console.warn(message); break; case "error": console.error(message); break; default: console.log(message); } } /** * Sync logger for external sync operations * Provides clean, grouped logging similar to API route logging */ class ExternalSyncLogger { constructor() { this.operations = new Map(); } /** * Start a new sync operation */ startOperation(type, context, enableLogs = false) { const requestId = this.generateRequestId(); const fullContext = { deviceName: context.deviceName || "unknown", deviceId: context.deviceId || "unknown", platform: context.platform || "unknown", requestId, timestamp: Date.now(), }; this.operations.set(requestId, { context: fullContext, startTime: Date.now(), stats: { storageUpdates: { mmkv: 0, asyncStorage: 0, secureStore: 0 }, queryActions: { dataUpdates: 0, refetches: 0, invalidations: 0, resets: 0, removes: 0, errors: 0, }, connectionEvents: { connects: 0, disconnects: 0, reconnects: 0 }, errors: [], }, enableLogs, }); if (enableLogs) { const icon = this.getOperationIcon(type); const readableTime = new Date(fullContext.timestamp).toLocaleString("en-US", { month: "short", day: "numeric", hour: "2-digit", minute: "2-digit", second: "2-digit", hour12: true, }); log(`┌─ 🌴 ${this.getOperationTitle(type)} • ${fullContext.deviceName} (${fullContext.platform}) • ${readableTime}`, enableLogs); } return requestId; } /** * Log a storage update */ logStorageUpdate(requestId, storageType, key, currentValue, newValue) { const operation = this.operations.get(requestId); if (!operation) return; operation.stats.storageUpdates[storageType]++; if (operation.enableLogs) { const icon = this.getStorageIcon(storageType); const typeDisplay = storageType === "asyncStorage" ? "AsyncStorage" : storageType === "secureStore" ? "SecureStore" : "MMKV"; log(`├─ ${icon} ${typeDisplay}: ${key} | ${JSON.stringify(currentValue)} → ${JSON.stringify(newValue)}`, operation.enableLogs); } } /** * Log a query action */ logQueryAction(requestId, action, queryHash, success = true) { const operation = this.operations.get(requestId); if (!operation) return; // Update stats based on action type switch (action) { case "ACTION-DATA-UPDATE": operation.stats.queryActions.dataUpdates++; break; case "ACTION-REFETCH": operation.stats.queryActions.refetches++; break; case "ACTION-INVALIDATE": operation.stats.queryActions.invalidations++; break; case "ACTION-RESET": operation.stats.queryActions.resets++; break; case "ACTION-REMOVE": operation.stats.queryActions.removes++; break; default: if (!success) operation.stats.queryActions.errors++; break; } if (operation.enableLogs) { const icon = this.getActionIcon(action, success); const actionName = this.getActionDisplayName(action); log(`├─ ${icon} ${actionName}: ${queryHash}`, operation.enableLogs); } } /** * Log a connection event */ logConnectionEvent(requestId, event, details) { const operation = this.operations.get(requestId); if (!operation) return; operation.stats.connectionEvents[`${event}s`]++; if (operation.enableLogs) { const icon = event === "connect" ? "🔗" : event === "disconnect" ? "🔌" : "🔄"; const message = details ? `${event.toUpperCase()}: ${details}` : event.toUpperCase(); console.log(`├ ${icon} ${message}`); } } /** * Log an error */ logError(requestId, type, message, error) { var _a; const operation = this.operations.get(requestId); if (!operation) return; operation.stats.errors.push({ type, message, timestamp: Date.now(), }); if (operation.enableLogs) { console.log(`├ ❌ ${type}: ${message}`); if (error === null || error === void 0 ? void 0 : error.stack) { console.log(`├ Stack: ${(_a = error.stack.split("\n")[1]) === null || _a === void 0 ? void 0 : _a.trim()}`); } } } /** * Complete and log the operation summary */ completeOperation(requestId, success = true) { const operation = this.operations.get(requestId); if (!operation) return; // Only show completion log if there was an error if (operation.enableLogs && !success) { log(`└─ ❌ Error`, operation.enableLogs); log("", operation.enableLogs); // Add empty line for spacing } else if (operation.enableLogs) { // Just add spacing for successful operations without the "Complete" message log("", operation.enableLogs); } // Clean up without logging summary this.operations.delete(requestId); } generateRequestId() { return Math.random().toString(36).substring(2, 15); } getOperationIcon(type) { switch (type) { case "connection": return "🔗"; case "query-action": return "🔄"; case "storage-update": return "💾"; case "sync-session": return "🔄"; default: return "📋"; } } getOperationTitle(type) { switch (type) { case "connection": return "Connection"; case "query-action": return "Query Action"; case "storage-update": return "Storage Update"; case "sync-session": return "Sync Session"; default: return "Operation"; } } getStorageIcon(storageType) { switch (storageType) { case "mmkv": return "💾"; case "asyncStorage": return "📱"; case "secureStore": return "🔐"; default: return "📦"; } } getActionIcon(action, success) { if (!success) return "🔴"; // Red for failures (#EF4444) switch (action) { case "ACTION-DATA-UPDATE": return "🟢"; // Green for fresh/success (#039855) case "ACTION-REFETCH": return "🔵"; // Blue for refetch (#1570EF) case "ACTION-INVALIDATE": return "🟠"; // Orange for invalidate (#DC6803) case "ACTION-RESET": return "⚫"; // Dark gray for reset (#475467) case "ACTION-REMOVE": return "🟣"; // Pink/purple for remove (#DB2777) case "ACTION-TRIGGER-ERROR": return "🔴"; // Red for error (#EF4444) case "ACTION-RESTORE-ERROR": return "🟢"; // Green for restore (success variant) case "ACTION-TRIGGER-LOADING": return "🔷"; // Light blue diamond for loading (#0891B2) case "ACTION-RESTORE-LOADING": return "🔶"; // Orange diamond for restore loading (loading variant) case "ACTION-CLEAR-MUTATION-CACHE": return "⚪"; // White for clear cache (neutral) case "ACTION-CLEAR-QUERY-CACHE": return "⬜"; // White square for clear cache (neutral) case "ACTION-ONLINE-MANAGER-ONLINE": return "🟢"; // Green for online (fresh) case "ACTION-ONLINE-MANAGER-OFFLINE": return "🔴"; // Red for offline (error) default: return "⚪"; // White for generic (inactive #667085) } } getActionDisplayName(action) { switch (action) { case "ACTION-DATA-UPDATE": return "Data Update"; case "ACTION-REFETCH": return "Refetch"; case "ACTION-INVALIDATE": return "Invalidate"; case "ACTION-RESET": return "Reset"; case "ACTION-REMOVE": return "Remove"; case "ACTION-TRIGGER-ERROR": return "Trigger Error"; case "ACTION-RESTORE-ERROR": return "Restore Error"; case "ACTION-TRIGGER-LOADING": return "Trigger Loading"; case "ACTION-RESTORE-LOADING": return "Restore Loading"; default: return action.replace("ACTION-", "").replace(/-/g, " "); } } formatDuration(ms) { if (ms < 1000) return `${ms}ms`; const seconds = (ms / 1000).toFixed(1); return `${seconds}s`; } } export const syncLogger = new ExternalSyncLogger(); //# sourceMappingURL=logger.js.map