@oneuptime/common 14.0.6 → 14.0.7

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 (127) hide show
  1. package/Models/DatabaseModels/InventoryItem.ts +23 -12
  2. package/Server/Infrastructure/Postgres/SchemaMigrations/1795200000000-AddInventoryItemProjectEntityKeyIndex.ts +217 -0
  3. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +2 -0
  4. package/Server/Services/AlertService.ts +32 -36
  5. package/Server/Services/IncidentAlertService.ts +609 -2
  6. package/Server/Services/IncidentService.ts +134 -44
  7. package/Server/Services/InventoryItemService.ts +38 -0
  8. package/Server/Services/IoTDeviceCredentialService.ts +13 -4
  9. package/Server/Services/ScheduledMaintenanceService.ts +50 -46
  10. package/Server/Services/UserNotificationRuleService.ts +55 -53
  11. package/Server/Services/WorkspaceNotificationSummaryService.ts +38 -20
  12. package/Server/Utils/AffectedResources/LinkedAffectedResources.ts +576 -0
  13. package/Server/Utils/Alert/AlertStateChangeAuthorization.ts +129 -0
  14. package/Server/Utils/Inventory/InventoryOverviewAggregation.ts +111 -0
  15. package/Server/Utils/Response.ts +31 -0
  16. package/Server/Utils/Topology/TopologyConcurrencyLimiter.ts +229 -0
  17. package/Server/Utils/Topology/TopologyQueries.ts +1350 -0
  18. package/Server/Utils/Topology/TopologyRequest.ts +463 -0
  19. package/Server/Utils/Topology/TopologyResponseCache.ts +183 -0
  20. package/Server/Utils/Topology/TopologySql.ts +1024 -0
  21. package/Tests/App/Dashboard/AcknowledgeAlertsOnDeclare.test.ts +369 -0
  22. package/Tests/App/Dashboard/AffectedResourcesSlo.test.tsx +1 -1
  23. package/Tests/App/Dashboard/AffectedResourcesSummaryStep.test.tsx +510 -123
  24. package/Tests/App/Dashboard/AlertsTableAffectedResources.test.tsx +490 -0
  25. package/Tests/App/Dashboard/ChangeAlertStateDeclareIncident.test.tsx +886 -0
  26. package/Tests/App/Dashboard/CreateReviewStepRoleSummary.test.tsx +1250 -0
  27. package/Tests/App/Dashboard/CreateReviewStepSelectionSummary.test.tsx +738 -0
  28. package/Tests/App/Dashboard/DeclareIncidentFromAlert.test.ts +417 -0
  29. package/Tests/App/Dashboard/EntityDetailPanel.test.tsx +1948 -229
  30. package/Tests/App/Dashboard/EntityDetailPanelLifecycle.test.tsx +493 -0
  31. package/Tests/App/Dashboard/EntityDetailPanelNavigation.test.tsx +439 -0
  32. package/Tests/App/Dashboard/EventOverviewPages.test.tsx +292 -1
  33. package/Tests/App/Dashboard/EventStatusPanel.test.tsx +798 -2
  34. package/Tests/App/Dashboard/FetchStateAndSeverityElements.test.tsx +669 -0
  35. package/Tests/App/Dashboard/FetchUsers.test.tsx +230 -0
  36. package/Tests/App/Dashboard/IncidentCreateAcknowledgeAlerts.test.tsx +1611 -0
  37. package/Tests/App/Dashboard/InfrastructureExplorer.test.tsx +1365 -57
  38. package/Tests/App/Dashboard/InfrastructureGraph.test.tsx +964 -23
  39. package/Tests/App/Dashboard/InventoryRelationships.test.tsx +885 -0
  40. package/Tests/App/Dashboard/ServiceMapDatabaseLink.test.tsx +201 -15
  41. package/Tests/App/Dashboard/ServiceMapGraph.test.tsx +508 -36
  42. package/Tests/App/Dashboard/TopologyDataLifecycle.test.tsx +583 -0
  43. package/Tests/App/Dashboard/TopologyDataLoading.test.tsx +982 -218
  44. package/Tests/App/Dashboard/TopologyPageNavigation.test.tsx +818 -114
  45. package/Tests/Server/Infrastructure/Postgres/RenameInventoryItemMigration.test.ts +90 -21
  46. package/Tests/Server/Services/DomainService.test.ts +525 -0
  47. package/Tests/Server/Services/IncidentAlertAcknowledgeOnDeclare.test.ts +2630 -0
  48. package/Tests/Server/Services/IncidentAlertPostgres.test.ts +1625 -1
  49. package/Tests/Server/Services/IncidentDeclareAcknowledgeAlerts.test.ts +2189 -0
  50. package/Tests/Server/Services/InventoryItemServiceOverviewCounts.test.ts +345 -0
  51. package/Tests/Server/Services/InventoryOverviewPostgres.test.ts +254 -0
  52. package/Tests/Server/Services/IoTDeviceCredentialService.test.ts +819 -0
  53. package/Tests/Server/Services/LinkedAffectedResourcesCreatedFeed.test.ts +420 -0
  54. package/Tests/Server/Services/SloAffectedResourceCreatedFeed.test.ts +92 -36
  55. package/Tests/Server/Utils/AffectedResources/LinkedAffectedResources.test.ts +858 -0
  56. package/Tests/Server/Utils/Alert/AlertStateChangeAuthorization.test.ts +1172 -0
  57. package/Tests/Server/Utils/Topology/InventoryItemEntityKeyIndexMigration.test.ts +386 -0
  58. package/Tests/Server/Utils/Topology/InventoryItemEntityKeyIndexMigrationPostgres.test.ts +430 -0
  59. package/Tests/Server/Utils/Topology/TopologyActivityParityPostgres.test.ts +279 -0
  60. package/Tests/Server/Utils/Topology/TopologyConcurrencyLimiter.test.ts +534 -0
  61. package/Tests/Server/Utils/Topology/TopologyEstateGenerator.ts +624 -0
  62. package/Tests/Server/Utils/Topology/TopologyJsonResponse.test.ts +90 -0
  63. package/Tests/Server/Utils/Topology/TopologyQueries.test.ts +1634 -0
  64. package/Tests/Server/Utils/Topology/TopologyQueriesDifferentialPostgres.test.ts +683 -0
  65. package/Tests/Server/Utils/Topology/TopologyQueriesPostgres.test.ts +2624 -0
  66. package/Tests/Server/Utils/Topology/TopologyReference.ts +1018 -0
  67. package/Tests/Server/Utils/Topology/TopologyRequest.test.ts +643 -0
  68. package/Tests/Server/Utils/Topology/TopologyResponseCache.test.ts +305 -0
  69. package/Tests/Server/Utils/Topology/TopologySql.test.ts +973 -0
  70. package/Tests/Types/Topology/TopologyTypeRules.test.ts +176 -0
  71. package/Tests/Utils/Incident/IncidentFromAlerts.test.ts +302 -0
  72. package/Types/Incident/IncidentAlertLink.ts +19 -0
  73. package/Types/Telemetry/InventoryLiveness.ts +26 -0
  74. package/Types/Topology/TopologyApi.ts +428 -0
  75. package/Types/Topology/TopologyTypeRules.ts +191 -0
  76. package/Utils/Incident/IncidentFromAlerts.ts +78 -0
  77. package/build/dist/Models/DatabaseModels/InventoryItem.js +20 -11
  78. package/build/dist/Models/DatabaseModels/InventoryItem.js.map +1 -1
  79. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795200000000-AddInventoryItemProjectEntityKeyIndex.js +165 -0
  80. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795200000000-AddInventoryItemProjectEntityKeyIndex.js.map +1 -0
  81. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +2 -0
  82. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  83. package/build/dist/Server/Services/AlertService.js +21 -33
  84. package/build/dist/Server/Services/AlertService.js.map +1 -1
  85. package/build/dist/Server/Services/IncidentAlertService.js +457 -3
  86. package/build/dist/Server/Services/IncidentAlertService.js.map +1 -1
  87. package/build/dist/Server/Services/IncidentService.js +96 -42
  88. package/build/dist/Server/Services/IncidentService.js.map +1 -1
  89. package/build/dist/Server/Services/InventoryItemService.js +31 -0
  90. package/build/dist/Server/Services/InventoryItemService.js.map +1 -1
  91. package/build/dist/Server/Services/IoTDeviceCredentialService.js +12 -5
  92. package/build/dist/Server/Services/IoTDeviceCredentialService.js.map +1 -1
  93. package/build/dist/Server/Services/ScheduledMaintenanceService.js +37 -40
  94. package/build/dist/Server/Services/ScheduledMaintenanceService.js.map +1 -1
  95. package/build/dist/Server/Services/UserNotificationRuleService.js +55 -51
  96. package/build/dist/Server/Services/UserNotificationRuleService.js.map +1 -1
  97. package/build/dist/Server/Services/WorkspaceNotificationSummaryService.js +42 -25
  98. package/build/dist/Server/Services/WorkspaceNotificationSummaryService.js.map +1 -1
  99. package/build/dist/Server/Utils/AffectedResources/LinkedAffectedResources.js +405 -0
  100. package/build/dist/Server/Utils/AffectedResources/LinkedAffectedResources.js.map +1 -0
  101. package/build/dist/Server/Utils/Alert/AlertStateChangeAuthorization.js +112 -0
  102. package/build/dist/Server/Utils/Alert/AlertStateChangeAuthorization.js.map +1 -0
  103. package/build/dist/Server/Utils/Inventory/InventoryOverviewAggregation.js +81 -0
  104. package/build/dist/Server/Utils/Inventory/InventoryOverviewAggregation.js.map +1 -0
  105. package/build/dist/Server/Utils/Response.js +30 -0
  106. package/build/dist/Server/Utils/Response.js.map +1 -1
  107. package/build/dist/Server/Utils/Topology/TopologyConcurrencyLimiter.js +178 -0
  108. package/build/dist/Server/Utils/Topology/TopologyConcurrencyLimiter.js.map +1 -0
  109. package/build/dist/Server/Utils/Topology/TopologyQueries.js +884 -0
  110. package/build/dist/Server/Utils/Topology/TopologyQueries.js.map +1 -0
  111. package/build/dist/Server/Utils/Topology/TopologyRequest.js +275 -0
  112. package/build/dist/Server/Utils/Topology/TopologyRequest.js.map +1 -0
  113. package/build/dist/Server/Utils/Topology/TopologyResponseCache.js +146 -0
  114. package/build/dist/Server/Utils/Topology/TopologyResponseCache.js.map +1 -0
  115. package/build/dist/Server/Utils/Topology/TopologySql.js +688 -0
  116. package/build/dist/Server/Utils/Topology/TopologySql.js.map +1 -0
  117. package/build/dist/Types/Incident/IncidentAlertLink.js +17 -0
  118. package/build/dist/Types/Incident/IncidentAlertLink.js.map +1 -1
  119. package/build/dist/Types/Telemetry/InventoryLiveness.js +23 -0
  120. package/build/dist/Types/Telemetry/InventoryLiveness.js.map +1 -1
  121. package/build/dist/Types/Topology/TopologyApi.js +55 -0
  122. package/build/dist/Types/Topology/TopologyApi.js.map +1 -0
  123. package/build/dist/Types/Topology/TopologyTypeRules.js +165 -0
  124. package/build/dist/Types/Topology/TopologyTypeRules.js.map +1 -0
  125. package/build/dist/Utils/Incident/IncidentFromAlerts.js +38 -0
  126. package/build/dist/Utils/Incident/IncidentFromAlerts.js.map +1 -1
  127. package/package.json +1 -1
@@ -0,0 +1,884 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ import { PostgresStatementTimeoutMs } from "../../EnvironmentConfig";
11
+ import InventoryItemService from "../../Services/InventoryItemService";
12
+ import CaptureSpan from "../Telemetry/CaptureSpan";
13
+ import EntityType from "../../../Types/Telemetry/EntityType";
14
+ import { TOPOLOGY_API_FORMAT_VERSION, TOPOLOGY_CONNECTION_SECTIONS, TopologyApiLimits, } from "../../../Types/Topology/TopologyApi";
15
+ import { isFlatInfrastructureType, isTopologyInfrastructureType, } from "../../../Types/Topology/TopologyTypeRules";
16
+ import { rowsForSection, } from "./TopologyRequest";
17
+ import { collectionPageStatement, collectionSearchStatement, entitySectionsStatement, entityStatement, infrastructureNodesStatement, infrastructureTypeCountsStatement, itemsByKeysStatement, placementsStatement, duplicateKeysStatement, projectTypesStatement, serviceMapDependenciesStatement, serviceMapEntitiesStatement, servicesStatement, } from "./TopologySql";
18
+ /*
19
+ * The Topology API's reads: Postgres reduces the inventory graph and each
20
+ * view receives only the rows it draws, computed over the whole inventory.
21
+ * The SQL lives in TopologySql; this module runs it and shapes the contract
22
+ * JSON (Common/Types/Topology/TopologyApi.ts).
23
+ *
24
+ * Every request reads one consistent snapshot on one connection: a READ ONLY
25
+ * REPEATABLE READ transaction whose statements run one after another, so the
26
+ * service list, the relationships and the counts a response is built from can
27
+ * never disagree with each other. Parallel query is switched off for the
28
+ * transaction: the docker-compose Postgres has a 64 MB /dev/shm, and parallel
29
+ * hash joins over a large project fail there under concurrent load ("could not
30
+ * resize shared memory segment"); the heaviest statement here is a single pass
31
+ * over one project and does not need the workers. JIT is off too: it spends
32
+ * 100-200 ms compiling each large statement and wins nothing back on reads of
33
+ * this size.
34
+ *
35
+ * The statement timeout is set on the transaction as well, not left to the
36
+ * connection's startup parameter: PgBouncer drops that parameter, and behind
37
+ * it nothing but node-postgres's client-side query_timeout would remain — which
38
+ * abandons a query without cancelling it, leaving one of the heaviest reads in
39
+ * the app running on the server (holding its snapshot) after the user was
40
+ * already told it failed. The configured value stays below that client
41
+ * timeout, so Postgres cancels first.
42
+ */
43
+ /*
44
+ * `SET LOCAL statement_timeout = <ms>` for the configured statement timeout,
45
+ * or null when none is configured (0, or not a number): then the connection's
46
+ * own setting applies, as for every other query.
47
+ */
48
+ export function statementTimeoutSql(timeoutMs) {
49
+ if (!Number.isFinite(timeoutMs) || timeoutMs < 1) {
50
+ return null;
51
+ }
52
+ return `SET LOCAL statement_timeout = ${Math.floor(timeoutMs)}`;
53
+ }
54
+ // ---------------------------------------------------------------- decoding
55
+ function readString(row, key) {
56
+ const value = row[key];
57
+ return typeof value === "string" ? value : String(value !== null && value !== void 0 ? value : "");
58
+ }
59
+ function readNullableString(row, key) {
60
+ const value = row[key];
61
+ if (value === null || value === undefined) {
62
+ return null;
63
+ }
64
+ return typeof value === "string" ? value : String(value);
65
+ }
66
+ function readNullableNumber(row, key) {
67
+ const value = row[key];
68
+ if (value === null || value === undefined || value === "") {
69
+ return null;
70
+ }
71
+ const parsed = typeof value === "number" ? value : Number(value);
72
+ return Number.isFinite(parsed) ? parsed : null;
73
+ }
74
+ function readNumber(row, key) {
75
+ var _a;
76
+ return (_a = readNullableNumber(row, key)) !== null && _a !== void 0 ? _a : 0;
77
+ }
78
+ function readBoolean(row, key) {
79
+ const value = row[key];
80
+ return value === true || value === "t" || value === "true";
81
+ }
82
+ function readJsonObject(row, key) {
83
+ const value = row[key];
84
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
85
+ return null;
86
+ }
87
+ return value;
88
+ }
89
+ /* A bag of string attributes, or undefined when it holds none. */
90
+ function readStringBag(row, key) {
91
+ const bag = readJsonObject(row, key);
92
+ if (!bag) {
93
+ return undefined;
94
+ }
95
+ const strings = {};
96
+ let count = 0;
97
+ for (const attribute of Object.keys(bag).sort()) {
98
+ const value = bag[attribute];
99
+ if (typeof value === "string") {
100
+ strings[attribute] = value;
101
+ count++;
102
+ }
103
+ }
104
+ return count > 0 ? strings : undefined;
105
+ }
106
+ function toLeanEntity(row) {
107
+ var _a;
108
+ return {
109
+ key: readString(row, "key"),
110
+ type: readString(row, "type"),
111
+ name: readNullableString(row, "name"),
112
+ /* The column is NOT NULL; "" reads as "no source" on both sides. */
113
+ source: (_a = readNullableString(row, "source")) !== null && _a !== void 0 ? _a : "",
114
+ lastSeenAt: readNullableNumber(row, "lastSeenAt"),
115
+ };
116
+ }
117
+ function toServiceMapEntity(row) {
118
+ const entity = toLeanEntity(row);
119
+ const descriptive = readStringBag(row, "descriptiveAttributes");
120
+ const identifying = readStringBag(row, "identifyingAttributes");
121
+ if (descriptive) {
122
+ entity.descriptiveAttributes = descriptive;
123
+ }
124
+ if (identifying) {
125
+ entity.identifyingAttributes = identifying;
126
+ }
127
+ return entity;
128
+ }
129
+ function toConnectionRow(value) {
130
+ const row = (value || {});
131
+ const connection = {
132
+ relationshipType: readString(row, "relationshipType"),
133
+ direction: row["direction"] === "in" ? "in" : "out",
134
+ otherKey: readString(row, "otherKey"),
135
+ otherKnown: readBoolean(row, "otherKnown"),
136
+ otherName: readNullableString(row, "otherName"),
137
+ otherType: readNullableString(row, "otherType"),
138
+ callCount: readNullableNumber(row, "callCount"),
139
+ errorCount: readNullableNumber(row, "errorCount"),
140
+ avgDurationMs: readNullableNumber(row, "avgDurationMs"),
141
+ lastSeenAt: readNullableNumber(row, "lastSeenAt"),
142
+ };
143
+ // Only the all-time statement selects it; the drawer's rows stay as they were.
144
+ if ("otherId" in row) {
145
+ connection.otherId = readNullableString(row, "otherId");
146
+ }
147
+ return connection;
148
+ }
149
+ function compareCodeUnits(left, right) {
150
+ if (left < right) {
151
+ return -1;
152
+ }
153
+ return left > right ? 1 : 0;
154
+ }
155
+ function emptySections() {
156
+ return {
157
+ calls: { total: 0, unknownTotal: 0, rows: [], nextOffset: null },
158
+ calledBy: { total: 0, unknownTotal: 0, rows: [], nextOffset: null },
159
+ runsOn: { total: 0, unknownTotal: 0, rows: [], nextOffset: null },
160
+ related: { total: 0, unknownTotal: 0, rows: [], nextOffset: null },
161
+ };
162
+ }
163
+ function isSection(value) {
164
+ return TOPOLOGY_CONNECTION_SECTIONS.some((section) => {
165
+ return section === value;
166
+ });
167
+ }
168
+ /*
169
+ * Decodes entitySectionsStatement's single row. `offset` is where the rows of
170
+ * each section start (0 for the drawer's first view).
171
+ */
172
+ function decodeSections(rows, offset) {
173
+ const sections = emptySections();
174
+ const row = rows[0] || {};
175
+ const totals = row["sections"];
176
+ for (const total of Array.isArray(totals) ? totals : []) {
177
+ const entry = (total || {});
178
+ const section = entry["section"];
179
+ if (isSection(section)) {
180
+ sections[section].total = readNumber(entry, "total");
181
+ sections[section].unknownTotal = readNumber(entry, "unknownTotal");
182
+ }
183
+ }
184
+ const connectionRows = row["rows"];
185
+ for (const connection of Array.isArray(connectionRows)
186
+ ? connectionRows
187
+ : []) {
188
+ const section = (connection || {})["section"];
189
+ if (isSection(section)) {
190
+ sections[section].rows.push(toConnectionRow(connection));
191
+ }
192
+ }
193
+ for (const section of TOPOLOGY_CONNECTION_SECTIONS) {
194
+ const reached = offset + sections[section].rows.length;
195
+ sections[section].nextOffset =
196
+ sections[section].rows.length > 0 && reached < sections[section].total
197
+ ? reached
198
+ : null;
199
+ }
200
+ return {
201
+ sections,
202
+ isScanLimited: readNumber(row, "scanned") > TopologyApiLimits.EntityConnectionScanLimit,
203
+ };
204
+ }
205
+ // ------------------------------------------------------------------ queries
206
+ export default class TopologyQueries {
207
+ /*
208
+ * Runs `work` on one pooled connection inside a READ ONLY REPEATABLE READ
209
+ * transaction with a server-side statement timeout. TypeORM commits on
210
+ * success, rolls back on failure and always releases the connection.
211
+ */
212
+ static async inReadOnlySnapshot(work) {
213
+ const manager = InventoryItemService.getRepository().manager;
214
+ return await manager.transaction("REPEATABLE READ", async (transaction) => {
215
+ await transaction.query("SET TRANSACTION READ ONLY");
216
+ const statementTimeout = statementTimeoutSql(PostgresStatementTimeoutMs);
217
+ if (statementTimeout) {
218
+ await transaction.query(statementTimeout);
219
+ }
220
+ await transaction.query("SET LOCAL max_parallel_workers_per_gather = 0");
221
+ await transaction.query("SET LOCAL jit = off");
222
+ return await work({
223
+ query: async (statement) => {
224
+ return (await transaction.query(statement.sql, statement.params));
225
+ },
226
+ });
227
+ });
228
+ }
229
+ static envelope(rangeStart) {
230
+ return {
231
+ formatVersion: TOPOLOGY_API_FORMAT_VERSION,
232
+ rangeStart: rangeStart.toISOString(),
233
+ generatedAt: new Date().toISOString(),
234
+ };
235
+ }
236
+ /* The all-time responses have no range start to echo. */
237
+ static allTimeEnvelope() {
238
+ return {
239
+ formatVersion: TOPOLOGY_API_FORMAT_VERSION,
240
+ generatedAt: new Date().toISOString(),
241
+ };
242
+ }
243
+ /* The project's distinct entity types (see projectTypesStatement). */
244
+ static async readProjectTypes(runner, projectId) {
245
+ const rows = await runner.query(projectTypesStatement({ projectId }));
246
+ return rows
247
+ .map((row) => {
248
+ return readString(row, "entityType");
249
+ })
250
+ .filter((type) => {
251
+ return type.length > 0;
252
+ });
253
+ }
254
+ /*
255
+ * The project's types plus the keys more than one live row carries, read
256
+ * once per request so the statements that list items apply the winner rule
257
+ * only where it can matter (see winnerSql).
258
+ */
259
+ static async readWinnerScope(runner, projectId, projectTypes) {
260
+ const rows = await runner.query(duplicateKeysStatement({ projectId }));
261
+ return {
262
+ projectTypes,
263
+ duplicateKeys: rows
264
+ .map((row) => {
265
+ return readString(row, "key");
266
+ })
267
+ .sort(compareCodeUnits),
268
+ };
269
+ }
270
+ /*
271
+ * Rows up to `cap`, or — when there are more — the first `cap` and the
272
+ * exact total from `count`. The row statement asks for cap + 1 so the
273
+ * common case (under the cap) costs no count at all.
274
+ */
275
+ static async readCapped(runner, rows, count, cap) {
276
+ const found = await runner.query(rows(cap + 1));
277
+ if (found.length <= cap) {
278
+ return { rows: found, total: found.length, count: {} };
279
+ }
280
+ const counted = await runner.query(count());
281
+ const countRow = counted[0] || {};
282
+ return {
283
+ rows: found.slice(0, cap),
284
+ total: Math.max(readNumber(countRow, "total"), cap),
285
+ count: countRow,
286
+ };
287
+ }
288
+ /*
289
+ * Per (service, target type): the distinct resources each service runs on
290
+ * (in-range runs-on / hosted-on onto live items of any type), and how many
291
+ * of those reported in range. Placements and targets are read separately so
292
+ * the target lookup is by an array of keys the planner can size.
293
+ */
294
+ static async readRunsOnCounts(runner, data) {
295
+ const placementRows = await runner.query(placementsStatement({
296
+ projectId: data.projectId,
297
+ rangeStart: data.rangeStart,
298
+ serviceKeys: data.serviceKeys,
299
+ }));
300
+ if (placementRows.length === 0) {
301
+ return [];
302
+ }
303
+ const targetKeys = Array.from(new Set(placementRows.map((row) => {
304
+ return readString(row, "target");
305
+ }))).sort(compareCodeUnits);
306
+ const targetRows = await runner.query(itemsByKeysStatement({
307
+ projectId: data.projectId,
308
+ rangeStart: data.rangeStart,
309
+ winner: data.winner,
310
+ keys: targetKeys,
311
+ }));
312
+ const targetByKey = new Map();
313
+ for (const row of targetRows) {
314
+ targetByKey.set(readString(row, "key"), {
315
+ type: readString(row, "type"),
316
+ active: readBoolean(row, "active"),
317
+ });
318
+ }
319
+ const counts = new Map();
320
+ for (const row of placementRows) {
321
+ const service = readString(row, "service");
322
+ const target = targetByKey.get(readString(row, "target"));
323
+ if (!target) {
324
+ continue;
325
+ }
326
+ const countKey = `${service}\u0000${target.type}`;
327
+ let count = counts.get(countKey);
328
+ if (!count) {
329
+ count = { service, type: target.type, active: 0, total: 0 };
330
+ counts.set(countKey, count);
331
+ }
332
+ /* Placements are distinct (service, target) pairs: one per target. */
333
+ count.total++;
334
+ if (target.active) {
335
+ count.active++;
336
+ }
337
+ }
338
+ return Array.from(counts.values()).sort((left, right) => {
339
+ return (compareCodeUnits(left.service, right.service) ||
340
+ compareCodeUnits(left.type, right.type));
341
+ });
342
+ }
343
+ /*
344
+ * Service Map: every live service, everything services call, the in-range
345
+ * calls between them, and per (service, target type) what the services run
346
+ * on. No pods or other infrastructure rows.
347
+ */
348
+ static async getServiceMap(request) {
349
+ const projectId = request.projectId.toString();
350
+ const rangeStart = request.rangeStart.toISOString();
351
+ const entityCap = TopologyApiLimits.MaxServiceMapEntities;
352
+ const dependencyCap = TopologyApiLimits.MaxServiceMapDependencies;
353
+ return await TopologyQueries.inReadOnlySnapshot(async (runner) => {
354
+ const response = Object.assign(Object.assign({}, TopologyQueries.envelope(request.rangeStart)), { entities: [], dependencies: [], runsOn: [], entityTruncation: null, dependencyTruncation: null });
355
+ const projectTypes = await TopologyQueries.readProjectTypes(runner, projectId);
356
+ if (!projectTypes.includes(EntityType.Service)) {
357
+ return response;
358
+ }
359
+ const winner = await TopologyQueries.readWinnerScope(runner, projectId, projectTypes);
360
+ const services = await TopologyQueries.readCapped(runner, (limit) => {
361
+ return serviceMapEntitiesStatement({
362
+ projectId,
363
+ winner,
364
+ mode: "rows",
365
+ limit,
366
+ });
367
+ }, () => {
368
+ return serviceMapEntitiesStatement({
369
+ projectId,
370
+ winner,
371
+ mode: "count",
372
+ limit: 0,
373
+ });
374
+ }, entityCap);
375
+ const serviceKeys = services.rows.map((row) => {
376
+ return readString(row, "key");
377
+ });
378
+ if (serviceKeys.length === 0) {
379
+ return response;
380
+ }
381
+ const dependencies = await TopologyQueries.readCapped(runner, (limit) => {
382
+ return serviceMapDependenciesStatement({
383
+ projectId,
384
+ rangeStart,
385
+ serviceKeys,
386
+ mode: "rows",
387
+ limit,
388
+ });
389
+ }, () => {
390
+ return serviceMapDependenciesStatement({
391
+ projectId,
392
+ rangeStart,
393
+ serviceKeys,
394
+ mode: "count",
395
+ limit: 0,
396
+ });
397
+ }, dependencyCap);
398
+ response.dependencies = dependencies.rows.map((row) => {
399
+ return {
400
+ from: readString(row, "from"),
401
+ to: readString(row, "to"),
402
+ callCount: readNullableNumber(row, "callCount"),
403
+ errorCount: readNullableNumber(row, "errorCount"),
404
+ avgDurationMs: readNullableNumber(row, "avgDurationMs"),
405
+ };
406
+ });
407
+ if (dependencies.total > dependencies.rows.length) {
408
+ response.dependencyTruncation = {
409
+ shown: dependencies.rows.length,
410
+ total: dependencies.total,
411
+ };
412
+ }
413
+ /*
414
+ * Callees: the non-service items the shipped calls point at (a callee
415
+ * that is a service is already in the list above).
416
+ */
417
+ const serviceKeySet = new Set(serviceKeys);
418
+ const calleeKeys = Array.from(new Set(response.dependencies.map((dependency) => {
419
+ return dependency.to;
420
+ })))
421
+ .filter((key) => {
422
+ return !serviceKeySet.has(key);
423
+ })
424
+ .sort(compareCodeUnits);
425
+ let callees = {
426
+ rows: [],
427
+ total: 0,
428
+ };
429
+ if (calleeKeys.length > 0) {
430
+ callees = await TopologyQueries.readCapped(runner, (limit) => {
431
+ return serviceMapEntitiesStatement({
432
+ projectId,
433
+ winner,
434
+ keys: calleeKeys,
435
+ mode: "rows",
436
+ limit,
437
+ });
438
+ }, () => {
439
+ return serviceMapEntitiesStatement({
440
+ projectId,
441
+ winner,
442
+ keys: calleeKeys,
443
+ mode: "count",
444
+ limit: 0,
445
+ });
446
+ }, entityCap - services.rows.length);
447
+ }
448
+ response.entities = [...services.rows, ...callees.rows].map(toServiceMapEntity);
449
+ const entityTotal = services.total + callees.total;
450
+ if (entityTotal > response.entities.length) {
451
+ response.entityTruncation = {
452
+ shown: response.entities.length,
453
+ total: entityTotal,
454
+ };
455
+ }
456
+ response.runsOn = await TopologyQueries.readRunsOnCounts(runner, {
457
+ projectId,
458
+ rangeStart,
459
+ winner,
460
+ serviceKeys,
461
+ });
462
+ return response;
463
+ });
464
+ }
465
+ /*
466
+ * Infrastructure's traffic: the in-range calls between services that both
467
+ * run on a shipped node, so the map can draw them between the resources
468
+ * those services run on. A service placed nowhere could never be drawn, so
469
+ * calls to or from one are not read at all. Capped like the Service Map's
470
+ * dependencies (the first rows in its order, with the exact total), then
471
+ * ordered by (from, to) — each pair is at most one row (the unique index).
472
+ */
473
+ static async readInfrastructureDependencies(runner, data) {
474
+ const placedServiceIndexes = Array.from(new Set(data.response.placements.map((placement) => {
475
+ return placement[0];
476
+ }))).sort((left, right) => {
477
+ return left - right;
478
+ });
479
+ /* A call needs two different services at its ends. */
480
+ if (placedServiceIndexes.length < 2) {
481
+ return;
482
+ }
483
+ const placedServiceKeys = placedServiceIndexes.map((index) => {
484
+ return data.response.services[index].key;
485
+ });
486
+ const dependencies = await TopologyQueries.readCapped(runner, (limit) => {
487
+ return serviceMapDependenciesStatement({
488
+ projectId: data.projectId,
489
+ rangeStart: data.rangeStart,
490
+ serviceKeys: placedServiceKeys,
491
+ calleeKeys: placedServiceKeys,
492
+ mode: "rows",
493
+ limit,
494
+ });
495
+ }, () => {
496
+ return serviceMapDependenciesStatement({
497
+ projectId: data.projectId,
498
+ rangeStart: data.rangeStart,
499
+ serviceKeys: placedServiceKeys,
500
+ calleeKeys: placedServiceKeys,
501
+ mode: "count",
502
+ limit: 0,
503
+ });
504
+ }, TopologyApiLimits.MaxServiceMapDependencies);
505
+ const shipped = [];
506
+ for (const row of dependencies.rows) {
507
+ const from = data.serviceIndexByKey.get(readString(row, "from"));
508
+ const to = data.serviceIndexByKey.get(readString(row, "to"));
509
+ if (from === undefined || to === undefined || from === to) {
510
+ continue;
511
+ }
512
+ shipped.push({
513
+ from,
514
+ to,
515
+ callCount: readNullableNumber(row, "callCount"),
516
+ errorCount: readNullableNumber(row, "errorCount"),
517
+ avgDurationMs: readNullableNumber(row, "avgDurationMs"),
518
+ });
519
+ }
520
+ shipped.sort((left, right) => {
521
+ return left.from - right.from || left.to - right.to;
522
+ });
523
+ data.response.dependencies = shipped;
524
+ if (dependencies.total > dependencies.rows.length) {
525
+ data.response.dependencyTruncation = {
526
+ shown: dependencies.rows.length,
527
+ total: dependencies.total,
528
+ };
529
+ }
530
+ }
531
+ /*
532
+ * Infrastructure: one lean row per resource with its container chosen in
533
+ * SQL, every live service, where services run, the calls between placed
534
+ * services, and flat types too large to ship row by row as collections
535
+ * with exact counts.
536
+ */
537
+ static async getInfrastructure(request) {
538
+ const projectId = request.projectId.toString();
539
+ const rangeStart = request.rangeStart.toISOString();
540
+ const nodeCap = TopologyApiLimits.MaxInfrastructureNodes;
541
+ return await TopologyQueries.inReadOnlySnapshot(async (runner) => {
542
+ const response = Object.assign(Object.assign({}, TopologyQueries.envelope(request.rangeStart)), { nodes: [], services: [], placements: [], dependencies: [], dependencyTruncation: null, collections: [], totals: { resources: 0, activeResources: 0 }, truncation: null });
543
+ const projectTypes = await TopologyQueries.readProjectTypes(runner, projectId);
544
+ const infrastructureTypes = projectTypes.filter((type) => {
545
+ return isTopologyInfrastructureType(type);
546
+ });
547
+ /*
548
+ * Collections: a flat type (nothing nests in it, it nests in nothing,
549
+ * nothing groups it) with more items than the inline budget. Its
550
+ * volume is not bounded by any discovery budget, so the browser gets
551
+ * exact counts and pages the rows on demand. Its counts are over its
552
+ * rows; keys are unique per type.
553
+ */
554
+ const typeCounts = infrastructureTypes.length > 0
555
+ ? await runner.query(infrastructureTypeCountsStatement({
556
+ projectId,
557
+ rangeStart,
558
+ infrastructureTypes,
559
+ }))
560
+ : [];
561
+ const collectedTypes = new Set();
562
+ for (const row of typeCounts) {
563
+ const type = readString(row, "type");
564
+ const total = readNumber(row, "total");
565
+ if (isFlatInfrastructureType(type) &&
566
+ total > TopologyApiLimits.InlineFlatItemsPerType) {
567
+ collectedTypes.add(type);
568
+ response.collections.push({
569
+ type,
570
+ total,
571
+ active: readNumber(row, "active"),
572
+ lastSeenAt: readNullableNumber(row, "lastSeenAt"),
573
+ activeLastSeenAt: readNullableNumber(row, "activeLastSeenAt"),
574
+ });
575
+ }
576
+ }
577
+ const nodeTypes = infrastructureTypes.filter((type) => {
578
+ return !collectedTypes.has(type);
579
+ });
580
+ const hasServices = projectTypes.includes(EntityType.Service);
581
+ const winner = nodeTypes.length > 0 || hasServices
582
+ ? await TopologyQueries.readWinnerScope(runner, projectId, projectTypes)
583
+ : { projectTypes, duplicateKeys: [] };
584
+ let nodes = { rows: [], total: 0, count: {} };
585
+ if (nodeTypes.length > 0) {
586
+ nodes = await TopologyQueries.readCapped(runner, (limit) => {
587
+ return infrastructureNodesStatement({
588
+ projectId,
589
+ rangeStart,
590
+ winner,
591
+ nodeTypes,
592
+ mode: "rows",
593
+ limit,
594
+ });
595
+ }, () => {
596
+ return infrastructureNodesStatement({
597
+ projectId,
598
+ rangeStart,
599
+ winner,
600
+ nodeTypes,
601
+ mode: "count",
602
+ limit: 0,
603
+ });
604
+ }, nodeCap);
605
+ }
606
+ const nodeIndexByKey = new Map();
607
+ nodes.rows.forEach((row, index) => {
608
+ nodeIndexByKey.set(readString(row, "key"), index);
609
+ });
610
+ response.nodes = nodes.rows.map((row) => {
611
+ const node = toLeanEntity(row);
612
+ const parentKey = readNullableString(row, "parent");
613
+ /* A container outside the shipped set (a truncated list) is dropped. */
614
+ const parent = parentKey === null ? undefined : nodeIndexByKey.get(parentKey);
615
+ if (parent === undefined) {
616
+ return node;
617
+ }
618
+ node.parent = parent;
619
+ node.parentVia = readString(row, "parentVia");
620
+ if (readBoolean(row, "parentInactive")) {
621
+ const activeParentKey = readNullableString(row, "activeParent");
622
+ const activeParent = activeParentKey === null
623
+ ? undefined
624
+ : nodeIndexByKey.get(activeParentKey);
625
+ if (activeParent === undefined) {
626
+ node.activeParent = -1;
627
+ }
628
+ else {
629
+ node.activeParent = activeParent;
630
+ node.activeParentVia = readString(row, "activeParentVia");
631
+ }
632
+ }
633
+ return node;
634
+ });
635
+ let activeNodes = 0;
636
+ if (nodes.total > nodes.rows.length) {
637
+ activeNodes = readNumber(nodes.count, "active");
638
+ response.truncation = {
639
+ shown: nodes.rows.length,
640
+ total: nodes.total,
641
+ };
642
+ }
643
+ else {
644
+ for (const row of nodes.rows) {
645
+ if (readBoolean(row, "active")) {
646
+ activeNodes++;
647
+ }
648
+ }
649
+ }
650
+ response.totals = {
651
+ resources: nodes.total,
652
+ activeResources: activeNodes,
653
+ };
654
+ for (const collection of response.collections) {
655
+ response.totals.resources += collection.total;
656
+ response.totals.activeResources += collection.active;
657
+ }
658
+ if (hasServices) {
659
+ const serviceRows = await runner.query(servicesStatement({ projectId, winner }));
660
+ response.services = serviceRows.map((row) => {
661
+ return {
662
+ key: readString(row, "key"),
663
+ name: readNullableString(row, "name"),
664
+ };
665
+ });
666
+ }
667
+ if (response.services.length > 0 && response.nodes.length > 0) {
668
+ const serviceIndexByKey = new Map();
669
+ response.services.forEach((service, index) => {
670
+ serviceIndexByKey.set(service.key, index);
671
+ });
672
+ const placementRows = await runner.query(placementsStatement({
673
+ projectId,
674
+ rangeStart,
675
+ serviceKeys: response.services.map((service) => {
676
+ return service.key;
677
+ }),
678
+ }));
679
+ const placements = [];
680
+ for (const row of placementRows) {
681
+ const service = serviceIndexByKey.get(readString(row, "service"));
682
+ const node = nodeIndexByKey.get(readString(row, "target"));
683
+ if (service !== undefined && node !== undefined) {
684
+ placements.push([service, node]);
685
+ }
686
+ }
687
+ placements.sort((left, right) => {
688
+ return left[0] - right[0] || left[1] - right[1];
689
+ });
690
+ response.placements = placements;
691
+ await TopologyQueries.readInfrastructureDependencies(runner, {
692
+ projectId,
693
+ rangeStart,
694
+ response,
695
+ serviceIndexByKey,
696
+ });
697
+ }
698
+ return response;
699
+ });
700
+ }
701
+ /* One keyset page of a collection, with the total matching the filters. */
702
+ static async getCollectionPage(request) {
703
+ const projectId = request.projectId.toString();
704
+ const rangeStart = request.rangeStart.toISOString();
705
+ return await TopologyQueries.inReadOnlySnapshot(async (runner) => {
706
+ var _a;
707
+ const filters = {
708
+ projectId,
709
+ rangeStart,
710
+ entityType: request.entityType,
711
+ includeInactive: request.includeInactive,
712
+ nameTerms: request.nameTerms,
713
+ cursor: request.cursor,
714
+ };
715
+ const countRows = await runner.query(collectionPageStatement(Object.assign(Object.assign({}, filters), { mode: "count", limit: 0 })));
716
+ const rows = await runner.query(collectionPageStatement(Object.assign(Object.assign({}, filters), { mode: "rows", limit: request.limit + 1 })));
717
+ const items = rows
718
+ .slice(0, request.limit)
719
+ .map(toLeanEntity);
720
+ const last = items[items.length - 1];
721
+ return Object.assign(Object.assign({}, TopologyQueries.envelope(request.rangeStart)), { entityType: request.entityType, total: readNumber(countRows[0] || {}, "total"), items, nextCursor: rows.length > request.limit && last
722
+ ? { name: (_a = last.name) !== null && _a !== void 0 ? _a : "", key: last.key }
723
+ : null });
724
+ });
725
+ }
726
+ /* How many items of each requested collection match its terms. */
727
+ static async getCollectionSearch(request) {
728
+ const response = Object.assign(Object.assign({}, TopologyQueries.envelope(request.rangeStart)), { matches: [] });
729
+ if (request.types.length === 0) {
730
+ return response;
731
+ }
732
+ const rows = await TopologyQueries.inReadOnlySnapshot(async (runner) => {
733
+ return await runner.query(collectionSearchStatement({
734
+ projectId: request.projectId.toString(),
735
+ rangeStart: request.rangeStart.toISOString(),
736
+ includeInactive: request.includeInactive,
737
+ types: request.types,
738
+ }));
739
+ });
740
+ const countByType = new Map();
741
+ for (const row of rows) {
742
+ countByType.set(readString(row, "entityType"), readNumber(row, "count"));
743
+ }
744
+ for (const type of request.types) {
745
+ const count = countByType.get(type.entityType) || 0;
746
+ if (count > 0) {
747
+ response.matches.push({ entityType: type.entityType, count });
748
+ }
749
+ }
750
+ return response;
751
+ }
752
+ /*
753
+ * The drawer: the entity's full row and its in-range relationships in four
754
+ * sections with exact totals (lower bounds when the scan stopped) and the
755
+ * top rows of each.
756
+ */
757
+ static async getEntity(request) {
758
+ const result = await TopologyQueries.readEntityAndSections(request, { kind: "range", rangeStart: request.rangeStart.toISOString() }, TopologyQueries.firstView());
759
+ return Object.assign(Object.assign({}, TopologyQueries.envelope(request.rangeStart)), { entity: result.entity, sections: result.decoded.sections, isScanLimited: result.decoded.isScanLimited });
760
+ }
761
+ /* "Show more": the next page of one drawer section. */
762
+ static async getEntityConnections(request) {
763
+ const result = await TopologyQueries.readEntityAndSections(request, { kind: "range", rangeStart: request.rangeStart.toISOString() }, TopologyQueries.pageWindow(request));
764
+ return Object.assign(Object.assign({}, TopologyQueries.envelope(request.rangeStart)), { section: request.section, connections: result.decoded.sections[request.section], isScanLimited: result.decoded.isScanLimited });
765
+ }
766
+ /*
767
+ * The inventory item page: the drawer's sections over everything the
768
+ * inventory holds — every relationship however long ago it was seen, for
769
+ * an item archived or not, with archived other ends named and linkable.
770
+ */
771
+ static async getEntityAllTime(request) {
772
+ const result = await TopologyQueries.readEntityAndSections(request, { kind: "allTime" }, TopologyQueries.firstView());
773
+ return Object.assign(Object.assign({}, TopologyQueries.allTimeEnvelope()), { entity: result.entity, sections: result.decoded.sections, isScanLimited: result.decoded.isScanLimited });
774
+ }
775
+ /* "Show more" on the inventory item page: one all-time section's page. */
776
+ static async getEntityAllTimeConnections(request) {
777
+ const result = await TopologyQueries.readEntityAndSections(request, { kind: "allTime" }, TopologyQueries.pageWindow(request));
778
+ return Object.assign(Object.assign({}, TopologyQueries.allTimeEnvelope()), { section: request.section, connections: result.decoded.sections[request.section], isScanLimited: result.decoded.isScanLimited });
779
+ }
780
+ /* The first view: the top rows of every section. */
781
+ static firstView() {
782
+ return {
783
+ kind: "top",
784
+ dependencyRows: TopologyApiLimits.EntityDependencyRows,
785
+ otherRows: TopologyApiLimits.EntityOtherRows,
786
+ };
787
+ }
788
+ static pageWindow(request) {
789
+ return {
790
+ kind: "page",
791
+ section: request.section,
792
+ offset: request.offset,
793
+ limit: request.limit || rowsForSection(request.section),
794
+ };
795
+ }
796
+ static async readEntityAndSections(request, scope, window) {
797
+ const projectId = request.projectId.toString();
798
+ const allTime = scope.kind === "allTime";
799
+ return await TopologyQueries.inReadOnlySnapshot(async (runner) => {
800
+ const nothing = {
801
+ sections: emptySections(),
802
+ isScanLimited: false,
803
+ };
804
+ const projectTypes = await TopologyQueries.readProjectTypes(runner, projectId);
805
+ if (projectTypes.length === 0) {
806
+ return { entity: null, decoded: nothing };
807
+ }
808
+ const entityRows = await runner.query(entityStatement({
809
+ projectId,
810
+ projectTypes,
811
+ entityKey: request.entityKey,
812
+ entityType: request.entityType,
813
+ includeArchived: allTime,
814
+ }));
815
+ const entityRow = entityRows[0];
816
+ if (!entityRow) {
817
+ return { entity: null, decoded: nothing };
818
+ }
819
+ const entity = Object.assign(Object.assign({}, toLeanEntity(entityRow)), { id: readString(entityRow, "id"), firstSeenAt: readNullableNumber(entityRow, "firstSeenAt"), resourceType: readNullableString(entityRow, "resourceType"), resourceId: readNullableString(entityRow, "resourceId"), identifyingAttributes: readJsonObject(entityRow, "identifyingAttributes"), descriptiveAttributes: readJsonObject(entityRow, "descriptiveAttributes") });
820
+ const sectionRows = await runner.query(entitySectionsStatement({
821
+ projectId,
822
+ scope,
823
+ projectTypes,
824
+ entityKey: entity.key,
825
+ isService: entity.type === EntityType.Service,
826
+ scanLimit: TopologyApiLimits.EntityConnectionScanLimit + 1,
827
+ window,
828
+ }));
829
+ return {
830
+ entity,
831
+ decoded: decodeSections(sectionRows, window.kind === "page" ? window.offset : 0),
832
+ };
833
+ });
834
+ }
835
+ }
836
+ __decorate([
837
+ CaptureSpan(),
838
+ __metadata("design:type", Function),
839
+ __metadata("design:paramtypes", [Object]),
840
+ __metadata("design:returntype", Promise)
841
+ ], TopologyQueries, "getServiceMap", null);
842
+ __decorate([
843
+ CaptureSpan(),
844
+ __metadata("design:type", Function),
845
+ __metadata("design:paramtypes", [Object]),
846
+ __metadata("design:returntype", Promise)
847
+ ], TopologyQueries, "getInfrastructure", null);
848
+ __decorate([
849
+ CaptureSpan(),
850
+ __metadata("design:type", Function),
851
+ __metadata("design:paramtypes", [Object]),
852
+ __metadata("design:returntype", Promise)
853
+ ], TopologyQueries, "getCollectionPage", null);
854
+ __decorate([
855
+ CaptureSpan(),
856
+ __metadata("design:type", Function),
857
+ __metadata("design:paramtypes", [Object]),
858
+ __metadata("design:returntype", Promise)
859
+ ], TopologyQueries, "getCollectionSearch", null);
860
+ __decorate([
861
+ CaptureSpan(),
862
+ __metadata("design:type", Function),
863
+ __metadata("design:paramtypes", [Object]),
864
+ __metadata("design:returntype", Promise)
865
+ ], TopologyQueries, "getEntity", null);
866
+ __decorate([
867
+ CaptureSpan(),
868
+ __metadata("design:type", Function),
869
+ __metadata("design:paramtypes", [Object]),
870
+ __metadata("design:returntype", Promise)
871
+ ], TopologyQueries, "getEntityConnections", null);
872
+ __decorate([
873
+ CaptureSpan(),
874
+ __metadata("design:type", Function),
875
+ __metadata("design:paramtypes", [Object]),
876
+ __metadata("design:returntype", Promise)
877
+ ], TopologyQueries, "getEntityAllTime", null);
878
+ __decorate([
879
+ CaptureSpan(),
880
+ __metadata("design:type", Function),
881
+ __metadata("design:paramtypes", [Object]),
882
+ __metadata("design:returntype", Promise)
883
+ ], TopologyQueries, "getEntityAllTimeConnections", null);
884
+ //# sourceMappingURL=TopologyQueries.js.map