@oneuptime/common 12.0.29 → 12.0.30

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.
Files changed (189) hide show
  1. package/Models/DatabaseModels/Index.ts +11 -0
  2. package/Models/DatabaseModels/OnCallDutyPolicySchedule.ts +43 -0
  3. package/Models/DatabaseModels/OnCallDutyPolicyScheduleCalendarFeed.ts +662 -0
  4. package/Models/DatabaseModels/ProjectOnCallCalendarFeed.ts +584 -0
  5. package/Models/DatabaseModels/UserOnCallCalendarFeed.ts +546 -0
  6. package/Models/DatabaseModels/UserOnCallShiftReminder.ts +231 -0
  7. package/Models/DatabaseModels/UserOnCallShiftReminderLog.ts +331 -0
  8. package/Server/API/OnCallCalendarAPI.ts +2194 -0
  9. package/Server/EnvironmentConfig.ts +138 -0
  10. package/Server/Infrastructure/OnCallCalendarFeedCache.ts +1050 -0
  11. package/Server/Infrastructure/Postgres/SchemaMigrations/1790400000000-AddOnCallCalendarFeeds.ts +253 -0
  12. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +2 -0
  13. package/Server/Middleware/OnCallCalendarFeedRateLimit.ts +487 -0
  14. package/Server/Services/Index.ts +12 -0
  15. package/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.ts +32 -0
  16. package/Server/Services/OnCallDutyPolicyScheduleCalendarFeedService.ts +260 -0
  17. package/Server/Services/OnCallDutyPolicyScheduleLayerService.ts +70 -3
  18. package/Server/Services/OnCallDutyPolicyScheduleLayerUserService.ts +138 -3
  19. package/Server/Services/OnCallDutyPolicyScheduleService.ts +1465 -134
  20. package/Server/Services/OnCallDutyPolicyUserOverrideService.ts +167 -31
  21. package/Server/Services/ProjectOnCallCalendarFeedService.ts +192 -0
  22. package/Server/Services/TeamMemberService.ts +489 -1
  23. package/Server/Services/TeamService.ts +50 -0
  24. package/Server/Services/UserNotificationSettingService.ts +44 -1
  25. package/Server/Services/UserOnCallCalendarFeedService.ts +159 -0
  26. package/Server/Services/UserOnCallShiftReminderLogService.ts +151 -0
  27. package/Server/Services/UserOnCallShiftReminderService.ts +112 -0
  28. package/Server/Utils/OnCall/CalendarFeedToken.ts +241 -0
  29. package/Server/Utils/OnCall/OnCallCalendarFeedRenderer.ts +1488 -0
  30. package/Server/Utils/OnCall/OnCallCalendarFeedUrls.ts +230 -0
  31. package/Server/Utils/OnCall/OnCallShiftChangeListeners.ts +227 -0
  32. package/Server/Utils/OnCall/OnCallShiftMaterializer.ts +1127 -0
  33. package/Server/Utils/OnCall/OnCallShiftReminderListener.ts +174 -0
  34. package/Server/Utils/OnCall/OnCallShiftReminderRunner.ts +2584 -0
  35. package/Server/Utils/Response.ts +134 -0
  36. package/Server/Utils/StartServer.ts +10 -0
  37. package/Server/Utils/Telemetry/AppMetrics.ts +51 -0
  38. package/Tests/App/Dashboard/OnCallCalendarFeedLinks.test.tsx +229 -0
  39. package/Tests/App/Dashboard/OnCallCalendarFeedPlanGate.test.tsx +489 -0
  40. package/Tests/App/Dashboard/OnCallCalendarFeedSideMenus.test.tsx +149 -0
  41. package/Tests/App/Dashboard/OnCallCalendarFeedUtil.test.ts +855 -0
  42. package/Tests/App/Dashboard/OnCallPersonalCalendarFeed.test.tsx +1209 -0
  43. package/Tests/App/Dashboard/OnCallSharedCalendarFeedCard.test.tsx +1019 -0
  44. package/Tests/App/Dashboard/OnCallShiftRemindersAndUpcomingShifts.test.tsx +655 -0
  45. package/Tests/App/Dashboard/UserSettingsSetupChecklistModel.test.ts +73 -0
  46. package/Tests/Models/OnCallCalendarFeedModels.test.ts +642 -0
  47. package/Tests/Models/OnCallDutyPolicyScheduleCalendarFeed.test.ts +288 -0
  48. package/Tests/Models/OnCallDutyPolicyScheduleShiftConfigVersion.test.ts +88 -0
  49. package/Tests/Models/UserOnCallShiftReminderModels.test.ts +368 -0
  50. package/Tests/Server/API/Helpers.ts +8 -0
  51. package/Tests/Server/API/OnCallCalendarAPI.test.ts +4461 -0
  52. package/Tests/Server/EnvironmentConfigOnCallCalendarFeed.test.ts +357 -0
  53. package/Tests/Server/Infrastructure/OnCallCalendarFeedCache.test.ts +1589 -0
  54. package/Tests/Server/Infrastructure/Postgres/AddOnCallCalendarFeedsMigration.test.ts +369 -0
  55. package/Tests/Server/Middleware/OnCallCalendarFeedRateLimit.test.ts +1365 -0
  56. package/Tests/Server/Services/FeedRetentionConsistency.test.ts +70 -0
  57. package/Tests/Server/Services/OnCallCalendarFeedServices.test.ts +1103 -0
  58. package/Tests/Server/Services/OnCallDutyPolicyScheduleResolver.test.ts +1037 -0
  59. package/Tests/Server/Services/OnCallShiftConfigPropagation.test.ts +1270 -0
  60. package/Tests/Server/Services/TeamDeleteMemberCleanup.test.ts +156 -0
  61. package/Tests/Server/Services/TeamMemberOnCallCleanup.test.ts +755 -0
  62. package/Tests/Server/Services/UserNotificationSettingShiftReminderDefaults.test.ts +267 -0
  63. package/Tests/Server/Services/UserOnCallShiftReminderServices.test.ts +583 -0
  64. package/Tests/Server/Types/Database/Permissions/OnCallCalendarFeedPermissions.test.ts +254 -0
  65. package/Tests/Server/Utils/OnCall/CalendarFeedToken.test.ts +467 -0
  66. package/Tests/Server/Utils/OnCall/OnCallCalendarFeedRenderer.test.ts +2142 -0
  67. package/Tests/Server/Utils/OnCall/OnCallCalendarFeedUrls.test.ts +278 -0
  68. package/Tests/Server/Utils/OnCall/OnCallResolverTestHarness.ts +440 -0
  69. package/Tests/Server/Utils/OnCall/OnCallShiftChangeListeners.test.ts +314 -0
  70. package/Tests/Server/Utils/OnCall/OnCallShiftMaterializer.test.ts +1502 -0
  71. package/Tests/Server/Utils/OnCall/OnCallShiftReminderListener.test.ts +491 -0
  72. package/Tests/Server/Utils/OnCall/OnCallShiftReminderRunner.test.ts +3088 -0
  73. package/Tests/Server/Utils/OnCall/OnCallShiftReminderTestHarness.ts +910 -0
  74. package/Tests/Server/Utils/ResponseSendCalendarResponse.test.ts +561 -0
  75. package/Tests/Server/Utils/StartServerEncryptionSecretWarning.test.ts +64 -0
  76. package/Tests/Server/Utils/Telemetry/AppMetrics.test.ts +29 -0
  77. package/Tests/Types/Calendar/ICalendar.test.ts +488 -0
  78. package/Tests/Types/NotificationSetting/NotificationSettingEventType.test.ts +53 -0
  79. package/Tests/Types/OnCallDutyPolicy/CalendarFeedTestFixtures.ts +310 -0
  80. package/Tests/Types/OnCallDutyPolicy/CalendarFeedWindow.test.ts +205 -0
  81. package/Tests/Types/OnCallDutyPolicy/LayerUtilLayerMetaAndIterationCap.test.ts +458 -0
  82. package/Tests/Types/OnCallDutyPolicy/MaterializedShift.test.ts +197 -0
  83. package/Tests/Types/OnCallDutyPolicy/OnCallCalendarFeedUtil.test.ts +1986 -0
  84. package/Tests/Types/OnCallDutyPolicy/ScheduleShiftUtilGroupKey.test.ts +678 -0
  85. package/Tests/Types/OnCallDutyPolicy/ShiftSeamUtil.test.ts +417 -0
  86. package/Tests/UI/Utils/Breadcrumb/fixtures/RealBreadcrumbTrails.ts +10 -0
  87. package/Tests/UI/Utils/Breadcrumb/fixtures/RealRoutePatterns.ts +2 -0
  88. package/Types/Calendar/ICalendar.ts +442 -0
  89. package/Types/Email/EmailTemplateType.ts +2 -0
  90. package/Types/NotificationSetting/NotificationSettingEventType.ts +4 -0
  91. package/Types/OnCallDutyPolicy/CalendarFeedWindow.ts +140 -0
  92. package/Types/OnCallDutyPolicy/Layer.ts +190 -35
  93. package/Types/OnCallDutyPolicy/MaterializedShift.ts +274 -0
  94. package/Types/OnCallDutyPolicy/OnCallCalendarFeedUtil.ts +1415 -0
  95. package/Types/OnCallDutyPolicy/ScheduleShiftUtil.ts +159 -4
  96. package/Types/OnCallDutyPolicy/ShiftSeamUtil.ts +106 -0
  97. package/build/dist/Models/DatabaseModels/Index.js +11 -0
  98. package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
  99. package/build/dist/Models/DatabaseModels/OnCallDutyPolicySchedule.js +44 -0
  100. package/build/dist/Models/DatabaseModels/OnCallDutyPolicySchedule.js.map +1 -1
  101. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyScheduleCalendarFeed.js +699 -0
  102. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyScheduleCalendarFeed.js.map +1 -0
  103. package/build/dist/Models/DatabaseModels/ProjectOnCallCalendarFeed.js +620 -0
  104. package/build/dist/Models/DatabaseModels/ProjectOnCallCalendarFeed.js.map +1 -0
  105. package/build/dist/Models/DatabaseModels/UserOnCallCalendarFeed.js +585 -0
  106. package/build/dist/Models/DatabaseModels/UserOnCallCalendarFeed.js.map +1 -0
  107. package/build/dist/Models/DatabaseModels/UserOnCallShiftReminder.js +247 -0
  108. package/build/dist/Models/DatabaseModels/UserOnCallShiftReminder.js.map +1 -0
  109. package/build/dist/Models/DatabaseModels/UserOnCallShiftReminderLog.js +355 -0
  110. package/build/dist/Models/DatabaseModels/UserOnCallShiftReminderLog.js.map +1 -0
  111. package/build/dist/Server/API/OnCallCalendarAPI.js +1371 -0
  112. package/build/dist/Server/API/OnCallCalendarAPI.js.map +1 -0
  113. package/build/dist/Server/EnvironmentConfig.js +102 -0
  114. package/build/dist/Server/EnvironmentConfig.js.map +1 -1
  115. package/build/dist/Server/Infrastructure/OnCallCalendarFeedCache.js +663 -0
  116. package/build/dist/Server/Infrastructure/OnCallCalendarFeedCache.js.map +1 -0
  117. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790400000000-AddOnCallCalendarFeeds.js +103 -0
  118. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790400000000-AddOnCallCalendarFeeds.js.map +1 -0
  119. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +2 -0
  120. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  121. package/build/dist/Server/Middleware/OnCallCalendarFeedRateLimit.js +342 -0
  122. package/build/dist/Server/Middleware/OnCallCalendarFeedRateLimit.js.map +1 -0
  123. package/build/dist/Server/Services/Index.js +12 -0
  124. package/build/dist/Server/Services/Index.js.map +1 -1
  125. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.js +20 -0
  126. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.js.map +1 -1
  127. package/build/dist/Server/Services/OnCallDutyPolicyScheduleCalendarFeedService.js +219 -0
  128. package/build/dist/Server/Services/OnCallDutyPolicyScheduleCalendarFeedService.js.map +1 -0
  129. package/build/dist/Server/Services/OnCallDutyPolicyScheduleLayerService.js +47 -3
  130. package/build/dist/Server/Services/OnCallDutyPolicyScheduleLayerService.js.map +1 -1
  131. package/build/dist/Server/Services/OnCallDutyPolicyScheduleLayerUserService.js +112 -3
  132. package/build/dist/Server/Services/OnCallDutyPolicyScheduleLayerUserService.js.map +1 -1
  133. package/build/dist/Server/Services/OnCallDutyPolicyScheduleService.js +955 -9
  134. package/build/dist/Server/Services/OnCallDutyPolicyScheduleService.js.map +1 -1
  135. package/build/dist/Server/Services/OnCallDutyPolicyUserOverrideService.js +93 -6
  136. package/build/dist/Server/Services/OnCallDutyPolicyUserOverrideService.js.map +1 -1
  137. package/build/dist/Server/Services/ProjectOnCallCalendarFeedService.js +157 -0
  138. package/build/dist/Server/Services/ProjectOnCallCalendarFeedService.js.map +1 -0
  139. package/build/dist/Server/Services/TeamMemberService.js +396 -1
  140. package/build/dist/Server/Services/TeamMemberService.js.map +1 -1
  141. package/build/dist/Server/Services/TeamService.js +43 -0
  142. package/build/dist/Server/Services/TeamService.js.map +1 -1
  143. package/build/dist/Server/Services/UserNotificationSettingService.js +26 -1
  144. package/build/dist/Server/Services/UserNotificationSettingService.js.map +1 -1
  145. package/build/dist/Server/Services/UserOnCallCalendarFeedService.js +140 -0
  146. package/build/dist/Server/Services/UserOnCallCalendarFeedService.js.map +1 -0
  147. package/build/dist/Server/Services/UserOnCallShiftReminderLogService.js +116 -0
  148. package/build/dist/Server/Services/UserOnCallShiftReminderLogService.js.map +1 -0
  149. package/build/dist/Server/Services/UserOnCallShiftReminderService.js +92 -0
  150. package/build/dist/Server/Services/UserOnCallShiftReminderService.js.map +1 -0
  151. package/build/dist/Server/Utils/OnCall/CalendarFeedToken.js +161 -0
  152. package/build/dist/Server/Utils/OnCall/CalendarFeedToken.js.map +1 -0
  153. package/build/dist/Server/Utils/OnCall/OnCallCalendarFeedRenderer.js +983 -0
  154. package/build/dist/Server/Utils/OnCall/OnCallCalendarFeedRenderer.js.map +1 -0
  155. package/build/dist/Server/Utils/OnCall/OnCallCalendarFeedUrls.js +155 -0
  156. package/build/dist/Server/Utils/OnCall/OnCallCalendarFeedUrls.js.map +1 -0
  157. package/build/dist/Server/Utils/OnCall/OnCallShiftChangeListeners.js +145 -0
  158. package/build/dist/Server/Utils/OnCall/OnCallShiftChangeListeners.js.map +1 -0
  159. package/build/dist/Server/Utils/OnCall/OnCallShiftMaterializer.js +752 -0
  160. package/build/dist/Server/Utils/OnCall/OnCallShiftMaterializer.js.map +1 -0
  161. package/build/dist/Server/Utils/OnCall/OnCallShiftReminderListener.js +92 -0
  162. package/build/dist/Server/Utils/OnCall/OnCallShiftReminderListener.js.map +1 -0
  163. package/build/dist/Server/Utils/OnCall/OnCallShiftReminderRunner.js +1786 -0
  164. package/build/dist/Server/Utils/OnCall/OnCallShiftReminderRunner.js.map +1 -0
  165. package/build/dist/Server/Utils/Response.js +97 -0
  166. package/build/dist/Server/Utils/Response.js.map +1 -1
  167. package/build/dist/Server/Utils/StartServer.js +9 -1
  168. package/build/dist/Server/Utils/StartServer.js.map +1 -1
  169. package/build/dist/Server/Utils/Telemetry/AppMetrics.js +41 -0
  170. package/build/dist/Server/Utils/Telemetry/AppMetrics.js.map +1 -1
  171. package/build/dist/Types/Calendar/ICalendar.js +290 -0
  172. package/build/dist/Types/Calendar/ICalendar.js.map +1 -0
  173. package/build/dist/Types/Email/EmailTemplateType.js +2 -0
  174. package/build/dist/Types/Email/EmailTemplateType.js.map +1 -1
  175. package/build/dist/Types/NotificationSetting/NotificationSettingEventType.js +3 -0
  176. package/build/dist/Types/NotificationSetting/NotificationSettingEventType.js.map +1 -1
  177. package/build/dist/Types/OnCallDutyPolicy/CalendarFeedWindow.js +97 -0
  178. package/build/dist/Types/OnCallDutyPolicy/CalendarFeedWindow.js.map +1 -0
  179. package/build/dist/Types/OnCallDutyPolicy/Layer.js +113 -19
  180. package/build/dist/Types/OnCallDutyPolicy/Layer.js.map +1 -1
  181. package/build/dist/Types/OnCallDutyPolicy/MaterializedShift.js +134 -0
  182. package/build/dist/Types/OnCallDutyPolicy/MaterializedShift.js.map +1 -0
  183. package/build/dist/Types/OnCallDutyPolicy/OnCallCalendarFeedUtil.js +800 -0
  184. package/build/dist/Types/OnCallDutyPolicy/OnCallCalendarFeedUtil.js.map +1 -0
  185. package/build/dist/Types/OnCallDutyPolicy/ScheduleShiftUtil.js +97 -3
  186. package/build/dist/Types/OnCallDutyPolicy/ScheduleShiftUtil.js.map +1 -1
  187. package/build/dist/Types/OnCallDutyPolicy/ShiftSeamUtil.js +77 -0
  188. package/build/dist/Types/OnCallDutyPolicy/ShiftSeamUtil.js.map +1 -0
  189. package/package.json +1 -1
@@ -0,0 +1,290 @@
1
+ import BadDataException from "../Exception/BadDataException";
2
+ /*
3
+ * Zero-dependency RFC 5545 (iCalendar) serializer for subscription feeds.
4
+ *
5
+ * Deliberate choices, recorded here because every one of them was a
6
+ * decision, not an omission:
7
+ *
8
+ * - No METHOD. RFC 5546 (iTIP) would require ORGANIZER on a PUBLISH, and
9
+ * subscription feeds are not iTIP messages; Google, Apple and Outlook all
10
+ * treat a METHOD-less VCALENDAR as a plain calendar, which is what we are.
11
+ * - DTSTAMP = the feed input's last-modified instant, not "now". Without
12
+ * METHOD, RFC 5545 §3.8.7.2 reads DTSTAMP as the last revision, and using
13
+ * it makes an unchanged schedule serialize to a byte-identical body so ETags
14
+ * and body caches work.
15
+ * - No VTIMEZONE and no TZID. Every DTSTART/DTEND is an absolute UTC instant
16
+ * ("...Z"). The engine already resolves wall-clock rules into instants, the
17
+ * client converts to the viewer's zone, and shipping a VTIMEZONE database
18
+ * would lag IANA. Wall-clock renderings go in DESCRIPTION instead.
19
+ * - No VALARM (reminders are delivered by OneUptime's own notification path so
20
+ * they honour the user's notification settings), no RRULE (shifts are
21
+ * materialised individually so overrides and rotations never desynchronise),
22
+ * no CLASS (Outlook maps CLASS:PRIVATE to Private sensitivity and Google to
23
+ * private visibility, which blanks a shared team calendar for everyone but
24
+ * its owner), no ORGANIZER/ATTENDEE.
25
+ * - Both REFRESH-INTERVAL;VALUE=DURATION (RFC 7986) and X-PUBLISHED-TTL are
26
+ * emitted from the same duration: classic Outlook honours X-PUBLISHED-TTL
27
+ * when "Update Limit" is on and never refreshes a feed without it.
28
+ * - Property order inside VCALENDAR and VEVENT is fixed so equal inputs give
29
+ * equal bytes.
30
+ *
31
+ * Wire format: CRLF line breaks, content lines folded at 75 octets on UTF-8
32
+ * character boundaries (RFC 5545 §3.1), TEXT values escaped per §3.3.11.
33
+ */
34
+ export const ICALENDAR_LINE_BREAK = "\r\n";
35
+ // RFC 5545 §3.1: lines SHOULD NOT be longer than 75 octets, excluding CRLF.
36
+ export const ICALENDAR_MAX_LINE_OCTETS = 75;
37
+ export const ICALENDAR_VERSION = "2.0";
38
+ export var ICalendarEventStatus;
39
+ (function (ICalendarEventStatus) {
40
+ ICalendarEventStatus["Confirmed"] = "CONFIRMED";
41
+ ICalendarEventStatus["Tentative"] = "TENTATIVE";
42
+ ICalendarEventStatus["Cancelled"] = "CANCELLED";
43
+ })(ICalendarEventStatus || (ICalendarEventStatus = {}));
44
+ export var ICalendarTransparency;
45
+ (function (ICalendarTransparency) {
46
+ ICalendarTransparency["Transparent"] = "TRANSPARENT";
47
+ ICalendarTransparency["Opaque"] = "OPAQUE";
48
+ })(ICalendarTransparency || (ICalendarTransparency = {}));
49
+ const ISO_8601_DURATION_REGEX = /^P(?:\d+W|(?:\d+D)?(?:T(?:\d+H)?(?:\d+M)?(?:\d+S)?)?)$/;
50
+ // RFC 5545 §3.2: a parameter value holding any of these must be quoted.
51
+ const RESERVED_PARAMETER_CHARACTERS = /[;:,]/;
52
+ export default class ICalendar {
53
+ static serialize(document) {
54
+ const lines = [];
55
+ lines.push("BEGIN:VCALENDAR");
56
+ lines.push(`VERSION:${ICALENDAR_VERSION}`);
57
+ lines.push(ICalendar.contentLine("PRODID", document.calendar.productId));
58
+ lines.push("CALSCALE:GREGORIAN");
59
+ const calendar = document.calendar;
60
+ if (calendar.name !== undefined && calendar.name !== "") {
61
+ lines.push(ICalendar.textLine("NAME", calendar.name));
62
+ }
63
+ const displayName = calendar.displayName !== undefined && calendar.displayName !== ""
64
+ ? calendar.displayName
65
+ : calendar.name;
66
+ if (displayName !== undefined && displayName !== "") {
67
+ lines.push(ICalendar.textLine("X-WR-CALNAME", displayName));
68
+ }
69
+ if (calendar.description !== undefined && calendar.description !== "") {
70
+ lines.push(ICalendar.textLine("X-WR-CALDESC", calendar.description));
71
+ }
72
+ if (calendar.timezone !== undefined && calendar.timezone !== "") {
73
+ lines.push(ICalendar.textLine("X-WR-TIMEZONE", calendar.timezone));
74
+ }
75
+ if (calendar.refreshInterval !== undefined) {
76
+ const duration = ICalendar.validateDuration(calendar.refreshInterval);
77
+ lines.push(ICalendar.contentLine("REFRESH-INTERVAL", duration, {
78
+ VALUE: "DURATION",
79
+ }));
80
+ lines.push(ICalendar.contentLine("X-PUBLISHED-TTL", duration));
81
+ }
82
+ if (calendar.lastModified !== undefined) {
83
+ lines.push(ICalendar.contentLine("LAST-MODIFIED", ICalendar.formatUtcDateTime(calendar.lastModified)));
84
+ }
85
+ for (const event of document.events) {
86
+ lines.push(...ICalendar.serializeEvent(event));
87
+ }
88
+ lines.push("END:VCALENDAR");
89
+ return (lines
90
+ .map((line) => {
91
+ return ICalendar.foldLine(line);
92
+ })
93
+ .join(ICALENDAR_LINE_BREAK) + ICALENDAR_LINE_BREAK);
94
+ }
95
+ /*
96
+ * The unfolded content lines of one VEVENT, in the fixed order. Exposed so
97
+ * tests and callers can inspect a single event without a whole document.
98
+ */
99
+ static serializeEvent(event) {
100
+ if (!event.uid || event.uid.trim() === "") {
101
+ throw new BadDataException("iCalendar event UID must not be empty");
102
+ }
103
+ if (event.end.getTime() <= event.start.getTime()) {
104
+ throw new BadDataException(`iCalendar event ${event.uid} must end after it starts`);
105
+ }
106
+ const lines = [];
107
+ lines.push("BEGIN:VEVENT");
108
+ lines.push(ICalendar.textLine("UID", event.uid));
109
+ lines.push(ICalendar.contentLine("DTSTAMP", ICalendar.formatUtcDateTime(event.dtStamp)));
110
+ if (event.lastModified !== undefined) {
111
+ lines.push(ICalendar.contentLine("LAST-MODIFIED", ICalendar.formatUtcDateTime(event.lastModified)));
112
+ }
113
+ if (event.sequence !== undefined) {
114
+ lines.push(ICalendar.contentLine("SEQUENCE", String(ICalendar.validateSequence(event.sequence))));
115
+ }
116
+ lines.push(ICalendar.contentLine("DTSTART", ICalendar.formatUtcDateTime(event.start)));
117
+ lines.push(ICalendar.contentLine("DTEND", ICalendar.formatUtcDateTime(event.end)));
118
+ lines.push(ICalendar.textLine("SUMMARY", event.summary));
119
+ if (event.description !== undefined && event.description !== "") {
120
+ lines.push(ICalendar.textLine("DESCRIPTION", event.description));
121
+ }
122
+ if (event.location !== undefined && event.location !== "") {
123
+ lines.push(ICalendar.textLine("LOCATION", event.location));
124
+ }
125
+ if (event.url !== undefined && event.url !== "") {
126
+ // URI value type: not TEXT-escaped, but never allowed to break the line.
127
+ lines.push(ICalendar.contentLine("URL", ICalendar.stripLineBreaks(event.url)));
128
+ }
129
+ if (event.status !== undefined) {
130
+ lines.push(ICalendar.contentLine("STATUS", event.status));
131
+ }
132
+ if (event.transparency !== undefined) {
133
+ lines.push(ICalendar.contentLine("TRANSP", event.transparency));
134
+ }
135
+ if (event.categories !== undefined && event.categories.length > 0) {
136
+ lines.push(ICalendar.contentLine("CATEGORIES", event.categories
137
+ .map((category) => {
138
+ return ICalendar.escapeText(category);
139
+ })
140
+ .join(",")));
141
+ }
142
+ lines.push("END:VEVENT");
143
+ return lines;
144
+ }
145
+ /*
146
+ * RFC 5545 §3.3.11 TEXT escaping: backslash, semicolon and comma are
147
+ * escaped; a newline becomes the two characters "\n"; carriage returns and
148
+ * other control characters (which TEXT may not contain) are dropped.
149
+ */
150
+ static escapeText(text) {
151
+ let result = "";
152
+ for (const char of text) {
153
+ if (char === "\\") {
154
+ result += "\\\\";
155
+ }
156
+ else if (char === ";") {
157
+ result += "\\;";
158
+ }
159
+ else if (char === ",") {
160
+ result += "\\,";
161
+ }
162
+ else if (char === "\n") {
163
+ result += "\\n";
164
+ }
165
+ else if (char === "\t") {
166
+ result += char;
167
+ }
168
+ else if (ICalendar.isControlCharacter(char)) {
169
+ continue;
170
+ }
171
+ else {
172
+ result += char;
173
+ }
174
+ }
175
+ return result;
176
+ }
177
+ // "YYYYMMDDTHHMMSSZ" — RFC 5545 §3.3.5 form #2, UTC.
178
+ static formatUtcDateTime(date) {
179
+ if (!(date instanceof Date) || Number.isNaN(date.getTime())) {
180
+ throw new BadDataException("iCalendar date is not a valid Date");
181
+ }
182
+ const pad = (value) => {
183
+ return value < 10 ? `0${value}` : String(value);
184
+ };
185
+ return (`${date.getUTCFullYear()}${pad(date.getUTCMonth() + 1)}${pad(date.getUTCDate())}` +
186
+ `T${pad(date.getUTCHours())}${pad(date.getUTCMinutes())}${pad(date.getUTCSeconds())}Z`);
187
+ }
188
+ /*
189
+ * Fold one logical content line at 75 octets (RFC 5545 §3.1). The
190
+ * continuation lines start with a single space that counts toward their
191
+ * own 75-octet budget. Never splits inside a UTF-8 multi-byte sequence:
192
+ * the walk is per code point and each code point's octet length is known.
193
+ */
194
+ static foldLine(line) {
195
+ if (ICalendar.getUtf8OctetLength(line) <= ICALENDAR_MAX_LINE_OCTETS) {
196
+ return line;
197
+ }
198
+ const pieces = [];
199
+ let current = "";
200
+ let currentOctets = 0;
201
+ // The first physical line has the full budget; continuations lose one to the leading space.
202
+ let budget = ICALENDAR_MAX_LINE_OCTETS;
203
+ for (const char of line) {
204
+ const octets = ICalendar.getUtf8OctetLength(char);
205
+ if (currentOctets + octets > budget) {
206
+ pieces.push(current);
207
+ current = "";
208
+ currentOctets = 0;
209
+ budget = ICALENDAR_MAX_LINE_OCTETS - 1;
210
+ }
211
+ current += char;
212
+ currentOctets += octets;
213
+ }
214
+ if (current !== "") {
215
+ pieces.push(current);
216
+ }
217
+ return pieces.join(`${ICALENDAR_LINE_BREAK} `);
218
+ }
219
+ // Reverse of foldLine, for tests and readers: joins continuation lines.
220
+ static unfold(body) {
221
+ return body.replace(/\r\n[ \t]/g, "");
222
+ }
223
+ static getUtf8OctetLength(text) {
224
+ var _a;
225
+ let octets = 0;
226
+ for (const char of text) {
227
+ const codePoint = (_a = char.codePointAt(0)) !== null && _a !== void 0 ? _a : 0;
228
+ if (codePoint < 0x80) {
229
+ octets += 1;
230
+ }
231
+ else if (codePoint < 0x800) {
232
+ octets += 2;
233
+ }
234
+ else if (codePoint < 0x10000) {
235
+ octets += 3;
236
+ }
237
+ else {
238
+ octets += 4;
239
+ }
240
+ }
241
+ return octets;
242
+ }
243
+ /*
244
+ * "NAME;PARAM=value:value" with the value used verbatim (callers escape
245
+ * TEXT values themselves or use textLine). Parameter values that contain
246
+ * characters RFC 5545 §3.2 reserves are quoted; double quotes inside them
247
+ * are dropped because there is no way to escape them.
248
+ */
249
+ static contentLine(name, value, parameters) {
250
+ var _a;
251
+ let line = name.toUpperCase();
252
+ if (parameters) {
253
+ for (const parameterName of Object.keys(parameters)) {
254
+ const rawValue = ((_a = parameters[parameterName]) !== null && _a !== void 0 ? _a : "").replace(/"/g, "");
255
+ const needsQuotes = RESERVED_PARAMETER_CHARACTERS.test(rawValue);
256
+ line += `;${parameterName.toUpperCase()}=${needsQuotes ? `"${rawValue}"` : rawValue}`;
257
+ }
258
+ }
259
+ return `${line}:${ICalendar.stripLineBreaks(value)}`;
260
+ }
261
+ // A TEXT property: the value is escaped per §3.3.11.
262
+ static textLine(name, value) {
263
+ return ICalendar.contentLine(name, ICalendar.escapeText(value));
264
+ }
265
+ static validateDuration(duration) {
266
+ const trimmed = duration.trim().toUpperCase();
267
+ if (!ISO_8601_DURATION_REGEX.test(trimmed) ||
268
+ trimmed === "P" ||
269
+ trimmed === "PT") {
270
+ throw new BadDataException(`iCalendar refresh interval must be an ISO 8601 duration, got "${duration}"`);
271
+ }
272
+ return trimmed;
273
+ }
274
+ static validateSequence(sequence) {
275
+ if (!Number.isInteger(sequence) || sequence < 0) {
276
+ throw new BadDataException(`iCalendar SEQUENCE must be a non-negative integer, got ${sequence}`);
277
+ }
278
+ return sequence;
279
+ }
280
+ static isControlCharacter(char) {
281
+ var _a;
282
+ const codePoint = (_a = char.codePointAt(0)) !== null && _a !== void 0 ? _a : 0;
283
+ return codePoint < 0x20 || codePoint === 0x7f;
284
+ }
285
+ // Line breaks can never appear inside a content line, whatever the value type.
286
+ static stripLineBreaks(value) {
287
+ return value.replace(/[\r\n]+/g, "");
288
+ }
289
+ }
290
+ //# sourceMappingURL=ICalendar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ICalendar.js","sourceRoot":"","sources":["../../../../Types/Calendar/ICalendar.ts"],"names":[],"mappings":"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"}
@@ -80,6 +80,8 @@ var EmailTemplateType;
80
80
  EmailTemplateType["UserCurrentlyOnOnCallRoster"] = "UserCurrentlyOnOnCallRoster.hbs";
81
81
  EmailTemplateType["UserNextOnOnCallRoster"] = "UserNextOnOnCallRoster.hbs";
82
82
  EmailTemplateType["UserNoLongerActiveOnOnCallRoster"] = "UserNoLongerActiveOnOnCallRoster.hbs";
83
+ EmailTemplateType["UserOnCallShiftReminder"] = "UserOnCallShiftReminder.hbs";
84
+ EmailTemplateType["UserOnCallShiftReassigned"] = "UserOnCallShiftReassigned.hbs";
83
85
  EmailTemplateType["ProjectSubscriptionOverdue"] = "ProjectSubscriptionOverdue.hbs";
84
86
  EmailTemplateType["Invoice"] = "Invoice.hbs";
85
87
  EmailTemplateType["ClickhouseCapacityWarning"] = "ClickhouseCapacityWarning.hbs";
@@ -1 +1 @@
1
- {"version":3,"file":"EmailTemplateType.js","sourceRoot":"","sources":["../../../../Types/Email/EmailTemplateType.ts"],"names":[],"mappings":"AAAA,IAAK,iBAmGJ;AAnGD,WAAK,iBAAiB;IACpB,wDAAmC,CAAA;IACnC,0DAAqC,CAAA;IACrC,sDAAiC,CAAA;IACjC,kEAA6C,CAAA;IAC7C,sEAAiD,CAAA;IACjD,oFAA+D,CAAA;IAC/D,wFAAmE,CAAA;IACnE,gEAA2C,CAAA;IAC3C,wFAAmE,CAAA;IACnE,wDAAmC,CAAA;IACnC,4DAAuC,CAAA;IACvC,4EAAuD,CAAA;IACvD,4FAAuE,CAAA;IACvE,oFAA+D,CAAA;IAC/D,4DAAuC,CAAA;IACvC,sDAAiC,CAAA;IACjC,sDAAiC,CAAA;IACjC,0EAAqD,CAAA;IACrD,wFAAmE,CAAA;IACnE,gFAA2D,CAAA;IAC3D,oGAA+E,CAAA;IAC/E,kFAA6D,CAAA;IAC7D,wFAAmE,CAAA;IACnE,0FAAqE,CAAA;IACrE,kHAA6F,CAAA;IAC7F,0HAAqG,CAAA;IACrG,4HAAuG,CAAA;IACvG,8EAAyD,CAAA;IACzD,gFAA2D,CAAA;IAC3D,0EAAqD,CAAA;IACrD,0HAAqG,CAAA;IACrG,8CAAyB,CAAA;IACzB,gEAA2C,CAAA;IAC3C,oFAA+D,CAAA;IAC/D,oEAA+C,CAAA;IAC/C,gFAA2D,CAAA;IAE3D,wEAAmD,CAAA;IAEnD,kEAA6C,CAAA;IAC7C,gFAA2D,CAAA;IAC3D,4EAAuD,CAAA;IACvD,sFAAiE,CAAA;IACjE,oEAA+C,CAAA;IAC/C,4FAAuE,CAAA;IAEvE,4DAAuC,CAAA;IACvC,0EAAqD,CAAA;IACrD,sEAAiD,CAAA;IACjD,gFAA2D,CAAA;IAC3D,sFAAiE,CAAA;IAEjE,0EAAqD,CAAA;IACrD,wFAAmE,CAAA;IACnE,oFAA+D,CAAA;IAC/D,8FAAyE,CAAA;IACzE,oFAA+D,CAAA;IAE/D,gFAA2D,CAAA;IAC3D,8FAAyE,CAAA;IACzE,0FAAqE,CAAA;IACrE,oGAA+E,CAAA;IAC/E,gGAA2E,CAAA;IAE3E,8EAAyD,CAAA;IACzD,wFAAmE,CAAA;IACnE,sFAAiE,CAAA;IAEjE,oGAA+E,CAAA;IAC/E,0FAAqE,CAAA;IACrE,wGAAmF,CAAA;IACnF,8GAAyF,CAAA;IACzF,oHAA+F,CAAA;IAC/F,0FAAqE,CAAA;IACrE,sEAAiD,CAAA;IACjD,gGAA2E,CAAA;IAC3E,wDAAmC,CAAA;IACnC,8DAAyC,CAAA;IACzC,oEAA+C,CAAA;IAC/C,8DAAyC,CAAA;IACzC,4EAAuD,CAAA;IACvD,kFAA6D,CAAA;IAE7D,4EAAuD,CAAA;IACvD,oFAA+D,CAAA;IAC/D,oFAA+D,CAAA;IAC/D,0EAAqD,CAAA;IACrD,8FAAyE,CAAA;IAEzE,kFAA6D,CAAA;IAC7D,4CAAuB,CAAA;IAEvB,gFAA2D,CAAA;IAC3D,kEAA6C,CAAA;IAC7C,wEAAmD,CAAA;IAEnD,8FAAyE,CAAA;IACzE,4FAAuE,CAAA;AACzE,CAAC,EAnGI,iBAAiB,KAAjB,iBAAiB,QAmGrB;AAED,eAAe,iBAAiB,CAAC"}
1
+ {"version":3,"file":"EmailTemplateType.js","sourceRoot":"","sources":["../../../../Types/Email/EmailTemplateType.ts"],"names":[],"mappings":"AAAA,IAAK,iBAqGJ;AArGD,WAAK,iBAAiB;IACpB,wDAAmC,CAAA;IACnC,0DAAqC,CAAA;IACrC,sDAAiC,CAAA;IACjC,kEAA6C,CAAA;IAC7C,sEAAiD,CAAA;IACjD,oFAA+D,CAAA;IAC/D,wFAAmE,CAAA;IACnE,gEAA2C,CAAA;IAC3C,wFAAmE,CAAA;IACnE,wDAAmC,CAAA;IACnC,4DAAuC,CAAA;IACvC,4EAAuD,CAAA;IACvD,4FAAuE,CAAA;IACvE,oFAA+D,CAAA;IAC/D,4DAAuC,CAAA;IACvC,sDAAiC,CAAA;IACjC,sDAAiC,CAAA;IACjC,0EAAqD,CAAA;IACrD,wFAAmE,CAAA;IACnE,gFAA2D,CAAA;IAC3D,oGAA+E,CAAA;IAC/E,kFAA6D,CAAA;IAC7D,wFAAmE,CAAA;IACnE,0FAAqE,CAAA;IACrE,kHAA6F,CAAA;IAC7F,0HAAqG,CAAA;IACrG,4HAAuG,CAAA;IACvG,8EAAyD,CAAA;IACzD,gFAA2D,CAAA;IAC3D,0EAAqD,CAAA;IACrD,0HAAqG,CAAA;IACrG,8CAAyB,CAAA;IACzB,gEAA2C,CAAA;IAC3C,oFAA+D,CAAA;IAC/D,oEAA+C,CAAA;IAC/C,gFAA2D,CAAA;IAE3D,wEAAmD,CAAA;IAEnD,kEAA6C,CAAA;IAC7C,gFAA2D,CAAA;IAC3D,4EAAuD,CAAA;IACvD,sFAAiE,CAAA;IACjE,oEAA+C,CAAA;IAC/C,4FAAuE,CAAA;IAEvE,4DAAuC,CAAA;IACvC,0EAAqD,CAAA;IACrD,sEAAiD,CAAA;IACjD,gFAA2D,CAAA;IAC3D,sFAAiE,CAAA;IAEjE,0EAAqD,CAAA;IACrD,wFAAmE,CAAA;IACnE,oFAA+D,CAAA;IAC/D,8FAAyE,CAAA;IACzE,oFAA+D,CAAA;IAE/D,gFAA2D,CAAA;IAC3D,8FAAyE,CAAA;IACzE,0FAAqE,CAAA;IACrE,oGAA+E,CAAA;IAC/E,gGAA2E,CAAA;IAE3E,8EAAyD,CAAA;IACzD,wFAAmE,CAAA;IACnE,sFAAiE,CAAA;IAEjE,oGAA+E,CAAA;IAC/E,0FAAqE,CAAA;IACrE,wGAAmF,CAAA;IACnF,8GAAyF,CAAA;IACzF,oHAA+F,CAAA;IAC/F,0FAAqE,CAAA;IACrE,sEAAiD,CAAA;IACjD,gGAA2E,CAAA;IAC3E,wDAAmC,CAAA;IACnC,8DAAyC,CAAA;IACzC,oEAA+C,CAAA;IAC/C,8DAAyC,CAAA;IACzC,4EAAuD,CAAA;IACvD,kFAA6D,CAAA;IAE7D,4EAAuD,CAAA;IACvD,oFAA+D,CAAA;IAC/D,oFAA+D,CAAA;IAC/D,0EAAqD,CAAA;IACrD,8FAAyE,CAAA;IACzE,4EAAuD,CAAA;IACvD,gFAA2D,CAAA;IAE3D,kFAA6D,CAAA;IAC7D,4CAAuB,CAAA;IAEvB,gFAA2D,CAAA;IAC3D,kEAA6C,CAAA;IAC7C,wEAAmD,CAAA;IAEnD,8FAAyE,CAAA;IACzE,4FAAuE,CAAA;AACzE,CAAC,EArGI,iBAAiB,KAAjB,iBAAiB,QAqGrB;AAED,eAAe,iBAAiB,CAAC"}
@@ -56,6 +56,9 @@ var NotificationSettingEventType;
56
56
  NotificationSettingEventType["SEND_WHEN_USER_IS_ADDED_TO_ON_CALL_POLICY"] = "When user is added to on-call policy";
57
57
  NotificationSettingEventType["SEND_WHEN_USER_IS_REMOVED_FROM_ON_CALL_POLICY"] = "When user is removed from on-call policy";
58
58
  NotificationSettingEventType["SEND_WHEN_USER_IS_NO_LONGER_ACTIVE_ON_ON_CALL_ROSTER"] = "When user is no longer active on on-call roster";
59
+ // On Call Shift Reminders (see UserOnCallShiftReminder)
60
+ NotificationSettingEventType["SEND_BEFORE_USER_ON_CALL_SHIFT_STARTS"] = "Before user's on-call shift starts";
61
+ NotificationSettingEventType["SEND_WHEN_USER_ON_CALL_SHIFT_IS_REASSIGNED"] = "User's upcoming on-call shift is reassigned";
59
62
  })(NotificationSettingEventType || (NotificationSettingEventType = {}));
60
63
  export default NotificationSettingEventType;
61
64
  //# sourceMappingURL=NotificationSettingEventType.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"NotificationSettingEventType.js","sourceRoot":"","sources":["../../../../Types/NotificationSetting/NotificationSettingEventType.ts"],"names":[],"mappings":"AAAA,IAAK,4BAsEJ;AAtED,WAAK,4BAA4B;IAC/B,WAAW;IACX,mJAAmH,CAAA;IACnH,2JAA2H,CAAA;IAC3H,+JAA+H,CAAA;IAC/H,uIAAuG,CAAA;IACvG,2IAA2G,CAAA;IAC3G,6IAA6G,CAAA;IAE7G,SAAS;IAET,0IAA0G,CAAA;IAC1G,kJAAkH,CAAA;IAClH,sJAAsH,CAAA;IACtH,iIAAiG,CAAA;IACjG,uIAAuG,CAAA;IAEvG,iBAAiB;IAEjB,kKAAkI,CAAA;IAClI,0KAA0I,CAAA;IAC1I,8KAA8I,CAAA;IAC9I,iJAAiH,CAAA;IACjH,wJAAwH,CAAA;IAExH,oBAAoB;IAEpB,2KAA2I,CAAA;IAC3I,mLAAmJ,CAAA;IACnJ,uLAAuJ,CAAA;IACvJ,uJAAuH,CAAA;IACvH,iKAAiI,CAAA;IAEjI,WAAW;IACX,qIAAqG,CAAA;IACrG,gJAAgH,CAAA;IAChH,8JAA8H,CAAA;IAC9H,2IAA2G,CAAA;IAC3G,2KAA2I,CAAA;IAE3I,wBAAwB;IACxB,0JAA0H,CAAA;IAC1H,kKAAkI,CAAA;IAClI,iJAAiH,CAAA;IACjH,sKAAsI,CAAA;IACtI,oLAAoJ,CAAA;IAEpJ,cAAc;IACd,sLAAsJ,CAAA;IACtJ,4JAA4H,CAAA;IAC5H,6IAA6G,CAAA;IAE7G,mCAAmC;IACnC,wJAAwH,CAAA;IACxH,iIAAiG,CAAA;IAEjG,sCAAsC;IACtC,iKAAiI,CAAA;IACjI,uIAAuG,CAAA;IAEvG,MAAM;IACN,gJAAgH,CAAA;IAChH,6HAA6F,CAAA;IAE7F,wBAAwB;IACxB,gGAAgE,CAAA;IAChE,0GAA0E,CAAA;IAC1E,kHAAkF,CAAA;IAClF,0HAA0F,CAAA;IAC1F,wIAAwG,CAAA;AAC1G,CAAC,EAtEI,4BAA4B,KAA5B,4BAA4B,QAsEhC;AAED,eAAe,4BAA4B,CAAC"}
1
+ {"version":3,"file":"NotificationSettingEventType.js","sourceRoot":"","sources":["../../../../Types/NotificationSetting/NotificationSettingEventType.ts"],"names":[],"mappings":"AAAA,IAAK,4BA0EJ;AA1ED,WAAK,4BAA4B;IAC/B,WAAW;IACX,mJAAmH,CAAA;IACnH,2JAA2H,CAAA;IAC3H,+JAA+H,CAAA;IAC/H,uIAAuG,CAAA;IACvG,2IAA2G,CAAA;IAC3G,6IAA6G,CAAA;IAE7G,SAAS;IAET,0IAA0G,CAAA;IAC1G,kJAAkH,CAAA;IAClH,sJAAsH,CAAA;IACtH,iIAAiG,CAAA;IACjG,uIAAuG,CAAA;IAEvG,iBAAiB;IAEjB,kKAAkI,CAAA;IAClI,0KAA0I,CAAA;IAC1I,8KAA8I,CAAA;IAC9I,iJAAiH,CAAA;IACjH,wJAAwH,CAAA;IAExH,oBAAoB;IAEpB,2KAA2I,CAAA;IAC3I,mLAAmJ,CAAA;IACnJ,uLAAuJ,CAAA;IACvJ,uJAAuH,CAAA;IACvH,iKAAiI,CAAA;IAEjI,WAAW;IACX,qIAAqG,CAAA;IACrG,gJAAgH,CAAA;IAChH,8JAA8H,CAAA;IAC9H,2IAA2G,CAAA;IAC3G,2KAA2I,CAAA;IAE3I,wBAAwB;IACxB,0JAA0H,CAAA;IAC1H,kKAAkI,CAAA;IAClI,iJAAiH,CAAA;IACjH,sKAAsI,CAAA;IACtI,oLAAoJ,CAAA;IAEpJ,cAAc;IACd,sLAAsJ,CAAA;IACtJ,4JAA4H,CAAA;IAC5H,6IAA6G,CAAA;IAE7G,mCAAmC;IACnC,wJAAwH,CAAA;IACxH,iIAAiG,CAAA;IAEjG,sCAAsC;IACtC,iKAAiI,CAAA;IACjI,uIAAuG,CAAA;IAEvG,MAAM;IACN,gJAAgH,CAAA;IAChH,6HAA6F,CAAA;IAE7F,wBAAwB;IACxB,gGAAgE,CAAA;IAChE,0GAA0E,CAAA;IAC1E,kHAAkF,CAAA;IAClF,0HAA0F,CAAA;IAC1F,wIAAwG,CAAA;IAExG,wDAAwD;IACxD,4GAA4E,CAAA;IAC5E,0HAA0F,CAAA;AAC5F,CAAC,EA1EI,4BAA4B,KAA5B,4BAA4B,QA0EhC;AAED,eAAe,4BAA4B,CAAC"}
@@ -0,0 +1,97 @@
1
+ /*
2
+ * Window and cost constants for the on-call calendar feeds.
3
+ *
4
+ * These are deliberately constants rather than environment variables: they
5
+ * bound how much work one feed fetch can cause and how large a body a
6
+ * calendar client has to swallow, and an operator tuning them per install
7
+ * would only move the failure elsewhere (Google skips events in very large
8
+ * feeds; Proton rejects oversized feeds outright).
9
+ */
10
+ // Furthest a feed may look ahead, in days.
11
+ export const MAX_FUTURE_DAYS = 180;
12
+ // Shortest look-ahead a subscriber may pick, in days.
13
+ export const MIN_FUTURE_DAYS = 7;
14
+ // Look-ahead used when a feed row has no explicit setting.
15
+ export const DEFAULT_FUTURE_DAYS = 90;
16
+ // Furthest a feed may look back, in days. History is opt-in beyond 2 days.
17
+ export const MAX_PAST_DAYS = 60;
18
+ // Look-back used when a feed row has no explicit setting.
19
+ export const DEFAULT_PAST_DAYS = 2;
20
+ /*
21
+ * Hard cap on VEVENTs in one feed. When a feed would exceed it, futureDays is
22
+ * shrunk until it fits (see OnCallCalendarFeedUtil.shrinkWindowToFit).
23
+ */
24
+ export const MAX_EVENTS = 5000;
25
+ // Hard cap on "No coverage" events per feed (oldest first).
26
+ export const MAX_GAP_EVENTS = 100;
27
+ // A rotated-out token keeps serving an EMPTY calendar for this long.
28
+ export const PREVIOUS_TOKEN_GRACE_DAYS = 30;
29
+ // Rendered body cache TTL, in seconds (also the Cache-Control max-age).
30
+ export const BODY_CACHE_TTL_SECONDS = 300;
31
+ // Schedule-level materialized-shift cache TTL, in seconds.
32
+ export const SCHEDULE_CACHE_TTL_SECONDS = 3600;
33
+ // Maximum concurrent uncached renders per process.
34
+ export const RENDER_CONCURRENCY = 4;
35
+ /*
36
+ * Per-layer rotation-period budget for feed rendering (LayerUtil's
37
+ * maxSimulationIterations). Well above any realistic schedule age at hourly
38
+ * granularity, far below the engine's 5,000,000 ceiling.
39
+ */
40
+ export const FEED_SIMULATION_ITERATION_CAP = 200000;
41
+ const MILLISECONDS_PER_DAY = 24 * 60 * 60 * 1000;
42
+ export default class CalendarFeedWindow {
43
+ /*
44
+ * Coerce a stored / user-supplied pastDays value into the allowed range.
45
+ * Anything that is not a finite number falls back to the default rather
46
+ * than to 0, so a missing column never silently hides the current shift.
47
+ */
48
+ static clampPastDays(value) {
49
+ const parsed = CalendarFeedWindow.toFiniteInteger(value);
50
+ if (Number.isNaN(parsed)) {
51
+ return DEFAULT_PAST_DAYS;
52
+ }
53
+ return Math.min(MAX_PAST_DAYS, Math.max(0, parsed));
54
+ }
55
+ static clampFutureDays(value) {
56
+ const parsed = CalendarFeedWindow.toFiniteInteger(value);
57
+ if (Number.isNaN(parsed)) {
58
+ return DEFAULT_FUTURE_DAYS;
59
+ }
60
+ return Math.min(MAX_FUTURE_DAYS, Math.max(MIN_FUTURE_DAYS, parsed));
61
+ }
62
+ /*
63
+ * The feed window for a fetch at `now`. Both edges sit on UTC midnights so
64
+ * every fetch inside the same UTC day produces the same window — which is
65
+ * what makes the rendered body cacheable across polls.
66
+ */
67
+ static computeFeedWindow(data) {
68
+ const pastDays = CalendarFeedWindow.clampPastDays(data.pastDays);
69
+ const futureDays = CalendarFeedWindow.clampFutureDays(data.futureDays);
70
+ const todayUtc = CalendarFeedWindow.startOfUtcDay(data.now);
71
+ return {
72
+ feedStart: new Date(todayUtc - pastDays * MILLISECONDS_PER_DAY),
73
+ feedEnd: new Date(todayUtc + (futureDays + 1) * MILLISECONDS_PER_DAY),
74
+ };
75
+ }
76
+ // 00:00:00.000 UTC of the day containing `date`, as epoch milliseconds.
77
+ static startOfUtcDay(date) {
78
+ return Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate());
79
+ }
80
+ // "YYYY-MM-DD" of the UTC day containing `date`, for cache keys.
81
+ static getUtcDayBucket(date) {
82
+ return new Date(CalendarFeedWindow.startOfUtcDay(date))
83
+ .toISOString()
84
+ .slice(0, 10);
85
+ }
86
+ static toFiniteInteger(value) {
87
+ if (typeof value === "number") {
88
+ return Number.isFinite(value) ? Math.floor(value) : Number.NaN;
89
+ }
90
+ if (typeof value === "string" && value.trim() !== "") {
91
+ const parsed = Number(value);
92
+ return Number.isFinite(parsed) ? Math.floor(parsed) : Number.NaN;
93
+ }
94
+ return Number.NaN;
95
+ }
96
+ }
97
+ //# sourceMappingURL=CalendarFeedWindow.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CalendarFeedWindow.js","sourceRoot":"","sources":["../../../../Types/OnCallDutyPolicy/CalendarFeedWindow.ts"],"names":[],"mappings":"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"}