gramobase 1.0.11 → 1.0.13

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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/studio/ui.ts","../../src/workers/BotWorkerPool.ts","../../src/cache/HotCache.ts","../../src/storage/TelegramStorage.ts","../../src/wal/WriteAheadLog.ts","../../src/registry/Registry.ts","../../src/orm/Collection.ts","../../src/auth/GramoBaseAuth.ts","../../src/realtime/RealtimeManager.ts","../../src/migrations/MigrationRunner.ts","../../src/index.ts","../../src/studio/server.ts"],"names":["EventEmitter","TelegramBot","PQueue","pRetry","AbortError","LRUCache","createHash","randomBytes","createCipheriv","createDecipheriv","randomUUID","lease","z","existsSync","readFileSync","bcrypt","jwt","UserSchema","path","fs","http"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAIA,IAAM,GAAA,GAAM;AAAA,EAEV,KAAA,EAAU,CAAA,uTAAA,CAAA;AAAA,EACV,KAAA,EAAU,CAAA,sWAAA,CAAA;AAAA,EACV,KAAA,EAAU,CAAA,2OAAA,CAAA;AAAA,EACV,GAAA,EAAU,CAAA,uUAAA,CAAA;AAAA,EACV,MAAA,EAAU,CAAA,8QAAA,CAAA;AAAA,EACV,GAAA,EAAU,CAAA,kNAAA,CAAA;AAAA,EACV,GAAA,EAAU,CAAA,sYAAA,CAAA;AAAA,EACV,IAAA,EAAU,CAAA,6SAAA,CAAA;AAAA,EACV,IAAA,EAAU,CAAA,4TAAA,CAAA;AAAA,EACV,OAAA,EAAU,CAAA,mUAAA,CAAA;AAAA,EACV,KAAA,EAAU,CAAA,4UAAA,CAAA;AAAA,EACV,CAAA,EAAU,CAAA,oOAAA,CAAA;AAAA,EACV,OAAA,EAAU,CAAA,oQAAA,CAAA;AAAA,EACV,KAAA,EAAU,CAAA,sUAAA,CAAA;AAAA,EACV,QAAA,EAAU,CAAA,8MAAA,CAAA;AAAA,EACV,OAAA,EAAU,CAAA,8LAAA,CAAA;AAAA,EACV,QAAA,EAAU,CAAA,6LAAA,CAAA;AAAA,EACV,MAAA,EAAU,CAAA,8LAAA,CAAA;AAAA,EACV,MAAA,EAAU,CAAA,6LAAA,CAAA;AAAA,EACV,MAAA,EAAU,CAAA,4PAAA,CAAA;AAAA,EACV,KAAA,EAAU,CAAA,6LAAA,CAAA;AAAA,EACV,MAAA,EAAU,CAAA,oOAAA;AACZ,CAAA;AAEO,SAAS,aAAA,GAAwB;AACtC,EAAA,OAAO,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;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","file":"server.cjs","sourcesContent":["// gramobase studio — self-contained browser UI\n// Returns the full HTML page as a string — no bundler needed.\n\n// ─── Inline Lucide-style SVG icons ──────────────────────────────────────────\nconst ico = {\n db: `<svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><ellipse cx=\"12\" cy=\"5\" rx=\"9\" ry=\"3\"/><path d=\"M3 5v14a9 3 0 0 0 18 0V5\"/><path d=\"M3 12a9 3 0 0 0 18 0\"/></svg>`,\n gauge: `<svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M12 2a10 10 0 1 0 10 10\"/><path d=\"M12 2v4\"/><path d=\"m4.93 4.93 2.83 2.83\"/><path d=\"M22 12h-4\"/><path d=\"m15 9 3-3\"/><circle cx=\"12\" cy=\"12\" r=\"3\"/></svg>`,\n radio: `<svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M4.9 19.1C1 15.2 1 8.8 4.9 4.9\"/><path d=\"M7.8 16.2c-2.3-2.3-2.3-6.1 0-8.5\"/><circle cx=\"12\" cy=\"12\" r=\"2\"/><path d=\"M16.2 7.8c2.3 2.3 2.3 6.1 0 8.5\"/><path d=\"M19.1 4.9C23 8.8 23 15.2 19.1 19.1\"/></svg>`,\n table: `<svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M3 3h18v18H3z\"/><path d=\"M3 9h18\"/><path d=\"M3 15h18\"/><path d=\"M9 3v18\"/></svg>`,\n bot: `<svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"3\" y=\"11\" width=\"18\" height=\"10\" rx=\"2\"/><circle cx=\"12\" cy=\"5\" r=\"2\"/><path d=\"M12 7v4\"/><line x1=\"8\" y1=\"16\" x2=\"8\" y2=\"16\"/><line x1=\"16\" y1=\"16\" x2=\"16\" y2=\"16\"/></svg>`,\n layers: `<svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polygon points=\"12 2 2 7 12 12 22 7 12 2\"/><polyline points=\"2 17 12 22 22 17\"/><polyline points=\"2 12 12 17 22 12\"/></svg>`,\n zap: `<svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polygon points=\"13 2 3 14 12 14 11 22 21 10 12 10 13 2\"/></svg>`,\n hdd: `<svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><line x1=\"22\" y1=\"12\" x2=\"2\" y2=\"12\"/><path d=\"M5.45 5.11 2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.45-6.89A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11z\"/><line x1=\"6\" y1=\"16\" x2=\"6.01\" y2=\"16\"/><line x1=\"10\" y1=\"16\" x2=\"10.01\" y2=\"16\"/></svg>`,\n hash: `<svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><line x1=\"4\" y1=\"9\" x2=\"20\" y2=\"9\"/><line x1=\"4\" y1=\"15\" x2=\"20\" y2=\"15\"/><line x1=\"10\" y1=\"3\" x2=\"8\" y2=\"21\"/><line x1=\"16\" y1=\"3\" x2=\"14\" y2=\"21\"/></svg>`,\n grid: `<svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"3\" y=\"3\" width=\"7\" height=\"7\"/><rect x=\"14\" y=\"3\" width=\"7\" height=\"7\"/><rect x=\"3\" y=\"14\" width=\"7\" height=\"7\"/><rect x=\"14\" y=\"14\" width=\"7\" height=\"7\"/></svg>`,\n refresh: `<svg width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8\"/><path d=\"M21 3v5h-5\"/><path d=\"M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16\"/><path d=\"M3 21v-5h5\"/></svg>`,\n trash: `<svg width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"3 6 5 6 21 6\"/><path d=\"M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6\"/><path d=\"M10 11v6\"/><path d=\"M14 11v6\"/><path d=\"M9 6V4a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v2\"/></svg>`,\n x: `<svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"/><line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"/></svg>`,\n xCircle: `<svg width=\"36\" height=\"36\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><circle cx=\"12\" cy=\"12\" r=\"10\"/><line x1=\"15\" y1=\"9\" x2=\"9\" y2=\"15\"/><line x1=\"9\" y1=\"9\" x2=\"15\" y2=\"15\"/></svg>`,\n inbox: `<svg width=\"36\" height=\"36\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"22 12 16 12 14 15 10 15 8 12 2 12\"/><path d=\"M5.45 5.11 2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.45-6.89A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11z\"/></svg>`,\n activity: `<svg width=\"36\" height=\"36\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"22 12 18 12 15 21 9 3 6 12 2 12\"/></svg>`,\n sortAsc: `<svg width=\"11\" height=\"11\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"18 15 12 9 6 15\"/></svg>`,\n sortDesc: `<svg width=\"11\" height=\"11\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"6 9 12 15 18 9\"/></svg>`,\n chevrL: `<svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"15 18 9 12 15 6\"/></svg>`,\n chevrR: `<svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"9 18 15 12 9 6\"/></svg>`,\n logoDb: `<svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><ellipse cx=\"12\" cy=\"5\" rx=\"9\" ry=\"3\"/><path d=\"M3 5v14a9 3 0 0 0 18 0V5\"/><path d=\"M3 12a9 3 0 0 0 18 0\"/></svg>`,\n check: `<svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"20 6 9 17 4 12\"/></svg>`,\n close2: `<svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"/><line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"/></svg>`,\n};\n\nexport function getStudioHTML(): string {\n return `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n <title>gramobase studio</title>\n <link rel=\"preconnect\" href=\"https://fonts.googleapis.com\" />\n <link rel=\"preconnect\" href=\"https://fonts.gstatic.com\" crossorigin />\n <link href=\"https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap\" rel=\"stylesheet\" />\n <style>\n *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }\n\n :root {\n --bg: #0a0b0e;\n --bg2: #111318;\n --bg3: #181b22;\n --bg4: #1e2230;\n --border: rgba(255,255,255,0.07);\n --border2: rgba(255,255,255,0.12);\n --accent: #3b82f6;\n --accent2: #60a5fa;\n --accent-glow:rgba(59,130,246,0.25);\n --green: #22c55e;\n --red: #ef4444;\n --yellow: #f59e0b;\n --purple: #a78bfa;\n --teal: #2dd4bf;\n --text: #e2e8f0;\n --text2: #94a3b8;\n --text3: #475569;\n --radius: 10px;\n --font-mono: 'JetBrains Mono', monospace;\n --sidebar-w: 240px;\n }\n\n html, body { height: 100%; background: var(--bg); color: var(--text); font-family: 'Inter', sans-serif; font-size: 14px; }\n\n /* ── LAYOUT ──────────────────────────────────────────────────── */\n #app { display: flex; height: 100vh; overflow: hidden; }\n\n /* ── SIDEBAR ─────────────────────────────────────────────────── */\n #sidebar {\n width: var(--sidebar-w); min-width: var(--sidebar-w);\n background: var(--bg2);\n border-right: 1px solid var(--border);\n display: flex; flex-direction: column;\n overflow: hidden;\n }\n #sidebar-header {\n padding: 18px 16px 14px;\n border-bottom: 1px solid var(--border);\n display: flex; align-items: center; gap: 10px;\n }\n .logo-icon {\n width: 28px; height: 28px; border-radius: 7px;\n background: linear-gradient(135deg, var(--accent), var(--purple));\n display: flex; align-items: center; justify-content: center;\n flex-shrink: 0;\n box-shadow: 0 0 16px var(--accent-glow);\n }\n .logo-icon svg { display: block; }\n .logo-text { font-weight: 700; font-size: 15px; letter-spacing: -0.3px; }\n .logo-badge {\n font-size: 9px; font-weight: 600; padding: 1px 5px; border-radius: 4px;\n background: var(--accent-glow); color: var(--accent2);\n border: 1px solid var(--accent); margin-left: auto;\n }\n #sidebar-nav { flex: 1; overflow-y: auto; padding: 10px 0; }\n .nav-section { padding: 6px 16px 4px; font-size: 10px; font-weight: 600; letter-spacing: 0.8px; text-transform: uppercase; color: var(--text3); }\n .nav-item {\n display: flex; align-items: center; gap: 9px;\n padding: 7px 16px; cursor: pointer; border-radius: 0;\n color: var(--text2); font-size: 13px; transition: all 0.15s;\n border-left: 2px solid transparent;\n }\n .nav-item:hover { background: var(--bg3); color: var(--text); }\n .nav-item.active { background: var(--bg4); color: var(--accent2); border-left-color: var(--accent); }\n .nav-item svg { flex-shrink: 0; opacity: 0.7; }\n .nav-item.active svg, .nav-item:hover svg { opacity: 1; }\n .nav-item-count {\n margin-left: auto; font-size: 10px; padding: 1px 6px; border-radius: 10px;\n background: var(--bg4); color: var(--text3); font-family: var(--font-mono);\n }\n #sidebar-footer {\n padding: 12px 16px;\n border-top: 1px solid var(--border);\n font-size: 11px; color: var(--text3);\n display: flex; align-items: center; gap: 6px;\n }\n .status-dot { width: 6px; height: 6px; border-radius: 50%; background: var(--green); flex-shrink: 0; box-shadow: 0 0 6px var(--green); }\n .status-dot.red { background: var(--red); box-shadow: 0 0 6px var(--red); }\n\n /* ── MAIN ────────────────────────────────────────────────────── */\n #main { flex: 1; display: flex; flex-direction: column; overflow: hidden; }\n\n /* ── TOPBAR ──────────────────────────────────────────────────── */\n #topbar {\n height: 52px; display: flex; align-items: center; gap: 12px;\n padding: 0 20px;\n background: var(--bg2); border-bottom: 1px solid var(--border);\n flex-shrink: 0;\n }\n #topbar-title { font-weight: 600; font-size: 15px; }\n #topbar-sub { font-size: 12px; color: var(--text3); }\n #topbar-actions { margin-left: auto; display: flex; gap: 8px; align-items: center; }\n .btn {\n display: inline-flex; align-items: center; gap: 6px;\n padding: 5px 12px; border-radius: 6px; border: 1px solid var(--border2);\n background: var(--bg3); color: var(--text2); cursor: pointer;\n font-size: 12px; font-family: 'Inter', sans-serif;\n transition: all 0.15s;\n }\n .btn:hover { background: var(--bg4); color: var(--text); border-color: var(--accent); }\n .btn svg { flex-shrink: 0; }\n\n /* ── CONTENT ─────────────────────────────────────────────────── */\n #content { flex: 1; overflow: hidden; position: relative; }\n .panel { display: none; height: 100%; overflow-y: auto; }\n .panel.active { display: block; }\n\n /* ── OVERVIEW PANEL ──────────────────────────────────────────── */\n #panel-overview { padding: 24px; }\n .stats-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 14px; margin-bottom: 28px; }\n .stat-card {\n background: var(--bg2); border: 1px solid var(--border);\n border-radius: var(--radius); padding: 18px;\n transition: border-color 0.2s;\n }\n .stat-card:hover { border-color: var(--border2); }\n .stat-icon-wrap {\n width: 34px; height: 34px; border-radius: 8px;\n display: flex; align-items: center; justify-content: center;\n margin-bottom: 12px; flex-shrink: 0;\n }\n .stat-icon-wrap.blue { background: rgba(59,130,246,0.12); color: var(--accent2); }\n .stat-icon-wrap.purple{ background: rgba(167,139,250,0.12); color: var(--purple); }\n .stat-icon-wrap.green { background: rgba(34,197,94,0.12); color: var(--green); }\n .stat-icon-wrap.teal { background: rgba(45,212,191,0.12); color: var(--teal); }\n .stat-icon-wrap.yellow{ background: rgba(245,158,11,0.12); color: var(--yellow); }\n .stat-label { font-size: 11px; color: var(--text3); font-weight: 500; letter-spacing: 0.5px; text-transform: uppercase; margin-bottom: 6px; }\n .stat-value { font-size: 26px; font-weight: 700; letter-spacing: -0.5px; }\n .stat-sub { font-size: 11px; color: var(--text3); margin-top: 4px; }\n .stat-value.green { color: var(--green); }\n .stat-value.blue { color: var(--accent2); }\n .stat-value.purple { color: var(--purple); }\n .stat-value.yellow { color: var(--yellow); }\n .stat-value.teal { color: var(--teal); }\n\n .section-title { font-size: 13px; font-weight: 600; color: var(--text2); margin-bottom: 12px; display: flex; align-items: center; gap: 8px; }\n .section-title::after { content: ''; flex: 1; height: 1px; background: var(--border); }\n\n /* ── BOT STATUS ──────────────────────────────────────────────── */\n .info-card {\n background: var(--bg2); border: 1px solid var(--border);\n border-radius: var(--radius); padding: 16px; margin-bottom: 14px;\n }\n .info-row { display: flex; align-items: center; gap: 10px; padding: 7px 0; border-bottom: 1px solid var(--border); }\n .info-row:last-child { border-bottom: none; }\n .info-key { font-size: 12px; color: var(--text3); width: 130px; flex-shrink: 0; }\n .info-val { font-size: 13px; font-family: var(--font-mono); color: var(--text); }\n .badge { display: inline-flex; align-items: center; gap: 4px; padding: 2px 8px; border-radius: 20px; font-size: 11px; font-weight: 500; }\n .badge.green { background: rgba(34,197,94,0.12); color: var(--green); border: 1px solid rgba(34,197,94,0.2); }\n .badge.blue { background: rgba(59,130,246,0.12); color: var(--accent2);border: 1px solid rgba(59,130,246,0.2); }\n .badge.online-dot::before { content: ''; display: inline-block; width: 5px; height: 5px; border-radius: 50%; background: var(--green); }\n\n /* worker pool bars */\n .worker-bars { display: flex; flex-direction: column; gap: 8px; }\n .worker-row { display: flex; align-items: center; gap: 10px; }\n .worker-label { font-size: 11px; color: var(--text3); width: 60px; flex-shrink: 0; font-family: var(--font-mono); }\n .progress-bar { flex: 1; height: 6px; background: var(--bg4); border-radius: 3px; overflow: hidden; }\n .progress-fill { height: 100%; border-radius: 3px; background: linear-gradient(90deg, var(--accent), var(--purple)); transition: width 0.4s; }\n .worker-stat { font-size: 11px; color: var(--text3); width: 60px; text-align: right; font-family: var(--font-mono); }\n\n /* ── COLLECTION PANEL ────────────────────────────────────────── */\n #panel-collection { display: none; flex-direction: column; height: 100%; }\n #panel-collection.active { display: flex; }\n\n #collection-toolbar {\n padding: 12px 20px; border-bottom: 1px solid var(--border);\n display: flex; align-items: center; gap: 10px; flex-shrink: 0;\n background: var(--bg2);\n }\n .filter-wrap {\n display: flex; align-items: center; gap: 6px;\n flex: 1; max-width: 320px;\n background: var(--bg3); border: 1px solid var(--border2);\n border-radius: 6px; padding: 0 10px;\n transition: border-color 0.15s;\n }\n .filter-wrap:focus-within { border-color: var(--accent); }\n .filter-wrap svg { color: var(--text3); flex-shrink: 0; }\n #filter-input {\n flex: 1; border: none; background: transparent;\n padding: 6px 0;\n color: var(--text); font-size: 13px; font-family: 'Inter', sans-serif;\n outline: none;\n }\n #filter-input::placeholder { color: var(--text3); }\n select.sort-select {\n background: var(--bg3); border: 1px solid var(--border2);\n border-radius: 6px; padding: 6px 10px;\n color: var(--text); font-size: 13px; font-family: 'Inter', sans-serif;\n outline: none; cursor: pointer;\n }\n\n /* ── TABLE ───────────────────────────────────────────────────── */\n #table-wrap { flex: 1; overflow: auto; }\n table { width: 100%; border-collapse: collapse; }\n thead { position: sticky; top: 0; z-index: 2; }\n th {\n background: var(--bg2); color: var(--text3);\n font-size: 11px; font-weight: 600; letter-spacing: 0.5px; text-transform: uppercase;\n padding: 10px 16px; text-align: left;\n border-bottom: 1px solid var(--border);\n cursor: pointer; white-space: nowrap;\n user-select: none;\n }\n th .th-inner { display: flex; align-items: center; gap: 4px; }\n th:hover { color: var(--text); }\n th.sorted { color: var(--accent2); }\n td {\n padding: 9px 16px; border-bottom: 1px solid var(--border);\n font-size: 13px; max-width: 250px;\n white-space: nowrap; overflow: hidden; text-overflow: ellipsis;\n vertical-align: middle;\n }\n tr { cursor: pointer; transition: background 0.1s; }\n tr:hover td { background: var(--bg3); }\n tr.selected td { background: rgba(59,130,246,0.08); }\n .cell-id { font-family: var(--font-mono); font-size: 11px; color: var(--text3); }\n .cell-bool { display: inline-flex; align-items: center; gap: 4px; font-size: 11px; font-weight: 500; }\n .cell-bool.t { color: var(--green); }\n .cell-bool.f { color: var(--red); }\n .cell-num { color: var(--purple); font-family: var(--font-mono); font-size: 12px; }\n .cell-date { color: var(--teal); font-size: 11px; }\n .cell-null { color: var(--text3); font-style: italic; font-size: 11px; }\n .cell-obj { color: var(--text3); font-size: 11px; font-family: var(--font-mono); }\n\n /* ── PAGINATION ──────────────────────────────────────────────── */\n #pagination {\n padding: 10px 20px; border-top: 1px solid var(--border);\n display: flex; align-items: center; gap: 10px;\n background: var(--bg2); flex-shrink: 0;\n }\n #pagination-info { font-size: 12px; color: var(--text3); }\n #pagination-controls { margin-left: auto; display: flex; gap: 6px; }\n .page-btn {\n width: 28px; height: 28px; border-radius: 5px;\n background: var(--bg3); border: 1px solid var(--border);\n color: var(--text2); cursor: pointer; font-size: 12px;\n display: flex; align-items: center; justify-content: center;\n transition: all 0.15s;\n }\n .page-btn:hover:not(:disabled) { background: var(--bg4); border-color: var(--accent); color: var(--accent2); }\n .page-btn:disabled { opacity: 0.35; cursor: not-allowed; }\n .page-btn.active { background: var(--accent); border-color: var(--accent); color: #fff; }\n\n /* ── REALTIME PANEL ──────────────────────────────────────────── */\n #panel-realtime { display: none; flex-direction: column; height: 100%; }\n #panel-realtime.active { display: flex; }\n #events-toolbar {\n padding: 12px 20px; border-bottom: 1px solid var(--border);\n display: flex; align-items: center; gap: 10px;\n background: var(--bg2); flex-shrink: 0;\n }\n .event-indicator { display: flex; align-items: center; gap: 6px; font-size: 12px; color: var(--text3); }\n .pulse { width: 7px; height: 7px; border-radius: 50%; background: var(--green); animation: pulse 1.5s infinite; }\n @keyframes pulse { 0%,100% { opacity: 1; } 50% { opacity: 0.3; } }\n #events-log {\n flex: 1; overflow-y: auto; padding: 12px 20px;\n display: flex; flex-direction: column; gap: 6px;\n }\n .event-item {\n display: flex; align-items: flex-start; gap: 12px;\n padding: 10px 14px; border-radius: 8px;\n background: var(--bg2); border: 1px solid var(--border);\n animation: fadeIn 0.3s ease;\n }\n @keyframes fadeIn { from { opacity:0; transform: translateY(-4px); } to { opacity:1; transform: translateY(0); } }\n .event-type {\n font-size: 10px; font-weight: 700; padding: 2px 7px; border-radius: 4px;\n text-transform: uppercase; letter-spacing: 0.5px; flex-shrink: 0; margin-top: 1px;\n }\n .event-type.insert { background: rgba(34,197,94,0.15); color: var(--green); }\n .event-type.update { background: rgba(245,158,11,0.15); color: var(--yellow); }\n .event-type.delete { background: rgba(239,68,68,0.15); color: var(--red); }\n .event-type.system { background: rgba(167,139,250,0.15);color: var(--purple); }\n .event-body { flex: 1; min-width: 0; }\n .event-title { font-size: 13px; font-weight: 500; margin-bottom: 2px; }\n .event-detail{ font-size: 11px; color: var(--text3); font-family: var(--font-mono); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\n .event-time { font-size: 10px; color: var(--text3); flex-shrink: 0; font-family: var(--font-mono); }\n\n /* ── INSPECTOR MODAL ─────────────────────────────────────────── */\n #inspector-overlay {\n display: none; position: fixed; inset: 0; z-index: 100;\n background: rgba(0,0,0,0.7); backdrop-filter: blur(4px);\n align-items: flex-start; justify-content: flex-end;\n }\n #inspector-overlay.open { display: flex; }\n #inspector-panel {\n width: min(560px, 90vw); height: 100vh; overflow-y: auto;\n background: var(--bg2); border-left: 1px solid var(--border);\n padding: 20px; display: flex; flex-direction: column; gap: 14px;\n animation: slideIn 0.25s ease;\n }\n @keyframes slideIn { from { transform: translateX(40px); opacity: 0; } to { transform: translateX(0); opacity: 1; } }\n #inspector-header { display: flex; align-items: center; justify-content: space-between; }\n #inspector-title { font-size: 15px; font-weight: 600; }\n #inspector-close {\n width: 28px; height: 28px; border-radius: 6px;\n background: var(--bg3); border: 1px solid var(--border);\n cursor: pointer; color: var(--text3);\n display: flex; align-items: center; justify-content: center;\n transition: all 0.15s;\n }\n #inspector-close:hover { color: var(--red); border-color: var(--red); background: rgba(239,68,68,0.1); }\n #inspector-body { flex: 1; }\n #inspector-json {\n background: var(--bg); border: 1px solid var(--border);\n border-radius: 8px; padding: 16px;\n font-family: var(--font-mono); font-size: 12px; line-height: 1.7;\n white-space: pre-wrap; word-break: break-all; overflow-x: auto;\n color: var(--text);\n }\n .j-key { color: #93c5fd; }\n .j-str { color: #86efac; }\n .j-num { color: #c4b5fd; }\n .j-bool { color: #f97316; }\n .j-null { color: var(--text3); }\n\n /* ── EMPTY / LOADING ─────────────────────────────────────────── */\n .loading-spinner {\n width: 30px; height: 30px; border: 3px solid var(--border2);\n border-top-color: var(--accent); border-radius: 50%;\n animation: spin 0.7s linear infinite; margin: 60px auto;\n }\n @keyframes spin { to { transform: rotate(360deg); } }\n .empty-state { text-align: center; padding: 60px 20px; color: var(--text3); }\n .empty-state .empty-icon { display: flex; justify-content: center; margin-bottom: 14px; opacity: 0.4; }\n .empty-state p { font-size: 14px; margin-bottom: 6px; color: var(--text2); }\n .empty-state small { font-size: 12px; }\n\n /* ── SCROLLBAR ───────────────────────────────────────────────── */\n ::-webkit-scrollbar { width: 5px; height: 5px; }\n ::-webkit-scrollbar-track { background: transparent; }\n ::-webkit-scrollbar-thumb { background: var(--bg4); border-radius: 10px; }\n ::-webkit-scrollbar-thumb:hover { background: var(--text3); }\n\n /* ── TOAST ───────────────────────────────────────────────────── */\n #toast {\n position: fixed; bottom: 20px; right: 20px;\n background: var(--bg3); border: 1px solid var(--border2);\n border-radius: 8px; padding: 10px 16px; font-size: 13px;\n display: none; z-index: 200; animation: toastIn 0.2s ease;\n }\n @keyframes toastIn { from { opacity:0; transform: translateY(10px); } to { opacity:1; transform: translateY(0); } }\n\n /* ── SEARCH ICON ─────────────────────────────────────────────── */\n .search-icon { color: var(--text3); pointer-events: none; }\n </style>\n</head>\n<body>\n<div id=\"app\">\n\n <!-- ── SIDEBAR ──────────────────────────────────────────────────── -->\n <nav id=\"sidebar\">\n <div id=\"sidebar-header\">\n <div class=\"logo-icon\">${ico.logoDb}</div>\n <span class=\"logo-text\">gramobase</span>\n <span class=\"logo-badge\">STUDIO</span>\n </div>\n <div id=\"sidebar-nav\">\n <div class=\"nav-section\">Dashboard</div>\n <div class=\"nav-item active\" data-panel=\"overview\" onclick=\"switchPanel('overview')\">\n ${ico.gauge} Overview\n </div>\n <div class=\"nav-item\" data-panel=\"realtime\" onclick=\"switchPanel('realtime')\">\n ${ico.radio} Realtime Feed\n </div>\n\n <div class=\"nav-section\" style=\"margin-top:10px\">Collections</div>\n <div id=\"collection-list\">\n <div style=\"padding:12px 16px;font-size:12px;color:var(--text3)\">Loading...</div>\n </div>\n </div>\n <div id=\"sidebar-footer\">\n <span class=\"status-dot\" id=\"conn-dot\"></span>\n <span id=\"conn-label\">Connecting...</span>\n </div>\n </nav>\n\n <!-- ── MAIN ─────────────────────────────────────────────────────── -->\n <div id=\"main\">\n <div id=\"topbar\">\n <span id=\"topbar-title\">Overview</span>\n <span id=\"topbar-sub\"></span>\n <div id=\"topbar-actions\">\n <button class=\"btn\" onclick=\"refreshCurrent()\">${ico.refresh} Refresh</button>\n </div>\n </div>\n\n <div id=\"content\">\n\n <!-- Overview Panel -->\n <div id=\"panel-overview\" class=\"panel active\">\n <div id=\"overview-inner\" style=\"padding:24px\">\n <div style=\"text-align:center;padding:60px 0\"><div class=\"loading-spinner\"></div></div>\n </div>\n </div>\n\n <!-- Collection Panel -->\n <div id=\"panel-collection\" class=\"panel\">\n <div id=\"collection-toolbar\">\n <div class=\"filter-wrap\">\n <svg class=\"search-icon\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><circle cx=\"11\" cy=\"11\" r=\"8\"/><line x1=\"21\" y1=\"21\" x2=\"16.65\" y2=\"16.65\"/></svg>\n <input id=\"filter-input\" type=\"text\" placeholder=\"Filter: field:value or text\" oninput=\"debounceFilter()\" />\n </div>\n <select class=\"sort-select\" id=\"sort-field\" onchange=\"loadCollection()\">\n <option value=\"\">Sort by...</option>\n </select>\n <select class=\"sort-select\" id=\"sort-dir\" onchange=\"loadCollection()\" style=\"width:90px\">\n <option value=\"-1\">DESC</option>\n <option value=\"1\">ASC</option>\n </select>\n <span style=\"font-size:12px;color:var(--text3);margin-left:4px\" id=\"coll-count\"></span>\n </div>\n <div id=\"table-wrap\">\n <div style=\"text-align:center;padding:60px 0\"><div class=\"loading-spinner\"></div></div>\n </div>\n <div id=\"pagination\">\n <span id=\"pagination-info\"></span>\n <div id=\"pagination-controls\"></div>\n </div>\n </div>\n\n <!-- Realtime Panel -->\n <div id=\"panel-realtime\" class=\"panel\">\n <div id=\"events-toolbar\">\n <div class=\"event-indicator\"><div class=\"pulse\"></div> Live events</div>\n <button class=\"btn\" style=\"margin-left:auto\" onclick=\"clearEvents()\">${ico.trash} Clear</button>\n </div>\n <div id=\"events-log\">\n <div class=\"empty-state\" id=\"events-empty\">\n <div class=\"empty-icon\">${ico.activity}</div>\n <p>Waiting for events...</p>\n <small>Insert, update, or delete documents to see events here.</small>\n </div>\n </div>\n </div>\n\n </div>\n </div>\n</div>\n\n<!-- Inspector Drawer -->\n<div id=\"inspector-overlay\" onclick=\"closeInspector(event)\">\n <div id=\"inspector-panel\">\n <div id=\"inspector-header\">\n <span id=\"inspector-title\">Document</span>\n <div id=\"inspector-close\" onclick=\"closeInspector()\">${ico.x}</div>\n </div>\n <div id=\"inspector-body\">\n <pre id=\"inspector-json\"></pre>\n </div>\n </div>\n</div>\n\n<!-- Toast -->\n<div id=\"toast\"></div>\n\n<script>\n/* ─── Icon snippets for dynamic HTML ─────────────────────── */\nconst SVG = {\n bot: \\`${ico.bot}\\`,\n layers: \\`${ico.layers}\\`,\n zap: \\`${ico.zap}\\`,\n hdd: \\`${ico.hdd}\\`,\n hash: \\`${ico.hash}\\`,\n grid: \\`${ico.grid}\\`,\n table: \\`${ico.table}\\`,\n xCirc: \\`${ico.xCircle}\\`,\n inbox: \\`${ico.inbox}\\`,\n asc: \\`${ico.sortAsc}\\`,\n desc: \\`${ico.sortDesc}\\`,\n chevrL: \\`${ico.chevrL}\\`,\n chevrR: \\`${ico.chevrR}\\`,\n check: \\`${ico.check}\\`,\n close2: \\`${ico.close2}\\`,\n};\n\n/* ─── State ───────────────────────────────────────────────── */\nlet currentPanel = 'overview';\nlet currentCollection = null;\nlet currentPage = 1;\nlet pageSize = 25;\nlet totalDocs = 0;\nlet sortField = '';\nlet sortDir = -1;\nlet filterText = '';\nlet filterTimer = null;\nlet columns = [];\nlet eventSource = null;\nlet eventCount = 0;\n\n/* ─── Init ────────────────────────────────────────────────── */\nasync function init() {\n await loadStatus();\n await loadCollections();\n connectSSE();\n}\n\n/* ─── Status / Overview ───────────────────────────────────── */\nasync function loadStatus() {\n try {\n const data = await api('/api/status');\n setConnected(true, '@' + (data.bot?.username || 'unknown'));\n renderOverview(data);\n } catch (e) {\n setConnected(false, 'Connection failed');\n renderOverviewError(e.message);\n }\n}\n\nfunction renderOverview(data) {\n const cache = data.cache || {};\n const workers = data.workers || {};\n const tokens = workers.tokens || [];\n\n const hitPct = cache.hits + cache.misses > 0\n ? Math.round((cache.hits / (cache.hits + cache.misses)) * 100)\n : 0;\n const cacheUsedMb = ((cache.bytes || 0) / 1024 / 1024).toFixed(1);\n const cacheMaxMb = ((cache.maxBytes || 1) / 1024 / 1024).toFixed(0);\n const hitColor = hitPct > 70 ? 'green' : hitPct > 40 ? 'yellow' : 'blue';\n\n document.getElementById('overview-inner').innerHTML = \\`\n <div class=\"stats-grid\">\n <div class=\"stat-card\">\n <div class=\"stat-icon-wrap blue\">\\${SVG.bot}</div>\n <div class=\"stat-label\">Bot</div>\n <div class=\"stat-value blue\" style=\"font-size:18px\">@\\${escH(data.bot?.username || '—')}</div>\n <div class=\"stat-sub\">\\${escH(data.bot?.firstName || '')}</div>\n </div>\n <div class=\"stat-card\">\n <div class=\"stat-icon-wrap purple\">\\${SVG.layers}</div>\n <div class=\"stat-label\">Token Pool</div>\n <div class=\"stat-value purple\">\\${tokens.length || 1}</div>\n <div class=\"stat-sub\">\\${(tokens.length||1) * 30} req/s capacity</div>\n </div>\n <div class=\"stat-card\">\n <div class=\"stat-icon-wrap \\${hitColor}\">\\${SVG.zap}</div>\n <div class=\"stat-label\">Cache Hit Rate</div>\n <div class=\"stat-value \\${hitColor}\">\\${hitPct}%</div>\n <div class=\"stat-sub\">\\${cache.hits||0} hits / \\${cache.misses||0} misses</div>\n </div>\n <div class=\"stat-card\">\n <div class=\"stat-icon-wrap teal\">\\${SVG.hdd}</div>\n <div class=\"stat-label\">Cache Usage</div>\n <div class=\"stat-value teal\">\\${cacheUsedMb} MB</div>\n <div class=\"stat-sub\">of \\${cacheMaxMb} MB limit</div>\n </div>\n <div class=\"stat-card\">\n <div class=\"stat-icon-wrap blue\">\\${SVG.hash}</div>\n <div class=\"stat-label\">Channel</div>\n <div class=\"stat-value blue\" style=\"font-size:15px;font-family:var(--font-mono)\">\\${escH(data.channelId || '—')}</div>\n <div class=\"stat-sub\">Primary channel</div>\n </div>\n <div class=\"stat-card\">\n <div class=\"stat-icon-wrap green\">\\${SVG.grid}</div>\n <div class=\"stat-label\">Collections</div>\n <div class=\"stat-value green\">\\${(data.collections||[]).length}</div>\n <div class=\"stat-sub\">discovered</div>\n </div>\n </div>\n\n <div class=\"section-title\">Bot Connection</div>\n <div class=\"info-card\">\n <div class=\"info-row\"><span class=\"info-key\">Status</span><span class=\"info-val\"><span class=\"badge green online-dot\"> Online</span></span></div>\n <div class=\"info-row\"><span class=\"info-key\">Username</span><span class=\"info-val\">@\\${escH(data.bot?.username||'—')}</span></div>\n <div class=\"info-row\"><span class=\"info-key\">First Name</span><span class=\"info-val\">\\${escH(data.bot?.firstName||'—')}</span></div>\n <div class=\"info-row\"><span class=\"info-key\">Channel ID</span><span class=\"info-val\">\\${escH(data.channelId||'—')}</span></div>\n <div class=\"info-row\"><span class=\"info-key\">Token Count</span><span class=\"info-val\"><span class=\"badge blue\">\\${tokens.length||1} token\\${(tokens.length||1)>1?'s':''}</span></span></div>\n </div>\n\n \\${tokens.length > 0 ? \\`\n <div class=\"section-title\" style=\"margin-top:20px\">Worker Pool</div>\n <div class=\"info-card\">\n <div class=\"worker-bars\">\n \\${tokens.map((t,i) => \\`\n <div class=\"worker-row\">\n <span class=\"worker-label\">Token \\${i+1}</span>\n <div class=\"progress-bar\"><div class=\"progress-fill\" style=\"width:\\${Math.min(100,(t.activeRequests||0)/25*100)}%\"></div></div>\n <span class=\"worker-stat\">\\${t.activeRequests||0}/25</span>\n </div>\n \\`).join('')}\n </div>\n </div>\n \\` : ''}\n \\`;\n}\n\nfunction renderOverviewError(msg) {\n document.getElementById('overview-inner').innerHTML = \\`\n <div class=\"empty-state\">\n <div class=\"empty-icon\">\\${SVG.xCirc}</div>\n <p>Could not connect to gramobase</p>\n <small>\\${escH(msg)}</small>\n </div>\n \\`;\n}\n\n/* ─── Collections ─────────────────────────────────────────── */\nasync function loadCollections() {\n try {\n const data = await api('/api/collections');\n const list = data.collections || [];\n const nav = document.getElementById('collection-list');\n if (list.length === 0) {\n nav.innerHTML = '<div style=\"padding:10px 16px;font-size:12px;color:var(--text3)\">No collections yet</div>';\n return;\n }\n nav.innerHTML = list.map(c => \\`\n <div class=\"nav-item\" data-panel=\"collection\" data-col=\"\\${escH(c.name)}\" onclick=\"openCollection('\\${escH(c.name)}')\">\n \\${SVG.table}\n <span style=\"overflow:hidden;text-overflow:ellipsis;white-space:nowrap\">\\${escH(c.name)}</span>\n <span class=\"nav-item-count\">\\${c.count||'?'}</span>\n </div>\n \\`).join('');\n } catch(e) {}\n}\n\nasync function openCollection(name) {\n currentCollection = name;\n currentPage = 1;\n filterText = '';\n sortField = '';\n document.getElementById('filter-input').value = '';\n document.getElementById('sort-field').innerHTML = '<option value=\"\">Sort by...</option>';\n switchPanel('collection');\n document.getElementById('topbar-title').textContent = name;\n document.getElementById('topbar-sub').textContent = 'collection';\n await loadCollection();\n}\n\nasync function loadCollection() {\n if (!currentCollection) return;\n sortField = document.getElementById('sort-field').value;\n sortDir = parseInt(document.getElementById('sort-dir').value, 10);\n const params = new URLSearchParams({\n page: currentPage, limit: pageSize, filter: filterText, sortField, sortDir,\n });\n setTableLoading();\n try {\n const data = await api('/api/collection/' + encodeURIComponent(currentCollection) + '?' + params);\n totalDocs = data.total || 0;\n columns = data.columns || [];\n renderTable(data.docs || [], data.columns || []);\n renderPagination();\n updateSortSelect(data.columns || []);\n document.getElementById('coll-count').textContent = totalDocs + ' docs';\n document.querySelectorAll('.nav-item[data-col]').forEach(item => {\n if (item.dataset.col === currentCollection) {\n const cnt = item.querySelector('.nav-item-count');\n if (cnt) cnt.textContent = totalDocs;\n }\n });\n } catch(e) {\n document.getElementById('table-wrap').innerHTML = \\`<div class=\"empty-state\"><div class=\"empty-icon\">\\${SVG.xCirc}</div><p>\\${escH(e.message)}</p></div>\\`;\n }\n}\n\nfunction setTableLoading() {\n document.getElementById('table-wrap').innerHTML = '<div style=\"text-align:center;padding:60px 0\"><div class=\"loading-spinner\"></div></div>';\n}\n\nfunction updateSortSelect(cols) {\n const sel = document.getElementById('sort-field');\n const cur = sel.value;\n sel.innerHTML = '<option value=\"\">Sort by...</option>' +\n cols.map(c => \\`<option value=\"\\${escH(c)}\" \\${c===cur?'selected':''}>\\${escH(c)}</option>\\`).join('');\n}\n\nfunction renderTable(docs, cols) {\n if (docs.length === 0) {\n document.getElementById('table-wrap').innerHTML = \\`\n <div class=\"empty-state\">\n <div class=\"empty-icon\">\\${SVG.inbox}</div>\n <p>No documents found</p>\n <small>Try adjusting your filter or add some data.</small>\n </div>\\`;\n return;\n }\n const allCols = ['_id', ...cols.filter(c => !c.startsWith('_') && c !== '_id'), '_createdAt', '_updatedAt'];\n const sortIcon = (c) => sortField === c ? (sortDir === -1 ? SVG.desc : SVG.asc) : '';\n const html = \\`<table>\n <thead><tr>\n \\${allCols.map(c => \\`<th class=\"\\${sortField===c?'sorted':''}\" onclick=\"sortBy('\\${escH(c)}')\"><div class=\"th-inner\">\\${escH(c)}\\${sortIcon(c)}</div></th>\\`).join('')}\n </tr></thead>\n <tbody>\n \\${docs.map((doc, i) => \\`\n <tr onclick=\"inspectDoc(\\${i})\" data-idx=\"\\${i}\">\n \\${allCols.map(c => \\`<td>\\${renderCell(doc[c], c)}</td>\\`).join('')}\n </tr>\\`).join('')}\n </tbody>\n </table>\\`;\n document.getElementById('table-wrap').innerHTML = html;\n window._currentDocs = docs;\n}\n\nfunction renderCell(val, col) {\n if (val === undefined || val === null) return '<span class=\"cell-null\">—</span>';\n if (col === '_id' || col === '_collection') return \\`<span class=\"cell-id\">\\${escH(String(val).slice(0,12))}…</span>\\`;\n if (col === '_createdAt' || col === '_updatedAt') return \\`<span class=\"cell-date\">\\${escH(fmtDate(val))}</span>\\`;\n if (typeof val === 'boolean') return val\n ? \\`<span class=\"cell-bool t\">\\${SVG.check} true</span>\\`\n : \\`<span class=\"cell-bool f\">\\${SVG.close2} false</span>\\`;\n if (typeof val === 'number') return \\`<span class=\"cell-num\">\\${escH(String(val))}</span>\\`;\n if (typeof val === 'object') return '<span class=\"cell-obj\">{…}</span>';\n const s = String(val);\n return \\`<span title=\"\\${escH(s)}\">\\${escH(s.length > 40 ? s.slice(0,40)+'…' : s)}</span>\\`;\n}\n\nfunction sortBy(col) {\n if (sortField === col) { sortDir = sortDir === -1 ? 1 : -1; }\n else { sortField = col; sortDir = -1; }\n document.getElementById('sort-field').value = sortField;\n document.getElementById('sort-dir').value = sortDir;\n loadCollection();\n}\n\nfunction inspectDoc(idx) {\n const doc = window._currentDocs?.[idx];\n if (!doc) return;\n document.getElementById('inspector-title').textContent = 'Document: ' + (doc._id?.slice(0,8)||'') + '…';\n document.getElementById('inspector-json').innerHTML = syntaxHL(JSON.stringify(doc, null, 2));\n document.getElementById('inspector-overlay').classList.add('open');\n document.querySelectorAll('tr').forEach(r => r.classList.toggle('selected', r.dataset.idx == idx));\n}\n\nfunction closeInspector(e) {\n if (e && e.target !== document.getElementById('inspector-overlay')) return;\n document.getElementById('inspector-overlay').classList.remove('open');\n document.querySelectorAll('tr.selected').forEach(r => r.classList.remove('selected'));\n}\n\n/* ─── Pagination ──────────────────────────────────────────── */\nfunction renderPagination() {\n const totalPages = Math.max(1, Math.ceil(totalDocs / pageSize));\n const start = (currentPage - 1) * pageSize + 1;\n const end = Math.min(currentPage * pageSize, totalDocs);\n document.getElementById('pagination-info').textContent = totalDocs > 0 ? \\`\\${start}–\\${end} of \\${totalDocs}\\` : '0 results';\n\n let btns = '';\n btns += \\`<button class=\"page-btn\" onclick=\"goPage(\\${currentPage-1})\" \\${currentPage<=1?'disabled':''}>\\${SVG.chevrL}</button>\\`;\n const pages = pageRange(currentPage, totalPages);\n pages.forEach(p => {\n if (p === '…') btns += \\`<span style=\"color:var(--text3);padding:0 4px;line-height:28px\">…</span>\\`;\n else btns += \\`<button class=\"page-btn \\${p===currentPage?'active':''}\" onclick=\"goPage(\\${p})\">\\${p}</button>\\`;\n });\n btns += \\`<button class=\"page-btn\" onclick=\"goPage(\\${currentPage+1})\" \\${currentPage>=totalPages?'disabled':''}>\\${SVG.chevrR}</button>\\`;\n document.getElementById('pagination-controls').innerHTML = btns;\n}\n\nfunction pageRange(cur, total) {\n if (total <= 7) return Array.from({length:total},(_,i)=>i+1);\n const pages = [1];\n if (cur > 3) pages.push('…');\n for (let i = Math.max(2,cur-1); i <= Math.min(total-1,cur+1); i++) pages.push(i);\n if (cur < total-2) pages.push('…');\n pages.push(total);\n return pages;\n}\n\nfunction goPage(p) {\n const totalPages = Math.ceil(totalDocs / pageSize);\n if (p < 1 || p > totalPages) return;\n currentPage = p;\n loadCollection();\n}\n\n/* ─── Filter ──────────────────────────────────────────────── */\nfunction debounceFilter() {\n clearTimeout(filterTimer);\n filterTimer = setTimeout(() => {\n filterText = document.getElementById('filter-input').value;\n currentPage = 1;\n loadCollection();\n }, 400);\n}\n\n/* ─── Realtime SSE ────────────────────────────────────────── */\nfunction connectSSE() {\n if (eventSource) eventSource.close();\n eventSource = new EventSource('/api/events');\n eventSource.onmessage = (e) => {\n try { addEvent(JSON.parse(e.data)); } catch(_) {}\n };\n eventSource.onerror = () => {};\n}\n\nfunction addEvent(ev) {\n eventCount++;\n const log = document.getElementById('events-log');\n const empty = document.getElementById('events-empty');\n if (empty) empty.remove();\n\n const typeMap = { insert:'insert', update:'update', delete:'delete', 'worker:rotate':'system', 'wal:flush':'system' };\n const type = typeMap[ev.type] || 'system';\n const title = ev.type === 'insert' ? \\`New doc in \\${ev.collection}\\`\n : ev.type === 'update' ? \\`Updated \\${ev.id?.slice(0,8)}… in \\${ev.collection}\\`\n : ev.type === 'delete' ? \\`Deleted \\${ev.id?.slice(0,8)}… from \\${ev.collection}\\`\n : ev.type === 'worker:rotate' ? 'Worker rotated token #' + ev.tokenIndex\n : ev.type === 'wal:flush' ? \\`WAL flushed \\${ev.entries} entries\\` : ev.type;\n const detail = ev.doc ? JSON.stringify(ev.doc).slice(0,80) : ev.changes ? JSON.stringify(ev.changes).slice(0,80) : '';\n\n const item = document.createElement('div');\n item.className = 'event-item';\n item.innerHTML = \\`\n <div class=\"event-type \\${type}\">\\${ev.type}</div>\n <div class=\"event-body\">\n <div class=\"event-title\">\\${escH(title)}</div>\n \\${detail ? \\`<div class=\"event-detail\">\\${escH(detail)}</div>\\` : ''}\n </div>\n <div class=\"event-time\">\\${fmtTime(new Date())}</div>\n \\`;\n log.insertBefore(item, log.firstChild);\n while (log.children.length > 200) log.removeChild(log.lastChild);\n if ((ev.collection === currentCollection) && currentPanel === 'collection') loadCollection();\n}\n\nfunction clearEvents() {\n document.getElementById('events-log').innerHTML = \\`\n <div class=\"empty-state\" id=\"events-empty\">\n <div class=\"empty-icon\">\\${SVG.xCirc}</div>\n <p>Waiting for events...</p>\n <small>Insert, update, or delete documents to see events here.</small>\n </div>\\`;\n eventCount = 0;\n}\n\n/* ─── Navigation ──────────────────────────────────────────── */\nfunction switchPanel(name) {\n currentPanel = name;\n document.querySelectorAll('.panel').forEach(p => p.classList.remove('active'));\n document.getElementById('panel-' + name).classList.add('active');\n document.querySelectorAll('.nav-item').forEach(i => {\n i.classList.toggle('active', i.dataset.panel === name && !i.dataset.col);\n });\n if (name === 'collection') {\n document.querySelectorAll('.nav-item[data-col]').forEach(i => {\n i.classList.toggle('active', i.dataset.col === currentCollection);\n });\n }\n if (name === 'overview') {\n document.getElementById('topbar-title').textContent = 'Overview';\n document.getElementById('topbar-sub').textContent = '';\n loadStatus(); loadCollections();\n }\n if (name === 'realtime') {\n document.getElementById('topbar-title').textContent = 'Realtime Feed';\n document.getElementById('topbar-sub').textContent = 'live events';\n }\n}\n\nfunction refreshCurrent() {\n if (currentPanel === 'overview') { loadStatus(); loadCollections(); }\n else if (currentPanel === 'collection') loadCollection();\n}\n\n/* ─── Utilities ───────────────────────────────────────────── */\nfunction setConnected(ok, label) {\n document.getElementById('conn-dot').className = 'status-dot' + (ok ? '' : ' red');\n document.getElementById('conn-label').textContent = label;\n}\n\nasync function api(url) {\n const r = await fetch(url);\n if (!r.ok) {\n const j = await r.json().catch(() => ({}));\n throw new Error(j.error || r.statusText);\n }\n return r.json();\n}\n\nfunction escH(s) {\n return String(s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\"/g,'&quot;');\n}\n\nfunction fmtDate(v) {\n if (!v) return '';\n try { return new Date(v).toLocaleString(); } catch(_) { return String(v); }\n}\n\nfunction fmtTime(d) { return d.toTimeString().slice(0,8); }\n\nfunction syntaxHL(json) {\n return json\n .replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;')\n .replace(/\"(\\\\\\\\.|[^\"\\\\\\\\])*\"\\\\s*:/g, s => \\`<span class=\"j-key\">\\${s}</span>\\`)\n .replace(/:\\\\s*\"(\\\\\\\\.|[^\"\\\\\\\\])*\"/g, s => {\n const col = s.indexOf('\"');\n return s.slice(0,col) + \\`<span class=\"j-str\">\\${s.slice(col)}</span>\\`;\n })\n .replace(/:\\\\s*(-?\\\\d+\\\\.?\\\\d*)/g, (m,n) => m.replace(n, \\`<span class=\"j-num\">\\${n}</span>\\`))\n .replace(/:\\\\s*(true|false)/g, (m,b) => m.replace(b, \\`<span class=\"j-bool\">\\${b}</span>\\`))\n .replace(/:\\\\s*(null)/g, (m,n) => m.replace(n, \\`<span class=\"j-null\">\\${n}</span>\\`));\n}\n\ninit();\n</script>\n</body>\n</html>`;\n}\n","import TelegramBot from 'node-telegram-bot-api';\nimport PQueue from 'p-queue';\nimport pRetry, { AbortError } from 'p-retry';\nimport EventEmitter from 'eventemitter3';\n\nexport interface WorkerStats {\n tokenIndex: number;\n requestCount: number;\n errorCount: number;\n lastUsed: number;\n rateLimitHits: number;\n}\n\n/**\n * BotWorkerPool manages a round-robin pool of Telegram bot tokens.\n * Each token gets its own PQueue limited to 25 concurrent requests\n * (safe under Telegram's 30 req/s flood limit with headroom).\n * On 429 responses, the worker is cooled down and the next token takes over.\n */\nexport class BotWorkerPool extends EventEmitter {\n private bots: TelegramBot[] = [];\n private queues: PQueue[] = [];\n private stats: WorkerStats[] = [];\n private currentIndex = 0;\n private debug: boolean;\n\n constructor(tokens: string[], concurrency = 25, debug = false) {\n super();\n this.debug = debug;\n\n if (tokens.length === 0) throw new Error('[gramobase] At least one bot token required');\n\n for (let i = 0; i < tokens.length; i++) {\n const token = tokens[i]!;\n this.bots.push(new TelegramBot(token, { polling: false }));\n this.queues.push(new PQueue({ concurrency, intervalCap: 25, interval: 1000 }));\n this.stats.push({\n tokenIndex: i,\n requestCount: 0,\n errorCount: 0,\n lastUsed: 0,\n rateLimitHits: 0,\n });\n }\n }\n\n /**\n * Execute a Telegram API call through the pool with automatic retry\n * and token rotation on rate limits.\n */\n async execute<T>(\n fn: (bot: TelegramBot) => Promise<T>,\n priority = 5\n ): Promise<T> {\n const idx = this.pickWorker();\n const queue = this.queues[idx]!;\n const bot = this.bots[idx]!;\n const stat = this.stats[idx]!;\n\n return queue.add(\n () =>\n pRetry(\n async () => {\n stat.requestCount++;\n stat.lastUsed = Date.now();\n try {\n const result = await fn(bot);\n return result;\n } catch (err: unknown) {\n stat.errorCount++;\n if (this.isFloodError(err)) {\n stat.rateLimitHits++;\n this.emit('worker:rotate', idx);\n const retryAfter = this.extractRetryAfter(err) * 1000;\n if (this.debug) {\n console.warn(`[gramobase] Worker ${idx} flood limited, retrying after ${retryAfter}ms`);\n }\n await this.sleep(retryAfter);\n throw err;\n }\n if (this.isRetryableError(err)) {\n throw err;\n }\n throw new AbortError(err instanceof Error ? err : new Error(String(err)));\n }\n },\n {\n retries: 5,\n factor: 2,\n minTimeout: 1000,\n maxTimeout: 30_000,\n onFailedAttempt: (error) => {\n if (this.debug) {\n console.warn(`[gramobase] Attempt ${error.attemptNumber} failed:`, error.message);\n }\n },\n }\n ),\n { priority }\n ) as Promise<T>;\n }\n\n /**\n * Round-robin with recency bias — prefer the worker that was least recently used.\n */\n private pickWorker(): number {\n if (this.bots.length === 1) return 0;\n\n let bestIdx = 0;\n let oldestTime = Infinity;\n\n for (let i = 0; i < this.stats.length; i++) {\n const stat = this.stats[i]!;\n if (stat.lastUsed < oldestTime) {\n oldestTime = stat.lastUsed;\n bestIdx = i;\n }\n }\n\n this.currentIndex = bestIdx;\n return bestIdx;\n }\n\n private isFloodError(err: unknown): boolean {\n if (err && typeof err === 'object') {\n const e = err as { code?: string; response?: { statusCode?: number } };\n return e.code === 'ETELEGRAM' && e.response?.statusCode === 429;\n }\n return false;\n }\n\n private isRetryableError(err: unknown): boolean {\n if (!err) return false;\n if (err instanceof Error) {\n if (err.name === 'TypeError' || err.name === 'ReferenceError' || err.name === 'ValidationError') {\n return false;\n }\n }\n if (typeof err === 'object') {\n const e = err as { code?: string; response?: { statusCode?: number } };\n if (e.code === 'ETELEGRAM' && e.response?.statusCode === 429) {\n return true;\n }\n if (e.response?.statusCode && e.response.statusCode >= 500) {\n return true;\n }\n const retryableCodes = ['ETIMEDOUT', 'ECONNRESET', 'ENOTFOUND', 'EAI_AGAIN', 'ECONNREFUSED'];\n if (e.code && retryableCodes.includes(e.code)) {\n return true;\n }\n }\n return false;\n }\n\n private extractRetryAfter(err: unknown): number {\n if (err && typeof err === 'object') {\n const e = err as { response?: { body?: { parameters?: { retry_after?: number } } } };\n return e.response?.body?.parameters?.retry_after ?? 5;\n }\n return 5;\n }\n\n getBot(index = 0): TelegramBot {\n return this.bots[index] ?? this.bots[0]!;\n }\n\n getStats(): WorkerStats[] {\n return [...this.stats];\n }\n\n getQueueSizes(): number[] {\n return this.queues.map((q) => q.size);\n }\n\n private sleep(ms: number): Promise<void> {\n return new Promise((r) => setTimeout(r, ms));\n }\n\n async destroy(): Promise<void> {\n await Promise.all(this.queues.map((q) => q.onIdle()));\n for (const bot of this.bots) {\n await bot.stopPolling();\n }\n }\n}\n","import { LRUCache } from 'lru-cache';\nimport EventEmitter from 'eventemitter3';\n\ninterface CacheEntry<T> {\n data: T;\n collection: string;\n cachedAt: number;\n}\n\n/**\n * HotCache is an in-memory LRU cache that sits in front of Telegram storage.\n *\n * All reads hit the cache first. On a miss, the caller fetches from Telegram\n * and stores the result here. All writes invalidate or update the relevant key.\n *\n * The cache also stores the \"collection index\" — the full key→msgId map for\n * each collection — so that single-document lookups are O(1) without scanning\n * all messages.\n */\nexport class HotCache extends EventEmitter {\n private cache: LRUCache<string, CacheEntry<unknown>>;\n private collectionIndexes: Map<string, Map<string, number>> = new Map();\n private stats = { hits: 0, misses: 0, evictions: 0 };\n\n constructor(maxBytes = 64 * 1024 * 1024, ttlMs = 60_000) {\n super();\n this.cache = new LRUCache({\n maxSize: maxBytes,\n sizeCalculation: (val) =>\n JSON.stringify(val).length * 2, // rough UTF-16 byte estimate\n ttl: ttlMs,\n dispose: () => {\n this.stats.evictions++;\n },\n });\n }\n\n // ─── Document cache ──────────────────────────────────────────────────────\n\n get<T>(collection: string, id: string): T | undefined {\n const key = this.docKey(collection, id);\n const entry = this.cache.get(key) as CacheEntry<T> | undefined;\n if (entry) {\n this.stats.hits++;\n this.emit('cache:hit', { collection, key: id });\n return entry.data;\n }\n this.stats.misses++;\n this.emit('cache:miss', { collection, key: id });\n return undefined;\n }\n\n set<T>(collection: string, id: string, data: T): void {\n const key = this.docKey(collection, id);\n this.cache.set(key, { data, collection, cachedAt: Date.now() });\n }\n\n delete(collection: string, id: string): void {\n this.cache.delete(this.docKey(collection, id));\n }\n\n invalidateCollection(collection: string): void {\n for (const key of this.cache.keys()) {\n if (key.startsWith(`doc:${collection}:`)) {\n this.cache.delete(key);\n }\n }\n this.collectionIndexes.delete(collection);\n }\n\n // ─── Query cache ─────────────────────────────────────────────────────────\n\n getQuery<T>(queryHash: string): T[] | undefined {\n const entry = this.cache.get(`query:${queryHash}`) as CacheEntry<T[]> | undefined;\n return entry?.data;\n }\n\n setQuery<T>(queryHash: string, results: T[]): void {\n this.cache.set(`query:${queryHash}`, {\n data: results,\n collection: '__query__',\n cachedAt: Date.now(),\n });\n }\n\n invalidateQuery(collection: string): void {\n for (const key of this.cache.keys()) {\n if (key.startsWith(`query:${collection}:`)) {\n this.cache.delete(key);\n }\n }\n }\n\n // ─── Collection index ─────────────────────────────────────────────────────\n // Maps document _id → Telegram message ID for O(1) lookup\n\n getIndex(collection: string): Map<string, number> | undefined {\n return this.collectionIndexes.get(collection);\n }\n\n setIndex(collection: string, index: Map<string, number>): void {\n this.collectionIndexes.set(collection, index);\n }\n\n updateIndexEntry(collection: string, id: string, msgId: number): void {\n const idx = this.collectionIndexes.get(collection);\n if (idx) {\n idx.set(id, msgId);\n } else {\n this.collectionIndexes.set(collection, new Map([[id, msgId]]));\n }\n }\n\n deleteIndexEntry(collection: string, id: string): void {\n this.collectionIndexes.get(collection)?.delete(id);\n }\n\n getMsgId(collection: string, id: string): number | undefined {\n return this.collectionIndexes.get(collection)?.get(id);\n }\n\n // ─── Bulk read ────────────────────────────────────────────────────────────\n\n getMany<T>(collection: string, ids: string[]): Map<string, T> {\n const result = new Map<string, T>();\n for (const id of ids) {\n const val = this.get<T>(collection, id);\n if (val !== undefined) result.set(id, val);\n }\n return result;\n }\n\n // ─── Stats ────────────────────────────────────────────────────────────────\n\n getStats() {\n return {\n ...this.stats,\n size: this.cache.size,\n hitRate:\n this.stats.hits + this.stats.misses > 0\n ? this.stats.hits / (this.stats.hits + this.stats.misses)\n : 0,\n };\n }\n\n clear(): void {\n this.cache.clear();\n this.collectionIndexes.clear();\n }\n\n private docKey(collection: string, id: string): string {\n return `doc:${collection}:${id}`;\n }\n}\n","import { createCipheriv, createDecipheriv, randomBytes, createHash } from 'crypto';\nimport { BotWorkerPool } from '../workers/BotWorkerPool.js';\nimport { GramoBaseDocument } from '../types/index.js';\n\nconst INDEX_TAG = '__GRAMOBASE_INDEX__';\nconst DOC_TAG = '__GRAMOBASE_DOC__';\nconst MAX_MSG_BYTES = 4000;\n\nexport interface IndexMessage {\n collection: string;\n // id → msgId map\n entries: Record<string, number>;\n walSeq: number;\n updatedAt: string;\n msgId?: number;\n}\n\n/**\n * TelegramStorage handles the raw read/write operations against Telegram channels.\n *\n * Each collection gets a \"collection index message\" (pinned or findable by tag)\n * that maps document IDs to their Telegram message IDs.\n *\n * Documents are stored as JSON message text, optionally AES-256 encrypted.\n * Files are stored via sendDocument/sendPhoto and referenced by Telegram file_id.\n */\nexport class TelegramStorage {\n private encryptionKey: Buffer | null = null;\n // collection → pinned index message ID\n private indexMsgIds: Map<string, number> = new Map();\n\n constructor(\n private pool: BotWorkerPool,\n private defaultChannelId: string,\n encryptionKey?: string,\n private debug = false\n ) {\n if (encryptionKey) {\n this.encryptionKey = createHash('sha256').update(encryptionKey).digest();\n }\n }\n\n // ─── Index management ─────────────────────────────────────────────────────\n\n async loadIndex(collection: string, channelId?: string): Promise<IndexMessage> {\n const channel = channelId ?? this.defaultChannelId;\n\n try {\n const chat = await this.pool.execute((bot) => bot.getChat(channel)) as any;\n\n // Check pinned message first\n if (chat.pinned_message?.text?.startsWith(INDEX_TAG)) {\n const json = chat.pinned_message.text.replace(INDEX_TAG + '\\n', '');\n const parsed = JSON.parse(json) as IndexMessage;\n this.indexMsgIds.set(collection, chat.pinned_message.message_id);\n return parsed;\n }\n } catch {\n // No pinned message or channel is empty\n }\n\n // Return an empty index\n return {\n collection,\n entries: {},\n walSeq: 0,\n updatedAt: new Date().toISOString(),\n };\n }\n\n async saveIndex(index: IndexMessage, channelId?: string): Promise<void> {\n const channel = channelId ?? this.defaultChannelId;\n const text = `${INDEX_TAG}\\n${JSON.stringify(index)}`;\n\n const existingMsgId = this.indexMsgIds.get(index.collection);\n\n if (existingMsgId) {\n try {\n await this.pool.execute((bot) =>\n bot.editMessageText(text, {\n chat_id: channel,\n message_id: existingMsgId,\n })\n );\n return;\n } catch {\n // Message deleted or uneditable; create fresh\n }\n }\n\n const msg = await this.pool.execute((bot) =>\n bot.sendMessage(channel, text, { disable_notification: true })\n ) as any;\n\n this.indexMsgIds.set(index.collection, msg.message_id);\n\n await this.pool.execute((bot) =>\n bot.pinChatMessage(channel, msg.message_id, { disable_notification: true })\n );\n }\n\n // ─── Document CRUD ────────────────────────────────────────────────────────\n\n async writeDocument(\n doc: GramoBaseDocument,\n channelId?: string\n ): Promise<number> {\n const channel = channelId ?? this.defaultChannelId;\n let text = JSON.stringify({ [DOC_TAG]: true, ...doc });\n\n if (this.encryptionKey) {\n text = this.encrypt(text);\n }\n\n // Split large documents across multiple messages\n if (Buffer.byteLength(text, 'utf8') > MAX_MSG_BYTES) {\n return this.writeChunked(text, channel);\n }\n\n const msg = await this.pool.execute((bot) =>\n bot.sendMessage(channel, text, { disable_notification: true })\n ) as any;\n\n return msg.message_id as number;\n }\n\n async readDocument(\n msgId: number,\n channelId?: string\n ): Promise<GramoBaseDocument | null> {\n const channel = channelId ?? this.defaultChannelId;\n\n try {\n const msgs = await this.pool.execute((bot) =>\n (bot as any).forwardMessages(channel, channel, [msgId])\n ) as any;\n\n const msg = Array.isArray(msgs) ? msgs[0] : msgs;\n if (!msg?.text) return null;\n\n let text = msg.text as string;\n if (this.encryptionKey && text.startsWith('ENC:')) {\n text = this.decrypt(text);\n }\n\n // Reassemble chunked messages if needed\n if (text.startsWith('CHUNK:')) {\n text = await this.readChunked(text, channel);\n }\n\n const parsed = JSON.parse(text);\n delete parsed[DOC_TAG];\n return parsed as GramoBaseDocument;\n } catch {\n return null;\n }\n }\n\n async deleteDocument(msgId: number, channelId?: string): Promise<void> {\n const channel = channelId ?? this.defaultChannelId;\n await this.pool.execute((bot) =>\n (bot as any).deleteMessage(channel, msgId)\n );\n }\n\n async updateDocument(\n msgId: number,\n doc: GramoBaseDocument,\n channelId?: string\n ): Promise<number> {\n // Telegram doesn't support editing beyond 48h — delete + re-insert\n await this.deleteDocument(msgId, channelId);\n return this.writeDocument(doc, channelId);\n }\n\n // ─── Chunked large documents ──────────────────────────────────────────────\n\n private async writeChunked(text: string, channel: string): Promise<number> {\n const chunks: string[] = [];\n for (let i = 0; i < text.length; i += MAX_MSG_BYTES) {\n chunks.push(text.slice(i, i + MAX_MSG_BYTES));\n }\n\n const msgIds: number[] = [];\n for (const chunk of chunks) {\n const msg = await this.pool.execute((bot) =>\n bot.sendMessage(channel, chunk, { disable_notification: true })\n ) as any;\n msgIds.push(msg.message_id as number);\n }\n\n // Header message with chunk references\n const header = `CHUNK:${JSON.stringify(msgIds)}`;\n const headerMsg = await this.pool.execute((bot) =>\n bot.sendMessage(channel, header, { disable_notification: true })\n ) as any;\n\n return headerMsg.message_id as number;\n }\n\n private async readChunked(headerText: string, channel: string): Promise<string> {\n const msgIds: number[] = JSON.parse(headerText.replace('CHUNK:', ''));\n const parts: string[] = [];\n\n for (const id of msgIds) {\n const msgs = await this.pool.execute((bot) =>\n (bot as any).forwardMessages(channel, channel, [id])\n ) as any;\n const msg = Array.isArray(msgs) ? msgs[0] : msgs;\n if (msg?.text) parts.push(msg.text as string);\n }\n\n return parts.join('');\n }\n\n // ─── File storage ─────────────────────────────────────────────────────────\n\n async uploadFile(\n data: Buffer,\n fileName: string,\n mimeType: string,\n channelId?: string\n ): Promise<{ fileId: string; msgId: number }> {\n const channel = channelId ?? this.defaultChannelId;\n const isImage = mimeType.startsWith('image/');\n\n let msg: any;\n if (isImage) {\n msg = await this.pool.execute((bot) =>\n bot.sendPhoto(channel, data, {\n caption: fileName,\n disable_notification: true,\n })\n );\n } else {\n msg = await this.pool.execute((bot) =>\n bot.sendDocument(channel, data, {\n caption: fileName,\n disable_notification: true,\n })\n );\n }\n\n const fileId = isImage\n ? (msg as any).photo?.[(msg as any).photo.length - 1]?.file_id\n : (msg as any).document?.file_id;\n\n return { fileId, msgId: msg.message_id };\n }\n\n async getFileUrl(fileId: string): Promise<string> {\n return this.pool.execute((bot) => bot.getFileLink(fileId));\n }\n\n // ─── Encryption ───────────────────────────────────────────────────────────\n\n private encrypt(text: string): string {\n if (!this.encryptionKey) return text;\n const iv = randomBytes(16);\n const cipher = createCipheriv('aes-256-cbc', this.encryptionKey, iv);\n const encrypted = Buffer.concat([\n cipher.update(text, 'utf8'),\n cipher.final(),\n ]);\n return `ENC:${iv.toString('hex')}:${encrypted.toString('base64')}`;\n }\n\n private decrypt(text: string): string {\n if (!this.encryptionKey) return text;\n const [, ivHex, encB64] = text.split(':');\n if (!ivHex || !encB64) throw new Error('Invalid encrypted payload');\n const iv = Buffer.from(ivHex, 'hex');\n const encBuf = Buffer.from(encB64, 'base64');\n const decipher = createDecipheriv('aes-256-cbc', this.encryptionKey, iv);\n return Buffer.concat([decipher.update(encBuf), decipher.final()]).toString('utf8');\n }\n}\n","import { createHash } from 'crypto';\nimport { WalEntry, WalOpType } from '../types/index.js';\nimport { BotWorkerPool } from '../workers/BotWorkerPool.js';\n\nconst WAL_HEADER = '__WAL__';\nconst WAL_SEQ_TAG = '__WAL_SEQ__';\n\n/**\n * Write-Ahead Log backed by a Telegram channel.\n *\n * Every mutation is written to the WAL channel as a message BEFORE it is\n * applied to the main index. On startup, the WAL is replayed to recover\n * any operations that didn't complete during a crash.\n *\n * Format of each WAL message:\n * { \"__wal\": true, seq: N, op: \"INSERT\"|..., collection, id, data, ts, checksum }\n */\nexport class WriteAheadLog {\n private seq = 0;\n private buffer: WalEntry[] = [];\n private flushTimer: NodeJS.Timeout | null = null;\n private readonly FLUSH_INTERVAL_MS = 2000;\n private readonly BUFFER_LIMIT = 50;\n\n constructor(\n private pool: BotWorkerPool,\n private walChannelId: string,\n private debug: boolean = false\n ) {}\n\n async init(): Promise<void> {\n // Find the last WAL sequence number to resume from\n try {\n const msgs = await this.pool.execute((bot) =>\n (bot as any).getChatHistory(this.walChannelId, { limit: 10 })\n );\n for (const msg of (msgs as any[]).reverse()) {\n if (msg.text?.includes(WAL_SEQ_TAG)) {\n const match = msg.text.match(/__WAL_SEQ__:(\\d+)/);\n if (match) {\n this.seq = parseInt(match[1]!, 10);\n break;\n }\n }\n }\n } catch {\n // Channel may be empty on first run\n }\n if (this.debug) console.log(`[WAL] Initialized at seq=${this.seq}`);\n }\n\n /**\n * Append an entry to the WAL buffer. Flushes immediately if buffer is full.\n */\n async append(\n op: WalOpType,\n collection: string,\n id: string,\n data?: unknown\n ): Promise<WalEntry> {\n this.seq++;\n const entry: WalEntry = {\n seq: this.seq,\n op,\n collection,\n id,\n data,\n timestamp: new Date().toISOString(),\n checksum: '',\n };\n entry.checksum = this.checksum(entry);\n this.buffer.push(entry);\n\n if (this.buffer.length >= this.BUFFER_LIMIT) {\n await this.flush();\n } else {\n this.scheduleFlush();\n }\n\n return entry;\n }\n\n /**\n * Flush buffered WAL entries to Telegram.\n */\n async flush(): Promise<void> {\n if (this.buffer.length === 0) return;\n if (this.flushTimer) {\n clearTimeout(this.flushTimer);\n this.flushTimer = null;\n }\n\n const batch = [...this.buffer];\n this.buffer = [];\n\n const payload = JSON.stringify({\n __wal: true,\n [WAL_SEQ_TAG]: batch[batch.length - 1]!.seq,\n entries: batch,\n });\n\n // Split if > 4096 bytes (Telegram message limit)\n const chunks = this.chunk(payload, 4000);\n for (const chunk of chunks) {\n await this.pool.execute((bot) =>\n bot.sendMessage(this.walChannelId, `${WAL_HEADER}\\n${chunk}`, {\n disable_notification: true,\n })\n );\n }\n\n if (this.debug) console.log(`[WAL] Flushed ${batch.length} entries`);\n this.pool.emit('wal:flush', batch.length);\n }\n\n /**\n * Replay all WAL entries since a given sequence number.\n * Returns entries in order — the caller applies them to restore state.\n */\n async replay(sinceSeq = 0): Promise<WalEntry[]> {\n const entries: WalEntry[] = [];\n\n // Fetch messages from WAL channel, parse WAL entries\n try {\n const msgs = await this.pool.execute((bot) =>\n (bot as any).getChatHistory(this.walChannelId, { limit: 100 })\n );\n\n for (const msg of msgs as any[]) {\n if (!msg.text?.startsWith(WAL_HEADER)) continue;\n const jsonStr = msg.text.replace(WAL_HEADER + '\\n', '');\n try {\n const parsed = JSON.parse(jsonStr);\n if (parsed.__wal && Array.isArray(parsed.entries)) {\n for (const e of parsed.entries as WalEntry[]) {\n if (e.seq > sinceSeq && this.verifyChecksum(e)) {\n entries.push(e);\n }\n }\n }\n } catch {\n // Corrupted WAL entry — skip\n }\n }\n } catch {\n // Empty or inaccessible WAL\n }\n\n return entries.sort((a, b) => a.seq - b.seq);\n }\n\n private scheduleFlush(): void {\n if (this.flushTimer) return;\n this.flushTimer = setTimeout(() => this.flush(), this.FLUSH_INTERVAL_MS);\n }\n\n private checksum(entry: Omit<WalEntry, 'checksum'>): string {\n const str = `${entry.seq}:${entry.op}:${entry.collection}:${entry.id}:${JSON.stringify(entry.data)}`;\n return createHash('sha256').update(str).digest('hex').slice(0, 16);\n }\n\n private verifyChecksum(entry: WalEntry): boolean {\n const { checksum, ...rest } = entry;\n return checksum === this.checksum(rest);\n }\n\n private chunk(str: string, size: number): string[] {\n const chunks: string[] = [];\n for (let i = 0; i < str.length; i += size) {\n chunks.push(str.slice(i, i + size));\n }\n return chunks;\n }\n\n getCurrentSeq(): number {\n return this.seq;\n }\n}\n","import { randomUUID } from 'crypto';\nimport { Lease } from '../types/index.js';\nimport { BotWorkerPool } from '../workers/BotWorkerPool.js';\n\nconst REGISTRY_TAG = '__GRAMOBASE_REGISTRY__';\nconst LEASE_TTL_MS = 30_000;\nconst HEARTBEAT_MS = 10_000;\n\ninterface RegistryState {\n activeLease: Lease | null;\n instanceId: string;\n registryMsgId: number | null;\n}\n\n/**\n * Registry uses a pinned Telegram message as a distributed lock.\n *\n * When a gramobase instance starts up, it reads the registry message.\n * If no lease exists or the existing lease is expired, it writes a new\n * lease with its own instanceId and begins sending heartbeats.\n *\n * This prevents multiple writer processes from corrupting the index\n * (last-write-wins races on the pinned index message).\n *\n * Read-only operations are always permitted. Only index mutations\n * require holding the write lease.\n */\nexport class Registry {\n private state: RegistryState;\n private readonly instanceId: string;\n\n constructor(\n private pool: BotWorkerPool,\n private channelId: string,\n private debug: boolean = false\n ) {\n this.instanceId = randomUUID();\n this.state = {\n activeLease: null,\n instanceId: this.instanceId,\n registryMsgId: null,\n };\n }\n\n async acquireWriteLease(): Promise<Lease> {\n const existing = await this.readRegistryMessage();\n\n if (existing?.activeLease) {\n const lease = existing.activeLease;\n if (lease.instanceId !== this.instanceId && Date.now() < lease.expiresAt) {\n throw new Error(\n `[gramobase Registry] Another instance (${lease.instanceId}) holds the write lease until ${new Date(lease.expiresAt).toISOString()}. ` +\n `Use Registry.forceRelease() to break a stale lease.`\n );\n }\n }\n\n const lease: Lease = {\n instanceId: this.instanceId,\n acquiredAt: Date.now(),\n expiresAt: Date.now() + LEASE_TTL_MS,\n heartbeatInterval: null,\n };\n\n await this.writeRegistryMessage({ activeLease: lease });\n this.state.activeLease = lease;\n\n // Start heartbeat to renew lease while process is alive\n lease.heartbeatInterval = setInterval(\n () => this.heartbeat(),\n HEARTBEAT_MS\n );\n\n if (this.debug) console.log(`[Registry] Acquired write lease: ${this.instanceId}`);\n return lease;\n }\n\n async releaseWriteLease(): Promise<void> {\n if (!this.state.activeLease) return;\n\n if (this.state.activeLease.heartbeatInterval) {\n clearInterval(this.state.activeLease.heartbeatInterval);\n }\n\n await this.writeRegistryMessage({ activeLease: null });\n this.state.activeLease = null;\n\n if (this.debug) console.log(`[Registry] Released write lease: ${this.instanceId}`);\n }\n\n async forceRelease(): Promise<void> {\n await this.writeRegistryMessage({ activeLease: null });\n this.state.activeLease = null;\n if (this.debug) console.log('[Registry] Forced lease release');\n }\n\n async isWriteLeaseHeld(): Promise<boolean> {\n const state = await this.readRegistryMessage();\n if (!state?.activeLease) return false;\n const { activeLease } = state;\n return activeLease.instanceId === this.instanceId && Date.now() < activeLease.expiresAt;\n }\n\n private async heartbeat(): Promise<void> {\n if (!this.state.activeLease) return;\n this.state.activeLease.expiresAt = Date.now() + LEASE_TTL_MS;\n await this.writeRegistryMessage({ activeLease: this.state.activeLease });\n if (this.debug) console.log('[Registry] Heartbeat sent');\n }\n\n private async readRegistryMessage(): Promise<{ activeLease: Lease | null } | null> {\n try {\n const chat = await this.pool.execute((bot) =>\n bot.getChat(this.channelId)\n ) as any;\n\n if (chat.pinned_message?.text?.startsWith(REGISTRY_TAG)) {\n this.state.registryMsgId = chat.pinned_message.message_id;\n const json = chat.pinned_message.text.replace(REGISTRY_TAG + '\\n', '');\n return JSON.parse(json);\n }\n } catch {\n // No registry message yet\n }\n return null;\n }\n\n private async writeRegistryMessage(\n data: { activeLease: Lease | null }\n ): Promise<void> {\n const text = `${REGISTRY_TAG}\\n${JSON.stringify(data, null, 0)}`;\n\n if (this.state.registryMsgId) {\n // Try to update existing pinned message\n try {\n await this.pool.execute((bot) =>\n bot.editMessageText(text, {\n chat_id: this.channelId,\n message_id: this.state.registryMsgId!,\n })\n );\n return;\n } catch {\n // Message may have been deleted; fall through to create new\n }\n }\n\n const msg = await this.pool.execute((bot) =>\n bot.sendMessage(this.channelId, text, { disable_notification: true })\n ) as any;\n\n this.state.registryMsgId = msg.message_id;\n await this.pool.execute((bot) =>\n bot.pinChatMessage(this.channelId, msg.message_id, {\n disable_notification: true,\n })\n );\n }\n\n getInstanceId(): string {\n return this.instanceId;\n }\n\n getCurrentLease(): Lease | null {\n return this.state.activeLease;\n }\n}\n","import { randomUUID, createHash } from 'crypto';\nimport { z } from 'zod';\nimport {\n Filter,\n FindOptions,\n UpdateOperators,\n GramoBaseDocument,\n CollectionConfig,\n WithId,\n} from '../types/index.js';\nimport { HotCache } from '../cache/HotCache.js';\nimport { TelegramStorage } from '../storage/TelegramStorage.js';\nimport { WriteAheadLog } from '../wal/WriteAheadLog.js';\n\ntype DocOf<T extends z.ZodType> = WithId<z.infer<T>>;\n\n/**\n * Collection<T> is the main ORM interface.\n *\n * It provides a MongoDB-like API and handles:\n * - Schema validation via Zod\n * - Hot-cache reads (LRU in-memory)\n * - WAL writes before Telegram flush\n * - Index management (id → msgId map, stored as a pinned message)\n * - Filter/sort/skip/limit in memory after cache warm-up\n */\nexport class Collection<T extends z.ZodType> {\n private name: string;\n private config: CollectionConfig<T>;\n private cache: HotCache;\n private storage: TelegramStorage;\n private wal: WriteAheadLog;\n private channelId: string;\n private indexLoaded = false;\n\n constructor(\n name: string,\n config: CollectionConfig<T>,\n cache: HotCache,\n storage: TelegramStorage,\n wal: WriteAheadLog,\n defaultChannelId: string\n ) {\n this.name = name;\n this.config = config;\n this.cache = cache;\n this.storage = storage;\n this.wal = wal;\n this.channelId = config.channelId ?? defaultChannelId;\n }\n\n // ─── Init ──────────────────────────────────────────────────────────────\n\n async ensureIndexLoaded(): Promise<void> {\n if (this.indexLoaded) return;\n const idx = await this.storage.loadIndex(this.name, this.channelId);\n this.cache.setIndex(this.name, new Map(Object.entries(idx.entries).map(([k, v]) => [k, v])));\n this.indexLoaded = true;\n }\n\n // ─── Insert ────────────────────────────────────────────────────────────\n\n async insertOne(data: z.infer<T>): Promise<DocOf<T>> {\n const validated = this.config.schema.parse(data) as z.infer<T>;\n const doc: GramoBaseDocument = {\n ...validated,\n _id: randomUUID(),\n _collection: this.name,\n _msgId: 0,\n _createdAt: new Date().toISOString(),\n _updatedAt: new Date().toISOString(),\n };\n\n // WAL before write\n await this.wal.append('INSERT', this.name, doc._id, doc);\n\n const msgId = await this.storage.writeDocument(doc, this.channelId);\n doc._msgId = msgId;\n\n // Update cache + index\n this.cache.set(this.name, doc._id, doc);\n this.cache.updateIndexEntry(this.name, doc._id, msgId);\n this.cache.invalidateQuery(this.name);\n\n // Persist index\n await this.flushIndex();\n\n return doc as DocOf<T>;\n }\n\n async insertMany(items: z.infer<T>[]): Promise<DocOf<T>[]> {\n return Promise.all(items.map((item) => this.insertOne(item)));\n }\n\n // ─── Find ──────────────────────────────────────────────────────────────\n\n async findById(id: string): Promise<DocOf<T> | null> {\n // Cache hit\n const cached = this.cache.get<DocOf<T>>(this.name, id);\n if (cached) return cached;\n\n await this.ensureIndexLoaded();\n const msgId = this.cache.getMsgId(this.name, id);\n if (!msgId) return null;\n\n const doc = await this.storage.readDocument(msgId, this.channelId);\n if (!doc) return null;\n\n this.cache.set(this.name, id, doc);\n return doc as DocOf<T>;\n }\n\n async findOne(filter: Filter<z.infer<T>> = {}): Promise<DocOf<T> | null> {\n const results = await this.find({ filter, limit: 1 });\n return results[0] ?? null;\n }\n\n async find(options: FindOptions<z.infer<T>> = {}): Promise<DocOf<T>[]> {\n const { filter = {}, sort, limit, skip = 0, projection, useCache = true } = options;\n\n // Check query cache\n const queryHash = this.hashQuery(filter, sort, limit, skip);\n if (useCache) {\n const cached = this.cache.getQuery<DocOf<T>>(queryHash);\n if (cached) return cached;\n }\n\n // Load all documents from index\n await this.ensureIndexLoaded();\n const index = this.cache.getIndex(this.name);\n if (!index) return [];\n\n const docs: DocOf<T>[] = [];\n const ids = [...index.keys()];\n\n // Batch read with cache\n const uncachedIds: string[] = [];\n for (const id of ids) {\n const cached = this.cache.get<DocOf<T>>(this.name, id);\n if (cached) {\n docs.push(cached);\n } else {\n uncachedIds.push(id);\n }\n }\n\n // Fetch uncached from Telegram\n await Promise.all(\n uncachedIds.map(async (id) => {\n const doc = await this.findById(id);\n if (doc) docs.push(doc);\n })\n );\n\n // Apply filter\n let results = docs.filter((doc) => this.matchesFilter(doc, filter));\n\n // Apply sort\n if (sort) {\n results = this.applySort(results, sort as Record<string, 1 | -1>);\n }\n\n // Apply pagination\n results = results.slice(skip, limit ? skip + limit : undefined);\n\n // Apply projection\n if (projection) {\n results = results.map((doc) => this.applyProjection(doc, projection as Record<string, 1 | 0>));\n }\n\n // Cache query result\n if (useCache) {\n this.cache.setQuery(queryHash, results);\n }\n\n return results;\n }\n\n async count(filter: Filter<z.infer<T>> = {}): Promise<number> {\n const results = await this.find({ filter, useCache: true });\n return results.length;\n }\n\n // ─── Update ────────────────────────────────────────────────────────────\n\n async updateOne(\n filter: Filter<z.infer<T>>,\n update: UpdateOperators<z.infer<T>>\n ): Promise<DocOf<T> | null> {\n const doc = await this.findOne(filter);\n if (!doc) return null;\n return this.applyUpdate(doc, update);\n }\n\n async updateMany(\n filter: Filter<z.infer<T>>,\n update: UpdateOperators<z.infer<T>>\n ): Promise<DocOf<T>[]> {\n const docs = await this.find({ filter });\n return Promise.all(docs.map((doc) => this.applyUpdate(doc, update)));\n }\n\n async findByIdAndUpdate(\n id: string,\n update: UpdateOperators<z.infer<T>>\n ): Promise<DocOf<T> | null> {\n const doc = await this.findById(id);\n if (!doc) return null;\n return this.applyUpdate(doc, update);\n }\n\n private async applyUpdate(\n doc: GramoBaseDocument,\n update: UpdateOperators<unknown>\n ): Promise<DocOf<T>> {\n const updated = { ...doc, _updatedAt: new Date().toISOString() };\n\n if (update.$set) Object.assign(updated, update.$set);\n if (update.$unset) {\n for (const key of Object.keys(update.$unset)) {\n delete (updated as Record<string, unknown>)[key];\n }\n }\n if (update.$inc) {\n for (const [key, val] of Object.entries(update.$inc)) {\n (updated as Record<string, unknown>)[key] =\n (((updated as Record<string, unknown>)[key] as number) ?? 0) + (val as number);\n }\n }\n if (update.$push) {\n for (const [key, val] of Object.entries(update.$push)) {\n const arr = (updated as Record<string, unknown>)[key];\n (updated as Record<string, unknown>)[key] = Array.isArray(arr)\n ? [...arr, val]\n : [val];\n }\n }\n\n // Validate updated doc\n this.config.schema.parse(updated);\n\n await this.wal.append('UPDATE', this.name, updated._id, updated);\n\n const newMsgId = await this.storage.updateDocument(\n updated._msgId,\n updated as GramoBaseDocument,\n this.channelId\n );\n updated._msgId = newMsgId;\n\n this.cache.set(this.name, updated._id, updated);\n this.cache.updateIndexEntry(this.name, updated._id, newMsgId);\n this.cache.invalidateQuery(this.name);\n\n await this.flushIndex();\n\n return updated as DocOf<T>;\n }\n\n // ─── Delete ────────────────────────────────────────────────────────────\n\n async deleteOne(filter: Filter<z.infer<T>>): Promise<boolean> {\n const doc = await this.findOne(filter);\n if (!doc) return false;\n return this.deleteById(doc._id);\n }\n\n async deleteMany(filter: Filter<z.infer<T>>): Promise<number> {\n const docs = await this.find({ filter });\n await Promise.all(docs.map((doc) => this.deleteById(doc._id)));\n return docs.length;\n }\n\n async deleteById(id: string): Promise<boolean> {\n const msgId = this.cache.getMsgId(this.name, id);\n if (!msgId) return false;\n\n await this.wal.append('DELETE', this.name, id);\n await this.storage.deleteDocument(msgId, this.channelId);\n\n this.cache.delete(this.name, id);\n this.cache.deleteIndexEntry(this.name, id);\n this.cache.invalidateQuery(this.name);\n\n await this.flushIndex();\n return true;\n }\n\n // ─── Index flush ──────────────────────────────────────────────────────\n\n private async flushIndex(): Promise<void> {\n const index = this.cache.getIndex(this.name);\n if (!index) return;\n\n await this.storage.saveIndex(\n {\n collection: this.name,\n entries: Object.fromEntries(index.entries()),\n walSeq: this.wal.getCurrentSeq(),\n updatedAt: new Date().toISOString(),\n },\n this.channelId\n );\n }\n\n // ─── Filter engine ─────────────────────────────────────────────────────\n\n private matchesFilter(doc: unknown, filter: Filter<unknown>): boolean {\n for (const [key, condition] of Object.entries(filter)) {\n if (key === '$and') {\n if (!(condition as Filter<unknown>[]).every((f) => this.matchesFilter(doc, f)))\n return false;\n continue;\n }\n if (key === '$or') {\n if (!(condition as Filter<unknown>[]).some((f) => this.matchesFilter(doc, f)))\n return false;\n continue;\n }\n if (key === '$not') {\n if (this.matchesFilter(doc, condition as Filter<unknown>)) return false;\n continue;\n }\n\n const val = (doc as Record<string, unknown>)[key];\n if (condition === null || typeof condition !== 'object' || condition instanceof RegExp) {\n if (Array.isArray(val)) {\n if (condition instanceof RegExp) {\n if (!val.some((item) => condition.test(String(item)))) return false;\n } else {\n if (!val.includes(condition)) return false;\n }\n } else {\n if (condition instanceof RegExp) {\n if (!condition.test(String(val))) return false;\n } else {\n if (val !== condition) return false;\n }\n }\n continue;\n }\n\n const ops = condition as Record<string, unknown>;\n if ('$eq' in ops) {\n const eqVal = ops['$eq'];\n if (Array.isArray(val)) {\n if (Array.isArray(eqVal)) {\n if (val.length !== eqVal.length || !val.every((v, i) => v === eqVal[i])) return false;\n } else {\n if (!val.includes(eqVal)) return false;\n }\n } else {\n if (val !== eqVal) return false;\n }\n }\n if ('$ne' in ops) {\n const neVal = ops['$ne'];\n if (Array.isArray(val)) {\n if (Array.isArray(neVal)) {\n if (val.length === neVal.length && val.every((v, i) => v === neVal[i])) return false;\n } else {\n if (val.includes(neVal)) return false;\n }\n } else {\n if (val === neVal) return false;\n }\n }\n if ('$gt' in ops && !((val as number) > (ops['$gt'] as number))) return false;\n if ('$gte' in ops && !((val as number) >= (ops['$gte'] as number))) return false;\n if ('$lt' in ops && !((val as number) < (ops['$lt'] as number))) return false;\n if ('$lte' in ops && !((val as number) <= (ops['$lte'] as number))) return false;\n if ('$in' in ops) {\n const inList = ops['$in'] as unknown[];\n if (Array.isArray(val)) {\n const hasIntersection = val.some((v) => inList.includes(v));\n const hasExactArray = inList.some(\n (item) => Array.isArray(item) && item.length === val.length && item.every((v, i) => v === val[i])\n );\n if (!hasIntersection && !hasExactArray) return false;\n } else {\n if (!inList.includes(val)) return false;\n }\n }\n if ('$nin' in ops) {\n const ninList = ops['$nin'] as unknown[];\n if (Array.isArray(val)) {\n const hasIntersection = val.some((v) => ninList.includes(v));\n const hasExactArray = ninList.some(\n (item) => Array.isArray(item) && item.length === val.length && item.every((v, i) => v === val[i])\n );\n if (hasIntersection || hasExactArray) return false;\n } else {\n if (ninList.includes(val)) return false;\n }\n }\n if ('$exists' in ops) {\n const exists = val !== undefined && val !== null;\n if (exists !== ops['$exists']) return false;\n }\n if ('$regex' in ops) {\n const re =\n ops['$regex'] instanceof RegExp\n ? ops['$regex']\n : new RegExp(ops['$regex'] as string);\n if (Array.isArray(val)) {\n if (!val.some((item) => re.test(String(item)))) return false;\n } else {\n if (!re.test(String(val))) return false;\n }\n }\n }\n return true;\n }\n\n private applySort<D>(docs: D[], sort: Record<string, 1 | -1>): D[] {\n return [...docs].sort((a, b) => {\n for (const [key, dir] of Object.entries(sort)) {\n const av = (a as Record<string, unknown>)[key];\n const bv = (b as Record<string, unknown>)[key];\n if (av === bv) continue;\n if (av == null) return dir;\n if (bv == null) return -dir;\n return av < bv ? -dir : dir;\n }\n return 0;\n });\n }\n\n private applyProjection<D>(doc: D, projection: Record<string, 1 | 0>): D {\n const result: Record<string, unknown> = {};\n const isInclusive = Object.values(projection).some((v) => v === 1);\n for (const [key, val] of Object.entries(doc as Record<string, unknown>)) {\n if (isInclusive) {\n if (projection[key] === 1 || key.startsWith('_')) result[key] = val;\n } else {\n if (projection[key] !== 0) result[key] = val;\n }\n }\n return result as D;\n }\n\n private hashQuery(...args: unknown[]): string {\n return `${this.name}:` + createHash('md5').update(JSON.stringify(args)).digest('hex');\n }\n\n getName(): string {\n return this.name;\n }\n}\n","import { randomUUID, randomBytes } from 'crypto';\nimport * as jwt from 'jsonwebtoken';\nimport * as bcrypt from 'bcryptjs';\nimport { z } from 'zod';\nimport { AuthConfig, User, Session } from '../types/index.js';\nimport { Collection } from '../orm/Collection.js';\nimport { existsSync, readFileSync } from 'fs';\n\nconst UserSchema = z.object({\n email: z.string().email(),\n passwordHash: z.string(),\n roles: z.array(z.string()).default(['user']),\n metadata: z.record(z.unknown()).optional(),\n createdAt: z.string(),\n updatedAt: z.string(),\n});\n\n// TODO(security): Consider adding OAuth 2.0 provider support (e.g., Google, GitHub).\n// TODO(security): Consider adding MFA (TOTP/WebAuthn) for high-security deployments.\n// TODO(security): Consider adding pwned-password checking via haveibeenpwned.com API.\n\n/**\n * Resolve JWT secret with multi-tiered fallback:\n * 1. Explicit config value\n * 2. Environment variable\n * 3. Local jwt_secret.txt file\n * 4. Ephemeral random generation with warning (NOT suitable for multi-instance prod)\n *\n * MUST NOT hardcode or use default literal fallbacks.\n */\nfunction resolveJwtSecret(configSecret?: string): string {\n if (configSecret) return configSecret;\n if (process.env['JWT_SECRET']) return process.env['JWT_SECRET'];\n const secretFile = './jwt_secret.txt';\n if (existsSync(secretFile)) return readFileSync(secretFile, 'utf-8').trim();\n const ephemeral = randomBytes(32).toString('hex');\n console.warn(\n '[gramobase Auth] WARNING: No JWT_SECRET provided. Using an ephemeral random secret. ' +\n 'Tokens will be invalidated on restart. Set JWT_SECRET env variable for production!'\n );\n return ephemeral;\n}\n\n/**\n * Validate password strength (min 8 chars, no maximum).\n * Does not require specific character types — users choose their own strong passwords.\n */\nfunction validatePasswordStrength(password: string): void {\n if (password.length < 8) {\n throw new Error('[Auth] Password must be at least 8 characters long');\n }\n // TODO(security): Consider rejecting known breached passwords via HaveIBeenPwned API.\n}\n\nexport class GramoBaseAuth {\n private readonly DEFAULT_ROUNDS = 12;\n private readonly resolvedSecret: string;\n\n constructor(\n private users: Collection<typeof UserSchema>,\n private config: AuthConfig\n ) {\n // Resolve secret at construction time; fail safely if no secret available\n this.resolvedSecret = resolveJwtSecret(config.jwtSecret);\n }\n\n // ─── Registration ─────────────────────────────────────────────────────\n\n async register(\n email: string,\n password: string,\n roles: string[] = ['user'],\n metadata?: Record<string, unknown>\n ): Promise<{ user: User; session: Session }> {\n // Validate email format (basic — Zod schema handles full validation)\n if (!email || typeof email !== 'string') {\n throw new Error('[Auth] Invalid email');\n }\n\n // Validate password strength\n validatePasswordStrength(password);\n\n const existing = await this.users.findOne({ email: { $eq: email } } as any);\n if (existing) throw new Error('[Auth] Email already registered');\n\n const passwordHash = await bcrypt.hash(\n password,\n this.config.bcryptRounds ?? this.DEFAULT_ROUNDS\n );\n\n const now = new Date().toISOString();\n const doc = await this.users.insertOne({\n email,\n passwordHash,\n roles,\n metadata,\n createdAt: now,\n updatedAt: now,\n });\n\n const user = doc as unknown as User;\n const session = this.createSession(user);\n await this.config.onSignIn?.(user);\n\n return { user, session };\n }\n\n // ─── Login ────────────────────────────────────────────────────────────\n\n async login(email: string, password: string): Promise<{ user: User; session: Session }> {\n const doc = await this.users.findOne({ email: { $eq: email } } as any);\n if (!doc) {\n // Use constant-time comparison to avoid timing attacks on email existence\n await bcrypt.compare(password, '$2a$12$invalidhashtopreventtimingattacks');\n throw new Error('[Auth] Invalid credentials');\n }\n\n const user = doc as unknown as User;\n const valid = await bcrypt.compare(password, user.passwordHash);\n if (!valid) throw new Error('[Auth] Invalid credentials');\n\n const session = this.createSession(user);\n await this.config.onSignIn?.(user);\n\n return { user, session };\n }\n\n // ─── Token verification ───────────────────────────────────────────────\n\n verifyToken(token: string): Session {\n try {\n // Hardcode algorithm to prevent algorithm confusion attacks; reject 'none'\n const payload = jwt.verify(token, this.resolvedSecret, {\n algorithms: ['HS256'],\n }) as Session;\n return payload;\n } catch {\n throw new Error('[Auth] Invalid or expired token');\n }\n }\n\n // ─── Role-based access ────────────────────────────────────────────────\n\n requireRole(session: Session, role: string): void {\n if (!session.roles.includes(role) && !session.roles.includes('admin')) {\n throw new Error(`[Auth] Requires role: ${role}`);\n }\n }\n\n requireAnyRole(session: Session, roles: string[]): void {\n const hasRole = roles.some(\n (r) => session.roles.includes(r) || session.roles.includes('admin')\n );\n if (!hasRole) {\n throw new Error(`[Auth] Requires one of roles: ${roles.join(', ')}`);\n }\n }\n\n // ─── Password management ──────────────────────────────────────────────\n\n async changePassword(\n userId: string,\n oldPassword: string,\n newPassword: string\n ): Promise<void> {\n const doc = await this.users.findById(userId);\n if (!doc) throw new Error('[Auth] User not found');\n\n const user = doc as unknown as User;\n const valid = await bcrypt.compare(oldPassword, user.passwordHash);\n if (!valid) throw new Error('[Auth] Old password incorrect');\n\n // Validate new password strength\n validatePasswordStrength(newPassword);\n\n const newHash = await bcrypt.hash(\n newPassword,\n this.config.bcryptRounds ?? this.DEFAULT_ROUNDS\n );\n\n await this.users.findByIdAndUpdate(userId, {\n $set: { passwordHash: newHash, updatedAt: new Date().toISOString() } as any,\n });\n }\n\n async resetPassword(userId: string, newPassword: string): Promise<void> {\n validatePasswordStrength(newPassword);\n const newHash = await bcrypt.hash(\n newPassword,\n this.config.bcryptRounds ?? this.DEFAULT_ROUNDS\n );\n await this.users.findByIdAndUpdate(userId, {\n $set: { passwordHash: newHash, updatedAt: new Date().toISOString() } as any,\n });\n }\n\n // ─── User management ─────────────────────────────────────────────────\n\n async getUserById(id: string): Promise<User | null> {\n const doc = await this.users.findById(id);\n return doc ? (doc as unknown as User) : null;\n }\n\n async getUserByEmail(email: string): Promise<User | null> {\n const doc = await this.users.findOne({ email: { $eq: email } } as any);\n return doc ? (doc as unknown as User) : null;\n }\n\n async updateRoles(userId: string, roles: string[]): Promise<void> {\n await this.users.findByIdAndUpdate(userId, {\n $set: { roles, updatedAt: new Date().toISOString() } as any,\n });\n }\n\n async deleteUser(userId: string): Promise<void> {\n await this.users.deleteById(userId);\n await this.config.onSignOut?.(userId);\n }\n\n // ─── Session helpers ──────────────────────────────────────────────────\n\n private createSession(user: User): Session {\n const expiresIn = this.config.jwtExpiresIn ?? '7d';\n const payload: Omit<Session, 'token'> & { sub: string } = {\n sub: user._id,\n userId: user._id,\n roles: user.roles,\n expiresAt: Date.now() + this.parseExpiry(expiresIn),\n };\n\n // Sign with hardcoded HS256 algorithm; 'none' algorithm is never used\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const token = (jwt.sign as any)(payload, this.resolvedSecret, {\n expiresIn,\n algorithm: 'HS256',\n }) as string;\n return { ...payload, token };\n }\n\n private parseExpiry(s: string): number {\n const n = parseInt(s);\n if (s.endsWith('d')) return n * 86400_000;\n if (s.endsWith('h')) return n * 3600_000;\n if (s.endsWith('m')) return n * 60_000;\n return n * 1000;\n }\n\n // ─── Middleware factory (Express/Fastify compatible) ──────────────────\n\n middleware() {\n return (req: any, res: any, next: any) => {\n const auth = req.headers['authorization'] as string | undefined;\n if (!auth?.startsWith('Bearer ')) {\n return res.status(401).json({ error: 'Missing token' });\n }\n try {\n req.session = this.verifyToken(auth.slice(7));\n next();\n } catch {\n // Do NOT expose error details to client; log internally if needed\n res.status(401).json({ error: 'Unauthorized' });\n }\n };\n }\n\n requireRoleMiddleware(role: string) {\n return (req: any, res: any, next: any) => {\n try {\n this.requireRole(req.session, role);\n next();\n } catch {\n res.status(403).json({ error: 'Forbidden' });\n }\n };\n }\n}\n","import EventEmitter from 'eventemitter3';\nimport { GramoBaseEvent } from '../types/index.js';\nimport { BotWorkerPool } from '../workers/BotWorkerPool.js';\n\ntype Unsubscribe = () => void;\n\n/**\n * RealtimeManager bridges Telegram bot webhook / long-polling events\n * into a local EventEmitter that client code can subscribe to.\n *\n * Server-Sent Events (SSE) adapter included for HTTP streaming to browsers.\n */\nexport class RealtimeManager extends EventEmitter {\n private pollingActive = false;\n private pollingInterval: NodeJS.Timeout | null = null;\n private lastUpdateId = 0;\n\n constructor(\n private pool: BotWorkerPool,\n private webhookUrl?: string,\n private debug = false\n ) {\n super();\n }\n\n async start(): Promise<void> {\n if (this.webhookUrl) {\n await this.setupWebhook();\n } else {\n this.startPolling();\n }\n }\n\n async stop(): Promise<void> {\n if (this.pollingInterval) {\n clearInterval(this.pollingInterval);\n this.pollingInterval = null;\n }\n this.pollingActive = false;\n }\n\n // ─── Subscribe helpers ────────────────────────────────────────────────\n\n onInsert<T>(collection: string, cb: (doc: T) => void): Unsubscribe {\n const handler = (ev: GramoBaseEvent) => {\n if (ev.type === 'insert' && ev.collection === collection) {\n cb(ev.doc as T);\n }\n };\n this.on('event', handler);\n return () => this.off('event', handler);\n }\n\n onUpdate<T>(collection: string, cb: (id: string, changes: Partial<T>, doc: T) => void): Unsubscribe {\n const handler = (ev: GramoBaseEvent) => {\n if (ev.type === 'update' && ev.collection === collection) {\n cb(ev.id, ev.changes as Partial<T>, ev.doc as T);\n }\n };\n this.on('event', handler);\n return () => this.off('event', handler);\n }\n\n onDelete(collection: string, cb: (id: string) => void): Unsubscribe {\n const handler = (ev: GramoBaseEvent) => {\n if (ev.type === 'delete' && ev.collection === collection) {\n cb(ev.id);\n }\n };\n this.on('event', handler);\n return () => this.off('event', handler);\n }\n\n onAny(cb: (ev: GramoBaseEvent) => void): Unsubscribe {\n const handler = (ev: GramoBaseEvent) => cb(ev);\n this.on('event', handler);\n return () => this.off('event', handler);\n }\n\n // ─── SSE adapter ──────────────────────────────────────────────────────\n // Usage: app.get('/events', db.realtime.sseHandler())\n\n sseHandler(collection?: string) {\n return (req: any, res: any) => {\n res.setHeader('Content-Type', 'text/event-stream');\n res.setHeader('Cache-Control', 'no-cache, no-store');\n res.setHeader('Connection', 'keep-alive');\n res.setHeader('X-Content-Type-Options', 'nosniff');\n res.flushHeaders?.();\n\n const send = (ev: GramoBaseEvent) => {\n if (!collection || ('collection' in ev && ev.collection === collection)) {\n // JSON.stringify ensures proper output encoding — no raw user data in stream\n res.write(`data: ${JSON.stringify(ev)}\\n\\n`);\n }\n };\n\n this.on('event', send);\n const keepalive = setInterval(() => res.write(': ping\\n\\n'), 25_000);\n\n req.on('close', () => {\n this.off('event', send);\n clearInterval(keepalive);\n });\n };\n }\n\n // ─── Internal event dispatch ──────────────────────────────────────────\n\n dispatch(event: GramoBaseEvent): void {\n this.emit('event', event);\n if (this.debug) {\n // Only log event type — do NOT log event payload to avoid leaking sensitive data\n console.log('[Realtime]', event.type, 'collection' in event ? event.collection : '');\n }\n }\n\n // ─── Webhook setup ────────────────────────────────────────────────────\n\n private async setupWebhook(): Promise<void> {\n const bot = this.pool.getBot();\n await bot.setWebHook(this.webhookUrl!);\n if (this.debug) console.log('[Realtime] Webhook set');\n }\n\n // ─── Long polling fallback ────────────────────────────────────────────\n\n private startPolling(): void {\n this.pollingActive = true;\n const POLL_INTERVAL = 2000;\n\n this.pollingInterval = setInterval(async () => {\n try {\n const updates = await this.pool.execute((bot) =>\n bot.getUpdates({ offset: this.lastUpdateId + 1, limit: 100, timeout: 0 })\n ) as any[];\n\n for (const update of updates) {\n this.lastUpdateId = Math.max(this.lastUpdateId, update.update_id);\n this.processUpdate(update);\n }\n } catch {\n // Polling error — continue\n }\n }, POLL_INTERVAL);\n }\n\n private processUpdate(update: any): void {\n // Parse channel_post messages that are gramobase records\n const msg = update.channel_post ?? update.message;\n if (!msg?.text?.includes('\"__gramobase\"')) return;\n\n try {\n const payload = JSON.parse(msg.text);\n if (payload.__event) {\n this.dispatch(payload.__event as GramoBaseEvent);\n }\n } catch {\n // Not a gramobase event message\n }\n }\n}\n","import { Migration } from '../types/index.js';\nimport { BotWorkerPool } from '../workers/BotWorkerPool.js';\n\nconst MIGRATION_TAG = '__GRAMOBASE_MIGRATIONS__';\n\ninterface MigrationRecord {\n version: number;\n name: string;\n appliedAt: string;\n}\n\n/**\n * MigrationRunner stores a migration history message in the Telegram channel\n * and applies pending up() migrations in order.\n */\nexport class MigrationRunner {\n private historyMsgId: number | null = null;\n\n constructor(\n private pool: BotWorkerPool,\n private channelId: string,\n private debug = false\n ) {}\n\n async run(migrations: Migration[], db: unknown): Promise<void> {\n const applied = await this.loadHistory();\n const appliedVersions = new Set(applied.map((m) => m.version));\n\n const pending = migrations\n .filter((m) => !appliedVersions.has(m.version))\n .sort((a, b) => a.version - b.version);\n\n if (pending.length === 0) {\n if (this.debug) console.log('[Migrations] Nothing to run');\n return;\n }\n\n for (const migration of pending) {\n console.log(`[Migrations] Running: v${migration.version} — ${migration.name}`);\n await migration.up(db);\n applied.push({\n version: migration.version,\n name: migration.name,\n appliedAt: new Date().toISOString(),\n });\n await this.saveHistory(applied);\n console.log(`[Migrations] ✓ v${migration.version}`);\n }\n }\n\n async rollback(migrations: Migration[], db: unknown, steps = 1): Promise<void> {\n const applied = await this.loadHistory();\n const toRollback = applied\n .sort((a, b) => b.version - a.version)\n .slice(0, steps);\n\n for (const record of toRollback) {\n const migration = migrations.find((m) => m.version === record.version);\n if (!migration) throw new Error(`Migration v${record.version} not found`);\n\n console.log(`[Migrations] Rolling back: v${record.version} — ${record.name}`);\n await migration.down(db);\n applied.splice(applied.indexOf(record), 1);\n await this.saveHistory(applied);\n console.log(`[Migrations] ✓ Rolled back v${record.version}`);\n }\n }\n\n async status(migrations: Migration[]): Promise<void> {\n const applied = await this.loadHistory();\n const appliedVersions = new Set(applied.map((m) => m.version));\n\n console.log('\\n gramobase migration status\\n');\n for (const m of migrations.sort((a, b) => a.version - b.version)) {\n const status = appliedVersions.has(m.version) ? '✓' : '○';\n const appliedAt = applied.find((a) => a.version === m.version)?.appliedAt ?? '';\n console.log(` ${status} v${m.version} ${m.name.padEnd(40)} ${appliedAt}`);\n }\n console.log();\n }\n\n private async loadHistory(): Promise<MigrationRecord[]> {\n try {\n const chat = await this.pool.execute((bot) => bot.getChat(this.channelId)) as any;\n for (const msg of (chat.pinned_messages ?? [])) {\n if (msg.text?.startsWith(MIGRATION_TAG)) {\n this.historyMsgId = msg.message_id;\n return JSON.parse(msg.text.replace(MIGRATION_TAG + '\\n', ''));\n }\n }\n } catch {\n // No history yet\n }\n return [];\n }\n\n private async saveHistory(records: MigrationRecord[]): Promise<void> {\n const text = `${MIGRATION_TAG}\\n${JSON.stringify(records)}`;\n\n if (this.historyMsgId) {\n try {\n await this.pool.execute((bot) =>\n bot.editMessageText(text, {\n chat_id: this.channelId,\n message_id: this.historyMsgId!,\n })\n );\n return;\n } catch {}\n }\n\n const msg = await this.pool.execute((bot) =>\n bot.sendMessage(this.channelId, text, { disable_notification: true })\n ) as any;\n this.historyMsgId = msg.message_id;\n }\n}\n","import { z } from 'zod';\nimport { GramoBaseConfig, CollectionConfig, AuthConfig, UploadOptions, FileRecord, Migration } from './types/index.js';\nimport { BotWorkerPool } from './workers/BotWorkerPool.js';\nimport { HotCache } from './cache/HotCache.js';\nimport { TelegramStorage } from './storage/TelegramStorage.js';\nimport { WriteAheadLog } from './wal/WriteAheadLog.js';\nimport { Registry } from './registry/Registry.js';\nimport { Collection } from './orm/Collection.js';\nimport { GramoBaseAuth } from './auth/GramoBaseAuth.js';\nimport { RealtimeManager } from './realtime/RealtimeManager.js';\nimport { MigrationRunner } from './migrations/MigrationRunner.js';\nimport { randomUUID } from 'crypto';\n\nexport class GramoBase {\n private pool: BotWorkerPool;\n private cache: HotCache;\n private storage: TelegramStorage;\n private wal: WriteAheadLog;\n readonly registry: Registry;\n readonly realtime: RealtimeManager;\n private migrations: MigrationRunner;\n private collections: Map<string, Collection<z.ZodType>> = new Map();\n private initialized = false;\n private config: GramoBaseConfig;\n\n constructor(config: GramoBaseConfig) {\n this.config = config;\n const tokens = Array.isArray(config.botToken)\n ? config.botToken\n : [config.botToken];\n\n this.pool = new BotWorkerPool(tokens, config.concurrency ?? 25, config.debug ?? false);\n this.cache = new HotCache(config.cacheMaxBytes, config.cacheTtlMs);\n this.storage = new TelegramStorage(\n this.pool,\n config.channelId,\n config.encryptionKey,\n config.debug ?? false\n );\n this.wal = new WriteAheadLog(\n this.pool,\n config.walChannelId ?? config.channelId,\n config.debug ?? false\n );\n this.registry = new Registry(\n this.pool,\n config.indexChannelId ?? config.channelId,\n config.debug ?? false\n );\n this.realtime = new RealtimeManager(\n this.pool,\n config.webhookUrl,\n config.debug ?? false\n );\n this.migrations = new MigrationRunner(\n this.pool,\n config.channelId,\n config.debug ?? false\n );\n\n // Bubble worker events\n this.pool.on('worker:rotate', (idx) => {\n this.realtime.dispatch({ type: 'worker:rotate', tokenIndex: idx });\n });\n this.pool.on('wal:flush', (count) => {\n this.realtime.dispatch({ type: 'wal:flush', entries: count });\n });\n }\n\n // ─── Lifecycle ────────────────────────────────────────────────────────\n\n async connect(): Promise<this> {\n if (this.initialized) return this;\n\n await this.wal.init();\n await this.registry.acquireWriteLease();\n await this.realtime.start();\n\n // WAL replay — recover any uncommitted writes\n const walEntries = await this.wal.replay();\n if (walEntries.length > 0 && this.config.debug) {\n console.log(`[gramobase] Replaying ${walEntries.length} WAL entries`);\n }\n\n this.initialized = true;\n if (this.config.debug) console.log('[gramobase] Connected ✓');\n return this;\n }\n\n async disconnect(): Promise<void> {\n await this.wal.flush();\n await this.registry.releaseWriteLease();\n await this.realtime.stop();\n await this.pool.destroy();\n this.initialized = false;\n }\n\n // ─── Collection factory ───────────────────────────────────────────────\n\n collection<T extends z.ZodType>(\n name: string,\n config: CollectionConfig<T>\n ): Collection<T> {\n if (this.collections.has(name)) {\n return this.collections.get(name) as Collection<T>;\n }\n const col = new Collection(\n name,\n config,\n this.cache,\n this.storage,\n this.wal,\n this.config.channelId\n );\n this.collections.set(name, col as Collection<z.ZodType>);\n return col;\n }\n\n // ─── Auth factory ─────────────────────────────────────────────────────\n\n createAuth(config: AuthConfig): GramoBaseAuth {\n const UserSchema = z.object({\n email: z.string().email(),\n passwordHash: z.string(),\n roles: z.array(z.string()).default(['user']),\n metadata: z.record(z.unknown()).optional(),\n createdAt: z.string(),\n updatedAt: z.string(),\n });\n\n const users = this.collection('__gramobase_users__', { schema: UserSchema });\n return new GramoBaseAuth(users as any, config);\n }\n\n // ─── File storage ─────────────────────────────────────────────────────\n\n async uploadFile(\n data: Buffer,\n options: UploadOptions = {}\n ): Promise<FileRecord> {\n const { fileName = 'file', mimeType = 'application/octet-stream', metadata } = options;\n const channelId = this.config.channelId;\n\n const { fileId, msgId } = await this.storage.uploadFile(data, fileName, mimeType, channelId);\n const url = await this.storage.getFileUrl(fileId);\n\n const record: FileRecord = {\n _id: randomUUID(),\n fileId,\n fileName,\n mimeType,\n sizeBytes: data.length,\n uploadedAt: new Date().toISOString(),\n ...(url !== undefined ? { url } : {}),\n ...(metadata !== undefined ? { metadata } : {}),\n };\n\n // Store file record in a dedicated files collection\n const files = this.collection('__gramobase_files__', {\n schema: z.object({\n _id: z.string(),\n fileId: z.string(),\n fileName: z.string(),\n mimeType: z.string(),\n sizeBytes: z.number(),\n url: z.string().optional(),\n uploadedAt: z.string(),\n metadata: z.record(z.unknown()).optional(),\n }),\n });\n\n await (files as any).insertOne(record);\n return record;\n }\n\n async getFileUrl(fileId: string): Promise<string> {\n return this.storage.getFileUrl(fileId);\n }\n\n // ─── Migrations ───────────────────────────────────────────────────────\n\n async migrate(migrations: Migration[]): Promise<void> {\n await this.migrations.run(migrations, this);\n }\n\n async rollback(migrations: Migration[], steps = 1): Promise<void> {\n await this.migrations.rollback(migrations, this, steps);\n }\n\n async migrationStatus(migrations: Migration[]): Promise<void> {\n await this.migrations.status(migrations);\n }\n\n // ─── State helpers ────────────────────────────────────────────────────\n\n getCacheStats() {\n return this.cache.getStats();\n }\n\n getWorkerStats() {\n return this.pool.getStats();\n }\n\n getRegistryInstanceId(): string {\n return this.registry.getInstanceId();\n }\n\n /**\n * Warm up the cache by pre-loading all collection indexes.\n */\n async warmCache(): Promise<void> {\n for (const col of this.collections.values()) {\n await (col as any).ensureIndexLoaded();\n }\n }\n}\n\n// ─── Convenience factory ───────────────────────────────────────────────────\n\nexport function createClient(config: GramoBaseConfig): GramoBase {\n return new GramoBase(config);\n}\n\n// Re-exports\nexport { GramoBaseAuth } from './auth/GramoBaseAuth.js';\nexport { Collection } from './orm/Collection.js';\nexport { RealtimeManager } from './realtime/RealtimeManager.js';\nexport type * from './types/index.js';\n","import * as http from 'http';\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport { getStudioHTML } from './ui.js';\nimport { createClient, GramoBase } from '../index.js';\nimport type { GramoBaseConfig } from '../types/index.js';\n\n// ─── Config Loader ────────────────────────────────────────────────────────────\n\nfunction loadEnvFile(cwd: string): Record<string, string> {\n const envPath = path.join(cwd, '.env');\n const env: Record<string, string> = {};\n if (!fs.existsSync(envPath)) return env;\n const lines = fs.readFileSync(envPath, 'utf-8').split('\\n');\n for (const raw of lines) {\n const line = raw.trim();\n if (!line || line.startsWith('#')) continue;\n const eq = line.indexOf('=');\n if (eq === -1) continue;\n const key = line.slice(0, eq).trim();\n const val = line.slice(eq + 1).trim().replace(/^[\"']|[\"']$/g, '');\n env[key] = val;\n }\n return env;\n}\n\nfunction resolveConfig(cwd: string): GramoBaseConfig | null {\n const env = loadEnvFile(cwd);\n\n // Merge with process.env (process.env takes precedence)\n const get = (k: string): string | undefined => process.env[k] || env[k];\n\n // Collect tokens\n const tokens: string[] = [];\n // First try single token\n const single = get('GRAMOBASE_BOT_TOKEN');\n if (single) tokens.push(single);\n // Then try indexed tokens\n let i = 1;\n while (true) {\n const t = get(`GRAMOBASE_BOT_TOKEN_${i}`);\n if (!t) break;\n if (!tokens.includes(t)) tokens.push(t);\n i++;\n }\n\n const channelId = get('GRAMOBASE_CHANNEL_ID');\n if (tokens.length === 0 || !channelId) return null;\n\n const encKey = get('GRAMOBASE_ENCRYPTION_KEY');\n return {\n botToken: tokens.length === 1 ? tokens[0]! : tokens,\n channelId,\n ...(encKey !== undefined ? { encryptionKey: encKey } : {}),\n cacheMaxBytes: 64 * 1024 * 1024,\n cacheTtlMs: 60_000,\n concurrency: 25,\n debug: false,\n };\n}\n\n// ─── JSON Response Helper ─────────────────────────────────────────────────────\n\nfunction jsonRes(res: http.ServerResponse, status: number, body: unknown) {\n const payload = JSON.stringify(body);\n res.writeHead(status, {\n 'Content-Type': 'application/json',\n 'Content-Length': Buffer.byteLength(payload),\n 'Access-Control-Allow-Origin': '*',\n });\n res.end(payload);\n}\n\n// ─── Route Parser ─────────────────────────────────────────────────────────────\n\nfunction parseUrl(rawUrl: string): { pathname: string; query: URLSearchParams } {\n const base = 'http://localhost';\n const url = new URL(rawUrl, base);\n return { pathname: url.pathname, query: url.searchParams };\n}\n\n// ─── Studio Server ────────────────────────────────────────────────────────────\n\nexport async function startStudio(port: number, cwd: string = process.cwd()) {\n const config = resolveConfig(cwd);\n let db: GramoBase | null = null;\n let botInfo: { username: string; firstName: string } | null = null;\n\n if (config) {\n try {\n db = await createClient(config).connect();\n // Fetch bot info from Telegram\n const token = Array.isArray(config.botToken) ? config.botToken[0] : config.botToken;\n try {\n const r = await fetch(`https://api.telegram.org/bot${token}/getMe`);\n const j = await r.json() as any;\n if (j.ok) botInfo = { username: j.result.username, firstName: j.result.first_name };\n } catch (_) {}\n } catch (e) {\n db = null;\n }\n }\n\n // SSE client set\n const sseClients = new Set<http.ServerResponse>();\n\n // Listen to db realtime events and forward to SSE clients\n if (db) {\n const forward = (ev: unknown) => {\n const data = JSON.stringify(ev);\n sseClients.forEach(client => {\n try { client.write(`data: ${data}\\n\\n`); } catch (_) { sseClients.delete(client); }\n });\n };\n db.realtime.onInsert('*' as any, (doc: any) => forward({ type: 'insert', collection: doc._collection, doc }));\n db.realtime.onUpdate('*' as any, (id: any, changes: any, doc: any) => forward({ type: 'update', collection: doc?._collection, id, changes, doc }));\n db.realtime.onDelete('*' as any, (id: any) => forward({ type: 'delete', id }));\n }\n\n const server = http.createServer(async (req, res) => {\n const { pathname, query } = parseUrl(req.url || '/');\n\n // ── Serve UI ───────────────────────────────────────────────\n if (pathname === '/' || pathname === '/index.html') {\n const html = getStudioHTML();\n res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });\n res.end(html);\n return;\n }\n\n // ── SSE events stream ──────────────────────────────────────\n if (pathname === '/api/events') {\n res.writeHead(200, {\n 'Content-Type': 'text/event-stream',\n 'Cache-Control': 'no-cache',\n 'Connection': 'keep-alive',\n 'Access-Control-Allow-Origin': '*',\n });\n res.write(':\\n\\n'); // comment to establish connection\n sseClients.add(res);\n req.on('close', () => sseClients.delete(res));\n return;\n }\n\n // ── Status ─────────────────────────────────────────────────\n if (pathname === '/api/status') {\n if (!db || !config) {\n return jsonRes(res, 503, { error: 'Not connected. Check your .env file.' });\n }\n const cacheStats = db.getCacheStats();\n const workerStats = db.getWorkerStats();\n const colRes = await safeListCollections(db);\n return jsonRes(res, 200, {\n bot: botInfo,\n channelId: config.channelId,\n cache: cacheStats,\n workers: workerStats,\n collections: colRes,\n });\n }\n\n // ── Collections list ───────────────────────────────────────\n if (pathname === '/api/collections') {\n if (!db) return jsonRes(res, 503, { error: 'Not connected' });\n const cols = await safeListCollections(db);\n return jsonRes(res, 200, { collections: cols });\n }\n\n // ── Collection data ────────────────────────────────────────\n const colMatch = pathname.match(/^\\/api\\/collection\\/(.+)$/);\n if (colMatch) {\n if (!db) return jsonRes(res, 503, { error: 'Not connected' });\n const name = decodeURIComponent(colMatch[1] ?? '');\n\n // Guard: only alphanumeric / underscore / hyphen\n if (!/^[a-zA-Z0-9_\\-]+$/.test(name)) {\n return jsonRes(res, 400, { error: 'Invalid collection name' });\n }\n\n const page = Math.max(1, parseInt(query.get('page') || '1', 10));\n const limit = Math.min(100, Math.max(1, parseInt(query.get('limit') || '25', 10)));\n const skip = (page - 1) * limit;\n const sortFieldRaw = query.get('sortField') || '_createdAt';\n const sortDirRaw = parseInt(query.get('sortDir') || '-1', 10);\n\n // Sanitize sort field — only allow safe identifiers\n const sortField = /^[a-zA-Z0-9_.]+$/.test(sortFieldRaw) ? sortFieldRaw : '_createdAt';\n const sortDir = sortDirRaw === 1 ? 1 : -1;\n\n // Build filter from text query param\n const filterText = (query.get('filter') || '').trim();\n let filter: Record<string, unknown> = {};\n if (filterText) {\n // Try key:value syntax first\n const kv = filterText.match(/^([a-zA-Z0-9_.]+):(.+)$/);\n if (kv) {\n const [, k, v] = kv;\n const key = String(k ?? 'unknown');\n const num = Number(v ?? '');\n const filterVal = v === 'true' ? true : v === 'false' ? false : !isNaN(num) ? num : (v ?? '');\n filter = Object.fromEntries([[key, { $eq: filterVal }]]);\n } else {\n // text search via $regex on any string field (best-effort)\n filter = { $or: [{ text: { $regex: filterText } }, { name: { $regex: filterText } }, { title: { $regex: filterText } }] } as any;\n }\n }\n\n try {\n const { z } = await import('zod');\n const col = db.collection(name, { schema: z.record(z.unknown()) });\n const sort: Record<string, 1 | -1> = {};\n sort[sortField] = sortDir;\n const [docs, allDocs] = await Promise.all([\n (col as any).find({ filter, sort, limit, skip }),\n (col as any).count(filter),\n ]);\n\n // Discover columns from first few docs\n const colSet = new Set<string>();\n (docs as any[]).slice(0, 10).forEach((d: any) => Object.keys(d).forEach(k => colSet.add(k)));\n const columns = Array.from(colSet).filter(c => !['_id','_collection','_msgId','_createdAt','_updatedAt'].includes(c));\n\n return jsonRes(res, 200, { docs, total: allDocs, page, limit, columns });\n } catch (e: any) {\n return jsonRes(res, 500, { error: e.message || 'Query failed' });\n }\n }\n\n jsonRes(res, 404, { error: 'Not found' });\n });\n\n server.listen(port, '127.0.0.1', () => {});\n return server;\n}\n\n// ─── Safe collection discovery ────────────────────────────────────────────────\n\nasync function safeListCollections(db: GramoBase): Promise<Array<{ name: string; count: number }>> {\n try {\n // Access internal collection registry to discover known collections\n const registry = (db as any).collections as Map<string, unknown> | undefined;\n if (!registry) return [];\n const result: Array<{ name: string; count: number }> = [];\n for (const [name] of registry) {\n if (name.startsWith('__')) continue; // skip internal collections\n try {\n const col = (registry.get(name) as any);\n const count = await col.count({});\n result.push({ name, count });\n } catch (_) {\n result.push({ name, count: 0 });\n }\n }\n return result;\n } catch (_) {\n return [];\n }\n}\n"]}
1
+ {"version":3,"sources":["../../src/studio/ui.ts","../../src/workers/BotWorkerPool.ts","../../src/cache/HotCache.ts","../../src/storage/TelegramStorage.ts","../../src/wal/WriteAheadLog.ts","../../src/registry/Registry.ts","../../src/orm/Collection.ts","../../src/auth/GramoBaseAuth.ts","../../src/realtime/RealtimeManager.ts","../../src/migrations/MigrationRunner.ts","../../src/index.ts","../../src/studio/server.ts"],"names":["EventEmitter","TelegramBot","PQueue","pRetry","AbortError","LRUCache","createHash","randomBytes","createCipheriv","createDecipheriv","randomUUID","lease","z","existsSync","readFileSync","bcrypt","jwt","UserSchema","path","fs","http"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAIA,IAAM,GAAA,GAAM;AAAA,EAEV,KAAA,EAAU,CAAA,uTAAA,CAAA;AAAA,EACV,KAAA,EAAU,CAAA,sWAAA,CAAA;AAAA,EACV,KAAA,EAAU,CAAA,2OAAA,CAAA;AAAA,EACV,GAAA,EAAU,CAAA,uUAAA,CAAA;AAAA,EACV,MAAA,EAAU,CAAA,8QAAA,CAAA;AAAA,EACV,GAAA,EAAU,CAAA,kNAAA,CAAA;AAAA,EACV,GAAA,EAAU,CAAA,sYAAA,CAAA;AAAA,EACV,IAAA,EAAU,CAAA,6SAAA,CAAA;AAAA,EACV,IAAA,EAAU,CAAA,4TAAA,CAAA;AAAA,EACV,OAAA,EAAU,CAAA,mUAAA,CAAA;AAAA,EACV,KAAA,EAAU,CAAA,4UAAA,CAAA;AAAA,EACV,CAAA,EAAU,CAAA,oOAAA,CAAA;AAAA,EACV,OAAA,EAAU,CAAA,oQAAA,CAAA;AAAA,EACV,KAAA,EAAU,CAAA,sUAAA,CAAA;AAAA,EACV,QAAA,EAAU,CAAA,8MAAA,CAAA;AAAA,EACV,OAAA,EAAU,CAAA,8LAAA,CAAA;AAAA,EACV,QAAA,EAAU,CAAA,6LAAA,CAAA;AAAA,EACV,MAAA,EAAU,CAAA,8LAAA,CAAA;AAAA,EACV,MAAA,EAAU,CAAA,6LAAA,CAAA;AAAA,EACV,MAAA,EAAU,CAAA,4PAAA,CAAA;AAAA,EACV,KAAA,EAAU,CAAA,6LAAA,CAAA;AAAA,EACV,MAAA,EAAU,CAAA,oOAAA;AACZ,CAAA;AAEO,SAAS,aAAA,GAAwB;AACtC,EAAA,OAAO,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;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","file":"server.cjs","sourcesContent":["// gramobase studio — self-contained browser UI\n// Returns the full HTML page as a string — no bundler needed.\n\n// ─── Inline Lucide-style SVG icons ──────────────────────────────────────────\nconst ico = {\n db: `<svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><ellipse cx=\"12\" cy=\"5\" rx=\"9\" ry=\"3\"/><path d=\"M3 5v14a9 3 0 0 0 18 0V5\"/><path d=\"M3 12a9 3 0 0 0 18 0\"/></svg>`,\n gauge: `<svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M12 2a10 10 0 1 0 10 10\"/><path d=\"M12 2v4\"/><path d=\"m4.93 4.93 2.83 2.83\"/><path d=\"M22 12h-4\"/><path d=\"m15 9 3-3\"/><circle cx=\"12\" cy=\"12\" r=\"3\"/></svg>`,\n radio: `<svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M4.9 19.1C1 15.2 1 8.8 4.9 4.9\"/><path d=\"M7.8 16.2c-2.3-2.3-2.3-6.1 0-8.5\"/><circle cx=\"12\" cy=\"12\" r=\"2\"/><path d=\"M16.2 7.8c2.3 2.3 2.3 6.1 0 8.5\"/><path d=\"M19.1 4.9C23 8.8 23 15.2 19.1 19.1\"/></svg>`,\n table: `<svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M3 3h18v18H3z\"/><path d=\"M3 9h18\"/><path d=\"M3 15h18\"/><path d=\"M9 3v18\"/></svg>`,\n bot: `<svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"3\" y=\"11\" width=\"18\" height=\"10\" rx=\"2\"/><circle cx=\"12\" cy=\"5\" r=\"2\"/><path d=\"M12 7v4\"/><line x1=\"8\" y1=\"16\" x2=\"8\" y2=\"16\"/><line x1=\"16\" y1=\"16\" x2=\"16\" y2=\"16\"/></svg>`,\n layers: `<svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polygon points=\"12 2 2 7 12 12 22 7 12 2\"/><polyline points=\"2 17 12 22 22 17\"/><polyline points=\"2 12 12 17 22 12\"/></svg>`,\n zap: `<svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polygon points=\"13 2 3 14 12 14 11 22 21 10 12 10 13 2\"/></svg>`,\n hdd: `<svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><line x1=\"22\" y1=\"12\" x2=\"2\" y2=\"12\"/><path d=\"M5.45 5.11 2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.45-6.89A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11z\"/><line x1=\"6\" y1=\"16\" x2=\"6.01\" y2=\"16\"/><line x1=\"10\" y1=\"16\" x2=\"10.01\" y2=\"16\"/></svg>`,\n hash: `<svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><line x1=\"4\" y1=\"9\" x2=\"20\" y2=\"9\"/><line x1=\"4\" y1=\"15\" x2=\"20\" y2=\"15\"/><line x1=\"10\" y1=\"3\" x2=\"8\" y2=\"21\"/><line x1=\"16\" y1=\"3\" x2=\"14\" y2=\"21\"/></svg>`,\n grid: `<svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"3\" y=\"3\" width=\"7\" height=\"7\"/><rect x=\"14\" y=\"3\" width=\"7\" height=\"7\"/><rect x=\"3\" y=\"14\" width=\"7\" height=\"7\"/><rect x=\"14\" y=\"14\" width=\"7\" height=\"7\"/></svg>`,\n refresh: `<svg width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8\"/><path d=\"M21 3v5h-5\"/><path d=\"M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16\"/><path d=\"M3 21v-5h5\"/></svg>`,\n trash: `<svg width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"3 6 5 6 21 6\"/><path d=\"M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6\"/><path d=\"M10 11v6\"/><path d=\"M14 11v6\"/><path d=\"M9 6V4a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v2\"/></svg>`,\n x: `<svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"/><line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"/></svg>`,\n xCircle: `<svg width=\"36\" height=\"36\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><circle cx=\"12\" cy=\"12\" r=\"10\"/><line x1=\"15\" y1=\"9\" x2=\"9\" y2=\"15\"/><line x1=\"9\" y1=\"9\" x2=\"15\" y2=\"15\"/></svg>`,\n inbox: `<svg width=\"36\" height=\"36\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"22 12 16 12 14 15 10 15 8 12 2 12\"/><path d=\"M5.45 5.11 2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.45-6.89A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11z\"/></svg>`,\n activity: `<svg width=\"36\" height=\"36\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"22 12 18 12 15 21 9 3 6 12 2 12\"/></svg>`,\n sortAsc: `<svg width=\"11\" height=\"11\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"18 15 12 9 6 15\"/></svg>`,\n sortDesc: `<svg width=\"11\" height=\"11\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"6 9 12 15 18 9\"/></svg>`,\n chevrL: `<svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"15 18 9 12 15 6\"/></svg>`,\n chevrR: `<svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"9 18 15 12 9 6\"/></svg>`,\n logoDb: `<svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><ellipse cx=\"12\" cy=\"5\" rx=\"9\" ry=\"3\"/><path d=\"M3 5v14a9 3 0 0 0 18 0V5\"/><path d=\"M3 12a9 3 0 0 0 18 0\"/></svg>`,\n check: `<svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"20 6 9 17 4 12\"/></svg>`,\n close2: `<svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"/><line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"/></svg>`,\n};\n\nexport function getStudioHTML(): string {\n return `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n <title>gramobase studio</title>\n <link rel=\"preconnect\" href=\"https://fonts.googleapis.com\" />\n <link rel=\"preconnect\" href=\"https://fonts.gstatic.com\" crossorigin />\n <link href=\"https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap\" rel=\"stylesheet\" />\n <style>\n *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }\n\n :root {\n --bg: #0a0b0e;\n --bg2: #111318;\n --bg3: #181b22;\n --bg4: #1e2230;\n --border: rgba(255,255,255,0.07);\n --border2: rgba(255,255,255,0.12);\n --accent: #3b82f6;\n --accent2: #60a5fa;\n --accent-glow:rgba(59,130,246,0.25);\n --green: #22c55e;\n --red: #ef4444;\n --yellow: #f59e0b;\n --purple: #a78bfa;\n --teal: #2dd4bf;\n --text: #e2e8f0;\n --text2: #94a3b8;\n --text3: #475569;\n --radius: 10px;\n --font-mono: 'JetBrains Mono', monospace;\n --sidebar-w: 240px;\n }\n\n html, body { height: 100%; background: var(--bg); color: var(--text); font-family: 'Inter', sans-serif; font-size: 14px; }\n\n /* ── LAYOUT ──────────────────────────────────────────────────── */\n #app { display: flex; height: 100vh; overflow: hidden; }\n\n /* ── SIDEBAR ─────────────────────────────────────────────────── */\n #sidebar {\n width: var(--sidebar-w); min-width: var(--sidebar-w);\n background: var(--bg2);\n border-right: 1px solid var(--border);\n display: flex; flex-direction: column;\n overflow: hidden;\n }\n #sidebar-header {\n padding: 18px 16px 14px;\n border-bottom: 1px solid var(--border);\n display: flex; align-items: center; gap: 10px;\n }\n .logo-icon {\n width: 28px; height: 28px; border-radius: 7px;\n background: linear-gradient(135deg, var(--accent), var(--purple));\n display: flex; align-items: center; justify-content: center;\n flex-shrink: 0;\n box-shadow: 0 0 16px var(--accent-glow);\n }\n .logo-icon svg { display: block; }\n .logo-text { font-weight: 700; font-size: 15px; letter-spacing: -0.3px; }\n .logo-badge {\n font-size: 9px; font-weight: 600; padding: 1px 5px; border-radius: 4px;\n background: var(--accent-glow); color: var(--accent2);\n border: 1px solid var(--accent); margin-left: auto;\n }\n #sidebar-nav { flex: 1; overflow-y: auto; padding: 10px 0; }\n .nav-section { padding: 6px 16px 4px; font-size: 10px; font-weight: 600; letter-spacing: 0.8px; text-transform: uppercase; color: var(--text3); }\n .nav-item {\n display: flex; align-items: center; gap: 9px;\n padding: 7px 16px; cursor: pointer; border-radius: 0;\n color: var(--text2); font-size: 13px; transition: all 0.15s;\n border-left: 2px solid transparent;\n }\n .nav-item:hover { background: var(--bg3); color: var(--text); }\n .nav-item.active { background: var(--bg4); color: var(--accent2); border-left-color: var(--accent); }\n .nav-item svg { flex-shrink: 0; opacity: 0.7; }\n .nav-item.active svg, .nav-item:hover svg { opacity: 1; }\n .nav-item-count {\n margin-left: auto; font-size: 10px; padding: 1px 6px; border-radius: 10px;\n background: var(--bg4); color: var(--text3); font-family: var(--font-mono);\n }\n #sidebar-footer {\n padding: 12px 16px;\n border-top: 1px solid var(--border);\n font-size: 11px; color: var(--text3);\n display: flex; align-items: center; gap: 6px;\n }\n .status-dot { width: 6px; height: 6px; border-radius: 50%; background: var(--green); flex-shrink: 0; box-shadow: 0 0 6px var(--green); }\n .status-dot.red { background: var(--red); box-shadow: 0 0 6px var(--red); }\n\n /* ── MAIN ────────────────────────────────────────────────────── */\n #main { flex: 1; display: flex; flex-direction: column; overflow: hidden; }\n\n /* ── TOPBAR ──────────────────────────────────────────────────── */\n #topbar {\n height: 52px; display: flex; align-items: center; gap: 12px;\n padding: 0 20px;\n background: var(--bg2); border-bottom: 1px solid var(--border);\n flex-shrink: 0;\n }\n #topbar-title { font-weight: 600; font-size: 15px; }\n #topbar-sub { font-size: 12px; color: var(--text3); }\n #topbar-actions { margin-left: auto; display: flex; gap: 8px; align-items: center; }\n .btn {\n display: inline-flex; align-items: center; gap: 6px;\n padding: 5px 12px; border-radius: 6px; border: 1px solid var(--border2);\n background: var(--bg3); color: var(--text2); cursor: pointer;\n font-size: 12px; font-family: 'Inter', sans-serif;\n transition: all 0.15s;\n }\n .btn:hover { background: var(--bg4); color: var(--text); border-color: var(--accent); }\n .btn svg { flex-shrink: 0; }\n\n /* ── CONTENT ─────────────────────────────────────────────────── */\n #content { flex: 1; overflow: hidden; position: relative; }\n .panel { display: none; height: 100%; overflow-y: auto; }\n .panel.active { display: block; }\n\n /* ── OVERVIEW PANEL ──────────────────────────────────────────── */\n #panel-overview { padding: 24px; }\n .stats-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 14px; margin-bottom: 28px; }\n .stat-card {\n background: var(--bg2); border: 1px solid var(--border);\n border-radius: var(--radius); padding: 18px;\n transition: border-color 0.2s;\n }\n .stat-card:hover { border-color: var(--border2); }\n .stat-icon-wrap {\n width: 34px; height: 34px; border-radius: 8px;\n display: flex; align-items: center; justify-content: center;\n margin-bottom: 12px; flex-shrink: 0;\n }\n .stat-icon-wrap.blue { background: rgba(59,130,246,0.12); color: var(--accent2); }\n .stat-icon-wrap.purple{ background: rgba(167,139,250,0.12); color: var(--purple); }\n .stat-icon-wrap.green { background: rgba(34,197,94,0.12); color: var(--green); }\n .stat-icon-wrap.teal { background: rgba(45,212,191,0.12); color: var(--teal); }\n .stat-icon-wrap.yellow{ background: rgba(245,158,11,0.12); color: var(--yellow); }\n .stat-label { font-size: 11px; color: var(--text3); font-weight: 500; letter-spacing: 0.5px; text-transform: uppercase; margin-bottom: 6px; }\n .stat-value { font-size: 26px; font-weight: 700; letter-spacing: -0.5px; }\n .stat-sub { font-size: 11px; color: var(--text3); margin-top: 4px; }\n .stat-value.green { color: var(--green); }\n .stat-value.blue { color: var(--accent2); }\n .stat-value.purple { color: var(--purple); }\n .stat-value.yellow { color: var(--yellow); }\n .stat-value.teal { color: var(--teal); }\n\n .section-title { font-size: 13px; font-weight: 600; color: var(--text2); margin-bottom: 12px; display: flex; align-items: center; gap: 8px; }\n .section-title::after { content: ''; flex: 1; height: 1px; background: var(--border); }\n\n /* ── BOT STATUS ──────────────────────────────────────────────── */\n .info-card {\n background: var(--bg2); border: 1px solid var(--border);\n border-radius: var(--radius); padding: 16px; margin-bottom: 14px;\n }\n .info-row { display: flex; align-items: center; gap: 10px; padding: 7px 0; border-bottom: 1px solid var(--border); }\n .info-row:last-child { border-bottom: none; }\n .info-key { font-size: 12px; color: var(--text3); width: 130px; flex-shrink: 0; }\n .info-val { font-size: 13px; font-family: var(--font-mono); color: var(--text); }\n .badge { display: inline-flex; align-items: center; gap: 4px; padding: 2px 8px; border-radius: 20px; font-size: 11px; font-weight: 500; }\n .badge.green { background: rgba(34,197,94,0.12); color: var(--green); border: 1px solid rgba(34,197,94,0.2); }\n .badge.blue { background: rgba(59,130,246,0.12); color: var(--accent2);border: 1px solid rgba(59,130,246,0.2); }\n .badge.online-dot::before { content: ''; display: inline-block; width: 5px; height: 5px; border-radius: 50%; background: var(--green); }\n\n /* worker pool bars */\n .worker-bars { display: flex; flex-direction: column; gap: 8px; }\n .worker-row { display: flex; align-items: center; gap: 10px; }\n .worker-label { font-size: 11px; color: var(--text3); width: 60px; flex-shrink: 0; font-family: var(--font-mono); }\n .progress-bar { flex: 1; height: 6px; background: var(--bg4); border-radius: 3px; overflow: hidden; }\n .progress-fill { height: 100%; border-radius: 3px; background: linear-gradient(90deg, var(--accent), var(--purple)); transition: width 0.4s; }\n .worker-stat { font-size: 11px; color: var(--text3); width: 60px; text-align: right; font-family: var(--font-mono); }\n\n /* ── COLLECTION PANEL ────────────────────────────────────────── */\n #panel-collection { display: none; flex-direction: column; height: 100%; }\n #panel-collection.active { display: flex; }\n\n #collection-toolbar {\n padding: 12px 20px; border-bottom: 1px solid var(--border);\n display: flex; align-items: center; gap: 10px; flex-shrink: 0;\n background: var(--bg2);\n }\n .filter-wrap {\n display: flex; align-items: center; gap: 6px;\n flex: 1; max-width: 320px;\n background: var(--bg3); border: 1px solid var(--border2);\n border-radius: 6px; padding: 0 10px;\n transition: border-color 0.15s;\n }\n .filter-wrap:focus-within { border-color: var(--accent); }\n .filter-wrap svg { color: var(--text3); flex-shrink: 0; }\n #filter-input {\n flex: 1; border: none; background: transparent;\n padding: 6px 0;\n color: var(--text); font-size: 13px; font-family: 'Inter', sans-serif;\n outline: none;\n }\n #filter-input::placeholder { color: var(--text3); }\n select.sort-select {\n background: var(--bg3); border: 1px solid var(--border2);\n border-radius: 6px; padding: 6px 10px;\n color: var(--text); font-size: 13px; font-family: 'Inter', sans-serif;\n outline: none; cursor: pointer;\n }\n\n /* ── TABLE ───────────────────────────────────────────────────── */\n #table-wrap { flex: 1; overflow: auto; }\n table { width: 100%; border-collapse: collapse; }\n thead { position: sticky; top: 0; z-index: 2; }\n th {\n background: var(--bg2); color: var(--text3);\n font-size: 11px; font-weight: 600; letter-spacing: 0.5px; text-transform: uppercase;\n padding: 10px 16px; text-align: left;\n border-bottom: 1px solid var(--border);\n cursor: pointer; white-space: nowrap;\n user-select: none;\n }\n th .th-inner { display: flex; align-items: center; gap: 4px; }\n th:hover { color: var(--text); }\n th.sorted { color: var(--accent2); }\n td {\n padding: 9px 16px; border-bottom: 1px solid var(--border);\n font-size: 13px; max-width: 250px;\n white-space: nowrap; overflow: hidden; text-overflow: ellipsis;\n vertical-align: middle;\n }\n tr { cursor: pointer; transition: background 0.1s; }\n tr:hover td { background: var(--bg3); }\n tr.selected td { background: rgba(59,130,246,0.08); }\n .cell-id { font-family: var(--font-mono); font-size: 11px; color: var(--text3); }\n .cell-bool { display: inline-flex; align-items: center; gap: 4px; font-size: 11px; font-weight: 500; }\n .cell-bool.t { color: var(--green); }\n .cell-bool.f { color: var(--red); }\n .cell-num { color: var(--purple); font-family: var(--font-mono); font-size: 12px; }\n .cell-date { color: var(--teal); font-size: 11px; }\n .cell-null { color: var(--text3); font-style: italic; font-size: 11px; }\n .cell-obj { color: var(--text3); font-size: 11px; font-family: var(--font-mono); }\n\n /* ── PAGINATION ──────────────────────────────────────────────── */\n #pagination {\n padding: 10px 20px; border-top: 1px solid var(--border);\n display: flex; align-items: center; gap: 10px;\n background: var(--bg2); flex-shrink: 0;\n }\n #pagination-info { font-size: 12px; color: var(--text3); }\n #pagination-controls { margin-left: auto; display: flex; gap: 6px; }\n .page-btn {\n width: 28px; height: 28px; border-radius: 5px;\n background: var(--bg3); border: 1px solid var(--border);\n color: var(--text2); cursor: pointer; font-size: 12px;\n display: flex; align-items: center; justify-content: center;\n transition: all 0.15s;\n }\n .page-btn:hover:not(:disabled) { background: var(--bg4); border-color: var(--accent); color: var(--accent2); }\n .page-btn:disabled { opacity: 0.35; cursor: not-allowed; }\n .page-btn.active { background: var(--accent); border-color: var(--accent); color: #fff; }\n\n /* ── REALTIME PANEL ──────────────────────────────────────────── */\n #panel-realtime { display: none; flex-direction: column; height: 100%; }\n #panel-realtime.active { display: flex; }\n #events-toolbar {\n padding: 12px 20px; border-bottom: 1px solid var(--border);\n display: flex; align-items: center; gap: 10px;\n background: var(--bg2); flex-shrink: 0;\n }\n .event-indicator { display: flex; align-items: center; gap: 6px; font-size: 12px; color: var(--text3); }\n .pulse { width: 7px; height: 7px; border-radius: 50%; background: var(--green); animation: pulse 1.5s infinite; }\n @keyframes pulse { 0%,100% { opacity: 1; } 50% { opacity: 0.3; } }\n #events-log {\n flex: 1; overflow-y: auto; padding: 12px 20px;\n display: flex; flex-direction: column; gap: 6px;\n }\n .event-item {\n display: flex; align-items: flex-start; gap: 12px;\n padding: 10px 14px; border-radius: 8px;\n background: var(--bg2); border: 1px solid var(--border);\n animation: fadeIn 0.3s ease;\n }\n @keyframes fadeIn { from { opacity:0; transform: translateY(-4px); } to { opacity:1; transform: translateY(0); } }\n .event-type {\n font-size: 10px; font-weight: 700; padding: 2px 7px; border-radius: 4px;\n text-transform: uppercase; letter-spacing: 0.5px; flex-shrink: 0; margin-top: 1px;\n }\n .event-type.insert { background: rgba(34,197,94,0.15); color: var(--green); }\n .event-type.update { background: rgba(245,158,11,0.15); color: var(--yellow); }\n .event-type.delete { background: rgba(239,68,68,0.15); color: var(--red); }\n .event-type.system { background: rgba(167,139,250,0.15);color: var(--purple); }\n .event-body { flex: 1; min-width: 0; }\n .event-title { font-size: 13px; font-weight: 500; margin-bottom: 2px; }\n .event-detail{ font-size: 11px; color: var(--text3); font-family: var(--font-mono); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\n .event-time { font-size: 10px; color: var(--text3); flex-shrink: 0; font-family: var(--font-mono); }\n\n /* ── INSPECTOR MODAL ─────────────────────────────────────────── */\n #inspector-overlay {\n display: none; position: fixed; inset: 0; z-index: 100;\n background: rgba(0,0,0,0.7); backdrop-filter: blur(4px);\n align-items: flex-start; justify-content: flex-end;\n }\n #inspector-overlay.open { display: flex; }\n #inspector-panel {\n width: min(560px, 90vw); height: 100vh; overflow-y: auto;\n background: var(--bg2); border-left: 1px solid var(--border);\n padding: 20px; display: flex; flex-direction: column; gap: 14px;\n animation: slideIn 0.25s ease;\n }\n @keyframes slideIn { from { transform: translateX(40px); opacity: 0; } to { transform: translateX(0); opacity: 1; } }\n #inspector-header { display: flex; align-items: center; justify-content: space-between; }\n #inspector-title { font-size: 15px; font-weight: 600; }\n #inspector-close {\n width: 28px; height: 28px; border-radius: 6px;\n background: var(--bg3); border: 1px solid var(--border);\n cursor: pointer; color: var(--text3);\n display: flex; align-items: center; justify-content: center;\n transition: all 0.15s;\n }\n #inspector-close:hover { color: var(--red); border-color: var(--red); background: rgba(239,68,68,0.1); }\n #inspector-body { flex: 1; }\n #inspector-json {\n background: var(--bg); border: 1px solid var(--border);\n border-radius: 8px; padding: 16px;\n font-family: var(--font-mono); font-size: 12px; line-height: 1.7;\n white-space: pre-wrap; word-break: break-all; overflow-x: auto;\n color: var(--text);\n }\n .j-key { color: #93c5fd; }\n .j-str { color: #86efac; }\n .j-num { color: #c4b5fd; }\n .j-bool { color: #f97316; }\n .j-null { color: var(--text3); }\n\n /* ── EMPTY / LOADING ─────────────────────────────────────────── */\n .loading-spinner {\n width: 30px; height: 30px; border: 3px solid var(--border2);\n border-top-color: var(--accent); border-radius: 50%;\n animation: spin 0.7s linear infinite; margin: 60px auto;\n }\n @keyframes spin { to { transform: rotate(360deg); } }\n .empty-state { text-align: center; padding: 60px 20px; color: var(--text3); }\n .empty-state .empty-icon { display: flex; justify-content: center; margin-bottom: 14px; opacity: 0.4; }\n .empty-state p { font-size: 14px; margin-bottom: 6px; color: var(--text2); }\n .empty-state small { font-size: 12px; }\n\n /* ── SCROLLBAR ───────────────────────────────────────────────── */\n ::-webkit-scrollbar { width: 5px; height: 5px; }\n ::-webkit-scrollbar-track { background: transparent; }\n ::-webkit-scrollbar-thumb { background: var(--bg4); border-radius: 10px; }\n ::-webkit-scrollbar-thumb:hover { background: var(--text3); }\n\n /* ── TOAST ───────────────────────────────────────────────────── */\n #toast {\n position: fixed; bottom: 20px; right: 20px;\n background: var(--bg3); border: 1px solid var(--border2);\n border-radius: 8px; padding: 10px 16px; font-size: 13px;\n display: none; z-index: 200; animation: toastIn 0.2s ease;\n }\n @keyframes toastIn { from { opacity:0; transform: translateY(10px); } to { opacity:1; transform: translateY(0); } }\n\n /* ── SEARCH ICON ─────────────────────────────────────────────── */\n .search-icon { color: var(--text3); pointer-events: none; }\n </style>\n</head>\n<body>\n<div id=\"app\">\n\n <!-- ── SIDEBAR ──────────────────────────────────────────────────── -->\n <nav id=\"sidebar\">\n <div id=\"sidebar-header\">\n <div class=\"logo-icon\">${ico.logoDb}</div>\n <span class=\"logo-text\">gramobase</span>\n <span class=\"logo-badge\">STUDIO</span>\n </div>\n <div id=\"sidebar-nav\">\n <div class=\"nav-section\">Dashboard</div>\n <div class=\"nav-item active\" data-panel=\"overview\" onclick=\"switchPanel('overview')\">\n ${ico.gauge} Overview\n </div>\n <div class=\"nav-item\" data-panel=\"realtime\" onclick=\"switchPanel('realtime')\">\n ${ico.radio} Realtime Feed\n </div>\n\n <div class=\"nav-section\" style=\"margin-top:10px\">Collections</div>\n <div id=\"collection-list\">\n <div style=\"padding:12px 16px;font-size:12px;color:var(--text3)\">Loading...</div>\n </div>\n </div>\n <div id=\"sidebar-footer\">\n <span class=\"status-dot\" id=\"conn-dot\"></span>\n <span id=\"conn-label\">Connecting...</span>\n </div>\n </nav>\n\n <!-- ── MAIN ─────────────────────────────────────────────────────── -->\n <div id=\"main\">\n <div id=\"topbar\">\n <span id=\"topbar-title\">Overview</span>\n <span id=\"topbar-sub\"></span>\n <div id=\"topbar-actions\">\n <button class=\"btn\" onclick=\"refreshCurrent()\">${ico.refresh} Refresh</button>\n </div>\n </div>\n\n <div id=\"content\">\n\n <!-- Overview Panel -->\n <div id=\"panel-overview\" class=\"panel active\">\n <div id=\"overview-inner\" style=\"padding:24px\">\n <div style=\"text-align:center;padding:60px 0\"><div class=\"loading-spinner\"></div></div>\n </div>\n </div>\n\n <!-- Collection Panel -->\n <div id=\"panel-collection\" class=\"panel\">\n <div id=\"collection-toolbar\">\n <div class=\"filter-wrap\">\n <svg class=\"search-icon\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><circle cx=\"11\" cy=\"11\" r=\"8\"/><line x1=\"21\" y1=\"21\" x2=\"16.65\" y2=\"16.65\"/></svg>\n <input id=\"filter-input\" type=\"text\" placeholder=\"Filter: field:value or text\" oninput=\"debounceFilter()\" />\n </div>\n <select class=\"sort-select\" id=\"sort-field\" onchange=\"loadCollection()\">\n <option value=\"\">Sort by...</option>\n </select>\n <select class=\"sort-select\" id=\"sort-dir\" onchange=\"loadCollection()\" style=\"width:90px\">\n <option value=\"-1\">DESC</option>\n <option value=\"1\">ASC</option>\n </select>\n <span style=\"font-size:12px;color:var(--text3);margin-left:4px\" id=\"coll-count\"></span>\n </div>\n <div id=\"table-wrap\">\n <div style=\"text-align:center;padding:60px 0\"><div class=\"loading-spinner\"></div></div>\n </div>\n <div id=\"pagination\">\n <span id=\"pagination-info\"></span>\n <div id=\"pagination-controls\"></div>\n </div>\n </div>\n\n <!-- Realtime Panel -->\n <div id=\"panel-realtime\" class=\"panel\">\n <div id=\"events-toolbar\">\n <div class=\"event-indicator\"><div class=\"pulse\"></div> Live events</div>\n <button class=\"btn\" style=\"margin-left:auto\" onclick=\"clearEvents()\">${ico.trash} Clear</button>\n </div>\n <div id=\"events-log\">\n <div class=\"empty-state\" id=\"events-empty\">\n <div class=\"empty-icon\">${ico.activity}</div>\n <p>Waiting for events...</p>\n <small>Insert, update, or delete documents to see events here.</small>\n </div>\n </div>\n </div>\n\n </div>\n </div>\n</div>\n\n<!-- Inspector Drawer -->\n<div id=\"inspector-overlay\" onclick=\"closeInspector(event)\">\n <div id=\"inspector-panel\">\n <div id=\"inspector-header\">\n <span id=\"inspector-title\">Document</span>\n <div id=\"inspector-close\" onclick=\"closeInspector()\">${ico.x}</div>\n </div>\n <div id=\"inspector-body\">\n <pre id=\"inspector-json\"></pre>\n </div>\n </div>\n</div>\n\n<!-- Toast -->\n<div id=\"toast\"></div>\n\n<script>\n/* ─── Icon snippets for dynamic HTML ─────────────────────── */\nconst SVG = {\n bot: \\`${ico.bot}\\`,\n layers: \\`${ico.layers}\\`,\n zap: \\`${ico.zap}\\`,\n hdd: \\`${ico.hdd}\\`,\n hash: \\`${ico.hash}\\`,\n grid: \\`${ico.grid}\\`,\n table: \\`${ico.table}\\`,\n xCirc: \\`${ico.xCircle}\\`,\n inbox: \\`${ico.inbox}\\`,\n asc: \\`${ico.sortAsc}\\`,\n desc: \\`${ico.sortDesc}\\`,\n chevrL: \\`${ico.chevrL}\\`,\n chevrR: \\`${ico.chevrR}\\`,\n check: \\`${ico.check}\\`,\n close2: \\`${ico.close2}\\`,\n};\n\n/* ─── State ───────────────────────────────────────────────── */\nlet currentPanel = 'overview';\nlet currentCollection = null;\nlet currentPage = 1;\nlet pageSize = 25;\nlet totalDocs = 0;\nlet sortField = '';\nlet sortDir = -1;\nlet filterText = '';\nlet filterTimer = null;\nlet columns = [];\nlet eventSource = null;\nlet eventCount = 0;\n\n/* ─── Init ────────────────────────────────────────────────── */\nasync function init() {\n await loadStatus();\n await loadCollections();\n connectSSE();\n}\n\n/* ─── Status / Overview ───────────────────────────────────── */\nasync function loadStatus() {\n try {\n const data = await api('/api/status');\n setConnected(true, '@' + (data.bot?.username || 'unknown'));\n renderOverview(data);\n } catch (e) {\n setConnected(false, 'Connection failed');\n renderOverviewError(e.message);\n }\n}\n\nfunction renderOverview(data) {\n const cache = data.cache || {};\n const workers = data.workers || {};\n const tokens = workers.tokens || [];\n\n const hitPct = cache.hits + cache.misses > 0\n ? Math.round((cache.hits / (cache.hits + cache.misses)) * 100)\n : 0;\n const cacheUsedMb = ((cache.bytes || 0) / 1024 / 1024).toFixed(1);\n const cacheMaxMb = ((cache.maxBytes || 1) / 1024 / 1024).toFixed(0);\n const hitColor = hitPct > 70 ? 'green' : hitPct > 40 ? 'yellow' : 'blue';\n\n document.getElementById('overview-inner').innerHTML = \\`\n <div class=\"stats-grid\">\n <div class=\"stat-card\">\n <div class=\"stat-icon-wrap blue\">\\${SVG.bot}</div>\n <div class=\"stat-label\">Bot</div>\n <div class=\"stat-value blue\" style=\"font-size:18px\">@\\${escH(data.bot?.username || '—')}</div>\n <div class=\"stat-sub\">\\${escH(data.bot?.firstName || '')}</div>\n </div>\n <div class=\"stat-card\">\n <div class=\"stat-icon-wrap purple\">\\${SVG.layers}</div>\n <div class=\"stat-label\">Token Pool</div>\n <div class=\"stat-value purple\">\\${tokens.length || 1}</div>\n <div class=\"stat-sub\">\\${(tokens.length||1) * 30} req/s capacity</div>\n </div>\n <div class=\"stat-card\">\n <div class=\"stat-icon-wrap \\${hitColor}\">\\${SVG.zap}</div>\n <div class=\"stat-label\">Cache Hit Rate</div>\n <div class=\"stat-value \\${hitColor}\">\\${hitPct}%</div>\n <div class=\"stat-sub\">\\${cache.hits||0} hits / \\${cache.misses||0} misses</div>\n </div>\n <div class=\"stat-card\">\n <div class=\"stat-icon-wrap teal\">\\${SVG.hdd}</div>\n <div class=\"stat-label\">Cache Usage</div>\n <div class=\"stat-value teal\">\\${cacheUsedMb} MB</div>\n <div class=\"stat-sub\">of \\${cacheMaxMb} MB limit</div>\n </div>\n <div class=\"stat-card\">\n <div class=\"stat-icon-wrap blue\">\\${SVG.hash}</div>\n <div class=\"stat-label\">Channel</div>\n <div class=\"stat-value blue\" style=\"font-size:15px;font-family:var(--font-mono)\">\\${escH(data.channelId || '—')}</div>\n <div class=\"stat-sub\">Primary channel</div>\n </div>\n <div class=\"stat-card\">\n <div class=\"stat-icon-wrap green\">\\${SVG.grid}</div>\n <div class=\"stat-label\">Collections</div>\n <div class=\"stat-value green\">\\${(data.collections||[]).length}</div>\n <div class=\"stat-sub\">discovered</div>\n </div>\n </div>\n\n <div class=\"section-title\">Bot Connection</div>\n <div class=\"info-card\">\n <div class=\"info-row\"><span class=\"info-key\">Status</span><span class=\"info-val\"><span class=\"badge green online-dot\"> Online</span></span></div>\n <div class=\"info-row\"><span class=\"info-key\">Username</span><span class=\"info-val\">@\\${escH(data.bot?.username||'—')}</span></div>\n <div class=\"info-row\"><span class=\"info-key\">First Name</span><span class=\"info-val\">\\${escH(data.bot?.firstName||'—')}</span></div>\n <div class=\"info-row\"><span class=\"info-key\">Channel ID</span><span class=\"info-val\">\\${escH(data.channelId||'—')}</span></div>\n <div class=\"info-row\"><span class=\"info-key\">Token Count</span><span class=\"info-val\"><span class=\"badge blue\">\\${tokens.length||1} token\\${(tokens.length||1)>1?'s':''}</span></span></div>\n </div>\n\n \\${tokens.length > 0 ? \\`\n <div class=\"section-title\" style=\"margin-top:20px\">Worker Pool</div>\n <div class=\"info-card\">\n <div class=\"worker-bars\">\n \\${tokens.map((t,i) => \\`\n <div class=\"worker-row\">\n <span class=\"worker-label\">Token \\${i+1}</span>\n <div class=\"progress-bar\"><div class=\"progress-fill\" style=\"width:\\${Math.min(100,(t.activeRequests||0)/25*100)}%\"></div></div>\n <span class=\"worker-stat\">\\${t.activeRequests||0}/25</span>\n </div>\n \\`).join('')}\n </div>\n </div>\n \\` : ''}\n \\`;\n}\n\nfunction renderOverviewError(msg) {\n document.getElementById('overview-inner').innerHTML = \\`\n <div class=\"empty-state\">\n <div class=\"empty-icon\">\\${SVG.xCirc}</div>\n <p>Could not connect to gramobase</p>\n <small>\\${escH(msg)}</small>\n </div>\n \\`;\n}\n\n/* ─── Collections ─────────────────────────────────────────── */\nasync function loadCollections() {\n try {\n const data = await api('/api/collections');\n const list = data.collections || [];\n const nav = document.getElementById('collection-list');\n if (list.length === 0) {\n nav.innerHTML = '<div style=\"padding:10px 16px;font-size:12px;color:var(--text3)\">No collections yet</div>';\n return;\n }\n nav.innerHTML = list.map(c => \\`\n <div class=\"nav-item\" data-panel=\"collection\" data-col=\"\\${escH(c.name)}\" onclick=\"openCollection('\\${escH(c.name)}')\">\n \\${SVG.table}\n <span style=\"overflow:hidden;text-overflow:ellipsis;white-space:nowrap\">\\${escH(c.name)}</span>\n <span class=\"nav-item-count\">\\${c.count||'?'}</span>\n </div>\n \\`).join('');\n } catch(e) {}\n}\n\nasync function openCollection(name) {\n currentCollection = name;\n currentPage = 1;\n filterText = '';\n sortField = '';\n document.getElementById('filter-input').value = '';\n document.getElementById('sort-field').innerHTML = '<option value=\"\">Sort by...</option>';\n switchPanel('collection');\n document.getElementById('topbar-title').textContent = name;\n document.getElementById('topbar-sub').textContent = 'collection';\n await loadCollection();\n}\n\nasync function loadCollection() {\n if (!currentCollection) return;\n sortField = document.getElementById('sort-field').value;\n sortDir = parseInt(document.getElementById('sort-dir').value, 10);\n const params = new URLSearchParams({\n page: currentPage, limit: pageSize, filter: filterText, sortField, sortDir,\n });\n setTableLoading();\n try {\n const data = await api('/api/collection/' + encodeURIComponent(currentCollection) + '?' + params);\n totalDocs = data.total || 0;\n columns = data.columns || [];\n renderTable(data.docs || [], data.columns || []);\n renderPagination();\n updateSortSelect(data.columns || []);\n document.getElementById('coll-count').textContent = totalDocs + ' docs';\n document.querySelectorAll('.nav-item[data-col]').forEach(item => {\n if (item.dataset.col === currentCollection) {\n const cnt = item.querySelector('.nav-item-count');\n if (cnt) cnt.textContent = totalDocs;\n }\n });\n } catch(e) {\n document.getElementById('table-wrap').innerHTML = \\`<div class=\"empty-state\"><div class=\"empty-icon\">\\${SVG.xCirc}</div><p>\\${escH(e.message)}</p></div>\\`;\n }\n}\n\nfunction setTableLoading() {\n document.getElementById('table-wrap').innerHTML = '<div style=\"text-align:center;padding:60px 0\"><div class=\"loading-spinner\"></div></div>';\n}\n\nfunction updateSortSelect(cols) {\n const sel = document.getElementById('sort-field');\n const cur = sel.value;\n sel.innerHTML = '<option value=\"\">Sort by...</option>' +\n cols.map(c => \\`<option value=\"\\${escH(c)}\" \\${c===cur?'selected':''}>\\${escH(c)}</option>\\`).join('');\n}\n\nfunction renderTable(docs, cols) {\n if (docs.length === 0) {\n document.getElementById('table-wrap').innerHTML = \\`\n <div class=\"empty-state\">\n <div class=\"empty-icon\">\\${SVG.inbox}</div>\n <p>No documents found</p>\n <small>Try adjusting your filter or add some data.</small>\n </div>\\`;\n return;\n }\n const allCols = ['_id', ...cols.filter(c => !c.startsWith('_') && c !== '_id'), '_createdAt', '_updatedAt'];\n const sortIcon = (c) => sortField === c ? (sortDir === -1 ? SVG.desc : SVG.asc) : '';\n const html = \\`<table>\n <thead><tr>\n \\${allCols.map(c => \\`<th class=\"\\${sortField===c?'sorted':''}\" onclick=\"sortBy('\\${escH(c)}')\"><div class=\"th-inner\">\\${escH(c)}\\${sortIcon(c)}</div></th>\\`).join('')}\n </tr></thead>\n <tbody>\n \\${docs.map((doc, i) => \\`\n <tr onclick=\"inspectDoc(\\${i})\" data-idx=\"\\${i}\">\n \\${allCols.map(c => \\`<td>\\${renderCell(doc[c], c)}</td>\\`).join('')}\n </tr>\\`).join('')}\n </tbody>\n </table>\\`;\n document.getElementById('table-wrap').innerHTML = html;\n window._currentDocs = docs;\n}\n\nfunction renderCell(val, col) {\n if (val === undefined || val === null) return '<span class=\"cell-null\">—</span>';\n if (col === '_id' || col === '_collection') return \\`<span class=\"cell-id\">\\${escH(String(val).slice(0,12))}…</span>\\`;\n if (col === '_createdAt' || col === '_updatedAt') return \\`<span class=\"cell-date\">\\${escH(fmtDate(val))}</span>\\`;\n if (typeof val === 'boolean') return val\n ? \\`<span class=\"cell-bool t\">\\${SVG.check} true</span>\\`\n : \\`<span class=\"cell-bool f\">\\${SVG.close2} false</span>\\`;\n if (typeof val === 'number') return \\`<span class=\"cell-num\">\\${escH(String(val))}</span>\\`;\n if (typeof val === 'object') return '<span class=\"cell-obj\">{…}</span>';\n const s = String(val);\n return \\`<span title=\"\\${escH(s)}\">\\${escH(s.length > 40 ? s.slice(0,40)+'…' : s)}</span>\\`;\n}\n\nfunction sortBy(col) {\n if (sortField === col) { sortDir = sortDir === -1 ? 1 : -1; }\n else { sortField = col; sortDir = -1; }\n document.getElementById('sort-field').value = sortField;\n document.getElementById('sort-dir').value = sortDir;\n loadCollection();\n}\n\nfunction inspectDoc(idx) {\n const doc = window._currentDocs?.[idx];\n if (!doc) return;\n document.getElementById('inspector-title').textContent = 'Document: ' + (doc._id?.slice(0,8)||'') + '…';\n document.getElementById('inspector-json').innerHTML = syntaxHL(JSON.stringify(doc, null, 2));\n document.getElementById('inspector-overlay').classList.add('open');\n document.querySelectorAll('tr').forEach(r => r.classList.toggle('selected', r.dataset.idx == idx));\n}\n\nfunction closeInspector(e) {\n if (e && e.target !== document.getElementById('inspector-overlay')) return;\n document.getElementById('inspector-overlay').classList.remove('open');\n document.querySelectorAll('tr.selected').forEach(r => r.classList.remove('selected'));\n}\n\n/* ─── Pagination ──────────────────────────────────────────── */\nfunction renderPagination() {\n const totalPages = Math.max(1, Math.ceil(totalDocs / pageSize));\n const start = (currentPage - 1) * pageSize + 1;\n const end = Math.min(currentPage * pageSize, totalDocs);\n document.getElementById('pagination-info').textContent = totalDocs > 0 ? \\`\\${start}–\\${end} of \\${totalDocs}\\` : '0 results';\n\n let btns = '';\n btns += \\`<button class=\"page-btn\" onclick=\"goPage(\\${currentPage-1})\" \\${currentPage<=1?'disabled':''}>\\${SVG.chevrL}</button>\\`;\n const pages = pageRange(currentPage, totalPages);\n pages.forEach(p => {\n if (p === '…') btns += \\`<span style=\"color:var(--text3);padding:0 4px;line-height:28px\">…</span>\\`;\n else btns += \\`<button class=\"page-btn \\${p===currentPage?'active':''}\" onclick=\"goPage(\\${p})\">\\${p}</button>\\`;\n });\n btns += \\`<button class=\"page-btn\" onclick=\"goPage(\\${currentPage+1})\" \\${currentPage>=totalPages?'disabled':''}>\\${SVG.chevrR}</button>\\`;\n document.getElementById('pagination-controls').innerHTML = btns;\n}\n\nfunction pageRange(cur, total) {\n if (total <= 7) return Array.from({length:total},(_,i)=>i+1);\n const pages = [1];\n if (cur > 3) pages.push('…');\n for (let i = Math.max(2,cur-1); i <= Math.min(total-1,cur+1); i++) pages.push(i);\n if (cur < total-2) pages.push('…');\n pages.push(total);\n return pages;\n}\n\nfunction goPage(p) {\n const totalPages = Math.ceil(totalDocs / pageSize);\n if (p < 1 || p > totalPages) return;\n currentPage = p;\n loadCollection();\n}\n\n/* ─── Filter ──────────────────────────────────────────────── */\nfunction debounceFilter() {\n clearTimeout(filterTimer);\n filterTimer = setTimeout(() => {\n filterText = document.getElementById('filter-input').value;\n currentPage = 1;\n loadCollection();\n }, 400);\n}\n\n/* ─── Realtime SSE ────────────────────────────────────────── */\nfunction connectSSE() {\n if (eventSource) eventSource.close();\n eventSource = new EventSource('/api/events');\n eventSource.onmessage = (e) => {\n try { addEvent(JSON.parse(e.data)); } catch(_) {}\n };\n eventSource.onerror = () => {};\n}\n\nfunction addEvent(ev) {\n eventCount++;\n const log = document.getElementById('events-log');\n const empty = document.getElementById('events-empty');\n if (empty) empty.remove();\n\n const typeMap = { insert:'insert', update:'update', delete:'delete', 'worker:rotate':'system', 'wal:flush':'system' };\n const type = typeMap[ev.type] || 'system';\n const title = ev.type === 'insert' ? \\`New doc in \\${ev.collection}\\`\n : ev.type === 'update' ? \\`Updated \\${ev.id?.slice(0,8)}… in \\${ev.collection}\\`\n : ev.type === 'delete' ? \\`Deleted \\${ev.id?.slice(0,8)}… from \\${ev.collection}\\`\n : ev.type === 'worker:rotate' ? 'Worker rotated token #' + ev.tokenIndex\n : ev.type === 'wal:flush' ? \\`WAL flushed \\${ev.entries} entries\\` : ev.type;\n const detail = ev.doc ? JSON.stringify(ev.doc).slice(0,80) : ev.changes ? JSON.stringify(ev.changes).slice(0,80) : '';\n\n const item = document.createElement('div');\n item.className = 'event-item';\n item.innerHTML = \\`\n <div class=\"event-type \\${type}\">\\${ev.type}</div>\n <div class=\"event-body\">\n <div class=\"event-title\">\\${escH(title)}</div>\n \\${detail ? \\`<div class=\"event-detail\">\\${escH(detail)}</div>\\` : ''}\n </div>\n <div class=\"event-time\">\\${fmtTime(new Date())}</div>\n \\`;\n log.insertBefore(item, log.firstChild);\n while (log.children.length > 200) log.removeChild(log.lastChild);\n if ((ev.collection === currentCollection) && currentPanel === 'collection') loadCollection();\n}\n\nfunction clearEvents() {\n document.getElementById('events-log').innerHTML = \\`\n <div class=\"empty-state\" id=\"events-empty\">\n <div class=\"empty-icon\">\\${SVG.xCirc}</div>\n <p>Waiting for events...</p>\n <small>Insert, update, or delete documents to see events here.</small>\n </div>\\`;\n eventCount = 0;\n}\n\n/* ─── Navigation ──────────────────────────────────────────── */\nfunction switchPanel(name) {\n currentPanel = name;\n document.querySelectorAll('.panel').forEach(p => p.classList.remove('active'));\n document.getElementById('panel-' + name).classList.add('active');\n document.querySelectorAll('.nav-item').forEach(i => {\n i.classList.toggle('active', i.dataset.panel === name && !i.dataset.col);\n });\n if (name === 'collection') {\n document.querySelectorAll('.nav-item[data-col]').forEach(i => {\n i.classList.toggle('active', i.dataset.col === currentCollection);\n });\n }\n if (name === 'overview') {\n document.getElementById('topbar-title').textContent = 'Overview';\n document.getElementById('topbar-sub').textContent = '';\n loadStatus(); loadCollections();\n }\n if (name === 'realtime') {\n document.getElementById('topbar-title').textContent = 'Realtime Feed';\n document.getElementById('topbar-sub').textContent = 'live events';\n }\n}\n\nfunction refreshCurrent() {\n if (currentPanel === 'overview') { loadStatus(); loadCollections(); }\n else if (currentPanel === 'collection') loadCollection();\n}\n\n/* ─── Utilities ───────────────────────────────────────────── */\nfunction setConnected(ok, label) {\n document.getElementById('conn-dot').className = 'status-dot' + (ok ? '' : ' red');\n document.getElementById('conn-label').textContent = label;\n}\n\nasync function api(url) {\n const r = await fetch(url);\n if (!r.ok) {\n const j = await r.json().catch(() => ({}));\n throw new Error(j.error || r.statusText);\n }\n return r.json();\n}\n\nfunction escH(s) {\n return String(s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\"/g,'&quot;');\n}\n\nfunction fmtDate(v) {\n if (!v) return '';\n try { return new Date(v).toLocaleString(); } catch(_) { return String(v); }\n}\n\nfunction fmtTime(d) { return d.toTimeString().slice(0,8); }\n\nfunction syntaxHL(json) {\n return json\n .replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;')\n .replace(/\"(\\\\\\\\.|[^\"\\\\\\\\])*\"\\\\s*:/g, s => \\`<span class=\"j-key\">\\${s}</span>\\`)\n .replace(/:\\\\s*\"(\\\\\\\\.|[^\"\\\\\\\\])*\"/g, s => {\n const col = s.indexOf('\"');\n return s.slice(0,col) + \\`<span class=\"j-str\">\\${s.slice(col)}</span>\\`;\n })\n .replace(/:\\\\s*(-?\\\\d+\\\\.?\\\\d*)/g, (m,n) => m.replace(n, \\`<span class=\"j-num\">\\${n}</span>\\`))\n .replace(/:\\\\s*(true|false)/g, (m,b) => m.replace(b, \\`<span class=\"j-bool\">\\${b}</span>\\`))\n .replace(/:\\\\s*(null)/g, (m,n) => m.replace(n, \\`<span class=\"j-null\">\\${n}</span>\\`));\n}\n\ninit();\n</script>\n</body>\n</html>`;\n}\n","import TelegramBot from 'node-telegram-bot-api';\nimport PQueue from 'p-queue';\nimport pRetry, { AbortError } from 'p-retry';\nimport EventEmitter from 'eventemitter3';\n\nexport interface WorkerStats {\n tokenIndex: number;\n requestCount: number;\n errorCount: number;\n lastUsed: number;\n rateLimitHits: number;\n}\n\n/**\n * BotWorkerPool manages a round-robin pool of Telegram bot tokens.\n * Each token gets its own PQueue limited to 25 concurrent requests\n * (safe under Telegram's 30 req/s flood limit with headroom).\n * On 429 responses, the worker is cooled down and the next token takes over.\n */\nexport class BotWorkerPool extends EventEmitter {\n private bots: TelegramBot[] = [];\n private queues: PQueue[] = [];\n private stats: WorkerStats[] = [];\n private currentIndex = 0;\n private debug: boolean;\n\n constructor(tokens: string[], concurrency = 25, debug = false) {\n super();\n this.debug = debug;\n\n if (tokens.length === 0) throw new Error('[gramobase] At least one bot token required');\n\n for (let i = 0; i < tokens.length; i++) {\n const token = tokens[i]!;\n this.bots.push(new TelegramBot(token, { polling: false }));\n this.queues.push(new PQueue({ concurrency, intervalCap: 25, interval: 1000 }));\n this.stats.push({\n tokenIndex: i,\n requestCount: 0,\n errorCount: 0,\n lastUsed: 0,\n rateLimitHits: 0,\n });\n }\n }\n\n /**\n * Execute a Telegram API call through the pool with automatic retry\n * and token rotation on rate limits.\n */\n async execute<T>(\n fn: (bot: TelegramBot) => Promise<T>,\n priority = 5\n ): Promise<T> {\n const idx = this.pickWorker();\n const queue = this.queues[idx]!;\n const bot = this.bots[idx]!;\n const stat = this.stats[idx]!;\n\n return queue.add(\n () =>\n pRetry(\n async () => {\n stat.requestCount++;\n stat.lastUsed = Date.now();\n try {\n const result = await fn(bot);\n return result;\n } catch (err: unknown) {\n stat.errorCount++;\n if (this.isFloodError(err)) {\n stat.rateLimitHits++;\n this.emit('worker:rotate', idx);\n const retryAfter = this.extractRetryAfter(err) * 1000;\n if (this.debug) {\n console.warn(`[gramobase] Worker ${idx} flood limited, retrying after ${retryAfter}ms`);\n }\n await this.sleep(retryAfter);\n throw err;\n }\n if (this.isRetryableError(err)) {\n throw err;\n }\n throw new AbortError(err instanceof Error ? err : new Error(String(err)));\n }\n },\n {\n retries: 5,\n factor: 2,\n minTimeout: 1000,\n maxTimeout: 30_000,\n onFailedAttempt: (error) => {\n if (this.debug) {\n console.warn(`[gramobase] Attempt ${error.attemptNumber} failed:`, error.message);\n }\n },\n }\n ),\n { priority }\n ) as Promise<T>;\n }\n\n /**\n * Round-robin with recency bias — prefer the worker that was least recently used.\n */\n private pickWorker(): number {\n if (this.bots.length === 1) return 0;\n\n let bestIdx = 0;\n let oldestTime = Infinity;\n\n for (let i = 0; i < this.stats.length; i++) {\n const stat = this.stats[i]!;\n if (stat.lastUsed < oldestTime) {\n oldestTime = stat.lastUsed;\n bestIdx = i;\n }\n }\n\n this.currentIndex = bestIdx;\n return bestIdx;\n }\n\n private isFloodError(err: unknown): boolean {\n if (err && typeof err === 'object') {\n const e = err as { code?: string; response?: { statusCode?: number } };\n return e.code === 'ETELEGRAM' && e.response?.statusCode === 429;\n }\n return false;\n }\n\n private isRetryableError(err: unknown): boolean {\n if (!err) return false;\n if (err instanceof Error) {\n if (err.name === 'TypeError' || err.name === 'ReferenceError' || err.name === 'ValidationError') {\n return false;\n }\n }\n if (typeof err === 'object') {\n const e = err as { code?: string; response?: { statusCode?: number } };\n if (e.code === 'ETELEGRAM' && e.response?.statusCode === 429) {\n return true;\n }\n if (e.response?.statusCode && e.response.statusCode >= 500) {\n return true;\n }\n const retryableCodes = ['ETIMEDOUT', 'ECONNRESET', 'ENOTFOUND', 'EAI_AGAIN', 'ECONNREFUSED'];\n if (e.code && retryableCodes.includes(e.code)) {\n return true;\n }\n }\n return false;\n }\n\n private extractRetryAfter(err: unknown): number {\n if (err && typeof err === 'object') {\n const e = err as { response?: { body?: { parameters?: { retry_after?: number } } } };\n return e.response?.body?.parameters?.retry_after ?? 5;\n }\n return 5;\n }\n\n getBot(index = 0): TelegramBot {\n return this.bots[index] ?? this.bots[0]!;\n }\n\n getStats(): WorkerStats[] {\n return [...this.stats];\n }\n\n getQueueSizes(): number[] {\n return this.queues.map((q) => q.size);\n }\n\n private sleep(ms: number): Promise<void> {\n return new Promise((r) => setTimeout(r, ms));\n }\n\n async destroy(): Promise<void> {\n await Promise.all(this.queues.map((q) => q.onIdle()));\n for (const bot of this.bots) {\n await bot.stopPolling();\n }\n }\n}\n","import { LRUCache } from 'lru-cache';\nimport EventEmitter from 'eventemitter3';\n\ninterface CacheEntry<T> {\n data: T;\n collection: string;\n cachedAt: number;\n}\n\n/**\n * HotCache is an in-memory LRU cache that sits in front of Telegram storage.\n *\n * All reads hit the cache first. On a miss, the caller fetches from Telegram\n * and stores the result here. All writes invalidate or update the relevant key.\n *\n * The cache also stores the \"collection index\" — the full key→msgId map for\n * each collection — so that single-document lookups are O(1) without scanning\n * all messages.\n */\nexport class HotCache extends EventEmitter {\n private cache: LRUCache<string, CacheEntry<unknown>>;\n private collectionIndexes: Map<string, Map<string, number>> = new Map();\n private stats = { hits: 0, misses: 0, evictions: 0 };\n\n constructor(maxBytes = 64 * 1024 * 1024, ttlMs = 60_000) {\n super();\n this.cache = new LRUCache({\n maxSize: maxBytes,\n sizeCalculation: (val) =>\n JSON.stringify(val).length * 2, // rough UTF-16 byte estimate\n ttl: ttlMs,\n dispose: () => {\n this.stats.evictions++;\n },\n });\n }\n\n // ─── Document cache ──────────────────────────────────────────────────────\n\n get<T>(collection: string, id: string): T | undefined {\n const key = this.docKey(collection, id);\n const entry = this.cache.get(key) as CacheEntry<T> | undefined;\n if (entry) {\n this.stats.hits++;\n this.emit('cache:hit', { collection, key: id });\n return entry.data;\n }\n this.stats.misses++;\n this.emit('cache:miss', { collection, key: id });\n return undefined;\n }\n\n set<T>(collection: string, id: string, data: T): void {\n const key = this.docKey(collection, id);\n this.cache.set(key, { data, collection, cachedAt: Date.now() });\n }\n\n delete(collection: string, id: string): void {\n this.cache.delete(this.docKey(collection, id));\n }\n\n invalidateCollection(collection: string): void {\n for (const key of this.cache.keys()) {\n if (key.startsWith(`doc:${collection}:`)) {\n this.cache.delete(key);\n }\n }\n this.collectionIndexes.delete(collection);\n }\n\n // ─── Query cache ─────────────────────────────────────────────────────────\n\n getQuery<T>(queryHash: string): T[] | undefined {\n const entry = this.cache.get(`query:${queryHash}`) as CacheEntry<T[]> | undefined;\n return entry?.data;\n }\n\n setQuery<T>(queryHash: string, results: T[]): void {\n this.cache.set(`query:${queryHash}`, {\n data: results,\n collection: '__query__',\n cachedAt: Date.now(),\n });\n }\n\n invalidateQuery(collection: string): void {\n for (const key of this.cache.keys()) {\n if (key.startsWith(`query:${collection}:`)) {\n this.cache.delete(key);\n }\n }\n }\n\n // ─── Collection index ─────────────────────────────────────────────────────\n // Maps document _id → Telegram message ID for O(1) lookup\n\n getIndex(collection: string): Map<string, number> | undefined {\n return this.collectionIndexes.get(collection);\n }\n\n setIndex(collection: string, index: Map<string, number>): void {\n this.collectionIndexes.set(collection, index);\n }\n\n updateIndexEntry(collection: string, id: string, msgId: number): void {\n const idx = this.collectionIndexes.get(collection);\n if (idx) {\n idx.set(id, msgId);\n } else {\n this.collectionIndexes.set(collection, new Map([[id, msgId]]));\n }\n }\n\n deleteIndexEntry(collection: string, id: string): void {\n this.collectionIndexes.get(collection)?.delete(id);\n }\n\n getMsgId(collection: string, id: string): number | undefined {\n return this.collectionIndexes.get(collection)?.get(id);\n }\n\n // ─── Bulk read ────────────────────────────────────────────────────────────\n\n getMany<T>(collection: string, ids: string[]): Map<string, T> {\n const result = new Map<string, T>();\n for (const id of ids) {\n const val = this.get<T>(collection, id);\n if (val !== undefined) result.set(id, val);\n }\n return result;\n }\n\n // ─── Stats ────────────────────────────────────────────────────────────────\n\n getStats() {\n return {\n ...this.stats,\n size: this.cache.size,\n hitRate:\n this.stats.hits + this.stats.misses > 0\n ? this.stats.hits / (this.stats.hits + this.stats.misses)\n : 0,\n };\n }\n\n clear(): void {\n this.cache.clear();\n this.collectionIndexes.clear();\n }\n\n private docKey(collection: string, id: string): string {\n return `doc:${collection}:${id}`;\n }\n}\n","import { createCipheriv, createDecipheriv, randomBytes, createHash } from 'crypto';\nimport { BotWorkerPool } from '../workers/BotWorkerPool.js';\nimport { GramoBaseDocument } from '../types/index.js';\nimport { Registry } from '../registry/Registry.js';\n\nconst INDEX_TAG = '__GRAMOBASE_INDEX__';\nconst DOC_TAG = '__GRAMOBASE_DOC__';\nconst MAX_MSG_BYTES = 4000;\n\nexport interface IndexMessage {\n collection: string;\n // id → msgId map\n entries: Record<string, number>;\n walSeq: number;\n updatedAt: string;\n msgId?: number;\n}\n\n/**\n * TelegramStorage handles the raw read/write operations against Telegram channels.\n *\n * Each collection gets a \"collection index message\" (pinned or findable by tag)\n * that maps document IDs to their Telegram message IDs.\n *\n * Documents are stored as JSON message text, optionally AES-256 encrypted.\n * Files are stored via sendDocument/sendPhoto and referenced by Telegram file_id.\n */\nexport class TelegramStorage {\n private encryptionKey: Buffer | null = null;\n // collection → pinned index message ID\n private indexMsgIds: Map<string, number> = new Map();\n\n constructor(\n private pool: BotWorkerPool,\n private defaultChannelId: string,\n private registry: Registry,\n encryptionKey?: string,\n private debug = false\n ) {\n if (encryptionKey) {\n this.encryptionKey = createHash('sha256').update(encryptionKey).digest();\n }\n }\n\n // ─── Index management ─────────────────────────────────────────────────────\n\n private async readRawMessageText(msgId: number, channel: string): Promise<string | null> {\n try {\n const msg = await this.pool.execute((bot) =>\n bot.forwardMessage(channel, channel, msgId)\n ) as any;\n\n if (!msg?.text) return null;\n\n let text = msg.text as string;\n if (this.encryptionKey && text.startsWith('ENC:')) {\n text = this.decrypt(text);\n }\n return text;\n } catch {\n return null;\n }\n }\n\n async loadIndex(collection: string, channelId?: string): Promise<IndexMessage> {\n const channel = channelId ?? this.defaultChannelId;\n\n try {\n const msgId = await this.registry.getCollectionIndexMsgId(collection);\n if (msgId) {\n const text = await this.readRawMessageText(msgId, channel);\n if (text && text.startsWith(INDEX_TAG)) {\n const json = text.replace(INDEX_TAG + '\\n', '');\n const parsed = JSON.parse(json) as IndexMessage;\n this.indexMsgIds.set(collection, msgId);\n return parsed;\n }\n }\n } catch {\n // Fallback\n }\n\n try {\n const chat = await this.pool.execute((bot) => bot.getChat(channel)) as any;\n\n // Check pinned message first\n if (chat.pinned_message?.text?.startsWith(INDEX_TAG)) {\n const json = chat.pinned_message.text.replace(INDEX_TAG + '\\n', '');\n const parsed = JSON.parse(json) as IndexMessage;\n if (parsed.collection === collection) {\n this.indexMsgIds.set(collection, chat.pinned_message.message_id);\n await this.registry.setCollectionIndexMsgId(collection, chat.pinned_message.message_id);\n return parsed;\n }\n }\n } catch {\n // No pinned message or channel is empty\n }\n\n // Return an empty index\n return {\n collection,\n entries: {},\n walSeq: 0,\n updatedAt: new Date().toISOString(),\n };\n }\n\n async saveIndex(index: IndexMessage, channelId?: string): Promise<void> {\n const channel = channelId ?? this.defaultChannelId;\n const text = `${INDEX_TAG}\\n${JSON.stringify(index)}`;\n\n const existingMsgId = this.indexMsgIds.get(index.collection) ||\n await this.registry.getCollectionIndexMsgId(index.collection);\n\n if (existingMsgId) {\n try {\n await this.pool.execute((bot) =>\n bot.editMessageText(text, {\n chat_id: channel,\n message_id: existingMsgId,\n })\n );\n return;\n } catch {\n // Message deleted or uneditable; create fresh\n }\n }\n\n const msg = await this.pool.execute((bot) =>\n bot.sendMessage(channel, text, { disable_notification: true })\n ) as any;\n\n const newMsgId = msg.message_id;\n this.indexMsgIds.set(index.collection, newMsgId);\n await this.registry.setCollectionIndexMsgId(index.collection, newMsgId);\n }\n\n // ─── Document CRUD ────────────────────────────────────────────────────────\n\n async writeDocument(\n doc: GramoBaseDocument,\n channelId?: string\n ): Promise<number> {\n const channel = channelId ?? this.defaultChannelId;\n let text = JSON.stringify({ [DOC_TAG]: true, ...doc });\n\n if (this.encryptionKey) {\n text = this.encrypt(text);\n }\n\n // Split large documents across multiple messages\n if (Buffer.byteLength(text, 'utf8') > MAX_MSG_BYTES) {\n return this.writeChunked(text, channel);\n }\n\n const msg = await this.pool.execute((bot) =>\n bot.sendMessage(channel, text, { disable_notification: true })\n ) as any;\n\n return msg.message_id as number;\n }\n\n async readDocument(\n msgId: number,\n channelId?: string\n ): Promise<GramoBaseDocument | null> {\n const channel = channelId ?? this.defaultChannelId;\n\n try {\n const msg = await this.pool.execute((bot) =>\n bot.forwardMessage(channel, channel, msgId)\n ) as any;\n\n if (!msg?.text) return null;\n\n let text = msg.text as string;\n if (this.encryptionKey && text.startsWith('ENC:')) {\n text = this.decrypt(text);\n }\n\n // Reassemble chunked messages if needed\n if (text.startsWith('CHUNK:')) {\n text = await this.readChunked(text, channel);\n }\n\n const parsed = JSON.parse(text);\n delete parsed[DOC_TAG];\n parsed._msgId = msgId;\n return parsed as GramoBaseDocument;\n } catch {\n return null;\n }\n }\n\n async deleteDocument(msgId: number, channelId?: string): Promise<void> {\n const channel = channelId ?? this.defaultChannelId;\n await this.pool.execute((bot) =>\n (bot as any).deleteMessage(channel, msgId)\n );\n }\n\n async updateDocument(\n msgId: number,\n doc: GramoBaseDocument,\n channelId?: string\n ): Promise<number> {\n // Telegram doesn't support editing beyond 48h — delete + re-insert\n await this.deleteDocument(msgId, channelId);\n return this.writeDocument(doc, channelId);\n }\n\n // ─── Chunked large documents ──────────────────────────────────────────────\n\n private async writeChunked(text: string, channel: string): Promise<number> {\n const chunks: string[] = [];\n for (let i = 0; i < text.length; i += MAX_MSG_BYTES) {\n chunks.push(text.slice(i, i + MAX_MSG_BYTES));\n }\n\n const msgIds: number[] = [];\n for (const chunk of chunks) {\n const msg = await this.pool.execute((bot) =>\n bot.sendMessage(channel, chunk, { disable_notification: true })\n ) as any;\n msgIds.push(msg.message_id as number);\n }\n\n // Header message with chunk references\n const header = `CHUNK:${JSON.stringify(msgIds)}`;\n const headerMsg = await this.pool.execute((bot) =>\n bot.sendMessage(channel, header, { disable_notification: true })\n ) as any;\n\n return headerMsg.message_id as number;\n }\n\n private async readChunked(headerText: string, channel: string): Promise<string> {\n const msgIds: number[] = JSON.parse(headerText.replace('CHUNK:', ''));\n const parts: string[] = [];\n\n for (const id of msgIds) {\n const msg = await this.pool.execute((bot) =>\n bot.forwardMessage(channel, channel, id)\n ) as any;\n if (msg?.text) parts.push(msg.text as string);\n }\n\n return parts.join('');\n }\n\n // ─── File storage ─────────────────────────────────────────────────────────\n\n async uploadFile(\n data: Buffer,\n fileName: string,\n mimeType: string,\n channelId?: string\n ): Promise<{ fileId: string; msgId: number }> {\n const channel = channelId ?? this.defaultChannelId;\n const isImage = mimeType.startsWith('image/');\n\n let msg: any;\n if (isImage) {\n msg = await this.pool.execute((bot) =>\n bot.sendPhoto(channel, data, {\n caption: fileName,\n disable_notification: true,\n })\n );\n } else {\n msg = await this.pool.execute((bot) =>\n bot.sendDocument(channel, data, {\n caption: fileName,\n disable_notification: true,\n })\n );\n }\n\n const fileId = isImage\n ? (msg as any).photo?.[(msg as any).photo.length - 1]?.file_id\n : (msg as any).document?.file_id;\n\n return { fileId, msgId: msg.message_id };\n }\n\n async getFileUrl(fileId: string): Promise<string> {\n return this.pool.execute((bot) => bot.getFileLink(fileId));\n }\n\n // ─── Encryption ───────────────────────────────────────────────────────────\n\n private encrypt(text: string): string {\n if (!this.encryptionKey) return text;\n const iv = randomBytes(16);\n const cipher = createCipheriv('aes-256-cbc', this.encryptionKey, iv);\n const encrypted = Buffer.concat([\n cipher.update(text, 'utf8'),\n cipher.final(),\n ]);\n return `ENC:${iv.toString('hex')}:${encrypted.toString('base64')}`;\n }\n\n private decrypt(text: string): string {\n if (!this.encryptionKey) return text;\n const [, ivHex, encB64] = text.split(':');\n if (!ivHex || !encB64) throw new Error('Invalid encrypted payload');\n const iv = Buffer.from(ivHex, 'hex');\n const encBuf = Buffer.from(encB64, 'base64');\n const decipher = createDecipheriv('aes-256-cbc', this.encryptionKey, iv);\n return Buffer.concat([decipher.update(encBuf), decipher.final()]).toString('utf8');\n }\n}\n","import { createHash } from 'crypto';\nimport { WalEntry, WalOpType } from '../types/index.js';\nimport { BotWorkerPool } from '../workers/BotWorkerPool.js';\n\nconst WAL_HEADER = '__WAL__';\nconst WAL_SEQ_TAG = '__WAL_SEQ__';\n\n/**\n * Write-Ahead Log backed by a Telegram channel.\n *\n * Every mutation is written to the WAL channel as a message BEFORE it is\n * applied to the main index. On startup, the WAL is replayed to recover\n * any operations that didn't complete during a crash.\n *\n * Format of each WAL message:\n * { \"__wal\": true, seq: N, op: \"INSERT\"|..., collection, id, data, ts, checksum }\n */\nexport class WriteAheadLog {\n private seq = 0;\n private buffer: WalEntry[] = [];\n private flushTimer: NodeJS.Timeout | null = null;\n private readonly FLUSH_INTERVAL_MS = 2000;\n private readonly BUFFER_LIMIT = 50;\n\n constructor(\n private pool: BotWorkerPool,\n private walChannelId: string,\n private debug: boolean = false\n ) {}\n\n async init(): Promise<void> {\n // Find the last WAL sequence number to resume from\n try {\n const msgs = await this.pool.execute((bot) =>\n (bot as any).getChatHistory(this.walChannelId, { limit: 10 })\n );\n for (const msg of (msgs as any[]).reverse()) {\n if (msg.text?.includes(WAL_SEQ_TAG)) {\n const match = msg.text.match(/__WAL_SEQ__:(\\d+)/);\n if (match) {\n this.seq = parseInt(match[1]!, 10);\n break;\n }\n }\n }\n } catch {\n // Channel may be empty on first run\n }\n if (this.debug) console.log(`[WAL] Initialized at seq=${this.seq}`);\n }\n\n /**\n * Append an entry to the WAL buffer. Flushes immediately if buffer is full.\n */\n async append(\n op: WalOpType,\n collection: string,\n id: string,\n data?: unknown\n ): Promise<WalEntry> {\n this.seq++;\n const entry: WalEntry = {\n seq: this.seq,\n op,\n collection,\n id,\n data,\n timestamp: new Date().toISOString(),\n checksum: '',\n };\n entry.checksum = this.checksum(entry);\n this.buffer.push(entry);\n\n if (this.buffer.length >= this.BUFFER_LIMIT) {\n await this.flush();\n } else {\n this.scheduleFlush();\n }\n\n return entry;\n }\n\n /**\n * Flush buffered WAL entries to Telegram.\n */\n async flush(): Promise<void> {\n if (this.buffer.length === 0) return;\n if (this.flushTimer) {\n clearTimeout(this.flushTimer);\n this.flushTimer = null;\n }\n\n const batch = [...this.buffer];\n this.buffer = [];\n\n const payload = JSON.stringify({\n __wal: true,\n [WAL_SEQ_TAG]: batch[batch.length - 1]!.seq,\n entries: batch,\n });\n\n // Split if > 4096 bytes (Telegram message limit)\n const chunks = this.chunk(payload, 4000);\n for (const chunk of chunks) {\n await this.pool.execute((bot) =>\n bot.sendMessage(this.walChannelId, `${WAL_HEADER}\\n${chunk}`, {\n disable_notification: true,\n })\n );\n }\n\n if (this.debug) console.log(`[WAL] Flushed ${batch.length} entries`);\n this.pool.emit('wal:flush', batch.length);\n }\n\n /**\n * Replay all WAL entries since a given sequence number.\n * Returns entries in order — the caller applies them to restore state.\n */\n async replay(sinceSeq = 0): Promise<WalEntry[]> {\n const entries: WalEntry[] = [];\n\n // Fetch messages from WAL channel, parse WAL entries\n try {\n const msgs = await this.pool.execute((bot) =>\n (bot as any).getChatHistory(this.walChannelId, { limit: 100 })\n );\n\n for (const msg of msgs as any[]) {\n if (!msg.text?.startsWith(WAL_HEADER)) continue;\n const jsonStr = msg.text.replace(WAL_HEADER + '\\n', '');\n try {\n const parsed = JSON.parse(jsonStr);\n if (parsed.__wal && Array.isArray(parsed.entries)) {\n for (const e of parsed.entries as WalEntry[]) {\n if (e.seq > sinceSeq && this.verifyChecksum(e)) {\n entries.push(e);\n }\n }\n }\n } catch {\n // Corrupted WAL entry — skip\n }\n }\n } catch {\n // Empty or inaccessible WAL\n }\n\n return entries.sort((a, b) => a.seq - b.seq);\n }\n\n private scheduleFlush(): void {\n if (this.flushTimer) return;\n this.flushTimer = setTimeout(() => this.flush(), this.FLUSH_INTERVAL_MS);\n }\n\n private checksum(entry: Omit<WalEntry, 'checksum'>): string {\n const str = `${entry.seq}:${entry.op}:${entry.collection}:${entry.id}:${JSON.stringify(entry.data)}`;\n return createHash('sha256').update(str).digest('hex').slice(0, 16);\n }\n\n private verifyChecksum(entry: WalEntry): boolean {\n const { checksum, ...rest } = entry;\n return checksum === this.checksum(rest);\n }\n\n private chunk(str: string, size: number): string[] {\n const chunks: string[] = [];\n for (let i = 0; i < str.length; i += size) {\n chunks.push(str.slice(i, i + size));\n }\n return chunks;\n }\n\n getCurrentSeq(): number {\n return this.seq;\n }\n}\n","import { randomUUID } from 'crypto';\nimport { Lease } from '../types/index.js';\nimport { BotWorkerPool } from '../workers/BotWorkerPool.js';\n\nconst REGISTRY_TAG = '__GRAMOBASE_REGISTRY__';\nconst LEASE_TTL_MS = 30_000;\nconst HEARTBEAT_MS = 10_000;\n\ninterface RegistryState {\n activeLease: Lease | null;\n instanceId: string;\n registryMsgId: number | null;\n indexes: Record<string, number>;\n}\n\n/**\n * Registry uses a pinned Telegram message as a distributed lock.\n *\n * When a gramobase instance starts up, it reads the registry message.\n * If no lease exists or the existing lease is expired, it writes a new\n * lease with its own instanceId and begins sending heartbeats.\n *\n * This prevents multiple writer processes from corrupting the index\n * (last-write-wins races on the pinned index message).\n *\n * Read-only operations are always permitted. Only index mutations\n * require holding the write lease.\n */\nexport class Registry {\n private state: RegistryState;\n private readonly instanceId: string;\n\n constructor(\n private pool: BotWorkerPool,\n private channelId: string,\n private debug: boolean = false\n ) {\n this.instanceId = randomUUID();\n this.state = {\n activeLease: null,\n instanceId: this.instanceId,\n registryMsgId: null,\n indexes: {},\n };\n }\n\n async acquireWriteLease(options: { wait?: boolean } = { wait: true }): Promise<Lease> {\n const existing = await this.readRegistryMessage();\n\n if (existing?.activeLease) {\n const lease = existing.activeLease;\n if (lease.instanceId !== this.instanceId && Date.now() < lease.expiresAt) {\n if (!options.wait) {\n throw new Error(\n `[gramobase Registry] Another instance (${lease.instanceId}) holds the write lease until ${new Date(\n lease.expiresAt\n ).toISOString()}. Use Registry.forceRelease() to break a stale lease.`\n );\n }\n\n const waitMs = lease.expiresAt - Date.now() + 250; // +250ms buffer\n if (this.debug) {\n console.log(\n `[Registry] Lease held by ${lease.instanceId}, waiting ${waitMs}ms for it to expire...`\n );\n }\n await new Promise((resolve) => setTimeout(resolve, waitMs));\n // Re-read after waiting — if still held by same instance and still active, throw\n const recheckState = await this.readRegistryMessage();\n if (\n recheckState?.activeLease &&\n recheckState.activeLease.instanceId !== this.instanceId &&\n Date.now() < recheckState.activeLease.expiresAt\n ) {\n throw new Error(\n `[gramobase Registry] Another instance (${recheckState.activeLease.instanceId}) holds the write lease until ${new Date(\n recheckState.activeLease.expiresAt\n ).toISOString()}. Use Registry.forceRelease() to break a stale lease.`\n );\n }\n }\n }\n\n const lease: Lease = {\n instanceId: this.instanceId,\n acquiredAt: Date.now(),\n expiresAt: Date.now() + LEASE_TTL_MS,\n heartbeatInterval: null,\n };\n\n await this.writeRegistryMessage({ activeLease: lease });\n this.state.activeLease = lease;\n\n // Start heartbeat to renew lease while process is alive\n lease.heartbeatInterval = setInterval(\n () => this.heartbeat(),\n HEARTBEAT_MS\n );\n\n if (this.debug) console.log(`[Registry] Acquired write lease: ${this.instanceId}`);\n return lease;\n }\n\n async releaseWriteLease(): Promise<void> {\n if (!this.state.activeLease) return;\n\n if (this.state.activeLease.heartbeatInterval) {\n clearInterval(this.state.activeLease.heartbeatInterval);\n }\n\n await this.writeRegistryMessage({ activeLease: null });\n this.state.activeLease = null;\n\n if (this.debug) console.log(`[Registry] Released write lease: ${this.instanceId}`);\n }\n\n async forceRelease(): Promise<void> {\n await this.writeRegistryMessage({ activeLease: null });\n this.state.activeLease = null;\n if (this.debug) console.log('[Registry] Forced lease release');\n }\n\n async isWriteLeaseHeld(): Promise<boolean> {\n const state = await this.readRegistryMessage();\n if (!state?.activeLease) return false;\n const { activeLease } = state;\n return activeLease.instanceId === this.instanceId && Date.now() < activeLease.expiresAt;\n }\n\n private async heartbeat(): Promise<void> {\n if (!this.state.activeLease) return;\n this.state.activeLease.expiresAt = Date.now() + LEASE_TTL_MS;\n await this.writeRegistryMessage({ activeLease: this.state.activeLease });\n if (this.debug) console.log('[Registry] Heartbeat sent');\n }\n\n private async readRegistryMessage(): Promise<{ activeLease: Lease | null; indexes?: Record<string, number> } | null> {\n try {\n const chat = await this.pool.execute((bot) =>\n bot.getChat(this.channelId)\n ) as any;\n\n if (chat.pinned_message?.text?.startsWith(REGISTRY_TAG)) {\n this.state.registryMsgId = chat.pinned_message.message_id;\n const json = chat.pinned_message.text.replace(REGISTRY_TAG + '\\n', '');\n const parsed = JSON.parse(json);\n this.state.indexes = parsed.indexes || {};\n return parsed;\n }\n } catch {\n // No registry message yet\n }\n return null;\n }\n\n private async writeRegistryMessage(\n data: { activeLease: Lease | null; indexes?: Record<string, number> }\n ): Promise<void> {\n let leasePayload = null;\n if (data.activeLease) {\n const { heartbeatInterval, ...rest } = data.activeLease;\n leasePayload = rest;\n }\n const payload = {\n activeLease: leasePayload,\n indexes: data.indexes || this.state.indexes || {},\n };\n const text = `${REGISTRY_TAG}\\n${JSON.stringify(payload, null, 0)}`;\n\n if (this.state.registryMsgId) {\n // Try to update existing pinned message\n try {\n await this.pool.execute((bot) =>\n bot.editMessageText(text, {\n chat_id: this.channelId,\n message_id: this.state.registryMsgId!,\n })\n );\n return;\n } catch {\n // Message may have been deleted; fall through to create new\n }\n }\n\n const msg = await this.pool.execute((bot) =>\n bot.sendMessage(this.channelId, text, { disable_notification: true })\n ) as any;\n\n this.state.registryMsgId = msg.message_id;\n await this.pool.execute((bot) =>\n bot.pinChatMessage(this.channelId, msg.message_id, {\n disable_notification: true,\n })\n );\n }\n\n async getCollectionIndexMsgId(collection: string): Promise<number | null> {\n if (!this.state.registryMsgId) {\n await this.readRegistryMessage();\n }\n return this.state.indexes[collection] || null;\n }\n\n async setCollectionIndexMsgId(collection: string, msgId: number): Promise<void> {\n if (!this.state.registryMsgId) {\n await this.readRegistryMessage();\n }\n this.state.indexes[collection] = msgId;\n await this.writeRegistryMessage({\n activeLease: this.state.activeLease,\n indexes: this.state.indexes,\n });\n }\n\n getInstanceId(): string {\n return this.instanceId;\n }\n\n getCurrentLease(): Lease | null {\n return this.state.activeLease;\n }\n}\n","import { randomUUID, createHash } from 'crypto';\nimport { z } from 'zod';\nimport {\n Filter,\n FindOptions,\n UpdateOperators,\n GramoBaseDocument,\n CollectionConfig,\n WithId,\n SchemaLike,\n InferSchema,\n} from '../types/index.js';\nimport { HotCache } from '../cache/HotCache.js';\nimport { TelegramStorage } from '../storage/TelegramStorage.js';\nimport { WriteAheadLog } from '../wal/WriteAheadLog.js';\n\ntype DocOf<T extends SchemaLike> = WithId<InferSchema<T>>;\n\n/**\n * Collection<T> is the main ORM interface.\n *\n * It provides a MongoDB-like API and handles:\n * - Schema validation via Zod\n * - Hot-cache reads (LRU in-memory)\n * - WAL writes before Telegram flush\n * - Index management (id → msgId map, stored as a pinned message)\n * - Filter/sort/skip/limit in memory after cache warm-up\n */\nexport class Collection<T extends SchemaLike> {\n private name: string;\n private config: CollectionConfig<T>;\n private cache: HotCache;\n private storage: TelegramStorage;\n private wal: WriteAheadLog;\n private channelId: string;\n private indexLoaded = false;\n\n constructor(\n name: string,\n config: CollectionConfig<T>,\n cache: HotCache,\n storage: TelegramStorage,\n wal: WriteAheadLog,\n defaultChannelId: string\n ) {\n this.name = name;\n this.config = config;\n this.cache = cache;\n this.storage = storage;\n this.wal = wal;\n this.channelId = config.channelId ?? defaultChannelId;\n }\n\n // ─── Init ──────────────────────────────────────────────────────────────\n\n async ensureIndexLoaded(): Promise<void> {\n if (this.indexLoaded) return;\n const idx = await this.storage.loadIndex(this.name, this.channelId);\n this.cache.setIndex(this.name, new Map(Object.entries(idx.entries).map(([k, v]) => [k, v])));\n this.indexLoaded = true;\n }\n\n // ─── Insert ────────────────────────────────────────────────────────────\n\n async insertOne(data: InferSchema<T>): Promise<DocOf<T>> {\n const validated = this.config.schema.parse(data) as InferSchema<T>;\n const doc: GramoBaseDocument = {\n ...validated,\n _id: randomUUID(),\n _collection: this.name,\n _msgId: 0,\n _createdAt: new Date().toISOString(),\n _updatedAt: new Date().toISOString(),\n };\n\n // WAL before write\n await this.wal.append('INSERT', this.name, doc._id, doc);\n\n const msgId = await this.storage.writeDocument(doc, this.channelId);\n doc._msgId = msgId;\n\n // Update cache + index\n this.cache.set(this.name, doc._id, doc);\n this.cache.updateIndexEntry(this.name, doc._id, msgId);\n this.cache.invalidateQuery(this.name);\n\n // Persist index\n await this.flushIndex();\n\n return doc as DocOf<T>;\n }\n\n async insertMany(items: InferSchema<T>[]): Promise<DocOf<T>[]> {\n return Promise.all(items.map((item) => this.insertOne(item)));\n }\n\n // ─── Find ──────────────────────────────────────────────────────────────\n\n async findById(id: string): Promise<DocOf<T> | null> {\n // Cache hit\n const cached = this.cache.get<DocOf<T>>(this.name, id);\n if (cached) return cached;\n\n await this.ensureIndexLoaded();\n const msgId = this.cache.getMsgId(this.name, id);\n if (!msgId) return null;\n\n const doc = await this.storage.readDocument(msgId, this.channelId);\n if (!doc) return null;\n\n this.cache.set(this.name, id, doc);\n return doc as DocOf<T>;\n }\n\n async findOne(filter: Filter<InferSchema<T>> = {}): Promise<DocOf<T> | null> {\n const results = await this.find({ filter, limit: 1 });\n return results[0] ?? null;\n }\n\n async find(options: FindOptions<InferSchema<T>> = {}): Promise<DocOf<T>[]> {\n const { filter = {}, sort, limit, skip = 0, projection, useCache = true } = options;\n\n // Check query cache\n const queryHash = this.hashQuery(filter, sort, limit, skip);\n if (useCache) {\n const cached = this.cache.getQuery<DocOf<T>>(queryHash);\n if (cached) return cached;\n }\n\n // Load all documents from index\n await this.ensureIndexLoaded();\n const index = this.cache.getIndex(this.name);\n if (!index) return [];\n\n const docs: DocOf<T>[] = [];\n const ids = [...index.keys()];\n\n // Batch read with cache\n const uncachedIds: string[] = [];\n for (const id of ids) {\n const cached = this.cache.get<DocOf<T>>(this.name, id);\n if (cached) {\n docs.push(cached);\n } else {\n uncachedIds.push(id);\n }\n }\n\n // Fetch uncached from Telegram\n await Promise.all(\n uncachedIds.map(async (id) => {\n const doc = await this.findById(id);\n if (doc) docs.push(doc);\n })\n );\n\n // Apply filter\n let results = docs.filter((doc) => this.matchesFilter(doc, filter));\n\n // Apply sort\n if (sort) {\n results = this.applySort(results, sort as Record<string, 1 | -1>);\n }\n\n // Apply pagination\n results = results.slice(skip, limit ? skip + limit : undefined);\n\n // Apply projection\n if (projection) {\n results = results.map((doc) => this.applyProjection(doc, projection as Record<string, 1 | 0>));\n }\n\n // Cache query result\n if (useCache) {\n this.cache.setQuery(queryHash, results);\n }\n\n return results;\n }\n\n async count(filter: Filter<InferSchema<T>> = {}): Promise<number> {\n const results = await this.find({ filter, useCache: true });\n return results.length;\n }\n\n // ─── Update ────────────────────────────────────────────────────────────\n\n async updateOne(\n filter: Filter<InferSchema<T>>,\n update: UpdateOperators<InferSchema<T>>\n ): Promise<DocOf<T> | null> {\n const doc = await this.findOne(filter);\n if (!doc) return null;\n return this.applyUpdate(doc, update);\n }\n\n async updateMany(\n filter: Filter<InferSchema<T>>,\n update: UpdateOperators<InferSchema<T>>\n ): Promise<DocOf<T>[]> {\n const docs = await this.find({ filter });\n return Promise.all(docs.map((doc) => this.applyUpdate(doc, update)));\n }\n\n async findByIdAndUpdate(\n id: string,\n update: UpdateOperators<InferSchema<T>>\n ): Promise<DocOf<T> | null> {\n const doc = await this.findById(id);\n if (!doc) return null;\n return this.applyUpdate(doc, update);\n }\n\n private async applyUpdate(\n doc: GramoBaseDocument,\n update: UpdateOperators<unknown>\n ): Promise<DocOf<T>> {\n const updated = { ...doc, _updatedAt: new Date().toISOString() };\n\n if (update.$set) Object.assign(updated, update.$set);\n if (update.$unset) {\n for (const key of Object.keys(update.$unset)) {\n delete (updated as Record<string, unknown>)[key];\n }\n }\n if (update.$inc) {\n for (const [key, val] of Object.entries(update.$inc)) {\n (updated as Record<string, unknown>)[key] =\n (((updated as Record<string, unknown>)[key] as number) ?? 0) + (val as number);\n }\n }\n if (update.$push) {\n for (const [key, val] of Object.entries(update.$push)) {\n const arr = (updated as Record<string, unknown>)[key];\n (updated as Record<string, unknown>)[key] = Array.isArray(arr)\n ? [...arr, val]\n : [val];\n }\n }\n\n // Validate updated doc\n this.config.schema.parse(updated);\n\n await this.wal.append('UPDATE', this.name, updated._id, updated);\n\n const newMsgId = await this.storage.updateDocument(\n updated._msgId,\n updated as GramoBaseDocument,\n this.channelId\n );\n updated._msgId = newMsgId;\n\n this.cache.set(this.name, updated._id, updated);\n this.cache.updateIndexEntry(this.name, updated._id, newMsgId);\n this.cache.invalidateQuery(this.name);\n\n await this.flushIndex();\n\n return updated as DocOf<T>;\n }\n\n // ─── Delete ────────────────────────────────────────────────────────────\n\n async deleteOne(filter: Filter<InferSchema<T>>): Promise<boolean> {\n const doc = await this.findOne(filter);\n if (!doc) return false;\n return this.deleteById(doc._id);\n }\n\n async deleteMany(filter: Filter<InferSchema<T>>): Promise<number> {\n const docs = await this.find({ filter });\n await Promise.all(docs.map((doc) => this.deleteById(doc._id)));\n return docs.length;\n }\n\n async deleteById(id: string): Promise<boolean> {\n const msgId = this.cache.getMsgId(this.name, id);\n if (!msgId) return false;\n\n await this.wal.append('DELETE', this.name, id);\n await this.storage.deleteDocument(msgId, this.channelId);\n\n this.cache.delete(this.name, id);\n this.cache.deleteIndexEntry(this.name, id);\n this.cache.invalidateQuery(this.name);\n\n await this.flushIndex();\n return true;\n }\n\n // ─── Index flush ──────────────────────────────────────────────────────\n\n private async flushIndex(): Promise<void> {\n const index = this.cache.getIndex(this.name);\n if (!index) return;\n\n await this.storage.saveIndex(\n {\n collection: this.name,\n entries: Object.fromEntries(index.entries()),\n walSeq: this.wal.getCurrentSeq(),\n updatedAt: new Date().toISOString(),\n },\n this.channelId\n );\n }\n\n // ─── Filter engine ─────────────────────────────────────────────────────\n\n private matchesFilter(doc: unknown, filter: Filter<unknown>): boolean {\n for (const [key, condition] of Object.entries(filter)) {\n if (key === '$and') {\n if (!(condition as Filter<unknown>[]).every((f) => this.matchesFilter(doc, f)))\n return false;\n continue;\n }\n if (key === '$or') {\n if (!(condition as Filter<unknown>[]).some((f) => this.matchesFilter(doc, f)))\n return false;\n continue;\n }\n if (key === '$not') {\n if (this.matchesFilter(doc, condition as Filter<unknown>)) return false;\n continue;\n }\n\n const val = (doc as Record<string, unknown>)[key];\n if (condition === null || typeof condition !== 'object' || condition instanceof RegExp) {\n if (Array.isArray(val)) {\n if (condition instanceof RegExp) {\n if (!val.some((item) => condition.test(String(item)))) return false;\n } else {\n if (!val.includes(condition)) return false;\n }\n } else {\n if (condition instanceof RegExp) {\n if (!condition.test(String(val))) return false;\n } else {\n if (val !== condition) return false;\n }\n }\n continue;\n }\n\n const ops = condition as Record<string, unknown>;\n if ('$eq' in ops) {\n const eqVal = ops['$eq'];\n if (Array.isArray(val)) {\n if (Array.isArray(eqVal)) {\n if (val.length !== eqVal.length || !val.every((v, i) => v === eqVal[i])) return false;\n } else {\n if (!val.includes(eqVal)) return false;\n }\n } else {\n if (val !== eqVal) return false;\n }\n }\n if ('$ne' in ops) {\n const neVal = ops['$ne'];\n if (Array.isArray(val)) {\n if (Array.isArray(neVal)) {\n if (val.length === neVal.length && val.every((v, i) => v === neVal[i])) return false;\n } else {\n if (val.includes(neVal)) return false;\n }\n } else {\n if (val === neVal) return false;\n }\n }\n if ('$gt' in ops && !((val as number) > (ops['$gt'] as number))) return false;\n if ('$gte' in ops && !((val as number) >= (ops['$gte'] as number))) return false;\n if ('$lt' in ops && !((val as number) < (ops['$lt'] as number))) return false;\n if ('$lte' in ops && !((val as number) <= (ops['$lte'] as number))) return false;\n if ('$in' in ops) {\n const inList = ops['$in'] as unknown[];\n if (Array.isArray(val)) {\n const hasIntersection = val.some((v) => inList.includes(v));\n const hasExactArray = inList.some(\n (item) => Array.isArray(item) && item.length === val.length && item.every((v, i) => v === val[i])\n );\n if (!hasIntersection && !hasExactArray) return false;\n } else {\n if (!inList.includes(val)) return false;\n }\n }\n if ('$nin' in ops) {\n const ninList = ops['$nin'] as unknown[];\n if (Array.isArray(val)) {\n const hasIntersection = val.some((v) => ninList.includes(v));\n const hasExactArray = ninList.some(\n (item) => Array.isArray(item) && item.length === val.length && item.every((v, i) => v === val[i])\n );\n if (hasIntersection || hasExactArray) return false;\n } else {\n if (ninList.includes(val)) return false;\n }\n }\n if ('$exists' in ops) {\n const exists = val !== undefined && val !== null;\n if (exists !== ops['$exists']) return false;\n }\n if ('$regex' in ops) {\n const re =\n ops['$regex'] instanceof RegExp\n ? ops['$regex']\n : new RegExp(ops['$regex'] as string);\n if (Array.isArray(val)) {\n if (!val.some((item) => re.test(String(item)))) return false;\n } else {\n if (!re.test(String(val))) return false;\n }\n }\n }\n return true;\n }\n\n private applySort<D>(docs: D[], sort: Record<string, 1 | -1>): D[] {\n return [...docs].sort((a, b) => {\n for (const [key, dir] of Object.entries(sort)) {\n const av = (a as Record<string, unknown>)[key];\n const bv = (b as Record<string, unknown>)[key];\n if (av === bv) continue;\n if (av == null) return dir;\n if (bv == null) return -dir;\n return av < bv ? -dir : dir;\n }\n return 0;\n });\n }\n\n private applyProjection<D>(doc: D, projection: Record<string, 1 | 0>): D {\n const result: Record<string, unknown> = {};\n const isInclusive = Object.values(projection).some((v) => v === 1);\n for (const [key, val] of Object.entries(doc as Record<string, unknown>)) {\n if (isInclusive) {\n if (projection[key] === 1 || key.startsWith('_')) result[key] = val;\n } else {\n if (projection[key] !== 0) result[key] = val;\n }\n }\n return result as D;\n }\n\n private hashQuery(...args: unknown[]): string {\n return `${this.name}:` + createHash('md5').update(JSON.stringify(args)).digest('hex');\n }\n\n getName(): string {\n return this.name;\n }\n}\n","import { randomUUID, randomBytes } from 'crypto';\nimport * as jwt from 'jsonwebtoken';\nimport * as bcrypt from 'bcryptjs';\nimport { z } from 'zod';\nimport { AuthConfig, User, Session } from '../types/index.js';\nimport { Collection } from '../orm/Collection.js';\nimport { existsSync, readFileSync } from 'fs';\n\nconst UserSchema = z.object({\n email: z.string().email(),\n passwordHash: z.string(),\n roles: z.array(z.string()).default(['user']),\n metadata: z.record(z.unknown()).optional(),\n createdAt: z.string(),\n updatedAt: z.string(),\n});\n\n// TODO(security): Consider adding OAuth 2.0 provider support (e.g., Google, GitHub).\n// TODO(security): Consider adding MFA (TOTP/WebAuthn) for high-security deployments.\n// TODO(security): Consider adding pwned-password checking via haveibeenpwned.com API.\n\n/**\n * Resolve JWT secret with multi-tiered fallback:\n * 1. Explicit config value\n * 2. Environment variable\n * 3. Local jwt_secret.txt file\n * 4. Ephemeral random generation with warning (NOT suitable for multi-instance prod)\n *\n * MUST NOT hardcode or use default literal fallbacks.\n */\nfunction resolveJwtSecret(configSecret?: string): string {\n if (configSecret) return configSecret;\n if (process.env['JWT_SECRET']) return process.env['JWT_SECRET'];\n const secretFile = './jwt_secret.txt';\n if (existsSync(secretFile)) return readFileSync(secretFile, 'utf-8').trim();\n const ephemeral = randomBytes(32).toString('hex');\n console.warn(\n '[gramobase Auth] WARNING: No JWT_SECRET provided. Using an ephemeral random secret. ' +\n 'Tokens will be invalidated on restart. Set JWT_SECRET env variable for production!'\n );\n return ephemeral;\n}\n\n/**\n * Validate password strength (min 8 chars, no maximum).\n * Does not require specific character types — users choose their own strong passwords.\n */\nfunction validatePasswordStrength(password: string): void {\n if (password.length < 8) {\n throw new Error('[Auth] Password must be at least 8 characters long');\n }\n // TODO(security): Consider rejecting known breached passwords via HaveIBeenPwned API.\n}\n\nexport class GramoBaseAuth {\n private readonly DEFAULT_ROUNDS = 12;\n private readonly resolvedSecret: string;\n\n constructor(\n private users: Collection<typeof UserSchema>,\n private config: AuthConfig\n ) {\n // Resolve secret at construction time; fail safely if no secret available\n this.resolvedSecret = resolveJwtSecret(config.jwtSecret);\n }\n\n // ─── Registration ─────────────────────────────────────────────────────\n\n async register(\n email: string,\n password: string,\n roles: string[] = ['user'],\n metadata?: Record<string, unknown>\n ): Promise<{ user: User; session: Session }> {\n // Validate email format (basic — Zod schema handles full validation)\n if (!email || typeof email !== 'string') {\n throw new Error('[Auth] Invalid email');\n }\n\n // Validate password strength\n validatePasswordStrength(password);\n\n const existing = await this.users.findOne({ email: { $eq: email } } as any);\n if (existing) throw new Error('[Auth] Email already registered');\n\n const passwordHash = await bcrypt.hash(\n password,\n this.config.bcryptRounds ?? this.DEFAULT_ROUNDS\n );\n\n const now = new Date().toISOString();\n const doc = await this.users.insertOne({\n email,\n passwordHash,\n roles,\n metadata,\n createdAt: now,\n updatedAt: now,\n });\n\n const user = doc as unknown as User;\n const session = this.createSession(user);\n await this.config.onSignIn?.(user);\n\n return { user, session };\n }\n\n // ─── Login ────────────────────────────────────────────────────────────\n\n async login(email: string, password: string): Promise<{ user: User; session: Session }> {\n const doc = await this.users.findOne({ email: { $eq: email } } as any);\n if (!doc) {\n // Use constant-time comparison to avoid timing attacks on email existence\n await bcrypt.compare(password, '$2a$12$invalidhashtopreventtimingattacks');\n throw new Error('[Auth] Invalid credentials');\n }\n\n const user = doc as unknown as User;\n const valid = await bcrypt.compare(password, user.passwordHash);\n if (!valid) throw new Error('[Auth] Invalid credentials');\n\n const session = this.createSession(user);\n await this.config.onSignIn?.(user);\n\n return { user, session };\n }\n\n // ─── Token verification ───────────────────────────────────────────────\n\n verifyToken(token: string): Session {\n try {\n // Hardcode algorithm to prevent algorithm confusion attacks; reject 'none'\n const payload = jwt.verify(token, this.resolvedSecret, {\n algorithms: ['HS256'],\n }) as Session;\n return payload;\n } catch {\n throw new Error('[Auth] Invalid or expired token');\n }\n }\n\n // ─── Role-based access ────────────────────────────────────────────────\n\n requireRole(session: Session, role: string): void {\n if (!session.roles.includes(role) && !session.roles.includes('admin')) {\n throw new Error(`[Auth] Requires role: ${role}`);\n }\n }\n\n requireAnyRole(session: Session, roles: string[]): void {\n const hasRole = roles.some(\n (r) => session.roles.includes(r) || session.roles.includes('admin')\n );\n if (!hasRole) {\n throw new Error(`[Auth] Requires one of roles: ${roles.join(', ')}`);\n }\n }\n\n // ─── Password management ──────────────────────────────────────────────\n\n async changePassword(\n userId: string,\n oldPassword: string,\n newPassword: string\n ): Promise<void> {\n const doc = await this.users.findById(userId);\n if (!doc) throw new Error('[Auth] User not found');\n\n const user = doc as unknown as User;\n const valid = await bcrypt.compare(oldPassword, user.passwordHash);\n if (!valid) throw new Error('[Auth] Old password incorrect');\n\n // Validate new password strength\n validatePasswordStrength(newPassword);\n\n const newHash = await bcrypt.hash(\n newPassword,\n this.config.bcryptRounds ?? this.DEFAULT_ROUNDS\n );\n\n await this.users.findByIdAndUpdate(userId, {\n $set: { passwordHash: newHash, updatedAt: new Date().toISOString() } as any,\n });\n }\n\n async resetPassword(userId: string, newPassword: string): Promise<void> {\n validatePasswordStrength(newPassword);\n const newHash = await bcrypt.hash(\n newPassword,\n this.config.bcryptRounds ?? this.DEFAULT_ROUNDS\n );\n await this.users.findByIdAndUpdate(userId, {\n $set: { passwordHash: newHash, updatedAt: new Date().toISOString() } as any,\n });\n }\n\n // ─── User management ─────────────────────────────────────────────────\n\n async getUserById(id: string): Promise<User | null> {\n const doc = await this.users.findById(id);\n return doc ? (doc as unknown as User) : null;\n }\n\n async getUserByEmail(email: string): Promise<User | null> {\n const doc = await this.users.findOne({ email: { $eq: email } } as any);\n return doc ? (doc as unknown as User) : null;\n }\n\n async updateRoles(userId: string, roles: string[]): Promise<void> {\n await this.users.findByIdAndUpdate(userId, {\n $set: { roles, updatedAt: new Date().toISOString() } as any,\n });\n }\n\n async deleteUser(userId: string): Promise<void> {\n await this.users.deleteById(userId);\n await this.config.onSignOut?.(userId);\n }\n\n // ─── Session helpers ──────────────────────────────────────────────────\n\n private createSession(user: User): Session {\n const expiresIn = this.config.jwtExpiresIn ?? '7d';\n const payload: Omit<Session, 'token'> & { sub: string } = {\n sub: user._id,\n userId: user._id,\n roles: user.roles,\n expiresAt: Date.now() + this.parseExpiry(expiresIn),\n };\n\n // Sign with hardcoded HS256 algorithm; 'none' algorithm is never used\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const token = (jwt.sign as any)(payload, this.resolvedSecret, {\n expiresIn,\n algorithm: 'HS256',\n }) as string;\n return { ...payload, token };\n }\n\n private parseExpiry(s: string): number {\n const n = parseInt(s);\n if (s.endsWith('d')) return n * 86400_000;\n if (s.endsWith('h')) return n * 3600_000;\n if (s.endsWith('m')) return n * 60_000;\n return n * 1000;\n }\n\n // ─── Middleware factory (Express/Fastify compatible) ──────────────────\n\n middleware() {\n return (req: any, res: any, next: any) => {\n const auth = req.headers['authorization'] as string | undefined;\n if (!auth?.startsWith('Bearer ')) {\n return res.status(401).json({ error: 'Missing token' });\n }\n try {\n req.session = this.verifyToken(auth.slice(7));\n next();\n } catch {\n // Do NOT expose error details to client; log internally if needed\n res.status(401).json({ error: 'Unauthorized' });\n }\n };\n }\n\n requireRoleMiddleware(role: string) {\n return (req: any, res: any, next: any) => {\n try {\n this.requireRole(req.session, role);\n next();\n } catch {\n res.status(403).json({ error: 'Forbidden' });\n }\n };\n }\n}\n","import EventEmitter from 'eventemitter3';\nimport { GramoBaseEvent } from '../types/index.js';\nimport { BotWorkerPool } from '../workers/BotWorkerPool.js';\n\ntype Unsubscribe = () => void;\n\n/**\n * RealtimeManager bridges Telegram bot webhook / long-polling events\n * into a local EventEmitter that client code can subscribe to.\n *\n * Server-Sent Events (SSE) adapter included for HTTP streaming to browsers.\n */\nexport class RealtimeManager extends EventEmitter {\n private pollingActive = false;\n private pollingInterval: NodeJS.Timeout | null = null;\n private lastUpdateId = 0;\n\n constructor(\n private pool: BotWorkerPool,\n private webhookUrl?: string,\n private debug = false\n ) {\n super();\n }\n\n async start(): Promise<void> {\n if (this.webhookUrl) {\n await this.setupWebhook();\n } else {\n this.startPolling();\n }\n }\n\n async stop(): Promise<void> {\n if (this.pollingInterval) {\n clearInterval(this.pollingInterval);\n this.pollingInterval = null;\n }\n this.pollingActive = false;\n }\n\n // ─── Subscribe helpers ────────────────────────────────────────────────\n\n onInsert<T>(collection: string, cb: (doc: T) => void): Unsubscribe {\n const handler = (ev: GramoBaseEvent) => {\n if (ev.type === 'insert' && ev.collection === collection) {\n cb(ev.doc as T);\n }\n };\n this.on('event', handler);\n return () => this.off('event', handler);\n }\n\n onUpdate<T>(collection: string, cb: (id: string, changes: Partial<T>, doc: T) => void): Unsubscribe {\n const handler = (ev: GramoBaseEvent) => {\n if (ev.type === 'update' && ev.collection === collection) {\n cb(ev.id, ev.changes as Partial<T>, ev.doc as T);\n }\n };\n this.on('event', handler);\n return () => this.off('event', handler);\n }\n\n onDelete(collection: string, cb: (id: string) => void): Unsubscribe {\n const handler = (ev: GramoBaseEvent) => {\n if (ev.type === 'delete' && ev.collection === collection) {\n cb(ev.id);\n }\n };\n this.on('event', handler);\n return () => this.off('event', handler);\n }\n\n onAny(cb: (ev: GramoBaseEvent) => void): Unsubscribe {\n const handler = (ev: GramoBaseEvent) => cb(ev);\n this.on('event', handler);\n return () => this.off('event', handler);\n }\n\n // ─── SSE adapter ──────────────────────────────────────────────────────\n // Usage: app.get('/events', db.realtime.sseHandler())\n\n sseHandler(collection?: string) {\n return (req: any, res: any) => {\n res.setHeader('Content-Type', 'text/event-stream');\n res.setHeader('Cache-Control', 'no-cache, no-store');\n res.setHeader('Connection', 'keep-alive');\n res.setHeader('X-Content-Type-Options', 'nosniff');\n res.flushHeaders?.();\n\n const send = (ev: GramoBaseEvent) => {\n if (!collection || ('collection' in ev && ev.collection === collection)) {\n // JSON.stringify ensures proper output encoding — no raw user data in stream\n res.write(`data: ${JSON.stringify(ev)}\\n\\n`);\n }\n };\n\n this.on('event', send);\n const keepalive = setInterval(() => res.write(': ping\\n\\n'), 25_000);\n\n req.on('close', () => {\n this.off('event', send);\n clearInterval(keepalive);\n });\n };\n }\n\n // ─── Internal event dispatch ──────────────────────────────────────────\n\n dispatch(event: GramoBaseEvent): void {\n this.emit('event', event);\n if (this.debug) {\n // Only log event type — do NOT log event payload to avoid leaking sensitive data\n console.log('[Realtime]', event.type, 'collection' in event ? event.collection : '');\n }\n }\n\n // ─── Webhook setup ────────────────────────────────────────────────────\n\n private async setupWebhook(): Promise<void> {\n const bot = this.pool.getBot();\n await bot.setWebHook(this.webhookUrl!);\n if (this.debug) console.log('[Realtime] Webhook set');\n }\n\n // ─── Long polling fallback ────────────────────────────────────────────\n\n private startPolling(): void {\n this.pollingActive = true;\n const POLL_INTERVAL = 2000;\n\n this.pollingInterval = setInterval(async () => {\n try {\n const updates = await this.pool.execute((bot) =>\n bot.getUpdates({ offset: this.lastUpdateId + 1, limit: 100, timeout: 0 })\n ) as any[];\n\n for (const update of updates) {\n this.lastUpdateId = Math.max(this.lastUpdateId, update.update_id);\n this.processUpdate(update);\n }\n } catch {\n // Polling error — continue\n }\n }, POLL_INTERVAL);\n }\n\n private processUpdate(update: any): void {\n // Parse channel_post messages that are gramobase records\n const msg = update.channel_post ?? update.message;\n if (!msg?.text?.includes('\"__gramobase\"')) return;\n\n try {\n const payload = JSON.parse(msg.text);\n if (payload.__event) {\n this.dispatch(payload.__event as GramoBaseEvent);\n }\n } catch {\n // Not a gramobase event message\n }\n }\n}\n","import { Migration } from '../types/index.js';\nimport { BotWorkerPool } from '../workers/BotWorkerPool.js';\n\nconst MIGRATION_TAG = '__GRAMOBASE_MIGRATIONS__';\n\ninterface MigrationRecord {\n version: number;\n name: string;\n appliedAt: string;\n}\n\n/**\n * MigrationRunner stores a migration history message in the Telegram channel\n * and applies pending up() migrations in order.\n */\nexport class MigrationRunner {\n private historyMsgId: number | null = null;\n\n constructor(\n private pool: BotWorkerPool,\n private channelId: string,\n private debug = false\n ) {}\n\n async run(migrations: Migration[], db: unknown): Promise<void> {\n const applied = await this.loadHistory();\n const appliedVersions = new Set(applied.map((m) => m.version));\n\n const pending = migrations\n .filter((m) => !appliedVersions.has(m.version))\n .sort((a, b) => a.version - b.version);\n\n if (pending.length === 0) {\n if (this.debug) console.log('[Migrations] Nothing to run');\n return;\n }\n\n for (const migration of pending) {\n console.log(`[Migrations] Running: v${migration.version} — ${migration.name}`);\n await migration.up(db);\n applied.push({\n version: migration.version,\n name: migration.name,\n appliedAt: new Date().toISOString(),\n });\n await this.saveHistory(applied);\n console.log(`[Migrations] ✓ v${migration.version}`);\n }\n }\n\n async rollback(migrations: Migration[], db: unknown, steps = 1): Promise<void> {\n const applied = await this.loadHistory();\n const toRollback = applied\n .sort((a, b) => b.version - a.version)\n .slice(0, steps);\n\n for (const record of toRollback) {\n const migration = migrations.find((m) => m.version === record.version);\n if (!migration) throw new Error(`Migration v${record.version} not found`);\n\n console.log(`[Migrations] Rolling back: v${record.version} — ${record.name}`);\n await migration.down(db);\n applied.splice(applied.indexOf(record), 1);\n await this.saveHistory(applied);\n console.log(`[Migrations] ✓ Rolled back v${record.version}`);\n }\n }\n\n async status(migrations: Migration[]): Promise<void> {\n const applied = await this.loadHistory();\n const appliedVersions = new Set(applied.map((m) => m.version));\n\n console.log('\\n gramobase migration status\\n');\n for (const m of migrations.sort((a, b) => a.version - b.version)) {\n const status = appliedVersions.has(m.version) ? '✓' : '○';\n const appliedAt = applied.find((a) => a.version === m.version)?.appliedAt ?? '';\n console.log(` ${status} v${m.version} ${m.name.padEnd(40)} ${appliedAt}`);\n }\n console.log();\n }\n\n private async loadHistory(): Promise<MigrationRecord[]> {\n try {\n const chat = await this.pool.execute((bot) => bot.getChat(this.channelId)) as any;\n for (const msg of (chat.pinned_messages ?? [])) {\n if (msg.text?.startsWith(MIGRATION_TAG)) {\n this.historyMsgId = msg.message_id;\n return JSON.parse(msg.text.replace(MIGRATION_TAG + '\\n', ''));\n }\n }\n } catch {\n // No history yet\n }\n return [];\n }\n\n private async saveHistory(records: MigrationRecord[]): Promise<void> {\n const text = `${MIGRATION_TAG}\\n${JSON.stringify(records)}`;\n\n if (this.historyMsgId) {\n try {\n await this.pool.execute((bot) =>\n bot.editMessageText(text, {\n chat_id: this.channelId,\n message_id: this.historyMsgId!,\n })\n );\n return;\n } catch {}\n }\n\n const msg = await this.pool.execute((bot) =>\n bot.sendMessage(this.channelId, text, { disable_notification: true })\n ) as any;\n this.historyMsgId = msg.message_id;\n }\n}\n","import { z } from 'zod';\nimport { GramoBaseConfig, CollectionConfig, AuthConfig, UploadOptions, FileRecord, Migration, SchemaLike } from './types/index.js';\nimport { BotWorkerPool } from './workers/BotWorkerPool.js';\nimport { HotCache } from './cache/HotCache.js';\nimport { TelegramStorage } from './storage/TelegramStorage.js';\nimport { WriteAheadLog } from './wal/WriteAheadLog.js';\nimport { Registry } from './registry/Registry.js';\nimport { Collection } from './orm/Collection.js';\nimport { GramoBaseAuth } from './auth/GramoBaseAuth.js';\nimport { RealtimeManager } from './realtime/RealtimeManager.js';\nimport { MigrationRunner } from './migrations/MigrationRunner.js';\nimport { randomUUID } from 'crypto';\n\nexport class GramoBase {\n private pool: BotWorkerPool;\n private cache: HotCache;\n private storage: TelegramStorage;\n private wal: WriteAheadLog;\n readonly registry: Registry;\n readonly realtime: RealtimeManager;\n private migrations: MigrationRunner;\n private collections: Map<string, Collection<any>> = new Map();\n private initialized = false;\n private config: GramoBaseConfig;\n\n constructor(config: GramoBaseConfig) {\n this.config = config;\n const tokens = Array.isArray(config.botToken)\n ? config.botToken\n : [config.botToken];\n\n this.pool = new BotWorkerPool(tokens, config.concurrency ?? 25, config.debug ?? false);\n this.cache = new HotCache(config.cacheMaxBytes, config.cacheTtlMs);\n this.registry = new Registry(\n this.pool,\n config.indexChannelId ?? config.channelId,\n config.debug ?? false\n );\n this.storage = new TelegramStorage(\n this.pool,\n config.channelId,\n this.registry,\n config.encryptionKey,\n config.debug ?? false\n );\n this.wal = new WriteAheadLog(\n this.pool,\n config.walChannelId ?? config.channelId,\n config.debug ?? false\n );\n this.realtime = new RealtimeManager(\n this.pool,\n config.webhookUrl,\n config.debug ?? false\n );\n this.migrations = new MigrationRunner(\n this.pool,\n config.channelId,\n config.debug ?? false\n );\n\n // Bubble worker events\n this.pool.on('worker:rotate', (idx) => {\n this.realtime.dispatch({ type: 'worker:rotate', tokenIndex: idx });\n });\n this.pool.on('wal:flush', (count) => {\n this.realtime.dispatch({ type: 'wal:flush', entries: count });\n });\n }\n\n // ─── Lifecycle ────────────────────────────────────────────────────────\n\n async connect(): Promise<this> {\n if (this.initialized) return this;\n\n await this.wal.init();\n await this.registry.acquireWriteLease();\n await this.realtime.start();\n\n // WAL replay — recover any uncommitted writes\n const walEntries = await this.wal.replay();\n if (walEntries.length > 0 && this.config.debug) {\n console.log(`[gramobase] Replaying ${walEntries.length} WAL entries`);\n }\n\n this.initialized = true;\n if (this.config.debug) console.log('[gramobase] Connected ✓');\n return this;\n }\n\n async disconnect(): Promise<void> {\n await this.wal.flush();\n await this.registry.releaseWriteLease();\n await this.realtime.stop();\n await this.pool.destroy();\n this.initialized = false;\n }\n\n // ─── Collection factory ───────────────────────────────────────────────\n\n collection<T extends SchemaLike>(\n name: string,\n config: CollectionConfig<T>\n ): Collection<T> {\n if (this.collections.has(name)) {\n return this.collections.get(name) as Collection<T>;\n }\n const col = new Collection(\n name,\n config,\n this.cache,\n this.storage,\n this.wal,\n this.config.channelId\n );\n this.collections.set(name, col as Collection<any>);\n return col;\n }\n\n // ─── Auth factory ─────────────────────────────────────────────────────\n\n createAuth(config: AuthConfig): GramoBaseAuth {\n const UserSchema = z.object({\n email: z.string().email(),\n passwordHash: z.string(),\n roles: z.array(z.string()).default(['user']),\n metadata: z.record(z.unknown()).optional(),\n createdAt: z.string(),\n updatedAt: z.string(),\n });\n\n const users = this.collection('__gramobase_users__', { schema: UserSchema });\n return new GramoBaseAuth(users as any, config);\n }\n\n // ─── File storage ─────────────────────────────────────────────────────\n\n async uploadFile(\n data: Buffer,\n options: UploadOptions = {}\n ): Promise<FileRecord> {\n const { fileName = 'file', mimeType = 'application/octet-stream', metadata } = options;\n const channelId = this.config.channelId;\n\n const { fileId, msgId } = await this.storage.uploadFile(data, fileName, mimeType, channelId);\n const url = await this.storage.getFileUrl(fileId);\n\n const record: FileRecord = {\n _id: randomUUID(),\n fileId,\n fileName,\n mimeType,\n sizeBytes: data.length,\n uploadedAt: new Date().toISOString(),\n ...(url !== undefined ? { url } : {}),\n ...(metadata !== undefined ? { metadata } : {}),\n };\n\n // Store file record in a dedicated files collection\n const files = this.collection('__gramobase_files__', {\n schema: z.object({\n _id: z.string(),\n fileId: z.string(),\n fileName: z.string(),\n mimeType: z.string(),\n sizeBytes: z.number(),\n url: z.string().optional(),\n uploadedAt: z.string(),\n metadata: z.record(z.unknown()).optional(),\n }),\n });\n\n await (files as any).insertOne(record);\n return record;\n }\n\n async getFileUrl(fileId: string): Promise<string> {\n return this.storage.getFileUrl(fileId);\n }\n\n // ─── Migrations ───────────────────────────────────────────────────────\n\n async migrate(migrations: Migration[]): Promise<void> {\n await this.migrations.run(migrations, this);\n }\n\n async rollback(migrations: Migration[], steps = 1): Promise<void> {\n await this.migrations.rollback(migrations, this, steps);\n }\n\n async migrationStatus(migrations: Migration[]): Promise<void> {\n await this.migrations.status(migrations);\n }\n\n // ─── State helpers ────────────────────────────────────────────────────\n\n getCacheStats() {\n return this.cache.getStats();\n }\n\n getWorkerStats() {\n return this.pool.getStats();\n }\n\n getRegistryInstanceId(): string {\n return this.registry.getInstanceId();\n }\n\n /**\n * Warm up the cache by pre-loading all collection indexes.\n */\n async warmCache(): Promise<void> {\n for (const col of this.collections.values()) {\n await (col as any).ensureIndexLoaded();\n }\n }\n}\n\nconst globalForGramo = globalThis as unknown as { __gramobase_clients__?: Map<string, GramoBase> };\n\nexport function createClient(config: GramoBaseConfig): GramoBase {\n if (config.global) {\n if (!globalForGramo.__gramobase_clients__) {\n globalForGramo.__gramobase_clients__ = new Map();\n }\n const cacheKey = Array.isArray(config.botToken)\n ? `${config.channelId}:${config.botToken.join(',')}`\n : `${config.channelId}:${config.botToken}`;\n \n if (globalForGramo.__gramobase_clients__.has(cacheKey)) {\n return globalForGramo.__gramobase_clients__.get(cacheKey)!;\n }\n const client = new GramoBase(config);\n globalForGramo.__gramobase_clients__.set(cacheKey, client);\n return client;\n }\n return new GramoBase(config);\n}\n\n// Re-exports\nexport { GramoBaseAuth } from './auth/GramoBaseAuth.js';\nexport { Collection } from './orm/Collection.js';\nexport { RealtimeManager } from './realtime/RealtimeManager.js';\nexport type * from './types/index.js';\n","import * as http from 'http';\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport { getStudioHTML } from './ui.js';\nimport { createClient, GramoBase } from '../index.js';\nimport type { GramoBaseConfig } from '../types/index.js';\n\n// ─── Config Loader ────────────────────────────────────────────────────────────\n\nfunction loadEnvFile(cwd: string): Record<string, string> {\n const envPath = path.join(cwd, '.env');\n const env: Record<string, string> = {};\n if (!fs.existsSync(envPath)) return env;\n const lines = fs.readFileSync(envPath, 'utf-8').split('\\n');\n for (const raw of lines) {\n const line = raw.trim();\n if (!line || line.startsWith('#')) continue;\n const eq = line.indexOf('=');\n if (eq === -1) continue;\n const key = line.slice(0, eq).trim();\n const val = line.slice(eq + 1).trim().replace(/^[\"']|[\"']$/g, '');\n env[key] = val;\n }\n return env;\n}\n\nfunction resolveConfig(cwd: string): GramoBaseConfig | null {\n const env = loadEnvFile(cwd);\n\n // Merge with process.env (process.env takes precedence)\n const get = (k: string): string | undefined => process.env[k] || env[k];\n\n // Collect tokens\n const tokens: string[] = [];\n // First try single token\n const single = get('GRAMOBASE_BOT_TOKEN');\n if (single) tokens.push(single);\n // Then try indexed tokens\n let i = 1;\n while (true) {\n const t = get(`GRAMOBASE_BOT_TOKEN_${i}`);\n if (!t) break;\n if (!tokens.includes(t)) tokens.push(t);\n i++;\n }\n\n const channelId = get('GRAMOBASE_CHANNEL_ID');\n if (tokens.length === 0 || !channelId) return null;\n\n const encKey = get('GRAMOBASE_ENCRYPTION_KEY');\n return {\n botToken: tokens.length === 1 ? tokens[0]! : tokens,\n channelId,\n ...(encKey !== undefined ? { encryptionKey: encKey } : {}),\n cacheMaxBytes: 64 * 1024 * 1024,\n cacheTtlMs: 60_000,\n concurrency: 25,\n debug: false,\n };\n}\n\n// ─── JSON Response Helper ─────────────────────────────────────────────────────\n\nfunction jsonRes(res: http.ServerResponse, status: number, body: unknown) {\n const payload = JSON.stringify(body);\n res.writeHead(status, {\n 'Content-Type': 'application/json',\n 'Content-Length': Buffer.byteLength(payload),\n 'Access-Control-Allow-Origin': '*',\n });\n res.end(payload);\n}\n\n// ─── Route Parser ─────────────────────────────────────────────────────────────\n\nfunction parseUrl(rawUrl: string): { pathname: string; query: URLSearchParams } {\n const base = 'http://localhost';\n const url = new URL(rawUrl, base);\n return { pathname: url.pathname, query: url.searchParams };\n}\n\n// ─── Studio Server ────────────────────────────────────────────────────────────\n\nexport async function startStudio(port: number, cwd: string = process.cwd()) {\n const config = resolveConfig(cwd);\n let db: GramoBase | null = null;\n let botInfo: { username: string; firstName: string } | null = null;\n\n if (config) {\n try {\n db = await createClient(config).connect();\n // Fetch bot info from Telegram\n const token = Array.isArray(config.botToken) ? config.botToken[0] : config.botToken;\n try {\n const r = await fetch(`https://api.telegram.org/bot${token}/getMe`);\n const j = await r.json() as any;\n if (j.ok) botInfo = { username: j.result.username, firstName: j.result.first_name };\n } catch (_) {}\n } catch (e) {\n db = null;\n }\n }\n\n // Graceful shutdown handling\n const cleanShutdown = async () => {\n if (db) {\n try {\n await db.disconnect();\n } catch (_) {}\n db = null;\n }\n server.close(() => {\n process.exit(0);\n });\n // Fallback if close takes too long\n setTimeout(() => process.exit(0), 1000);\n };\n\n process.once('SIGINT', cleanShutdown);\n process.once('SIGTERM', cleanShutdown);\n\n // SSE client set\n const sseClients = new Set<http.ServerResponse>();\n\n // Listen to db realtime events and forward to SSE clients\n if (db) {\n const forward = (ev: unknown) => {\n const data = JSON.stringify(ev);\n sseClients.forEach(client => {\n try { client.write(`data: ${data}\\n\\n`); } catch (_) { sseClients.delete(client); }\n });\n };\n db.realtime.onInsert('*' as any, (doc: any) => forward({ type: 'insert', collection: doc._collection, doc }));\n db.realtime.onUpdate('*' as any, (id: any, changes: any, doc: any) => forward({ type: 'update', collection: doc?._collection, id, changes, doc }));\n db.realtime.onDelete('*' as any, (id: any) => forward({ type: 'delete', id }));\n }\n\n const server = http.createServer(async (req, res) => {\n const { pathname, query } = parseUrl(req.url || '/');\n\n // ── Serve UI ───────────────────────────────────────────────\n if (pathname === '/' || pathname === '/index.html') {\n const html = getStudioHTML();\n res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });\n res.end(html);\n return;\n }\n\n // ── SSE events stream ──────────────────────────────────────\n if (pathname === '/api/events') {\n res.writeHead(200, {\n 'Content-Type': 'text/event-stream',\n 'Cache-Control': 'no-cache',\n 'Connection': 'keep-alive',\n 'Access-Control-Allow-Origin': '*',\n });\n res.write(':\\n\\n'); // comment to establish connection\n sseClients.add(res);\n req.on('close', () => sseClients.delete(res));\n return;\n }\n\n // ── Status ─────────────────────────────────────────────────\n if (pathname === '/api/status') {\n if (!db || !config) {\n return jsonRes(res, 503, { error: 'Not connected. Check your .env file.' });\n }\n const cacheStats = db.getCacheStats();\n const workerStats = db.getWorkerStats();\n const colRes = await safeListCollections(db);\n return jsonRes(res, 200, {\n bot: botInfo,\n channelId: config.channelId,\n cache: cacheStats,\n workers: workerStats,\n collections: colRes,\n });\n }\n\n // ── Collections list ───────────────────────────────────────\n if (pathname === '/api/collections') {\n if (!db) return jsonRes(res, 503, { error: 'Not connected' });\n const cols = await safeListCollections(db);\n return jsonRes(res, 200, { collections: cols });\n }\n\n // ── Collection data ────────────────────────────────────────\n const colMatch = pathname.match(/^\\/api\\/collection\\/(.+)$/);\n if (colMatch) {\n if (!db) return jsonRes(res, 503, { error: 'Not connected' });\n const name = decodeURIComponent(colMatch[1] ?? '');\n\n // Guard: only alphanumeric / underscore / hyphen\n if (!/^[a-zA-Z0-9_\\-]+$/.test(name)) {\n return jsonRes(res, 400, { error: 'Invalid collection name' });\n }\n\n const page = Math.max(1, parseInt(query.get('page') || '1', 10));\n const limit = Math.min(100, Math.max(1, parseInt(query.get('limit') || '25', 10)));\n const skip = (page - 1) * limit;\n const sortFieldRaw = query.get('sortField') || '_createdAt';\n const sortDirRaw = parseInt(query.get('sortDir') || '-1', 10);\n\n // Sanitize sort field — only allow safe identifiers\n const sortField = /^[a-zA-Z0-9_.]+$/.test(sortFieldRaw) ? sortFieldRaw : '_createdAt';\n const sortDir = sortDirRaw === 1 ? 1 : -1;\n\n // Build filter from text query param\n const filterText = (query.get('filter') || '').trim();\n let filter: Record<string, unknown> = {};\n if (filterText) {\n // Try key:value syntax first\n const kv = filterText.match(/^([a-zA-Z0-9_.]+):(.+)$/);\n if (kv) {\n const [, k, v] = kv;\n const key = String(k ?? 'unknown');\n const num = Number(v ?? '');\n const filterVal = v === 'true' ? true : v === 'false' ? false : !isNaN(num) ? num : (v ?? '');\n filter = Object.fromEntries([[key, { $eq: filterVal }]]);\n } else {\n // text search via $regex on any string field (best-effort)\n filter = { $or: [{ text: { $regex: filterText } }, { name: { $regex: filterText } }, { title: { $regex: filterText } }] } as any;\n }\n }\n\n try {\n const { z } = await import('zod');\n const col = db.collection(name, { schema: z.record(z.unknown()) });\n const sort: Record<string, 1 | -1> = {};\n sort[sortField] = sortDir;\n const [docs, allDocs] = await Promise.all([\n (col as any).find({ filter, sort, limit, skip }),\n (col as any).count(filter),\n ]);\n\n // Discover columns from first few docs\n const colSet = new Set<string>();\n (docs as any[]).slice(0, 10).forEach((d: any) => Object.keys(d).forEach(k => colSet.add(k)));\n const columns = Array.from(colSet).filter(c => !['_id','_collection','_msgId','_createdAt','_updatedAt'].includes(c));\n\n return jsonRes(res, 200, { docs, total: allDocs, page, limit, columns });\n } catch (e: any) {\n return jsonRes(res, 500, { error: e.message || 'Query failed' });\n }\n }\n\n jsonRes(res, 404, { error: 'Not found' });\n });\n\n server.listen(port, '127.0.0.1', () => {});\n return server;\n}\n\n// ─── Safe collection discovery ────────────────────────────────────────────────\n\nasync function safeListCollections(db: GramoBase): Promise<Array<{ name: string; count: number }>> {\n try {\n // Access internal collection registry to discover known collections\n const registry = (db as any).collections as Map<string, unknown> | undefined;\n if (!registry) return [];\n const result: Array<{ name: string; count: number }> = [];\n for (const [name] of registry) {\n if (name.startsWith('__')) continue; // skip internal collections\n try {\n const col = (registry.get(name) as any);\n const count = await col.count({});\n result.push({ name, count });\n } catch (_) {\n result.push({ name, count: 0 });\n }\n }\n return result;\n } catch (_) {\n return [];\n }\n}\n"]}