@checkstack/healthcheck-frontend 0.9.0 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,38 @@
1
1
  # @checkstack/healthcheck-frontend
2
2
 
3
+ ## 0.10.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 3dd1914: Migrate health check strategies to VersionedAggregated with \_type discriminator
8
+
9
+ All 13 health check strategies now use `VersionedAggregated` for their `aggregatedResult` property, enabling automatic bucket merging with 100% mathematical fidelity.
10
+
11
+ **Key changes:**
12
+
13
+ - **`_type` discriminator**: All aggregated state objects now include a required `_type` field (`"average"`, `"rate"`, `"counter"`, `"minmax"`) for reliable type detection
14
+ - The `HealthCheckStrategy` interface now requires `aggregatedResult` to be a `VersionedAggregated<AggregatedResultShape>`
15
+ - Strategy/collector `mergeResult` methods return state objects with `_type` (e.g., `{ _type: "average", _sum, _count, avg }`)
16
+ - `mergeAggregatedBucketResults`, `combineBuckets`, and `reaggregateBuckets` now require `registry` and `strategyId` parameters
17
+ - `HealthCheckService` constructor now requires both `registry` and `collectorRegistry` parameters
18
+ - Frontend `extractComputedValue` now uses `_type` discriminator for robust type detection
19
+
20
+ **Breaking Change**: State objects now require `_type`. Merge functions automatically add `_type` to output. The bucket merging functions and `HealthCheckService` now require additional required parameters.
21
+
22
+ ## 0.9.1
23
+
24
+ ### Patch Changes
25
+
26
+ - Updated dependencies [f676e11]
27
+ - @checkstack/ui@1.0.0
28
+ - @checkstack/common@0.6.2
29
+ - @checkstack/auth-frontend@0.5.9
30
+ - @checkstack/dashboard-frontend@0.3.15
31
+ - @checkstack/catalog-common@1.2.7
32
+ - @checkstack/frontend-api@0.3.5
33
+ - @checkstack/healthcheck-common@0.8.2
34
+ - @checkstack/signal-frontend@0.0.12
35
+
3
36
  ## 0.9.0
4
37
 
5
38
  ### Minor Changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@checkstack/healthcheck-frontend",
3
- "version": "0.9.0",
3
+ "version": "0.10.0",
4
4
  "type": "module",
5
5
  "main": "src/index.tsx",
6
6
  "scripts": {
@@ -9,14 +9,14 @@
9
9
  "lint:code": "eslint . --max-warnings 0"
10
10
  },
11
11
  "dependencies": {
12
- "@checkstack/auth-frontend": "0.5.7",
13
- "@checkstack/catalog-common": "1.2.5",
12
+ "@checkstack/auth-frontend": "0.5.8",
13
+ "@checkstack/catalog-common": "1.2.6",
14
14
  "@checkstack/common": "0.6.1",
15
- "@checkstack/dashboard-frontend": "0.3.13",
15
+ "@checkstack/dashboard-frontend": "0.3.14",
16
16
  "@checkstack/frontend-api": "0.3.4",
17
17
  "@checkstack/healthcheck-common": "0.8.1",
18
18
  "@checkstack/signal-frontend": "0.0.11",
19
- "@checkstack/ui": "0.5.2",
19
+ "@checkstack/ui": "0.5.3",
20
20
  "ajv": "^8.17.1",
21
21
  "ajv-formats": "^3.0.1",
22
22
  "date-fns": "^4.1.0",
@@ -17,8 +17,7 @@ import type {
17
17
  * JSON Schema property with healthcheck result-specific x-* extensions.
18
18
  * Uses the generic core type for proper recursive typing.
19
19
  */
20
- export interface ResultSchemaProperty
21
- extends JsonSchemaPropertyCore<ResultSchemaProperty> {
20
+ export interface ResultSchemaProperty extends JsonSchemaPropertyCore<ResultSchemaProperty> {
22
21
  // Result-specific x-* extensions for chart rendering
23
22
  "x-chart-type"?: ChartType;
24
23
  "x-chart-label"?: string;
@@ -58,7 +57,7 @@ export interface ChartField {
58
57
  * @returns Array of chart fields with metadata
59
58
  */
60
59
  export function extractChartFields(
61
- schema: Record<string, unknown> | null | undefined
60
+ schema: Record<string, unknown> | null | undefined,
62
61
  ): ChartField[] {
63
62
  if (!schema) return [];
64
63
 
@@ -72,13 +71,13 @@ export function extractChartFields(
72
71
  if (name === "collectors" && prop.type === "object" && prop.properties) {
73
72
  // Traverse each collector's schema
74
73
  for (const [collectorId, collectorProp] of Object.entries(
75
- prop.properties
74
+ prop.properties,
76
75
  )) {
77
76
  if (collectorProp.type === "object" && collectorProp.properties) {
78
77
  // Extract fields from the collector's result schema
79
78
  const collectorFields = extractFieldsFromProperties(
80
79
  collectorProp.properties,
81
- collectorId
80
+ collectorId,
82
81
  );
83
82
  fields.push(...collectorFields);
84
83
  }
@@ -100,7 +99,7 @@ export function extractChartFields(
100
99
  */
101
100
  function extractFieldsFromProperties(
102
101
  properties: Record<string, ResultSchemaProperty>,
103
- collectorId: string
102
+ collectorId: string,
104
103
  ): ChartField[] {
105
104
  const fields: ChartField[] = [];
106
105
 
@@ -126,7 +125,7 @@ function extractFieldsFromProperties(
126
125
  */
127
126
  function extractSingleField(
128
127
  name: string,
129
- prop: ResultSchemaProperty
128
+ prop: ResultSchemaProperty,
130
129
  ): ChartField {
131
130
  let schemaType = prop.type ?? "unknown";
132
131
  if (prop.type === "array" && prop.items?.type) {
@@ -164,6 +163,7 @@ function formatFieldName(name: string): string {
164
163
  /**
165
164
  * Get the value for a field from a data object.
166
165
  * For strategy-level fields, also searches inside collectors as fallback.
166
+ * Automatically extracts computed values from aggregated state objects.
167
167
  *
168
168
  * @param data - The metadata object
169
169
  * @param fieldName - Simple field name (no dot notation for collector fields)
@@ -172,7 +172,7 @@ function formatFieldName(name: string): string {
172
172
  export function getFieldValue(
173
173
  data: Record<string, unknown> | undefined,
174
174
  fieldName: string,
175
- collectorInstanceId?: string
175
+ collectorInstanceId?: string,
176
176
  ): unknown {
177
177
  if (!data) return undefined;
178
178
 
@@ -184,7 +184,7 @@ export function getFieldValue(
184
184
  if (collectors && typeof collectors === "object") {
185
185
  const collectorData = collectors[collectorInstanceId];
186
186
  if (collectorData && typeof collectorData === "object") {
187
- return collectorData[fieldName];
187
+ return extractComputedValue(collectorData[fieldName]);
188
188
  }
189
189
  }
190
190
  return undefined;
@@ -193,7 +193,7 @@ export function getFieldValue(
193
193
  // For non-collector fields, try direct lookup first
194
194
  const directValue = data[fieldName];
195
195
  if (directValue !== undefined) {
196
- return directValue;
196
+ return extractComputedValue(directValue);
197
197
  }
198
198
 
199
199
  // Fallback: search all collectors for the field (for strategy schema fields)
@@ -205,7 +205,7 @@ export function getFieldValue(
205
205
  if (collectorData && typeof collectorData === "object") {
206
206
  const value = collectorData[fieldName];
207
207
  if (value !== undefined) {
208
- return value;
208
+ return extractComputedValue(value);
209
209
  }
210
210
  }
211
211
  }
@@ -213,3 +213,49 @@ export function getFieldValue(
213
213
 
214
214
  return undefined;
215
215
  }
216
+
217
+ /**
218
+ * Extract the computed value from an aggregated state object.
219
+ * Uses the required `_type` discriminator field for type detection.
220
+ * Logs errors instead of throwing to avoid breaking the app.
221
+ *
222
+ * @param value - Value from API data (unknown type from JSON parsing)
223
+ */
224
+ function extractComputedValue(value: unknown): unknown {
225
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
226
+ return value;
227
+ }
228
+
229
+ const obj = value as Record<string, unknown>;
230
+
231
+ // _type is required for all aggregated state objects
232
+ if (!("_type" in obj)) {
233
+ console.error(
234
+ "[AutoChart] Missing _type discriminator in aggregated state:",
235
+ obj,
236
+ );
237
+ return value;
238
+ }
239
+
240
+ switch (obj._type) {
241
+ case "average": {
242
+ return obj.avg;
243
+ }
244
+ case "rate": {
245
+ return obj.rate;
246
+ }
247
+ case "counter": {
248
+ return obj.count;
249
+ }
250
+ case "minmax": {
251
+ // Default to max for minmax; caller can access min directly if needed
252
+ return obj.max;
253
+ }
254
+ default: {
255
+ console.error(
256
+ `[AutoChart] Unrecognized aggregated state type: ${String(obj._type)}`,
257
+ );
258
+ return value;
259
+ }
260
+ }
261
+ }