feat(streaming): add real-time streaming (MongoDB change streams & S3 bucket watchers) with WebSocket subscriptions and activity stream UI

This commit is contained in:
2026-01-25 21:41:55 +00:00
parent c60cbf5215
commit 20e08d123f
23 changed files with 2456 additions and 19 deletions

View File

@@ -1,11 +1,11 @@
import * as plugins from '../plugins.js';
import { apiService } from '../services/index.js';
import { apiService, changeStreamService } from '../services/index.js';
import { themeStyles } from '../styles/index.js';
const { html, css, cssManager, customElement, state, DeesElement } = plugins;
const { DeesContextmenu } = plugins.deesCatalog;
type TViewMode = 's3' | 'mongo' | 'settings';
type TViewMode = 's3' | 'mongo' | 'activity' | 'settings';
@customElement('tsview-app')
export class TsviewApp extends DeesElement {
@@ -422,6 +422,17 @@ export class TsviewApp extends DeesElement {
async connectedCallback() {
super.connectedCallback();
await this.loadData();
// Initialize WebSocket connection for real-time updates
this.initializeChangeStream();
}
private async initializeChangeStream() {
try {
await changeStreamService.connect();
console.log('[TsviewApp] ChangeStream connected');
} catch (error) {
console.warn('[TsviewApp] Failed to connect to ChangeStream:', error);
}
}
private async loadData() {
@@ -729,6 +740,12 @@ export class TsviewApp extends DeesElement {
>
MongoDB
</button>
<button
class="nav-tab ${this.viewMode === 'activity' ? 'active' : ''}"
@click=${() => this.setViewMode('activity')}
>
Activity
</button>
<button
class="nav-tab ${this.viewMode === 'settings' ? 'active' : ''}"
@click=${() => this.setViewMode('settings')}
@@ -940,6 +957,19 @@ export class TsviewApp extends DeesElement {
`;
}
if (this.viewMode === 'activity') {
return html`
<aside class="sidebar">
<div class="sidebar-header">Activity Stream</div>
<div class="sidebar-list">
<div class="sidebar-item" style="color: #888; font-size: 12px; cursor: default;">
Real-time changes from MongoDB and S3 appear here automatically.
</div>
</div>
</aside>
`;
}
return html`
<aside class="sidebar">
<div class="sidebar-header">Settings</div>
@@ -1048,6 +1078,17 @@ export class TsviewApp extends DeesElement {
`;
}
if (this.viewMode === 'activity') {
return html`
<div class="content-area" style="padding: 0;">
<tsview-activity-stream
@navigate-to-mongo=${this.handleNavigateToMongo}
@navigate-to-s3=${this.handleNavigateToS3}
></tsview-activity-stream>
</div>
`;
}
return html`
<div class="content-area">
<h2>Settings</h2>
@@ -1055,4 +1096,21 @@ export class TsviewApp extends DeesElement {
</div>
`;
}
private handleNavigateToMongo(e: CustomEvent) {
const { database, collection, documentId } = e.detail;
this.viewMode = 'mongo';
this.selectedDatabase = database;
this.selectedCollection = collection;
// If documentId is provided, we could potentially scroll to or highlight that document
// For now, just navigate to the collection
}
private handleNavigateToS3(e: CustomEvent) {
const { bucket, key } = e.detail;
this.viewMode = 's3';
this.selectedBucket = bucket;
// The S3 browser will need to be updated to navigate to the specific key
// For now, just navigate to the bucket
}
}