yaver-feedback-react-native 0.8.11 → 0.8.12

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.
@@ -53,6 +53,7 @@ export type CommandHandler = (cmd: BlackBoxCommand) => void;
53
53
  export declare class BlackBox {
54
54
  private static baseUrl;
55
55
  private static authToken;
56
+ private static relayPassword;
56
57
  private static deviceId;
57
58
  private static appName;
58
59
  private static buffer;
package/dist/BlackBox.js CHANGED
@@ -18,6 +18,7 @@ class BlackBox {
18
18
  }
19
19
  BlackBox.baseUrl = feedbackConfig.agentUrl.replace(/\/$/, '');
20
20
  BlackBox.authToken = feedbackConfig.authToken ?? null;
21
+ BlackBox.relayPassword = feedbackConfig.relayPassword ?? '';
21
22
  BlackBox.deviceId = config?.deviceId ?? BlackBox.generateDeviceId();
22
23
  BlackBox.appName = config?.appName ?? '';
23
24
  BlackBox.flushInterval = config?.flushInterval ?? 2000;
@@ -252,15 +253,19 @@ class BlackBox {
252
253
  BlackBox.sseAbortController = controller;
253
254
  const url = `${BlackBox.baseUrl}/blackbox/command-stream?device=${encodeURIComponent(BlackBox.deviceId)}`;
254
255
  try {
256
+ const sseHeaders = {
257
+ Authorization: `Bearer ${BlackBox.authToken}`,
258
+ 'X-Device-ID': BlackBox.deviceId,
259
+ 'X-Platform': react_native_1.Platform.OS,
260
+ 'X-App-Name': BlackBox.appName,
261
+ Accept: 'text/event-stream',
262
+ };
263
+ if (BlackBox.relayPassword) {
264
+ sseHeaders['X-Relay-Password'] = BlackBox.relayPassword;
265
+ }
255
266
  const response = await fetch(url, {
256
267
  method: 'GET',
257
- headers: {
258
- Authorization: `Bearer ${BlackBox.authToken}`,
259
- 'X-Device-ID': BlackBox.deviceId,
260
- 'X-Platform': react_native_1.Platform.OS,
261
- 'X-App-Name': BlackBox.appName,
262
- Accept: 'text/event-stream',
263
- },
268
+ headers: sseHeaders,
264
269
  // @ts-ignore — React Native supports signal on fetch
265
270
  signal: controller.signal,
266
271
  });
@@ -354,15 +359,19 @@ class BlackBox {
354
359
  const events = BlackBox.buffer;
355
360
  BlackBox.buffer = [];
356
361
  try {
362
+ const flushHeaders = {
363
+ Authorization: `Bearer ${BlackBox.authToken}`,
364
+ 'Content-Type': 'application/json',
365
+ 'X-Device-ID': BlackBox.deviceId,
366
+ 'X-Platform': react_native_1.Platform.OS,
367
+ 'X-App-Name': BlackBox.appName,
368
+ };
369
+ if (BlackBox.relayPassword) {
370
+ flushHeaders['X-Relay-Password'] = BlackBox.relayPassword;
371
+ }
357
372
  await fetch(`${BlackBox.baseUrl}/blackbox/events`, {
358
373
  method: 'POST',
359
- headers: {
360
- Authorization: `Bearer ${BlackBox.authToken}`,
361
- 'Content-Type': 'application/json',
362
- 'X-Device-ID': BlackBox.deviceId,
363
- 'X-Platform': react_native_1.Platform.OS,
364
- 'X-App-Name': BlackBox.appName,
365
- },
374
+ headers: flushHeaders,
366
375
  body: JSON.stringify(events),
367
376
  });
368
377
  }
@@ -380,6 +389,12 @@ class BlackBox {
380
389
  exports.BlackBox = BlackBox;
381
390
  BlackBox.baseUrl = null;
382
391
  BlackBox.authToken = null;
392
+ // Mirror of the user's relay password — required for EVERY request that
393
+ // crosses the relay (`https://public.yaver.io/d/<id>/...`). Without it
394
+ // the relay rejects with HTTP 401 "invalid relay password" and the
395
+ // event stream silently fails. Set on start() from YaverFeedback's
396
+ // resolved relay password (same source the P2PClient uses).
397
+ BlackBox.relayPassword = '';
383
398
  BlackBox.deviceId = '';
384
399
  BlackBox.appName = '';
385
400
  BlackBox.buffer = [];
@@ -376,7 +376,7 @@ const FeedbackModal = () => {
376
376
  return;
377
377
  }
378
378
  try {
379
- const uploaded = await (0, upload_1.uploadFeedback)(config.agentUrl, config.authToken ?? '', bundle);
379
+ const uploaded = await (0, upload_1.uploadFeedback)(config.agentUrl, config.authToken ?? '', bundle, YaverFeedback_1.YaverFeedback.getRelayPassword());
380
380
  // The agent returns the new report id as `id` (see
381
381
  // feedback_http.go::ReceiveFeedback). Trigger the fix loop if we got
382
382
  // one back; otherwise just ack the upload.
@@ -116,6 +116,13 @@ export declare class YaverFeedback {
116
116
  static isEnabled(): boolean;
117
117
  /** Returns the current config, or null if not initialized. */
118
118
  static getConfig(): FeedbackConfig | null;
119
+ /** Returns the resolved relay password the SDK is currently using.
120
+ * Empty string when no relay routing is in play (direct LAN agent
121
+ * URLs need no password). Callers attaching it to relay-routed
122
+ * HTTP requests must check for empty before setting the header,
123
+ * since "X-Relay-Password: " is treated as invalid by the relay
124
+ * and would 401 the request. */
125
+ static getRelayPassword(): string;
119
126
  /**
120
127
  * Manually attach an error with optional metadata.
121
128
  * Use this in catch blocks to give the agent extra context.
@@ -781,6 +781,15 @@ class YaverFeedback {
781
781
  static getConfig() {
782
782
  return config;
783
783
  }
784
+ /** Returns the resolved relay password the SDK is currently using.
785
+ * Empty string when no relay routing is in play (direct LAN agent
786
+ * URLs need no password). Callers attaching it to relay-routed
787
+ * HTTP requests must check for empty before setting the header,
788
+ * since "X-Relay-Password: " is treated as invalid by the relay
789
+ * and would 401 the request. */
790
+ static getRelayPassword() {
791
+ return p2pRelayPassword;
792
+ }
784
793
  /**
785
794
  * Manually attach an error with optional metadata.
786
795
  * Use this in catch blocks to give the agent extra context.
@@ -988,7 +997,7 @@ class YaverFeedback {
988
997
  screenshots: screenshotPath ? [screenshotPath] : [],
989
998
  errors: errorBuffer.length > 0 ? [...errorBuffer] : undefined,
990
999
  };
991
- await uploadFeedback(config.agentUrl, config.authToken ?? '', bundle);
1000
+ await uploadFeedback(config.agentUrl, config.authToken ?? '', bundle, p2pRelayPassword);
992
1001
  console.log('[YaverFeedback] Auto-report sent');
993
1002
  }
994
1003
  catch (err) {
package/dist/upload.d.ts CHANGED
@@ -12,7 +12,7 @@ import { FeedbackBundle } from './types';
12
12
  * Callers can inspect `.id` / `.reportId` to drive a follow-up
13
13
  * `/feedback/{id}/fix` kick.
14
14
  */
15
- export declare function uploadFeedback(agentUrl: string, authToken: string, bundle: FeedbackBundle): Promise<{
15
+ export declare function uploadFeedback(agentUrl: string, authToken: string, bundle: FeedbackBundle, relayPassword?: string): Promise<{
16
16
  id?: string;
17
17
  reportId?: string;
18
18
  [k: string]: unknown;
package/dist/upload.js CHANGED
@@ -15,7 +15,7 @@ const react_native_1 = require("react-native");
15
15
  * Callers can inspect `.id` / `.reportId` to drive a follow-up
16
16
  * `/feedback/{id}/fix` kick.
17
17
  */
18
- async function uploadFeedback(agentUrl, authToken, bundle) {
18
+ async function uploadFeedback(agentUrl, authToken, bundle, relayPassword = '') {
19
19
  const formData = new FormData();
20
20
  // Attach metadata as JSON
21
21
  formData.append('metadata', JSON.stringify(bundle.metadata));
@@ -44,11 +44,15 @@ async function uploadFeedback(agentUrl, authToken, bundle) {
44
44
  });
45
45
  }
46
46
  const url = agentUrl.replace(/\/$/, '') + '/feedback';
47
+ const headers = {
48
+ Authorization: `Bearer ${authToken}`,
49
+ };
50
+ if (relayPassword) {
51
+ headers['X-Relay-Password'] = relayPassword;
52
+ }
47
53
  const response = await fetch(url, {
48
54
  method: 'POST',
49
- headers: {
50
- Authorization: `Bearer ${authToken}`,
51
- },
55
+ headers,
52
56
  body: formData,
53
57
  });
54
58
  if (!response.ok) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "yaver-feedback-react-native",
3
- "version": "0.8.11",
3
+ "version": "0.8.12",
4
4
  "description": "Visual feedback SDK for Yaver \u2014 bug reports, screen recording, voice annotations, and local-first developer workflows",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
package/src/BlackBox.ts CHANGED
@@ -69,6 +69,12 @@ export type CommandHandler = (cmd: BlackBoxCommand) => void;
69
69
  export class BlackBox {
70
70
  private static baseUrl: string | null = null;
71
71
  private static authToken: string | null = null;
72
+ // Mirror of the user's relay password — required for EVERY request that
73
+ // crosses the relay (`https://public.yaver.io/d/<id>/...`). Without it
74
+ // the relay rejects with HTTP 401 "invalid relay password" and the
75
+ // event stream silently fails. Set on start() from YaverFeedback's
76
+ // resolved relay password (same source the P2PClient uses).
77
+ private static relayPassword: string = '';
72
78
  private static deviceId: string = '';
73
79
  private static appName: string = '';
74
80
  private static buffer: BlackBoxEvent[] = [];
@@ -103,6 +109,7 @@ export class BlackBox {
103
109
 
104
110
  BlackBox.baseUrl = feedbackConfig.agentUrl.replace(/\/$/, '');
105
111
  BlackBox.authToken = feedbackConfig.authToken ?? null;
112
+ BlackBox.relayPassword = (feedbackConfig as { relayPassword?: string }).relayPassword ?? '';
106
113
  BlackBox.deviceId = config?.deviceId ?? BlackBox.generateDeviceId();
107
114
  BlackBox.appName = config?.appName ?? '';
108
115
  BlackBox.flushInterval = config?.flushInterval ?? 2000;
@@ -375,15 +382,19 @@ export class BlackBox {
375
382
  const url = `${BlackBox.baseUrl}/blackbox/command-stream?device=${encodeURIComponent(BlackBox.deviceId)}`;
376
383
 
377
384
  try {
385
+ const sseHeaders: Record<string, string> = {
386
+ Authorization: `Bearer ${BlackBox.authToken}`,
387
+ 'X-Device-ID': BlackBox.deviceId,
388
+ 'X-Platform': Platform.OS,
389
+ 'X-App-Name': BlackBox.appName,
390
+ Accept: 'text/event-stream',
391
+ };
392
+ if (BlackBox.relayPassword) {
393
+ sseHeaders['X-Relay-Password'] = BlackBox.relayPassword;
394
+ }
378
395
  const response = await fetch(url, {
379
396
  method: 'GET',
380
- headers: {
381
- Authorization: `Bearer ${BlackBox.authToken}`,
382
- 'X-Device-ID': BlackBox.deviceId,
383
- 'X-Platform': Platform.OS,
384
- 'X-App-Name': BlackBox.appName,
385
- Accept: 'text/event-stream',
386
- },
397
+ headers: sseHeaders,
387
398
  // @ts-ignore — React Native supports signal on fetch
388
399
  signal: controller.signal,
389
400
  });
@@ -479,15 +490,19 @@ export class BlackBox {
479
490
  BlackBox.buffer = [];
480
491
 
481
492
  try {
493
+ const flushHeaders: Record<string, string> = {
494
+ Authorization: `Bearer ${BlackBox.authToken}`,
495
+ 'Content-Type': 'application/json',
496
+ 'X-Device-ID': BlackBox.deviceId,
497
+ 'X-Platform': Platform.OS,
498
+ 'X-App-Name': BlackBox.appName,
499
+ };
500
+ if (BlackBox.relayPassword) {
501
+ flushHeaders['X-Relay-Password'] = BlackBox.relayPassword;
502
+ }
482
503
  await fetch(`${BlackBox.baseUrl}/blackbox/events`, {
483
504
  method: 'POST',
484
- headers: {
485
- Authorization: `Bearer ${BlackBox.authToken}`,
486
- 'Content-Type': 'application/json',
487
- 'X-Device-ID': BlackBox.deviceId,
488
- 'X-Platform': Platform.OS,
489
- 'X-App-Name': BlackBox.appName,
490
- },
505
+ headers: flushHeaders,
491
506
  body: JSON.stringify(events),
492
507
  });
493
508
  } catch {
@@ -415,6 +415,7 @@ export const FeedbackModal: React.FC = () => {
415
415
  config.agentUrl,
416
416
  config.authToken ?? '',
417
417
  bundle,
418
+ YaverFeedback.getRelayPassword(),
418
419
  );
419
420
  // The agent returns the new report id as `id` (see
420
421
  // feedback_http.go::ReceiveFeedback). Trigger the fix loop if we got
@@ -815,6 +815,16 @@ export class YaverFeedback {
815
815
  return config;
816
816
  }
817
817
 
818
+ /** Returns the resolved relay password the SDK is currently using.
819
+ * Empty string when no relay routing is in play (direct LAN agent
820
+ * URLs need no password). Callers attaching it to relay-routed
821
+ * HTTP requests must check for empty before setting the header,
822
+ * since "X-Relay-Password: " is treated as invalid by the relay
823
+ * and would 401 the request. */
824
+ static getRelayPassword(): string {
825
+ return p2pRelayPassword;
826
+ }
827
+
818
828
  /**
819
829
  * Manually attach an error with optional metadata.
820
830
  * Use this in catch blocks to give the agent extra context.
@@ -1040,7 +1050,7 @@ export class YaverFeedback {
1040
1050
  errors: errorBuffer.length > 0 ? [...errorBuffer] : undefined,
1041
1051
  };
1042
1052
 
1043
- await uploadFeedback(config.agentUrl, config.authToken ?? '', bundle);
1053
+ await uploadFeedback(config.agentUrl, config.authToken ?? '', bundle, p2pRelayPassword);
1044
1054
  console.log('[YaverFeedback] Auto-report sent');
1045
1055
  } catch (err) {
1046
1056
  console.warn('[YaverFeedback] Auto-report failed:', err);
package/src/upload.ts CHANGED
@@ -18,6 +18,7 @@ export async function uploadFeedback(
18
18
  agentUrl: string,
19
19
  authToken: string,
20
20
  bundle: FeedbackBundle,
21
+ relayPassword: string = '',
21
22
  ): Promise<{ id?: string; reportId?: string; [k: string]: unknown }> {
22
23
  const formData = new FormData();
23
24
 
@@ -54,11 +55,15 @@ export async function uploadFeedback(
54
55
 
55
56
  const url = agentUrl.replace(/\/$/, '') + '/feedback';
56
57
 
58
+ const headers: Record<string, string> = {
59
+ Authorization: `Bearer ${authToken}`,
60
+ };
61
+ if (relayPassword) {
62
+ headers['X-Relay-Password'] = relayPassword;
63
+ }
57
64
  const response = await fetch(url, {
58
65
  method: 'POST',
59
- headers: {
60
- Authorization: `Bearer ${authToken}`,
61
- },
66
+ headers,
62
67
  body: formData,
63
68
  });
64
69