Spaces:
Sleeping
Sleeping
File size: 2,142 Bytes
cb43fbd | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | import { z } from 'zod';
/**
* System-notice API contract — the /api/system-notices endpoints.
*
* Notices are server-side announcements (release notes, onboarding hints, ...)
* defined in a static registry. The server evaluates each notice's conditions
* for the current user and returns only the active, non-dismissed ones, sorted
* by priority/severity/date. The DTO sent to the client is the notice minus the
* server-only fields (conditions, publishedAt, version bounds, priority) — see
* SystemNoticeDTO in server/src/systemNotices/types.ts, which this mirrors.
*
* The bespoke 404 `{ error: 'NOTICE_NOT_FOUND' }` body and the 204 dismiss
* response are reproduced in the controller, not derived from this schema.
*/
export const noticeDisplaySchema = z.enum(['modal', 'banner', 'toast']);
export const noticeSeveritySchema = z.enum(['info', 'warn', 'critical']);
const noticeMediaSchema = z.object({
src: z.string(),
srcDark: z.string().optional(),
altKey: z.string(),
placement: z.enum(['hero', 'inline']).optional(),
aspectRatio: z.string().optional(),
});
const noticeHighlightSchema = z.object({
labelKey: z.string(),
iconName: z.string().optional(),
});
/** Call-to-action: either a navigation link or an in-app action. */
const noticeCtaSchema = z.discriminatedUnion('kind', [
z.object({ kind: z.literal('nav'), labelKey: z.string(), href: z.string() }),
z.object({
kind: z.literal('action'),
labelKey: z.string(),
actionId: z.string(),
dismissOnAction: z.boolean().optional(),
}),
]);
/** The client-facing notice (server-evaluated; conditions/versioning stripped). */
export const systemNoticeDtoSchema = z.object({
id: z.string(),
display: noticeDisplaySchema,
severity: noticeSeveritySchema,
titleKey: z.string(),
bodyKey: z.string(),
bodyParams: z.record(z.string(), z.string()).optional(),
icon: z.string().optional(),
media: noticeMediaSchema.optional(),
highlights: z.array(noticeHighlightSchema).optional(),
cta: noticeCtaSchema.optional(),
dismissible: z.boolean(),
});
export type SystemNoticeDto = z.infer<typeof systemNoticeDtoSchema>;
|