mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-09 13:01:00 +00:00
fix(openapi): declare what the measurement list and create answers carry
The sleep list rows of GET /api/measurements carry the main night's stage minutes, time in bed, time awake and awakenings, and the aggregate buckets carry the bucket's lowest and highest reading; none of these were in the contract. The create answer's union tried the plain row before the named sleep-stage result, so a contract check read a named-stage answer as a plain row and dropped its status. The responses are unchanged; the contract now says what they hold.
This commit is contained in:
1 parent
899b86f4d4
commit
f7051ee15f
2 files changed
+138
-2
No files matched your search
+89
-1
@@ -48307,6 +48307,32 @@ components:
|
||||
description: Time asleep across those naps, in minutes.
|
||||
type: number
|
||||
minimum: 0
|
||||
sleepStages:
|
||||
description: The main night's minutes per stage (`IN_BED`, `ASLEEP`, `AWAKE`, `CORE`, `DEEP`, `REM`), each the union of
|
||||
that stage's spans; empty on a day of naps alone.
|
||||
type: object
|
||||
propertyNames:
|
||||
type: string
|
||||
additionalProperties:
|
||||
type: number
|
||||
minimum: 0
|
||||
inBedMinutes:
|
||||
description: The main night's time in bed in minutes, or null when no in-bed span was recorded.
|
||||
anyOf:
|
||||
- type: number
|
||||
minimum: 0
|
||||
- type: "null"
|
||||
awakeMinutes:
|
||||
description: The main night's time awake in bed in minutes, or null when no awake span was recorded.
|
||||
anyOf:
|
||||
- type: number
|
||||
minimum: 0
|
||||
- type: "null"
|
||||
awakenings:
|
||||
description: Awake spans between the main night's first and last time asleep.
|
||||
type: integer
|
||||
minimum: 0
|
||||
maximum: 9007199254740991
|
||||
required:
|
||||
- id
|
||||
- type
|
||||
@@ -49077,6 +49103,32 @@ components:
|
||||
description: Time asleep across those naps, in minutes.
|
||||
type: number
|
||||
minimum: 0
|
||||
sleepStages:
|
||||
description: The main night's minutes per stage (`IN_BED`, `ASLEEP`, `AWAKE`, `CORE`, `DEEP`, `REM`), each the union of
|
||||
that stage's spans; empty on a day of naps alone.
|
||||
type: object
|
||||
propertyNames:
|
||||
type: string
|
||||
additionalProperties:
|
||||
type: number
|
||||
minimum: 0
|
||||
inBedMinutes:
|
||||
description: The main night's time in bed in minutes, or null when no in-bed span was recorded.
|
||||
anyOf:
|
||||
- type: number
|
||||
minimum: 0
|
||||
- type: "null"
|
||||
awakeMinutes:
|
||||
description: The main night's time awake in bed in minutes, or null when no awake span was recorded.
|
||||
anyOf:
|
||||
- type: number
|
||||
minimum: 0
|
||||
- type: "null"
|
||||
awakenings:
|
||||
description: Awake spans between the main night's first and last time asleep.
|
||||
type: integer
|
||||
minimum: 0
|
||||
maximum: 9007199254740991
|
||||
required:
|
||||
- id
|
||||
- type
|
||||
@@ -49105,6 +49157,16 @@ components:
|
||||
type: integer
|
||||
minimum: 0
|
||||
maximum: 9007199254740991
|
||||
minValue:
|
||||
description: The lowest reading in the bucket; absent on a summed (cumulative) type.
|
||||
type:
|
||||
- number
|
||||
- "null"
|
||||
maxValue:
|
||||
description: The highest reading in the bucket; absent on a summed (cumulative) type.
|
||||
type:
|
||||
- number
|
||||
- "null"
|
||||
unit:
|
||||
type: string
|
||||
required:
|
||||
@@ -49282,6 +49344,32 @@ components:
|
||||
description: Time asleep across those naps, in minutes.
|
||||
type: number
|
||||
minimum: 0
|
||||
sleepStages:
|
||||
description: The main night's minutes per stage (`IN_BED`, `ASLEEP`, `AWAKE`, `CORE`, `DEEP`, `REM`), each the union of
|
||||
that stage's spans; empty on a day of naps alone.
|
||||
type: object
|
||||
propertyNames:
|
||||
type: string
|
||||
additionalProperties:
|
||||
type: number
|
||||
minimum: 0
|
||||
inBedMinutes:
|
||||
description: The main night's time in bed in minutes, or null when no in-bed span was recorded.
|
||||
anyOf:
|
||||
- type: number
|
||||
minimum: 0
|
||||
- type: "null"
|
||||
awakeMinutes:
|
||||
description: The main night's time awake in bed in minutes, or null when no awake span was recorded.
|
||||
anyOf:
|
||||
- type: number
|
||||
minimum: 0
|
||||
- type: "null"
|
||||
awakenings:
|
||||
description: Awake spans between the main night's first and last time asleep.
|
||||
type: integer
|
||||
minimum: 0
|
||||
maximum: 9007199254740991
|
||||
status:
|
||||
type: string
|
||||
enum:
|
||||
@@ -49306,11 +49394,11 @@ components:
|
||||
properties:
|
||||
data:
|
||||
anyOf:
|
||||
- $ref: "#/components/schemas/NamedSleepStageMeasurement"
|
||||
- $ref: "#/components/schemas/MeasurementResource"
|
||||
- type: array
|
||||
items:
|
||||
$ref: "#/components/schemas/MeasurementResource"
|
||||
- $ref: "#/components/schemas/NamedSleepStageMeasurement"
|
||||
error:
|
||||
type: "null"
|
||||
meta:
|
||||
|
||||
@@ -356,6 +356,36 @@ export const measurementResource = z
|
||||
.nonnegative()
|
||||
.optional()
|
||||
.describe("Time asleep across those naps, in minutes."),
|
||||
sleepStages: z
|
||||
.record(z.string(), z.number().nonnegative())
|
||||
.optional()
|
||||
.describe(
|
||||
"The main night's minutes per stage (`IN_BED`, `ASLEEP`, `AWAKE`, `CORE`, `DEEP`, `REM`), each the union of that stage's spans; empty on a day of naps alone.",
|
||||
),
|
||||
inBedMinutes: z
|
||||
.number()
|
||||
.nonnegative()
|
||||
.nullable()
|
||||
.optional()
|
||||
.describe(
|
||||
"The main night's time in bed in minutes, or null when no in-bed span was recorded.",
|
||||
),
|
||||
awakeMinutes: z
|
||||
.number()
|
||||
.nonnegative()
|
||||
.nullable()
|
||||
.optional()
|
||||
.describe(
|
||||
"The main night's time awake in bed in minutes, or null when no awake span was recorded.",
|
||||
),
|
||||
awakenings: z
|
||||
.number()
|
||||
.int()
|
||||
.nonnegative()
|
||||
.optional()
|
||||
.describe(
|
||||
"Awake spans between the main night's first and last time asleep.",
|
||||
),
|
||||
})
|
||||
.meta({
|
||||
id: "MeasurementResource",
|
||||
@@ -388,6 +418,20 @@ const aggregatedMeasurementBucket = z
|
||||
value: z.number().describe("The bucket's aggregated value."),
|
||||
measuredAt: isoDateTime().describe("Bucket start."),
|
||||
count: z.number().int().nonnegative().optional(),
|
||||
minValue: z
|
||||
.number()
|
||||
.nullable()
|
||||
.optional()
|
||||
.describe(
|
||||
"The lowest reading in the bucket; absent on a summed (cumulative) type.",
|
||||
),
|
||||
maxValue: z
|
||||
.number()
|
||||
.nullable()
|
||||
.optional()
|
||||
.describe(
|
||||
"The highest reading in the bucket; absent on a summed (cumulative) type.",
|
||||
),
|
||||
unit: z.string().optional(),
|
||||
})
|
||||
.meta({
|
||||
@@ -895,11 +939,15 @@ export const measurementPaths: NonNullable<ZodOpenApiObject["paths"]> = {
|
||||
"Created. A single resource for the object body; an array of resources, in request order, for the array body; for a named sleep-stage body, the stored row with `status: inserted`.",
|
||||
content: {
|
||||
"application/json": {
|
||||
// The named-stage result first: it requires `status`, so a
|
||||
// plain row falls through to `measurementResource`, while a
|
||||
// union that tried the plain row first would read a named-stage
|
||||
// answer as a plain row and drop its `status`.
|
||||
schema: dataEnvelope(
|
||||
z.union([
|
||||
namedSleepStageResult,
|
||||
measurementResource,
|
||||
z.array(measurementResource),
|
||||
namedSleepStageResult,
|
||||
]),
|
||||
"CreateMeasurementResponse",
|
||||
),
|
||||
|
||||
Reference in new issue
Block a user