shoonya-sdk 1.3.2 → 1.4.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.cjs CHANGED
@@ -77,6 +77,14 @@ var import_totp_generator2 = __toESM(require("totp-generator"), 1);
77
77
 
78
78
  // src/token-manager.ts
79
79
  var import_totp_generator = __toESM(require("totp-generator"), 1);
80
+
81
+ // src/utils/common.ts
82
+ function ensureTrailingSlash(url) {
83
+ return url.endsWith("/") ? url : url + "/";
84
+ }
85
+ __name(ensureTrailingSlash, "ensureTrailingSlash");
86
+
87
+ // src/token-manager.ts
80
88
  var Tokens = class {
81
89
  static {
82
90
  __name(this, "Tokens");
@@ -90,6 +98,7 @@ var Tokens = class {
90
98
  imei;
91
99
  source = "API";
92
100
  twoFactor;
101
+ authBaseUrl = "https://api.shoonya.com/NorenWClientTP/";
93
102
  constructor() {
94
103
  }
95
104
  updateCred(cred) {
@@ -118,6 +127,12 @@ var Tokens = class {
118
127
  twoFa: this.twoFactor
119
128
  };
120
129
  }
130
+ updateAuthBaseUrl(url) {
131
+ this.authBaseUrl = ensureTrailingSlash(url);
132
+ }
133
+ getAuthBaseUrl() {
134
+ return this.authBaseUrl;
135
+ }
121
136
  };
122
137
  var tokens = new Tokens();
123
138
  async function refreshAccessToken(retryCount = 1) {
@@ -153,7 +168,7 @@ function getAccessToken() {
153
168
  };
154
169
  return new Promise((resolve2, reject) => {
155
170
  const jData = `jData=${JSON.stringify(cred)}`;
156
- fetch("https://api.shoonya.com/NorenWClientTP/QuickAuth", {
171
+ fetch(tokens.getAuthBaseUrl() + "QuickAuth", {
157
172
  method: "POST",
158
173
  body: jData
159
174
  }).then((res) => res.json()).then((data) => {
@@ -266,11 +281,13 @@ var RestClient = class {
266
281
  accountId = "";
267
282
  logger;
268
283
  constructor(cred, params) {
269
- const { logging = false } = params || {};
284
+ const { logging = false, baseUrl = this.httpBaseUrl } = params || {};
270
285
  tokens.updateCred(cred);
271
286
  this.userId = this.accountId = cred.userId;
272
287
  this.logger = new logger_default("shoonya_rest-client", 1024 * 1024);
273
288
  this.logger.logging = logging;
289
+ this.httpBaseUrl = ensureTrailingSlash(baseUrl);
290
+ tokens.updateAuthBaseUrl(this.httpBaseUrl);
274
291
  }
275
292
  async request(path, body) {
276
293
  const needsAuth = !tokens.getAccessToken() && !["login", "logout"].includes(path);
@@ -788,7 +805,8 @@ var WebsocketClient = class extends import_events.EventEmitter {
788
805
  logging = false,
789
806
  logFileType = "SEPARATE",
790
807
  maxRetryAttempt = 3,
791
- heartbeatInterval = 15e3
808
+ heartbeatInterval = 15e3,
809
+ baseUrl = this.wsBaseUrl
792
810
  } = params || {};
793
811
  this.maxRetryAttempt = maxRetryAttempt;
794
812
  this.heartbeatInterval = heartbeatInterval;
@@ -798,6 +816,11 @@ var WebsocketClient = class extends import_events.EventEmitter {
798
816
  logFileType
799
817
  );
800
818
  this.logger.logging ||= logging;
819
+ this.wsBaseUrl = ensureTrailingSlash(baseUrl);
820
+ const derivedAuthBaseUrl = this.inferAuthBaseUrlFromWs(this.wsBaseUrl);
821
+ if (derivedAuthBaseUrl) {
822
+ tokens.updateAuthBaseUrl(derivedAuthBaseUrl);
823
+ }
801
824
  const storedCred = tokens.getCred();
802
825
  const c = storedCred.userId ? storedCred : cred;
803
826
  if (!c) {
@@ -815,6 +838,19 @@ var WebsocketClient = class extends import_events.EventEmitter {
815
838
  );
816
839
  }
817
840
  }
841
+ inferAuthBaseUrlFromWs(wsBaseUrl) {
842
+ if (!wsBaseUrl.includes("/NorenWSTP/")) {
843
+ return null;
844
+ }
845
+ let url = wsBaseUrl.replace("/NorenWSTP/", "/NorenWClientTP/");
846
+ if (url.startsWith("ws://")) {
847
+ url = "http://" + url.slice(5);
848
+ }
849
+ if (url.startsWith("wss://")) {
850
+ url = "https://" + url.slice(6);
851
+ }
852
+ return url;
853
+ }
818
854
  connect() {
819
855
  if (this.ws && (this.ws.readyState === this.ws.CONNECTING || this.ws.readyState === this.ws.OPEN))
820
856
  return;
@@ -825,23 +861,40 @@ var WebsocketClient = class extends import_events.EventEmitter {
825
861
  this.ws.on("error", this.wsErrorEvent);
826
862
  }
827
863
  wsOpenEvent = async () => {
828
- if (!tokens.getAccessToken()) {
829
- await refreshAccessToken();
864
+ try {
865
+ if (!tokens.getAccessToken()) {
866
+ await refreshAccessToken();
867
+ }
868
+ const { userId, accountId } = tokens.getCred();
869
+ const msg = {
870
+ t: "c",
871
+ uid: userId,
872
+ actid: accountId,
873
+ source: "API",
874
+ susertoken: tokens.getAccessToken()
875
+ };
876
+ this.send(msg);
877
+ this.emit("open");
878
+ } catch (error) {
879
+ this.logger.log(`Error in wsOpenEvent: ${error.message}`, "ERROR");
880
+ console.error("Error in wsOpenEvent:", error);
881
+ this.emit("error", error);
882
+ this.ws?.close(1011, "Internal Error");
830
883
  }
831
- const { userId, accountId } = tokens.getCred();
832
- const msg = {
833
- t: "c",
834
- uid: userId,
835
- actid: accountId,
836
- source: "API",
837
- susertoken: tokens.getAccessToken()
838
- };
839
- this.send(msg);
840
- this.emit("open");
841
884
  };
842
885
  wsMessageEvent = (msg) => {
843
- const result = JSON.parse(msg.toString());
844
- if (result.t === "ck" && result.s.toLowerCase() === "ok") {
886
+ let result;
887
+ try {
888
+ result = JSON.parse(msg.toString());
889
+ } catch (error) {
890
+ this.logger.log(`Error parsing message: ${error.message}`, "ERROR");
891
+ console.error("Error parsing message:", error);
892
+ return;
893
+ }
894
+ if (!result || typeof result !== "object") {
895
+ return;
896
+ }
897
+ if (result.t === "ck" && result.s?.toLowerCase() === "ok") {
845
898
  setTimeout(() => {
846
899
  this.logger.log("|WSClient| Connected with Shoonya WS.");
847
900
  this.sendHeartbeat(this.heartbeatInterval);
package/dist/index.d.cts CHANGED
@@ -751,6 +751,7 @@ declare class RestClient {
751
751
  private logger;
752
752
  constructor(cred: UserCred, params?: {
753
753
  logging?: boolean;
754
+ baseUrl?: string;
754
755
  });
755
756
  request<T>(path: Path, body: {
756
757
  data: Record<string, string>;
@@ -931,7 +932,9 @@ declare class WebsocketClient extends EventEmitter {
931
932
  logFileType?: LoggerType;
932
933
  maxRetryAttempt?: number;
933
934
  heartbeatInterval?: number;
935
+ baseUrl?: string;
934
936
  });
937
+ private inferAuthBaseUrlFromWs;
935
938
  connect(): void;
936
939
  private wsOpenEvent;
937
940
  private wsMessageEvent;
package/dist/index.d.ts CHANGED
@@ -751,6 +751,7 @@ declare class RestClient {
751
751
  private logger;
752
752
  constructor(cred: UserCred, params?: {
753
753
  logging?: boolean;
754
+ baseUrl?: string;
754
755
  });
755
756
  request<T>(path: Path, body: {
756
757
  data: Record<string, string>;
@@ -931,7 +932,9 @@ declare class WebsocketClient extends EventEmitter {
931
932
  logFileType?: LoggerType;
932
933
  maxRetryAttempt?: number;
933
934
  heartbeatInterval?: number;
935
+ baseUrl?: string;
934
936
  });
937
+ private inferAuthBaseUrlFromWs;
935
938
  connect(): void;
936
939
  private wsOpenEvent;
937
940
  private wsMessageEvent;
package/dist/index.js CHANGED
@@ -42,6 +42,14 @@ import totp2 from "totp-generator";
42
42
 
43
43
  // src/token-manager.ts
44
44
  import totp from "totp-generator";
45
+
46
+ // src/utils/common.ts
47
+ function ensureTrailingSlash(url) {
48
+ return url.endsWith("/") ? url : url + "/";
49
+ }
50
+ __name(ensureTrailingSlash, "ensureTrailingSlash");
51
+
52
+ // src/token-manager.ts
45
53
  var Tokens = class {
46
54
  static {
47
55
  __name(this, "Tokens");
@@ -55,6 +63,7 @@ var Tokens = class {
55
63
  imei;
56
64
  source = "API";
57
65
  twoFactor;
66
+ authBaseUrl = "https://api.shoonya.com/NorenWClientTP/";
58
67
  constructor() {
59
68
  }
60
69
  updateCred(cred) {
@@ -83,6 +92,12 @@ var Tokens = class {
83
92
  twoFa: this.twoFactor
84
93
  };
85
94
  }
95
+ updateAuthBaseUrl(url) {
96
+ this.authBaseUrl = ensureTrailingSlash(url);
97
+ }
98
+ getAuthBaseUrl() {
99
+ return this.authBaseUrl;
100
+ }
86
101
  };
87
102
  var tokens = new Tokens();
88
103
  async function refreshAccessToken(retryCount = 1) {
@@ -118,7 +133,7 @@ function getAccessToken() {
118
133
  };
119
134
  return new Promise((resolve2, reject) => {
120
135
  const jData = `jData=${JSON.stringify(cred)}`;
121
- fetch("https://api.shoonya.com/NorenWClientTP/QuickAuth", {
136
+ fetch(tokens.getAuthBaseUrl() + "QuickAuth", {
122
137
  method: "POST",
123
138
  body: jData
124
139
  }).then((res) => res.json()).then((data) => {
@@ -238,11 +253,13 @@ var RestClient = class {
238
253
  accountId = "";
239
254
  logger;
240
255
  constructor(cred, params) {
241
- const { logging = false } = params || {};
256
+ const { logging = false, baseUrl = this.httpBaseUrl } = params || {};
242
257
  tokens.updateCred(cred);
243
258
  this.userId = this.accountId = cred.userId;
244
259
  this.logger = new logger_default("shoonya_rest-client", 1024 * 1024);
245
260
  this.logger.logging = logging;
261
+ this.httpBaseUrl = ensureTrailingSlash(baseUrl);
262
+ tokens.updateAuthBaseUrl(this.httpBaseUrl);
246
263
  }
247
264
  async request(path, body) {
248
265
  const needsAuth = !tokens.getAccessToken() && !["login", "logout"].includes(path);
@@ -760,7 +777,8 @@ var WebsocketClient = class extends EventEmitter {
760
777
  logging = false,
761
778
  logFileType = "SEPARATE",
762
779
  maxRetryAttempt = 3,
763
- heartbeatInterval = 15e3
780
+ heartbeatInterval = 15e3,
781
+ baseUrl = this.wsBaseUrl
764
782
  } = params || {};
765
783
  this.maxRetryAttempt = maxRetryAttempt;
766
784
  this.heartbeatInterval = heartbeatInterval;
@@ -770,6 +788,11 @@ var WebsocketClient = class extends EventEmitter {
770
788
  logFileType
771
789
  );
772
790
  this.logger.logging ||= logging;
791
+ this.wsBaseUrl = ensureTrailingSlash(baseUrl);
792
+ const derivedAuthBaseUrl = this.inferAuthBaseUrlFromWs(this.wsBaseUrl);
793
+ if (derivedAuthBaseUrl) {
794
+ tokens.updateAuthBaseUrl(derivedAuthBaseUrl);
795
+ }
773
796
  const storedCred = tokens.getCred();
774
797
  const c = storedCred.userId ? storedCred : cred;
775
798
  if (!c) {
@@ -787,6 +810,19 @@ var WebsocketClient = class extends EventEmitter {
787
810
  );
788
811
  }
789
812
  }
813
+ inferAuthBaseUrlFromWs(wsBaseUrl) {
814
+ if (!wsBaseUrl.includes("/NorenWSTP/")) {
815
+ return null;
816
+ }
817
+ let url = wsBaseUrl.replace("/NorenWSTP/", "/NorenWClientTP/");
818
+ if (url.startsWith("ws://")) {
819
+ url = "http://" + url.slice(5);
820
+ }
821
+ if (url.startsWith("wss://")) {
822
+ url = "https://" + url.slice(6);
823
+ }
824
+ return url;
825
+ }
790
826
  connect() {
791
827
  if (this.ws && (this.ws.readyState === this.ws.CONNECTING || this.ws.readyState === this.ws.OPEN))
792
828
  return;
@@ -797,23 +833,40 @@ var WebsocketClient = class extends EventEmitter {
797
833
  this.ws.on("error", this.wsErrorEvent);
798
834
  }
799
835
  wsOpenEvent = async () => {
800
- if (!tokens.getAccessToken()) {
801
- await refreshAccessToken();
836
+ try {
837
+ if (!tokens.getAccessToken()) {
838
+ await refreshAccessToken();
839
+ }
840
+ const { userId, accountId } = tokens.getCred();
841
+ const msg = {
842
+ t: "c",
843
+ uid: userId,
844
+ actid: accountId,
845
+ source: "API",
846
+ susertoken: tokens.getAccessToken()
847
+ };
848
+ this.send(msg);
849
+ this.emit("open");
850
+ } catch (error) {
851
+ this.logger.log(`Error in wsOpenEvent: ${error.message}`, "ERROR");
852
+ console.error("Error in wsOpenEvent:", error);
853
+ this.emit("error", error);
854
+ this.ws?.close(1011, "Internal Error");
802
855
  }
803
- const { userId, accountId } = tokens.getCred();
804
- const msg = {
805
- t: "c",
806
- uid: userId,
807
- actid: accountId,
808
- source: "API",
809
- susertoken: tokens.getAccessToken()
810
- };
811
- this.send(msg);
812
- this.emit("open");
813
856
  };
814
857
  wsMessageEvent = (msg) => {
815
- const result = JSON.parse(msg.toString());
816
- if (result.t === "ck" && result.s.toLowerCase() === "ok") {
858
+ let result;
859
+ try {
860
+ result = JSON.parse(msg.toString());
861
+ } catch (error) {
862
+ this.logger.log(`Error parsing message: ${error.message}`, "ERROR");
863
+ console.error("Error parsing message:", error);
864
+ return;
865
+ }
866
+ if (!result || typeof result !== "object") {
867
+ return;
868
+ }
869
+ if (result.t === "ck" && result.s?.toLowerCase() === "ok") {
817
870
  setTimeout(() => {
818
871
  this.logger.log("|WSClient| Connected with Shoonya WS.");
819
872
  this.sendHeartbeat(this.heartbeatInterval);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "shoonya-sdk",
3
- "version": "1.3.2",
3
+ "version": "1.4.0",
4
4
  "description": "Wrapper around Shoonya API",
5
5
  "main": "dist/index.cjs",
6
6
  "module": "dist/index.js",