@blinkdotnew/sdk 0.6.0 → 0.6.2
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 +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +73 -10
- package/dist/index.mjs +73 -10
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -681,6 +681,7 @@ declare class BlinkRealtimeChannel implements RealtimeChannel {
|
|
|
681
681
|
private isSubscribed;
|
|
682
682
|
private reconnectTimer;
|
|
683
683
|
private heartbeatTimer;
|
|
684
|
+
private reconnectAttempts;
|
|
684
685
|
constructor(channelName: string, httpClient: HttpClient, projectId: string);
|
|
685
686
|
subscribe(options?: {
|
|
686
687
|
userId?: string;
|
|
@@ -709,6 +710,7 @@ declare class BlinkRealtimeImpl implements BlinkRealtime {
|
|
|
709
710
|
private httpClient;
|
|
710
711
|
private projectId;
|
|
711
712
|
private channels;
|
|
713
|
+
private handlers;
|
|
712
714
|
constructor(httpClient: HttpClient, projectId: string);
|
|
713
715
|
channel(name: string): RealtimeChannel;
|
|
714
716
|
subscribe(channelName: string, callback: (message: RealtimeMessage) => void, options?: RealtimeSubscribeOptions): Promise<() => void>;
|
package/dist/index.d.ts
CHANGED
|
@@ -681,6 +681,7 @@ declare class BlinkRealtimeChannel implements RealtimeChannel {
|
|
|
681
681
|
private isSubscribed;
|
|
682
682
|
private reconnectTimer;
|
|
683
683
|
private heartbeatTimer;
|
|
684
|
+
private reconnectAttempts;
|
|
684
685
|
constructor(channelName: string, httpClient: HttpClient, projectId: string);
|
|
685
686
|
subscribe(options?: {
|
|
686
687
|
userId?: string;
|
|
@@ -709,6 +710,7 @@ declare class BlinkRealtimeImpl implements BlinkRealtime {
|
|
|
709
710
|
private httpClient;
|
|
710
711
|
private projectId;
|
|
711
712
|
private channels;
|
|
713
|
+
private handlers;
|
|
712
714
|
constructor(httpClient: HttpClient, projectId: string);
|
|
713
715
|
channel(name: string): RealtimeChannel;
|
|
714
716
|
subscribe(channelName: string, callback: (message: RealtimeMessage) => void, options?: RealtimeSubscribeOptions): Promise<() => void>;
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
4
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
5
|
+
}) : x)(function(x) {
|
|
6
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
7
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
8
|
+
});
|
|
9
|
+
|
|
3
10
|
// ../core/src/types.ts
|
|
4
11
|
var BlinkError = class extends Error {
|
|
5
12
|
constructor(message, code, status, details) {
|
|
@@ -2474,6 +2481,17 @@ var BlinkDataImpl = class {
|
|
|
2474
2481
|
};
|
|
2475
2482
|
|
|
2476
2483
|
// src/realtime.ts
|
|
2484
|
+
var getWebSocketClass = () => {
|
|
2485
|
+
if (typeof WebSocket !== "undefined") {
|
|
2486
|
+
return WebSocket;
|
|
2487
|
+
}
|
|
2488
|
+
try {
|
|
2489
|
+
const WS = __require("ws");
|
|
2490
|
+
return WS;
|
|
2491
|
+
} catch (error) {
|
|
2492
|
+
throw new BlinkRealtimeError('WebSocket is not available. Install "ws" package for Node.js environments.');
|
|
2493
|
+
}
|
|
2494
|
+
};
|
|
2477
2495
|
var BlinkRealtimeChannel = class {
|
|
2478
2496
|
constructor(channelName, httpClient, projectId) {
|
|
2479
2497
|
this.channelName = channelName;
|
|
@@ -2486,6 +2504,7 @@ var BlinkRealtimeChannel = class {
|
|
|
2486
2504
|
isSubscribed = false;
|
|
2487
2505
|
reconnectTimer = null;
|
|
2488
2506
|
heartbeatTimer = null;
|
|
2507
|
+
reconnectAttempts = 0;
|
|
2489
2508
|
async subscribe(options = {}) {
|
|
2490
2509
|
if (this.isSubscribed) {
|
|
2491
2510
|
return;
|
|
@@ -2576,7 +2595,9 @@ var BlinkRealtimeChannel = class {
|
|
|
2576
2595
|
channel: this.channelName,
|
|
2577
2596
|
limit: options.limit,
|
|
2578
2597
|
start: options.after,
|
|
2598
|
+
// after = start from this ID onwards
|
|
2579
2599
|
end: options.before
|
|
2600
|
+
// before = end at this ID
|
|
2580
2601
|
});
|
|
2581
2602
|
return response.data.messages;
|
|
2582
2603
|
} catch (error) {
|
|
@@ -2586,16 +2607,24 @@ var BlinkRealtimeChannel = class {
|
|
|
2586
2607
|
}
|
|
2587
2608
|
}
|
|
2588
2609
|
async connectWebSocket() {
|
|
2589
|
-
if (this.websocket && this.websocket.readyState ===
|
|
2610
|
+
if (this.websocket && this.websocket.readyState === 1) {
|
|
2590
2611
|
return;
|
|
2591
2612
|
}
|
|
2592
2613
|
return new Promise((resolve, reject) => {
|
|
2593
2614
|
try {
|
|
2594
|
-
const
|
|
2615
|
+
const httpClient = this.httpClient;
|
|
2616
|
+
const coreUrl = httpClient.coreUrl || "https://core.blink.new";
|
|
2617
|
+
const baseUrl = coreUrl.includes("localhost") ? "ws://localhost:3000" : coreUrl.replace("https://", "wss://").replace("http://", "ws://");
|
|
2595
2618
|
const wsUrl = `${baseUrl}?project_id=${this.projectId}`;
|
|
2596
|
-
|
|
2619
|
+
const WSClass = getWebSocketClass();
|
|
2620
|
+
this.websocket = new WSClass(wsUrl);
|
|
2621
|
+
if (!this.websocket) {
|
|
2622
|
+
reject(new BlinkRealtimeError("Failed to create WebSocket instance"));
|
|
2623
|
+
return;
|
|
2624
|
+
}
|
|
2597
2625
|
this.websocket.onopen = () => {
|
|
2598
2626
|
console.log(`\u{1F517} Connected to realtime for project ${this.projectId}`);
|
|
2627
|
+
this.reconnectAttempts = 0;
|
|
2599
2628
|
resolve();
|
|
2600
2629
|
};
|
|
2601
2630
|
this.websocket.onmessage = (event) => {
|
|
@@ -2616,7 +2645,7 @@ var BlinkRealtimeChannel = class {
|
|
|
2616
2645
|
reject(new BlinkRealtimeError("WebSocket connection failed"));
|
|
2617
2646
|
};
|
|
2618
2647
|
setTimeout(() => {
|
|
2619
|
-
if (this.websocket?.readyState !==
|
|
2648
|
+
if (this.websocket?.readyState !== 1) {
|
|
2620
2649
|
reject(new BlinkRealtimeError("WebSocket connection timeout"));
|
|
2621
2650
|
}
|
|
2622
2651
|
}, 5e3);
|
|
@@ -2664,8 +2693,8 @@ var BlinkRealtimeChannel = class {
|
|
|
2664
2693
|
if (this.heartbeatTimer) {
|
|
2665
2694
|
clearInterval(this.heartbeatTimer);
|
|
2666
2695
|
}
|
|
2667
|
-
this.heartbeatTimer =
|
|
2668
|
-
if (this.websocket && this.websocket.readyState ===
|
|
2696
|
+
this.heartbeatTimer = globalThis.setInterval(() => {
|
|
2697
|
+
if (this.websocket && this.websocket.readyState === 1) {
|
|
2669
2698
|
this.websocket.send(JSON.stringify({ type: "ping", payload: {} }));
|
|
2670
2699
|
}
|
|
2671
2700
|
}, 25e3);
|
|
@@ -2674,7 +2703,12 @@ var BlinkRealtimeChannel = class {
|
|
|
2674
2703
|
if (this.reconnectTimer) {
|
|
2675
2704
|
clearTimeout(this.reconnectTimer);
|
|
2676
2705
|
}
|
|
2677
|
-
this.
|
|
2706
|
+
this.reconnectAttempts++;
|
|
2707
|
+
const baseDelay = Math.min(3e4, Math.pow(2, this.reconnectAttempts) * 1e3);
|
|
2708
|
+
const jitter = Math.random() * 1e3;
|
|
2709
|
+
const delay = baseDelay + jitter;
|
|
2710
|
+
console.log(`\u{1F504} Scheduling reconnect attempt ${this.reconnectAttempts} in ${Math.round(delay)}ms`);
|
|
2711
|
+
this.reconnectTimer = globalThis.setTimeout(async () => {
|
|
2678
2712
|
if (this.isSubscribed) {
|
|
2679
2713
|
try {
|
|
2680
2714
|
await this.connectWebSocket();
|
|
@@ -2693,7 +2727,7 @@ var BlinkRealtimeChannel = class {
|
|
|
2693
2727
|
this.scheduleReconnect();
|
|
2694
2728
|
}
|
|
2695
2729
|
}
|
|
2696
|
-
},
|
|
2730
|
+
}, delay);
|
|
2697
2731
|
}
|
|
2698
2732
|
cleanup() {
|
|
2699
2733
|
this.isSubscribed = false;
|
|
@@ -2719,6 +2753,7 @@ var BlinkRealtimeImpl = class {
|
|
|
2719
2753
|
this.projectId = projectId;
|
|
2720
2754
|
}
|
|
2721
2755
|
channels = /* @__PURE__ */ new Map();
|
|
2756
|
+
handlers = {};
|
|
2722
2757
|
channel(name) {
|
|
2723
2758
|
if (!this.channels.has(name)) {
|
|
2724
2759
|
this.channels.set(name, new BlinkRealtimeChannel(name, this.httpClient, this.projectId));
|
|
@@ -2728,7 +2763,21 @@ var BlinkRealtimeImpl = class {
|
|
|
2728
2763
|
async subscribe(channelName, callback, options = {}) {
|
|
2729
2764
|
const channel = this.channel(channelName);
|
|
2730
2765
|
await channel.subscribe(options);
|
|
2731
|
-
|
|
2766
|
+
const state = this.handlers[channelName] ??= {
|
|
2767
|
+
msgHandlers: /* @__PURE__ */ new Set(),
|
|
2768
|
+
presHandlers: /* @__PURE__ */ new Set(),
|
|
2769
|
+
subscribed: true
|
|
2770
|
+
};
|
|
2771
|
+
state.msgHandlers.add(callback);
|
|
2772
|
+
const messageUnsub = channel.onMessage(callback);
|
|
2773
|
+
return () => {
|
|
2774
|
+
messageUnsub();
|
|
2775
|
+
state.msgHandlers.delete(callback);
|
|
2776
|
+
if (state.msgHandlers.size === 0 && state.presHandlers.size === 0) {
|
|
2777
|
+
channel.unsubscribe();
|
|
2778
|
+
delete this.handlers[channelName];
|
|
2779
|
+
}
|
|
2780
|
+
};
|
|
2732
2781
|
}
|
|
2733
2782
|
async publish(channelName, type, data, options = {}) {
|
|
2734
2783
|
const channel = this.channel(channelName);
|
|
@@ -2740,7 +2789,21 @@ var BlinkRealtimeImpl = class {
|
|
|
2740
2789
|
}
|
|
2741
2790
|
onPresence(channelName, callback) {
|
|
2742
2791
|
const channel = this.channel(channelName);
|
|
2743
|
-
|
|
2792
|
+
const state = this.handlers[channelName] ??= {
|
|
2793
|
+
msgHandlers: /* @__PURE__ */ new Set(),
|
|
2794
|
+
presHandlers: /* @__PURE__ */ new Set(),
|
|
2795
|
+
subscribed: false
|
|
2796
|
+
};
|
|
2797
|
+
state.presHandlers.add(callback);
|
|
2798
|
+
const presenceUnsub = channel.onPresence(callback);
|
|
2799
|
+
return () => {
|
|
2800
|
+
presenceUnsub();
|
|
2801
|
+
state.presHandlers.delete(callback);
|
|
2802
|
+
if (state.msgHandlers.size === 0 && state.presHandlers.size === 0) {
|
|
2803
|
+
channel.unsubscribe();
|
|
2804
|
+
delete this.handlers[channelName];
|
|
2805
|
+
}
|
|
2806
|
+
};
|
|
2744
2807
|
}
|
|
2745
2808
|
};
|
|
2746
2809
|
|
package/dist/index.mjs
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
2
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
3
|
+
}) : x)(function(x) {
|
|
4
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
5
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
6
|
+
});
|
|
7
|
+
|
|
1
8
|
// ../core/src/types.ts
|
|
2
9
|
var BlinkError = class extends Error {
|
|
3
10
|
constructor(message, code, status, details) {
|
|
@@ -2472,6 +2479,17 @@ var BlinkDataImpl = class {
|
|
|
2472
2479
|
};
|
|
2473
2480
|
|
|
2474
2481
|
// src/realtime.ts
|
|
2482
|
+
var getWebSocketClass = () => {
|
|
2483
|
+
if (typeof WebSocket !== "undefined") {
|
|
2484
|
+
return WebSocket;
|
|
2485
|
+
}
|
|
2486
|
+
try {
|
|
2487
|
+
const WS = __require("ws");
|
|
2488
|
+
return WS;
|
|
2489
|
+
} catch (error) {
|
|
2490
|
+
throw new BlinkRealtimeError('WebSocket is not available. Install "ws" package for Node.js environments.');
|
|
2491
|
+
}
|
|
2492
|
+
};
|
|
2475
2493
|
var BlinkRealtimeChannel = class {
|
|
2476
2494
|
constructor(channelName, httpClient, projectId) {
|
|
2477
2495
|
this.channelName = channelName;
|
|
@@ -2484,6 +2502,7 @@ var BlinkRealtimeChannel = class {
|
|
|
2484
2502
|
isSubscribed = false;
|
|
2485
2503
|
reconnectTimer = null;
|
|
2486
2504
|
heartbeatTimer = null;
|
|
2505
|
+
reconnectAttempts = 0;
|
|
2487
2506
|
async subscribe(options = {}) {
|
|
2488
2507
|
if (this.isSubscribed) {
|
|
2489
2508
|
return;
|
|
@@ -2574,7 +2593,9 @@ var BlinkRealtimeChannel = class {
|
|
|
2574
2593
|
channel: this.channelName,
|
|
2575
2594
|
limit: options.limit,
|
|
2576
2595
|
start: options.after,
|
|
2596
|
+
// after = start from this ID onwards
|
|
2577
2597
|
end: options.before
|
|
2598
|
+
// before = end at this ID
|
|
2578
2599
|
});
|
|
2579
2600
|
return response.data.messages;
|
|
2580
2601
|
} catch (error) {
|
|
@@ -2584,16 +2605,24 @@ var BlinkRealtimeChannel = class {
|
|
|
2584
2605
|
}
|
|
2585
2606
|
}
|
|
2586
2607
|
async connectWebSocket() {
|
|
2587
|
-
if (this.websocket && this.websocket.readyState ===
|
|
2608
|
+
if (this.websocket && this.websocket.readyState === 1) {
|
|
2588
2609
|
return;
|
|
2589
2610
|
}
|
|
2590
2611
|
return new Promise((resolve, reject) => {
|
|
2591
2612
|
try {
|
|
2592
|
-
const
|
|
2613
|
+
const httpClient = this.httpClient;
|
|
2614
|
+
const coreUrl = httpClient.coreUrl || "https://core.blink.new";
|
|
2615
|
+
const baseUrl = coreUrl.includes("localhost") ? "ws://localhost:3000" : coreUrl.replace("https://", "wss://").replace("http://", "ws://");
|
|
2593
2616
|
const wsUrl = `${baseUrl}?project_id=${this.projectId}`;
|
|
2594
|
-
|
|
2617
|
+
const WSClass = getWebSocketClass();
|
|
2618
|
+
this.websocket = new WSClass(wsUrl);
|
|
2619
|
+
if (!this.websocket) {
|
|
2620
|
+
reject(new BlinkRealtimeError("Failed to create WebSocket instance"));
|
|
2621
|
+
return;
|
|
2622
|
+
}
|
|
2595
2623
|
this.websocket.onopen = () => {
|
|
2596
2624
|
console.log(`\u{1F517} Connected to realtime for project ${this.projectId}`);
|
|
2625
|
+
this.reconnectAttempts = 0;
|
|
2597
2626
|
resolve();
|
|
2598
2627
|
};
|
|
2599
2628
|
this.websocket.onmessage = (event) => {
|
|
@@ -2614,7 +2643,7 @@ var BlinkRealtimeChannel = class {
|
|
|
2614
2643
|
reject(new BlinkRealtimeError("WebSocket connection failed"));
|
|
2615
2644
|
};
|
|
2616
2645
|
setTimeout(() => {
|
|
2617
|
-
if (this.websocket?.readyState !==
|
|
2646
|
+
if (this.websocket?.readyState !== 1) {
|
|
2618
2647
|
reject(new BlinkRealtimeError("WebSocket connection timeout"));
|
|
2619
2648
|
}
|
|
2620
2649
|
}, 5e3);
|
|
@@ -2662,8 +2691,8 @@ var BlinkRealtimeChannel = class {
|
|
|
2662
2691
|
if (this.heartbeatTimer) {
|
|
2663
2692
|
clearInterval(this.heartbeatTimer);
|
|
2664
2693
|
}
|
|
2665
|
-
this.heartbeatTimer =
|
|
2666
|
-
if (this.websocket && this.websocket.readyState ===
|
|
2694
|
+
this.heartbeatTimer = globalThis.setInterval(() => {
|
|
2695
|
+
if (this.websocket && this.websocket.readyState === 1) {
|
|
2667
2696
|
this.websocket.send(JSON.stringify({ type: "ping", payload: {} }));
|
|
2668
2697
|
}
|
|
2669
2698
|
}, 25e3);
|
|
@@ -2672,7 +2701,12 @@ var BlinkRealtimeChannel = class {
|
|
|
2672
2701
|
if (this.reconnectTimer) {
|
|
2673
2702
|
clearTimeout(this.reconnectTimer);
|
|
2674
2703
|
}
|
|
2675
|
-
this.
|
|
2704
|
+
this.reconnectAttempts++;
|
|
2705
|
+
const baseDelay = Math.min(3e4, Math.pow(2, this.reconnectAttempts) * 1e3);
|
|
2706
|
+
const jitter = Math.random() * 1e3;
|
|
2707
|
+
const delay = baseDelay + jitter;
|
|
2708
|
+
console.log(`\u{1F504} Scheduling reconnect attempt ${this.reconnectAttempts} in ${Math.round(delay)}ms`);
|
|
2709
|
+
this.reconnectTimer = globalThis.setTimeout(async () => {
|
|
2676
2710
|
if (this.isSubscribed) {
|
|
2677
2711
|
try {
|
|
2678
2712
|
await this.connectWebSocket();
|
|
@@ -2691,7 +2725,7 @@ var BlinkRealtimeChannel = class {
|
|
|
2691
2725
|
this.scheduleReconnect();
|
|
2692
2726
|
}
|
|
2693
2727
|
}
|
|
2694
|
-
},
|
|
2728
|
+
}, delay);
|
|
2695
2729
|
}
|
|
2696
2730
|
cleanup() {
|
|
2697
2731
|
this.isSubscribed = false;
|
|
@@ -2717,6 +2751,7 @@ var BlinkRealtimeImpl = class {
|
|
|
2717
2751
|
this.projectId = projectId;
|
|
2718
2752
|
}
|
|
2719
2753
|
channels = /* @__PURE__ */ new Map();
|
|
2754
|
+
handlers = {};
|
|
2720
2755
|
channel(name) {
|
|
2721
2756
|
if (!this.channels.has(name)) {
|
|
2722
2757
|
this.channels.set(name, new BlinkRealtimeChannel(name, this.httpClient, this.projectId));
|
|
@@ -2726,7 +2761,21 @@ var BlinkRealtimeImpl = class {
|
|
|
2726
2761
|
async subscribe(channelName, callback, options = {}) {
|
|
2727
2762
|
const channel = this.channel(channelName);
|
|
2728
2763
|
await channel.subscribe(options);
|
|
2729
|
-
|
|
2764
|
+
const state = this.handlers[channelName] ??= {
|
|
2765
|
+
msgHandlers: /* @__PURE__ */ new Set(),
|
|
2766
|
+
presHandlers: /* @__PURE__ */ new Set(),
|
|
2767
|
+
subscribed: true
|
|
2768
|
+
};
|
|
2769
|
+
state.msgHandlers.add(callback);
|
|
2770
|
+
const messageUnsub = channel.onMessage(callback);
|
|
2771
|
+
return () => {
|
|
2772
|
+
messageUnsub();
|
|
2773
|
+
state.msgHandlers.delete(callback);
|
|
2774
|
+
if (state.msgHandlers.size === 0 && state.presHandlers.size === 0) {
|
|
2775
|
+
channel.unsubscribe();
|
|
2776
|
+
delete this.handlers[channelName];
|
|
2777
|
+
}
|
|
2778
|
+
};
|
|
2730
2779
|
}
|
|
2731
2780
|
async publish(channelName, type, data, options = {}) {
|
|
2732
2781
|
const channel = this.channel(channelName);
|
|
@@ -2738,7 +2787,21 @@ var BlinkRealtimeImpl = class {
|
|
|
2738
2787
|
}
|
|
2739
2788
|
onPresence(channelName, callback) {
|
|
2740
2789
|
const channel = this.channel(channelName);
|
|
2741
|
-
|
|
2790
|
+
const state = this.handlers[channelName] ??= {
|
|
2791
|
+
msgHandlers: /* @__PURE__ */ new Set(),
|
|
2792
|
+
presHandlers: /* @__PURE__ */ new Set(),
|
|
2793
|
+
subscribed: false
|
|
2794
|
+
};
|
|
2795
|
+
state.presHandlers.add(callback);
|
|
2796
|
+
const presenceUnsub = channel.onPresence(callback);
|
|
2797
|
+
return () => {
|
|
2798
|
+
presenceUnsub();
|
|
2799
|
+
state.presHandlers.delete(callback);
|
|
2800
|
+
if (state.msgHandlers.size === 0 && state.presHandlers.size === 0) {
|
|
2801
|
+
channel.unsubscribe();
|
|
2802
|
+
delete this.handlers[channelName];
|
|
2803
|
+
}
|
|
2804
|
+
};
|
|
2742
2805
|
}
|
|
2743
2806
|
};
|
|
2744
2807
|
|