@oneuptime/common 11.5.13 → 11.6.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.
Files changed (122) hide show
  1. package/Models/DatabaseModels/EnterpriseLicense.ts +21 -0
  2. package/Models/DatabaseModels/EnterpriseLicenseInstance.ts +25 -0
  3. package/Models/DatabaseModels/GlobalConfig.ts +76 -0
  4. package/Server/API/EnterpriseLicenseAPI.ts +57 -0
  5. package/Server/API/GlobalConfigAPI.ts +62 -1
  6. package/Server/EnvironmentConfig.ts +22 -0
  7. package/Server/Infrastructure/Postgres/SchemaMigrations/1784659816363-AddInstanceVersionAndLatestReleaseColumns.ts +38 -0
  8. package/Server/Infrastructure/Postgres/SchemaMigrations/1784705487674-AddEnterpriseLicenseEvaluationColumns.ts +25 -0
  9. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +4 -0
  10. package/Server/Services/AnalyticsDatabaseService.ts +48 -45
  11. package/Server/Services/DatabaseService.ts +66 -1
  12. package/Server/Services/WorkflowService.ts +100 -39
  13. package/Server/Types/Workflow/Components/Schedule.ts +57 -32
  14. package/Server/Utils/AnalyticsDatabase/InsertDedupContext.ts +59 -0
  15. package/Server/Utils/Express.ts +13 -0
  16. package/Server/Utils/Telemetry/TelemetryFanInWriter.ts +799 -0
  17. package/Server/Utils/Telemetry/TelemetryWriterClient.ts +263 -0
  18. package/Server/Utils/Telemetry/TelemetryWriterServer.ts +240 -0
  19. package/Server/Utils/Telemetry/TelemetryWriterShedMetrics.ts +93 -0
  20. package/Tests/Server/Services/DatabaseServiceSanitizeUpdateData.test.ts +232 -0
  21. package/Tests/Server/Services/UpdateOneByIdKeepsRowId.test.ts +107 -0
  22. package/Tests/Server/Services/WorkflowService.test.ts +308 -0
  23. package/Tests/Server/Utils/Attribution.test.ts +203 -0
  24. package/Tests/Server/Utils/Marketing/ConversionUploadProvider.test.ts +183 -0
  25. package/Tests/Server/Utils/Marketing/GoogleAds.test.ts +340 -0
  26. package/Tests/Server/Utils/Monitor/Criteria/ExceptionMonitorCriteria.test.ts +87 -0
  27. package/Tests/Server/Utils/Monitor/Criteria/LogMonitorCriteria.test.ts +165 -0
  28. package/Tests/Server/Utils/Monitor/Criteria/TraceMonitorCriteria.test.ts +86 -0
  29. package/Tests/Server/Utils/Telemetry/TelemetryFanInWriter.test.ts +1565 -0
  30. package/Tests/Server/Utils/Telemetry/TelemetryWriterClient.test.ts +313 -0
  31. package/Tests/Server/Utils/Telemetry/TelemetryWriterServer.test.ts +270 -0
  32. package/Tests/Server/Utils/Telemetry/TelemetryWriterShedMetrics.test.ts +127 -0
  33. package/Tests/Types/AI/CodeFixTaskType.test.ts +3 -0
  34. package/Tests/Types/Monitor/MonitorCriteriaMetricVariables.test.ts +228 -0
  35. package/Tests/Types/Monitor/MonitorStepDefaultTelemetryConfig.test.ts +169 -0
  36. package/Tests/Types/Monitor/MonitorStepExceptionMonitor.test.ts +289 -0
  37. package/Tests/Types/Monitor/MonitorStepLogMonitor.test.ts +231 -0
  38. package/Tests/Types/Monitor/MonitorStepMetricViewConfigUtil.test.ts +245 -0
  39. package/Tests/Types/Monitor/MonitorStepNetworkDeviceMonitor.test.ts +155 -0
  40. package/Tests/Types/Monitor/MonitorStepTelemetrySerialization.test.ts +141 -0
  41. package/Tests/Types/Monitor/MonitorStepTraceMonitor.test.ts +137 -0
  42. package/Tests/Types/Workspace/NotificationRules/NotificationRuleCondition.test.ts +311 -0
  43. package/Tests/UI/Utils/Breadcrumb/BreadcrumbTrailResolver.test.ts +461 -0
  44. package/Tests/UI/Utils/Breadcrumb/fixtures/RealBreadcrumbTrails.ts +2852 -0
  45. package/Tests/UI/Utils/Breadcrumb/fixtures/RealRoutePatterns.ts +758 -0
  46. package/Tests/UI/Utils/NotificationMethodUtil.test.ts +564 -0
  47. package/Tests/Utils/Array.test.ts +156 -0
  48. package/Tests/Utils/CronTab.test.ts +199 -0
  49. package/Tests/Utils/ModelImportExport.test.ts +101 -0
  50. package/Tests/Utils/Number.test.ts +179 -0
  51. package/Tests/Utils/VersionUtil.test.ts +348 -0
  52. package/Tests/jest.setup.ts +1 -0
  53. package/Types/EnterpriseLicense/EnterpriseLicenseInstanceSummary.ts +6 -0
  54. package/Types/Monitor/MonitorStep.ts +24 -4
  55. package/Types/Monitor/MonitorStepMetricViewConfigUtil.ts +105 -0
  56. package/UI/Components/EditionLabel/EditionLabel.tsx +445 -12
  57. package/UI/Components/Workflow/ArgumentsForm.tsx +68 -30
  58. package/UI/Components/Workflow/CronScheduleField.tsx +411 -0
  59. package/UI/Utils/Breadcrumb/BreadcrumbTrailResolver.ts +176 -0
  60. package/UI/Utils/NotificationMethodUtil.ts +310 -0
  61. package/Utils/CronTab.ts +823 -0
  62. package/Utils/ModelImportExport.ts +21 -6
  63. package/Utils/VersionUtil.ts +260 -0
  64. package/build/dist/Models/DatabaseModels/EnterpriseLicense.js +22 -0
  65. package/build/dist/Models/DatabaseModels/EnterpriseLicense.js.map +1 -1
  66. package/build/dist/Models/DatabaseModels/EnterpriseLicenseInstance.js +26 -0
  67. package/build/dist/Models/DatabaseModels/EnterpriseLicenseInstance.js.map +1 -1
  68. package/build/dist/Models/DatabaseModels/GlobalConfig.js +81 -0
  69. package/build/dist/Models/DatabaseModels/GlobalConfig.js.map +1 -1
  70. package/build/dist/Server/API/EnterpriseLicenseAPI.js +47 -0
  71. package/build/dist/Server/API/EnterpriseLicenseAPI.js.map +1 -1
  72. package/build/dist/Server/API/GlobalConfigAPI.js +52 -1
  73. package/build/dist/Server/API/GlobalConfigAPI.js.map +1 -1
  74. package/build/dist/Server/EnvironmentConfig.js +17 -0
  75. package/build/dist/Server/EnvironmentConfig.js.map +1 -1
  76. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784659816363-AddInstanceVersionAndLatestReleaseColumns.js +18 -0
  77. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784659816363-AddInstanceVersionAndLatestReleaseColumns.js.map +1 -0
  78. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784705487674-AddEnterpriseLicenseEvaluationColumns.js +14 -0
  79. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784705487674-AddEnterpriseLicenseEvaluationColumns.js.map +1 -0
  80. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +4 -0
  81. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  82. package/build/dist/Server/Services/AnalyticsDatabaseService.js +44 -16
  83. package/build/dist/Server/Services/AnalyticsDatabaseService.js.map +1 -1
  84. package/build/dist/Server/Services/DatabaseService.js +53 -1
  85. package/build/dist/Server/Services/DatabaseService.js.map +1 -1
  86. package/build/dist/Server/Services/WorkflowService.js +80 -30
  87. package/build/dist/Server/Services/WorkflowService.js.map +1 -1
  88. package/build/dist/Server/Types/Workflow/Components/Schedule.js +44 -19
  89. package/build/dist/Server/Types/Workflow/Components/Schedule.js.map +1 -1
  90. package/build/dist/Server/Utils/AnalyticsDatabase/InsertDedupContext.js +24 -0
  91. package/build/dist/Server/Utils/AnalyticsDatabase/InsertDedupContext.js.map +1 -0
  92. package/build/dist/Server/Utils/Express.js +12 -0
  93. package/build/dist/Server/Utils/Express.js.map +1 -1
  94. package/build/dist/Server/Utils/Telemetry/TelemetryFanInWriter.js +496 -0
  95. package/build/dist/Server/Utils/Telemetry/TelemetryFanInWriter.js.map +1 -0
  96. package/build/dist/Server/Utils/Telemetry/TelemetryWriterClient.js +165 -0
  97. package/build/dist/Server/Utils/Telemetry/TelemetryWriterClient.js.map +1 -0
  98. package/build/dist/Server/Utils/Telemetry/TelemetryWriterServer.js +136 -0
  99. package/build/dist/Server/Utils/Telemetry/TelemetryWriterServer.js.map +1 -0
  100. package/build/dist/Server/Utils/Telemetry/TelemetryWriterShedMetrics.js +76 -0
  101. package/build/dist/Server/Utils/Telemetry/TelemetryWriterShedMetrics.js.map +1 -0
  102. package/build/dist/Types/Monitor/MonitorStep.js +20 -4
  103. package/build/dist/Types/Monitor/MonitorStep.js.map +1 -1
  104. package/build/dist/Types/Monitor/MonitorStepMetricViewConfigUtil.js +73 -0
  105. package/build/dist/Types/Monitor/MonitorStepMetricViewConfigUtil.js.map +1 -0
  106. package/build/dist/UI/Components/EditionLabel/EditionLabel.js +261 -13
  107. package/build/dist/UI/Components/EditionLabel/EditionLabel.js.map +1 -1
  108. package/build/dist/UI/Components/Workflow/ArgumentsForm.js +30 -6
  109. package/build/dist/UI/Components/Workflow/ArgumentsForm.js.map +1 -1
  110. package/build/dist/UI/Components/Workflow/CronScheduleField.js +209 -0
  111. package/build/dist/UI/Components/Workflow/CronScheduleField.js.map +1 -0
  112. package/build/dist/UI/Utils/Breadcrumb/BreadcrumbTrailResolver.js +129 -0
  113. package/build/dist/UI/Utils/Breadcrumb/BreadcrumbTrailResolver.js.map +1 -0
  114. package/build/dist/UI/Utils/NotificationMethodUtil.js +189 -0
  115. package/build/dist/UI/Utils/NotificationMethodUtil.js.map +1 -0
  116. package/build/dist/Utils/CronTab.js +609 -0
  117. package/build/dist/Utils/CronTab.js.map +1 -0
  118. package/build/dist/Utils/ModelImportExport.js +20 -6
  119. package/build/dist/Utils/ModelImportExport.js.map +1 -1
  120. package/build/dist/Utils/VersionUtil.js +193 -0
  121. package/build/dist/Utils/VersionUtil.js.map +1 -0
  122. package/package.json +1 -1
@@ -0,0 +1,311 @@
1
+ import NotificationRuleCondition, {
2
+ ConditionType,
3
+ NotificationRuleConditionCheckOn,
4
+ NotificationRuleConditionUtil,
5
+ } from "../../../../Types/Workspace/NotificationRules/NotificationRuleCondition";
6
+ import NotificationRuleEventType from "../../../../Types/Workspace/NotificationRules/EventType";
7
+ import IncidentNotificationRule from "../../../../Types/Workspace/NotificationRules/NotificationRuleTypes/IncidentNotificationRule";
8
+ import WorkspaceType from "../../../../Types/Workspace/WorkspaceType";
9
+
10
+ describe("NotificationRuleConditionUtil", () => {
11
+ const makeRule: (
12
+ overrides?: Partial<IncidentNotificationRule>,
13
+ ) => IncidentNotificationRule = (
14
+ overrides: Partial<IncidentNotificationRule> = {},
15
+ ): IncidentNotificationRule => {
16
+ return {
17
+ filters: [],
18
+ shouldCreateNewChannel: true,
19
+ newChannelTemplateName: "incident-{{id}}",
20
+ shouldPostToExistingChannel: false,
21
+ ...overrides,
22
+ } as unknown as IncidentNotificationRule;
23
+ };
24
+
25
+ const validate: (rule: IncidentNotificationRule) => string | null = (
26
+ rule: IncidentNotificationRule,
27
+ ): string | null => {
28
+ return NotificationRuleConditionUtil.getValidationError({
29
+ notificationRule: rule,
30
+ eventType: NotificationRuleEventType.Incident,
31
+ workspaceType: WorkspaceType.Slack,
32
+ });
33
+ };
34
+
35
+ describe("getValidationError - filters", () => {
36
+ test("requires checkOn on every filter", () => {
37
+ const rule: IncidentNotificationRule = makeRule({
38
+ filters: [
39
+ {
40
+ conditionType: ConditionType.EqualTo,
41
+ value: "x",
42
+ } as unknown as NotificationRuleCondition,
43
+ ],
44
+ });
45
+ expect(validate(rule)).toBe("Check On is required");
46
+ });
47
+
48
+ test("requires a condition type", () => {
49
+ const rule: IncidentNotificationRule = makeRule({
50
+ filters: [
51
+ {
52
+ checkOn: NotificationRuleConditionCheckOn.IncidentTitle,
53
+ conditionType: undefined,
54
+ value: "x",
55
+ },
56
+ ],
57
+ });
58
+ expect(validate(rule)).toBe(
59
+ `Filter Condition is required for ${NotificationRuleConditionCheckOn.IncidentTitle}`,
60
+ );
61
+ });
62
+
63
+ test("requires a value", () => {
64
+ const rule: IncidentNotificationRule = makeRule({
65
+ filters: [
66
+ {
67
+ checkOn: NotificationRuleConditionCheckOn.IncidentTitle,
68
+ conditionType: ConditionType.EqualTo,
69
+ value: undefined,
70
+ },
71
+ ],
72
+ });
73
+ expect(validate(rule)).toBe(
74
+ `Value is required for ${NotificationRuleConditionCheckOn.IncidentTitle}`,
75
+ );
76
+ });
77
+
78
+ test("rejects an empty-array value", () => {
79
+ const rule: IncidentNotificationRule = makeRule({
80
+ filters: [
81
+ {
82
+ checkOn: NotificationRuleConditionCheckOn.IncidentLabels,
83
+ conditionType: ConditionType.ContainsAny,
84
+ value: [],
85
+ },
86
+ ],
87
+ });
88
+ expect(validate(rule)).toBe(
89
+ `Value is required for ${NotificationRuleConditionCheckOn.IncidentLabels}`,
90
+ );
91
+ });
92
+ });
93
+
94
+ describe("getValidationError - channel selection", () => {
95
+ test("requires either create-new or post-to-existing channel", () => {
96
+ const rule: IncidentNotificationRule = makeRule({
97
+ shouldCreateNewChannel: false,
98
+ shouldPostToExistingChannel: false,
99
+ });
100
+ expect(validate(rule)).toBe(
101
+ "Please select either create slack channel or post to existing Slack channel",
102
+ );
103
+ });
104
+
105
+ test("requires an existing channel name when posting to an existing channel", () => {
106
+ const rule: IncidentNotificationRule = makeRule({
107
+ shouldCreateNewChannel: false,
108
+ shouldPostToExistingChannel: true,
109
+ existingChannelNames: " ",
110
+ });
111
+ expect(validate(rule)).toBe("Existing Slack channel name is required");
112
+ });
113
+
114
+ test("requires a new channel name when creating a channel", () => {
115
+ const rule: IncidentNotificationRule = makeRule({
116
+ shouldCreateNewChannel: true,
117
+ newChannelTemplateName: " ",
118
+ });
119
+ expect(validate(rule)).toBe("New Slack channel name is required");
120
+ });
121
+
122
+ test("returns null for a fully valid rule", () => {
123
+ expect(validate(makeRule())).toBeNull();
124
+ });
125
+
126
+ test("skips channel validation for event types that do not post to channels", () => {
127
+ const rule: IncidentNotificationRule = makeRule({
128
+ shouldCreateNewChannel: false,
129
+ shouldPostToExistingChannel: false,
130
+ });
131
+ // Monitor events are not in the channel-required set.
132
+ expect(
133
+ NotificationRuleConditionUtil.getValidationError({
134
+ notificationRule: rule,
135
+ eventType: NotificationRuleEventType.Monitor,
136
+ workspaceType: WorkspaceType.Slack,
137
+ }),
138
+ ).toBeNull();
139
+ });
140
+ });
141
+
142
+ describe("hasValueField", () => {
143
+ test.each([
144
+ ConditionType.IsEmpty,
145
+ ConditionType.IsNotEmpty,
146
+ ConditionType.True,
147
+ ConditionType.False,
148
+ ])(
149
+ "returns false for the valueless condition %s",
150
+ (conditionType: ConditionType) => {
151
+ expect(
152
+ NotificationRuleConditionUtil.hasValueField({
153
+ checkOn: NotificationRuleConditionCheckOn.IncidentTitle,
154
+ conditionType,
155
+ }),
156
+ ).toBe(false);
157
+ },
158
+ );
159
+
160
+ test.each([ConditionType.EqualTo, ConditionType.Contains])(
161
+ "returns true for the value-based condition %s",
162
+ (conditionType: ConditionType) => {
163
+ expect(
164
+ NotificationRuleConditionUtil.hasValueField({
165
+ checkOn: NotificationRuleConditionCheckOn.IncidentTitle,
166
+ conditionType,
167
+ }),
168
+ ).toBe(true);
169
+ },
170
+ );
171
+ });
172
+
173
+ describe("isDropdownValueField", () => {
174
+ test("returns false when checkOn or conditionType is missing", () => {
175
+ expect(
176
+ NotificationRuleConditionUtil.isDropdownValueField({
177
+ checkOn: undefined,
178
+ conditionType: ConditionType.ContainsAny,
179
+ }),
180
+ ).toBe(false);
181
+ expect(
182
+ NotificationRuleConditionUtil.isDropdownValueField({
183
+ checkOn: NotificationRuleConditionCheckOn.IncidentState,
184
+ conditionType: undefined,
185
+ }),
186
+ ).toBe(false);
187
+ });
188
+
189
+ test.each([
190
+ NotificationRuleConditionCheckOn.IncidentState,
191
+ NotificationRuleConditionCheckOn.IncidentSeverity,
192
+ NotificationRuleConditionCheckOn.MonitorLabels,
193
+ NotificationRuleConditionCheckOn.Monitors,
194
+ ])(
195
+ "returns true for the dropdown checkOn %s",
196
+ (checkOn: NotificationRuleConditionCheckOn) => {
197
+ expect(
198
+ NotificationRuleConditionUtil.isDropdownValueField({
199
+ checkOn,
200
+ conditionType: ConditionType.ContainsAny,
201
+ }),
202
+ ).toBe(true);
203
+ },
204
+ );
205
+
206
+ test.each([
207
+ NotificationRuleConditionCheckOn.IncidentTitle,
208
+ NotificationRuleConditionCheckOn.IncidentDescription,
209
+ ])(
210
+ "returns false for the free-text checkOn %s",
211
+ (checkOn: NotificationRuleConditionCheckOn) => {
212
+ expect(
213
+ NotificationRuleConditionUtil.isDropdownValueField({
214
+ checkOn,
215
+ conditionType: ConditionType.EqualTo,
216
+ }),
217
+ ).toBe(false);
218
+ },
219
+ );
220
+ });
221
+
222
+ describe("getCheckOnByEventType", () => {
223
+ test("returns incident checkOns for the Incident event", () => {
224
+ const checkOns: Array<NotificationRuleConditionCheckOn> =
225
+ NotificationRuleConditionUtil.getCheckOnByEventType(
226
+ NotificationRuleEventType.Incident,
227
+ );
228
+ expect(checkOns).toContain(
229
+ NotificationRuleConditionCheckOn.IncidentTitle,
230
+ );
231
+ expect(checkOns).toContain(NotificationRuleConditionCheckOn.Monitors);
232
+ expect(checkOns).not.toContain(
233
+ NotificationRuleConditionCheckOn.AlertTitle,
234
+ );
235
+ });
236
+
237
+ test("returns monitor checkOns for the Monitor event", () => {
238
+ const checkOns: Array<NotificationRuleConditionCheckOn> =
239
+ NotificationRuleConditionUtil.getCheckOnByEventType(
240
+ NotificationRuleEventType.Monitor,
241
+ );
242
+ expect(checkOns).toContain(NotificationRuleConditionCheckOn.MonitorName);
243
+ expect(checkOns).toContain(
244
+ NotificationRuleConditionCheckOn.MonitorStatus,
245
+ );
246
+ });
247
+
248
+ test("returns an empty list for an unhandled event type", () => {
249
+ expect(
250
+ NotificationRuleConditionUtil.getCheckOnByEventType(
251
+ NotificationRuleEventType.OnCallDutyPolicy,
252
+ ),
253
+ ).toEqual([]);
254
+ });
255
+ });
256
+
257
+ describe("getConditionTypeByCheckOn", () => {
258
+ test("free-text fields offer the string comparison operators", () => {
259
+ const types: Array<ConditionType> =
260
+ NotificationRuleConditionUtil.getConditionTypeByCheckOn(
261
+ NotificationRuleConditionCheckOn.IncidentTitle,
262
+ );
263
+ expect(types).toContain(ConditionType.EqualTo);
264
+ expect(types).toContain(ConditionType.Contains);
265
+ expect(types).toContain(ConditionType.StartsWith);
266
+ expect(types).not.toContain(ConditionType.ContainsAll);
267
+ });
268
+
269
+ test("state/severity fields offer ContainsAny / NotContains", () => {
270
+ expect(
271
+ NotificationRuleConditionUtil.getConditionTypeByCheckOn(
272
+ NotificationRuleConditionCheckOn.IncidentState,
273
+ ),
274
+ ).toEqual([ConditionType.ContainsAny, ConditionType.NotContains]);
275
+ });
276
+
277
+ test("label fields additionally offer ContainsAll", () => {
278
+ const types: Array<ConditionType> =
279
+ NotificationRuleConditionUtil.getConditionTypeByCheckOn(
280
+ NotificationRuleConditionCheckOn.IncidentLabels,
281
+ );
282
+ expect(types).toContain(ConditionType.ContainsAll);
283
+ });
284
+
285
+ test("returns an empty list for an unhandled checkOn", () => {
286
+ expect(
287
+ NotificationRuleConditionUtil.getConditionTypeByCheckOn(
288
+ "Unhandled" as NotificationRuleConditionCheckOn,
289
+ ),
290
+ ).toEqual([]);
291
+ });
292
+ });
293
+
294
+ describe("getDropdownOptionsByCheckOn", () => {
295
+ test("returns an empty list when the backing collections are empty", () => {
296
+ expect(
297
+ NotificationRuleConditionUtil.getDropdownOptionsByCheckOn({
298
+ alertSeverities: [],
299
+ alertStates: [],
300
+ incidentSeverities: [],
301
+ monitorStatus: [],
302
+ incidentStates: [],
303
+ scheduledMaintenanceStates: [],
304
+ labels: [],
305
+ monitors: [],
306
+ checkOn: NotificationRuleConditionCheckOn.IncidentSeverity,
307
+ }),
308
+ ).toEqual([]);
309
+ });
310
+ });
311
+ });