@oneuptime/common 11.1.2 → 11.2.1

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 (155) hide show
  1. package/Models/DatabaseModels/Alert.ts +55 -0
  2. package/Models/DatabaseModels/Incident.ts +55 -0
  3. package/Models/DatabaseModels/Index.ts +12 -0
  4. package/Models/DatabaseModels/IoTDevice.ts +690 -0
  5. package/Models/DatabaseModels/IoTFleet.ts +862 -0
  6. package/Models/DatabaseModels/IoTFleetLabelRule.ts +514 -0
  7. package/Models/DatabaseModels/IoTFleetOwnerRule.ts +596 -0
  8. package/Models/DatabaseModels/IoTFleetOwnerTeam.ts +485 -0
  9. package/Models/DatabaseModels/IoTFleetOwnerUser.ts +484 -0
  10. package/Models/DatabaseModels/ScheduledMaintenance.ts +55 -0
  11. package/Server/API/IoTDeviceAPI.ts +128 -0
  12. package/Server/API/TelemetryAPI.ts +104 -35
  13. package/Server/Infrastructure/Postgres/SchemaMigrations/1782900000000-AddIoTFleetAndDeviceTables.ts +399 -0
  14. package/Server/Infrastructure/Postgres/SchemaMigrations/1783000000000-AddIoTFleetActivityJoinTables.ts +97 -0
  15. package/Server/Infrastructure/Postgres/SchemaMigrations/1783010000000-MigrationName.ts +979 -0
  16. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +6 -0
  17. package/Server/Services/AlertService.ts +24 -3
  18. package/Server/Services/IncidentService.ts +24 -3
  19. package/Server/Services/IoTDeviceService.ts +356 -0
  20. package/Server/Services/IoTFleetLabelRuleEngineService.ts +198 -0
  21. package/Server/Services/IoTFleetLabelRuleService.ts +14 -0
  22. package/Server/Services/IoTFleetOwnerRuleEngineService.ts +216 -0
  23. package/Server/Services/IoTFleetOwnerRuleService.ts +14 -0
  24. package/Server/Services/IoTFleetOwnerTeamService.ts +10 -0
  25. package/Server/Services/IoTFleetOwnerUserService.ts +10 -0
  26. package/Server/Services/IoTFleetService.ts +376 -0
  27. package/Server/Services/OpenTelemetryIngestService.ts +16 -0
  28. package/Server/Services/StatusPageService.ts +69 -26
  29. package/Server/Services/StatusPageSubscriberNotificationTemplateService.ts +36 -0
  30. package/Server/Services/TelemetryUsageBillingService.ts +18 -0
  31. package/Server/Services/TraceAggregationService.ts +174 -0
  32. package/Server/Utils/Monitor/Criteria/ServerMonitorCriteria.ts +1 -1
  33. package/Server/Utils/Monitor/MonitorAlert.ts +24 -4
  34. package/Server/Utils/Monitor/MonitorClusterContext.ts +26 -2
  35. package/Server/Utils/Monitor/MonitorCriteriaEvaluator.ts +4 -2
  36. package/Server/Utils/Monitor/MonitorIncident.ts +39 -5
  37. package/Server/Utils/Monitor/MonitorMaintenanceSuppression.ts +14 -0
  38. package/Server/Utils/Monitor/SeriesResourceLabels.ts +22 -0
  39. package/Server/Utils/Telemetry/IoTSnapshotScan.ts +408 -0
  40. package/Tests/Server/Utils/Monitor/MonitorMaintenanceSuppression.test.ts +36 -0
  41. package/Types/Icon/IconProp.ts +1 -0
  42. package/Types/Monitor/IotAlertTemplates.ts +593 -0
  43. package/Types/Monitor/IotMetricCatalog.ts +146 -0
  44. package/Types/Monitor/MonitorStep.ts +31 -0
  45. package/Types/Monitor/MonitorStepIoTMonitor.ts +65 -0
  46. package/Types/Monitor/MonitorType.ts +12 -1
  47. package/Types/Permission.ts +230 -0
  48. package/Types/StatusPage/StatusPageSubscriberNotificationEventType.ts +3 -0
  49. package/Types/Telemetry/ServiceType.ts +1 -0
  50. package/UI/Components/Charts/ChartGroup/ChartGroup.tsx +5 -5
  51. package/UI/Components/Icon/Icon.tsx +18 -2
  52. package/UI/Components/Page/Page.tsx +1 -2
  53. package/build/dist/Models/DatabaseModels/Alert.js +54 -0
  54. package/build/dist/Models/DatabaseModels/Alert.js.map +1 -1
  55. package/build/dist/Models/DatabaseModels/Incident.js +54 -0
  56. package/build/dist/Models/DatabaseModels/Incident.js.map +1 -1
  57. package/build/dist/Models/DatabaseModels/Index.js +12 -0
  58. package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
  59. package/build/dist/Models/DatabaseModels/IoTDevice.js +722 -0
  60. package/build/dist/Models/DatabaseModels/IoTDevice.js.map +1 -0
  61. package/build/dist/Models/DatabaseModels/IoTFleet.js +882 -0
  62. package/build/dist/Models/DatabaseModels/IoTFleet.js.map +1 -0
  63. package/build/dist/Models/DatabaseModels/IoTFleetLabelRule.js +522 -0
  64. package/build/dist/Models/DatabaseModels/IoTFleetLabelRule.js.map +1 -0
  65. package/build/dist/Models/DatabaseModels/IoTFleetOwnerRule.js +603 -0
  66. package/build/dist/Models/DatabaseModels/IoTFleetOwnerRule.js.map +1 -0
  67. package/build/dist/Models/DatabaseModels/IoTFleetOwnerTeam.js +503 -0
  68. package/build/dist/Models/DatabaseModels/IoTFleetOwnerTeam.js.map +1 -0
  69. package/build/dist/Models/DatabaseModels/IoTFleetOwnerUser.js +502 -0
  70. package/build/dist/Models/DatabaseModels/IoTFleetOwnerUser.js.map +1 -0
  71. package/build/dist/Models/DatabaseModels/ScheduledMaintenance.js +54 -0
  72. package/build/dist/Models/DatabaseModels/ScheduledMaintenance.js.map +1 -1
  73. package/build/dist/Server/API/IoTDeviceAPI.js +92 -0
  74. package/build/dist/Server/API/IoTDeviceAPI.js.map +1 -0
  75. package/build/dist/Server/API/TelemetryAPI.js +76 -27
  76. package/build/dist/Server/API/TelemetryAPI.js.map +1 -1
  77. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1782900000000-AddIoTFleetAndDeviceTables.js +187 -0
  78. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1782900000000-AddIoTFleetAndDeviceTables.js.map +1 -0
  79. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783000000000-AddIoTFleetActivityJoinTables.js +48 -0
  80. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783000000000-AddIoTFleetActivityJoinTables.js.map +1 -0
  81. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783010000000-MigrationName.js +340 -0
  82. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783010000000-MigrationName.js.map +1 -0
  83. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +6 -0
  84. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  85. package/build/dist/Server/Services/AlertService.js +22 -3
  86. package/build/dist/Server/Services/AlertService.js.map +1 -1
  87. package/build/dist/Server/Services/IncidentService.js +22 -3
  88. package/build/dist/Server/Services/IncidentService.js.map +1 -1
  89. package/build/dist/Server/Services/IoTDeviceService.js +249 -0
  90. package/build/dist/Server/Services/IoTDeviceService.js.map +1 -0
  91. package/build/dist/Server/Services/IoTFleetLabelRuleEngineService.js +166 -0
  92. package/build/dist/Server/Services/IoTFleetLabelRuleEngineService.js.map +1 -0
  93. package/build/dist/Server/Services/IoTFleetLabelRuleService.js +13 -0
  94. package/build/dist/Server/Services/IoTFleetLabelRuleService.js.map +1 -0
  95. package/build/dist/Server/Services/IoTFleetOwnerRuleEngineService.js +186 -0
  96. package/build/dist/Server/Services/IoTFleetOwnerRuleEngineService.js.map +1 -0
  97. package/build/dist/Server/Services/IoTFleetOwnerRuleService.js +13 -0
  98. package/build/dist/Server/Services/IoTFleetOwnerRuleService.js.map +1 -0
  99. package/build/dist/Server/Services/IoTFleetOwnerTeamService.js +9 -0
  100. package/build/dist/Server/Services/IoTFleetOwnerTeamService.js.map +1 -0
  101. package/build/dist/Server/Services/IoTFleetOwnerUserService.js +9 -0
  102. package/build/dist/Server/Services/IoTFleetOwnerUserService.js.map +1 -0
  103. package/build/dist/Server/Services/IoTFleetService.js +340 -0
  104. package/build/dist/Server/Services/IoTFleetService.js.map +1 -0
  105. package/build/dist/Server/Services/OpenTelemetryIngestService.js +26 -11
  106. package/build/dist/Server/Services/OpenTelemetryIngestService.js.map +1 -1
  107. package/build/dist/Server/Services/StatusPageService.js +57 -23
  108. package/build/dist/Server/Services/StatusPageService.js.map +1 -1
  109. package/build/dist/Server/Services/StatusPageSubscriberNotificationTemplateService.js +34 -0
  110. package/build/dist/Server/Services/StatusPageSubscriberNotificationTemplateService.js.map +1 -1
  111. package/build/dist/Server/Services/TelemetryUsageBillingService.js +13 -0
  112. package/build/dist/Server/Services/TelemetryUsageBillingService.js.map +1 -1
  113. package/build/dist/Server/Services/TraceAggregationService.js +136 -0
  114. package/build/dist/Server/Services/TraceAggregationService.js.map +1 -1
  115. package/build/dist/Server/Utils/Monitor/Criteria/ServerMonitorCriteria.js +15 -15
  116. package/build/dist/Server/Utils/Monitor/Criteria/ServerMonitorCriteria.js.map +1 -1
  117. package/build/dist/Server/Utils/Monitor/MonitorAlert.js +37 -19
  118. package/build/dist/Server/Utils/Monitor/MonitorAlert.js.map +1 -1
  119. package/build/dist/Server/Utils/Monitor/MonitorClusterContext.js +27 -4
  120. package/build/dist/Server/Utils/Monitor/MonitorClusterContext.js.map +1 -1
  121. package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js +4 -2
  122. package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js.map +1 -1
  123. package/build/dist/Server/Utils/Monitor/MonitorIncident.js +39 -11
  124. package/build/dist/Server/Utils/Monitor/MonitorIncident.js.map +1 -1
  125. package/build/dist/Server/Utils/Monitor/MonitorMaintenanceSuppression.js +8 -0
  126. package/build/dist/Server/Utils/Monitor/MonitorMaintenanceSuppression.js.map +1 -1
  127. package/build/dist/Server/Utils/Monitor/SeriesResourceLabels.js +17 -0
  128. package/build/dist/Server/Utils/Monitor/SeriesResourceLabels.js.map +1 -1
  129. package/build/dist/Server/Utils/Telemetry/IoTSnapshotScan.js +300 -0
  130. package/build/dist/Server/Utils/Telemetry/IoTSnapshotScan.js.map +1 -0
  131. package/build/dist/Types/Icon/IconProp.js +1 -0
  132. package/build/dist/Types/Icon/IconProp.js.map +1 -1
  133. package/build/dist/Types/Monitor/IotAlertTemplates.js +467 -0
  134. package/build/dist/Types/Monitor/IotAlertTemplates.js.map +1 -0
  135. package/build/dist/Types/Monitor/IotMetricCatalog.js +108 -0
  136. package/build/dist/Types/Monitor/IotMetricCatalog.js.map +1 -0
  137. package/build/dist/Types/Monitor/MonitorStep.js +23 -0
  138. package/build/dist/Types/Monitor/MonitorStep.js.map +1 -1
  139. package/build/dist/Types/Monitor/MonitorStepIoTMonitor.js +32 -0
  140. package/build/dist/Types/Monitor/MonitorStepIoTMonitor.js.map +1 -0
  141. package/build/dist/Types/Monitor/MonitorType.js +11 -1
  142. package/build/dist/Types/Monitor/MonitorType.js.map +1 -1
  143. package/build/dist/Types/Permission.js +204 -0
  144. package/build/dist/Types/Permission.js.map +1 -1
  145. package/build/dist/Types/StatusPage/StatusPageSubscriberNotificationEventType.js +2 -0
  146. package/build/dist/Types/StatusPage/StatusPageSubscriberNotificationEventType.js.map +1 -1
  147. package/build/dist/Types/Telemetry/ServiceType.js +1 -0
  148. package/build/dist/Types/Telemetry/ServiceType.js.map +1 -1
  149. package/build/dist/UI/Components/Charts/ChartGroup/ChartGroup.js +3 -3
  150. package/build/dist/UI/Components/Charts/ChartGroup/ChartGroup.js.map +1 -1
  151. package/build/dist/UI/Components/Icon/Icon.js +12 -2
  152. package/build/dist/UI/Components/Icon/Icon.js.map +1 -1
  153. package/build/dist/UI/Components/Page/Page.js +1 -2
  154. package/build/dist/UI/Components/Page/Page.js.map +1 -1
  155. package/package.json +1 -1
@@ -0,0 +1,722 @@
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 IoTFleet from "./IoTFleet";
11
+ import Project from "./Project";
12
+ import User from "./User";
13
+ import BaseModel from "./DatabaseBaseModel/DatabaseBaseModel";
14
+ import Route from "../../Types/API/Route";
15
+ import ColumnAccessControl from "../../Types/Database/AccessControl/ColumnAccessControl";
16
+ import TableAccessControl from "../../Types/Database/AccessControl/TableAccessControl";
17
+ import ColumnLength from "../../Types/Database/ColumnLength";
18
+ import ColumnType from "../../Types/Database/ColumnType";
19
+ import CrudApiEndpoint from "../../Types/Database/CrudApiEndpoint";
20
+ import TableColumn from "../../Types/Database/TableColumn";
21
+ import TableColumnType from "../../Types/Database/TableColumnType";
22
+ import TableMetadata from "../../Types/Database/TableMetadata";
23
+ import TenantColumn from "../../Types/Database/TenantColumn";
24
+ import IconProp from "../../Types/Icon/IconProp";
25
+ import ObjectID from "../../Types/ObjectID";
26
+ import Permission from "../../Types/Permission";
27
+ import { Column, Entity, Index, JoinColumn, ManyToOne } from "typeorm";
28
+ /*
29
+ * ------------------------------------------------------------------
30
+ * IoTDevice
31
+ * ------------------------------------------------------------------
32
+ *
33
+ * Inventory snapshot of a single IoT device (sensor, gateway, etc.)
34
+ * in a single fleet. Populated by the OTel metrics ingest path from
35
+ * the device/gateway OTLP push stream — identity and status already
36
+ * arrive in every metric batch, so no separate object stream is
37
+ * needed.
38
+ *
39
+ * `externalId` is the `device.id` datapoint label verbatim —
40
+ * immutable and collision-free within a fleet.
41
+ *
42
+ * Latest-metric delta: iot_cpu_usage_ratio is already a true 0..1
43
+ * ratio, so latestCpuPercent is just ratio * 100 — no
44
+ * allocatable-denominator cache is needed.
45
+ *
46
+ * The list/detail pages read this table instead of groupBy-ing over
47
+ * 24h of ClickHouse metric data. Rows are upserted per scrape and
48
+ * hard-deleted once lastSeenAt falls behind "now - 15min" for fleets
49
+ * that remain connected.
50
+ *
51
+ * Writes go through IoTDeviceService under isRoot; users never
52
+ * create/update/delete rows directly.
53
+ *
54
+ * ------------------------------------------------------------------
55
+ */
56
+ const READ_PERMISSIONS = [
57
+ Permission.ProjectOwner,
58
+ Permission.ProjectAdmin,
59
+ Permission.ProjectMember,
60
+ Permission.Viewer,
61
+ Permission.SettingsAdmin,
62
+ Permission.SettingsMember,
63
+ Permission.SettingsViewer,
64
+ Permission.ReadIoTFleet,
65
+ ];
66
+ let IoTDevice = class IoTDevice extends BaseModel {
67
+ constructor() {
68
+ super(...arguments);
69
+ this.project = undefined;
70
+ this.projectId = undefined;
71
+ this.iotFleet = undefined;
72
+ this.iotFleetId = undefined;
73
+ this.kind = undefined;
74
+ this.externalId = undefined;
75
+ this.name = undefined;
76
+ this.deviceType = undefined;
77
+ this.firmwareVersion = undefined;
78
+ this.isUp = undefined;
79
+ this.uptimeSeconds = undefined;
80
+ this.latestCpuPercent = undefined;
81
+ this.latestMemoryBytes = undefined;
82
+ this.maxMemoryBytes = undefined;
83
+ this.latestMemoryPercent = undefined;
84
+ this.latestBatteryPercent = undefined;
85
+ this.latestSignalStrengthDbm = undefined;
86
+ this.latestTemperatureCelsius = undefined;
87
+ this.metricsUpdatedAt = undefined;
88
+ this.lastSeenAt = undefined;
89
+ this.createdByUser = undefined;
90
+ this.createdByUserId = undefined;
91
+ this.deletedByUser = undefined;
92
+ this.deletedByUserId = undefined;
93
+ }
94
+ };
95
+ __decorate([
96
+ ColumnAccessControl({
97
+ create: [],
98
+ read: READ_PERMISSIONS,
99
+ update: [],
100
+ }),
101
+ TableColumn({
102
+ manyToOneRelationColumn: "projectId",
103
+ type: TableColumnType.Entity,
104
+ modelType: Project,
105
+ title: "Project",
106
+ description: "Relation to Project this device belongs to.",
107
+ }),
108
+ ManyToOne(() => {
109
+ return Project;
110
+ }, {
111
+ eager: false,
112
+ nullable: true,
113
+ onDelete: "CASCADE",
114
+ orphanedRowAction: "nullify",
115
+ }),
116
+ JoinColumn({ name: "projectId" }),
117
+ __metadata("design:type", Project)
118
+ ], IoTDevice.prototype, "project", void 0);
119
+ __decorate([
120
+ ColumnAccessControl({
121
+ create: [],
122
+ read: READ_PERMISSIONS,
123
+ update: [],
124
+ }),
125
+ Index(),
126
+ TableColumn({
127
+ type: TableColumnType.ObjectID,
128
+ required: true,
129
+ canReadOnRelationQuery: true,
130
+ title: "Project ID",
131
+ description: "ID of the Project this device belongs to.",
132
+ }),
133
+ Column({
134
+ type: ColumnType.ObjectID,
135
+ nullable: false,
136
+ transformer: ObjectID.getDatabaseTransformer(),
137
+ }),
138
+ __metadata("design:type", ObjectID)
139
+ ], IoTDevice.prototype, "projectId", void 0);
140
+ __decorate([
141
+ ColumnAccessControl({
142
+ create: [],
143
+ read: READ_PERMISSIONS,
144
+ update: [],
145
+ }),
146
+ TableColumn({
147
+ manyToOneRelationColumn: "iotFleetId",
148
+ type: TableColumnType.Entity,
149
+ modelType: IoTFleet,
150
+ title: "IoT Fleet",
151
+ description: "Fleet this device lives in.",
152
+ }),
153
+ ManyToOne(() => {
154
+ return IoTFleet;
155
+ }, {
156
+ eager: false,
157
+ nullable: true,
158
+ onDelete: "CASCADE",
159
+ orphanedRowAction: "nullify",
160
+ }),
161
+ JoinColumn({ name: "iotFleetId" }),
162
+ __metadata("design:type", IoTFleet)
163
+ ], IoTDevice.prototype, "iotFleet", void 0);
164
+ __decorate([
165
+ ColumnAccessControl({
166
+ create: [],
167
+ read: READ_PERMISSIONS,
168
+ update: [],
169
+ }),
170
+ Index(),
171
+ TableColumn({
172
+ type: TableColumnType.ObjectID,
173
+ required: true,
174
+ canReadOnRelationQuery: true,
175
+ title: "IoT Fleet ID",
176
+ description: "ID of the IoT Fleet this device lives in.",
177
+ }),
178
+ Column({
179
+ type: ColumnType.ObjectID,
180
+ nullable: false,
181
+ transformer: ObjectID.getDatabaseTransformer(),
182
+ }),
183
+ __metadata("design:type", ObjectID)
184
+ ], IoTDevice.prototype, "iotFleetId", void 0);
185
+ __decorate([
186
+ ColumnAccessControl({
187
+ create: [],
188
+ read: READ_PERMISSIONS,
189
+ update: [],
190
+ }),
191
+ TableColumn({
192
+ required: true,
193
+ type: TableColumnType.ShortText,
194
+ canReadOnRelationQuery: true,
195
+ title: "Kind",
196
+ description: "IoT device class in singular PascalCase: Device, Sensor or Gateway.",
197
+ }),
198
+ Column({
199
+ nullable: false,
200
+ type: ColumnType.ShortText,
201
+ length: ColumnLength.ShortText,
202
+ }),
203
+ __metadata("design:type", String)
204
+ ], IoTDevice.prototype, "kind", void 0);
205
+ __decorate([
206
+ ColumnAccessControl({
207
+ create: [],
208
+ read: READ_PERMISSIONS,
209
+ update: [],
210
+ }),
211
+ TableColumn({
212
+ required: true,
213
+ type: TableColumnType.ShortText,
214
+ canReadOnRelationQuery: true,
215
+ title: "External ID",
216
+ description: "The `device.id` datapoint label verbatim. Immutable and collision-free within a fleet; also the detail-route param.",
217
+ }),
218
+ Column({
219
+ nullable: false,
220
+ type: ColumnType.ShortText,
221
+ length: ColumnLength.ShortText,
222
+ }),
223
+ __metadata("design:type", String)
224
+ ], IoTDevice.prototype, "externalId", void 0);
225
+ __decorate([
226
+ ColumnAccessControl({
227
+ create: [],
228
+ read: READ_PERMISSIONS,
229
+ update: [],
230
+ }),
231
+ TableColumn({
232
+ required: false,
233
+ type: TableColumnType.ShortText,
234
+ canReadOnRelationQuery: true,
235
+ title: "Name",
236
+ description: "Human-friendly name from the iot_device_info `name` label. Null until the matching info series is scraped.",
237
+ }),
238
+ Column({
239
+ nullable: true,
240
+ type: ColumnType.ShortText,
241
+ length: ColumnLength.ShortText,
242
+ }),
243
+ __metadata("design:type", String)
244
+ ], IoTDevice.prototype, "name", void 0);
245
+ __decorate([
246
+ ColumnAccessControl({
247
+ create: [],
248
+ read: READ_PERMISSIONS,
249
+ update: [],
250
+ }),
251
+ TableColumn({
252
+ required: false,
253
+ type: TableColumnType.ShortText,
254
+ canReadOnRelationQuery: true,
255
+ title: "Device Type",
256
+ description: "Device type from the `iot.device.type` attribute (e.g. thermostat, camera, meter). Null until reported.",
257
+ }),
258
+ Column({
259
+ nullable: true,
260
+ type: ColumnType.ShortText,
261
+ length: ColumnLength.ShortText,
262
+ }),
263
+ __metadata("design:type", String)
264
+ ], IoTDevice.prototype, "deviceType", void 0);
265
+ __decorate([
266
+ ColumnAccessControl({
267
+ create: [],
268
+ read: READ_PERMISSIONS,
269
+ update: [],
270
+ }),
271
+ TableColumn({
272
+ required: false,
273
+ type: TableColumnType.ShortText,
274
+ canReadOnRelationQuery: true,
275
+ title: "Firmware Version",
276
+ description: "Firmware version from the `iot.device.firmware` attribute. Null until reported.",
277
+ }),
278
+ Column({
279
+ nullable: true,
280
+ type: ColumnType.ShortText,
281
+ length: ColumnLength.ShortText,
282
+ }),
283
+ __metadata("design:type", String)
284
+ ], IoTDevice.prototype, "firmwareVersion", void 0);
285
+ __decorate([
286
+ ColumnAccessControl({
287
+ create: [],
288
+ read: READ_PERMISSIONS,
289
+ update: [],
290
+ }),
291
+ TableColumn({
292
+ required: false,
293
+ type: TableColumnType.Boolean,
294
+ canReadOnRelationQuery: true,
295
+ title: "Is Up",
296
+ description: "True when the latest iot_device_up value for this device is 1 (device online).",
297
+ }),
298
+ Column({
299
+ nullable: true,
300
+ type: ColumnType.Boolean,
301
+ }),
302
+ __metadata("design:type", Boolean)
303
+ ], IoTDevice.prototype, "isUp", void 0);
304
+ __decorate([
305
+ ColumnAccessControl({
306
+ create: [],
307
+ read: READ_PERMISSIONS,
308
+ update: [],
309
+ }),
310
+ TableColumn({
311
+ required: false,
312
+ type: TableColumnType.Number,
313
+ canReadOnRelationQuery: true,
314
+ title: "Uptime Seconds",
315
+ description: "Latest iot_uptime_seconds value for this device. Null until the first metric arrives.",
316
+ }),
317
+ Column({
318
+ nullable: true,
319
+ type: ColumnType.Number,
320
+ }),
321
+ __metadata("design:type", Number)
322
+ ], IoTDevice.prototype, "uptimeSeconds", void 0);
323
+ __decorate([
324
+ ColumnAccessControl({
325
+ create: [],
326
+ read: READ_PERMISSIONS,
327
+ update: [],
328
+ }),
329
+ TableColumn({
330
+ required: false,
331
+ type: TableColumnType.Number,
332
+ canReadOnRelationQuery: true,
333
+ title: "Latest CPU Percent",
334
+ description: "Most recent CPU utilization percent (iot_cpu_usage_ratio * 100 — already a true ratio; no allocatable-denominator cache needed). Stored as decimal so sub-percent precision survives the round trip. Null until the first metric arrives.",
335
+ }),
336
+ Column({
337
+ nullable: true,
338
+ type: ColumnType.Decimal,
339
+ transformer: {
340
+ to: (value) => {
341
+ if (value === null || value === undefined) {
342
+ return null;
343
+ }
344
+ return value;
345
+ },
346
+ from: (value) => {
347
+ if (value === null || value === undefined) {
348
+ return null;
349
+ }
350
+ if (typeof value === "number") {
351
+ return value;
352
+ }
353
+ const parsed = parseFloat(value);
354
+ return isNaN(parsed) ? null : parsed;
355
+ },
356
+ },
357
+ }),
358
+ __metadata("design:type", Number)
359
+ ], IoTDevice.prototype, "latestCpuPercent", void 0);
360
+ __decorate([
361
+ ColumnAccessControl({
362
+ create: [],
363
+ read: READ_PERMISSIONS,
364
+ update: [],
365
+ }),
366
+ TableColumn({
367
+ required: false,
368
+ type: TableColumnType.BigPositiveNumber,
369
+ canReadOnRelationQuery: true,
370
+ title: "Latest Memory Bytes",
371
+ description: "Most recent memory usage (iot_memory_usage_bytes). Stored as bigint so values past 2 GiB don't overflow.",
372
+ }),
373
+ Column({
374
+ nullable: true,
375
+ type: ColumnType.BigPositiveNumber,
376
+ transformer: {
377
+ to: (value) => {
378
+ if (value === null || value === undefined) {
379
+ return null;
380
+ }
381
+ return Math.trunc(value).toString();
382
+ },
383
+ from: (value) => {
384
+ if (value === null || value === undefined) {
385
+ return null;
386
+ }
387
+ const parsed = parseInt(value, 10);
388
+ return isNaN(parsed) ? null : parsed;
389
+ },
390
+ },
391
+ }),
392
+ __metadata("design:type", Number)
393
+ ], IoTDevice.prototype, "latestMemoryBytes", void 0);
394
+ __decorate([
395
+ ColumnAccessControl({
396
+ create: [],
397
+ read: READ_PERMISSIONS,
398
+ update: [],
399
+ }),
400
+ TableColumn({
401
+ required: false,
402
+ type: TableColumnType.BigPositiveNumber,
403
+ canReadOnRelationQuery: true,
404
+ title: "Max Memory Bytes",
405
+ description: "Total memory available to this device (iot_memory_size_bytes). The denominator for the memory usage bar.",
406
+ }),
407
+ Column({
408
+ nullable: true,
409
+ type: ColumnType.BigPositiveNumber,
410
+ transformer: {
411
+ to: (value) => {
412
+ if (value === null || value === undefined) {
413
+ return null;
414
+ }
415
+ return Math.trunc(value).toString();
416
+ },
417
+ from: (value) => {
418
+ if (value === null || value === undefined) {
419
+ return null;
420
+ }
421
+ const parsed = parseInt(value, 10);
422
+ return isNaN(parsed) ? null : parsed;
423
+ },
424
+ },
425
+ }),
426
+ __metadata("design:type", Number)
427
+ ], IoTDevice.prototype, "maxMemoryBytes", void 0);
428
+ __decorate([
429
+ ColumnAccessControl({
430
+ create: [],
431
+ read: READ_PERMISSIONS,
432
+ update: [],
433
+ }),
434
+ TableColumn({
435
+ required: false,
436
+ type: TableColumnType.Number,
437
+ canReadOnRelationQuery: true,
438
+ title: "Latest Memory Percent",
439
+ description: "Most recent memory usage as a percent of maxMemoryBytes. Stored as decimal — mirrors latestCpuPercent — so list views can sort/filter without dividing bigints client-side.",
440
+ }),
441
+ Column({
442
+ nullable: true,
443
+ type: ColumnType.Decimal,
444
+ transformer: {
445
+ to: (value) => {
446
+ if (value === null || value === undefined) {
447
+ return null;
448
+ }
449
+ return value;
450
+ },
451
+ from: (value) => {
452
+ if (value === null || value === undefined) {
453
+ return null;
454
+ }
455
+ if (typeof value === "number") {
456
+ return value;
457
+ }
458
+ const parsed = parseFloat(value);
459
+ return isNaN(parsed) ? null : parsed;
460
+ },
461
+ },
462
+ }),
463
+ __metadata("design:type", Number)
464
+ ], IoTDevice.prototype, "latestMemoryPercent", void 0);
465
+ __decorate([
466
+ ColumnAccessControl({
467
+ create: [],
468
+ read: READ_PERMISSIONS,
469
+ update: [],
470
+ }),
471
+ TableColumn({
472
+ required: false,
473
+ type: TableColumnType.Number,
474
+ canReadOnRelationQuery: true,
475
+ title: "Latest Battery Percent",
476
+ description: "Most recent battery level percent (iot_battery_percent). Stored as decimal so sub-percent precision survives the round trip. Null until the first metric arrives.",
477
+ }),
478
+ Column({
479
+ nullable: true,
480
+ type: ColumnType.Decimal,
481
+ transformer: {
482
+ to: (value) => {
483
+ if (value === null || value === undefined) {
484
+ return null;
485
+ }
486
+ return value;
487
+ },
488
+ from: (value) => {
489
+ if (value === null || value === undefined) {
490
+ return null;
491
+ }
492
+ if (typeof value === "number") {
493
+ return value;
494
+ }
495
+ const parsed = parseFloat(value);
496
+ return isNaN(parsed) ? null : parsed;
497
+ },
498
+ },
499
+ }),
500
+ __metadata("design:type", Number)
501
+ ], IoTDevice.prototype, "latestBatteryPercent", void 0);
502
+ __decorate([
503
+ ColumnAccessControl({
504
+ create: [],
505
+ read: READ_PERMISSIONS,
506
+ update: [],
507
+ }),
508
+ TableColumn({
509
+ required: false,
510
+ type: TableColumnType.Number,
511
+ canReadOnRelationQuery: true,
512
+ title: "Latest Signal Strength Dbm",
513
+ description: "Most recent signal strength in dBm (iot_signal_strength_dbm). Stored as decimal so sub-unit precision survives the round trip. Null until the first metric arrives.",
514
+ }),
515
+ Column({
516
+ nullable: true,
517
+ type: ColumnType.Decimal,
518
+ transformer: {
519
+ to: (value) => {
520
+ if (value === null || value === undefined) {
521
+ return null;
522
+ }
523
+ return value;
524
+ },
525
+ from: (value) => {
526
+ if (value === null || value === undefined) {
527
+ return null;
528
+ }
529
+ if (typeof value === "number") {
530
+ return value;
531
+ }
532
+ const parsed = parseFloat(value);
533
+ return isNaN(parsed) ? null : parsed;
534
+ },
535
+ },
536
+ }),
537
+ __metadata("design:type", Number)
538
+ ], IoTDevice.prototype, "latestSignalStrengthDbm", void 0);
539
+ __decorate([
540
+ ColumnAccessControl({
541
+ create: [],
542
+ read: READ_PERMISSIONS,
543
+ update: [],
544
+ }),
545
+ TableColumn({
546
+ required: false,
547
+ type: TableColumnType.Number,
548
+ canReadOnRelationQuery: true,
549
+ title: "Latest Temperature Celsius",
550
+ description: "Most recent temperature reading in degrees Celsius (iot_temperature_celsius). Stored as decimal so sub-degree precision survives the round trip. Null until the first metric arrives.",
551
+ }),
552
+ Column({
553
+ nullable: true,
554
+ type: ColumnType.Decimal,
555
+ transformer: {
556
+ to: (value) => {
557
+ if (value === null || value === undefined) {
558
+ return null;
559
+ }
560
+ return value;
561
+ },
562
+ from: (value) => {
563
+ if (value === null || value === undefined) {
564
+ return null;
565
+ }
566
+ if (typeof value === "number") {
567
+ return value;
568
+ }
569
+ const parsed = parseFloat(value);
570
+ return isNaN(parsed) ? null : parsed;
571
+ },
572
+ },
573
+ }),
574
+ __metadata("design:type", Number)
575
+ ], IoTDevice.prototype, "latestTemperatureCelsius", void 0);
576
+ __decorate([
577
+ ColumnAccessControl({
578
+ create: [],
579
+ read: READ_PERMISSIONS,
580
+ update: [],
581
+ }),
582
+ TableColumn({
583
+ required: false,
584
+ type: TableColumnType.Date,
585
+ canReadOnRelationQuery: true,
586
+ title: "Metrics Updated At",
587
+ description: "Observed timestamp of the latest metric point. Acts as the monotonic guard for metric updates and the cutoff for staleness rendering.",
588
+ }),
589
+ Column({
590
+ nullable: true,
591
+ type: ColumnType.Date,
592
+ }),
593
+ __metadata("design:type", Date)
594
+ ], IoTDevice.prototype, "metricsUpdatedAt", void 0);
595
+ __decorate([
596
+ ColumnAccessControl({
597
+ create: [],
598
+ read: READ_PERMISSIONS,
599
+ update: [],
600
+ }),
601
+ TableColumn({
602
+ required: true,
603
+ type: TableColumnType.Date,
604
+ canReadOnRelationQuery: true,
605
+ title: "Last Seen At",
606
+ description: "Agent-observed timestamp of the most recent scrape containing this device. Also acts as the monotonic guard for upserts.",
607
+ }),
608
+ Column({
609
+ nullable: false,
610
+ type: ColumnType.Date,
611
+ }),
612
+ __metadata("design:type", Date)
613
+ ], IoTDevice.prototype, "lastSeenAt", void 0);
614
+ __decorate([
615
+ ColumnAccessControl({
616
+ create: [],
617
+ read: READ_PERMISSIONS,
618
+ update: [],
619
+ }),
620
+ TableColumn({
621
+ manyToOneRelationColumn: "createdByUserId",
622
+ type: TableColumnType.Entity,
623
+ modelType: User,
624
+ title: "Created By User",
625
+ description: "Not user-facing; ingest writes as isRoot so this stays null in practice.",
626
+ }),
627
+ ManyToOne(() => {
628
+ return User;
629
+ }, {
630
+ eager: false,
631
+ nullable: true,
632
+ onDelete: "SET NULL",
633
+ orphanedRowAction: "nullify",
634
+ }),
635
+ JoinColumn({ name: "createdByUserId" }),
636
+ __metadata("design:type", User)
637
+ ], IoTDevice.prototype, "createdByUser", void 0);
638
+ __decorate([
639
+ ColumnAccessControl({
640
+ create: [],
641
+ read: READ_PERMISSIONS,
642
+ update: [],
643
+ }),
644
+ TableColumn({
645
+ type: TableColumnType.ObjectID,
646
+ title: "Created By User ID",
647
+ description: "ID of the user who created this row.",
648
+ }),
649
+ Column({
650
+ type: ColumnType.ObjectID,
651
+ nullable: true,
652
+ transformer: ObjectID.getDatabaseTransformer(),
653
+ }),
654
+ __metadata("design:type", ObjectID)
655
+ ], IoTDevice.prototype, "createdByUserId", void 0);
656
+ __decorate([
657
+ ColumnAccessControl({
658
+ create: [],
659
+ read: READ_PERMISSIONS,
660
+ update: [],
661
+ }),
662
+ TableColumn({
663
+ manyToOneRelationColumn: "deletedByUserId",
664
+ type: TableColumnType.Entity,
665
+ modelType: User,
666
+ title: "Deleted By User",
667
+ description: "Relation to the user who deleted this row.",
668
+ }),
669
+ ManyToOne(() => {
670
+ return User;
671
+ }, {
672
+ eager: false,
673
+ nullable: true,
674
+ onDelete: "SET NULL",
675
+ orphanedRowAction: "nullify",
676
+ }),
677
+ JoinColumn({ name: "deletedByUserId" }),
678
+ __metadata("design:type", User)
679
+ ], IoTDevice.prototype, "deletedByUser", void 0);
680
+ __decorate([
681
+ ColumnAccessControl({
682
+ create: [],
683
+ read: READ_PERMISSIONS,
684
+ update: [],
685
+ }),
686
+ TableColumn({
687
+ type: TableColumnType.ObjectID,
688
+ title: "Deleted By User ID",
689
+ description: "ID of the user who deleted this row.",
690
+ }),
691
+ Column({
692
+ type: ColumnType.ObjectID,
693
+ nullable: true,
694
+ transformer: ObjectID.getDatabaseTransformer(),
695
+ }),
696
+ __metadata("design:type", ObjectID)
697
+ ], IoTDevice.prototype, "deletedByUserId", void 0);
698
+ IoTDevice = __decorate([
699
+ TenantColumn("projectId"),
700
+ TableAccessControl({
701
+ create: [],
702
+ read: READ_PERMISSIONS,
703
+ update: [],
704
+ delete: [],
705
+ }),
706
+ CrudApiEndpoint(new Route("/iot-device")),
707
+ TableMetadata({
708
+ tableName: "IoTDevice",
709
+ singularName: "IoT Device",
710
+ pluralName: "IoT Devices",
711
+ icon: IconProp.Cube,
712
+ tableDescription: "Snapshot of an IoT device (sensor, gateway, etc.) as last reported by the IoT fleet. Populated by the telemetry ingest pipeline; not user-editable.",
713
+ }),
714
+ Index(["projectId", "iotFleetId", "kind", "externalId"], {
715
+ unique: true,
716
+ }),
717
+ Entity({
718
+ name: "IoTDevice",
719
+ })
720
+ ], IoTDevice);
721
+ export default IoTDevice;
722
+ //# sourceMappingURL=IoTDevice.js.map