@runtimescope/collector 0.7.2 → 0.9.0

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.
@@ -11,14 +11,14 @@ import {
11
11
  SqliteStore,
12
12
  isSqliteAvailable,
13
13
  resolveTlsConfig
14
- } from "./chunk-TUFSIGGJ.js";
14
+ } from "./chunk-HZWALDZM.js";
15
15
 
16
16
  // src/standalone.ts
17
17
  import { existsSync } from "fs";
18
18
  import { join } from "path";
19
19
  var HOST = process.env.RUNTIMESCOPE_HOST ?? "127.0.0.1";
20
- var COLLECTOR_PORT = parseInt(process.env.RUNTIMESCOPE_PORT ?? "9092", 10);
21
- var HTTP_PORT = parseInt(process.env.RUNTIMESCOPE_HTTP_PORT ?? "9093", 10);
20
+ var COLLECTOR_PORT = parseInt(process.env.RUNTIMESCOPE_PORT ?? "9090", 10);
21
+ var HTTP_PORT = parseInt(process.env.RUNTIMESCOPE_HTTP_PORT ?? "9091", 10);
22
22
  var BUFFER_SIZE = parseInt(process.env.RUNTIMESCOPE_BUFFER_SIZE ?? "10000", 10);
23
23
  var RETENTION_DAYS = parseInt(process.env.RUNTIMESCOPE_RETENTION_DAYS ?? "30", 10);
24
24
  async function main() {
@@ -106,6 +106,7 @@ async function main() {
106
106
  rateLimiter: collector.getRateLimiter(),
107
107
  pmStore,
108
108
  discovery,
109
+ projectManager,
109
110
  getConnectedSessions: () => collector.getConnectedSessions()
110
111
  });
111
112
  try {
@@ -113,8 +114,14 @@ async function main() {
113
114
  } catch (err) {
114
115
  console.error("[RuntimeScope] HTTP API failed to start:", err.message);
115
116
  }
116
- collector.onConnect((sessionId, projectName) => {
117
+ collector.onConnect((sessionId, projectName, projectId) => {
117
118
  httpServer.broadcastSessionChange("session_connected", sessionId, projectName);
119
+ if (pmStore) {
120
+ try {
121
+ pmStore.autoLinkApp(projectName, projectId);
122
+ } catch {
123
+ }
124
+ }
118
125
  });
119
126
  collector.onDisconnect((sessionId, projectName) => {
120
127
  httpServer.broadcastSessionChange("session_disconnected", sessionId, projectName);
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/standalone.ts"],"sourcesContent":["#!/usr/bin/env node\n\n// ============================================================\n// RuntimeScope Standalone Collector\n// Runs CollectorServer + HttpServer as a standalone service\n// without MCP, Playwright, or ProcessMonitor.\n//\n// Usage:\n// node dist/standalone.js\n// npx @runtimescope/collector\n// docker run runtimescope\n// ============================================================\n\nimport { existsSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { CollectorServer } from './server.js';\nimport { HttpServer } from './http-server.js';\nimport { ProjectManager } from './project-manager.js';\nimport { PmStore } from './pm/pm-store.js';\nimport { ProjectDiscovery } from './pm/project-discovery.js';\nimport { SessionManager } from './session-manager.js';\nimport { SqliteStore } from './sqlite-store.js';\nimport { isSqliteAvailable } from './sqlite-check.js';\nimport { AuthManager } from './auth.js';\nimport { Redactor } from './redactor.js';\nimport { resolveTlsConfig } from './tls.js';\n\nconst HOST = process.env.RUNTIMESCOPE_HOST ?? '127.0.0.1';\n// Standalone defaults to 9092/9093 to avoid conflicting with the MCP server (9090/9091)\nconst COLLECTOR_PORT = parseInt(process.env.RUNTIMESCOPE_PORT ?? '9092', 10);\nconst HTTP_PORT = parseInt(process.env.RUNTIMESCOPE_HTTP_PORT ?? '9093', 10);\nconst BUFFER_SIZE = parseInt(process.env.RUNTIMESCOPE_BUFFER_SIZE ?? '10000', 10);\nconst RETENTION_DAYS = parseInt(process.env.RUNTIMESCOPE_RETENTION_DAYS ?? '30', 10);\n\nasync function main() {\n console.error('[RuntimeScope] Starting standalone collector...');\n\n // 1. Initialize project management + config\n const projectManager = new ProjectManager();\n projectManager.ensureGlobalDir();\n const globalConfig = projectManager.getGlobalConfig();\n\n // 2. Security: auth, TLS, redaction, CORS\n const authManager = new AuthManager({\n enabled: globalConfig.auth?.enabled ?? false,\n apiKeys: globalConfig.auth?.apiKeys ?? [],\n });\n\n const tlsConfig = resolveTlsConfig() ?? globalConfig.tls ?? undefined;\n\n const redactor = new Redactor({\n enabled: globalConfig.redaction?.enabled ?? false,\n useBuiltIn: true,\n rules: globalConfig.redaction?.rules?.map(r => ({\n name: r.name,\n pattern: new RegExp(r.pattern, 'gi'),\n replacement: r.replacement,\n })),\n });\n\n const corsOrigins = process.env.RUNTIMESCOPE_CORS_ORIGINS?.split(',').map(s => s.trim())\n ?? globalConfig.corsOrigins;\n\n if (authManager.isEnabled()) {\n console.error(`[RuntimeScope] Auth enabled (${globalConfig.auth?.apiKeys?.length ?? 0} API keys)`);\n }\n if (tlsConfig) {\n console.error(`[RuntimeScope] TLS enabled (cert: ${tlsConfig.certPath})`);\n }\n if (redactor.isEnabled()) {\n console.error('[RuntimeScope] Payload redaction enabled');\n }\n\n // 3. Start collector WebSocket server\n const collector = new CollectorServer({\n bufferSize: BUFFER_SIZE,\n projectManager,\n authManager,\n rateLimits: globalConfig.rateLimits,\n tls: tlsConfig,\n });\n await collector.start({ port: COLLECTOR_PORT, host: HOST, maxRetries: 5, retryDelayMs: 1000 });\n\n const store = collector.getStore();\n\n // Wire redactor for defense-in-depth\n if (redactor.isEnabled()) {\n store.setRedactor(redactor);\n }\n\n // 4. Session management — auto-snapshot on disconnect\n const sqliteStores = collector.getSqliteStores();\n const sessionManager = new SessionManager(projectManager, sqliteStores, store);\n\n collector.onDisconnect((sessionId, projectName) => {\n try {\n sessionManager.createSnapshot(sessionId, projectName);\n console.error(`[RuntimeScope] Session ${sessionId} metrics saved`);\n } catch {\n // Non-fatal\n }\n });\n\n // 5. Retention pruning (only if SQLite is available)\n if (isSqliteAvailable()) {\n const cutoffMs = Date.now() - RETENTION_DAYS * 24 * 60 * 60 * 1000;\n for (const projectName of projectManager.listProjects()) {\n const dbPath = projectManager.getProjectDbPath(projectName);\n if (existsSync(dbPath)) {\n try {\n const tempStore = new SqliteStore({ dbPath });\n const deleted = tempStore.deleteOldEvents(cutoffMs);\n if (deleted > 0) {\n console.error(`[RuntimeScope] Pruned ${deleted} events older than ${RETENTION_DAYS}d from \"${projectName}\"`);\n }\n tempStore.close();\n } catch {\n // Non-fatal\n }\n }\n }\n }\n\n // 6. Project Management layer (requires SQLite)\n let pmStore: PmStore | undefined;\n let discovery: ProjectDiscovery | undefined;\n\n if (isSqliteAvailable()) {\n const pmDbPath = join(projectManager.rootDir, 'pm.db');\n pmStore = new PmStore({ dbPath: pmDbPath });\n discovery = new ProjectDiscovery(pmStore, projectManager);\n\n // Run discovery in background (non-blocking)\n discovery.discoverAll().then((result) => {\n console.error(`[RuntimeScope] PM: ${result.projectsDiscovered} projects, ${result.sessionsDiscovered} sessions discovered`);\n }).catch((err) => {\n console.error('[RuntimeScope] PM discovery error:', (err as Error).message);\n });\n }\n\n // 7. Start HTTP API server (with POST /api/events + PM routes)\n const httpServer = new HttpServer(store, undefined, {\n authManager,\n allowedOrigins: corsOrigins,\n rateLimiter: collector.getRateLimiter(),\n pmStore,\n discovery,\n getConnectedSessions: () => collector.getConnectedSessions(),\n });\n\n try {\n await httpServer.start({ port: HTTP_PORT, host: HOST, tls: tlsConfig });\n } catch (err) {\n console.error('[RuntimeScope] HTTP API failed to start:', (err as Error).message);\n }\n\n // Push session connect/disconnect to dashboard in real-time\n collector.onConnect((sessionId, projectName) => {\n httpServer.broadcastSessionChange('session_connected', sessionId, projectName);\n });\n collector.onDisconnect((sessionId, projectName) => {\n httpServer.broadcastSessionChange('session_disconnected', sessionId, projectName);\n });\n\n // 7. Startup summary\n const proto = tlsConfig ? 'wss' : 'ws';\n const httpProto = tlsConfig ? 'https' : 'http';\n console.error(`[RuntimeScope] Standalone collector ready`);\n console.error(`[RuntimeScope] WebSocket: ${proto}://${HOST}:${COLLECTOR_PORT}`);\n console.error(`[RuntimeScope] HTTP API: ${httpProto}://${HOST}:${HTTP_PORT}`);\n console.error(`[RuntimeScope] Health: ${httpProto}://${HOST}:${HTTP_PORT}/api/health`);\n console.error(`[RuntimeScope] Ingest: POST ${httpProto}://${HOST}:${HTTP_PORT}/api/events`);\n\n // 8. Graceful shutdown\n let shuttingDown = false;\n const shutdown = async () => {\n if (shuttingDown) return;\n shuttingDown = true;\n console.error('[RuntimeScope] Shutting down...');\n\n await httpServer.stop();\n collector.stop();\n pmStore?.close();\n\n process.exit(0);\n };\n\n process.on('SIGINT', () => { shutdown(); });\n process.on('SIGTERM', () => { shutdown(); });\n}\n\nmain().catch((err) => {\n console.error('[RuntimeScope] Fatal error:', err);\n process.exit(1);\n});\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/standalone.ts"],"sourcesContent":["#!/usr/bin/env node\n\n// ============================================================\n// RuntimeScope Standalone Collector\n// Runs CollectorServer + HttpServer as a standalone service\n// without MCP, Playwright, or ProcessMonitor.\n//\n// Usage:\n// node dist/standalone.js\n// npx @runtimescope/collector\n// docker run runtimescope\n// ============================================================\n\nimport { existsSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { CollectorServer } from './server.js';\nimport { HttpServer } from './http-server.js';\nimport { ProjectManager } from './project-manager.js';\nimport { PmStore } from './pm/pm-store.js';\nimport { ProjectDiscovery } from './pm/project-discovery.js';\nimport { SessionManager } from './session-manager.js';\nimport { SqliteStore } from './sqlite-store.js';\nimport { isSqliteAvailable } from './sqlite-check.js';\nimport { AuthManager } from './auth.js';\nimport { Redactor } from './redactor.js';\nimport { resolveTlsConfig } from './tls.js';\n\nconst HOST = process.env.RUNTIMESCOPE_HOST ?? '127.0.0.1';\n// Same default ports as MCP server — only one should run at a time\nconst COLLECTOR_PORT = parseInt(process.env.RUNTIMESCOPE_PORT ?? '9090', 10);\nconst HTTP_PORT = parseInt(process.env.RUNTIMESCOPE_HTTP_PORT ?? '9091', 10);\nconst BUFFER_SIZE = parseInt(process.env.RUNTIMESCOPE_BUFFER_SIZE ?? '10000', 10);\nconst RETENTION_DAYS = parseInt(process.env.RUNTIMESCOPE_RETENTION_DAYS ?? '30', 10);\n\nasync function main() {\n console.error('[RuntimeScope] Starting standalone collector...');\n\n // 1. Initialize project management + config\n const projectManager = new ProjectManager();\n projectManager.ensureGlobalDir();\n const globalConfig = projectManager.getGlobalConfig();\n\n // 2. Security: auth, TLS, redaction, CORS\n const authManager = new AuthManager({\n enabled: globalConfig.auth?.enabled ?? false,\n apiKeys: globalConfig.auth?.apiKeys ?? [],\n });\n\n const tlsConfig = resolveTlsConfig() ?? globalConfig.tls ?? undefined;\n\n const redactor = new Redactor({\n enabled: globalConfig.redaction?.enabled ?? false,\n useBuiltIn: true,\n rules: globalConfig.redaction?.rules?.map(r => ({\n name: r.name,\n pattern: new RegExp(r.pattern, 'gi'),\n replacement: r.replacement,\n })),\n });\n\n const corsOrigins = process.env.RUNTIMESCOPE_CORS_ORIGINS?.split(',').map(s => s.trim())\n ?? globalConfig.corsOrigins;\n\n if (authManager.isEnabled()) {\n console.error(`[RuntimeScope] Auth enabled (${globalConfig.auth?.apiKeys?.length ?? 0} API keys)`);\n }\n if (tlsConfig) {\n console.error(`[RuntimeScope] TLS enabled (cert: ${tlsConfig.certPath})`);\n }\n if (redactor.isEnabled()) {\n console.error('[RuntimeScope] Payload redaction enabled');\n }\n\n // 3. Start collector WebSocket server\n const collector = new CollectorServer({\n bufferSize: BUFFER_SIZE,\n projectManager,\n authManager,\n rateLimits: globalConfig.rateLimits,\n tls: tlsConfig,\n });\n await collector.start({ port: COLLECTOR_PORT, host: HOST, maxRetries: 5, retryDelayMs: 1000 });\n\n const store = collector.getStore();\n\n // Wire redactor for defense-in-depth\n if (redactor.isEnabled()) {\n store.setRedactor(redactor);\n }\n\n // 4. Session management — auto-snapshot on disconnect\n const sqliteStores = collector.getSqliteStores();\n const sessionManager = new SessionManager(projectManager, sqliteStores, store);\n\n collector.onDisconnect((sessionId, projectName) => {\n try {\n sessionManager.createSnapshot(sessionId, projectName);\n console.error(`[RuntimeScope] Session ${sessionId} metrics saved`);\n } catch {\n // Non-fatal\n }\n });\n\n // 5. Retention pruning (only if SQLite is available)\n if (isSqliteAvailable()) {\n const cutoffMs = Date.now() - RETENTION_DAYS * 24 * 60 * 60 * 1000;\n for (const projectName of projectManager.listProjects()) {\n const dbPath = projectManager.getProjectDbPath(projectName);\n if (existsSync(dbPath)) {\n try {\n const tempStore = new SqliteStore({ dbPath });\n const deleted = tempStore.deleteOldEvents(cutoffMs);\n if (deleted > 0) {\n console.error(`[RuntimeScope] Pruned ${deleted} events older than ${RETENTION_DAYS}d from \"${projectName}\"`);\n }\n tempStore.close();\n } catch {\n // Non-fatal\n }\n }\n }\n }\n\n // 6. Project Management layer (requires SQLite)\n let pmStore: PmStore | undefined;\n let discovery: ProjectDiscovery | undefined;\n\n if (isSqliteAvailable()) {\n const pmDbPath = join(projectManager.rootDir, 'pm.db');\n pmStore = new PmStore({ dbPath: pmDbPath });\n discovery = new ProjectDiscovery(pmStore, projectManager);\n\n // Run discovery in background (non-blocking)\n discovery.discoverAll().then((result) => {\n console.error(`[RuntimeScope] PM: ${result.projectsDiscovered} projects, ${result.sessionsDiscovered} sessions discovered`);\n }).catch((err) => {\n console.error('[RuntimeScope] PM discovery error:', (err as Error).message);\n });\n }\n\n // 7. Start HTTP API server (with POST /api/events + PM routes)\n const httpServer = new HttpServer(store, undefined, {\n authManager,\n allowedOrigins: corsOrigins,\n rateLimiter: collector.getRateLimiter(),\n pmStore,\n discovery,\n projectManager,\n getConnectedSessions: () => collector.getConnectedSessions(),\n });\n\n try {\n await httpServer.start({ port: HTTP_PORT, host: HOST, tls: tlsConfig });\n } catch (err) {\n console.error('[RuntimeScope] HTTP API failed to start:', (err as Error).message);\n }\n\n // Push session connect/disconnect to dashboard in real-time\n collector.onConnect((sessionId, projectName, projectId) => {\n httpServer.broadcastSessionChange('session_connected', sessionId, projectName);\n // Auto-link SDK appName to PM project\n if (pmStore) {\n try { pmStore.autoLinkApp(projectName, projectId); } catch { /* non-fatal */ }\n }\n });\n collector.onDisconnect((sessionId, projectName) => {\n httpServer.broadcastSessionChange('session_disconnected', sessionId, projectName);\n });\n\n // 7. Startup summary\n const proto = tlsConfig ? 'wss' : 'ws';\n const httpProto = tlsConfig ? 'https' : 'http';\n console.error(`[RuntimeScope] Standalone collector ready`);\n console.error(`[RuntimeScope] WebSocket: ${proto}://${HOST}:${COLLECTOR_PORT}`);\n console.error(`[RuntimeScope] HTTP API: ${httpProto}://${HOST}:${HTTP_PORT}`);\n console.error(`[RuntimeScope] Health: ${httpProto}://${HOST}:${HTTP_PORT}/api/health`);\n console.error(`[RuntimeScope] Ingest: POST ${httpProto}://${HOST}:${HTTP_PORT}/api/events`);\n\n // 8. Graceful shutdown\n let shuttingDown = false;\n const shutdown = async () => {\n if (shuttingDown) return;\n shuttingDown = true;\n console.error('[RuntimeScope] Shutting down...');\n\n await httpServer.stop();\n collector.stop();\n pmStore?.close();\n\n process.exit(0);\n };\n\n process.on('SIGINT', () => { shutdown(); });\n process.on('SIGTERM', () => { shutdown(); });\n}\n\nmain().catch((err) => {\n console.error('[RuntimeScope] Fatal error:', err);\n process.exit(1);\n});\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@runtimescope/collector",
3
- "version": "0.7.2",
3
+ "version": "0.9.0",
4
4
  "description": "Event collector and persistence layer for RuntimeScope",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -26,9 +26,11 @@
26
26
  "test:watch": "vitest"
27
27
  },
28
28
  "dependencies": {
29
- "better-sqlite3": "^11.0.0",
30
29
  "ws": "^8.16.0"
31
30
  },
31
+ "optionalDependencies": {
32
+ "better-sqlite3": "^11.0.0"
33
+ },
32
34
  "devDependencies": {
33
35
  "@types/better-sqlite3": "^7.6.8",
34
36
  "@types/ws": "^8.5.10",