@outbuild-company/schedule-core 1.31.1 → 1.31.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.cts CHANGED
@@ -2657,6 +2657,8 @@ interface BackendCalendarExceptionInput {
2657
2657
  to_date: string;
2658
2658
  workable: boolean;
2659
2659
  shifts?: BackendShiftInput[];
2660
+ /** Recurrence step: `DAILY`, `WEEKLY`, `MONTHLY` or `YEARLY`. Empty or unknown means a plain range. */
2661
+ every_type?: string | null;
2660
2662
  }
2661
2663
  /** Calendar payload accepted at the backend normalization boundary. */
2662
2664
  interface BackendCalendarInput {
package/dist/index.d.ts CHANGED
@@ -2657,6 +2657,8 @@ interface BackendCalendarExceptionInput {
2657
2657
  to_date: string;
2658
2658
  workable: boolean;
2659
2659
  shifts?: BackendShiftInput[];
2660
+ /** Recurrence step: `DAILY`, `WEEKLY`, `MONTHLY` or `YEARLY`. Empty or unknown means a plain range. */
2661
+ every_type?: string | null;
2660
2662
  }
2661
2663
  /** Calendar payload accepted at the backend normalization boundary. */
2662
2664
  interface BackendCalendarInput {
package/dist/index.js CHANGED
@@ -24249,6 +24249,13 @@ function computeProjectWorkHours(calendars) {
24249
24249
  var DAY_MS = 24 * 60 * 60 * 1e3;
24250
24250
  var EXCEPTION_DATE_FORMAT_REGEX = /^(\d{4})[/-](\d{1,2})[/-](\d{1,2})/;
24251
24251
  var WEEKDAYS_PER_WEEK = 7;
24252
+ var EXCEPTION_EVERY_TYPE = {
24253
+ DAILY: "DAILY",
24254
+ WEEKLY: "WEEKLY",
24255
+ MONTHLY: "MONTHLY",
24256
+ YEARLY: "YEARLY"
24257
+ };
24258
+ var MONTHS_PER_YEAR = 12;
24252
24259
  var CALENDAR_FALLBACK_WORKING_DAYS = [false, true, true, true, true, true, false];
24253
24260
  var WORKING_DAY_TRUE_VALUES = /* @__PURE__ */ new Set([
24254
24261
  "1",
@@ -24345,7 +24352,8 @@ function parseExceptionDays(exceptions, range) {
24345
24352
  const rangeKeys = expandRangeToUtcKeys(
24346
24353
  exception.from_date,
24347
24354
  exception.to_date,
24348
- range
24355
+ range,
24356
+ exception.every_type
24349
24357
  );
24350
24358
  if (rangeKeys.length === 0) continue;
24351
24359
  const value = exceptionToDateValue(exception);
@@ -24354,19 +24362,59 @@ function parseExceptionDays(exceptions, range) {
24354
24362
  }
24355
24363
  return Object.keys(map).length > 0 ? map : null;
24356
24364
  }
24357
- function expandRangeToUtcKeys(from, to, range) {
24365
+ function expandRangeToUtcKeys(from, to, range, everyType) {
24358
24366
  const fromTs = parseExceptionDate(from);
24359
24367
  const toTs = parseExceptionDate(to);
24360
24368
  if (fromTs === null || toTs === null) return [];
24361
24369
  if (range && (toTs < range.start || fromTs > range.end)) return [];
24362
- const keys = [];
24363
- let cursor = range ? Math.max(fromTs, range.start) : fromTs;
24370
+ const first = range ? Math.max(fromTs, range.start) : fromTs;
24364
24371
  const last = range ? Math.min(toTs, range.end) : toTs;
24365
- while (cursor <= last) {
24366
- keys.push(String(cursor));
24367
- cursor += DAY_MS;
24372
+ const timestamps = steppedTimestamps(fromTs, first, last, everyType);
24373
+ return timestamps.map(String);
24374
+ }
24375
+ function steppedTimestamps(anchor, first, last, everyType) {
24376
+ switch (everyType) {
24377
+ case EXCEPTION_EVERY_TYPE.DAILY:
24378
+ return everyNthDay(anchor, first, last, 1);
24379
+ case EXCEPTION_EVERY_TYPE.WEEKLY:
24380
+ return everyNthDay(anchor, first, last, WEEKDAYS_PER_WEEK);
24381
+ case EXCEPTION_EVERY_TYPE.MONTHLY:
24382
+ return monthlyOccurrences(anchor, first, last, 1);
24383
+ case EXCEPTION_EVERY_TYPE.YEARLY:
24384
+ return monthlyOccurrences(anchor, first, last, MONTHS_PER_YEAR);
24385
+ default:
24386
+ return everyNthDay(anchor, first, last, 1);
24387
+ }
24388
+ }
24389
+ function everyNthDay(anchor, first, last, stepDays) {
24390
+ const stepMs = stepDays * DAY_MS;
24391
+ const skipped = Math.max(0, Math.ceil((first - anchor) / stepMs));
24392
+ const timestamps = [];
24393
+ for (let cursor = anchor + skipped * stepMs; cursor <= last; cursor += stepMs) {
24394
+ timestamps.push(cursor);
24395
+ }
24396
+ return timestamps;
24397
+ }
24398
+ function monthlyOccurrences(anchor, first, last, stepMonths) {
24399
+ const anchorDate = new Date(anchor);
24400
+ const anchorMonthIndex = anchorDate.getUTCFullYear() * MONTHS_PER_YEAR + anchorDate.getUTCMonth();
24401
+ const firstDate = new Date(first);
24402
+ const firstMonthIndex = firstDate.getUTCFullYear() * MONTHS_PER_YEAR + firstDate.getUTCMonth();
24403
+ const anchorDay = anchorDate.getUTCDate();
24404
+ const skipped = Math.max(
24405
+ 0,
24406
+ Math.floor((firstMonthIndex - anchorMonthIndex) / stepMonths)
24407
+ );
24408
+ const timestamps = [];
24409
+ for (let step = skipped; ; step += 1) {
24410
+ const monthIndex = anchorMonthIndex + step * stepMonths;
24411
+ const year = Math.floor(monthIndex / MONTHS_PER_YEAR);
24412
+ const month = monthIndex % MONTHS_PER_YEAR;
24413
+ const timestamp = Date.UTC(year, month, anchorDay);
24414
+ if (timestamp > last) return timestamps;
24415
+ const dayExists = new Date(timestamp).getUTCMonth() === month;
24416
+ if (dayExists && timestamp >= first) timestamps.push(timestamp);
24368
24417
  }
24369
- return keys;
24370
24418
  }
24371
24419
  function parseExceptionDate(raw) {
24372
24420
  if (typeof raw !== "string") return null;