@oneuptime/common 7.0.5080 → 7.0.5092

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 (59) hide show
  1. package/Models/DatabaseModels/OnCallDutyPolicyEscalationRule.ts +1 -1
  2. package/Models/DatabaseModels/OnCallDutyPolicyEscalationRuleSchedule.ts +1 -1
  3. package/Models/DatabaseModels/OnCallDutyPolicyEscalationRuleTeam.ts +1 -1
  4. package/Models/DatabaseModels/OnCallDutyPolicyEscalationRuleUser.ts +1 -1
  5. package/Models/DatabaseModels/Project.ts +33 -0
  6. package/Server/Infrastructure/Postgres/SchemaMigrations/1756821449686-MigrationName.ts +17 -0
  7. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +2 -0
  8. package/Server/Services/AlertService.ts +1 -1
  9. package/Server/Services/MonitorService.ts +27 -7
  10. package/Server/Types/Markdown.ts +0 -1
  11. package/Server/Utils/Monitor/MonitorAlert.ts +20 -4
  12. package/Server/Utils/Monitor/MonitorIncident.ts +23 -5
  13. package/Server/Utils/Monitor/MonitorTemplateUtil.ts +108 -0
  14. package/Server/Utils/VM/VMAPI.ts +11 -2
  15. package/Types/WebsiteRequest.ts +11 -0
  16. package/UI/Components/Graphs/ServiceDependencyGraph.tsx +10 -5
  17. package/UI/Components/Input/Input.tsx +5 -4
  18. package/UI/Components/Workflow/ArgumentsForm.tsx +5 -3
  19. package/UI/Components/Workflow/Utils.ts +3 -8
  20. package/Utils/API.ts +14 -0
  21. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyEscalationRule.js +1 -1
  22. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyEscalationRule.js.map +1 -1
  23. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyEscalationRuleSchedule.js +1 -1
  24. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyEscalationRuleSchedule.js.map +1 -1
  25. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyEscalationRuleTeam.js +1 -1
  26. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyEscalationRuleTeam.js.map +1 -1
  27. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyEscalationRuleUser.js +1 -1
  28. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyEscalationRuleUser.js.map +1 -1
  29. package/build/dist/Models/DatabaseModels/Project.js +34 -0
  30. package/build/dist/Models/DatabaseModels/Project.js.map +1 -1
  31. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1756821449686-MigrationName.js +12 -0
  32. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1756821449686-MigrationName.js.map +1 -0
  33. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +2 -0
  34. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  35. package/build/dist/Server/Services/AlertService.js +1 -1
  36. package/build/dist/Server/Services/AlertService.js.map +1 -1
  37. package/build/dist/Server/Services/MonitorService.js +22 -7
  38. package/build/dist/Server/Services/MonitorService.js.map +1 -1
  39. package/build/dist/Server/Types/Markdown.js.map +1 -1
  40. package/build/dist/Server/Utils/Monitor/MonitorAlert.js +17 -3
  41. package/build/dist/Server/Utils/Monitor/MonitorAlert.js.map +1 -1
  42. package/build/dist/Server/Utils/Monitor/MonitorIncident.js +17 -3
  43. package/build/dist/Server/Utils/Monitor/MonitorIncident.js.map +1 -1
  44. package/build/dist/Server/Utils/Monitor/MonitorTemplateUtil.js +80 -0
  45. package/build/dist/Server/Utils/Monitor/MonitorTemplateUtil.js.map +1 -0
  46. package/build/dist/Server/Utils/VM/VMAPI.js +9 -1
  47. package/build/dist/Server/Utils/VM/VMAPI.js.map +1 -1
  48. package/build/dist/Types/WebsiteRequest.js +6 -0
  49. package/build/dist/Types/WebsiteRequest.js.map +1 -1
  50. package/build/dist/UI/Components/Graphs/ServiceDependencyGraph.js +1 -1
  51. package/build/dist/UI/Components/Graphs/ServiceDependencyGraph.js.map +1 -1
  52. package/build/dist/UI/Components/Input/Input.js.map +1 -1
  53. package/build/dist/UI/Components/Workflow/ArgumentsForm.js +4 -2
  54. package/build/dist/UI/Components/Workflow/ArgumentsForm.js.map +1 -1
  55. package/build/dist/UI/Components/Workflow/Utils.js +1 -4
  56. package/build/dist/UI/Components/Workflow/Utils.js.map +1 -1
  57. package/build/dist/Utils/API.js +8 -0
  58. package/build/dist/Utils/API.js.map +1 -1
  59. package/package.json +1 -1
@@ -46,7 +46,7 @@ import { Column, Entity, Index, JoinColumn, ManyToOne } from "typeorm";
46
46
  Permission.EditProjectOnCallDutyPolicyEscalationRule,
47
47
  ],
48
48
  })
49
- @CrudApiEndpoint(new Route("/on-call-duty-policy-esclation-rule"))
49
+ @CrudApiEndpoint(new Route("/on-call-duty-policy-escalation-rule"))
50
50
  @Entity({
51
51
  name: "OnCallDutyPolicyEscalationRule",
52
52
  })
@@ -47,7 +47,7 @@ import { Column, Entity, Index, JoinColumn, ManyToOne } from "typeorm";
47
47
  Permission.EditProjectOnCallDutyPolicyEscalationRuleSchedule,
48
48
  ],
49
49
  })
50
- @CrudApiEndpoint(new Route("/on-call-duty-policy-esclation-rule-schedule"))
50
+ @CrudApiEndpoint(new Route("/on-call-duty-policy-escalation-rule-schedule"))
51
51
  @Entity({
52
52
  name: "OnCallDutyPolicyEscalationRuleSchedule",
53
53
  })
@@ -47,7 +47,7 @@ import { Column, Entity, Index, JoinColumn, ManyToOne } from "typeorm";
47
47
  Permission.EditProjectOnCallDutyPolicyEscalationRuleTeam,
48
48
  ],
49
49
  })
50
- @CrudApiEndpoint(new Route("/on-call-duty-policy-esclation-rule-team"))
50
+ @CrudApiEndpoint(new Route("/on-call-duty-policy-escalation-rule-team"))
51
51
  @Entity({
52
52
  name: "OnCallDutyPolicyEscalationRuleTeam",
53
53
  })
@@ -46,7 +46,7 @@ import { Column, Entity, Index, JoinColumn, ManyToOne } from "typeorm";
46
46
  Permission.EditProjectOnCallDutyPolicyEscalationRuleUser,
47
47
  ],
48
48
  })
49
- @CrudApiEndpoint(new Route("/on-call-duty-policy-esclation-rule-user"))
49
+ @CrudApiEndpoint(new Route("/on-call-duty-policy-escalation-rule-user"))
50
50
  @Entity({
51
51
  name: "OnCallDutyPolicyEscalationRuleUser",
52
52
  })
@@ -1291,4 +1291,37 @@ export default class Project extends TenantModel {
1291
1291
  type: ColumnType.Boolean,
1292
1292
  })
1293
1293
  public letCustomerSupportAccessProject?: boolean = undefined;
1294
+
1295
+ @ColumnAccessControl({
1296
+ create: [],
1297
+ read: [
1298
+ Permission.ProjectOwner,
1299
+ Permission.ProjectAdmin,
1300
+ Permission.ProjectMember,
1301
+ Permission.ReadProject,
1302
+ Permission.UnAuthorizedSsoUser,
1303
+ Permission.ProjectUser,
1304
+ ],
1305
+ update: [
1306
+ Permission.ProjectOwner,
1307
+ Permission.ProjectAdmin,
1308
+ Permission.EditProject,
1309
+ ],
1310
+ })
1311
+ @TableColumn({
1312
+ required: false,
1313
+ type: TableColumnType.Boolean,
1314
+ isDefaultValueColumn: false,
1315
+ title: "Do NOT auto-add Global Probes to new monitors",
1316
+ description:
1317
+ "If enabled, global probes will NOT be automatically added to new monitors. Enable this only if you are using ONLY custom probes to monitor your resources.",
1318
+ defaultValue: false,
1319
+ })
1320
+ @Column({
1321
+ type: ColumnType.Boolean,
1322
+ nullable: false,
1323
+ unique: false,
1324
+ default: false,
1325
+ })
1326
+ public doNotAddGlobalProbesByDefaultOnNewMonitors?: boolean = undefined;
1294
1327
  }
@@ -0,0 +1,17 @@
1
+ import { MigrationInterface, QueryRunner } from "typeorm";
2
+
3
+ export class MigrationName1756821449686 implements MigrationInterface {
4
+ public name = "MigrationName1756821449686";
5
+
6
+ public async up(queryRunner: QueryRunner): Promise<void> {
7
+ await queryRunner.query(
8
+ `ALTER TABLE "Project" ADD "doNotAddGlobalProbesByDefaultOnNewMonitors" boolean NOT NULL DEFAULT false`,
9
+ );
10
+ }
11
+
12
+ public async down(queryRunner: QueryRunner): Promise<void> {
13
+ await queryRunner.query(
14
+ `ALTER TABLE "Project" DROP COLUMN "doNotAddGlobalProbesByDefaultOnNewMonitors"`,
15
+ );
16
+ }
17
+ }
@@ -164,6 +164,7 @@ import { MigrationName1755778934927 } from "./1755778934927-MigrationName";
164
164
  import { MigrationName1756293325324 } from "./1756293325324-MigrationName";
165
165
  import { MigrationName1756296282627 } from "./1756296282627-MigrationName";
166
166
  import { MigrationName1756300358095 } from "./1756300358095-MigrationName";
167
+ import { MigrationName1756821449686 } from "./1756821449686-MigrationName";
167
168
 
168
169
  export default [
169
170
  InitialMigration,
@@ -332,4 +333,5 @@ export default [
332
333
  MigrationName1756293325324,
333
334
  MigrationName1756296282627,
334
335
  MigrationName1756300358095,
336
+ MigrationName1756821449686,
335
337
  ];
@@ -440,7 +440,7 @@ export class Service extends DatabaseService<Model> {
440
440
 
441
441
  ${createdItem.description || "No description provided."}
442
442
 
443
- `;
443
+ `;
444
444
 
445
445
  if (alert.currentAlertState?.name) {
446
446
  feedInfoInMarkdown += `🔴 **Alert State**: ${alert.currentAlertState.name} \n\n`;
@@ -68,6 +68,7 @@ import { FindWhere } from "../../Types/BaseDatabase/Query";
68
68
  import logger from "../Utils/Logger";
69
69
  import PushNotificationUtil from "../Utils/PushNotificationUtil";
70
70
  import ExceptionMessages from "../../Types/Exception/ExceptionMessages";
71
+ import Project from "../../Models/DatabaseModels/Project";
71
72
 
72
73
  export class Service extends DatabaseService<Model> {
73
74
  public constructor() {
@@ -791,21 +792,40 @@ ${createdItem.description?.trim() || "No description provided."}
791
792
  projectId: ObjectID,
792
793
  monitorId: ObjectID,
793
794
  ): Promise<void> {
794
- const globalProbes: Array<Probe> = await ProbeService.findBy({
795
- query: {
796
- isGlobalProbe: true,
797
- shouldAutoEnableProbeOnNewMonitors: true,
798
- },
795
+ // Fetch project to see if global probes should be added automatically.
796
+ const project: Project | null = await ProjectService.findOneById({
797
+ id: projectId,
799
798
  select: {
800
799
  _id: true,
800
+ doNotAddGlobalProbesByDefaultOnNewMonitors: true,
801
801
  },
802
- skip: 0,
803
- limit: LIMIT_PER_PROJECT,
804
802
  props: {
805
803
  isRoot: true,
806
804
  },
807
805
  });
808
806
 
807
+ const shouldSkipGlobalProbes: boolean =
808
+ project?.doNotAddGlobalProbesByDefaultOnNewMonitors === true;
809
+
810
+ let globalProbes: Array<Probe> = [];
811
+
812
+ if (!shouldSkipGlobalProbes) {
813
+ globalProbes = await ProbeService.findBy({
814
+ query: {
815
+ isGlobalProbe: true,
816
+ shouldAutoEnableProbeOnNewMonitors: true,
817
+ },
818
+ select: {
819
+ _id: true,
820
+ },
821
+ skip: 0,
822
+ limit: LIMIT_PER_PROJECT,
823
+ props: {
824
+ isRoot: true,
825
+ },
826
+ });
827
+ }
828
+
809
829
  const projectProbes: Array<Probe> = await ProbeService.findBy({
810
830
  query: {
811
831
  isGlobalProbe: false,
@@ -97,7 +97,6 @@ export default class Markdown {
97
97
 
98
98
  // Inline code
99
99
  renderer.codespan = function (code) {
100
-
101
100
  return `<code class="rounded-md bg-slate-100 px-1.5 py-0.5 text-sm text-slate-700 font-mono">${code}</code>`;
102
101
  };
103
102
 
@@ -19,6 +19,8 @@ import AlertStateTimelineService from "../../Services/AlertStateTimelineService"
19
19
  import logger from "../Logger";
20
20
  import CaptureSpan from "../Telemetry/CaptureSpan";
21
21
  import DataToProcess from "./DataToProcess";
22
+ import MonitorTemplateUtil from "./MonitorTemplateUtil";
23
+ import { JSONObject } from "../../../Types/JSON";
22
24
 
23
25
  export default class MonitorAlert {
24
26
  @CaptureSpan()
@@ -130,9 +132,20 @@ export default class MonitorAlert {
130
132
  logger.debug(`${input.monitor.id?.toString()} - Create alert.`);
131
133
 
132
134
  const alert: Alert = new Alert();
133
-
134
- alert.title = criteriaAlert.title;
135
- alert.description = criteriaAlert.description;
135
+ const storageMap: JSONObject =
136
+ MonitorTemplateUtil.buildTemplateStorageMap({
137
+ monitorType: input.monitor.monitorType!,
138
+ dataToProcess: input.dataToProcess,
139
+ });
140
+
141
+ alert.title = MonitorTemplateUtil.processTemplateString({
142
+ value: criteriaAlert.title,
143
+ storageMap,
144
+ });
145
+ alert.description = MonitorTemplateUtil.processTemplateString({
146
+ value: criteriaAlert.description,
147
+ storageMap,
148
+ });
136
149
 
137
150
  if (!criteriaAlert.alertSeverityId) {
138
151
  // pick the critical criteria.
@@ -194,7 +207,10 @@ export default class MonitorAlert {
194
207
  }
195
208
 
196
209
  if (criteriaAlert.remediationNotes) {
197
- alert.remediationNotes = criteriaAlert.remediationNotes;
210
+ alert.remediationNotes = MonitorTemplateUtil.processTemplateString({
211
+ value: criteriaAlert.remediationNotes,
212
+ storageMap,
213
+ });
198
214
  }
199
215
 
200
216
  if (DisableAutomaticAlertCreation) {
@@ -19,6 +19,8 @@ import IncidentStateTimelineService from "../../Services/IncidentStateTimelineSe
19
19
  import logger from "../Logger";
20
20
  import CaptureSpan from "../Telemetry/CaptureSpan";
21
21
  import DataToProcess from "./DataToProcess";
22
+ import MonitorTemplateUtil from "./MonitorTemplateUtil";
23
+ import { JSONObject } from "../../../Types/JSON";
22
24
 
23
25
  export default class MonitorIncident {
24
26
  @CaptureSpan()
@@ -34,7 +36,7 @@ export default class MonitorIncident {
34
36
  // check active incidents and if there are open incidents, do not cretae anothr incident.
35
37
  const openIncidents: Array<Incident> = await IncidentService.findBy({
36
38
  query: {
37
- monitors: [input.monitorId] as any,
39
+ monitors: [input.monitorId],
38
40
  currentIncidentState: {
39
41
  isResolvedState: false,
40
42
  },
@@ -136,9 +138,20 @@ export default class MonitorIncident {
136
138
  logger.debug(`${input.monitor.id?.toString()} - Create incident.`);
137
139
 
138
140
  const incident: Incident = new Incident();
139
-
140
- incident.title = criteriaIncident.title;
141
- incident.description = criteriaIncident.description;
141
+ const storageMap: JSONObject =
142
+ MonitorTemplateUtil.buildTemplateStorageMap({
143
+ monitorType: input.monitor.monitorType!,
144
+ dataToProcess: input.dataToProcess,
145
+ });
146
+
147
+ incident.title = MonitorTemplateUtil.processTemplateString({
148
+ value: criteriaIncident.title,
149
+ storageMap,
150
+ });
151
+ incident.description = MonitorTemplateUtil.processTemplateString({
152
+ value: criteriaIncident.description,
153
+ storageMap,
154
+ });
142
155
 
143
156
  if (!criteriaIncident.incidentSeverityId) {
144
157
  // pick the critical criteria.
@@ -204,7 +217,12 @@ export default class MonitorIncident {
204
217
  }
205
218
 
206
219
  if (criteriaIncident.remediationNotes) {
207
- incident.remediationNotes = criteriaIncident.remediationNotes;
220
+ incident.remediationNotes = MonitorTemplateUtil.processTemplateString(
221
+ {
222
+ value: criteriaIncident.remediationNotes,
223
+ storageMap,
224
+ },
225
+ );
208
226
  }
209
227
 
210
228
  if (DisableAutomaticIncidentCreation) {
@@ -0,0 +1,108 @@
1
+ import MonitorType from "../../../Types/Monitor/MonitorType";
2
+ import { JSONObject } from "../../../Types/JSON";
3
+ import ProbeMonitorResponse from "../../../Types/Probe/ProbeMonitorResponse";
4
+ import IncomingMonitorRequest from "../../../Types/Monitor/IncomingMonitor/IncomingMonitorRequest";
5
+ import Typeof from "../../../Types/Typeof";
6
+ import VMUtil from "../VM/VMAPI";
7
+ import DataToProcess from "./DataToProcess";
8
+ import logger from "../Logger";
9
+
10
+ /**
11
+ * Utility for building template variable storage map and processing dynamic placeholders
12
+ * shared between Incident and Alert auto-creation.
13
+ */
14
+ export default class MonitorTemplateUtil {
15
+ /**
16
+ * Build a storage map of variables available for templating based on monitor type.
17
+ */
18
+ public static buildTemplateStorageMap(data: {
19
+ monitorType: MonitorType;
20
+ dataToProcess: DataToProcess;
21
+ }): JSONObject {
22
+ let storageMap: JSONObject = {};
23
+
24
+ try {
25
+ if (
26
+ data.monitorType === MonitorType.API ||
27
+ data.monitorType === MonitorType.Website
28
+ ) {
29
+ let responseBody: JSONObject | null = null;
30
+ try {
31
+ responseBody = JSON.parse(
32
+ ((data.dataToProcess as ProbeMonitorResponse)
33
+ .responseBody as string) || "{}",
34
+ );
35
+ } catch (err) {
36
+ logger.error(err);
37
+ responseBody = (data.dataToProcess as ProbeMonitorResponse)
38
+ .responseBody as JSONObject;
39
+ }
40
+
41
+ if (
42
+ typeof responseBody === Typeof.String &&
43
+ responseBody?.toString() === ""
44
+ ) {
45
+ responseBody = {};
46
+ }
47
+
48
+ storageMap = {
49
+ responseBody: responseBody,
50
+ responseHeaders: (data.dataToProcess as ProbeMonitorResponse)
51
+ .responseHeaders,
52
+ responseStatusCode: (data.dataToProcess as ProbeMonitorResponse)
53
+ .responseCode,
54
+ responseTimeInMs: (data.dataToProcess as ProbeMonitorResponse)
55
+ .responseTimeInMs,
56
+ isOnline: (data.dataToProcess as ProbeMonitorResponse).isOnline,
57
+ } as JSONObject;
58
+ }
59
+
60
+ if (data.monitorType === MonitorType.IncomingRequest) {
61
+ storageMap = {
62
+ requestBody: (data.dataToProcess as IncomingMonitorRequest)
63
+ .requestBody,
64
+ requestHeaders: (data.dataToProcess as IncomingMonitorRequest)
65
+ .requestHeaders,
66
+ } as JSONObject;
67
+ }
68
+ } catch (err) {
69
+ logger.error(err);
70
+ }
71
+
72
+ logger.debug(`Storage Map: ${JSON.stringify(storageMap, null, 2)}`);
73
+
74
+ return storageMap;
75
+ }
76
+
77
+ /**
78
+ * Replace {{var}} placeholders in the given string with values from the storage map.
79
+ */
80
+ public static processTemplateString(data: {
81
+ value: string | undefined;
82
+ storageMap: JSONObject;
83
+ }): string {
84
+ try {
85
+ const { value, storageMap } = data;
86
+
87
+ if (!value) {
88
+ return "";
89
+ }
90
+
91
+ let replaced: string = VMUtil.replaceValueInPlace(
92
+ storageMap,
93
+ value,
94
+ false,
95
+ );
96
+ replaced =
97
+ replaced !== undefined && replaced !== null ? `${replaced}` : "";
98
+
99
+ logger.debug(`Original Value: ${data.value}`);
100
+ logger.debug(`Replaced Value: ${replaced}`);
101
+
102
+ return replaced;
103
+ } catch (err) {
104
+ logger.error(err);
105
+ return data.value || "";
106
+ }
107
+ }
108
+ }
@@ -82,10 +82,19 @@ export default class VMUtil {
82
82
  }
83
83
 
84
84
  for (const variable of variablesInArgument) {
85
- const valueToReplaceInPlace: string = VMUtil.deepFind(
85
+ const foundValue: JSONValue = VMUtil.deepFind(
86
86
  storageMap as any,
87
87
  variable as any,
88
- ) as string;
88
+ );
89
+
90
+ let valueToReplaceInPlace: string;
91
+
92
+ // Properly serialize objects to JSON strings
93
+ if (typeof foundValue === "object" && foundValue !== null) {
94
+ valueToReplaceInPlace = JSON.stringify(foundValue, null, 2);
95
+ } else {
96
+ valueToReplaceInPlace = foundValue as string;
97
+ }
89
98
 
90
99
  if (valueToReplaceInPlaceCopy.trim() === "{{" + variable + "}}") {
91
100
  valueToReplaceInPlaceCopy = valueToReplaceInPlace;
@@ -4,6 +4,8 @@ import URL from "./API/URL";
4
4
  import Dictionary from "./Dictionary";
5
5
  import HTML from "./Html";
6
6
  import axios, { AxiosRequestConfig, AxiosResponse } from "axios";
7
+ import type { Agent as HttpAgent } from "http";
8
+ import type { Agent as HttpsAgent } from "https";
7
9
 
8
10
  export interface WebsiteResponse {
9
11
  url: URL;
@@ -22,6 +24,8 @@ export default class WebsiteRequest {
22
24
  timeout?: number | undefined;
23
25
  isHeadRequest?: boolean | undefined;
24
26
  doNotFollowRedirects?: boolean | undefined;
27
+ httpAgent?: HttpAgent | undefined; // per-request HTTP proxy agent
28
+ httpsAgent?: HttpsAgent | undefined; // per-request HTTPS proxy agent
25
29
  },
26
30
  ): Promise<WebsiteResponse> {
27
31
  const axiosOptions: AxiosRequestConfig = {
@@ -41,6 +45,13 @@ export default class WebsiteRequest {
41
45
  axiosOptions.maxRedirects = 0;
42
46
  }
43
47
 
48
+ if (options.httpAgent) {
49
+ (axiosOptions as AxiosRequestConfig).httpAgent = options.httpAgent;
50
+ }
51
+ if (options.httpsAgent) {
52
+ (axiosOptions as AxiosRequestConfig).httpsAgent = options.httpsAgent;
53
+ }
54
+
44
55
  // use axios to fetch an HTML page
45
56
  let response: AxiosResponse | null = null;
46
57
 
@@ -14,9 +14,14 @@ import ReactFlow, {
14
14
  Position,
15
15
  } from "reactflow";
16
16
  import "reactflow/dist/style.css";
17
- import type { ElkExtendedEdge, ElkNode } from "elkjs";
17
+ import type { ElkExtendedEdge, ElkNode, LayoutOptions } from "elkjs";
18
18
  import ELK from "elkjs/lib/elk.bundled.js";
19
19
 
20
+ // Minimal interface for the ELK layout engine we rely on.
21
+ interface ElkLayoutEngine {
22
+ layout: (graph: ElkNode) => Promise<ElkNode>;
23
+ }
24
+
20
25
  export interface ServiceNodeData {
21
26
  id: string;
22
27
  name: string;
@@ -96,7 +101,7 @@ const ServiceDependencyGraph: FunctionComponent<ServiceDependencyGraphProps> = (
96
101
  const [rfEdges, setRfEdges] = useState<Edge[]>([]);
97
102
 
98
103
  useEffect((): void => {
99
- const elk: any = new ELK();
104
+ const elk: ElkLayoutEngine = new ELK() as unknown as ElkLayoutEngine;
100
105
  // fixed node dimensions for layout (px)
101
106
  const NODE_WIDTH: number = 220;
102
107
  const NODE_HEIGHT: number = 56;
@@ -123,7 +128,7 @@ const ServiceDependencyGraph: FunctionComponent<ServiceDependencyGraphProps> = (
123
128
  "elk.layered.spacing.nodeNodeBetweenLayers": "120",
124
129
  "elk.spacing.nodeNode": "60",
125
130
  "elk.edgeRouting": "POLYLINE",
126
- },
131
+ } as LayoutOptions,
127
132
  children: sortedServices.map((svc: ServiceNodeData): ElkNode => {
128
133
  return {
129
134
  id: svc.id,
@@ -142,9 +147,9 @@ const ServiceDependencyGraph: FunctionComponent<ServiceDependencyGraphProps> = (
142
147
 
143
148
  const layout: () => Promise<void> = async (): Promise<void> => {
144
149
  try {
145
- const res: any = await elk.layout(elkGraph as any);
150
+ const res: ElkNode = (await elk.layout(elkGraph)) as ElkNode; // casting to bundled ElkNode shape
146
151
  const placedNodes: Node[] = (res.children || []).map(
147
- (child: any): Node => {
152
+ (child: ElkNode): Node => {
148
153
  const svc: ServiceNodeData | undefined = sortedServices.find(
149
154
  (s: ServiceNodeData): boolean => {
150
155
  return s.id === child.id;
@@ -64,7 +64,8 @@ const Input: FunctionComponent<ComponentProps> = (
64
64
 
65
65
  const [value, setValue] = useState<string | Date>("");
66
66
  const [displayValue, setDisplayValue] = useState<string>("");
67
- const ref: any = useRef<any>(null);
67
+ const ref: React.MutableRefObject<HTMLInputElement | null> =
68
+ useRef<HTMLInputElement | null>(null);
68
69
 
69
70
  useEffect(() => {
70
71
  if (
@@ -120,9 +121,9 @@ const Input: FunctionComponent<ComponentProps> = (
120
121
  }, [value]);
121
122
 
122
123
  useEffect(() => {
123
- const input: any = ref.current;
124
+ const input: HTMLInputElement | null = ref.current;
124
125
  if (input) {
125
- (input as any).value = displayValue;
126
+ input.value = displayValue;
126
127
  }
127
128
  }, [ref, displayValue]);
128
129
 
@@ -195,7 +196,7 @@ const Input: FunctionComponent<ComponentProps> = (
195
196
  tabIndex={props.tabIndex}
196
197
  onKeyDown={
197
198
  props.onEnterPress
198
- ? (event: any) => {
199
+ ? (event: React.KeyboardEvent<HTMLInputElement>) => {
199
200
  if (event.key === "Enter") {
200
201
  props.onEnterPress?.();
201
202
  }
@@ -27,7 +27,9 @@ export interface ComponentProps {
27
27
  const ArgumentsForm: FunctionComponent<ComponentProps> = (
28
28
  props: ComponentProps,
29
29
  ): ReactElement => {
30
- const formRef: any = useRef<FormProps<FormValues<JSONObject>>>(null);
30
+ const formRef: React.MutableRefObject<FormProps<
31
+ FormValues<JSONObject>
32
+ > | null> = useRef<FormProps<FormValues<JSONObject>> | null>(null);
31
33
  const [component, setComponent] = useState<NodeDataProp>(props.component);
32
34
  const [showVariableModal, setShowVariableModal] = useState<boolean>(false);
33
35
  const [showComponentPickerModal, setShowComponentPickerModal] =
@@ -143,7 +145,7 @@ const ArgumentsForm: FunctionComponent<ComponentProps> = (
143
145
  }}
144
146
  onSave={(variableId: string) => {
145
147
  setShowVariableModal(false);
146
- formRef.current.setFieldValue(
148
+ formRef.current?.setFieldValue(
147
149
  selectedArgId,
148
150
  (component.arguments && component.arguments[selectedArgId]
149
151
  ? component.arguments[selectedArgId]
@@ -161,7 +163,7 @@ const ArgumentsForm: FunctionComponent<ComponentProps> = (
161
163
  }}
162
164
  onSave={(returnValuePath: string) => {
163
165
  setShowComponentPickerModal(false);
164
- formRef.current.setFieldValue(
166
+ formRef.current?.setFieldValue(
165
167
  selectedArgId,
166
168
  (component.arguments && component.arguments[selectedArgId]
167
169
  ? component.arguments[selectedArgId]
@@ -1,7 +1,6 @@
1
1
  import { DropdownOption } from "../Dropdown/Dropdown";
2
2
  import FormFieldSchemaType from "../Forms/Types/FormFieldSchemaType";
3
3
  import IconProp from "../../../Types/Icon/IconProp";
4
- import Typeof from "../../../Types/Typeof";
5
4
  import ComponentMetadata, {
6
5
  ComponentCategory,
7
6
  ComponentInputType,
@@ -44,7 +43,7 @@ export const loadComponentsAndCategories: LoadComponentsAndCategoriesFunction =
44
43
 
45
44
  type ComponentInputTypeToFormFieldTypeFunction = (
46
45
  componentInputType: ComponentInputType,
47
- argValue: any,
46
+ argValue: unknown,
48
47
  ) => {
49
48
  fieldType: FormFieldSchemaType;
50
49
  dropdownOptions?: Array<DropdownOption> | undefined;
@@ -53,7 +52,7 @@ type ComponentInputTypeToFormFieldTypeFunction = (
53
52
  export const componentInputTypeToFormFieldType: ComponentInputTypeToFormFieldTypeFunction =
54
53
  (
55
54
  componentInputType: ComponentInputType,
56
- argValue: any,
55
+ argValue: unknown,
57
56
  ): {
58
57
  fieldType: FormFieldSchemaType;
59
58
  dropdownOptions?: Array<DropdownOption> | undefined;
@@ -122,11 +121,7 @@ export const componentInputTypeToFormFieldType: ComponentInputTypeToFormFieldTyp
122
121
 
123
122
  // Second priority.
124
123
 
125
- if (
126
- argValue &&
127
- typeof argValue === Typeof.String &&
128
- argValue.toString().includes("{{")
129
- ) {
124
+ if (typeof argValue === "string" && argValue.includes("{{")) {
130
125
  return {
131
126
  fieldType: FormFieldSchemaType.Text,
132
127
  dropdownOptions: [],
package/Utils/API.ts CHANGED
@@ -13,12 +13,17 @@ import APIException from "../Types/Exception/ApiException";
13
13
  import { JSONArray, JSONObject } from "../Types/JSON";
14
14
  import axios, { AxiosError, AxiosRequestConfig, AxiosResponse } from "axios";
15
15
  import Sleep from "../Types/Sleep";
16
+ import type { Agent as HttpAgent } from "http";
17
+ import type { Agent as HttpsAgent } from "https";
16
18
 
17
19
  export interface RequestOptions {
18
20
  retries?: number | undefined;
19
21
  exponentialBackoff?: boolean | undefined;
20
22
  timeout?: number | undefined;
21
23
  doNotFollowRedirects?: boolean | undefined;
24
+ // Per-request proxy agent support (Probe supplies these instead of mutating global axios defaults)
25
+ httpAgent?: HttpAgent | undefined;
26
+ httpsAgent?: HttpsAgent | undefined;
22
27
  }
23
28
 
24
29
  export default class API {
@@ -400,6 +405,15 @@ export default class API {
400
405
  axiosOptions.maxRedirects = 0;
401
406
  }
402
407
 
408
+ // Attach proxy agents per request if provided (avoids global side-effects)
409
+ if (options?.httpAgent) {
410
+ (axiosOptions as AxiosRequestConfig).httpAgent = options.httpAgent;
411
+ }
412
+ if (options?.httpsAgent) {
413
+ (axiosOptions as AxiosRequestConfig).httpsAgent =
414
+ options.httpsAgent;
415
+ }
416
+
403
417
  result = await axios(axiosOptions);
404
418
 
405
419
  break;
@@ -444,7 +444,7 @@ OnCallDutyPolicyEscalationRule = __decorate([
444
444
  Permission.EditProjectOnCallDutyPolicyEscalationRule,
445
445
  ],
446
446
  }),
447
- CrudApiEndpoint(new Route("/on-call-duty-policy-esclation-rule")),
447
+ CrudApiEndpoint(new Route("/on-call-duty-policy-escalation-rule")),
448
448
  Entity({
449
449
  name: "OnCallDutyPolicyEscalationRule",
450
450
  }),