shoonya-sdk 1.0.0 → 1.1.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/README.md CHANGED
@@ -25,7 +25,7 @@ import { RestClient, WebsocketClient } from "shoonya-sdk";
25
25
  const restClient = new RestClient(credentials, { logging: true });
26
26
  const wsClient = new WebsocketClient({ logging: true }); // No need to pass credential here
27
27
 
28
- const userDetail = restClient.getUserDetails();
28
+ const userDetail = await restClient.getUserDetails();
29
29
  console.log(`Logged in as ${userDetail.actid}`);
30
30
 
31
31
  wsClient.on("connected", () => {
package/dist/index.cjs CHANGED
@@ -175,48 +175,50 @@ var Logger = class {
175
175
  maxSize = 0;
176
176
  fileName = "";
177
177
  logging;
178
+ type;
178
179
  /**
179
180
  *
180
181
  * @param logFileName name to prepend the logs file with
181
182
  * @param size max size of file (in bytes)
182
183
  */
183
- constructor(logFileName, size) {
184
+ constructor(logFileName, size, type = "UNIFIED") {
184
185
  this.logPath = (0, import_node_path.resolve)("./logs", `${logFileName}_${Date.now()}.log`);
185
186
  this.maxSize = size;
186
187
  this.fileName = logFileName;
188
+ this.type = type;
187
189
  }
188
190
  log(msg, logType = "DEBUG") {
189
191
  if (!this.logging)
190
192
  return;
191
- this.checkPathExistance();
193
+ const path = this.checkPathExistance(logType);
192
194
  const content = `${logType}:[${(/* @__PURE__ */ new Date()).toISOString()}]:${msg}
193
195
  `;
194
196
  try {
195
- (0, import_node_fs.appendFileSync)(this.logPath, content);
197
+ (0, import_node_fs.appendFileSync)(path, content);
196
198
  } catch (err) {
197
199
  console.error(`Failed to write to log file: ${err}`);
198
200
  }
199
201
  try {
200
202
  (0, import_node_fs.existsSync)(this.logPath);
201
- this.checkLogSize();
203
+ this.checkLogSize(path);
202
204
  } catch {
203
205
  console.log("Log file not exists");
204
206
  }
205
207
  }
206
- checkLogSize() {
207
- const dirName = (0, import_node_path.dirname)(this.logPath);
208
+ checkLogSize(path) {
209
+ const dirName = (0, import_node_path.dirname)(path);
208
210
  try {
209
- const stats = (0, import_node_fs.statSync)(this.logPath);
211
+ const stats = (0, import_node_fs.statSync)(path);
210
212
  if (stats.size >= this.maxSize) {
211
213
  this.logPath = (0, import_node_path.resolve)(dirName, `${this.fileName}_${Date.now()}.log`);
212
- this.deleteOldestFile();
214
+ this.deleteOldestFile(path);
213
215
  }
214
216
  } catch (err) {
215
217
  console.log("File not found");
216
218
  }
217
219
  }
218
- deleteOldestFile() {
219
- const dirName = (0, import_node_path.dirname)(this.logPath);
220
+ deleteOldestFile(path) {
221
+ const dirName = (0, import_node_path.dirname)(path);
220
222
  const files = (0, import_node_fs.readdirSync)(dirName);
221
223
  const currentDate = /* @__PURE__ */ new Date();
222
224
  const sevenDaysAgo = (/* @__PURE__ */ new Date()).setDate(currentDate.getDate() - 7);
@@ -228,11 +230,13 @@ var Logger = class {
228
230
  }
229
231
  }
230
232
  }
231
- async checkPathExistance() {
232
- const pathExists = (0, import_node_fs.existsSync)(this.logPath);
233
+ checkPathExistance(type) {
234
+ const path = this.type === "SEPARATE" ? `${this.logPath.split(".")[0]}_${type.toLowerCase()}.log` : this.logPath;
235
+ const pathExists = (0, import_node_fs.existsSync)(path);
233
236
  if (!pathExists) {
234
237
  (0, import_node_fs.mkdirSync)((0, import_node_path.dirname)(this.logPath), { recursive: true });
235
238
  }
239
+ return path;
236
240
  }
237
241
  };
238
242
  var logger_default = Logger;
@@ -754,6 +758,7 @@ var WebsocketClient = class extends import_events.EventEmitter {
754
758
  reconnectTimer;
755
759
  subscribedTokens = [];
756
760
  logger;
761
+ maxRetryAttempt;
757
762
  /**
758
763
  *
759
764
  * @param params
@@ -762,12 +767,19 @@ var WebsocketClient = class extends import_events.EventEmitter {
762
767
  constructor(params) {
763
768
  super();
764
769
  const {
765
- reconnectInterval = 3e3,
770
+ reconnectInterval = 3e4,
766
771
  dailyRefreshTime = "09:10+05:30",
767
772
  cred,
768
- logging = false
773
+ logging = false,
774
+ logFileType = "SEPARATE",
775
+ maxRetryAttepmt = 3
769
776
  } = params || {};
770
- this.logger = new logger_default("shoonya_ws-client", 1024 * 1024);
777
+ this.maxRetryAttempt = maxRetryAttepmt;
778
+ this.logger = new logger_default(
779
+ "shoonya_ws-client",
780
+ 1024 * 1024 * 10,
781
+ logFileType
782
+ );
771
783
  this.logger.logging ||= logging;
772
784
  const storedCred = tokens.getCred();
773
785
  const c = storedCred.userId ? storedCred : cred;
@@ -813,7 +825,7 @@ var WebsocketClient = class extends import_events.EventEmitter {
813
825
  };
814
826
  wsMessageEvent = (msg) => {
815
827
  const result = JSON.parse(msg.toString());
816
- if (result.t === "ck") {
828
+ if (result.t === "ck" && result.s.toLowerCase() === "ok") {
817
829
  console.log("Connected with Shoonya Websocket.");
818
830
  this.logger.log("|WSClient| Connected with Shoonya WS.");
819
831
  clearInterval(this.reconnectTimer);
@@ -848,6 +860,7 @@ var WebsocketClient = class extends import_events.EventEmitter {
848
860
  if (code === 1) {
849
861
  try {
850
862
  await refreshAccessToken();
863
+ this.logger.log("Access Token Refreshed");
851
864
  } catch (err) {
852
865
  err instanceof Error && this.logger.log(err.message, "ERROR");
853
866
  }
@@ -856,10 +869,18 @@ var WebsocketClient = class extends import_events.EventEmitter {
856
869
  return;
857
870
  }
858
871
  if (code !== 0) {
859
- this.logger.log("Disconnected. Attempting to reconnect....");
872
+ let retryAttempts = 0;
860
873
  clearInterval(this.reconnectTimer);
861
874
  this.reconnectTimer = setInterval(() => {
875
+ retryAttempts++;
876
+ this.logger.log(
877
+ `Disconnected with error code ${code}. Attempt ${retryAttempts} to reconnect....`
878
+ );
862
879
  this.connect();
880
+ if (this.maxRetryAttempt === retryAttempts) {
881
+ this.logger.log("Max Retry Attempt Reached. Stopped Retrying.");
882
+ clearInterval(this.reconnectInterval);
883
+ }
863
884
  }, this.reconnectInterval);
864
885
  return;
865
886
  }
@@ -888,6 +909,9 @@ var WebsocketClient = class extends import_events.EventEmitter {
888
909
  // unsubcribe depth subscription
889
910
  k: scripList.join("#")
890
911
  };
912
+ this.subscribedTokens = this.subscribedTokens.filter(
913
+ (item) => !scripList.includes(item)
914
+ );
891
915
  this.send(msg);
892
916
  }
893
917
  resubscribe() {
@@ -910,6 +934,7 @@ var WebsocketClient = class extends import_events.EventEmitter {
910
934
  const currentMin = date.getUTCMinutes();
911
935
  const currentHour = date.getUTCHours();
912
936
  if (lastMin !== min && hour === currentHour && min === currentMin) {
937
+ this.logger.log("refreshing access token");
913
938
  this.ws.close(1);
914
939
  lastMin = min;
915
940
  return;
package/dist/index.d.cts CHANGED
@@ -879,6 +879,8 @@ declare class RestClient {
879
879
  };
880
880
  }
881
881
 
882
+ type LoggerType = "UNIFIED" | "SEPARATE";
883
+
882
884
  type DailyTimeString = `${number}:${number}${"+" | "-"}${number}:${number}`;
883
885
  interface Events {
884
886
  open: () => void;
@@ -905,6 +907,7 @@ declare class WebsocketClient extends EventEmitter {
905
907
  private reconnectTimer;
906
908
  private subscribedTokens;
907
909
  private logger;
910
+ private maxRetryAttempt;
908
911
  /**
909
912
  *
910
913
  * @param params
@@ -915,6 +918,8 @@ declare class WebsocketClient extends EventEmitter {
915
918
  dailyRefreshTime?: DailyTimeString;
916
919
  logging?: boolean;
917
920
  cred?: UserCred;
921
+ logFileType?: LoggerType;
922
+ maxRetryAttepmt: number;
918
923
  });
919
924
  connect(): void;
920
925
  private wsOpenEvent;
@@ -930,4 +935,4 @@ declare class WebsocketClient extends EventEmitter {
930
935
  private validateTimezoneString;
931
936
  }
932
937
 
933
- export { AddScripToWatchlist, BaseType, BaseTypeFail, BaseTypeSuccess, BaseTypeWithoutTime, BasketMargin, CancelOrder, ChangePassword, DepthSubscriptionUpdate, ExchMessage, Exchange, ExitSNOOrder, ForgotPassword, GetClientDetails, GetHSToken, GetLimitsParam, GetListOfPredefinedMW, GetListOfPredefinedMWScrip, GetSecurityInfo, GetTokenExpiry, GetUserDetails, GetWatchlist, GetWatchlistNames, HistoricData, Holdings, IndexList, Limits, Login, LoginWithDevicePin, LogoutResponse, MakeKeysRequired, ModifyOrder, OptionChain, Order, OrderBook, OrderInput, OrderMargin, Path, PlaceOrder, PositionBook, ProductConversion, ProductType, RemoveScripFromWatchlist, RestClient, ScripInfo, SearchScrip, Segment, SetDevicePin, SingleOrderHistory, SingleOrderStatus, TopIndexList, TopIndexListNames, TradeBook, UserCred, ValidateHSToken, WebsocketClient, getQuotes, paths };
938
+ export { AddScripToWatchlist, BaseType, BaseTypeFail, BaseTypeSuccess, BaseTypeWithoutTime, BasketMargin, CancelOrder, ChangePassword, DailyTimeString, DepthSubscriptionUpdate, ExchMessage, Exchange, ExitSNOOrder, ForgotPassword, GetClientDetails, GetHSToken, GetLimitsParam, GetListOfPredefinedMW, GetListOfPredefinedMWScrip, GetSecurityInfo, GetTokenExpiry, GetUserDetails, GetWatchlist, GetWatchlistNames, HistoricData, Holdings, IndexList, Limits, Login, LoginWithDevicePin, LogoutResponse, MakeKeysRequired, ModifyOrder, OptionChain, Order, OrderBook, OrderInput, OrderMargin, Path, PlaceOrder, PositionBook, ProductConversion, ProductType, RemoveScripFromWatchlist, RestClient, ScripInfo, SearchScrip, Segment, SetDevicePin, SingleOrderHistory, SingleOrderStatus, TopIndexList, TopIndexListNames, TradeBook, UserCred, ValidateHSToken, WebsocketClient, getQuotes, paths };
package/dist/index.d.ts CHANGED
@@ -879,6 +879,8 @@ declare class RestClient {
879
879
  };
880
880
  }
881
881
 
882
+ type LoggerType = "UNIFIED" | "SEPARATE";
883
+
882
884
  type DailyTimeString = `${number}:${number}${"+" | "-"}${number}:${number}`;
883
885
  interface Events {
884
886
  open: () => void;
@@ -905,6 +907,7 @@ declare class WebsocketClient extends EventEmitter {
905
907
  private reconnectTimer;
906
908
  private subscribedTokens;
907
909
  private logger;
910
+ private maxRetryAttempt;
908
911
  /**
909
912
  *
910
913
  * @param params
@@ -915,6 +918,8 @@ declare class WebsocketClient extends EventEmitter {
915
918
  dailyRefreshTime?: DailyTimeString;
916
919
  logging?: boolean;
917
920
  cred?: UserCred;
921
+ logFileType?: LoggerType;
922
+ maxRetryAttepmt: number;
918
923
  });
919
924
  connect(): void;
920
925
  private wsOpenEvent;
@@ -930,4 +935,4 @@ declare class WebsocketClient extends EventEmitter {
930
935
  private validateTimezoneString;
931
936
  }
932
937
 
933
- export { AddScripToWatchlist, BaseType, BaseTypeFail, BaseTypeSuccess, BaseTypeWithoutTime, BasketMargin, CancelOrder, ChangePassword, DepthSubscriptionUpdate, ExchMessage, Exchange, ExitSNOOrder, ForgotPassword, GetClientDetails, GetHSToken, GetLimitsParam, GetListOfPredefinedMW, GetListOfPredefinedMWScrip, GetSecurityInfo, GetTokenExpiry, GetUserDetails, GetWatchlist, GetWatchlistNames, HistoricData, Holdings, IndexList, Limits, Login, LoginWithDevicePin, LogoutResponse, MakeKeysRequired, ModifyOrder, OptionChain, Order, OrderBook, OrderInput, OrderMargin, Path, PlaceOrder, PositionBook, ProductConversion, ProductType, RemoveScripFromWatchlist, RestClient, ScripInfo, SearchScrip, Segment, SetDevicePin, SingleOrderHistory, SingleOrderStatus, TopIndexList, TopIndexListNames, TradeBook, UserCred, ValidateHSToken, WebsocketClient, getQuotes, paths };
938
+ export { AddScripToWatchlist, BaseType, BaseTypeFail, BaseTypeSuccess, BaseTypeWithoutTime, BasketMargin, CancelOrder, ChangePassword, DailyTimeString, DepthSubscriptionUpdate, ExchMessage, Exchange, ExitSNOOrder, ForgotPassword, GetClientDetails, GetHSToken, GetLimitsParam, GetListOfPredefinedMW, GetListOfPredefinedMWScrip, GetSecurityInfo, GetTokenExpiry, GetUserDetails, GetWatchlist, GetWatchlistNames, HistoricData, Holdings, IndexList, Limits, Login, LoginWithDevicePin, LogoutResponse, MakeKeysRequired, ModifyOrder, OptionChain, Order, OrderBook, OrderInput, OrderMargin, Path, PlaceOrder, PositionBook, ProductConversion, ProductType, RemoveScripFromWatchlist, RestClient, ScripInfo, SearchScrip, Segment, SetDevicePin, SingleOrderHistory, SingleOrderStatus, TopIndexList, TopIndexListNames, TradeBook, UserCred, ValidateHSToken, WebsocketClient, getQuotes, paths };
package/dist/index.js CHANGED
@@ -147,48 +147,50 @@ var Logger = class {
147
147
  maxSize = 0;
148
148
  fileName = "";
149
149
  logging;
150
+ type;
150
151
  /**
151
152
  *
152
153
  * @param logFileName name to prepend the logs file with
153
154
  * @param size max size of file (in bytes)
154
155
  */
155
- constructor(logFileName, size) {
156
+ constructor(logFileName, size, type = "UNIFIED") {
156
157
  this.logPath = resolve("./logs", `${logFileName}_${Date.now()}.log`);
157
158
  this.maxSize = size;
158
159
  this.fileName = logFileName;
160
+ this.type = type;
159
161
  }
160
162
  log(msg, logType = "DEBUG") {
161
163
  if (!this.logging)
162
164
  return;
163
- this.checkPathExistance();
165
+ const path = this.checkPathExistance(logType);
164
166
  const content = `${logType}:[${(/* @__PURE__ */ new Date()).toISOString()}]:${msg}
165
167
  `;
166
168
  try {
167
- appendFileSync(this.logPath, content);
169
+ appendFileSync(path, content);
168
170
  } catch (err) {
169
171
  console.error(`Failed to write to log file: ${err}`);
170
172
  }
171
173
  try {
172
174
  existsSync(this.logPath);
173
- this.checkLogSize();
175
+ this.checkLogSize(path);
174
176
  } catch {
175
177
  console.log("Log file not exists");
176
178
  }
177
179
  }
178
- checkLogSize() {
179
- const dirName = dirname(this.logPath);
180
+ checkLogSize(path) {
181
+ const dirName = dirname(path);
180
182
  try {
181
- const stats = statSync(this.logPath);
183
+ const stats = statSync(path);
182
184
  if (stats.size >= this.maxSize) {
183
185
  this.logPath = resolve(dirName, `${this.fileName}_${Date.now()}.log`);
184
- this.deleteOldestFile();
186
+ this.deleteOldestFile(path);
185
187
  }
186
188
  } catch (err) {
187
189
  console.log("File not found");
188
190
  }
189
191
  }
190
- deleteOldestFile() {
191
- const dirName = dirname(this.logPath);
192
+ deleteOldestFile(path) {
193
+ const dirName = dirname(path);
192
194
  const files = readdirSync(dirName);
193
195
  const currentDate = /* @__PURE__ */ new Date();
194
196
  const sevenDaysAgo = (/* @__PURE__ */ new Date()).setDate(currentDate.getDate() - 7);
@@ -200,11 +202,13 @@ var Logger = class {
200
202
  }
201
203
  }
202
204
  }
203
- async checkPathExistance() {
204
- const pathExists = existsSync(this.logPath);
205
+ checkPathExistance(type) {
206
+ const path = this.type === "SEPARATE" ? `${this.logPath.split(".")[0]}_${type.toLowerCase()}.log` : this.logPath;
207
+ const pathExists = existsSync(path);
205
208
  if (!pathExists) {
206
209
  mkdirSync(dirname(this.logPath), { recursive: true });
207
210
  }
211
+ return path;
208
212
  }
209
213
  };
210
214
  var logger_default = Logger;
@@ -726,6 +730,7 @@ var WebsocketClient = class extends EventEmitter {
726
730
  reconnectTimer;
727
731
  subscribedTokens = [];
728
732
  logger;
733
+ maxRetryAttempt;
729
734
  /**
730
735
  *
731
736
  * @param params
@@ -734,12 +739,19 @@ var WebsocketClient = class extends EventEmitter {
734
739
  constructor(params) {
735
740
  super();
736
741
  const {
737
- reconnectInterval = 3e3,
742
+ reconnectInterval = 3e4,
738
743
  dailyRefreshTime = "09:10+05:30",
739
744
  cred,
740
- logging = false
745
+ logging = false,
746
+ logFileType = "SEPARATE",
747
+ maxRetryAttepmt = 3
741
748
  } = params || {};
742
- this.logger = new logger_default("shoonya_ws-client", 1024 * 1024);
749
+ this.maxRetryAttempt = maxRetryAttepmt;
750
+ this.logger = new logger_default(
751
+ "shoonya_ws-client",
752
+ 1024 * 1024 * 10,
753
+ logFileType
754
+ );
743
755
  this.logger.logging ||= logging;
744
756
  const storedCred = tokens.getCred();
745
757
  const c = storedCred.userId ? storedCred : cred;
@@ -785,7 +797,7 @@ var WebsocketClient = class extends EventEmitter {
785
797
  };
786
798
  wsMessageEvent = (msg) => {
787
799
  const result = JSON.parse(msg.toString());
788
- if (result.t === "ck") {
800
+ if (result.t === "ck" && result.s.toLowerCase() === "ok") {
789
801
  console.log("Connected with Shoonya Websocket.");
790
802
  this.logger.log("|WSClient| Connected with Shoonya WS.");
791
803
  clearInterval(this.reconnectTimer);
@@ -820,6 +832,7 @@ var WebsocketClient = class extends EventEmitter {
820
832
  if (code === 1) {
821
833
  try {
822
834
  await refreshAccessToken();
835
+ this.logger.log("Access Token Refreshed");
823
836
  } catch (err) {
824
837
  err instanceof Error && this.logger.log(err.message, "ERROR");
825
838
  }
@@ -828,10 +841,18 @@ var WebsocketClient = class extends EventEmitter {
828
841
  return;
829
842
  }
830
843
  if (code !== 0) {
831
- this.logger.log("Disconnected. Attempting to reconnect....");
844
+ let retryAttempts = 0;
832
845
  clearInterval(this.reconnectTimer);
833
846
  this.reconnectTimer = setInterval(() => {
847
+ retryAttempts++;
848
+ this.logger.log(
849
+ `Disconnected with error code ${code}. Attempt ${retryAttempts} to reconnect....`
850
+ );
834
851
  this.connect();
852
+ if (this.maxRetryAttempt === retryAttempts) {
853
+ this.logger.log("Max Retry Attempt Reached. Stopped Retrying.");
854
+ clearInterval(this.reconnectInterval);
855
+ }
835
856
  }, this.reconnectInterval);
836
857
  return;
837
858
  }
@@ -860,6 +881,9 @@ var WebsocketClient = class extends EventEmitter {
860
881
  // unsubcribe depth subscription
861
882
  k: scripList.join("#")
862
883
  };
884
+ this.subscribedTokens = this.subscribedTokens.filter(
885
+ (item) => !scripList.includes(item)
886
+ );
863
887
  this.send(msg);
864
888
  }
865
889
  resubscribe() {
@@ -882,6 +906,7 @@ var WebsocketClient = class extends EventEmitter {
882
906
  const currentMin = date.getUTCMinutes();
883
907
  const currentHour = date.getUTCHours();
884
908
  if (lastMin !== min && hour === currentHour && min === currentMin) {
909
+ this.logger.log("refreshing access token");
885
910
  this.ws.close(1);
886
911
  lastMin = min;
887
912
  return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "shoonya-sdk",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "Wrapper around Shoonya API",
5
5
  "main": "dist/index.cjs",
6
6
  "module": "dist/index.js",