diff --git a/docs/api/openapi.yaml b/docs/api/openapi.yaml index 574eeb12f..3c83adf26 100644 --- a/docs/api/openapi.yaml +++ b/docs/api/openapi.yaml @@ -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: diff --git a/src/lib/openapi/routes/measurements.ts b/src/lib/openapi/routes/measurements.ts index 88706b03a..8415c13b8 100644 --- a/src/lib/openapi/routes/measurements.ts +++ b/src/lib/openapi/routes/measurements.ts @@ -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 = { "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", ),