@djangocfg/debuger 2.1.219

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/README.md +345 -0
  2. package/dist/chunk-ESIQODSI.mjs +115 -0
  3. package/dist/chunk-ESIQODSI.mjs.map +1 -0
  4. package/dist/chunk-PAWJFY3S.mjs +6 -0
  5. package/dist/chunk-PAWJFY3S.mjs.map +1 -0
  6. package/dist/chunk-YQE3KTBG.mjs +64 -0
  7. package/dist/chunk-YQE3KTBG.mjs.map +1 -0
  8. package/dist/customEmitter-BO-1IWxm.d.ts +57 -0
  9. package/dist/emitters/index.cjs +74 -0
  10. package/dist/emitters/index.cjs.map +1 -0
  11. package/dist/emitters/index.d.ts +33 -0
  12. package/dist/emitters/index.mjs +4 -0
  13. package/dist/emitters/index.mjs.map +1 -0
  14. package/dist/index.cjs +887 -0
  15. package/dist/index.cjs.map +1 -0
  16. package/dist/index.d.ts +162 -0
  17. package/dist/index.mjs +694 -0
  18. package/dist/index.mjs.map +1 -0
  19. package/dist/logger/index.cjs +123 -0
  20. package/dist/logger/index.cjs.map +1 -0
  21. package/dist/logger/index.d.ts +50 -0
  22. package/dist/logger/index.mjs +4 -0
  23. package/dist/logger/index.mjs.map +1 -0
  24. package/package.json +67 -0
  25. package/src/DebugButton.tsx +143 -0
  26. package/src/DebugPanel.tsx +171 -0
  27. package/src/bridges/index.ts +1 -0
  28. package/src/bridges/monitorBridge.ts +63 -0
  29. package/src/emitters/Emitter.ts +51 -0
  30. package/src/emitters/audioEmitter.ts +74 -0
  31. package/src/emitters/customEmitter.ts +42 -0
  32. package/src/emitters/index.ts +10 -0
  33. package/src/hooks/useAudioEventLog.ts +147 -0
  34. package/src/hooks/useCustomEventLog.ts +39 -0
  35. package/src/hooks/useDebugShortcut.ts +27 -0
  36. package/src/hooks/useStoreSnapshot.ts +70 -0
  37. package/src/index.ts +62 -0
  38. package/src/logger/index.ts +3 -0
  39. package/src/logger/logStore.ts +89 -0
  40. package/src/logger/logger.ts +95 -0
  41. package/src/logger/types.ts +39 -0
  42. package/src/panels/AudioDebugPanel.tsx +157 -0
  43. package/src/panels/LogsPanel.tsx +267 -0
  44. package/src/panels/StorePanel.tsx +71 -0
  45. package/src/store/debugStore.ts +42 -0
  46. package/src/styles/index.css +5 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/store/debugStore.ts","../src/hooks/useDebugShortcut.ts","../src/bridges/monitorBridge.ts","../src/panels/LogsPanel.tsx","../src/hooks/useAudioEventLog.ts","../src/panels/AudioDebugPanel.tsx","../src/DebugPanel.tsx","../src/DebugButton.tsx","../src/hooks/useStoreSnapshot.ts","../src/panels/StorePanel.tsx","../src/hooks/useCustomEventLog.ts"],"names":["useState","useRef","useCallback","useEffect","jsxs","jsx","Badge","cn","Button","Trash2","Radio","Bug","Tooltip","TooltipTrigger","TooltipContent","ScrollArea","LazyJsonTree","MAX_EVENTS"],"mappings":"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","file":"index.mjs","sourcesContent":["'use client';\n\nimport { create } from 'zustand';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport type DebugTab = 'logs' | 'audio' | 'pipeline' | 'custom';\n\nexport interface DebugStore {\n isOpen: boolean;\n tab: DebugTab;\n isUnlocked: boolean;\n open: () => void;\n close: () => void;\n toggle: () => void;\n setTab: (t: DebugTab) => void;\n unlock: (key: string) => boolean;\n}\n\n// ============================================================================\n// Store\n// ============================================================================\n\nexport const useDebugStore = create<DebugStore>((set) => ({\n isOpen: false,\n tab: 'logs',\n isUnlocked: false,\n\n open: () => set({ isOpen: true }),\n close: () => set({ isOpen: false }),\n toggle: () => set((s) => ({ isOpen: !s.isOpen })),\n setTab: (tab) => set({ tab }),\n\n unlock: (_key) => {\n // Any non-empty value unlocks — no secret key required\n const valid = true;\n if (valid) set({ isUnlocked: true });\n return valid;\n },\n}));\n","'use client';\n\nimport { useHotkey } from '@djangocfg/ui-core/hooks';\nimport { useDebugStore } from '../store/debugStore';\n\n/**\n * Registers a global keyboard shortcut to toggle the debug panel.\n * Default: Cmd+D (meta+d) on Mac / Win+D on Windows.\n *\n * Guards:\n * - In production: only fires if `isUnlocked === true`\n */\nexport function useDebugShortcut(): void {\n const toggle = useDebugStore((s) => s.toggle);\n const isUnlocked = useDebugStore((s) => s.isUnlocked);\n const isDev = typeof process !== 'undefined' && process.env?.NODE_ENV !== 'production';\n\n useHotkey(\n 'meta+d',\n (e) => {\n e.preventDefault();\n if (!isDev && !isUnlocked) return;\n toggle();\n },\n { preventDefault: true },\n );\n}\n","'use client';\n\n/**\n * monitorBridge — subscribes to @djangocfg/monitor store and forwards\n * captured events into debugger's logStore.\n *\n * Call once at app startup (e.g. inside DebugPanel or a provider).\n * Safe to call multiple times — only installs one subscription.\n *\n * @example\n * import { installMonitorBridge } from '@djangocfg/debuger/bridges'\n * installMonitorBridge()\n */\n\nimport { monitorStore } from '@djangocfg/monitor/client';\nimport { useDebugLogStore } from '../logger/logStore';\nimport type { LogLevel } from '../logger/types';\n\nlet _installed = false;\n\nexport function installMonitorBridge(): (() => void) | undefined {\n if (typeof window === 'undefined') return;\n if (_installed) return;\n\n let prevLen = monitorStore.getState().buffer.length;\n\n const unsub = monitorStore.subscribe((state) => {\n const buffer = state.buffer;\n if (buffer.length <= prevLen) { prevLen = buffer.length; return; }\n const newEvents = buffer.slice(prevLen);\n prevLen = buffer.length;\n\n for (const event of newEvents) {\n const level: LogLevel =\n event.level === 'error' ? 'error'\n : event.level === 'warn' ? 'warn'\n : 'info';\n\n useDebugLogStore.getState().addLog({\n level,\n component: `monitor:${event.event_type ?? 'event'}`,\n message: event.message ?? '',\n data: {\n ...(event.url && { url: event.url }),\n ...(event.session_id && { session_id: event.session_id }),\n ...(event.http_status !== undefined && {\n http_status: event.http_status,\n http_method: event.http_method,\n http_url: event.http_url,\n }),\n ...(event.extra ? { extra: event.extra } : {}),\n },\n stack: event.stack_trace,\n });\n }\n });\n\n _installed = true;\n return () => {\n unsub();\n _installed = false;\n };\n}\n","'use client';\n\nimport React, { useState, useCallback, useEffect, useRef } from 'react';\nimport {\n useDebugLogStore,\n useDebugFilteredLogs,\n useDebugLogCount,\n useDebugErrorCount,\n type LogLevel,\n type LogEntry,\n} from '../logger';\nimport {\n Button,\n CopyButton,\n Badge,\n Input,\n Tooltip,\n TooltipContent,\n TooltipTrigger,\n} from '@djangocfg/ui-core/components';\nimport { LazyJsonTree } from '@djangocfg/ui-tools';\nimport { useVirtualizer, type VirtualItem } from '@tanstack/react-virtual';\nimport {\n Bug, Trash2, Download, ChevronDown, ChevronUp,\n AlertCircle, Info, AlertTriangle, CheckCircle, Search,\n} from 'lucide-react';\nimport { cn } from '@djangocfg/ui-core/lib';\n\n// ============================================================================\n// Constants\n// ============================================================================\n\nconst ROW_ESTIMATE_PX = 32;\nconst OVERSCAN = 5;\n\nconst LOG_LEVEL_CONFIG: Record<LogLevel, { icon: React.ElementType; color: string }> = {\n debug: { icon: Bug, color: 'text-muted-foreground' },\n info: { icon: Info, color: 'text-blue-500' },\n warn: { icon: AlertTriangle, color: 'text-yellow-500' },\n error: { icon: AlertCircle, color: 'text-red-500' },\n success: { icon: CheckCircle, color: 'text-green-500' },\n};\n\nconst LOG_LEVELS = Object.keys(LOG_LEVEL_CONFIG) as LogLevel[];\n\n// ============================================================================\n// LogEntryRow\n// ============================================================================\n\ninterface LogEntryRowProps {\n entry: LogEntry;\n expanded: boolean;\n onToggle: () => void;\n}\n\nfunction LogEntryRow({ entry, expanded, onToggle }: LogEntryRowProps) {\n const config = LOG_LEVEL_CONFIG[entry.level];\n const Icon = config.icon;\n const pad = (n: number, len = 2) => String(n).padStart(len, '0');\n const d = entry.timestamp;\n const time = `${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}.${pad(d.getMilliseconds(), 3)}`;\n const hasData = entry.data && Object.keys(entry.data).length > 0;\n const hasStack = !!entry.stack;\n const isExpandable = hasData || hasStack;\n\n return (\n <div className=\"border-b border-border/50 last:border-0\">\n <button\n type=\"button\"\n onClick={isExpandable ? onToggle : undefined}\n disabled={!isExpandable}\n className={cn(\n 'flex w-full items-start gap-2 px-3 py-1.5 text-left text-xs',\n isExpandable ? 'hover:bg-muted/50 cursor-pointer' : 'cursor-default'\n )}\n >\n <Icon className={cn('h-3.5 w-3.5 mt-0.5 shrink-0', config.color)} />\n <span className=\"text-muted-foreground font-mono shrink-0\">{time}</span>\n <Badge variant=\"outline\" className=\"shrink-0 text-[10px] px-1 py-0\">{entry.component}</Badge>\n <span className=\"flex-1 truncate\">{entry.message}</span>\n {isExpandable && (\n <span className=\"shrink-0 text-muted-foreground\">\n {expanded ? <ChevronUp className=\"h-3 w-3\" /> : <ChevronDown className=\"h-3 w-3\" />}\n </span>\n )}\n </button>\n {expanded && isExpandable && (\n <div className=\"px-3 pb-2 pl-8\">\n {hasData && <div className=\"mt-1\"><LazyJsonTree data={entry.data} mode=\"compact\" /></div>}\n {hasStack && (\n <pre className=\"mt-2 text-[10px] text-red-400 whitespace-pre-wrap font-mono bg-red-950/20 p-2 rounded\">\n {entry.stack}\n </pre>\n )}\n </div>\n )}\n </div>\n );\n}\n\n// ============================================================================\n// LogsPanel\n// ============================================================================\n\nexport function LogsPanel({ isActive }: { isActive: boolean }) {\n const [expandedLogs, setExpandedLogs] = useState<Set<string>>(new Set());\n const [searchQuery, setSearchQuery] = useState('');\n const [selectedLevels, setSelectedLevels] = useState<Set<LogLevel>>(\n new Set(['debug', 'info', 'warn', 'error', 'success'])\n );\n const [componentFilter, setComponentFilter] = useState('');\n\n const logs = useDebugFilteredLogs();\n const logCount = useDebugLogCount();\n const errorCount = useDebugErrorCount();\n const clearLogs = useDebugLogStore((s) => s.clearLogs);\n const setFilter = useDebugLogStore((s) => s.setFilter);\n const exportLogs = useDebugLogStore((s) => s.exportLogs);\n\n // Virtualizer\n const scrollRef = useRef<HTMLDivElement>(null);\n const virtualizer = useVirtualizer({\n count: logs.length,\n getScrollElement: () => scrollRef.current,\n estimateSize: () => ROW_ESTIMATE_PX,\n overscan: OVERSCAN,\n });\n\n useEffect(() => {\n if (!isActive) return;\n setFilter({\n levels: Array.from(selectedLevels),\n component: componentFilter || undefined,\n search: searchQuery || undefined,\n });\n }, [isActive, selectedLevels, componentFilter, searchQuery, setFilter]);\n\n const handleToggleExpand = useCallback((id: string) => {\n setExpandedLogs((prev) => {\n const next = new Set(prev);\n next.has(id) ? next.delete(id) : next.add(id);\n return next;\n });\n }, []);\n\n const handleToggleLevel = useCallback((level: LogLevel) => {\n setSelectedLevels((prev) => {\n const next = new Set(prev);\n next.has(level) ? next.delete(level) : next.add(level);\n return next;\n });\n }, []);\n\n const handleExport = useCallback(() => {\n const json = exportLogs();\n const blob = new Blob([json], { type: 'application/json' });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = `debug-logs-${new Date().toISOString().slice(0, 19).replace(/:/g, '-')}.json`;\n a.click();\n URL.revokeObjectURL(url);\n }, [exportLogs]);\n\n const handleClear = useCallback(() => {\n clearLogs();\n setExpandedLogs(new Set());\n }, [clearLogs]);\n\n const logsJson = exportLogs();\n const virtualItems = virtualizer.getVirtualItems();\n const totalSize = virtualizer.getTotalSize();\n\n return (\n <div className=\"flex flex-col h-full\">\n {/* Stats */}\n <div className=\"flex items-center gap-2 border-b border-border px-3 py-1.5 shrink-0\">\n <Badge variant=\"secondary\" className=\"text-[10px]\">{logCount} logs</Badge>\n {errorCount > 0 && <Badge variant=\"destructive\" className=\"text-[10px]\">{errorCount} errors</Badge>}\n </div>\n\n {/* Filters */}\n <div className=\"flex flex-wrap items-center gap-2 border-b border-border px-3 py-2 shrink-0\">\n <div className=\"relative flex-1 min-w-[140px]\">\n <Search className=\"absolute left-2 top-1/2 h-3.5 w-3.5 -translate-y-1/2 text-muted-foreground\" />\n <Input\n placeholder=\"Search...\"\n value={searchQuery}\n onChange={(e) => setSearchQuery(e.target.value)}\n className=\"h-7 pl-7 text-xs\"\n />\n </div>\n <Input\n placeholder=\"Component...\"\n value={componentFilter}\n onChange={(e) => setComponentFilter(e.target.value)}\n className=\"h-7 w-24 text-xs\"\n />\n <div className=\"flex items-center gap-0.5\">\n {LOG_LEVELS.map((level) => {\n const { icon: Icon, color } = LOG_LEVEL_CONFIG[level];\n const active = selectedLevels.has(level);\n return (\n <Tooltip key={level}>\n <TooltipTrigger asChild>\n <Button variant={active ? 'secondary' : 'ghost'} size=\"icon\" className=\"h-6 w-6\" onClick={() => handleToggleLevel(level)}>\n <Icon className={cn('h-3.5 w-3.5', active && color)} />\n </Button>\n </TooltipTrigger>\n <TooltipContent>{level}</TooltipContent>\n </Tooltip>\n );\n })}\n </div>\n <div className=\"flex items-center gap-0.5 ml-auto\">\n <CopyButton value={logsJson} size=\"icon\" className=\"h-6 w-6\" />\n <Tooltip>\n <TooltipTrigger asChild>\n <Button variant=\"ghost\" size=\"icon\" className=\"h-6 w-6\" onClick={handleExport}>\n <Download className=\"h-3.5 w-3.5\" />\n </Button>\n </TooltipTrigger>\n <TooltipContent>Export JSON</TooltipContent>\n </Tooltip>\n <Tooltip>\n <TooltipTrigger asChild>\n <Button variant=\"ghost\" size=\"icon\" className=\"h-6 w-6\" onClick={handleClear}>\n <Trash2 className=\"h-3.5 w-3.5\" />\n </Button>\n </TooltipTrigger>\n <TooltipContent>Clear</TooltipContent>\n </Tooltip>\n </div>\n </div>\n\n {/* Virtualized log list */}\n <div ref={scrollRef} className=\"flex-1 overflow-auto\">\n {logs.length === 0 ? (\n <div className=\"flex flex-col items-center justify-center py-10 text-muted-foreground\">\n <Bug className=\"h-8 w-8 mb-2 opacity-40\" />\n <p className=\"text-sm\">No logs yet</p>\n </div>\n ) : (\n <div style={{ height: `${totalSize}px`, position: 'relative' }}>\n {virtualItems.map((vItem: VirtualItem) => {\n const entry = logs[vItem.index];\n return (\n <div\n key={entry.id}\n data-index={vItem.index}\n ref={virtualizer.measureElement}\n style={{ position: 'absolute', top: 0, left: 0, width: '100%', transform: `translateY(${vItem.start}px)` }}\n >\n <LogEntryRow\n entry={entry}\n expanded={expandedLogs.has(entry.id)}\n onToggle={() => handleToggleExpand(entry.id)}\n />\n </div>\n );\n })}\n </div>\n )}\n </div>\n </div>\n );\n}\n","'use client';\n\nimport { useState, useEffect, useRef, useCallback } from 'react';\nimport { subscribeAudioEvents, clearAudioEventBuffer } from '../emitters/audioEmitter';\nimport type { AudioDebugEvent, AudioEventKind } from '../emitters/audioEmitter';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface AudioLogEntry extends AudioDebugEvent {\n /** Local unique key for React rendering */\n id: string;\n}\n\nexport interface UseAudioEventLogResult {\n events: AudioLogEntry[];\n clear: () => void;\n /** Seek events per second (rolling 5s window) */\n seekRate: number;\n /** Average interval between 'sync' ticks in ms (e.g. RAF loop cadence) */\n syncIntervalMs: number | null;\n /** Running count per event kind */\n kindCounts: Partial<Record<AudioEventKind, number>>;\n}\n\n// ============================================================================\n// Constants\n// ============================================================================\n\nconst MAX_EVENTS = 200;\n\n// ============================================================================\n// Hook\n// ============================================================================\n\n/**\n * Subscribes to audio debug events and maintains a ring-buffer log.\n *\n * RAF batching: incoming events are queued in a ref and flushed into React\n * state once per animation frame — prevents render storms at 60fps.\n *\n * Only subscribes while `active` is true (panel tab is visible).\n */\nexport function useAudioEventLog(active: boolean): UseAudioEventLogResult {\n const [events, setEvents] = useState<AudioLogEntry[]>([]);\n const [syncIntervalMs, setSyncIntervalMs] = useState<number | null>(null);\n const [kindCounts, setKindCounts] = useState<Partial<Record<AudioEventKind, number>>>({});\n const [seekRate, setSeekRate] = useState(0);\n\n // Refs — mutated in the emitter callback without triggering renders\n const queueRef = useRef<AudioLogEntry[]>([]);\n const counterRef = useRef(0);\n const lastSyncTs = useRef<number | null>(null);\n const seekTimestamps = useRef<number[]>([]);\n const kindCountsRef = useRef<Partial<Record<AudioEventKind, number>>>({});\n\n const clear = useCallback(() => {\n clearAudioEventBuffer();\n queueRef.current = [];\n counterRef.current = 0;\n kindCountsRef.current = {};\n seekTimestamps.current = [];\n lastSyncTs.current = null;\n setEvents([]);\n setSyncIntervalMs(null);\n setKindCounts({});\n setSeekRate(0);\n }, []);\n\n // Subscribe — enqueue events without touching React state\n useEffect(() => {\n if (!active) return;\n\n const unsubscribe = subscribeAudioEvents((event) => {\n const entry: AudioLogEntry = { ...event, id: String(++counterRef.current) };\n queueRef.current.push(entry);\n\n // Track sync interval (no setState — RAF will pick it up)\n if (event.kind === 'sync') {\n if (lastSyncTs.current !== null) {\n const interval = event.ts - lastSyncTs.current;\n // Store on ref; RAF flush will call setSyncIntervalMs\n (entry as AudioLogEntry & { _interval?: number })._interval = interval;\n }\n lastSyncTs.current = event.ts;\n }\n\n // Track seeks\n if (event.kind === 'seek') {\n seekTimestamps.current.push(event.ts);\n }\n\n // Accumulate kind counts on ref\n kindCountsRef.current = {\n ...kindCountsRef.current,\n [event.kind]: (kindCountsRef.current[event.kind] ?? 0) + 1,\n };\n });\n\n return unsubscribe;\n }, [active]);\n\n // RAF flush loop — drains queue into React state once per frame\n useEffect(() => {\n if (!active) return;\n let rafId: number;\n\n const flush = () => {\n if (queueRef.current.length > 0) {\n const incoming = queueRef.current.splice(0);\n\n // Extract sync interval from last sync event in batch\n const lastSync = [...incoming].reverse().find((e) => e.kind === 'sync') as\n | (AudioLogEntry & { _interval?: number })\n | undefined;\n if (lastSync?._interval !== undefined) {\n setSyncIntervalMs(lastSync._interval);\n }\n\n setEvents((prev) => {\n const next = [...prev, ...incoming];\n return next.length > MAX_EVENTS ? next.slice(-MAX_EVENTS) : next;\n });\n\n setKindCounts({ ...kindCountsRef.current });\n }\n rafId = requestAnimationFrame(flush);\n };\n\n rafId = requestAnimationFrame(flush);\n return () => cancelAnimationFrame(rafId);\n }, [active]);\n\n // Rolling seek rate — recompute every second\n useEffect(() => {\n if (!active) return;\n const id = setInterval(() => {\n const now = Date.now();\n seekTimestamps.current = seekTimestamps.current.filter((t) => now - t < 5000);\n setSeekRate(Math.round((seekTimestamps.current.length / 5) * 10) / 10);\n }, 1000);\n return () => clearInterval(id);\n }, [active]);\n\n return { events, clear, seekRate, syncIntervalMs, kindCounts };\n}\n","'use client';\n\nimport React, { useCallback, useState } from 'react';\nimport {\n Button,\n Badge,\n ScrollArea,\n} from '@djangocfg/ui-core/components';\nimport { cn } from '@djangocfg/ui-core/lib';\nimport { Trash2, Radio } from 'lucide-react';\nimport { useAudioEventLog } from '../hooks/useAudioEventLog';\nimport type { AudioEventKind } from '../emitters/audioEmitter';\n\n// ============================================================================\n// Types / constants\n// ============================================================================\n\ntype DebugAudioMode = 'off' | 'on' | 'verbose';\n\nconst DEBUG_MODES: DebugAudioMode[] = ['off', 'on', 'verbose'];\n\nconst KIND_STYLES: Record<AudioEventKind, { label: string; className: string }> = {\n play: { label: 'play', className: 'text-green-400' },\n pause: { label: 'pause', className: 'text-yellow-400' },\n seek: { label: 'seek', className: 'text-blue-400' },\n ended: { label: 'ended', className: 'text-muted-foreground' },\n sync: { label: 'sync', className: 'text-muted-foreground/50' },\n load: { label: 'load', className: 'text-purple-400' },\n error: { label: 'error', className: 'text-red-400' },\n engine: { label: 'eng', className: 'text-cyan-400' },\n custom: { label: 'custom', className: 'text-orange-400' },\n};\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\nfunction getDebugAudioMode(): DebugAudioMode {\n try {\n const v = localStorage.getItem('DEBUG_AUDIO');\n if (v === 'verbose') return 'verbose';\n if (v) return 'on';\n } catch { /* ssr */ }\n return 'off';\n}\n\nfunction formatTs(ts: number): string {\n const d = new Date(ts);\n return `${String(d.getHours()).padStart(2, '0')}:${String(d.getMinutes()).padStart(2, '0')}:${String(d.getSeconds()).padStart(2, '0')}.${String(d.getMilliseconds()).padStart(3, '0')}`;\n}\n\n// ============================================================================\n// Component\n// ============================================================================\n\ninterface AudioDebugPanelProps {\n isActive: boolean;\n}\n\nexport function AudioDebugPanel({ isActive }: AudioDebugPanelProps) {\n const { events, clear, seekRate, syncIntervalMs, kindCounts } = useAudioEventLog(isActive);\n const [debugMode, setDebugMode] = useState<DebugAudioMode>(getDebugAudioMode);\n\n const handleSetDebugAudio = useCallback((mode: DebugAudioMode) => {\n if (mode === 'off') {\n localStorage.removeItem('DEBUG_AUDIO');\n } else {\n localStorage.setItem('DEBUG_AUDIO', mode === 'verbose' ? 'verbose' : '1');\n }\n setDebugMode(mode);\n }, []);\n\n const kindEntries = Object.entries(kindCounts) as [AudioEventKind, number][];\n const activeKinds = kindEntries.filter(([, count]) => count > 0);\n const reversedEvents = [...events].reverse();\n\n return (\n <div className=\"flex flex-col h-full\">\n {/* Metrics bar */}\n <div className=\"flex flex-wrap items-center gap-2 border-b border-border px-3 py-2 text-xs\">\n <span className=\"text-muted-foreground\">\n Sync interval:{' '}\n <span className=\"text-foreground font-mono\">\n {syncIntervalMs !== null ? `${syncIntervalMs.toFixed(1)}ms` : '—'}\n </span>\n </span>\n <span className=\"text-muted-foreground\">\n Seeks/s: <span className=\"text-foreground font-mono\">{seekRate}</span>\n </span>\n <span className=\"text-muted-foreground\">\n Total: <span className=\"text-foreground font-mono\">{events.length}</span>\n </span>\n\n <div className=\"flex gap-1 flex-wrap ml-auto\">\n {activeKinds.map(([kind, count]) => (\n <Badge key={kind} variant=\"outline\" className={cn('text-[10px] px-1 py-0', KIND_STYLES[kind]?.className)}>\n {KIND_STYLES[kind]?.label ?? kind} {count}\n </Badge>\n ))}\n </div>\n\n <Button variant=\"ghost\" size=\"icon\" className=\"h-6 w-6 ml-1\" onClick={clear}>\n <Trash2 className=\"h-3.5 w-3.5\" />\n </Button>\n </div>\n\n {/* DEBUG_AUDIO toggles */}\n <div className=\"flex items-center gap-1.5 border-b border-border px-3 py-1.5\">\n <span className=\"text-[10px] text-muted-foreground mr-1\">DEBUG_AUDIO:</span>\n {DEBUG_MODES.map((mode) => (\n <button\n key={mode}\n type=\"button\"\n className={cn(\n 'text-[10px] px-2 py-0.5 rounded border transition-colors',\n debugMode === mode\n ? 'border-primary bg-primary/10 text-primary'\n : 'border-border hover:bg-muted text-muted-foreground'\n )}\n onClick={() => handleSetDebugAudio(mode)}\n >\n {mode}\n </button>\n ))}\n </div>\n\n {/* Event log */}\n <ScrollArea className=\"flex-1\">\n {reversedEvents.length === 0 ? (\n <div className=\"flex flex-col items-center justify-center py-10 text-muted-foreground\">\n <Radio className=\"h-8 w-8 mb-2 opacity-40\" />\n <p className=\"text-sm\">No audio events yet</p>\n <p className=\"text-xs mt-1\">\n Wire <code className=\"text-xs\">emitAudioEvent()</code> into your audio engine\n </p>\n </div>\n ) : (\n <div className=\"divide-y divide-border/30\">\n {reversedEvents.map((entry) => {\n const style = KIND_STYLES[entry.kind] ?? { label: entry.kind, className: 'text-foreground' };\n return (\n <div key={entry.id} className=\"flex items-start gap-2 px-3 py-1 text-xs\">\n <span className=\"font-mono text-muted-foreground shrink-0 w-[88px]\">{formatTs(entry.ts)}</span>\n <span className={cn('shrink-0 w-12 font-medium', style.className)}>{style.label}</span>\n {entry.trackId && (\n <span className=\"shrink-0 font-mono text-muted-foreground\">{entry.trackId.slice(0, 6)}</span>\n )}\n <span className=\"truncate text-foreground/80\">{entry.msg}</span>\n </div>\n );\n })}\n </div>\n )}\n </ScrollArea>\n </div>\n );\n}\n","'use client';\n\nimport React, { useMemo, useState, useEffect } from 'react';\nimport { installMonitorBridge } from './bridges';\nimport {\n Button,\n Badge,\n Tooltip,\n TooltipContent,\n TooltipTrigger,\n} from '@djangocfg/ui-core/components';\nimport { cn } from '@djangocfg/ui-core/lib';\nimport { useDebugErrorCount } from './logger';\nimport {\n X, Bug, Minimize2, Maximize2,\n ScrollText, Radio,\n} from 'lucide-react';\nimport { useDebugStore } from './store/debugStore';\nimport type { DebugTab } from './store/debugStore';\nimport { LogsPanel } from './panels/LogsPanel';\nimport { AudioDebugPanel } from './panels/AudioDebugPanel';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface CustomDebugTab {\n /** Unique id — will be added to DebugTab union at runtime */\n id: string;\n label: string;\n icon: React.ElementType;\n panel: React.ComponentType<{ isActive: boolean }>;\n}\n\nexport interface DebugPanelProps {\n /** Additional app-specific tabs */\n tabs?: CustomDebugTab[];\n position?: 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left';\n defaultHeight?: number;\n defaultWidth?: number;\n}\n\n// ============================================================================\n// Built-in tabs\n// ============================================================================\n\nconst BUILTIN_TABS = [\n { id: 'logs', label: 'Logs', icon: ScrollText },\n { id: 'audio', label: 'Audio', icon: Radio },\n] as const;\n\nconst POSITION_CLASSES: Record<NonNullable<DebugPanelProps['position']>, string> = {\n 'bottom-right': 'bottom-4 right-4',\n 'bottom-left': 'bottom-4 left-4',\n 'top-right': 'top-4 right-4',\n 'top-left': 'top-4 left-4',\n};\n\n// ============================================================================\n// Component\n// ============================================================================\n\nexport function DebugPanel({\n tabs: customTabs = [],\n position = 'bottom-left',\n defaultHeight = 480,\n defaultWidth = 560,\n}: DebugPanelProps) {\n const isOpen = useDebugStore((s) => s.isOpen);\n const activeTab = useDebugStore((s) => s.tab);\n const setTab = useDebugStore((s) => s.setTab);\n const close = useDebugStore((s) => s.close);\n const errorCount = useDebugErrorCount();\n\n const [isMinimized, setIsMinimized] = useState(false);\n\n useEffect(() => {\n const unsub = installMonitorBridge();\n return () => unsub?.();\n }, []);\n\n const allTabs = useMemo(() => [\n ...BUILTIN_TABS,\n ...customTabs.map((t) => ({ id: t.id, label: t.label, icon: t.icon })),\n ], [customTabs]);\n\n const panelHeight = isMinimized ? 48 : defaultHeight;\n\n if (!isOpen) return null;\n\n return (\n <div\n className={cn(\n 'fixed z-[100] flex flex-col overflow-hidden rounded-lg border border-border bg-background shadow-xl',\n POSITION_CLASSES[position]\n )}\n style={{ width: defaultWidth, height: panelHeight }}\n >\n {/* Header */}\n <div className=\"flex items-center gap-2 border-b border-border bg-muted/50 px-3 py-2 shrink-0\">\n <Bug className=\"h-4 w-4 text-primary\" />\n <span className=\"text-sm font-medium\">Debug</span>\n\n {errorCount > 0 && (\n <Badge variant=\"destructive\" className=\"ml-1 text-[10px]\">{errorCount} errors</Badge>\n )}\n\n {/* Tab bar */}\n {!isMinimized && (\n <div className=\"flex items-center gap-0.5 ml-3\">\n {allTabs.map((tab) => {\n const Icon = tab.icon;\n const isActive = activeTab === tab.id;\n return (\n <button\n key={tab.id}\n type=\"button\"\n onClick={() => setTab(tab.id as DebugTab)}\n className={cn(\n 'flex items-center gap-1.5 px-2 py-0.5 rounded text-xs transition-colors',\n isActive\n ? 'bg-background text-foreground shadow-sm'\n : 'text-muted-foreground hover:text-foreground hover:bg-muted'\n )}\n >\n <Icon className=\"h-3 w-3\" />\n {tab.label}\n </button>\n );\n })}\n </div>\n )}\n\n <div className=\"flex items-center gap-1 ml-auto\">\n <Tooltip>\n <TooltipTrigger asChild>\n <Button variant=\"ghost\" size=\"icon\" className=\"h-6 w-6\" onClick={() => setIsMinimized((v) => !v)}>\n {isMinimized ? <Maximize2 className=\"h-3.5 w-3.5\" /> : <Minimize2 className=\"h-3.5 w-3.5\" />}\n </Button>\n </TooltipTrigger>\n <TooltipContent>{isMinimized ? 'Expand' : 'Minimize'}</TooltipContent>\n </Tooltip>\n <Tooltip>\n <TooltipTrigger asChild>\n <Button variant=\"ghost\" size=\"icon\" className=\"h-6 w-6\" onClick={close}>\n <X className=\"h-3.5 w-3.5\" />\n </Button>\n </TooltipTrigger>\n <TooltipContent>Close</TooltipContent>\n </Tooltip>\n </div>\n </div>\n\n {/* Panel content */}\n {!isMinimized && (\n <div className=\"flex-1 overflow-hidden\">\n {activeTab === 'logs' && <LogsPanel isActive={activeTab === 'logs'} />}\n {activeTab === 'audio' && <AudioDebugPanel isActive={activeTab === 'audio'} />}\n {customTabs.map((tab) => {\n const Panel = tab.panel;\n return (\n <div key={tab.id} className={cn('h-full', activeTab !== tab.id && 'hidden')}>\n <Panel isActive={activeTab === tab.id} />\n </div>\n );\n })}\n </div>\n )}\n </div>\n );\n}\n","'use client';\n\nimport React, { useCallback, useEffect, useRef } from 'react';\nimport { Bug } from 'lucide-react';\nimport {\n Tooltip,\n TooltipContent,\n TooltipTrigger,\n} from '@djangocfg/ui-core/components';\nimport { cn } from '@djangocfg/ui-core/lib';\nimport { useDebugStore } from './store/debugStore';\nimport { useDebugShortcut } from './hooks/useDebugShortcut';\nimport { useDebugErrorCount } from './logger';\nimport { DebugPanel } from './DebugPanel';\nimport type { DebugPanelProps } from './DebugPanel';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface DebugButtonProps {\n className?: string;\n /** Props forwarded to DebugPanel */\n panel?: Omit<DebugPanelProps, never>;\n}\n\n// ============================================================================\n// Easter-egg: 5 clicks in 2 seconds → unlock\n// ============================================================================\n\nfunction useEasterEgg(onTriggered: () => void) {\n const clicks = useRef<number[]>([]);\n\n return useCallback(() => {\n const now = Date.now();\n clicks.current = [...clicks.current.filter((t) => now - t < 2000), now];\n if (clicks.current.length >= 5) {\n clicks.current = [];\n onTriggered();\n }\n }, [onTriggered]);\n}\n\n// ============================================================================\n// DebugButton\n// ============================================================================\n\nexport function DebugButton({ className, panel = {} }: DebugButtonProps) {\n const isOpen = useDebugStore((s) => s.isOpen);\n const isUnlocked = useDebugStore((s) => s.isUnlocked);\n const unlock = useDebugStore((s) => s.unlock);\n const toggle = useDebugStore((s) => s.toggle);\n const errorCount = useDebugErrorCount();\n\n const isDev = typeof process !== 'undefined' && process.env?.NODE_ENV !== 'production';\n\n // Keyboard shortcut\n useDebugShortcut();\n\n // Hide Next.js dev indicator badge while panel is open.\n // Uses MutationObserver because <nextjs-portal> is mounted asynchronously after hydration.\n useEffect(() => {\n if (typeof document === 'undefined') return;\n\n const apply = () => {\n document.querySelectorAll<HTMLElement>('nextjs-portal').forEach((el) => {\n el.style.display = isOpen ? 'none' : '';\n });\n };\n\n apply(); // handle already-mounted elements\n\n const observer = new MutationObserver(apply);\n observer.observe(document.body, { childList: true });\n\n return () => observer.disconnect();\n }, [isOpen]);\n\n // URL-based unlock: ?debug=1 (any non-empty value works, no secret key)\n useEffect(() => {\n if (typeof window === 'undefined') return;\n const params = new URLSearchParams(window.location.search);\n const key = params.get('debug');\n if (key) {\n unlock(key);\n params.delete('debug');\n const newUrl = `${window.location.pathname}${params.toString() ? `?${params.toString()}` : ''}${window.location.hash}`;\n window.history.replaceState(null, '', newUrl);\n }\n }, [unlock]);\n\n // Easter-egg: 5 clicks in 2s → unlock directly\n const handleEasterEggClick = useCallback(() => { unlock('1'); toggle(); }, [unlock, toggle]);\n const handleEasterEggTrigger = useEasterEgg(handleEasterEggClick);\n\n // Visibility guard\n if (!isDev && !isUnlocked) {\n // In prod: render invisible click trap for easter-egg (5 clicks to unlock)\n return (\n <div\n className=\"fixed bottom-5 left-5 w-9 h-9 z-[99999] opacity-0\"\n onClick={handleEasterEggTrigger}\n />\n );\n }\n\n return (\n <>\n {/* Trigger button — hidden when panel is open */}\n {!isOpen && (\n <div className=\"fixed bottom-5 left-16 z-[99999]\">\n <Tooltip>\n <TooltipTrigger asChild>\n <button\n type=\"button\"\n className={cn(\n 'relative w-9 h-9 flex items-center justify-center rounded-full',\n 'bg-black/80 backdrop-blur-xl',\n 'shadow-[0_0_0_1px_#171717,inset_0_0_0_1px_hsla(0,0%,100%,0.14),0px_16px_32px_-8px_rgba(0,0,0,0.24)]',\n 'transition-all duration-150 hover:scale-105',\n 'focus:outline-none focus-visible:ring-2 focus-visible:ring-white/50',\n errorCount > 0 && 'bg-red-600/90',\n className\n )}\n onClick={toggle}\n >\n <Bug className={cn('h-4 w-4', errorCount > 0 ? 'text-white' : 'text-white/80')} />\n {errorCount > 0 && (\n <span className=\"absolute -right-1 -top-1 flex h-4 min-w-4 items-center justify-center rounded-full bg-white text-[10px] font-semibold text-red-600 shadow-sm\">\n {errorCount}\n </span>\n )}\n </button>\n </TooltipTrigger>\n <TooltipContent side=\"top\">Debug Panel <kbd className=\"ml-1 text-[10px] opacity-60\">⌘D</kbd></TooltipContent>\n </Tooltip>\n </div>\n )}\n\n <DebugPanel {...panel} />\n </>\n );\n}\n","'use client';\n\nimport { useState, useEffect, useRef } from 'react';\n\n// ============================================================================\n// Shallow equal (avoids unnecessary re-renders)\n// ============================================================================\n\nfunction shallowEqual(a: unknown, b: unknown): boolean {\n if (a === b) return true;\n if (typeof a !== 'object' || typeof b !== 'object') return false;\n if (a === null || b === null) return false;\n const keysA = Object.keys(a as object);\n const keysB = Object.keys(b as object);\n if (keysA.length !== keysB.length) return false;\n for (const key of keysA) {\n if ((a as Record<string, unknown>)[key] !== (b as Record<string, unknown>)[key]) return false;\n }\n return true;\n}\n\n// ============================================================================\n// Hook\n// ============================================================================\n\n/**\n * Polling-based external Zustand store snapshot.\n *\n * Reads the store state via `getState()` on an interval — NOT via reactive\n * subscription. This prevents debug panel renders from being triggered by\n * high-frequency store updates and avoids Zustand v5 infinite loop issues\n * (returning new object references from selectors without useShallow).\n *\n * Only polls while `active` is true (panel tab is visible).\n *\n * @param getState A stable function that returns the current store state slice.\n * Use `() => useMyStore.getState()` — the hook ref-stabilizes it.\n * @param intervalMs Poll interval in ms. Default 200ms.\n * @param active Whether to poll. Pass `isActive` from panel props.\n *\n * @example\n * const snap = useStoreSnapshot(\n * () => useTimelineStore.getState(),\n * 200,\n * isActive\n * );\n */\nexport function useStoreSnapshot<T>(\n getState: () => T,\n intervalMs = 200,\n active = true,\n): T {\n const getStateRef = useRef(getState);\n getStateRef.current = getState;\n\n const [snapshot, setSnapshot] = useState<T>(() => getState());\n\n useEffect(() => {\n if (!active) return;\n\n const id = setInterval(() => {\n const next = getStateRef.current();\n setSnapshot((prev) => (shallowEqual(prev, next) ? prev : next));\n }, intervalMs);\n\n return () => clearInterval(id);\n }, [active, intervalMs]);\n\n return snapshot;\n}\n","'use client';\n\nimport React from 'react';\nimport { ScrollArea } from '@djangocfg/ui-core/components';\nimport { LazyJsonTree } from '@djangocfg/ui-tools';\nimport { Database } from 'lucide-react';\nimport { useStoreSnapshot } from '../hooks/useStoreSnapshot';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface StorePanelProps {\n /** Display label shown above the JSON tree */\n label: string;\n /**\n * Getter for the store state slice to display.\n * Use `() => useMyStore.getState()` — stable function ref is not required,\n * the hook handles stabilization internally.\n */\n getState: () => Record<string, unknown>;\n /**\n * Poll interval in ms. Default 200ms.\n * Use higher values for stores that update very frequently.\n */\n intervalMs?: number;\n /** Only polls when active (panel tab is visible) */\n isActive: boolean;\n}\n\n// ============================================================================\n// Component\n// ============================================================================\n\n/**\n * Generic Zustand store viewer for the debug panel.\n *\n * Uses polling (not reactive subscription) to read external store state.\n * This avoids Zustand v5 infinite loop issues and prevents the debug panel\n * from re-rendering on every store change.\n *\n * @example — in consuming app's custom tab:\n * import { StorePanel } from '@org/debuger';\n * import { useTimelineStore } from '@stores/timelineStore';\n *\n * <StorePanel\n * label=\"Timeline Store\"\n * getState={() => useTimelineStore.getState()}\n * isActive={isActive}\n * />\n */\nexport function StorePanel({ label, getState, intervalMs = 200, isActive }: StorePanelProps) {\n const snapshot = useStoreSnapshot(getState, intervalMs, isActive);\n\n return (\n <div className=\"flex flex-col h-full\">\n <div className=\"flex items-center gap-2 border-b border-border px-3 py-2 shrink-0\">\n <Database className=\"h-3.5 w-3.5 text-muted-foreground\" />\n <span className=\"text-xs font-medium text-muted-foreground\">{label}</span>\n <span className=\"ml-auto text-[10px] text-muted-foreground/60\">\n polling {intervalMs}ms\n </span>\n </div>\n <ScrollArea className=\"flex-1\">\n <div className=\"p-2\">\n <LazyJsonTree data={snapshot} mode=\"full\" />\n </div>\n </ScrollArea>\n </div>\n );\n}\n","'use client';\n\nimport { useState, useEffect, useRef, useCallback } from 'react';\nimport { subscribeCustomEvents } from '../emitters/customEmitter';\nimport type { CustomDebugEvent } from '../emitters/customEmitter';\n\nexport interface CustomLogEntry extends CustomDebugEvent {\n id: string;\n}\n\nconst MAX_EVENTS = 300;\n\n/**\n * Subscribes to custom channel events and maintains a ring-buffer per channel.\n * Pass `channel` to filter — or undefined to receive all channels.\n */\nexport function useCustomEventLog(active: boolean, channel?: string) {\n const [events, setEvents] = useState<CustomLogEntry[]>([]);\n const counterRef = useRef(0);\n\n const clear = useCallback(() => setEvents([]), []);\n\n useEffect(() => {\n if (!active) return;\n\n const unsubscribe = subscribeCustomEvents((event) => {\n if (channel && event.channel !== channel) return;\n const entry: CustomLogEntry = { ...event, id: String(++counterRef.current) };\n setEvents((prev) => {\n const next = [...prev, entry];\n return next.length > MAX_EVENTS ? next.slice(-MAX_EVENTS) : next;\n });\n });\n\n return unsubscribe;\n }, [active, channel]);\n\n return { events, clear };\n}\n"]}
@@ -0,0 +1,123 @@
1
+ 'use strict';
2
+
3
+ var zustand = require('zustand');
4
+
5
+ var __defProp = Object.defineProperty;
6
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
7
+ var MAX_LOGS = 1e3;
8
+ var DEFAULT_FILTER = {
9
+ levels: ["debug", "info", "warn", "error", "success"]
10
+ };
11
+ var _counter = 0;
12
+ function generateId() {
13
+ return `log-${Date.now()}-${++_counter}`;
14
+ }
15
+ __name(generateId, "generateId");
16
+ function matchesFilter(entry, filter) {
17
+ if (!filter.levels.includes(entry.level)) return false;
18
+ if (filter.component) {
19
+ if (!entry.component.toLowerCase().includes(filter.component.toLowerCase())) return false;
20
+ }
21
+ if (filter.search) {
22
+ const s = filter.search.toLowerCase();
23
+ const inMsg = entry.message.toLowerCase().includes(s);
24
+ const inData = entry.data ? JSON.stringify(entry.data).toLowerCase().includes(s) : false;
25
+ if (!inMsg && !inData) return false;
26
+ }
27
+ return true;
28
+ }
29
+ __name(matchesFilter, "matchesFilter");
30
+ var useDebugLogStore = zustand.create((set, get) => ({
31
+ logs: [],
32
+ filter: DEFAULT_FILTER,
33
+ addLog: /* @__PURE__ */ __name((entry) => {
34
+ const newEntry = {
35
+ ...entry,
36
+ id: generateId(),
37
+ timestamp: /* @__PURE__ */ new Date()
38
+ };
39
+ set((state) => {
40
+ const next = [...state.logs, newEntry];
41
+ return { logs: next.length > MAX_LOGS ? next.slice(-MAX_LOGS) : next };
42
+ });
43
+ }, "addLog"),
44
+ clearLogs: /* @__PURE__ */ __name(() => set({ logs: [] }), "clearLogs"),
45
+ setFilter: /* @__PURE__ */ __name((filter) => set((state) => ({ filter: { ...state.filter, ...filter } })), "setFilter"),
46
+ getFilteredLogs: /* @__PURE__ */ __name(() => {
47
+ const { logs, filter } = get();
48
+ return logs.filter((e) => matchesFilter(e, filter));
49
+ }, "getFilteredLogs"),
50
+ exportLogs: /* @__PURE__ */ __name(() => JSON.stringify(get().logs, null, 2), "exportLogs")
51
+ }));
52
+ var useDebugFilteredLogs = /* @__PURE__ */ __name(() => {
53
+ const logs = useDebugLogStore((s) => s.logs);
54
+ const filter = useDebugLogStore((s) => s.filter);
55
+ return logs.filter((e) => matchesFilter(e, filter));
56
+ }, "useDebugFilteredLogs");
57
+ var useDebugLogCount = /* @__PURE__ */ __name(() => useDebugLogStore((s) => s.logs.length), "useDebugLogCount");
58
+ var useDebugErrorCount = /* @__PURE__ */ __name(() => useDebugLogStore((s) => s.logs.filter((l) => l.level === "error").length), "useDebugErrorCount");
59
+ var isBrowser = typeof window !== "undefined";
60
+ function extractStack(data) {
61
+ if (!data) return { cleanData: void 0, stack: void 0 };
62
+ const cleanData = { ...data };
63
+ let stack;
64
+ if (data.error instanceof Error) {
65
+ stack = data.error.stack;
66
+ cleanData.error = { name: data.error.name, message: data.error.message };
67
+ } else if (typeof data.error === "object" && data.error !== null) {
68
+ const e = data.error;
69
+ if (typeof e.stack === "string") stack = e.stack;
70
+ if (typeof e.message === "string") cleanData.error = e.message;
71
+ }
72
+ return { cleanData, stack };
73
+ }
74
+ __name(extractStack, "extractStack");
75
+ function createDebugLogger(component) {
76
+ const write = /* @__PURE__ */ __name((level, message, data) => {
77
+ const { cleanData, stack } = extractStack(data);
78
+ if (isBrowser) {
79
+ useDebugLogStore.getState().addLog({ level, component, message, data: cleanData, stack });
80
+ }
81
+ {
82
+ const method = level === "error" ? "error" : level === "warn" ? "warn" : "log";
83
+ const prefix = `[${component}]`;
84
+ if (cleanData) {
85
+ console[method](prefix, message, cleanData);
86
+ } else {
87
+ console[method](prefix, message);
88
+ }
89
+ }
90
+ }, "write");
91
+ return {
92
+ debug: /* @__PURE__ */ __name((msg, data) => write("debug", msg, data), "debug"),
93
+ info: /* @__PURE__ */ __name((msg, data) => write("info", msg, data), "info"),
94
+ warn: /* @__PURE__ */ __name((msg, data) => write("warn", msg, data), "warn"),
95
+ error: /* @__PURE__ */ __name((msg, data) => write("error", msg, data), "error"),
96
+ success: /* @__PURE__ */ __name((msg, data) => write("success", msg, data), "success")
97
+ };
98
+ }
99
+ __name(createDebugLogger, "createDebugLogger");
100
+ function debugLog(component, level, message, data) {
101
+ const { cleanData, stack } = extractStack(data);
102
+ if (isBrowser) {
103
+ useDebugLogStore.getState().addLog({ level, component, message, data: cleanData, stack });
104
+ }
105
+ {
106
+ const method = level === "error" ? "error" : level === "warn" ? "warn" : "log";
107
+ if (cleanData) {
108
+ console[method](`[${component}]`, message, cleanData);
109
+ } else {
110
+ console[method](`[${component}]`, message);
111
+ }
112
+ }
113
+ }
114
+ __name(debugLog, "debugLog");
115
+
116
+ exports.createDebugLogger = createDebugLogger;
117
+ exports.debugLog = debugLog;
118
+ exports.useDebugErrorCount = useDebugErrorCount;
119
+ exports.useDebugFilteredLogs = useDebugFilteredLogs;
120
+ exports.useDebugLogCount = useDebugLogCount;
121
+ exports.useDebugLogStore = useDebugLogStore;
122
+ //# sourceMappingURL=index.cjs.map
123
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/logger/logStore.ts","../../src/logger/logger.ts"],"names":["create"],"mappings":"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","file":"index.cjs","sourcesContent":["'use client';\n\nimport { create } from 'zustand';\nimport type { LogStore, LogEntry, LogFilter } from './types';\n\n// ============================================================================\n// Constants\n// ============================================================================\n\nconst MAX_LOGS = 1000;\n\nconst DEFAULT_FILTER: LogFilter = {\n levels: ['debug', 'info', 'warn', 'error', 'success'],\n};\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\nlet _counter = 0;\n\nfunction generateId(): string {\n return `log-${Date.now()}-${++_counter}`;\n}\n\nfunction matchesFilter(entry: LogEntry, filter: LogFilter): boolean {\n if (!filter.levels.includes(entry.level)) return false;\n\n if (filter.component) {\n if (!entry.component.toLowerCase().includes(filter.component.toLowerCase())) return false;\n }\n\n if (filter.search) {\n const s = filter.search.toLowerCase();\n const inMsg = entry.message.toLowerCase().includes(s);\n const inData = entry.data ? JSON.stringify(entry.data).toLowerCase().includes(s) : false;\n if (!inMsg && !inData) return false;\n }\n\n return true;\n}\n\n// ============================================================================\n// Store\n// ============================================================================\n\nexport const useDebugLogStore = create<LogStore>((set, get) => ({\n logs: [],\n filter: DEFAULT_FILTER,\n\n addLog: (entry) => {\n const newEntry: LogEntry = {\n ...entry,\n id: generateId(),\n timestamp: new Date(),\n };\n set((state) => {\n const next = [...state.logs, newEntry];\n return { logs: next.length > MAX_LOGS ? next.slice(-MAX_LOGS) : next };\n });\n },\n\n clearLogs: () => set({ logs: [] }),\n\n setFilter: (filter) =>\n set((state) => ({ filter: { ...state.filter, ...filter } })),\n\n getFilteredLogs: () => {\n const { logs, filter } = get();\n return logs.filter((e) => matchesFilter(e, filter));\n },\n\n exportLogs: () => JSON.stringify(get().logs, null, 2),\n}));\n\n// ============================================================================\n// Selector hooks\n// ============================================================================\n\nexport const useDebugFilteredLogs = () => {\n const logs = useDebugLogStore((s) => s.logs);\n const filter = useDebugLogStore((s) => s.filter);\n return logs.filter((e) => matchesFilter(e, filter));\n};\n\nexport const useDebugLogCount = () => useDebugLogStore((s) => s.logs.length);\n\nexport const useDebugErrorCount = () =>\n useDebugLogStore((s) => s.logs.filter((l) => l.level === 'error').length);\n","/**\n * Debug Logger\n *\n * Standalone logger for @djangocfg/debuger — no ui-core dependency.\n * Writes to useDebugLogStore (shown in LogsPanel) and to console in dev.\n */\n\nimport { useDebugLogStore } from './logStore';\nimport type { Logger, LogLevel } from './types';\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\nconst isDev = process.env.NODE_ENV !== 'production';\nconst isBrowser = typeof window !== 'undefined';\n\nfunction extractStack(data?: Record<string, unknown>): {\n cleanData: Record<string, unknown> | undefined;\n stack: string | undefined;\n} {\n if (!data) return { cleanData: undefined, stack: undefined };\n\n const cleanData = { ...data };\n let stack: string | undefined;\n\n if (data.error instanceof Error) {\n stack = data.error.stack;\n cleanData.error = { name: data.error.name, message: data.error.message };\n } else if (typeof data.error === 'object' && data.error !== null) {\n const e = data.error as Record<string, unknown>;\n if (typeof e.stack === 'string') stack = e.stack;\n if (typeof e.message === 'string') cleanData.error = e.message;\n }\n\n return { cleanData, stack };\n}\n\n// ============================================================================\n// createLogger\n// ============================================================================\n\nexport function createDebugLogger(component: string): Logger {\n const write = (level: LogLevel, message: string, data?: Record<string, unknown>) => {\n const { cleanData, stack } = extractStack(data);\n\n if (isBrowser) {\n useDebugLogStore.getState().addLog({ level, component, message, data: cleanData, stack });\n }\n\n if (isDev) {\n const method = level === 'error' ? 'error' : level === 'warn' ? 'warn' : 'log';\n const prefix = `[${component}]`;\n if (cleanData) {\n console[method](prefix, message, cleanData);\n } else {\n console[method](prefix, message);\n }\n }\n };\n\n return {\n debug: (msg, data) => write('debug', msg, data),\n info: (msg, data) => write('info', msg, data),\n warn: (msg, data) => write('warn', msg, data),\n error: (msg, data) => write('error', msg, data),\n success: (msg, data) => write('success', msg, data),\n };\n}\n\n// ============================================================================\n// debugLog — one-shot helper (creates logger on each call, for non-hot paths)\n// ============================================================================\n\nexport function debugLog(\n component: string,\n level: LogLevel,\n message: string,\n data?: Record<string, unknown>,\n): void {\n const { cleanData, stack } = extractStack(data);\n\n if (isBrowser) {\n useDebugLogStore.getState().addLog({ level, component, message, data: cleanData, stack });\n }\n\n if (isDev) {\n const method = level === 'error' ? 'error' : level === 'warn' ? 'warn' : 'log';\n if (cleanData) {\n console[method](`[${component}]`, message, cleanData);\n } else {\n console[method](`[${component}]`, message);\n }\n }\n}\n"]}
@@ -0,0 +1,50 @@
1
+ import * as zustand from 'zustand';
2
+
3
+ type LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'success';
4
+ interface LogEntry {
5
+ id: string;
6
+ timestamp: Date;
7
+ level: LogLevel;
8
+ component: string;
9
+ message: string;
10
+ data?: Record<string, unknown>;
11
+ stack?: string;
12
+ }
13
+ interface LogFilter {
14
+ levels: LogLevel[];
15
+ component?: string;
16
+ search?: string;
17
+ }
18
+ interface LogStore {
19
+ logs: LogEntry[];
20
+ filter: LogFilter;
21
+ addLog: (entry: Omit<LogEntry, 'id' | 'timestamp'>) => void;
22
+ clearLogs: () => void;
23
+ setFilter: (filter: Partial<LogFilter>) => void;
24
+ getFilteredLogs: () => LogEntry[];
25
+ exportLogs: () => string;
26
+ }
27
+ interface Logger {
28
+ debug: (message: string, data?: Record<string, unknown>) => void;
29
+ info: (message: string, data?: Record<string, unknown>) => void;
30
+ warn: (message: string, data?: Record<string, unknown>) => void;
31
+ error: (message: string, data?: Record<string, unknown>) => void;
32
+ success: (message: string, data?: Record<string, unknown>) => void;
33
+ }
34
+
35
+ /**
36
+ * Debug Logger
37
+ *
38
+ * Standalone logger for @djangocfg/debuger — no ui-core dependency.
39
+ * Writes to useDebugLogStore (shown in LogsPanel) and to console in dev.
40
+ */
41
+
42
+ declare function createDebugLogger(component: string): Logger;
43
+ declare function debugLog(component: string, level: LogLevel, message: string, data?: Record<string, unknown>): void;
44
+
45
+ declare const useDebugLogStore: zustand.UseBoundStore<zustand.StoreApi<LogStore>>;
46
+ declare const useDebugFilteredLogs: () => LogEntry[];
47
+ declare const useDebugLogCount: () => number;
48
+ declare const useDebugErrorCount: () => number;
49
+
50
+ export { type LogEntry, type LogFilter, type LogLevel, type LogStore, type Logger, createDebugLogger, debugLog, useDebugErrorCount, useDebugFilteredLogs, useDebugLogCount, useDebugLogStore };
@@ -0,0 +1,4 @@
1
+ export { createDebugLogger, debugLog, useDebugErrorCount, useDebugFilteredLogs, useDebugLogCount, useDebugLogStore } from '../chunk-ESIQODSI.mjs';
2
+ import '../chunk-PAWJFY3S.mjs';
3
+ //# sourceMappingURL=index.mjs.map
4
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"index.mjs"}
package/package.json ADDED
@@ -0,0 +1,67 @@
1
+ {
2
+ "name": "@djangocfg/debuger",
3
+ "version": "2.1.219",
4
+ "description": "Floating debug panel for DjangoCFG — logs, audio engine, store inspection, monitor bridge",
5
+ "type": "module",
6
+ "main": "./dist/index.cjs",
7
+ "module": "./dist/index.mjs",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.mjs",
13
+ "require": "./dist/index.cjs"
14
+ },
15
+ "./emitters": {
16
+ "types": "./dist/emitters/index.d.ts",
17
+ "import": "./dist/emitters/index.mjs",
18
+ "require": "./dist/emitters/index.cjs"
19
+ },
20
+ "./logger": {
21
+ "types": "./dist/logger/index.d.ts",
22
+ "import": "./dist/logger/index.mjs",
23
+ "require": "./dist/logger/index.cjs"
24
+ },
25
+ "./styles": "./src/styles/index.css"
26
+ },
27
+ "files": [
28
+ "dist",
29
+ "src"
30
+ ],
31
+ "scripts": {
32
+ "build": "tsup",
33
+ "dev": "tsup --watch",
34
+ "check": "tsc --noEmit",
35
+ "clean": "rm -rf dist",
36
+ "playground": "pnpm --filter @djangocfg/debuger-playground dev"
37
+ },
38
+ "peerDependencies": {
39
+ "react": "^19.1.0",
40
+ "react-dom": "^19.1.0",
41
+ "zustand": "^5.0.0",
42
+ "consola": "^3.4.2",
43
+ "@djangocfg/ui-core": "^2.1.219",
44
+ "@djangocfg/ui-tools": "^2.1.219",
45
+ "@tanstack/react-virtual": "^3.0.0",
46
+ "@djangocfg/monitor": "^2.1.219",
47
+ "lucide-react": ">=0.400.0"
48
+ },
49
+ "peerDependenciesMeta": {
50
+ "@djangocfg/monitor": {
51
+ "optional": true
52
+ },
53
+ "lucide-react": {
54
+ "optional": false
55
+ }
56
+ },
57
+ "devDependencies": {
58
+ "@djangocfg/typescript-config": "^2.1.219",
59
+ "@djangocfg/monitor": "^2.1.219",
60
+ "lucide-react": "^0.545.0",
61
+ "@types/node": "^25.2.3",
62
+ "@types/react": "^19.1.0",
63
+ "@types/react-dom": "^19.1.0",
64
+ "tsup": "^8.5.0",
65
+ "typescript": "^5.9.3"
66
+ }
67
+ }
@@ -0,0 +1,143 @@
1
+ 'use client';
2
+
3
+ import React, { useCallback, useEffect, useRef } from 'react';
4
+ import { Bug } from 'lucide-react';
5
+ import {
6
+ Tooltip,
7
+ TooltipContent,
8
+ TooltipTrigger,
9
+ } from '@djangocfg/ui-core/components';
10
+ import { cn } from '@djangocfg/ui-core/lib';
11
+ import { useDebugStore } from './store/debugStore';
12
+ import { useDebugShortcut } from './hooks/useDebugShortcut';
13
+ import { useDebugErrorCount } from './logger';
14
+ import { DebugPanel } from './DebugPanel';
15
+ import type { DebugPanelProps } from './DebugPanel';
16
+
17
+ // ============================================================================
18
+ // Types
19
+ // ============================================================================
20
+
21
+ export interface DebugButtonProps {
22
+ className?: string;
23
+ /** Props forwarded to DebugPanel */
24
+ panel?: Omit<DebugPanelProps, never>;
25
+ }
26
+
27
+ // ============================================================================
28
+ // Easter-egg: 5 clicks in 2 seconds → unlock
29
+ // ============================================================================
30
+
31
+ function useEasterEgg(onTriggered: () => void) {
32
+ const clicks = useRef<number[]>([]);
33
+
34
+ return useCallback(() => {
35
+ const now = Date.now();
36
+ clicks.current = [...clicks.current.filter((t) => now - t < 2000), now];
37
+ if (clicks.current.length >= 5) {
38
+ clicks.current = [];
39
+ onTriggered();
40
+ }
41
+ }, [onTriggered]);
42
+ }
43
+
44
+ // ============================================================================
45
+ // DebugButton
46
+ // ============================================================================
47
+
48
+ export function DebugButton({ className, panel = {} }: DebugButtonProps) {
49
+ const isOpen = useDebugStore((s) => s.isOpen);
50
+ const isUnlocked = useDebugStore((s) => s.isUnlocked);
51
+ const unlock = useDebugStore((s) => s.unlock);
52
+ const toggle = useDebugStore((s) => s.toggle);
53
+ const errorCount = useDebugErrorCount();
54
+
55
+ const isDev = typeof process !== 'undefined' && process.env?.NODE_ENV !== 'production';
56
+
57
+ // Keyboard shortcut
58
+ useDebugShortcut();
59
+
60
+ // Hide Next.js dev indicator badge while panel is open.
61
+ // Uses MutationObserver because <nextjs-portal> is mounted asynchronously after hydration.
62
+ useEffect(() => {
63
+ if (typeof document === 'undefined') return;
64
+
65
+ const apply = () => {
66
+ document.querySelectorAll<HTMLElement>('nextjs-portal').forEach((el) => {
67
+ el.style.display = isOpen ? 'none' : '';
68
+ });
69
+ };
70
+
71
+ apply(); // handle already-mounted elements
72
+
73
+ const observer = new MutationObserver(apply);
74
+ observer.observe(document.body, { childList: true });
75
+
76
+ return () => observer.disconnect();
77
+ }, [isOpen]);
78
+
79
+ // URL-based unlock: ?debug=1 (any non-empty value works, no secret key)
80
+ useEffect(() => {
81
+ if (typeof window === 'undefined') return;
82
+ const params = new URLSearchParams(window.location.search);
83
+ const key = params.get('debug');
84
+ if (key) {
85
+ unlock(key);
86
+ params.delete('debug');
87
+ const newUrl = `${window.location.pathname}${params.toString() ? `?${params.toString()}` : ''}${window.location.hash}`;
88
+ window.history.replaceState(null, '', newUrl);
89
+ }
90
+ }, [unlock]);
91
+
92
+ // Easter-egg: 5 clicks in 2s → unlock directly
93
+ const handleEasterEggClick = useCallback(() => { unlock('1'); toggle(); }, [unlock, toggle]);
94
+ const handleEasterEggTrigger = useEasterEgg(handleEasterEggClick);
95
+
96
+ // Visibility guard
97
+ if (!isDev && !isUnlocked) {
98
+ // In prod: render invisible click trap for easter-egg (5 clicks to unlock)
99
+ return (
100
+ <div
101
+ className="fixed bottom-5 left-5 w-9 h-9 z-[99999] opacity-0"
102
+ onClick={handleEasterEggTrigger}
103
+ />
104
+ );
105
+ }
106
+
107
+ return (
108
+ <>
109
+ {/* Trigger button — hidden when panel is open */}
110
+ {!isOpen && (
111
+ <div className="fixed bottom-5 left-16 z-[99999]">
112
+ <Tooltip>
113
+ <TooltipTrigger asChild>
114
+ <button
115
+ type="button"
116
+ className={cn(
117
+ 'relative w-9 h-9 flex items-center justify-center rounded-full',
118
+ 'bg-black/80 backdrop-blur-xl',
119
+ 'shadow-[0_0_0_1px_#171717,inset_0_0_0_1px_hsla(0,0%,100%,0.14),0px_16px_32px_-8px_rgba(0,0,0,0.24)]',
120
+ 'transition-all duration-150 hover:scale-105',
121
+ 'focus:outline-none focus-visible:ring-2 focus-visible:ring-white/50',
122
+ errorCount > 0 && 'bg-red-600/90',
123
+ className
124
+ )}
125
+ onClick={toggle}
126
+ >
127
+ <Bug className={cn('h-4 w-4', errorCount > 0 ? 'text-white' : 'text-white/80')} />
128
+ {errorCount > 0 && (
129
+ <span className="absolute -right-1 -top-1 flex h-4 min-w-4 items-center justify-center rounded-full bg-white text-[10px] font-semibold text-red-600 shadow-sm">
130
+ {errorCount}
131
+ </span>
132
+ )}
133
+ </button>
134
+ </TooltipTrigger>
135
+ <TooltipContent side="top">Debug Panel <kbd className="ml-1 text-[10px] opacity-60">⌘D</kbd></TooltipContent>
136
+ </Tooltip>
137
+ </div>
138
+ )}
139
+
140
+ <DebugPanel {...panel} />
141
+ </>
142
+ );
143
+ }