mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-12 06:06:10 +00:00
Add an optional hex liveActivityPushToken to device registration. The iOS client registers the current per-Activity ActivityKit push token so the server can address a Live Activity update or end push on a medication-intake mutation, and sends null to clear it when no Activity is running. Following the medicationDelivery override convention, the field is only touched when present, so an ordinary re-register keeps the prior value. Regenerate the OpenAPI contract.
96 lines
3.3 KiB
TypeScript
96 lines
3.3 KiB
TypeScript
/**
|
|
* OpenAPI route table — device (APNs) registration.
|
|
*
|
|
* Part of the OpenAPI route table; aggregated in `./index.ts`.
|
|
* Schemas come from `src/lib/validations/*` where shared with the
|
|
* runtime request parsing, so the wire contract stays single-source.
|
|
*/
|
|
import { z } from "zod/v4";
|
|
import type { ZodOpenApiObject } from "zod-openapi";
|
|
import { dataEnvelope, errorEnvelope, stdResponses } from "./shared";
|
|
|
|
const deviceRegisterRequest = z
|
|
.object({
|
|
token: z
|
|
.string()
|
|
.min(8)
|
|
.max(512)
|
|
.regex(/^[A-Za-z0-9+/=._:-]+$/)
|
|
.describe("Generic device identifier (legacy; APNs token below)."),
|
|
bundleId: z.string().min(1).max(128),
|
|
locale: z.string().min(2).max(16).optional(),
|
|
appVersion: z.string().min(1).max(32).optional(),
|
|
model: z.string().min(1).max(64).optional(),
|
|
apnsToken: z
|
|
.string()
|
|
.min(8)
|
|
.max(256)
|
|
.regex(/^[A-Fa-f0-9]+$/)
|
|
.optional()
|
|
.describe(
|
|
"Hex-encoded APNs device token. Must be paired with `apnsEnvironment`.",
|
|
),
|
|
apnsEnvironment: z
|
|
.enum(["sandbox", "production"])
|
|
.optional()
|
|
.describe(
|
|
"Gateway the iOS client received `apnsToken` from. Server never auto-detects.",
|
|
),
|
|
medicationDelivery: z
|
|
.enum(["server", "client"])
|
|
.nullable()
|
|
.optional()
|
|
.describe(
|
|
'v1.7.0 per-device medication-delivery override. NULL / omitted = inherit the user-level roaming default. "server" forces server APNs for this device; "client" forces local. Stored + echoed; cron suppression stays user-level.',
|
|
),
|
|
liveActivityPushToken: z
|
|
.string()
|
|
.min(8)
|
|
.max(256)
|
|
.regex(/^[A-Fa-f0-9]+$/)
|
|
.nullable()
|
|
.optional()
|
|
.describe(
|
|
"v1.17.1 (#22) hex-encoded ActivityKit Live Activity push token (distinct from the device APNs token). The server addresses a Live Activity update / end push on a medication-intake mutation. Omitted = keep the prior value; null = clear it when the Activity ends.",
|
|
),
|
|
})
|
|
.meta({
|
|
id: "DeviceRegisterRequest",
|
|
description:
|
|
"Native device registration. Re-registering an APNs token belonging to another user returns 409 (cross-user-hijack guard).",
|
|
});
|
|
|
|
export const devicePaths: NonNullable<ZodOpenApiObject["paths"]> = {
|
|
"/api/devices": {
|
|
post: {
|
|
tags: ["Devices"],
|
|
summary: "Register native device + APNs token",
|
|
description:
|
|
"Idempotent upsert by `token`. APNs token + environment are paired — supplying one without the other returns 422. Cross-user re-registration of either identifier returns 409.",
|
|
requestBody: {
|
|
required: true,
|
|
content: { "application/json": { schema: deviceRegisterRequest } },
|
|
},
|
|
responses: {
|
|
"201": {
|
|
description: "Device registered or refreshed.",
|
|
content: {
|
|
"application/json": {
|
|
schema: dataEnvelope(
|
|
z.object({ id: z.string() }),
|
|
"DeviceRegisterResponse",
|
|
),
|
|
},
|
|
},
|
|
},
|
|
"409": {
|
|
description:
|
|
"Device or APNs token already registered to another user.",
|
|
content: { "application/json": { schema: errorEnvelope } },
|
|
},
|
|
...stdResponses,
|
|
},
|
|
},
|
|
},
|
|
};
|