@tellann/frontend-sdk 0.2.0 → 0.4.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.
Files changed (2) hide show
  1. package/dist/index.js +30 -5
  2. package/package.json +3 -2
package/dist/index.js CHANGED
@@ -19,6 +19,23 @@ function qaRunActive() {
19
19
  const run = globalThis.__TELLANN_RUN__;
20
20
  return Boolean(run && run.runId && run.relayToken);
21
21
  }
22
+ /**
23
+ * The local relay the desktop observer injected for this run, if any.
24
+ *
25
+ * While a guided run is active every event has to travel through the relay:
26
+ * only the relay attaches the run-ingestion credential, and the collector
27
+ * advances the Flow boundary solely for credentialed events. A
28
+ * `FLOW_INITIAL_STATE` flushed straight to the configured gateway is ingested
29
+ * as ordinary telemetry, so the run would sit at "Waiting for
30
+ * FLOW_INITIAL_STATE" no matter how many times the page emits it.
31
+ */
32
+ function activeRunRelay() {
33
+ const run = globalThis.__TELLANN_RUN__;
34
+ if (!run || typeof run.runId !== 'string' || typeof run.relayToken !== 'string')
35
+ return null;
36
+ const endpoint = typeof run.relayEndpoint === 'string' ? run.relayEndpoint.replace(/\/$/, '') : '';
37
+ return endpoint ? { endpoint, token: run.relayToken } : null;
38
+ }
22
39
  function serializeCandidate(value) {
23
40
  if (value === undefined)
24
41
  return undefined;
@@ -397,13 +414,21 @@ class TellannFrontendSDK {
397
414
  console.error(`[Tellann] Batch payload size of ${payloadSize} bytes exceeds the 5 MB limit. Dropping batch.`);
398
415
  return;
399
416
  }
417
+ const relay = activeRunRelay();
418
+ const target = relay ? relay.endpoint : this.config.endpoint;
400
419
  const headers = {
401
420
  'Content-Type': 'application/json',
402
421
  };
403
- if (this.config.apiKey) {
422
+ if (relay) {
423
+ headers.Authorization = `Bearer ${relay.token}`;
424
+ }
425
+ else if (this.config.apiKey) {
404
426
  headers.Authorization = `Bearer ${this.config.apiKey}`;
405
427
  }
406
- if (this.config.environmentId) {
428
+ // The relay re-derives the environment from the run correlation, and its
429
+ // CORS allow-list does not carry this header — sending it would fail the
430
+ // preflight and lose the batch.
431
+ if (!relay && this.config.environmentId) {
407
432
  headers['x-tellann-environment-id'] = this.config.environmentId;
408
433
  }
409
434
  if (this.config.runId)
@@ -413,16 +438,16 @@ class TellannFrontendSDK {
413
438
  if (this.config.traceId)
414
439
  headers['x-tellann-trace-id'] = this.config.traceId;
415
440
  // sendBeacon cannot set auth headers, so only use it for unauthenticated direct collector targets.
416
- if (!this.config.apiKey && !this.config.environmentId && navigator.sendBeacon && typeof Blob !== 'undefined') {
441
+ if (!relay && !this.config.apiKey && !this.config.environmentId && navigator.sendBeacon && typeof Blob !== 'undefined') {
417
442
  const blob = new Blob([payload], { type: 'application/json' });
418
- const success = navigator.sendBeacon(`${this.config.endpoint}/v1/events/batch`, blob);
443
+ const success = navigator.sendBeacon(`${target}/v1/events/batch`, blob);
419
444
  if (!success) {
420
445
  throw new Error('sendBeacon returned false');
421
446
  }
422
447
  }
423
448
  else {
424
449
  // Fallback to fetch
425
- await fetch(`${this.config.endpoint}/v1/events/batch`, {
450
+ await fetch(`${target}/v1/events/batch`, {
426
451
  method: 'POST',
427
452
  headers,
428
453
  body: payload,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tellann/frontend-sdk",
3
- "version": "0.2.0",
3
+ "version": "0.4.0",
4
4
  "type": "module",
5
5
  "description": "Tellann browser telemetry and QA-run correlation SDK",
6
6
  "license": "UNLICENSED",
@@ -24,7 +24,8 @@
24
24
  "types": "./dist/index.d.ts",
25
25
  "import": "./dist/index.js",
26
26
  "default": "./dist/index.js"
27
- }
27
+ },
28
+ "./package.json": "./package.json"
28
29
  },
29
30
  "files": [
30
31
  "dist",