@pooflabs/core 0.0.48 → 0.0.49

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.
@@ -40,6 +40,23 @@ export declare function reconnectWithNewAuthV2(): Promise<void>;
40
40
  * a complete teardown and rebuild of connections.
41
41
  */
42
42
  export declare function forceReconnectV2(): Promise<void>;
43
+ /**
44
+ * Returns true if there is an active v2 WebSocket connection open.
45
+ */
46
+ export declare function hasActiveConnection(): boolean;
47
+ export declare function wsGet(path: string): Promise<any>;
48
+ export declare function wsSet(documents: Array<{
49
+ destinationPath: string;
50
+ document: any;
51
+ }>): Promise<any>;
52
+ export declare function wsQuery(path: string, opts?: {
53
+ filter?: any;
54
+ sort?: any;
55
+ limit?: number;
56
+ includeSubPaths?: boolean;
57
+ }): Promise<any>;
58
+ export declare function wsDelete(path: string): Promise<any>;
59
+ export declare function wsGetMany(paths: string[]): Promise<any>;
43
60
  declare global {
44
61
  interface Window {
45
62
  CUSTOM_TAROBASE_APP_ID_HEADER?: string;
package/dist/index.d.ts CHANGED
@@ -2,6 +2,7 @@ export { init } from './client/config';
2
2
  export { getConfig, ClientConfig } from './client/config';
3
3
  export { get, getMany, set, setMany, setFile, getFiles, runQuery, runQueryMany, runExpression, runExpressionMany, signMessage, signTransaction, signAndSubmitTransaction, count, aggregate, RequestOverrides, SetOptions, GetOptions, RunQueryOptions, CountOptions, AggregateOptions, AggregateOperation, AggregateResult, RunExpressionOptions, RunExpressionResult, InsufficientBalanceError, GetManyResult } from './client/operations';
4
4
  export { subscribe, closeAllSubscriptions, clearCache, getCachedData, reconnectWithNewAuth } from './client/subscription';
5
+ export { hasActiveConnection, wsGet, wsSet, wsQuery, wsDelete, wsGetMany } from './client/subscription-v2';
5
6
  export * from './types';
6
7
  export { getIdToken } from './utils/utils';
7
8
  export { WebSessionManager } from './utils/web-session-manager';
package/dist/index.js CHANGED
@@ -4764,6 +4764,7 @@ async function getOrCreateConnection(appId, isServer) {
4764
4764
  subscriptions: new Map(),
4765
4765
  pendingSubscriptions: new Map(),
4766
4766
  pendingUnsubscriptions: new Map(),
4767
+ pendingRequests: new Map(),
4767
4768
  isConnecting: false,
4768
4769
  isConnected: false,
4769
4770
  appId,
@@ -4862,11 +4863,17 @@ async function getOrCreateConnection(appId, isServer) {
4862
4863
  clearInterval(connection.tokenRefreshTimer);
4863
4864
  connection.tokenRefreshTimer = null;
4864
4865
  }
4866
+ // Reject all pending WS CRUD requests on disconnect (fail fast)
4867
+ for (const [id, pending] of connection.pendingRequests) {
4868
+ clearTimeout(pending.timer);
4869
+ pending.reject(new Error('WebSocket disconnected'));
4870
+ }
4871
+ connection.pendingRequests.clear();
4865
4872
  });
4866
4873
  return connection;
4867
4874
  }
4868
4875
  function handleServerMessage(connection, message) {
4869
- var _a;
4876
+ var _a, _b;
4870
4877
  switch (message.type) {
4871
4878
  case 'subscribed': {
4872
4879
  const subscription = connection.subscriptions.get(message.subscriptionId);
@@ -4911,8 +4918,45 @@ function handleServerMessage(connection, message) {
4911
4918
  }
4912
4919
  break;
4913
4920
  }
4921
+ case 'response': {
4922
+ const pendingReq = connection.pendingRequests.get(message.requestId);
4923
+ if (pendingReq) {
4924
+ connection.pendingRequests.delete(message.requestId);
4925
+ clearTimeout(pendingReq.timer);
4926
+ if (message.status >= 400) {
4927
+ pendingReq.reject(new Error(`Request failed with status ${message.status}`));
4928
+ }
4929
+ else {
4930
+ pendingReq.resolve(message.data);
4931
+ }
4932
+ }
4933
+ break;
4934
+ }
4935
+ case 'setResponse': {
4936
+ const pendingSet = connection.pendingRequests.get(message.requestId);
4937
+ if (pendingSet) {
4938
+ connection.pendingRequests.delete(message.requestId);
4939
+ clearTimeout(pendingSet.timer);
4940
+ if (message.statusCode >= 400) {
4941
+ pendingSet.reject(new Error(((_a = message.body) === null || _a === void 0 ? void 0 : _a.message) || `Set failed with status ${message.statusCode}`));
4942
+ }
4943
+ else {
4944
+ pendingSet.resolve(message.body);
4945
+ }
4946
+ }
4947
+ break;
4948
+ }
4914
4949
  case 'error': {
4915
4950
  console.error('[WS v2] Server error:', message.code, message.message);
4951
+ // Handle CRUD request errors (requestId present)
4952
+ if (message.requestId) {
4953
+ const pendingReq = connection.pendingRequests.get(message.requestId);
4954
+ if (pendingReq) {
4955
+ connection.pendingRequests.delete(message.requestId);
4956
+ clearTimeout(pendingReq.timer);
4957
+ pendingReq.reject(new Error(`${message.code}: ${message.message}`));
4958
+ }
4959
+ }
4916
4960
  if (message.subscriptionId) {
4917
4961
  // Reject pending subscription if this is a subscription error
4918
4962
  const pending = connection.pendingSubscriptions.get(message.subscriptionId);
@@ -4924,7 +4968,7 @@ function handleServerMessage(connection, message) {
4924
4968
  const subscription = connection.subscriptions.get(message.subscriptionId);
4925
4969
  if (subscription) {
4926
4970
  for (const callback of subscription.callbacks) {
4927
- (_a = callback.onError) === null || _a === void 0 ? void 0 : _a.call(callback, new Error(`${message.code}: ${message.message}`));
4971
+ (_b = callback.onError) === null || _b === void 0 ? void 0 : _b.call(callback, new Error(`${message.code}: ${message.message}`));
4928
4972
  }
4929
4973
  }
4930
4974
  }
@@ -5213,6 +5257,97 @@ async function doReconnectWithNewAuth() {
5213
5257
  }
5214
5258
  }
5215
5259
  }
5260
+ // ============ CRUD over WebSocket ============
5261
+ const WS_REQUEST_TIMEOUT_MS = 30000;
5262
+ function generateRequestId() {
5263
+ return `req_${Date.now()}_${Math.random().toString(36).substring(2, 11)}`;
5264
+ }
5265
+ /**
5266
+ * Returns true if there is an active v2 WebSocket connection open.
5267
+ */
5268
+ function hasActiveConnection() {
5269
+ for (const connection of connections.values()) {
5270
+ if (connection.ws && connection.isConnected) {
5271
+ return true;
5272
+ }
5273
+ }
5274
+ return false;
5275
+ }
5276
+ async function sendRequest(msgBuilder) {
5277
+ const config = await getConfig();
5278
+ const appId = config.appId;
5279
+ const connection = await getOrCreateConnection(appId, config.isServer);
5280
+ // Wait for the connection to be open (getOrCreateConnection may return
5281
+ // while still connecting).
5282
+ if (!connection.isConnected && connection.ws) {
5283
+ await new Promise((resolve, reject) => {
5284
+ const timeout = setTimeout(() => {
5285
+ var _a;
5286
+ (_a = connection.ws) === null || _a === void 0 ? void 0 : _a.removeEventListener('open', onOpen);
5287
+ reject(new Error('WebSocket connection timeout'));
5288
+ }, 10000);
5289
+ const onOpen = () => { clearTimeout(timeout); resolve(); };
5290
+ if (connection.isConnected) {
5291
+ clearTimeout(timeout);
5292
+ resolve();
5293
+ return;
5294
+ }
5295
+ connection.ws.addEventListener('open', onOpen);
5296
+ });
5297
+ }
5298
+ if (!connection.ws || !connection.isConnected) {
5299
+ throw new Error('WebSocket connection not available');
5300
+ }
5301
+ const requestId = generateRequestId();
5302
+ const message = msgBuilder(requestId);
5303
+ return new Promise((resolve, reject) => {
5304
+ const timer = setTimeout(() => {
5305
+ connection.pendingRequests.delete(requestId);
5306
+ reject(new Error(`WebSocket request timed out after ${WS_REQUEST_TIMEOUT_MS}ms`));
5307
+ }, WS_REQUEST_TIMEOUT_MS);
5308
+ connection.pendingRequests.set(requestId, { resolve, reject, timer });
5309
+ try {
5310
+ connection.ws.send(JSON.stringify(message));
5311
+ }
5312
+ catch (error) {
5313
+ connection.pendingRequests.delete(requestId);
5314
+ clearTimeout(timer);
5315
+ reject(error);
5316
+ }
5317
+ });
5318
+ }
5319
+ async function wsGet(path) {
5320
+ return sendRequest((requestId) => ({
5321
+ type: 'get',
5322
+ requestId,
5323
+ path,
5324
+ }));
5325
+ }
5326
+ async function wsSet(documents) {
5327
+ return sendRequest((requestId) => ({
5328
+ type: 'set',
5329
+ requestId,
5330
+ documents,
5331
+ }));
5332
+ }
5333
+ async function wsQuery(path, opts) {
5334
+ return sendRequest((requestId) => (Object.assign(Object.assign(Object.assign(Object.assign({ type: 'query', requestId,
5335
+ path }, ((opts === null || opts === void 0 ? void 0 : opts.filter) ? { filter: opts.filter } : {})), ((opts === null || opts === void 0 ? void 0 : opts.sort) ? { sort: opts.sort } : {})), ((opts === null || opts === void 0 ? void 0 : opts.limit) !== undefined ? { limit: opts.limit } : {})), ((opts === null || opts === void 0 ? void 0 : opts.includeSubPaths) ? { includeSubPaths: opts.includeSubPaths } : {}))));
5336
+ }
5337
+ async function wsDelete(path) {
5338
+ return sendRequest((requestId) => ({
5339
+ type: 'delete',
5340
+ requestId,
5341
+ path,
5342
+ }));
5343
+ }
5344
+ async function wsGetMany(paths) {
5345
+ return sendRequest((requestId) => ({
5346
+ type: 'getMany',
5347
+ requestId,
5348
+ paths,
5349
+ }));
5350
+ }
5216
5351
 
5217
5352
  /**
5218
5353
  * WebSocket Subscription Module
@@ -5487,6 +5622,7 @@ exports.getConfig = getConfig;
5487
5622
  exports.getFiles = getFiles;
5488
5623
  exports.getIdToken = getIdToken;
5489
5624
  exports.getMany = getMany;
5625
+ exports.hasActiveConnection = hasActiveConnection;
5490
5626
  exports.init = init;
5491
5627
  exports.reconnectWithNewAuth = reconnectWithNewAuth;
5492
5628
  exports.refreshSession = refreshSession;
@@ -5502,4 +5638,9 @@ exports.signMessage = signMessage;
5502
5638
  exports.signSessionCreateMessage = signSessionCreateMessage;
5503
5639
  exports.signTransaction = signTransaction;
5504
5640
  exports.subscribe = subscribe;
5641
+ exports.wsDelete = wsDelete;
5642
+ exports.wsGet = wsGet;
5643
+ exports.wsGetMany = wsGetMany;
5644
+ exports.wsQuery = wsQuery;
5645
+ exports.wsSet = wsSet;
5505
5646
  //# sourceMappingURL=index.js.map