@torrow/sdk-client 0.23.0 → 0.24.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.js CHANGED
@@ -12322,7 +12322,11 @@ var CalendarsFacade = class extends TorrowItemFacade {
12322
12322
  signal
12323
12323
  }).then((items) => projectReadList(items, (dto) => projectCalendarItem(dto)));
12324
12324
  }
12325
- /** Расписание кейсов календаря — `PUT /api/v1/calendars/{id}/timetable`. */
12325
+ /**
12326
+ * Исходное расписание кейсов календаря — `PUT /api/v1/calendars/{id}/timetable`.
12327
+ * После чтения нужных серверных страниц повторы явно разворачивает `expandRecurringTimetableCases`;
12328
+ * права на исходные строки проверяет сервер.
12329
+ */
12326
12330
  getTimetable(calendarId, body, options) {
12327
12331
  const { signal, ...queryOpts } = options ?? {};
12328
12332
  return this.http.requestJson({
@@ -12533,6 +12537,24 @@ function normalizeCaseActionRidsForWrite(body, path) {
12533
12537
  }
12534
12538
 
12535
12539
  // ../../src/resources/cases/types.ts
12540
+ var AvailabilityTimeValues = /* @__PURE__ */ ((AvailabilityTimeValues2) => {
12541
+ AvailabilityTimeValues2["Unknown"] = "UnknownSystemAvailabilityTime";
12542
+ AvailabilityTimeValues2["Free"] = "Free";
12543
+ AvailabilityTimeValues2["Busy"] = "Busy";
12544
+ return AvailabilityTimeValues2;
12545
+ })(AvailabilityTimeValues || {});
12546
+ var CaseParticipantTypeValues = /* @__PURE__ */ ((CaseParticipantTypeValues2) => {
12547
+ CaseParticipantTypeValues2["Unknown"] = "UnknownCaseParticipantType";
12548
+ CaseParticipantTypeValues2["Consumer"] = "Consumer";
12549
+ CaseParticipantTypeValues2["Executor"] = "Executor";
12550
+ CaseParticipantTypeValues2["Escort"] = "Escort";
12551
+ return CaseParticipantTypeValues2;
12552
+ })(CaseParticipantTypeValues || {});
12553
+ var ShowCaseInTimetableTypeValues = /* @__PURE__ */ ((ShowCaseInTimetableTypeValues2) => {
12554
+ ShowCaseInTimetableTypeValues2["All"] = "All";
12555
+ ShowCaseInTimetableTypeValues2["ExcludeUser"] = "ExcludeUser";
12556
+ return ShowCaseInTimetableTypeValues2;
12557
+ })(ShowCaseInTimetableTypeValues || {});
12536
12558
  var CaseStateValues = {
12537
12559
  Unknown: "UnknownCaseState",
12538
12560
  Verifying: "Verifying",
@@ -13492,7 +13514,11 @@ var ContactsFacade = class extends TorrowItemFacade {
13492
13514
  signal
13493
13515
  }).then((items) => projectReadList(items, (dto) => projectContactItem(dto)));
13494
13516
  }
13495
- /** Расписание по контакту (профиль/исполнитель) — `PUT /api/v1/contacts/{id}/timetable`. */
13517
+ /**
13518
+ * Исходное расписание по контакту (профиль/исполнитель) — `PUT /api/v1/contacts/{id}/timetable`.
13519
+ * После чтения нужных серверных страниц повторы явно разворачивает `expandRecurringTimetableCases`;
13520
+ * права на исходные строки проверяет сервер.
13521
+ */
13496
13522
  getTimetable(contactId, body, options) {
13497
13523
  const { signal, ...queryOpts } = options ?? {};
13498
13524
  return this.http.requestJson({
@@ -15095,6 +15121,8 @@ var ResourcesFacade = class extends TorrowItemFacade {
15095
15121
  }
15096
15122
  /**
15097
15123
  * Расписание заказов, привязанных к **ресурсу** — `PUT /api/v1/resources/{id}/timetable`.
15124
+ * Возвращает исходные строки сервера. Повторы разворачивает отдельный
15125
+ * `expandRecurringTimetableCases` после загрузки нужных страниц; права проверяет сервер.
15098
15126
  */
15099
15127
  getTimetable(resourceId, body, options) {
15100
15128
  const { signal, ...queryOpts } = options ?? {};
@@ -15801,6 +15829,8 @@ var ServicesFacade = class extends TorrowItemFacade {
15801
15829
  /**
15802
15830
  * События/заказы и занятость услуги — `PUT /api/v1/services/{serviceId}/timetable`.
15803
15831
  * Не вычисляет свободные слоты записи: для них используй `getCheckInSchedule` с `type: "FreeTimeSlots"`.
15832
+ * Возвращает исходные `TimetableCase[]`; серверный `take/skip` не считает виртуальные появления.
15833
+ * После чтения нужных страниц вызови `expandRecurringTimetableCases` явно; доступ проверяет сервер.
15804
15834
  */
15805
15835
  getTimetable(serviceId, body, options) {
15806
15836
  const { signal, ...queryOpts } = options ?? {};
@@ -17397,6 +17427,8 @@ var LoyaltyCardsFacade = class extends TorrowItemCoreFacade {
17397
17427
  /**
17398
17428
  * Расписание по карте — `PUT /api/v1/loyaltycards/{torrowId}/timetable`.
17399
17429
  * В torrow-apps: `LoyaltyCardClient.getTimetable`.
17430
+ * Возвращает исходные строки сервера; после чтения нужных страниц повторы явно
17431
+ * разворачивает `expandRecurringTimetableCases`. Права на исходные строки проверяет сервер.
17400
17432
  */
17401
17433
  getTimetable(torrowId, body, options) {
17402
17434
  const { signal, ...queryOpts } = options ?? {};
@@ -17474,6 +17506,38 @@ var UserSettingsFacade = class {
17474
17506
  });
17475
17507
  return { settings: parseOpaqueJsonSettings(dto.settings) };
17476
17508
  }
17509
+ /**
17510
+ * Читает проверенную IANA-зону текущего пользователя из `settings.place.timeZone`.
17511
+ * Отсутствующая, повреждённая или не поддержанная средой зона даёт `null`.
17512
+ * Ошибки GET и отмена запроса сохраняются; зона процесса не используется.
17513
+ */
17514
+ async getTimeZone(options) {
17515
+ const { settings } = await this.get(options);
17516
+ if (settings === null || settings === void 0 || typeof settings !== "object" || Array.isArray(settings)) {
17517
+ return null;
17518
+ }
17519
+ const place = settings.place;
17520
+ if (place === null || typeof place !== "object" || Array.isArray(place)) {
17521
+ return null;
17522
+ }
17523
+ const rawTimeZone = place.timeZone;
17524
+ if (typeof rawTimeZone !== "string") {
17525
+ return null;
17526
+ }
17527
+ const timeZone = rawTimeZone.trim();
17528
+ if (timeZone === "" || /^[+-]/.test(timeZone)) {
17529
+ return null;
17530
+ }
17531
+ try {
17532
+ new Intl.DateTimeFormat("en-US", { timeZone });
17533
+ return timeZone;
17534
+ } catch (error) {
17535
+ if (error instanceof RangeError) {
17536
+ return null;
17537
+ }
17538
+ throw error;
17539
+ }
17540
+ }
17477
17541
  /**
17478
17542
  * `PUT /api/v1/user/settings/update` — принимает JSON в `settings`, на wire уходит string.
17479
17543
  * `null`/`undefined` → `settings: null` в теле.
@@ -17712,7 +17776,11 @@ var UserFacade = class {
17712
17776
  signal: options?.signal
17713
17777
  });
17714
17778
  }
17715
- /** `PUT /api/v1/user/timetable` */
17779
+ /**
17780
+ * Исходные события текущего пользователя — `PUT /api/v1/user/timetable`.
17781
+ * `take/skip` делят серверные строки; повторы явно разворачивает `expandRecurringTimetableCases`
17782
+ * после чтения нужных страниц. Права на строки определяет сервер.
17783
+ */
17716
17784
  getTimetable(body, query, options) {
17717
17785
  return this.http.requestJson({
17718
17786
  method: "PUT",
@@ -18544,6 +18612,558 @@ var TimetableViewTypeValues = {
18544
18612
  Schedule: 5
18545
18613
  };
18546
18614
 
18615
+ // ../../src/resources/common/timetable-cron.ts
18616
+ import Cron from "cron-converter";
18617
+ var TimetableCronError = class extends Error {
18618
+ /** Машинно читаемая причина локального отказа. */
18619
+ failure;
18620
+ constructor(failure) {
18621
+ super(`Timetable cron: ${failure}`);
18622
+ this.name = "TimetableCronError";
18623
+ this.failure = failure;
18624
+ }
18625
+ };
18626
+ var MONTH_NAME = /\b(?:JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)\b/gi;
18627
+ var WEEKDAY_NAME = /\b(?:SUN|MON|TUE|WED|THU|FRI|SAT)\b/gi;
18628
+ var NUMERIC_FIELD = new RegExp("^[-0-9*,/]+$");
18629
+ function createTimetableCronSeeker(expression, earliestStartMs) {
18630
+ const fields = expression.trim().split(/\s+/);
18631
+ if (fields.length !== 5) {
18632
+ throw new TimetableCronError("UnsupportedSyntax" /* UnsupportedSyntax */);
18633
+ }
18634
+ const normalized = fields.map((field, index) => {
18635
+ if (index === 3) {
18636
+ return field.replace(MONTH_NAME, "1");
18637
+ }
18638
+ if (index === 4) {
18639
+ return field.replace(WEEKDAY_NAME, "1");
18640
+ }
18641
+ return field;
18642
+ });
18643
+ if (normalized.some((field) => !NUMERIC_FIELD.test(field))) {
18644
+ throw new TimetableCronError("UnsupportedSyntax" /* UnsupportedSyntax */);
18645
+ }
18646
+ if (!Number.isFinite(earliestStartMs)) {
18647
+ throw new TimetableCronError("InvalidSchedule" /* InvalidSchedule */);
18648
+ }
18649
+ const floorMs = Math.floor(earliestStartMs / 6e4) * 6e4;
18650
+ const floorDate = new Date(floorMs);
18651
+ if (!Number.isFinite(floorDate.getTime())) {
18652
+ throw new TimetableCronError("InvalidSchedule" /* InvalidSchedule */);
18653
+ }
18654
+ let seeker;
18655
+ try {
18656
+ seeker = new Cron().fromString(expression).schedule(floorDate);
18657
+ } catch {
18658
+ throw new TimetableCronError("InvalidSchedule" /* InvalidSchedule */);
18659
+ }
18660
+ let previousMs = floorMs - 6e4;
18661
+ return {
18662
+ next() {
18663
+ let date2;
18664
+ try {
18665
+ date2 = seeker.next().toJSDate();
18666
+ } catch {
18667
+ throw new TimetableCronError("InvalidSchedule" /* InvalidSchedule */);
18668
+ }
18669
+ if (!(date2 instanceof Date) || !Number.isFinite(date2.getTime()) || date2.getTime() <= previousMs) {
18670
+ throw new TimetableCronError("InvalidSchedule" /* InvalidSchedule */);
18671
+ }
18672
+ previousMs = date2.getTime();
18673
+ return date2;
18674
+ }
18675
+ };
18676
+ }
18677
+
18678
+ // ../../src/resources/common/timetable-weekly.ts
18679
+ var DAY_MS = 864e5;
18680
+ function civilOrdinal(year, month, day) {
18681
+ const date2 = /* @__PURE__ */ new Date(0);
18682
+ date2.setUTCFullYear(year, month - 1, day);
18683
+ date2.setUTCHours(0, 0, 0, 0);
18684
+ return date2.getTime();
18685
+ }
18686
+ function zonedCivilOrdinal(formatter, instant) {
18687
+ const parts = formatter.formatToParts(instant);
18688
+ const year = Number(parts.find((part) => part.type === "year")?.value);
18689
+ const month = Number(parts.find((part) => part.type === "month")?.value);
18690
+ const day = Number(parts.find((part) => part.type === "day")?.value);
18691
+ if (!Number.isSafeInteger(year) || !Number.isSafeInteger(month) || !Number.isSafeInteger(day)) {
18692
+ throw new Error("Invalid calendar date");
18693
+ }
18694
+ return civilOrdinal(year, month, day);
18695
+ }
18696
+ function isoWeekNumber(ordinal) {
18697
+ const dayOfWeek = (new Date(ordinal).getUTCDay() + 6) % 7;
18698
+ const thursday = ordinal + (3 - dayOfWeek) * DAY_MS;
18699
+ const weekYear = new Date(thursday).getUTCFullYear();
18700
+ const januaryFourth = civilOrdinal(weekYear, 1, 4);
18701
+ const firstWeekMonday = januaryFourth - (new Date(januaryFourth).getUTCDay() + 6) % 7 * DAY_MS;
18702
+ return Math.floor((ordinal - firstWeekMonday) / (7 * DAY_MS)) + 1;
18703
+ }
18704
+ function safeInteger(value) {
18705
+ const parsed = Number(value);
18706
+ return Number.isSafeInteger(parsed) && parsed >= 0 ? parsed : null;
18707
+ }
18708
+ function parseWeeklyPredicate(expression) {
18709
+ if (expression === "*") {
18710
+ return () => true;
18711
+ }
18712
+ const wildcardStep = /^\*\/(\d+)$/.exec(expression);
18713
+ if (wildcardStep) {
18714
+ const step = safeInteger(wildcardStep[1]);
18715
+ return step ? (week) => week % step === 0 : null;
18716
+ }
18717
+ const predicates = [];
18718
+ for (const part of expression.split(",")) {
18719
+ const single = /^(\d+)$/.exec(part);
18720
+ if (single) {
18721
+ const number = safeInteger(single[1]);
18722
+ if (number === null) {
18723
+ return null;
18724
+ }
18725
+ predicates.push((week) => week === number);
18726
+ continue;
18727
+ }
18728
+ const range = /^(\d+)-(\d+)(?:\/(\d+))?$/.exec(part);
18729
+ if (range) {
18730
+ const first = safeInteger(range[1]);
18731
+ const last = safeInteger(range[2]);
18732
+ const step = range[3] === void 0 ? null : safeInteger(range[3]);
18733
+ if (first === null || last === null || first > last || range[3] !== void 0 && (!step || step <= 0)) {
18734
+ return null;
18735
+ }
18736
+ predicates.push((week) => week >= first && week <= last && (step === null || week % step === 0));
18737
+ continue;
18738
+ }
18739
+ const fromStep = /^(\d+)\/(\d+)$/.exec(part);
18740
+ if (fromStep) {
18741
+ const first = safeInteger(fromStep[1]);
18742
+ const step = safeInteger(fromStep[2]);
18743
+ if (first === null || !step) {
18744
+ return null;
18745
+ }
18746
+ predicates.push((week) => week >= first && (week - first) % step === 0);
18747
+ continue;
18748
+ }
18749
+ return null;
18750
+ }
18751
+ return (week) => predicates.some((predicate) => predicate(week));
18752
+ }
18753
+ function createTimetableWeeklyChecker(weeklyCron, firstWeekDate, timeZone) {
18754
+ const predicate = parseWeeklyPredicate(weeklyCron);
18755
+ if (predicate === null || firstWeekDate != null && (!(firstWeekDate instanceof Date) || !Number.isFinite(firstWeekDate.getTime()))) {
18756
+ return null;
18757
+ }
18758
+ const formatter = new Intl.DateTimeFormat("en-US-u-ca-gregory-nu-latn", {
18759
+ timeZone,
18760
+ year: "numeric",
18761
+ month: "2-digit",
18762
+ day: "2-digit"
18763
+ });
18764
+ const anchorOrdinal = firstWeekDate == null ? null : zonedCivilOrdinal(formatter, firstWeekDate);
18765
+ return (candidateMs) => {
18766
+ const ordinal = zonedCivilOrdinal(formatter, new Date(candidateMs));
18767
+ if (anchorOrdinal !== null) {
18768
+ const daysBetween = Math.abs((ordinal - anchorOrdinal) / DAY_MS);
18769
+ const anchorDay = new Date(anchorOrdinal).getUTCDay();
18770
+ const candidateDay = new Date(ordinal).getUTCDay();
18771
+ const week = Math.floor((daysBetween + anchorDay - candidateDay) / 7) + 1;
18772
+ return predicate(week);
18773
+ }
18774
+ return predicate(isoWeekNumber(ordinal));
18775
+ };
18776
+ }
18777
+
18778
+ // ../../src/resources/common/timetable-recurring.ts
18779
+ var TimetableExpansionKind = /* @__PURE__ */ ((TimetableExpansionKind2) => {
18780
+ TimetableExpansionKind2["StoredCase"] = "stored_case";
18781
+ TimetableExpansionKind2["VirtualOccurrence"] = "virtual_occurrence";
18782
+ TimetableExpansionKind2["UnexpandedSeries"] = "unexpanded_series";
18783
+ return TimetableExpansionKind2;
18784
+ })(TimetableExpansionKind || {});
18785
+ var TimetableUnexpandedReason = /* @__PURE__ */ ((TimetableUnexpandedReason2) => {
18786
+ TimetableUnexpandedReason2["MissingScheduleRanges"] = "MissingScheduleRanges";
18787
+ TimetableUnexpandedReason2["MissingSeriesId"] = "MissingSeriesId";
18788
+ TimetableUnexpandedReason2["MissingWeeklyTimeZone"] = "MissingWeeklyTimeZone";
18789
+ TimetableUnexpandedReason2["InvalidSeriesDates"] = "InvalidSeriesDates";
18790
+ TimetableUnexpandedReason2["InvalidSchedule"] = "InvalidSchedule";
18791
+ TimetableUnexpandedReason2["UnsupportedCronSyntax"] = "UnsupportedCronSyntax";
18792
+ TimetableUnexpandedReason2["UnsupportedRecurrenceRule"] = "UnsupportedRecurrenceRule";
18793
+ return TimetableUnexpandedReason2;
18794
+ })(TimetableUnexpandedReason || {});
18795
+ var DEFAULT_MAX_CANDIDATES = 1e4;
18796
+ var DEFAULT_MAX_ITERATIONS = 1e5;
18797
+ var DEFAULT_MAX_RESULTS = 1e4;
18798
+ function sdkError(category) {
18799
+ return new TorrowSdkError({ category, operation: "expandRecurringTimetableCases" });
18800
+ }
18801
+ function validDate(value) {
18802
+ return value instanceof Date && Number.isFinite(value.getTime());
18803
+ }
18804
+ function validZone(value) {
18805
+ if (/^[+-]\d{1,2}(?::?\d{2})?$/.test(value)) {
18806
+ return false;
18807
+ }
18808
+ try {
18809
+ new Intl.DateTimeFormat("en", { timeZone: value });
18810
+ return true;
18811
+ } catch {
18812
+ return false;
18813
+ }
18814
+ }
18815
+ function budget(value, fallback) {
18816
+ if (value === void 0) {
18817
+ return fallback;
18818
+ }
18819
+ if (!Number.isSafeInteger(value) || value <= 0) {
18820
+ throw sdkError("InvalidInput" /* InvalidInput */);
18821
+ }
18822
+ return value;
18823
+ }
18824
+ function dateKey(source, identity, beginning, ending) {
18825
+ return JSON.stringify([
18826
+ source.timetableId ?? null,
18827
+ identity,
18828
+ beginning?.getTime() ?? null,
18829
+ ending?.getTime() ?? null
18830
+ ]);
18831
+ }
18832
+ function overlaps(beginning, ending, from, to, strict) {
18833
+ return strict ? beginning >= from && ending <= to : beginning < to && ending > from;
18834
+ }
18835
+ function expandRecurringTimetableCases(cases, options) {
18836
+ if (!Array.isArray(cases) || !options || !validDate(options.from) || !validDate(options.to)) {
18837
+ throw sdkError("InvalidInput" /* InvalidInput */);
18838
+ }
18839
+ const from = options.from.getTime();
18840
+ const to = options.to.getTime();
18841
+ if (from >= to || options.userTimeZone != null && (typeof options.userTimeZone !== "string" || !validZone(options.userTimeZone))) {
18842
+ throw sdkError("InvalidInput" /* InvalidInput */);
18843
+ }
18844
+ if (options.resolveRecurrenceContext !== void 0 && typeof options.resolveRecurrenceContext !== "function") {
18845
+ throw sdkError("InvalidInput" /* InvalidInput */);
18846
+ }
18847
+ if (options.strictlyInTimeRange !== void 0 && typeof options.strictlyInTimeRange !== "boolean") {
18848
+ throw sdkError("InvalidInput" /* InvalidInput */);
18849
+ }
18850
+ const maxCandidates = budget(options.maxCandidates, DEFAULT_MAX_CANDIDATES);
18851
+ const maxIterations = budget(options.maxIterations, DEFAULT_MAX_ITERATIONS);
18852
+ const maxResults = budget(options.maxResults, DEFAULT_MAX_RESULTS);
18853
+ const entries = [];
18854
+ let candidateCount = 0;
18855
+ let iterationCount = 0;
18856
+ function append(entry) {
18857
+ entries.push(entry);
18858
+ }
18859
+ function unexpanded(source, index, reason) {
18860
+ const identity = source.itemObject?.id || `row:${index}`;
18861
+ append({
18862
+ kind: "unexpanded_series" /* UnexpandedSeries */,
18863
+ source,
18864
+ reason,
18865
+ key: `${dateKey(source, identity, validDate(source.beginDate) ? source.beginDate : null, validDate(source.endDate) ? source.endDate : null)}:${reason}`
18866
+ });
18867
+ }
18868
+ for (const [index, source] of cases.entries()) {
18869
+ let resolveWeeklyZone2 = function() {
18870
+ if (!recurrenceContextResolved) {
18871
+ let context;
18872
+ try {
18873
+ context = options.resolveRecurrenceContext?.(source);
18874
+ } catch {
18875
+ throw sdkError("InvalidInput" /* InvalidInput */);
18876
+ }
18877
+ if (context != null && (typeof context !== "object" || Array.isArray(context))) {
18878
+ throw sdkError("InvalidInput" /* InvalidInput */);
18879
+ }
18880
+ if (context != null && "then" in context && typeof context.then === "function") {
18881
+ throw sdkError("InvalidInput" /* InvalidInput */);
18882
+ }
18883
+ const explicitZone = context?.weeklyTimeZone;
18884
+ if (explicitZone != null && (typeof explicitZone !== "string" || !validZone(explicitZone))) {
18885
+ throw sdkError("InvalidInput" /* InvalidInput */);
18886
+ }
18887
+ seriesWeeklyZone = explicitZone ?? options.userTimeZone ?? null;
18888
+ recurrenceContextResolved = true;
18889
+ }
18890
+ return seriesWeeklyZone;
18891
+ };
18892
+ var resolveWeeklyZone = resolveWeeklyZone2;
18893
+ if (!source || typeof source !== "object") {
18894
+ throw sdkError("InvalidInput" /* InvalidInput */);
18895
+ }
18896
+ const beginDate = validDate(source.beginDate) ? source.beginDate : null;
18897
+ const endDate = validDate(source.endDate) ? source.endDate : null;
18898
+ const sourceId = typeof source.itemObject?.id === "string" && source.itemObject.id.length > 0 ? source.itemObject.id : null;
18899
+ if (!source.schedule || source.groupId) {
18900
+ if (beginDate && endDate && !overlaps(beginDate.getTime(), endDate.getTime(), from, to, !!options.strictlyInTimeRange)) {
18901
+ continue;
18902
+ }
18903
+ append({
18904
+ kind: "stored_case" /* StoredCase */,
18905
+ source,
18906
+ caseId: sourceId,
18907
+ beginDate,
18908
+ endDate,
18909
+ key: dateKey(source, sourceId ?? `row:${index}`, beginDate, endDate)
18910
+ });
18911
+ continue;
18912
+ }
18913
+ if (!sourceId) {
18914
+ unexpanded(source, index, "MissingSeriesId" /* MissingSeriesId */);
18915
+ continue;
18916
+ }
18917
+ if (!beginDate || !endDate || endDate.getTime() <= beginDate.getTime()) {
18918
+ unexpanded(source, index, "InvalidSeriesDates" /* InvalidSeriesDates */);
18919
+ continue;
18920
+ }
18921
+ const ranges = source.schedule.scheduleRanges;
18922
+ if (ranges == null || Array.isArray(ranges) && ranges.length === 0) {
18923
+ unexpanded(source, index, "MissingScheduleRanges" /* MissingScheduleRanges */);
18924
+ continue;
18925
+ }
18926
+ if (!Array.isArray(ranges)) {
18927
+ unexpanded(source, index, "InvalidSchedule" /* InvalidSchedule */);
18928
+ continue;
18929
+ }
18930
+ const exceptions = source.schedule.scheduleRangeExceptions;
18931
+ if (exceptions != null && (typeof exceptions !== "object" || Array.isArray(exceptions))) {
18932
+ unexpanded(source, index, "InvalidSchedule" /* InvalidSchedule */);
18933
+ continue;
18934
+ }
18935
+ const rawExcluded = exceptions?.excludedTimeRanges;
18936
+ const rawReplaced = exceptions?.replacedTimeRanges;
18937
+ if (rawExcluded != null && !Array.isArray(rawExcluded) || rawReplaced != null && !Array.isArray(rawReplaced)) {
18938
+ unexpanded(source, index, "InvalidSchedule" /* InvalidSchedule */);
18939
+ continue;
18940
+ }
18941
+ const excludedRanges = [];
18942
+ const replacedRanges = [];
18943
+ let invalidException = false;
18944
+ for (const excluded of rawExcluded ?? []) {
18945
+ if (!excluded || !validDate(excluded.begin) || !validDate(excluded.end)) {
18946
+ invalidException = true;
18947
+ break;
18948
+ }
18949
+ const excludeBegin = excluded.begin.getTime();
18950
+ const excludeEnd = excluded.end.getTime();
18951
+ if (excludeEnd < excludeBegin) {
18952
+ invalidException = true;
18953
+ break;
18954
+ }
18955
+ excludedRanges.push({ begin: excludeBegin, end: excludeEnd });
18956
+ }
18957
+ for (const replaced of rawReplaced ?? []) {
18958
+ if (!replaced || !validDate(replaced.begin) || !validDate(replaced.end)) {
18959
+ invalidException = true;
18960
+ break;
18961
+ }
18962
+ replacedRanges.push({ begin: replaced.begin.getTime(), end: replaced.end.getTime() });
18963
+ }
18964
+ if (invalidException) {
18965
+ unexpanded(source, index, "InvalidSchedule" /* InvalidSchedule */);
18966
+ continue;
18967
+ }
18968
+ const replacementStarts = /* @__PURE__ */ new Map();
18969
+ for (let replacementIndex = replacedRanges.length - 1; replacementIndex >= 0; replacementIndex -= 1) {
18970
+ const replacement = replacedRanges[replacementIndex];
18971
+ replacementStarts.set(replacement.begin, replacementStarts.get(replacement.end) ?? replacement.end);
18972
+ }
18973
+ const seriesEntries = [];
18974
+ let seriesReason = null;
18975
+ let seriesWeeklyZone = null;
18976
+ let recurrenceContextResolved = false;
18977
+ for (const range of ranges) {
18978
+ if (!range || typeof range !== "object") {
18979
+ seriesReason = "InvalidSchedule" /* InvalidSchedule */;
18980
+ break;
18981
+ }
18982
+ const beginning = validDate(range.beginning) ? range.beginning.getTime() : Number.NaN;
18983
+ const ending = validDate(range.ending) ? range.ending.getTime() : Number.NaN;
18984
+ const duration = ending - beginning;
18985
+ if (!Number.isFinite(duration) || duration <= 0) {
18986
+ seriesReason = "InvalidSchedule" /* InvalidSchedule */;
18987
+ break;
18988
+ }
18989
+ const recurrence = range.recurringConditions;
18990
+ const cronExpression = recurrence?.cron;
18991
+ const hasCron = cronExpression != null;
18992
+ if (hasCron && (typeof cronExpression !== "string" || cronExpression.trim().length === 0)) {
18993
+ seriesReason = "InvalidSchedule" /* InvalidSchedule */;
18994
+ break;
18995
+ }
18996
+ const lower = recurrence?.beginDate == null ? beginning : validDate(recurrence.beginDate) ? recurrence.beginDate.getTime() : Number.NaN;
18997
+ const upper = recurrence?.endDate == null ? Number.POSITIVE_INFINITY : validDate(recurrence.endDate) ? recurrence.endDate.getTime() : Number.NaN;
18998
+ if (!Number.isFinite(lower) || Number.isNaN(upper) || lower > upper) {
18999
+ seriesReason = "InvalidSchedule" /* InvalidSchedule */;
19000
+ break;
19001
+ }
19002
+ const repeatSeconds = recurrence?.repeatInterval;
19003
+ const repeating = hasCron || repeatSeconds != null;
19004
+ const step = !hasCron && repeatSeconds != null ? repeatSeconds * 1e3 : 0;
19005
+ if (!hasCron && repeating && (!Number.isSafeInteger(repeatSeconds) || repeatSeconds <= 0 || !Number.isSafeInteger(step))) {
19006
+ seriesReason = "InvalidSchedule" /* InvalidSchedule */;
19007
+ break;
19008
+ }
19009
+ if (recurrence?.remainingCount != null && (!Number.isSafeInteger(recurrence.remainingCount) || recurrence.remainingCount < -1)) {
19010
+ seriesReason = "InvalidSchedule" /* InvalidSchedule */;
19011
+ break;
19012
+ }
19013
+ const earliestOverlap = options.strictlyInTimeRange ? from : from - duration + 1;
19014
+ let searchFrom = earliestOverlap;
19015
+ let searchUntil = to;
19016
+ for (const [originalStart, finalStart] of replacementStarts) {
19017
+ if (overlaps(finalStart, finalStart + duration, from, to, !!options.strictlyInTimeRange)) {
19018
+ searchFrom = Math.min(searchFrom, originalStart);
19019
+ searchUntil = Math.max(searchUntil, originalStart + 1);
19020
+ }
19021
+ }
19022
+ const firstAllowed = hasCron ? Math.max(lower, searchFrom) : Math.max(beginning, lower, searchFrom);
19023
+ const firstIndex = !hasCron && repeating ? Math.max(0, Math.ceil((firstAllowed - beginning) / step)) : 0;
19024
+ let cronSeeker = null;
19025
+ if (hasCron) {
19026
+ try {
19027
+ cronSeeker = createTimetableCronSeeker(cronExpression, firstAllowed);
19028
+ } catch (error) {
19029
+ seriesReason = error instanceof TimetableCronError && error.failure === "UnsupportedSyntax" /* UnsupportedSyntax */ ? "UnsupportedCronSyntax" /* UnsupportedCronSyntax */ : "InvalidSchedule" /* InvalidSchedule */;
19030
+ break;
19031
+ }
19032
+ }
19033
+ let weeklyChecker = null;
19034
+ if (recurrence?.weeklyCron != null) {
19035
+ if (typeof recurrence.weeklyCron !== "string") {
19036
+ seriesReason = "InvalidSchedule" /* InvalidSchedule */;
19037
+ break;
19038
+ }
19039
+ const weeklyZone = resolveWeeklyZone2();
19040
+ if (weeklyZone === null) {
19041
+ seriesReason = "MissingWeeklyTimeZone" /* MissingWeeklyTimeZone */;
19042
+ break;
19043
+ }
19044
+ weeklyChecker = createTimetableWeeklyChecker(recurrence.weeklyCron, recurrence.firstWeekDate, weeklyZone);
19045
+ if (weeklyChecker === null) {
19046
+ seriesReason = "InvalidSchedule" /* InvalidSchedule */;
19047
+ break;
19048
+ }
19049
+ }
19050
+ if (recurrence?.remainingCount === 0) {
19051
+ continue;
19052
+ }
19053
+ let visibleCount = 0;
19054
+ for (let occurrenceIndex = firstIndex; !repeating || occurrenceIndex <= Number.MAX_SAFE_INTEGER; occurrenceIndex += 1) {
19055
+ let start;
19056
+ if (cronSeeker) {
19057
+ try {
19058
+ start = cronSeeker.next().getTime();
19059
+ } catch {
19060
+ seriesReason = "InvalidSchedule" /* InvalidSchedule */;
19061
+ break;
19062
+ }
19063
+ } else {
19064
+ start = repeating ? beginning + occurrenceIndex * step : beginning;
19065
+ }
19066
+ if (!Number.isFinite(start) || start > upper || start >= searchUntil) {
19067
+ break;
19068
+ }
19069
+ iterationCount += 1;
19070
+ if (iterationCount > maxIterations) {
19071
+ throw sdkError("UnsupportedOperation" /* UnsupportedOperation */);
19072
+ }
19073
+ candidateCount += 1;
19074
+ if (candidateCount > maxCandidates) {
19075
+ throw sdkError("UnsupportedOperation" /* UnsupportedOperation */);
19076
+ }
19077
+ const finish = start + duration;
19078
+ if (!validDate(new Date(finish))) {
19079
+ seriesReason = "InvalidSchedule" /* InvalidSchedule */;
19080
+ break;
19081
+ }
19082
+ let matchesWeekly = true;
19083
+ if (weeklyChecker) {
19084
+ try {
19085
+ matchesWeekly = weeklyChecker(start);
19086
+ } catch {
19087
+ seriesReason = "InvalidSchedule" /* InvalidSchedule */;
19088
+ break;
19089
+ }
19090
+ }
19091
+ const isExcluded = excludedRanges.some((excluded) => excluded.begin <= start && excluded.end >= finish);
19092
+ const finalStart = replacementStarts.get(start) ?? start;
19093
+ const finalFinish = finalStart + duration;
19094
+ if (!validDate(new Date(finalFinish))) {
19095
+ seriesReason = "InvalidSchedule" /* InvalidSchedule */;
19096
+ break;
19097
+ }
19098
+ if (start >= lower && matchesWeekly && !isExcluded && overlaps(finalStart, finalFinish, from, to, !!options.strictlyInTimeRange)) {
19099
+ seriesEntries.push({
19100
+ kind: "virtual_occurrence" /* VirtualOccurrence */,
19101
+ source,
19102
+ seriesId: sourceId,
19103
+ beginDate: new Date(finalStart),
19104
+ endDate: new Date(finalFinish),
19105
+ key: dateKey(source, sourceId, new Date(finalStart), new Date(finalFinish))
19106
+ });
19107
+ visibleCount += 1;
19108
+ if (recurrence?.remainingCount != null && recurrence.remainingCount >= 0 && visibleCount >= recurrence.remainingCount) {
19109
+ break;
19110
+ }
19111
+ }
19112
+ if (!repeating) {
19113
+ break;
19114
+ }
19115
+ }
19116
+ if (seriesReason) {
19117
+ break;
19118
+ }
19119
+ }
19120
+ if (seriesReason) {
19121
+ unexpanded(source, index, seriesReason);
19122
+ continue;
19123
+ }
19124
+ for (const entry of seriesEntries) {
19125
+ append(entry);
19126
+ }
19127
+ }
19128
+ const storedDescendants = /* @__PURE__ */ new Set();
19129
+ for (const entry of entries) {
19130
+ if (entry.kind === "stored_case" /* StoredCase */ && typeof entry.source.groupId === "string" && entry.source.groupId.length > 0 && entry.beginDate && entry.endDate) {
19131
+ storedDescendants.add(JSON.stringify([entry.source.groupId, entry.beginDate.getTime(), entry.endDate.getTime()]));
19132
+ }
19133
+ }
19134
+ const seenOccurrences = /* @__PURE__ */ new Set();
19135
+ const result = entries.filter((entry) => {
19136
+ if (entry.kind === "virtual_occurrence" /* VirtualOccurrence */) {
19137
+ const replacementKey = JSON.stringify([entry.seriesId, entry.beginDate.getTime(), entry.endDate.getTime()]);
19138
+ if (storedDescendants.has(replacementKey)) {
19139
+ return false;
19140
+ }
19141
+ }
19142
+ if (entry.kind === "unexpanded_series" /* UnexpandedSeries */ || entry.kind === "stored_case" /* StoredCase */ && !entry.caseId) {
19143
+ return true;
19144
+ }
19145
+ const occurrenceKey = `${entry.kind}:${entry.key}`;
19146
+ if (seenOccurrences.has(occurrenceKey)) {
19147
+ return false;
19148
+ }
19149
+ seenOccurrences.add(occurrenceKey);
19150
+ return true;
19151
+ });
19152
+ if (result.length > maxResults) {
19153
+ throw sdkError("UnsupportedOperation" /* UnsupportedOperation */);
19154
+ }
19155
+ result.sort((left, right) => {
19156
+ const leftStart = left.kind === "unexpanded_series" /* UnexpandedSeries */ ? left.source.beginDate : left.beginDate;
19157
+ const rightStart = right.kind === "unexpanded_series" /* UnexpandedSeries */ ? right.source.beginDate : right.beginDate;
19158
+ const timeDifference = (validDate(leftStart) ? leftStart.getTime() : Number.POSITIVE_INFINITY) - (validDate(rightStart) ? rightStart.getTime() : Number.POSITIVE_INFINITY);
19159
+ if (timeDifference) {
19160
+ return timeDifference;
19161
+ }
19162
+ return left.key < right.key ? -1 : left.key > right.key ? 1 : 0;
19163
+ });
19164
+ return result;
19165
+ }
19166
+
18547
19167
  // ../../src/resources/contexts/context-icon-preset-paths.ts
18548
19168
  var CONTEXT_ICON_PRESET_PATHS = {
18549
19169
  anchor: "M35.4783 29.6467C30.6084 24.7768 26.629 15.4085 26.586 15.307C26.585 15.3045 26.5825 15.3015 26.5825 15.3015C26.5594 15.2485 26.527 15.2036 26.4889 15.1626C26.4775 15.1501 26.4645 15.1401 26.4515 15.129C26.4195 15.1006 26.3845 15.0771 26.3465 15.058C26.331 15.0505 26.317 15.042 26.301 15.0361C26.2465 15.0155 26.19 15.0011 26.13 15.0005H26.1265H26.125L26.1215 15.001C25.9914 14.9915 25.8714 15.0495 25.78 15.141C25.776 15.145 25.772 15.148 25.768 15.152C25.7279 15.195 25.6924 15.2425 25.668 15.2975L25.6644 15.3055C25.561 15.536 21.6095 24.3088 16.7716 29.1467C16.6441 29.2742 16.5951 29.4602 16.6431 29.6337C16.6911 29.8072 16.8291 29.9417 17.0037 29.9852C20.5716 30.8772 20.6245 37.3121 20.6251 37.5006C20.6256 37.7765 20.8495 37.9995 21.125 37.9995C21.401 37.999 21.6251 37.7761 21.6251 37.5C21.6251 37.4495 21.5811 30.7692 18.0356 29.2767C21.4051 25.6693 24.22 20.5154 25.6249 17.707V27.0508C24.4854 27.2833 23.625 28.2928 23.625 29.5002C23.625 30.8787 24.7465 32.0002 26.125 32.0002C27.5035 32.0002 28.6249 30.8787 28.6249 29.5002C28.6249 28.2928 27.7644 27.2833 26.625 27.0508V17.8115C28.0315 20.7629 30.8454 26.1428 34.2113 29.7717C30.6684 31.2087 30.6249 37.4546 30.6249 37.5C30.6249 37.776 30.8483 37.999 31.1238 37.9995C31.3998 37.9995 31.6239 37.7765 31.6249 37.501C31.6253 37.3331 31.6814 31.3761 35.2463 30.4852C35.4208 30.4417 35.5588 30.3072 35.6068 30.1337C35.6547 29.9602 35.6058 29.7742 35.4783 29.6467ZM27.6249 29.5002C27.6249 30.3272 26.9519 31.0002 26.125 31.0002C25.298 31.0002 24.625 30.3272 24.625 29.5002C24.625 28.6733 25.298 28.0003 26.125 28.0003C26.9519 28.0003 27.6249 28.6733 27.6249 29.5002ZM32.1248 37.0001H20.1251C19.8491 37.0001 19.6251 37.2241 19.6251 37.5V38.5C19.6251 38.776 19.8491 39 20.1251 39C20.4011 39 20.6251 38.776 20.6251 38.5V38.0001H31.6248V38.5C31.6248 38.776 31.8488 39 32.1248 39C32.4007 39 32.6247 38.776 32.6247 38.5V37.5C32.6248 37.2241 32.4008 37.0001 32.1248 37.0001Z",
@@ -19711,11 +20331,13 @@ export {
19711
20331
  AuthScopeValues,
19712
20332
  AuthSessionEffectStep,
19713
20333
  AuthSessionErrorReason,
20334
+ AvailabilityTimeValues,
19714
20335
  AvailableResourcesValues,
19715
20336
  BehaviorSettingsEffectStep,
19716
20337
  BlockReasonsFacade,
19717
20338
  CalendarViewTypeValues,
19718
20339
  CalendarsFacade,
20340
+ CaseParticipantTypeValues,
19719
20341
  CaseStateValues,
19720
20342
  CaseTypeValues,
19721
20343
  CasesFacade,
@@ -19793,11 +20415,14 @@ export {
19793
20415
  SessionDurationTypeValues,
19794
20416
  SessionPrecisionTypeValues,
19795
20417
  ShortUrlFacade,
20418
+ ShowCaseInTimetableTypeValues,
19796
20419
  StateManagementTypeValues,
19797
20420
  ThesaurusFacade,
19798
20421
  TimeSelectionTypeValues,
19799
20422
  TimeSplitTypeValues,
19800
20423
  TimeStepUiModeValues,
20424
+ TimetableExpansionKind,
20425
+ TimetableUnexpandedReason,
19801
20426
  TimetableViewTypeValues,
19802
20427
  TokenStatusValueList,
19803
20428
  TokenStatusValues,
@@ -19828,6 +20453,7 @@ export {
19828
20453
  createOrder,
19829
20454
  createServiceSessionDurationProperties,
19830
20455
  expandBookingWizardSteps,
20456
+ expandRecurringTimetableCases,
19831
20457
  generateRid,
19832
20458
  generateServiceResourceGroupId,
19833
20459
  generateTorrowId,