@ganaka/sdk 1.0.1 → 1.0.2

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.d.ts CHANGED
@@ -79,7 +79,7 @@ declare const fetchCandles: ({ developerToken, apiDomain, runId, currentTimestam
79
79
  developerToken: string;
80
80
  apiDomain: string;
81
81
  runId: string | null;
82
- currentTimestamp: Date;
82
+ currentTimestamp: string;
83
83
  currentTimezone?: string;
84
84
  }) => (params: default_2.infer<typeof v1_developer_groww_schemas.getGrowwHistoricalCandles.query>) => Promise<default_2.infer<typeof v1_developer_groww_schemas.getGrowwHistoricalCandles.response>["data"]>;
85
85
 
@@ -89,7 +89,7 @@ declare const fetchQuote: ({ developerToken, apiDomain, runId, currentTimestamp,
89
89
  developerToken: string;
90
90
  apiDomain: string;
91
91
  runId: string | null;
92
- currentTimestamp: Date;
92
+ currentTimestamp: string;
93
93
  currentTimezone?: string;
94
94
  }) => (params: default_2.infer<typeof v1_developer_groww_schemas.getGrowwQuote.query>) => Promise<default_2.infer<typeof v1_developer_groww_schemas.getGrowwQuote.response>["data"] | null>;
95
95
 
@@ -99,7 +99,7 @@ declare const fetchQuoteTimeline: ({ developerToken, apiDomain, runId, currentTi
99
99
  developerToken: string;
100
100
  apiDomain: string;
101
101
  runId: string | null;
102
- currentTimestamp: Date;
102
+ currentTimestamp: string;
103
103
  currentTimezone?: string;
104
104
  }) => (symbol: string, date: Date) => Promise<default_2.infer<typeof v1_developer_groww_schemas.getGrowwQuoteTimeline.response>["data"]["quoteTimeline"]>;
105
105
 
@@ -109,7 +109,7 @@ declare const fetchShortlist: ({ developerToken, apiDomain, runId, currentTimest
109
109
  developerToken: string;
110
110
  apiDomain: string;
111
111
  runId: string | null;
112
- currentTimestamp: Date;
112
+ currentTimestamp: string;
113
113
  currentTimezone?: string;
114
114
  }) => (queryParams: default_2.infer<typeof v1_developer_lists_schemas.getLists.query>) => Promise<default_2.infer<typeof v1_developer_lists_schemas.getLists.response>["data"] | null>;
115
115
 
@@ -117,8 +117,10 @@ export declare type FetchShortlistResponse = Awaited<ReturnType<ReturnType<typeo
117
117
 
118
118
  export declare function ganaka<T>({ fn, startTime, endTime, intervalMinutes, deleteRunAfterCompletion, }: {
119
119
  fn: (context: RunContext) => Promise<T>;
120
- startTime: Date;
121
- endTime: Date;
120
+ /** Start time in IST string format (YYYY-MM-DDTHH:mm:ss) */
121
+ startTime: string;
122
+ /** End time in IST string format (YYYY-MM-DDTHH:mm:ss) */
123
+ endTime: string;
122
124
  intervalMinutes: number;
123
125
  /**
124
126
  * Delete run after completion.
@@ -172,8 +174,8 @@ declare const getCandles: {
172
174
  low: z.ZodNumber;
173
175
  close: z.ZodNumber;
174
176
  }, z.core.$strip>>;
175
- start_time: z.ZodString;
176
- end_time: z.ZodString;
177
+ start_time: z.ZodNullable<z.ZodString>;
178
+ end_time: z.ZodNullable<z.ZodString>;
177
179
  interval_in_minutes: z.ZodNumber;
178
180
  }, z.core.$strip>;
179
181
  }, z.core.$strip>;
@@ -752,7 +754,11 @@ export declare interface RunContext {
752
754
  fetchQuote: ReturnType<typeof fetchQuote>;
753
755
  fetchQuoteTimeline: ReturnType<typeof fetchQuoteTimeline>;
754
756
  fetchShortlist: ReturnType<typeof fetchShortlist>;
755
- currentTimestamp: Date;
757
+ /**
758
+ * Current timestamp in IST string format (YYYY-MM-DDTHH:mm:ss)
759
+ * for every loop iteration
760
+ */
761
+ currentTimestamp: string;
756
762
  }
757
763
 
758
764
  declare const signIn: {
package/dist/index.js CHANGED
@@ -4402,8 +4402,8 @@ const p = object({
4402
4402
  close: number$1()
4403
4403
  })
4404
4404
  ),
4405
- start_time: string(),
4406
- end_time: string(),
4405
+ start_time: string().nullable(),
4406
+ end_time: string().nullable(),
4407
4407
  interval_in_minutes: number$1()
4408
4408
  })
4409
4409
  })
@@ -7924,8 +7924,7 @@ const fetchCandles = ({
7924
7924
  headers["X-Run-Id"] = runId;
7925
7925
  }
7926
7926
  if (currentTimestamp) {
7927
- const timestampStr = dayjs.tz(currentTimestamp, currentTimezone).format("YYYY-MM-DDTHH:mm:ss");
7928
- headers["X-Current-Timestamp"] = timestampStr;
7927
+ headers["X-Current-Timestamp"] = currentTimestamp;
7929
7928
  }
7930
7929
  if (currentTimezone) {
7931
7930
  headers["X-Current-Timezone"] = currentTimezone;
@@ -7969,8 +7968,7 @@ const fetchQuote = ({
7969
7968
  headers["X-Run-Id"] = runId;
7970
7969
  }
7971
7970
  if (currentTimestamp) {
7972
- const timestampStr = dayjs.tz(currentTimestamp, currentTimezone).format("YYYY-MM-DDTHH:mm:ss");
7973
- headers["X-Current-Timestamp"] = timestampStr;
7971
+ headers["X-Current-Timestamp"] = currentTimestamp;
7974
7972
  }
7975
7973
  if (currentTimezone) {
7976
7974
  headers["X-Current-Timezone"] = currentTimezone;
@@ -8014,8 +8012,7 @@ const fetchQuoteTimeline = ({
8014
8012
  headers["X-Run-Id"] = runId;
8015
8013
  }
8016
8014
  if (currentTimestamp) {
8017
- const timestampStr = dayjs.tz(currentTimestamp, currentTimezone).format("YYYY-MM-DDTHH:mm:ss");
8018
- headers["X-Current-Timestamp"] = timestampStr;
8015
+ headers["X-Current-Timestamp"] = currentTimestamp;
8019
8016
  }
8020
8017
  if (currentTimezone) {
8021
8018
  headers["X-Current-Timezone"] = currentTimezone;
@@ -8059,8 +8056,7 @@ const fetchShortlist = ({
8059
8056
  headers["X-Run-Id"] = runId;
8060
8057
  }
8061
8058
  if (currentTimestamp) {
8062
- const timestampStr = dayjs.tz(currentTimestamp, currentTimezone).format("YYYY-MM-DDTHH:mm:ss");
8063
- headers["X-Current-Timestamp"] = timestampStr;
8059
+ headers["X-Current-Timestamp"] = currentTimestamp;
8064
8060
  }
8065
8061
  if (currentTimezone) {
8066
8062
  headers["X-Current-Timezone"] = currentTimezone;
@@ -8154,7 +8150,7 @@ async function retryWithBackoff(fn, maxRetries = 3, baseDelayMs = 1e3) {
8154
8150
  throw lastError;
8155
8151
  }
8156
8152
  const placeOrder = ({ runId, apiClient }) => async (data) => {
8157
- console.log(data);
8153
+ logger.debug(`data: ${JSON.stringify(data)}`);
8158
8154
  if (runId) {
8159
8155
  try {
8160
8156
  await retryWithBackoff(
@@ -8270,73 +8266,144 @@ class ApiClient {
8270
8266
  }
8271
8267
  }
8272
8268
  }
8273
- function getNextIntervalBoundary(timestamp, intervalMinutes) {
8274
- const date2 = dayjs(timestamp);
8275
- const currentMinute = date2.minute();
8276
- const currentSecond = date2.second();
8277
- const currentMillisecond = date2.millisecond();
8278
- const minutesIntoHour = currentMinute % intervalMinutes;
8279
- if (minutesIntoHour === 0 && currentSecond === 0 && currentMillisecond === 0) {
8280
- return date2.add(intervalMinutes, "minute").toDate();
8281
- }
8282
- const minutesToAdd = intervalMinutes - minutesIntoHour;
8283
- return date2.add(minutesToAdd, "minute").second(0).millisecond(0).toDate();
8284
- }
8269
+ var calendar$1 = { exports: {} };
8270
+ (function(module2, exports$1) {
8271
+ !function(e, t2) {
8272
+ module2.exports = t2();
8273
+ }(commonjsGlobal, function() {
8274
+ return function(e, t2, a) {
8275
+ var n2 = "h:mm A", d2 = { lastDay: "[Yesterday at] " + n2, sameDay: "[Today at] " + n2, nextDay: "[Tomorrow at] " + n2, nextWeek: "dddd [at] " + n2, lastWeek: "[Last] dddd [at] " + n2, sameElse: "MM/DD/YYYY" };
8276
+ t2.prototype.calendar = function(e2, t3) {
8277
+ var n3 = t3 || this.$locale().calendar || d2, o2 = a(e2 || void 0).startOf("d"), s = this.diff(o2, "d", true), i2 = "sameElse", f2 = s < -6 ? i2 : s < -1 ? "lastWeek" : s < 0 ? "lastDay" : s < 1 ? "sameDay" : s < 2 ? "nextDay" : s < 7 ? "nextWeek" : i2, l2 = n3[f2] || d2[f2];
8278
+ return "function" == typeof l2 ? l2.call(this, a()) : this.format(l2);
8279
+ };
8280
+ };
8281
+ });
8282
+ })(calendar$1);
8283
+ var calendarExports = calendar$1.exports;
8284
+ const calendar = /* @__PURE__ */ getDefaultExportFromCjs(calendarExports);
8285
+ var relativeTime$1 = { exports: {} };
8286
+ (function(module2, exports$1) {
8287
+ !function(r2, e) {
8288
+ module2.exports = e();
8289
+ }(commonjsGlobal, function() {
8290
+ return function(r2, e, t2) {
8291
+ r2 = r2 || {};
8292
+ var n2 = e.prototype, o2 = { future: "in %s", past: "%s ago", s: "a few seconds", m: "a minute", mm: "%d minutes", h: "an hour", hh: "%d hours", d: "a day", dd: "%d days", M: "a month", MM: "%d months", y: "a year", yy: "%d years" };
8293
+ function i2(r3, e2, t3, o3) {
8294
+ return n2.fromToBase(r3, e2, t3, o3);
8295
+ }
8296
+ t2.en.relativeTime = o2, n2.fromToBase = function(e2, n3, i3, d3, u) {
8297
+ for (var f2, a, s, l2 = i3.$locale().relativeTime || o2, h = r2.thresholds || [{ l: "s", r: 44, d: "second" }, { l: "m", r: 89 }, { l: "mm", r: 44, d: "minute" }, { l: "h", r: 89 }, { l: "hh", r: 21, d: "hour" }, { l: "d", r: 35 }, { l: "dd", r: 25, d: "day" }, { l: "M", r: 45 }, { l: "MM", r: 10, d: "month" }, { l: "y", r: 17 }, { l: "yy", d: "year" }], m2 = h.length, c2 = 0; c2 < m2; c2 += 1) {
8298
+ var y2 = h[c2];
8299
+ y2.d && (f2 = d3 ? t2(e2).diff(i3, y2.d, true) : i3.diff(e2, y2.d, true));
8300
+ var p2 = (r2.rounding || Math.round)(Math.abs(f2));
8301
+ if (s = f2 > 0, p2 <= y2.r || !y2.r) {
8302
+ p2 <= 1 && c2 > 0 && (y2 = h[c2 - 1]);
8303
+ var v2 = l2[y2.l];
8304
+ u && (p2 = u("" + p2)), a = "string" == typeof v2 ? v2.replace("%d", p2) : v2(p2, n3, y2.l, s);
8305
+ break;
8306
+ }
8307
+ }
8308
+ if (n3) return a;
8309
+ var M2 = s ? l2.future : l2.past;
8310
+ return "function" == typeof M2 ? M2(a) : M2.replace("%s", a);
8311
+ }, n2.to = function(r3, e2) {
8312
+ return i2(r3, e2, this, true);
8313
+ }, n2.from = function(r3, e2) {
8314
+ return i2(r3, e2, this);
8315
+ };
8316
+ var d2 = function(r3) {
8317
+ return r3.$u ? t2.utc() : t2();
8318
+ };
8319
+ n2.toNow = function(r3) {
8320
+ return this.to(d2(this), r3);
8321
+ }, n2.fromNow = function(r3) {
8322
+ return this.from(d2(this), r3);
8323
+ };
8324
+ };
8325
+ });
8326
+ })(relativeTime$1);
8327
+ var relativeTimeExports = relativeTime$1.exports;
8328
+ const relativeTime = /* @__PURE__ */ getDefaultExportFromCjs(relativeTimeExports);
8329
+ dayjs.extend(utc);
8330
+ dayjs.extend(timezone);
8331
+ dayjs.extend(calendar);
8332
+ dayjs.extend(relativeTime);
8285
8333
  function sleep(ms) {
8286
8334
  return new Promise((resolve) => setTimeout(resolve, ms));
8287
8335
  }
8288
8336
  async function runMinuteLoop({
8289
- startTime,
8290
- endTime,
8291
- callback,
8292
- intervalMinutes
8337
+ startTimeDayJS,
8338
+ endTimeDayJS,
8339
+ intervalMinutes,
8340
+ callback
8293
8341
  }) {
8294
- const now = /* @__PURE__ */ new Date();
8295
- const isSimulationMode = now < startTime || now > endTime;
8342
+ let currentISTDayJS = dayjs.utc().tz("Asia/Kolkata");
8343
+ logger.debug(`currentIST: ${currentISTDayJS.format("YYYY-MM-DDTHH:mm:ss")}`);
8344
+ logger.debug(`startTime: ${startTimeDayJS.format("YYYY-MM-DDTHH:mm:ss")}`);
8345
+ logger.debug(`endTime: ${endTimeDayJS.format("YYYY-MM-DDTHH:mm:ss")}`);
8346
+ const isSimulationMode = currentISTDayJS.isAfter(endTimeDayJS);
8296
8347
  if (isSimulationMode) {
8297
- console.log("Current time is outside the specified range, simulating loop");
8348
+ logger.info("Current time is after endTime, simulating loop");
8349
+ }
8350
+ if (currentISTDayJS.isBefore(startTimeDayJS)) {
8351
+ const delayUntilStart = startTimeDayJS.diff(currentISTDayJS, "millisecond");
8352
+ logger.info(
8353
+ `Starting loop ${startTimeDayJS.from(currentISTDayJS)} at ${startTimeDayJS.format(
8354
+ "YYYY-MM-DD HH:mm"
8355
+ )}`
8356
+ );
8357
+ await sleep(delayUntilStart);
8358
+ currentISTDayJS = currentISTDayJS.add(delayUntilStart, "millisecond");
8359
+ }
8360
+ if (currentISTDayJS.isAfter(startTimeDayJS) && currentISTDayJS.isBefore(endTimeDayJS)) {
8361
+ startTimeDayJS = currentISTDayJS;
8298
8362
  }
8299
- const startDate = dayjs(startTime);
8300
- const startMinute = startDate.minute();
8363
+ const startMinute = startTimeDayJS.minute();
8301
8364
  const minutesToFirstBoundary = intervalMinutes - startMinute % intervalMinutes;
8302
- const isOnBoundary = startMinute % intervalMinutes === 0 && startDate.second() === 0 && startDate.millisecond() === 0;
8303
- let nextBoundary;
8365
+ const isOnBoundary = startMinute % intervalMinutes === 0 && startTimeDayJS.second() === 0 && startTimeDayJS.millisecond() === 0;
8366
+ let nextBoundaryDayJS;
8304
8367
  if (isOnBoundary) {
8305
- nextBoundary = startTime;
8368
+ nextBoundaryDayJS = startTimeDayJS;
8306
8369
  } else {
8307
- nextBoundary = startDate.add(minutesToFirstBoundary, "minute").second(0).millisecond(0).toDate();
8370
+ nextBoundaryDayJS = startTimeDayJS.add(minutesToFirstBoundary, "minute").second(0).millisecond(0);
8308
8371
  }
8372
+ logger.debug(`nextBoundary: ${nextBoundaryDayJS.format("YYYY-MM-DDTHH:mm:ss")}`);
8309
8373
  if (isSimulationMode) {
8310
- while (nextBoundary <= endTime) {
8374
+ while (nextBoundaryDayJS.isBefore(endTimeDayJS) || nextBoundaryDayJS.isSame(endTimeDayJS)) {
8311
8375
  try {
8312
- await callback(nextBoundary);
8376
+ await callback(nextBoundaryDayJS.format("YYYY-MM-DDTHH:mm:ss"));
8313
8377
  } catch (error) {
8314
8378
  console.error(
8315
- `Error executing callback at ${nextBoundary.toISOString()}:`,
8379
+ `Error executing callback at ${nextBoundaryDayJS.format("YYYY-MM-DDTHH:mm:ss")}:`,
8316
8380
  error
8317
8381
  );
8318
8382
  }
8319
- nextBoundary = dayjs(nextBoundary).add(intervalMinutes, "minute").toDate();
8383
+ nextBoundaryDayJS = nextBoundaryDayJS.add(intervalMinutes, "minute");
8320
8384
  }
8321
8385
  return;
8322
8386
  }
8323
- if (startTime < now && nextBoundary < now) {
8324
- nextBoundary = getNextIntervalBoundary(now, intervalMinutes);
8325
- }
8326
- while (nextBoundary <= endTime) {
8327
- const delay = nextBoundary.getTime() - Date.now();
8387
+ while (nextBoundaryDayJS.isBefore(endTimeDayJS) || nextBoundaryDayJS.isSame(endTimeDayJS)) {
8388
+ const delay = nextBoundaryDayJS.diff(currentISTDayJS, "millisecond");
8328
8389
  if (delay > 0) {
8390
+ logger.info(
8391
+ `Waiting for ${nextBoundaryDayJS.from(
8392
+ currentISTDayJS,
8393
+ true
8394
+ )} to reach next execution time: ${nextBoundaryDayJS.format("YYYY-MM-DD HH:mm:ss")}`
8395
+ );
8329
8396
  await sleep(delay);
8330
8397
  }
8331
8398
  try {
8332
- await callback(nextBoundary);
8399
+ await callback(nextBoundaryDayJS.format("YYYY-MM-DDTHH:mm:ss"));
8333
8400
  } catch (error) {
8334
8401
  console.error(
8335
- `Error executing callback at ${nextBoundary.toISOString()}:`,
8402
+ `Error executing callback at ${nextBoundaryDayJS.format("YYYY-MM-DDTHH:mm:ss")}:`,
8336
8403
  error
8337
8404
  );
8338
8405
  }
8339
- nextBoundary = dayjs(nextBoundary).add(intervalMinutes, "minute").toDate();
8406
+ nextBoundaryDayJS = nextBoundaryDayJS.add(intervalMinutes, "minute");
8340
8407
  }
8341
8408
  }
8342
8409
  dotenv.config();
@@ -8357,10 +8424,15 @@ async function ganaka({
8357
8424
  );
8358
8425
  }
8359
8426
  const apiClient = new ApiClient({ developerToken, apiDomain });
8427
+ const startTimeDayJS = dayjs.tz(startTime, "Asia/Kolkata");
8428
+ const endTimeDayJS = dayjs.tz(endTime, "Asia/Kolkata");
8429
+ if (startTimeDayJS.isAfter(endTimeDayJS)) {
8430
+ throw new Error("Start time cannot be after end time");
8431
+ }
8360
8432
  let runId = null;
8361
8433
  const createRunBody = {
8362
- start_datetime: dayjs.tz(startTime, "Asia/Kolkata").format("YYYY-MM-DDTHH:mm:ss"),
8363
- end_datetime: dayjs.tz(endTime, "Asia/Kolkata").format("YYYY-MM-DDTHH:mm:ss"),
8434
+ start_datetime: startTime,
8435
+ end_datetime: endTime,
8364
8436
  timezone: "Asia/Kolkata"
8365
8437
  };
8366
8438
  try {
@@ -8384,8 +8456,8 @@ async function ganaka({
8384
8456
  }
8385
8457
  try {
8386
8458
  await runMinuteLoop({
8387
- startTime,
8388
- endTime,
8459
+ startTimeDayJS,
8460
+ endTimeDayJS,
8389
8461
  intervalMinutes,
8390
8462
  callback: async (currentTimestamp) => {
8391
8463
  await fn({