@runtimescope/server-sdk 0.6.1 → 0.7.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.
package/dist/index.d.cts CHANGED
@@ -69,6 +69,8 @@ interface PerformanceEvent {
69
69
  type ServerRuntimeEvent = DatabaseEvent | ConsoleEvent | NetworkEvent | PerformanceEvent;
70
70
  interface ServerSdkConfig {
71
71
  serverUrl?: string;
72
+ /** Alias for serverUrl — matches the browser SDK's config */
73
+ endpoint?: string;
72
74
  appName?: string;
73
75
  sessionId?: string;
74
76
  /** API key for authenticated connections to the collector */
@@ -89,6 +91,12 @@ interface ServerSdkConfig {
89
91
  sampleRate?: number;
90
92
  maxEventsPerSecond?: number;
91
93
  maxQueueSize?: number;
94
+ /** Transport type: 'ws' (WebSocket, default) or 'http' (HTTP POST for serverless) */
95
+ transport?: 'ws' | 'http';
96
+ /** HTTP endpoint URL for HTTP transport (e.g., 'http://collector:9091/api/events') */
97
+ httpEndpoint?: string;
98
+ /** HTTP batch flush interval in ms (default: 1000) */
99
+ httpFlushIntervalMs?: number;
92
100
  }
93
101
 
94
102
  type EmitFn = (event: NetworkEvent) => void;
@@ -160,12 +168,46 @@ declare class Sampler {
160
168
  reset(): void;
161
169
  }
162
170
 
171
+ interface HttpTransportOptions {
172
+ url: string;
173
+ sessionId: string;
174
+ appName: string;
175
+ sdkVersion: string;
176
+ authToken?: string;
177
+ maxQueueSize?: number;
178
+ flushIntervalMs?: number;
179
+ maxRetries?: number;
180
+ retryDelayMs?: number;
181
+ }
182
+ declare class HttpTransport {
183
+ private queue;
184
+ private url;
185
+ private sessionId;
186
+ private appName;
187
+ private sdkVersion;
188
+ private authToken;
189
+ private maxQueueSize;
190
+ private maxRetries;
191
+ private retryDelayMs;
192
+ private flushTimer;
193
+ private _droppedCount;
194
+ private sessionRegistered;
195
+ constructor(options: HttpTransportOptions);
196
+ get droppedCount(): number;
197
+ sendEvent(event: ServerRuntimeEvent): void;
198
+ flush(): Promise<void>;
199
+ disconnect(): Promise<void>;
200
+ }
201
+
163
202
  declare class RuntimeScopeServer {
164
203
  private transport;
204
+ private httpTransport;
165
205
  private sessionId;
166
206
  private config;
167
207
  private sampler;
168
208
  private restoreFunctions;
209
+ /** Alias for `connect` — mirrors the browser SDK's init() API */
210
+ init(config?: ServerSdkConfig): void;
169
211
  connect(config?: ServerSdkConfig): void;
170
212
  disconnect(): void;
171
213
  get currentSessionId(): string;
@@ -183,4 +225,4 @@ declare class RuntimeScopeServer {
183
225
  }
184
226
  declare const RuntimeScope: RuntimeScopeServer;
185
227
 
186
- export { type ConsoleEvent, type DatabaseEvent, type MetricUnit, type NetworkEvent, type PerformanceEvent, RuntimeScope, Sampler, type ServerMetricName, type ServerRuntimeEvent, type ServerSdkConfig, _log, generateId, generateSessionId, getRequestContext, getSessionId, normalizeQuery, parseOperation, parseTablesAccessed, redactParams, runWithContext, runtimeScopeMiddleware };
228
+ export { type ConsoleEvent, type DatabaseEvent, HttpTransport, type HttpTransportOptions, type MetricUnit, type NetworkEvent, type PerformanceEvent, RuntimeScope, Sampler, type ServerMetricName, type ServerRuntimeEvent, type ServerSdkConfig, _log, generateId, generateSessionId, getRequestContext, getSessionId, normalizeQuery, parseOperation, parseTablesAccessed, redactParams, runWithContext, runtimeScopeMiddleware };
package/dist/index.d.ts CHANGED
@@ -69,6 +69,8 @@ interface PerformanceEvent {
69
69
  type ServerRuntimeEvent = DatabaseEvent | ConsoleEvent | NetworkEvent | PerformanceEvent;
70
70
  interface ServerSdkConfig {
71
71
  serverUrl?: string;
72
+ /** Alias for serverUrl — matches the browser SDK's config */
73
+ endpoint?: string;
72
74
  appName?: string;
73
75
  sessionId?: string;
74
76
  /** API key for authenticated connections to the collector */
@@ -89,6 +91,12 @@ interface ServerSdkConfig {
89
91
  sampleRate?: number;
90
92
  maxEventsPerSecond?: number;
91
93
  maxQueueSize?: number;
94
+ /** Transport type: 'ws' (WebSocket, default) or 'http' (HTTP POST for serverless) */
95
+ transport?: 'ws' | 'http';
96
+ /** HTTP endpoint URL for HTTP transport (e.g., 'http://collector:9091/api/events') */
97
+ httpEndpoint?: string;
98
+ /** HTTP batch flush interval in ms (default: 1000) */
99
+ httpFlushIntervalMs?: number;
92
100
  }
93
101
 
94
102
  type EmitFn = (event: NetworkEvent) => void;
@@ -160,12 +168,46 @@ declare class Sampler {
160
168
  reset(): void;
161
169
  }
162
170
 
171
+ interface HttpTransportOptions {
172
+ url: string;
173
+ sessionId: string;
174
+ appName: string;
175
+ sdkVersion: string;
176
+ authToken?: string;
177
+ maxQueueSize?: number;
178
+ flushIntervalMs?: number;
179
+ maxRetries?: number;
180
+ retryDelayMs?: number;
181
+ }
182
+ declare class HttpTransport {
183
+ private queue;
184
+ private url;
185
+ private sessionId;
186
+ private appName;
187
+ private sdkVersion;
188
+ private authToken;
189
+ private maxQueueSize;
190
+ private maxRetries;
191
+ private retryDelayMs;
192
+ private flushTimer;
193
+ private _droppedCount;
194
+ private sessionRegistered;
195
+ constructor(options: HttpTransportOptions);
196
+ get droppedCount(): number;
197
+ sendEvent(event: ServerRuntimeEvent): void;
198
+ flush(): Promise<void>;
199
+ disconnect(): Promise<void>;
200
+ }
201
+
163
202
  declare class RuntimeScopeServer {
164
203
  private transport;
204
+ private httpTransport;
165
205
  private sessionId;
166
206
  private config;
167
207
  private sampler;
168
208
  private restoreFunctions;
209
+ /** Alias for `connect` — mirrors the browser SDK's init() API */
210
+ init(config?: ServerSdkConfig): void;
169
211
  connect(config?: ServerSdkConfig): void;
170
212
  disconnect(): void;
171
213
  get currentSessionId(): string;
@@ -183,4 +225,4 @@ declare class RuntimeScopeServer {
183
225
  }
184
226
  declare const RuntimeScope: RuntimeScopeServer;
185
227
 
186
- export { type ConsoleEvent, type DatabaseEvent, type MetricUnit, type NetworkEvent, type PerformanceEvent, RuntimeScope, Sampler, type ServerMetricName, type ServerRuntimeEvent, type ServerSdkConfig, _log, generateId, generateSessionId, getRequestContext, getSessionId, normalizeQuery, parseOperation, parseTablesAccessed, redactParams, runWithContext, runtimeScopeMiddleware };
228
+ export { type ConsoleEvent, type DatabaseEvent, HttpTransport, type HttpTransportOptions, type MetricUnit, type NetworkEvent, type PerformanceEvent, RuntimeScope, Sampler, type ServerMetricName, type ServerRuntimeEvent, type ServerSdkConfig, _log, generateId, generateSessionId, getRequestContext, getSessionId, normalizeQuery, parseOperation, parseTablesAccessed, redactParams, runWithContext, runtimeScopeMiddleware };
package/dist/index.js CHANGED
@@ -128,6 +128,94 @@ var ServerTransport = class {
128
128
  }
129
129
  };
130
130
 
131
+ // src/http-transport.ts
132
+ var HttpTransport = class {
133
+ queue = [];
134
+ url;
135
+ sessionId;
136
+ appName;
137
+ sdkVersion;
138
+ authToken;
139
+ maxQueueSize;
140
+ maxRetries;
141
+ retryDelayMs;
142
+ flushTimer = null;
143
+ _droppedCount = 0;
144
+ sessionRegistered = false;
145
+ constructor(options) {
146
+ this.url = options.url;
147
+ this.sessionId = options.sessionId;
148
+ this.appName = options.appName;
149
+ this.sdkVersion = options.sdkVersion;
150
+ this.authToken = options.authToken;
151
+ this.maxQueueSize = options.maxQueueSize ?? 1e4;
152
+ this.maxRetries = options.maxRetries ?? 2;
153
+ this.retryDelayMs = options.retryDelayMs ?? 500;
154
+ const intervalMs = options.flushIntervalMs ?? 1e3;
155
+ this.flushTimer = setInterval(() => this.flush(), intervalMs);
156
+ if (this.flushTimer && typeof this.flushTimer === "object" && "unref" in this.flushTimer) {
157
+ this.flushTimer.unref();
158
+ }
159
+ }
160
+ get droppedCount() {
161
+ return this._droppedCount;
162
+ }
163
+ sendEvent(event) {
164
+ if (this.queue.length >= this.maxQueueSize) {
165
+ this.queue.shift();
166
+ this._droppedCount++;
167
+ }
168
+ this.queue.push(event);
169
+ }
170
+ async flush() {
171
+ if (this.queue.length === 0) return;
172
+ const batch = this.queue.splice(0);
173
+ const payload = {
174
+ sessionId: this.sessionId,
175
+ events: batch
176
+ };
177
+ if (!this.sessionRegistered) {
178
+ payload.appName = this.appName;
179
+ payload.sdkVersion = this.sdkVersion;
180
+ }
181
+ const body = JSON.stringify(payload);
182
+ for (let attempt = 0; attempt <= this.maxRetries; attempt++) {
183
+ try {
184
+ const headers = {
185
+ "Content-Type": "application/json"
186
+ };
187
+ if (this.authToken) {
188
+ headers["Authorization"] = `Bearer ${this.authToken}`;
189
+ }
190
+ const response = await fetch(this.url, {
191
+ method: "POST",
192
+ headers,
193
+ body,
194
+ signal: AbortSignal.timeout(5e3)
195
+ });
196
+ if (response.ok) {
197
+ this.sessionRegistered = true;
198
+ return;
199
+ }
200
+ if (response.status === 401 || response.status === 400) {
201
+ return;
202
+ }
203
+ } catch {
204
+ }
205
+ if (attempt < this.maxRetries) {
206
+ await new Promise((r) => setTimeout(r, this.retryDelayMs));
207
+ }
208
+ }
209
+ }
210
+ async disconnect() {
211
+ if (this.flushTimer) {
212
+ clearInterval(this.flushTimer);
213
+ this.flushTimer = null;
214
+ }
215
+ await this.flush();
216
+ }
217
+ };
218
+
131
219
  // src/utils/id.ts
132
220
  import { randomBytes } from "crypto";
133
221
  function generateId() {
@@ -1351,26 +1439,51 @@ function runtimeScopeMiddleware(emit, sessionId, options) {
1351
1439
  }
1352
1440
 
1353
1441
  // src/index.ts
1354
- var SDK_VERSION = "0.6.1";
1442
+ var SDK_VERSION = "0.7.0";
1355
1443
  var RuntimeScopeServer = class {
1356
1444
  transport = null;
1445
+ httpTransport = null;
1357
1446
  sessionId = "";
1358
1447
  config = {};
1359
1448
  sampler = null;
1360
1449
  restoreFunctions = [];
1450
+ /** Alias for `connect` — mirrors the browser SDK's init() API */
1451
+ init(config = {}) {
1452
+ return this.connect(config);
1453
+ }
1361
1454
  connect(config = {}) {
1362
1455
  this.config = config;
1363
1456
  this.sessionId = config.sessionId ?? generateSessionId();
1364
- const serverUrl = config.serverUrl ?? "ws://127.0.0.1:9090";
1365
- this.transport = new ServerTransport({
1366
- url: serverUrl,
1367
- sessionId: this.sessionId,
1368
- appName: config.appName ?? "server-app",
1369
- sdkVersion: SDK_VERSION,
1370
- authToken: config.authToken,
1371
- maxQueueSize: config.maxQueueSize
1372
- });
1373
- this.transport.connect();
1457
+ const serverUrl = config.serverUrl ?? config.endpoint ?? "ws://127.0.0.1:9090";
1458
+ if (config.transport === "http") {
1459
+ let httpUrl = config.httpEndpoint;
1460
+ if (!httpUrl) {
1461
+ const wsUrl = new URL(serverUrl);
1462
+ wsUrl.protocol = wsUrl.protocol === "wss:" ? "https:" : "http:";
1463
+ wsUrl.port = "9091";
1464
+ wsUrl.pathname = "/api/events";
1465
+ httpUrl = wsUrl.toString();
1466
+ }
1467
+ this.httpTransport = new HttpTransport({
1468
+ url: httpUrl,
1469
+ sessionId: this.sessionId,
1470
+ appName: config.appName ?? "server-app",
1471
+ sdkVersion: SDK_VERSION,
1472
+ authToken: config.authToken,
1473
+ maxQueueSize: config.maxQueueSize,
1474
+ flushIntervalMs: config.httpFlushIntervalMs
1475
+ });
1476
+ } else {
1477
+ this.transport = new ServerTransport({
1478
+ url: serverUrl,
1479
+ sessionId: this.sessionId,
1480
+ appName: config.appName ?? "server-app",
1481
+ sdkVersion: SDK_VERSION,
1482
+ authToken: config.authToken,
1483
+ maxQueueSize: config.maxQueueSize
1484
+ });
1485
+ this.transport.connect();
1486
+ }
1374
1487
  if (config.sampleRate !== void 0 || config.maxEventsPerSecond !== void 0) {
1375
1488
  this.sampler = new Sampler({
1376
1489
  sampleRate: config.sampleRate,
@@ -1399,7 +1512,7 @@ var RuntimeScopeServer = class {
1399
1512
  } catch {
1400
1513
  }
1401
1514
  }
1402
- if (config.captureHttp) {
1515
+ if (config.captureHttp !== false) {
1403
1516
  try {
1404
1517
  this.restoreFunctions.push(
1405
1518
  interceptHttp(emit, this.sessionId, {
@@ -1407,14 +1520,17 @@ var RuntimeScopeServer = class {
1407
1520
  maxBodySize: config.maxBodySize,
1408
1521
  redactHeaders: config.redactHeaders,
1409
1522
  // Auto-ignore the collector URL to prevent recursion
1410
- ignoreUrls: [serverUrl.replace("ws://", "").replace("wss://", "")],
1523
+ ignoreUrls: [
1524
+ serverUrl.replace("ws://", "").replace("wss://", ""),
1525
+ ...config.httpEndpoint ? [config.httpEndpoint.replace(/^https?:\/\//, "")] : []
1526
+ ],
1411
1527
  beforeSend: config.beforeSend
1412
1528
  })
1413
1529
  );
1414
1530
  } catch {
1415
1531
  }
1416
1532
  }
1417
- if (config.capturePerformance) {
1533
+ if (config.capturePerformance !== false) {
1418
1534
  try {
1419
1535
  this.restoreFunctions.push(
1420
1536
  startPerfMetrics(emit, this.sessionId, {
@@ -1435,6 +1551,10 @@ var RuntimeScopeServer = class {
1435
1551
  }
1436
1552
  this.restoreFunctions = [];
1437
1553
  this.sampler = null;
1554
+ if (this.httpTransport) {
1555
+ this.httpTransport.disconnect();
1556
+ this.httpTransport = null;
1557
+ }
1438
1558
  this.transport?.disconnect();
1439
1559
  this.transport = null;
1440
1560
  }
@@ -1443,12 +1563,12 @@ var RuntimeScopeServer = class {
1443
1563
  }
1444
1564
  emitEvent(event) {
1445
1565
  if (this.sampler && !this.sampler.shouldSample(event)) return;
1446
- if (this.config.beforeSend) {
1447
- const filtered = this.config.beforeSend(event);
1448
- if (!filtered) return;
1449
- this.transport?.sendEvent(filtered);
1566
+ const filtered = this.config.beforeSend ? this.config.beforeSend(event) : event;
1567
+ if (!filtered) return;
1568
+ if (this.httpTransport) {
1569
+ this.httpTransport.sendEvent(filtered);
1450
1570
  } else {
1451
- this.transport?.sendEvent(event);
1571
+ this.transport?.sendEvent(filtered);
1452
1572
  }
1453
1573
  }
1454
1574
  // --- Express/Connect Middleware ---
@@ -1569,6 +1689,7 @@ var RuntimeScopeServer = class {
1569
1689
  };
1570
1690
  var RuntimeScope = new RuntimeScopeServer();
1571
1691
  export {
1692
+ HttpTransport,
1572
1693
  RuntimeScope,
1573
1694
  Sampler,
1574
1695
  _log,