@bbearai/core 0.7.2 → 0.8.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.mts +23 -0
- package/dist/index.d.ts +23 -0
- package/dist/index.js +94 -0
- package/dist/index.mjs +94 -0
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -479,6 +479,7 @@ interface TesterThread {
|
|
|
479
479
|
createdAt: string;
|
|
480
480
|
unreadCount: number;
|
|
481
481
|
lastMessage?: TesterMessage;
|
|
482
|
+
reporterName?: string;
|
|
482
483
|
}
|
|
483
484
|
interface TesterMessage {
|
|
484
485
|
id: string;
|
|
@@ -1102,6 +1103,12 @@ declare class BugBearClient {
|
|
|
1102
1103
|
private initialized;
|
|
1103
1104
|
/** Initialization error, if any. */
|
|
1104
1105
|
private initError;
|
|
1106
|
+
/** Active presence session ID (passive time tracking). */
|
|
1107
|
+
private _presenceSessionId;
|
|
1108
|
+
/** Heartbeat interval for presence tracking. */
|
|
1109
|
+
private _presenceInterval;
|
|
1110
|
+
/** Whether presence is paused (tab hidden / app backgrounded). */
|
|
1111
|
+
private _presencePaused;
|
|
1105
1112
|
constructor(config: BugBearConfig);
|
|
1106
1113
|
/** Whether the client is ready for requests. */
|
|
1107
1114
|
get isReady(): boolean;
|
|
@@ -1561,6 +1568,22 @@ declare class BugBearClient {
|
|
|
1561
1568
|
* Transform database finding to QAFinding type
|
|
1562
1569
|
*/
|
|
1563
1570
|
private transformFinding;
|
|
1571
|
+
/** Current presence session ID (null if not tracking). */
|
|
1572
|
+
get presenceSessionId(): string | null;
|
|
1573
|
+
/**
|
|
1574
|
+
* Start passive presence tracking for this tester.
|
|
1575
|
+
* Idempotent — reuses an existing active session if one exists.
|
|
1576
|
+
*/
|
|
1577
|
+
startPresence(platform: 'web' | 'ios' | 'android'): Promise<string | null>;
|
|
1578
|
+
/** Gracefully end the current presence session. */
|
|
1579
|
+
endPresence(): Promise<void>;
|
|
1580
|
+
/** Pause heartbeat (tab hidden / app backgrounded). Sends one final beat. */
|
|
1581
|
+
pausePresence(): void;
|
|
1582
|
+
/** Resume heartbeat after pause. Restarts if session was cleaned up. */
|
|
1583
|
+
resumePresence(): Promise<void>;
|
|
1584
|
+
private heartbeatPresence;
|
|
1585
|
+
private startPresenceHeartbeat;
|
|
1586
|
+
private stopPresenceHeartbeat;
|
|
1564
1587
|
}
|
|
1565
1588
|
/**
|
|
1566
1589
|
* Create a BugBear client instance
|
package/dist/index.d.ts
CHANGED
|
@@ -479,6 +479,7 @@ interface TesterThread {
|
|
|
479
479
|
createdAt: string;
|
|
480
480
|
unreadCount: number;
|
|
481
481
|
lastMessage?: TesterMessage;
|
|
482
|
+
reporterName?: string;
|
|
482
483
|
}
|
|
483
484
|
interface TesterMessage {
|
|
484
485
|
id: string;
|
|
@@ -1102,6 +1103,12 @@ declare class BugBearClient {
|
|
|
1102
1103
|
private initialized;
|
|
1103
1104
|
/** Initialization error, if any. */
|
|
1104
1105
|
private initError;
|
|
1106
|
+
/** Active presence session ID (passive time tracking). */
|
|
1107
|
+
private _presenceSessionId;
|
|
1108
|
+
/** Heartbeat interval for presence tracking. */
|
|
1109
|
+
private _presenceInterval;
|
|
1110
|
+
/** Whether presence is paused (tab hidden / app backgrounded). */
|
|
1111
|
+
private _presencePaused;
|
|
1105
1112
|
constructor(config: BugBearConfig);
|
|
1106
1113
|
/** Whether the client is ready for requests. */
|
|
1107
1114
|
get isReady(): boolean;
|
|
@@ -1561,6 +1568,22 @@ declare class BugBearClient {
|
|
|
1561
1568
|
* Transform database finding to QAFinding type
|
|
1562
1569
|
*/
|
|
1563
1570
|
private transformFinding;
|
|
1571
|
+
/** Current presence session ID (null if not tracking). */
|
|
1572
|
+
get presenceSessionId(): string | null;
|
|
1573
|
+
/**
|
|
1574
|
+
* Start passive presence tracking for this tester.
|
|
1575
|
+
* Idempotent — reuses an existing active session if one exists.
|
|
1576
|
+
*/
|
|
1577
|
+
startPresence(platform: 'web' | 'ios' | 'android'): Promise<string | null>;
|
|
1578
|
+
/** Gracefully end the current presence session. */
|
|
1579
|
+
endPresence(): Promise<void>;
|
|
1580
|
+
/** Pause heartbeat (tab hidden / app backgrounded). Sends one final beat. */
|
|
1581
|
+
pausePresence(): void;
|
|
1582
|
+
/** Resume heartbeat after pause. Restarts if session was cleaned up. */
|
|
1583
|
+
resumePresence(): Promise<void>;
|
|
1584
|
+
private heartbeatPresence;
|
|
1585
|
+
private startPresenceHeartbeat;
|
|
1586
|
+
private stopPresenceHeartbeat;
|
|
1564
1587
|
}
|
|
1565
1588
|
/**
|
|
1566
1589
|
* Create a BugBear client instance
|
package/dist/index.js
CHANGED
|
@@ -914,6 +914,12 @@ var BugBearClient = class {
|
|
|
914
914
|
this.initialized = false;
|
|
915
915
|
/** Initialization error, if any. */
|
|
916
916
|
this.initError = null;
|
|
917
|
+
/** Active presence session ID (passive time tracking). */
|
|
918
|
+
this._presenceSessionId = null;
|
|
919
|
+
/** Heartbeat interval for presence tracking. */
|
|
920
|
+
this._presenceInterval = null;
|
|
921
|
+
/** Whether presence is paused (tab hidden / app backgrounded). */
|
|
922
|
+
this._presencePaused = false;
|
|
917
923
|
this.config = config;
|
|
918
924
|
if (config.apiKey) {
|
|
919
925
|
this.pendingInit = this.resolveFromApiKey(config.apiKey);
|
|
@@ -2559,6 +2565,7 @@ var BugBearClient = class {
|
|
|
2559
2565
|
lastMessageAt: row.last_message_at,
|
|
2560
2566
|
createdAt: row.created_at,
|
|
2561
2567
|
unreadCount: Number(row.unread_count) || 0,
|
|
2568
|
+
reporterName: row.reporter_name || void 0,
|
|
2562
2569
|
lastMessage: row.last_message_preview ? {
|
|
2563
2570
|
id: "",
|
|
2564
2571
|
threadId: row.thread_id,
|
|
@@ -2998,6 +3005,93 @@ var BugBearClient = class {
|
|
|
2998
3005
|
updatedAt: data.updated_at
|
|
2999
3006
|
};
|
|
3000
3007
|
}
|
|
3008
|
+
// ─── Passive Presence Tracking ──────────────────────────────
|
|
3009
|
+
/** Current presence session ID (null if not tracking). */
|
|
3010
|
+
get presenceSessionId() {
|
|
3011
|
+
return this._presenceSessionId;
|
|
3012
|
+
}
|
|
3013
|
+
/**
|
|
3014
|
+
* Start passive presence tracking for this tester.
|
|
3015
|
+
* Idempotent — reuses an existing active session if one exists.
|
|
3016
|
+
*/
|
|
3017
|
+
async startPresence(platform) {
|
|
3018
|
+
try {
|
|
3019
|
+
await this.ensureReady();
|
|
3020
|
+
const testerInfo = await this.getTesterInfo();
|
|
3021
|
+
if (!testerInfo) return null;
|
|
3022
|
+
const { data, error } = await this.supabase.rpc("upsert_tester_presence", {
|
|
3023
|
+
p_project_id: this.config.projectId,
|
|
3024
|
+
p_tester_id: testerInfo.id,
|
|
3025
|
+
p_platform: platform
|
|
3026
|
+
});
|
|
3027
|
+
if (error) {
|
|
3028
|
+
console.error("BugBear: Failed to start presence", formatPgError(error));
|
|
3029
|
+
return null;
|
|
3030
|
+
}
|
|
3031
|
+
this._presenceSessionId = data;
|
|
3032
|
+
this._presencePaused = false;
|
|
3033
|
+
this.startPresenceHeartbeat();
|
|
3034
|
+
return data;
|
|
3035
|
+
} catch (err) {
|
|
3036
|
+
console.error("BugBear: Error starting presence", err);
|
|
3037
|
+
return null;
|
|
3038
|
+
}
|
|
3039
|
+
}
|
|
3040
|
+
/** Gracefully end the current presence session. */
|
|
3041
|
+
async endPresence() {
|
|
3042
|
+
this.stopPresenceHeartbeat();
|
|
3043
|
+
if (!this._presenceSessionId) return;
|
|
3044
|
+
try {
|
|
3045
|
+
await this.supabase.rpc("end_tester_presence", {
|
|
3046
|
+
p_session_id: this._presenceSessionId
|
|
3047
|
+
});
|
|
3048
|
+
} catch {
|
|
3049
|
+
}
|
|
3050
|
+
this._presenceSessionId = null;
|
|
3051
|
+
}
|
|
3052
|
+
/** Pause heartbeat (tab hidden / app backgrounded). Sends one final beat. */
|
|
3053
|
+
pausePresence() {
|
|
3054
|
+
this._presencePaused = true;
|
|
3055
|
+
this.heartbeatPresence();
|
|
3056
|
+
}
|
|
3057
|
+
/** Resume heartbeat after pause. Restarts if session was cleaned up. */
|
|
3058
|
+
async resumePresence() {
|
|
3059
|
+
if (!this._presenceSessionId) return;
|
|
3060
|
+
this._presencePaused = false;
|
|
3061
|
+
try {
|
|
3062
|
+
const { data } = await this.supabase.rpc("heartbeat_tester_presence", {
|
|
3063
|
+
p_session_id: this._presenceSessionId
|
|
3064
|
+
});
|
|
3065
|
+
if (!data) {
|
|
3066
|
+
this._presenceSessionId = null;
|
|
3067
|
+
}
|
|
3068
|
+
} catch {
|
|
3069
|
+
this._presenceSessionId = null;
|
|
3070
|
+
}
|
|
3071
|
+
}
|
|
3072
|
+
async heartbeatPresence() {
|
|
3073
|
+
if (!this._presenceSessionId || this._presencePaused) return;
|
|
3074
|
+
try {
|
|
3075
|
+
const { data, error } = await this.supabase.rpc("heartbeat_tester_presence", {
|
|
3076
|
+
p_session_id: this._presenceSessionId
|
|
3077
|
+
});
|
|
3078
|
+
if (error || data === false) {
|
|
3079
|
+
this.stopPresenceHeartbeat();
|
|
3080
|
+
this._presenceSessionId = null;
|
|
3081
|
+
}
|
|
3082
|
+
} catch {
|
|
3083
|
+
}
|
|
3084
|
+
}
|
|
3085
|
+
startPresenceHeartbeat() {
|
|
3086
|
+
this.stopPresenceHeartbeat();
|
|
3087
|
+
this._presenceInterval = setInterval(() => this.heartbeatPresence(), 6e4);
|
|
3088
|
+
}
|
|
3089
|
+
stopPresenceHeartbeat() {
|
|
3090
|
+
if (this._presenceInterval) {
|
|
3091
|
+
clearInterval(this._presenceInterval);
|
|
3092
|
+
this._presenceInterval = null;
|
|
3093
|
+
}
|
|
3094
|
+
}
|
|
3001
3095
|
};
|
|
3002
3096
|
function createBugBear(config) {
|
|
3003
3097
|
return new BugBearClient(config);
|
package/dist/index.mjs
CHANGED
|
@@ -868,6 +868,12 @@ var BugBearClient = class {
|
|
|
868
868
|
this.initialized = false;
|
|
869
869
|
/** Initialization error, if any. */
|
|
870
870
|
this.initError = null;
|
|
871
|
+
/** Active presence session ID (passive time tracking). */
|
|
872
|
+
this._presenceSessionId = null;
|
|
873
|
+
/** Heartbeat interval for presence tracking. */
|
|
874
|
+
this._presenceInterval = null;
|
|
875
|
+
/** Whether presence is paused (tab hidden / app backgrounded). */
|
|
876
|
+
this._presencePaused = false;
|
|
871
877
|
this.config = config;
|
|
872
878
|
if (config.apiKey) {
|
|
873
879
|
this.pendingInit = this.resolveFromApiKey(config.apiKey);
|
|
@@ -2513,6 +2519,7 @@ var BugBearClient = class {
|
|
|
2513
2519
|
lastMessageAt: row.last_message_at,
|
|
2514
2520
|
createdAt: row.created_at,
|
|
2515
2521
|
unreadCount: Number(row.unread_count) || 0,
|
|
2522
|
+
reporterName: row.reporter_name || void 0,
|
|
2516
2523
|
lastMessage: row.last_message_preview ? {
|
|
2517
2524
|
id: "",
|
|
2518
2525
|
threadId: row.thread_id,
|
|
@@ -2952,6 +2959,93 @@ var BugBearClient = class {
|
|
|
2952
2959
|
updatedAt: data.updated_at
|
|
2953
2960
|
};
|
|
2954
2961
|
}
|
|
2962
|
+
// ─── Passive Presence Tracking ──────────────────────────────
|
|
2963
|
+
/** Current presence session ID (null if not tracking). */
|
|
2964
|
+
get presenceSessionId() {
|
|
2965
|
+
return this._presenceSessionId;
|
|
2966
|
+
}
|
|
2967
|
+
/**
|
|
2968
|
+
* Start passive presence tracking for this tester.
|
|
2969
|
+
* Idempotent — reuses an existing active session if one exists.
|
|
2970
|
+
*/
|
|
2971
|
+
async startPresence(platform) {
|
|
2972
|
+
try {
|
|
2973
|
+
await this.ensureReady();
|
|
2974
|
+
const testerInfo = await this.getTesterInfo();
|
|
2975
|
+
if (!testerInfo) return null;
|
|
2976
|
+
const { data, error } = await this.supabase.rpc("upsert_tester_presence", {
|
|
2977
|
+
p_project_id: this.config.projectId,
|
|
2978
|
+
p_tester_id: testerInfo.id,
|
|
2979
|
+
p_platform: platform
|
|
2980
|
+
});
|
|
2981
|
+
if (error) {
|
|
2982
|
+
console.error("BugBear: Failed to start presence", formatPgError(error));
|
|
2983
|
+
return null;
|
|
2984
|
+
}
|
|
2985
|
+
this._presenceSessionId = data;
|
|
2986
|
+
this._presencePaused = false;
|
|
2987
|
+
this.startPresenceHeartbeat();
|
|
2988
|
+
return data;
|
|
2989
|
+
} catch (err) {
|
|
2990
|
+
console.error("BugBear: Error starting presence", err);
|
|
2991
|
+
return null;
|
|
2992
|
+
}
|
|
2993
|
+
}
|
|
2994
|
+
/** Gracefully end the current presence session. */
|
|
2995
|
+
async endPresence() {
|
|
2996
|
+
this.stopPresenceHeartbeat();
|
|
2997
|
+
if (!this._presenceSessionId) return;
|
|
2998
|
+
try {
|
|
2999
|
+
await this.supabase.rpc("end_tester_presence", {
|
|
3000
|
+
p_session_id: this._presenceSessionId
|
|
3001
|
+
});
|
|
3002
|
+
} catch {
|
|
3003
|
+
}
|
|
3004
|
+
this._presenceSessionId = null;
|
|
3005
|
+
}
|
|
3006
|
+
/** Pause heartbeat (tab hidden / app backgrounded). Sends one final beat. */
|
|
3007
|
+
pausePresence() {
|
|
3008
|
+
this._presencePaused = true;
|
|
3009
|
+
this.heartbeatPresence();
|
|
3010
|
+
}
|
|
3011
|
+
/** Resume heartbeat after pause. Restarts if session was cleaned up. */
|
|
3012
|
+
async resumePresence() {
|
|
3013
|
+
if (!this._presenceSessionId) return;
|
|
3014
|
+
this._presencePaused = false;
|
|
3015
|
+
try {
|
|
3016
|
+
const { data } = await this.supabase.rpc("heartbeat_tester_presence", {
|
|
3017
|
+
p_session_id: this._presenceSessionId
|
|
3018
|
+
});
|
|
3019
|
+
if (!data) {
|
|
3020
|
+
this._presenceSessionId = null;
|
|
3021
|
+
}
|
|
3022
|
+
} catch {
|
|
3023
|
+
this._presenceSessionId = null;
|
|
3024
|
+
}
|
|
3025
|
+
}
|
|
3026
|
+
async heartbeatPresence() {
|
|
3027
|
+
if (!this._presenceSessionId || this._presencePaused) return;
|
|
3028
|
+
try {
|
|
3029
|
+
const { data, error } = await this.supabase.rpc("heartbeat_tester_presence", {
|
|
3030
|
+
p_session_id: this._presenceSessionId
|
|
3031
|
+
});
|
|
3032
|
+
if (error || data === false) {
|
|
3033
|
+
this.stopPresenceHeartbeat();
|
|
3034
|
+
this._presenceSessionId = null;
|
|
3035
|
+
}
|
|
3036
|
+
} catch {
|
|
3037
|
+
}
|
|
3038
|
+
}
|
|
3039
|
+
startPresenceHeartbeat() {
|
|
3040
|
+
this.stopPresenceHeartbeat();
|
|
3041
|
+
this._presenceInterval = setInterval(() => this.heartbeatPresence(), 6e4);
|
|
3042
|
+
}
|
|
3043
|
+
stopPresenceHeartbeat() {
|
|
3044
|
+
if (this._presenceInterval) {
|
|
3045
|
+
clearInterval(this._presenceInterval);
|
|
3046
|
+
this._presenceInterval = null;
|
|
3047
|
+
}
|
|
3048
|
+
}
|
|
2955
3049
|
};
|
|
2956
3050
|
function createBugBear(config) {
|
|
2957
3051
|
return new BugBearClient(config);
|