@chainstream-io/sdk 0.1.21 → 0.1.22

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.
@@ -268,10 +268,24 @@ var StreamApi = class {
268
268
  constructor(context) {
269
269
  __publicField(this, "realtimeClient");
270
270
  __publicField(this, "listenersMap");
271
- const realtimeEndpoint = this.buildWsUrl(context.streamUrl, context.accessToken);
271
+ __publicField(this, "context");
272
+ __publicField(this, "initPromise", null);
273
+ this.context = context;
274
+ this.listenersMap = /* @__PURE__ */ new Map();
275
+ }
276
+ /**
277
+ * Initialize Centrifuge client with current token
278
+ * This is called lazily when connect() is called
279
+ */
280
+ async initClient() {
281
+ if (this.realtimeClient) {
282
+ return;
283
+ }
284
+ const token = await this.getTokenValue();
285
+ const realtimeEndpoint = this.buildWsUrl(this.context.streamUrl, token);
272
286
  this.realtimeClient = new Centrifuge(realtimeEndpoint, {
273
287
  getToken: async (_ctx) => {
274
- return typeof context.accessToken === "string" ? context.accessToken : await context.accessToken.getToken();
288
+ return this.getTokenValue();
275
289
  }
276
290
  });
277
291
  this.realtimeClient.on("connected", () => {
@@ -281,34 +295,73 @@ var StreamApi = class {
281
295
  }).on("error", (err) => {
282
296
  console.error("[streaming] error: ", err);
283
297
  });
284
- this.listenersMap = /* @__PURE__ */ new Map();
298
+ }
299
+ /**
300
+ * Wait for initialization to complete
301
+ * If not initialized, auto-connect first
302
+ */
303
+ async ensureInitialized() {
304
+ if (!this.initPromise) {
305
+ this.connect();
306
+ }
307
+ await this.initPromise;
308
+ }
309
+ /**
310
+ * Get token value from string or TokenProvider
311
+ */
312
+ async getTokenValue() {
313
+ return typeof this.context.accessToken === "string" ? this.context.accessToken : await this.context.accessToken.getToken();
285
314
  }
286
315
  /**
287
316
  * Build WebSocket URL with token as query parameter
288
317
  */
289
- buildWsUrl(endpoint, accessToken) {
318
+ buildWsUrl(endpoint, token) {
290
319
  const url = new URL(endpoint);
291
- if (typeof accessToken === "string") {
292
- url.searchParams.set("token", accessToken);
293
- }
320
+ url.searchParams.set("token", token);
294
321
  return url.toString();
295
322
  }
323
+ /**
324
+ * Connect to the WebSocket server.
325
+ * This is automatically called when you use subscribe methods if not already connected.
326
+ * You can also call this method manually for explicit control.
327
+ */
296
328
  connect() {
297
- this.realtimeClient.connect();
329
+ this.initPromise = this.initClient().then(() => {
330
+ this.realtimeClient.connect();
331
+ });
332
+ }
333
+ /**
334
+ * Disconnect from the WebSocket server.
335
+ * All subscriptions will be automatically removed.
336
+ */
337
+ disconnect() {
338
+ if (this.realtimeClient) {
339
+ this.realtimeClient.disconnect();
340
+ }
341
+ }
342
+ /**
343
+ * Check if the WebSocket is currently connected.
344
+ */
345
+ isConnected() {
346
+ return this.realtimeClient?.state === "connected";
298
347
  }
299
348
  /**
300
349
  * Start batching commands for efficient bulk operations
301
350
  * All subscription commands after this call will be batched until stopBatching is called
302
351
  */
303
352
  startBatching() {
304
- this.realtimeClient.startBatching();
353
+ if (this.realtimeClient) {
354
+ this.realtimeClient.startBatching();
355
+ }
305
356
  }
306
357
  /**
307
358
  * Stop batching and flush all collected commands to the server
308
359
  * This will send all batched subscription commands in a single network request
309
360
  */
310
361
  stopBatching() {
311
- this.realtimeClient.stopBatching();
362
+ if (this.realtimeClient) {
363
+ this.realtimeClient.stopBatching();
364
+ }
312
365
  }
313
366
  /**
314
367
  * Batch subscribe method that accepts a function containing subscription calls
@@ -338,26 +391,31 @@ var StreamApi = class {
338
391
  });
339
392
  }
340
393
  subscribe(channel, fn, filter, methodName) {
341
- let sub = this.realtimeClient.getSubscription(channel);
342
394
  let listeners = this.listenersMap.get(channel);
343
- if (!sub) {
395
+ if (!listeners) {
344
396
  listeners = /* @__PURE__ */ new Set();
345
397
  this.listenersMap.set(channel, listeners);
346
- console.log("[xrealtime] create new sub: ", channel);
347
- const processedFilter = filter && methodName ? replaceFilterFields(filter, methodName) : filter;
348
- sub = this.realtimeClient.newSubscription(channel, {
349
- delta: "fossil",
350
- ...processedFilter && { filter: processedFilter }
351
- });
352
- sub.on("subscribed", () => {
353
- console.log("[xrealtime] subscribed", channel);
354
- }).on("unsubscribed", () => {
355
- console.log("[xrealtime] unsubscribed", channel);
356
- }).on("publication", (ctx) => {
357
- listeners?.forEach((it) => it(ctx.data));
358
- }).subscribe();
359
398
  }
360
- listeners?.add(fn);
399
+ listeners.add(fn);
400
+ this.ensureInitialized().then(() => {
401
+ let sub = this.realtimeClient.getSubscription(channel);
402
+ if (!sub) {
403
+ console.log("[xrealtime] create new sub: ", channel);
404
+ const processedFilter = filter && methodName ? replaceFilterFields(filter, methodName) : filter;
405
+ sub = this.realtimeClient.newSubscription(channel, {
406
+ delta: "fossil",
407
+ ...processedFilter && { filter: processedFilter }
408
+ });
409
+ sub.on("subscribed", () => {
410
+ console.log("[xrealtime] subscribed", channel);
411
+ }).on("unsubscribed", () => {
412
+ console.log("[xrealtime] unsubscribed", channel);
413
+ }).on("publication", (ctx) => {
414
+ const currentListeners = this.listenersMap.get(channel);
415
+ currentListeners?.forEach((it) => it(ctx.data));
416
+ }).subscribe();
417
+ }
418
+ });
361
419
  return new StreamUnsubscrible(this, channel, fn);
362
420
  }
363
421
  unsubscribe(channel, fn) {
@@ -369,12 +427,14 @@ var StreamApi = class {
369
427
  console.log("unsubscribe, remain listeners: ", listeners.size);
370
428
  if (listeners.size === 0) {
371
429
  console.log("unsubscribe channel: ", channel);
372
- const sub = this.realtimeClient.getSubscription(channel);
373
- if (sub) {
374
- sub.unsubscribe();
375
- this.realtimeClient.removeSubscription(sub);
376
- }
377
430
  this.listenersMap.delete(channel);
431
+ this.ensureInitialized().then(() => {
432
+ const sub = this.realtimeClient.getSubscription(channel);
433
+ if (sub) {
434
+ sub.unsubscribe();
435
+ this.realtimeClient.removeSubscription(sub);
436
+ }
437
+ });
378
438
  }
379
439
  }
380
440
  formatScientificNotation(value) {