@bbearai/core 0.2.4 → 0.2.7

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.mts CHANGED
@@ -148,6 +148,12 @@ interface BugBearConfig {
148
148
  * @param route - The route path (web) or screen name (React Native)
149
149
  */
150
150
  onNavigate?: (route: string) => void;
151
+ /**
152
+ * URL to the BugBear web dashboard for this project.
153
+ * Shown as a link in the widget so testers can access
154
+ * the full web experience (analytics, discussions, history, etc.)
155
+ */
156
+ dashboardUrl?: string;
151
157
  }
152
158
  interface BugBearTheme {
153
159
  /** Primary brand color */
@@ -712,9 +718,18 @@ declare class BugBearClient {
712
718
  */
713
719
  shouldShowWidget(): Promise<boolean>;
714
720
  /**
715
- * Upload a screenshot
721
+ * Upload a screenshot (web - uses File/Blob)
716
722
  */
717
723
  uploadScreenshot(file: File | Blob, filename?: string): Promise<string | null>;
724
+ /**
725
+ * Upload an image from a local file URI (React Native compatible).
726
+ * Fetches the URI as a blob and uploads to Supabase Storage.
727
+ * @param uri - Local file:// or content:// URI from image picker
728
+ * @param filename - Optional filename (auto-generated if omitted)
729
+ * @param bucket - Storage bucket: 'screenshots' or 'discussion-attachments'
730
+ * @returns Public URL of uploaded image, or null on failure
731
+ */
732
+ uploadImageFromUri(uri: string, filename?: string, bucket?: 'screenshots' | 'discussion-attachments'): Promise<string | null>;
718
733
  /**
719
734
  * Generate a title from the report content
720
735
  */
@@ -767,7 +782,11 @@ declare class BugBearClient {
767
782
  /**
768
783
  * Send a message to a thread
769
784
  */
770
- sendMessage(threadId: string, content: string): Promise<boolean>;
785
+ sendMessage(threadId: string, content: string, attachments?: Array<{
786
+ type: 'image' | 'document' | 'video_link';
787
+ url: string;
788
+ name: string;
789
+ }>): Promise<boolean>;
771
790
  /**
772
791
  * Mark a thread as read
773
792
  */
@@ -784,6 +803,11 @@ declare class BugBearClient {
784
803
  subject: string;
785
804
  message: string;
786
805
  threadType?: 'direct' | 'general_note';
806
+ attachments?: Array<{
807
+ type: 'image' | 'document' | 'video_link';
808
+ url: string;
809
+ name: string;
810
+ }>;
787
811
  }): Promise<{
788
812
  success: boolean;
789
813
  threadId?: string;
package/dist/index.d.ts CHANGED
@@ -148,6 +148,12 @@ interface BugBearConfig {
148
148
  * @param route - The route path (web) or screen name (React Native)
149
149
  */
150
150
  onNavigate?: (route: string) => void;
151
+ /**
152
+ * URL to the BugBear web dashboard for this project.
153
+ * Shown as a link in the widget so testers can access
154
+ * the full web experience (analytics, discussions, history, etc.)
155
+ */
156
+ dashboardUrl?: string;
151
157
  }
152
158
  interface BugBearTheme {
153
159
  /** Primary brand color */
@@ -712,9 +718,18 @@ declare class BugBearClient {
712
718
  */
713
719
  shouldShowWidget(): Promise<boolean>;
714
720
  /**
715
- * Upload a screenshot
721
+ * Upload a screenshot (web - uses File/Blob)
716
722
  */
717
723
  uploadScreenshot(file: File | Blob, filename?: string): Promise<string | null>;
724
+ /**
725
+ * Upload an image from a local file URI (React Native compatible).
726
+ * Fetches the URI as a blob and uploads to Supabase Storage.
727
+ * @param uri - Local file:// or content:// URI from image picker
728
+ * @param filename - Optional filename (auto-generated if omitted)
729
+ * @param bucket - Storage bucket: 'screenshots' or 'discussion-attachments'
730
+ * @returns Public URL of uploaded image, or null on failure
731
+ */
732
+ uploadImageFromUri(uri: string, filename?: string, bucket?: 'screenshots' | 'discussion-attachments'): Promise<string | null>;
718
733
  /**
719
734
  * Generate a title from the report content
720
735
  */
@@ -767,7 +782,11 @@ declare class BugBearClient {
767
782
  /**
768
783
  * Send a message to a thread
769
784
  */
770
- sendMessage(threadId: string, content: string): Promise<boolean>;
785
+ sendMessage(threadId: string, content: string, attachments?: Array<{
786
+ type: 'image' | 'document' | 'video_link';
787
+ url: string;
788
+ name: string;
789
+ }>): Promise<boolean>;
771
790
  /**
772
791
  * Mark a thread as read
773
792
  */
@@ -784,6 +803,11 @@ declare class BugBearClient {
784
803
  subject: string;
785
804
  message: string;
786
805
  threadType?: 'direct' | 'general_note';
806
+ attachments?: Array<{
807
+ type: 'image' | 'document' | 'video_link';
808
+ url: string;
809
+ name: string;
810
+ }>;
787
811
  }): Promise<{
788
812
  success: boolean;
789
813
  threadId?: string;
package/dist/index.js CHANGED
@@ -715,7 +715,7 @@ var BugBearClient = class {
715
715
  return qaEnabled && isTester;
716
716
  }
717
717
  /**
718
- * Upload a screenshot
718
+ * Upload a screenshot (web - uses File/Blob)
719
719
  */
720
720
  async uploadScreenshot(file, filename) {
721
721
  try {
@@ -736,6 +736,37 @@ var BugBearClient = class {
736
736
  return null;
737
737
  }
738
738
  }
739
+ /**
740
+ * Upload an image from a local file URI (React Native compatible).
741
+ * Fetches the URI as a blob and uploads to Supabase Storage.
742
+ * @param uri - Local file:// or content:// URI from image picker
743
+ * @param filename - Optional filename (auto-generated if omitted)
744
+ * @param bucket - Storage bucket: 'screenshots' or 'discussion-attachments'
745
+ * @returns Public URL of uploaded image, or null on failure
746
+ */
747
+ async uploadImageFromUri(uri, filename, bucket = "screenshots") {
748
+ try {
749
+ const response = await fetch(uri);
750
+ const blob = await response.blob();
751
+ const contentType = blob.type || "image/jpeg";
752
+ const ext = contentType === "image/png" ? "png" : "jpg";
753
+ const name = filename || `img-${Date.now()}-${Math.random().toString(36).slice(2, 8)}.${ext}`;
754
+ const path = `${this.config.projectId}/${name}`;
755
+ const { error } = await this.supabase.storage.from(bucket).upload(path, blob, {
756
+ contentType,
757
+ upsert: false
758
+ });
759
+ if (error) {
760
+ console.error("BugBear: Failed to upload image from URI", error);
761
+ return null;
762
+ }
763
+ const { data: { publicUrl } } = this.supabase.storage.from(bucket).getPublicUrl(path);
764
+ return publicUrl;
765
+ } catch (err) {
766
+ console.error("BugBear: Error uploading image from URI", err);
767
+ return null;
768
+ }
769
+ }
739
770
  /**
740
771
  * Generate a title from the report content
741
772
  */
@@ -936,7 +967,7 @@ var BugBearClient = class {
936
967
  /**
937
968
  * Send a message to a thread
938
969
  */
939
- async sendMessage(threadId, content) {
970
+ async sendMessage(threadId, content, attachments) {
940
971
  try {
941
972
  const testerInfo = await this.getTesterInfo();
942
973
  if (!testerInfo) {
@@ -948,13 +979,17 @@ var BugBearClient = class {
948
979
  console.error("BugBear: Rate limit exceeded for messages");
949
980
  return false;
950
981
  }
951
- const { error } = await this.supabase.from("discussion_messages").insert({
982
+ const insertData = {
952
983
  thread_id: threadId,
953
984
  sender_type: "tester",
954
985
  sender_tester_id: testerInfo.id,
955
986
  sender_name: testerInfo.name || testerInfo.email,
956
987
  content
957
- });
988
+ };
989
+ if (attachments && attachments.length > 0) {
990
+ insertData.attachments = attachments;
991
+ }
992
+ const { error } = await this.supabase.from("discussion_messages").insert(insertData);
958
993
  if (error) {
959
994
  console.error("BugBear: Failed to send message", error);
960
995
  return false;
@@ -1026,13 +1061,17 @@ var BugBearClient = class {
1026
1061
  console.error("BugBear: Failed to create thread", threadError);
1027
1062
  return { success: false, error: threadError.message };
1028
1063
  }
1029
- const { error: messageError } = await this.supabase.from("discussion_messages").insert({
1064
+ const messageData = {
1030
1065
  thread_id: thread.id,
1031
1066
  sender_type: "tester",
1032
1067
  sender_tester_id: testerInfo.id,
1033
1068
  sender_name: testerInfo.name || testerInfo.email,
1034
1069
  content: options.message
1035
- });
1070
+ };
1071
+ if (options.attachments && options.attachments.length > 0) {
1072
+ messageData.attachments = options.attachments;
1073
+ }
1074
+ const { error: messageError } = await this.supabase.from("discussion_messages").insert(messageData);
1036
1075
  if (messageError) {
1037
1076
  console.error("BugBear: Failed to add initial message", messageError);
1038
1077
  return { success: true, threadId: thread.id };
package/dist/index.mjs CHANGED
@@ -686,7 +686,7 @@ var BugBearClient = class {
686
686
  return qaEnabled && isTester;
687
687
  }
688
688
  /**
689
- * Upload a screenshot
689
+ * Upload a screenshot (web - uses File/Blob)
690
690
  */
691
691
  async uploadScreenshot(file, filename) {
692
692
  try {
@@ -707,6 +707,37 @@ var BugBearClient = class {
707
707
  return null;
708
708
  }
709
709
  }
710
+ /**
711
+ * Upload an image from a local file URI (React Native compatible).
712
+ * Fetches the URI as a blob and uploads to Supabase Storage.
713
+ * @param uri - Local file:// or content:// URI from image picker
714
+ * @param filename - Optional filename (auto-generated if omitted)
715
+ * @param bucket - Storage bucket: 'screenshots' or 'discussion-attachments'
716
+ * @returns Public URL of uploaded image, or null on failure
717
+ */
718
+ async uploadImageFromUri(uri, filename, bucket = "screenshots") {
719
+ try {
720
+ const response = await fetch(uri);
721
+ const blob = await response.blob();
722
+ const contentType = blob.type || "image/jpeg";
723
+ const ext = contentType === "image/png" ? "png" : "jpg";
724
+ const name = filename || `img-${Date.now()}-${Math.random().toString(36).slice(2, 8)}.${ext}`;
725
+ const path = `${this.config.projectId}/${name}`;
726
+ const { error } = await this.supabase.storage.from(bucket).upload(path, blob, {
727
+ contentType,
728
+ upsert: false
729
+ });
730
+ if (error) {
731
+ console.error("BugBear: Failed to upload image from URI", error);
732
+ return null;
733
+ }
734
+ const { data: { publicUrl } } = this.supabase.storage.from(bucket).getPublicUrl(path);
735
+ return publicUrl;
736
+ } catch (err) {
737
+ console.error("BugBear: Error uploading image from URI", err);
738
+ return null;
739
+ }
740
+ }
710
741
  /**
711
742
  * Generate a title from the report content
712
743
  */
@@ -907,7 +938,7 @@ var BugBearClient = class {
907
938
  /**
908
939
  * Send a message to a thread
909
940
  */
910
- async sendMessage(threadId, content) {
941
+ async sendMessage(threadId, content, attachments) {
911
942
  try {
912
943
  const testerInfo = await this.getTesterInfo();
913
944
  if (!testerInfo) {
@@ -919,13 +950,17 @@ var BugBearClient = class {
919
950
  console.error("BugBear: Rate limit exceeded for messages");
920
951
  return false;
921
952
  }
922
- const { error } = await this.supabase.from("discussion_messages").insert({
953
+ const insertData = {
923
954
  thread_id: threadId,
924
955
  sender_type: "tester",
925
956
  sender_tester_id: testerInfo.id,
926
957
  sender_name: testerInfo.name || testerInfo.email,
927
958
  content
928
- });
959
+ };
960
+ if (attachments && attachments.length > 0) {
961
+ insertData.attachments = attachments;
962
+ }
963
+ const { error } = await this.supabase.from("discussion_messages").insert(insertData);
929
964
  if (error) {
930
965
  console.error("BugBear: Failed to send message", error);
931
966
  return false;
@@ -997,13 +1032,17 @@ var BugBearClient = class {
997
1032
  console.error("BugBear: Failed to create thread", threadError);
998
1033
  return { success: false, error: threadError.message };
999
1034
  }
1000
- const { error: messageError } = await this.supabase.from("discussion_messages").insert({
1035
+ const messageData = {
1001
1036
  thread_id: thread.id,
1002
1037
  sender_type: "tester",
1003
1038
  sender_tester_id: testerInfo.id,
1004
1039
  sender_name: testerInfo.name || testerInfo.email,
1005
1040
  content: options.message
1006
- });
1041
+ };
1042
+ if (options.attachments && options.attachments.length > 0) {
1043
+ messageData.attachments = options.attachments;
1044
+ }
1045
+ const { error: messageError } = await this.supabase.from("discussion_messages").insert(messageData);
1007
1046
  if (messageError) {
1008
1047
  console.error("BugBear: Failed to add initial message", messageError);
1009
1048
  return { success: true, threadId: thread.id };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bbearai/core",
3
- "version": "0.2.4",
3
+ "version": "0.2.7",
4
4
  "description": "Core utilities and types for BugBear QA platform",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",