@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 +33 -0
- package/package.json +5 -5
- package/src/auto-charts/schema-parser.ts +57 -11
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.
|
|
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.
|
|
13
|
-
"@checkstack/catalog-common": "1.2.
|
|
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.
|
|
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.
|
|
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
|
+
}
|