@openfeed/sdk-js 1.1.4 → 1.1.6

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.
@@ -0,0 +1,5 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4
+
5
+ ### [1.1.4](https://github.com/openfeed-org/sdk-js/compare/1.1.3...1.1.4) (2023-12-21)
@@ -0,0 +1,10 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4
+
5
+ ### [1.1.5](https://github.com/openfeed-org/sdk-js/compare/1.1.4...1.1.5) (2023-12-22)
6
+
7
+
8
+ ### Bug Fixes
9
+
10
+ * new approach for listening to alias changes ([69f2d7d](https://github.com/openfeed-org/sdk-js/commit/69f2d7d6e5b64d7abeb6c6cda052c6e7f512aef3))
package/CHANGELOG.md CHANGED
@@ -2,4 +2,9 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4
4
 
5
- ### [1.1.4](https://github.com/openfeed-org/sdk-js/compare/1.1.3...1.1.4) (2023-12-21)
5
+ ### [1.1.6](https://github.com/openfeed-org/sdk-js/compare/1.1.5...1.1.6) (2024-02-27)
6
+
7
+
8
+ ### Bug Fixes
9
+
10
+ * enhance unsubscription flow to prevent duplicate race condition ([863a4fe](https://github.com/openfeed-org/sdk-js/commit/863a4fe5e2ff27613b70a9f1638df211fd796acc))
@@ -1 +1 @@
1
- export declare const version = "1.1.4";
1
+ export declare const version = "1.1.6";
package/dist/index.js CHANGED
@@ -8031,7 +8031,7 @@ class ResolutionSource {
8031
8031
  return this.onError;
8032
8032
  }
8033
8033
  }
8034
- const version = "1.1.4";
8034
+ const version = "1.1.6";
8035
8035
  const send = (socket, message) => {
8036
8036
  socket.send(OpenfeedGatewayRequestEncode.encode(toT(message)).finish());
8037
8037
  };
@@ -8073,7 +8073,7 @@ class ConnectionDisposedError extends Error {
8073
8073
  }
8074
8074
  class OpenFeedConnection {
8075
8075
  constructor(connectionToken, socket, listeners, logger) {
8076
- __publicField(this, "subscriptions", /* @__PURE__ */ new Map());
8076
+ __publicField(this, "subscriptionRequests", /* @__PURE__ */ new Map());
8077
8077
  __publicField(this, "exchangeRequests", /* @__PURE__ */ new Map());
8078
8078
  __publicField(this, "instrumentRequests", /* @__PURE__ */ new Map());
8079
8079
  __publicField(this, "definitionsInFlight", /* @__PURE__ */ new Map());
@@ -8157,6 +8157,16 @@ class OpenFeedConnection {
8157
8157
  request.resolve(message.exchangeResponse);
8158
8158
  continue;
8159
8159
  }
8160
+ if (message.subscriptionResponse) {
8161
+ const { correlationId, unsubscribe } = message.subscriptionResponse;
8162
+ if (!unsubscribe) {
8163
+ const request = this.subscriptionRequests.get(correlationId.toString());
8164
+ if (!request)
8165
+ throw new Error(`Subscription response ID ${correlationId} not found`);
8166
+ const [, sub] = request;
8167
+ sub.resolve();
8168
+ }
8169
+ }
8160
8170
  this.listeners.onMessage(message);
8161
8171
  }
8162
8172
  } catch (error) {
@@ -8229,7 +8239,8 @@ class OpenFeedConnection {
8229
8239
  requests: requests.map((r) => toT(r)),
8230
8240
  unsubscribe: false
8231
8241
  };
8232
- this.subscriptions.set(correlationId.toString(), subscriptionRequest);
8242
+ const source = new ResolutionSource();
8243
+ this.subscriptionRequests.set(correlationId.toString(), [subscriptionRequest, source]);
8233
8244
  send(this.socket, { subscriptionRequest });
8234
8245
  return correlationId;
8235
8246
  });
@@ -8237,13 +8248,12 @@ class OpenFeedConnection {
8237
8248
  if (this.whenDisconnectedSource.completed) {
8238
8249
  throw new ConnectionDisposedError("This connection was closed");
8239
8250
  }
8240
- const subscription = this.subscriptions.get(subscriptionId.toString());
8251
+ const subscription = this.subscriptionRequests.get(subscriptionId.toString());
8241
8252
  if (!subscription) {
8242
8253
  throw new Error(`Subscription ID ${subscriptionId} does not exist.`);
8243
8254
  }
8244
- const subscriptionRequest = { ...subscription, unsubscribe: true };
8245
- send(this.socket, { subscriptionRequest });
8246
- this.subscriptions.delete(subscriptionId.toString());
8255
+ const [originalRequest, sub] = subscription;
8256
+ this.fireUnsubscribeWhenReady(originalRequest, sub);
8247
8257
  });
8248
8258
  __publicField(this, "getExchanges", async () => {
8249
8259
  var _a;
@@ -8342,6 +8352,18 @@ class OpenFeedConnection {
8342
8352
  this.socket.close(1e3, error.message);
8343
8353
  this.whenDisconnectedSource.reject(error);
8344
8354
  }
8355
+ // We are keeping this fire and forget, because our problems
8356
+ // would be caused by disconnection, and reconnect will clean up the rest
8357
+ async fireUnsubscribeWhenReady(originalRequest, sub) {
8358
+ try {
8359
+ await sub.whenCompleted;
8360
+ const subscriptionRequest = { ...originalRequest, unsubscribe: true };
8361
+ send(this.socket, { subscriptionRequest });
8362
+ } catch (e) {
8363
+ } finally {
8364
+ this.subscriptionRequests.delete(originalRequest.correlationId.toString());
8365
+ }
8366
+ }
8345
8367
  }
8346
8368
  class OpenFeedClient {
8347
8369
  constructor(url, username, password, listeners, logger, clientId) {
@@ -8599,6 +8621,7 @@ class OpenFeedListeners {
8599
8621
  __publicField(this, "instrumentBySymbol", /* @__PURE__ */ new Map());
8600
8622
  __publicField(this, "instrumentByMarketId", /* @__PURE__ */ new Map());
8601
8623
  __publicField(this, "addDetails", (message) => {
8624
+ var _a, _b, _c;
8602
8625
  let def;
8603
8626
  let symbols;
8604
8627
  const getInstrumentDefinition = (marketId) => {
@@ -8606,22 +8629,49 @@ class OpenFeedListeners {
8606
8629
  return res ?? [void 0, void 0];
8607
8630
  };
8608
8631
  if (message.subscriptionResponse) {
8609
- if (message.subscriptionResponse != null && message.subscriptionResponse.marketId !== Long.ZERO) {
8610
- [def, symbols] = getInstrumentDefinition(message.subscriptionResponse.marketId);
8611
- if (!symbols) {
8612
- symbols = [message.subscriptionResponse.symbol];
8613
- } else if (!symbols.includes(message.subscriptionResponse.symbol)) {
8614
- symbols = [...symbols, message.subscriptionResponse.symbol];
8615
- }
8616
- this.instrumentByMarketId.set(message.subscriptionResponse.marketId.toString(), [def, symbols]);
8632
+ const { marketId, symbol, unsubscribe } = message.subscriptionResponse;
8633
+ if (marketId !== Long.ZERO) {
8634
+ [def, symbols] = getInstrumentDefinition(marketId);
8635
+ if (!unsubscribe) {
8636
+ if (!symbols) {
8637
+ symbols = [symbol];
8638
+ } else if (!symbols.includes(symbol)) {
8639
+ symbols = [...symbols, symbol];
8640
+ }
8641
+ } else {
8642
+ if (symbols) {
8643
+ symbols = symbols.filter((s) => s !== symbol);
8644
+ }
8645
+ this.instrumentBySymbol.delete(symbol);
8646
+ }
8647
+ this.instrumentByMarketId.set(marketId.toString(), [def, symbols]);
8617
8648
  }
8618
8649
  } else if (message.instrumentDefinition) {
8619
8650
  [def, symbols] = getInstrumentDefinition(message.instrumentDefinition.marketId);
8651
+ const { instrumentDefinition } = message;
8620
8652
  this.instrumentByMarketId.set(message.instrumentDefinition.marketId.toString(), [message.instrumentDefinition, symbols]);
8621
- this.instrumentBySymbol.set(message.instrumentDefinition.symbol, message.instrumentDefinition);
8622
- } else if (message.instrumentAction)
8623
- ;
8624
- else {
8653
+ this.instrumentBySymbol.set(message.instrumentDefinition.symbol, instrumentDefinition);
8654
+ symbols == null ? void 0 : symbols.forEach((s) => this.instrumentBySymbol.set(s, instrumentDefinition));
8655
+ } else if (message.instrumentAction) {
8656
+ const { marketId } = ((_a = message.instrumentAction) == null ? void 0 : _a.instrument) ?? {};
8657
+ if (message.instrumentAction.action === ActionType.ALIAS_CHANGED && marketId) {
8658
+ [def, symbols] = getInstrumentDefinition(marketId);
8659
+ const newSymbols = (symbols == null ? void 0 : symbols.filter((s) => !s.includes("*"))) ?? [];
8660
+ if (!newSymbols.length) {
8661
+ this.instrumentByMarketId.delete(marketId.toString());
8662
+ } else {
8663
+ this.instrumentByMarketId.set(marketId.toString(), [def, newSymbols]);
8664
+ }
8665
+ }
8666
+ if (message.instrumentAction.action === ActionType.EXCHANGE_MOVE && marketId) {
8667
+ [def, symbols] = getInstrumentDefinition(marketId);
8668
+ this.instrumentByMarketId.delete(marketId.toString());
8669
+ const newMarketId = (_c = (_b = message.instrumentAction.newInstrument) == null ? void 0 : _b.marketId) == null ? void 0 : _c.toString();
8670
+ if (newMarketId) {
8671
+ this.instrumentByMarketId.set(newMarketId, [def, symbols]);
8672
+ }
8673
+ }
8674
+ } else {
8625
8675
  for (const getter of IDGetters) {
8626
8676
  const id = getter(message);
8627
8677
  if (id !== void 0) {
package/dist/node.js CHANGED
@@ -11655,7 +11655,7 @@ var ResolutionSource = class {
11655
11655
  };
11656
11656
 
11657
11657
  // generated/version.ts
11658
- var version = "1.1.4";
11658
+ var version = "1.1.6";
11659
11659
 
11660
11660
  // src/connection/connection.ts
11661
11661
  var send = (socket, message) => {
@@ -11707,7 +11707,7 @@ var OpenFeedConnection = class {
11707
11707
  this.socket.onclose = this.onClose;
11708
11708
  this.runConnectionWatchLoop();
11709
11709
  }
11710
- subscriptions = /* @__PURE__ */ new Map();
11710
+ subscriptionRequests = /* @__PURE__ */ new Map();
11711
11711
  exchangeRequests = /* @__PURE__ */ new Map();
11712
11712
  instrumentRequests = /* @__PURE__ */ new Map();
11713
11713
  definitionsInFlight = /* @__PURE__ */ new Map();
@@ -11791,6 +11791,16 @@ var OpenFeedConnection = class {
11791
11791
  request.resolve(message.exchangeResponse);
11792
11792
  continue;
11793
11793
  }
11794
+ if (message.subscriptionResponse) {
11795
+ const { correlationId, unsubscribe } = message.subscriptionResponse;
11796
+ if (!unsubscribe) {
11797
+ const request = this.subscriptionRequests.get(correlationId.toString());
11798
+ if (!request)
11799
+ throw new Error(`Subscription response ID ${correlationId} not found`);
11800
+ const [, sub] = request;
11801
+ sub.resolve();
11802
+ }
11803
+ }
11794
11804
  this.listeners.onMessage(message);
11795
11805
  }
11796
11806
  } catch (error) {
@@ -11881,7 +11891,8 @@ var OpenFeedConnection = class {
11881
11891
  requests: requests.map((r) => toT(r)),
11882
11892
  unsubscribe: false
11883
11893
  };
11884
- this.subscriptions.set(correlationId.toString(), subscriptionRequest);
11894
+ const source = new ResolutionSource();
11895
+ this.subscriptionRequests.set(correlationId.toString(), [subscriptionRequest, source]);
11885
11896
  send(this.socket, { subscriptionRequest });
11886
11897
  return correlationId;
11887
11898
  };
@@ -11889,14 +11900,25 @@ var OpenFeedConnection = class {
11889
11900
  if (this.whenDisconnectedSource.completed) {
11890
11901
  throw new ConnectionDisposedError("This connection was closed");
11891
11902
  }
11892
- const subscription = this.subscriptions.get(subscriptionId.toString());
11903
+ const subscription = this.subscriptionRequests.get(subscriptionId.toString());
11893
11904
  if (!subscription) {
11894
11905
  throw new Error(`Subscription ID ${subscriptionId} does not exist.`);
11895
11906
  }
11896
- const subscriptionRequest = { ...subscription, unsubscribe: true };
11897
- send(this.socket, { subscriptionRequest });
11898
- this.subscriptions.delete(subscriptionId.toString());
11907
+ const [originalRequest, sub] = subscription;
11908
+ this.fireUnsubscribeWhenReady(originalRequest, sub);
11899
11909
  };
11910
+ // We are keeping this fire and forget, because our problems
11911
+ // would be caused by disconnection, and reconnect will clean up the rest
11912
+ async fireUnsubscribeWhenReady(originalRequest, sub) {
11913
+ try {
11914
+ await sub.whenCompleted;
11915
+ const subscriptionRequest = { ...originalRequest, unsubscribe: true };
11916
+ send(this.socket, { subscriptionRequest });
11917
+ } catch (e) {
11918
+ } finally {
11919
+ this.subscriptionRequests.delete(originalRequest.correlationId.toString());
11920
+ }
11921
+ }
11900
11922
  getExchanges = async () => {
11901
11923
  var _a;
11902
11924
  if (this.whenDisconnectedSource.completed) {
@@ -12228,6 +12250,7 @@ var OpenFeedListeners = class {
12228
12250
  this.onMessage = this.addDetails;
12229
12251
  }
12230
12252
  addDetails = (message) => {
12253
+ var _a, _b, _c;
12231
12254
  let def;
12232
12255
  let symbols;
12233
12256
  const getInstrumentDefinition = (marketId) => {
@@ -12235,20 +12258,48 @@ var OpenFeedListeners = class {
12235
12258
  return res ?? [void 0, void 0];
12236
12259
  };
12237
12260
  if (message.subscriptionResponse) {
12238
- if (message.subscriptionResponse != null && message.subscriptionResponse.marketId !== long_default.ZERO) {
12239
- [def, symbols] = getInstrumentDefinition(message.subscriptionResponse.marketId);
12240
- if (!symbols) {
12241
- symbols = [message.subscriptionResponse.symbol];
12242
- } else if (!symbols.includes(message.subscriptionResponse.symbol)) {
12243
- symbols = [...symbols, message.subscriptionResponse.symbol];
12261
+ const { marketId, symbol, unsubscribe } = message.subscriptionResponse;
12262
+ if (marketId !== long_default.ZERO) {
12263
+ [def, symbols] = getInstrumentDefinition(marketId);
12264
+ if (!unsubscribe) {
12265
+ if (!symbols) {
12266
+ symbols = [symbol];
12267
+ } else if (!symbols.includes(symbol)) {
12268
+ symbols = [...symbols, symbol];
12269
+ }
12270
+ } else {
12271
+ if (symbols) {
12272
+ symbols = symbols.filter((s) => s !== symbol);
12273
+ }
12274
+ this.instrumentBySymbol.delete(symbol);
12244
12275
  }
12245
- this.instrumentByMarketId.set(message.subscriptionResponse.marketId.toString(), [def, symbols]);
12276
+ this.instrumentByMarketId.set(marketId.toString(), [def, symbols]);
12246
12277
  }
12247
12278
  } else if (message.instrumentDefinition) {
12248
12279
  [def, symbols] = getInstrumentDefinition(message.instrumentDefinition.marketId);
12280
+ const { instrumentDefinition } = message;
12249
12281
  this.instrumentByMarketId.set(message.instrumentDefinition.marketId.toString(), [message.instrumentDefinition, symbols]);
12250
- this.instrumentBySymbol.set(message.instrumentDefinition.symbol, message.instrumentDefinition);
12282
+ this.instrumentBySymbol.set(message.instrumentDefinition.symbol, instrumentDefinition);
12283
+ symbols == null ? void 0 : symbols.forEach((s) => this.instrumentBySymbol.set(s, instrumentDefinition));
12251
12284
  } else if (message.instrumentAction) {
12285
+ const { marketId } = ((_a = message.instrumentAction) == null ? void 0 : _a.instrument) ?? {};
12286
+ if (message.instrumentAction.action === 4 /* ALIAS_CHANGED */ && marketId) {
12287
+ [def, symbols] = getInstrumentDefinition(marketId);
12288
+ const newSymbols = (symbols == null ? void 0 : symbols.filter((s) => !s.includes("*"))) ?? [];
12289
+ if (!newSymbols.length) {
12290
+ this.instrumentByMarketId.delete(marketId.toString());
12291
+ } else {
12292
+ this.instrumentByMarketId.set(marketId.toString(), [def, newSymbols]);
12293
+ }
12294
+ }
12295
+ if (message.instrumentAction.action === 3 /* EXCHANGE_MOVE */ && marketId) {
12296
+ [def, symbols] = getInstrumentDefinition(marketId);
12297
+ this.instrumentByMarketId.delete(marketId.toString());
12298
+ const newMarketId = (_c = (_b = message.instrumentAction.newInstrument) == null ? void 0 : _b.marketId) == null ? void 0 : _c.toString();
12299
+ if (newMarketId) {
12300
+ this.instrumentByMarketId.set(newMarketId, [def, symbols]);
12301
+ }
12302
+ }
12252
12303
  } else {
12253
12304
  for (const getter of IDGetters) {
12254
12305
  const id = getter(message);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openfeed/sdk-js",
3
- "version": "1.1.4",
3
+ "version": "1.1.6",
4
4
  "description": "JavaScript SDK for Barchart OpenFeed",
5
5
  "main": "dist/node.js",
6
6
  "browser": "dist/index.js",