You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
wiki/backend/api/schemas/notifications.ts

144 lines
5.0 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

import type { FastifyInstance } from 'fastify'
export async function registerSchemas(app: FastifyInstance): Promise<void> {
/**
* NOTIFICATION - One entry in somebody's inbox
*/
app.addSchema({
$id: 'Notification',
type: 'object',
properties: {
id: { type: 'string', format: 'uuid' },
category: {
type: 'string',
description:
'What kind of notification this is: `watchedPage`, `watchedPageComment`, `commentReply`, `mention`, `reviewRequested`, `pageCreated` or `pageDeleted`.'
},
variant: {
type: 'string',
description:
'What happened, within the category — `edited`, `moved`, `published`, `unpublished`, `scheduled`, `deleted`, `new`, `updated`, `created`, `restored`. The latest one, for an entry that absorbed several events.'
},
count: {
type: 'integer',
description:
'How many events this entry stands for. A page saved ten times while nobody looked is one entry with a count of ten.'
},
pageId: {
type: 'string',
format: 'uuid',
nullable: true,
description: 'The page it is about, while that page exists.'
},
commentId: {
type: 'string',
format: 'uuid',
nullable: true,
description: 'The comment it is about, while that comment exists.'
},
actorId: {
type: 'string',
format: 'uuid',
nullable: true,
description:
'Who did it, while their account exists. Null for a guest, whose name is in `data.actorName`.'
},
data: {
type: 'object',
additionalProperties: true,
description:
'A snapshot of what the entry is about, taken when it happened, so that it can still be drawn after the page has moved or gone: `page` (`id`, `title`, `path`, `locale`), `actorName`, `variants` (every variant absorbed), `previousPath`, `submissionId`, `origin` (`import` or `bulk` when nobody did it by hand), and `excerpt` — a comment’s first lines, present only while the comment exists.'
},
isRead: { type: 'boolean' },
createdAt: { type: 'string', format: 'date-time' },
updatedAt: {
type: 'string',
format: 'date-time',
description: 'When the entry last absorbed an event, which is what the inbox sorts by.'
}
}
})
/**
* NOTIFICATION PREFERENCE - One category, as Profile → Notifications offers it
*/
app.addSchema({
$id: 'NotificationPreference',
type: 'object',
properties: {
key: { type: 'string' },
section: {
type: 'string',
enum: ['watching', 'discussions', 'reviews', 'everything'],
description: 'The heading the Profile screen lists it under.'
},
inApp: { type: 'boolean' },
email: { type: 'boolean' },
defaults: {
type: 'object',
properties: {
inApp: { type: 'boolean' },
email: { type: 'boolean' }
}
}
}
})
/**
* NOTIFICATION SETTINGS - The instance-wide settings, used both ways
*/
app.addSchema({
$id: 'NotificationSettings',
type: 'object',
properties: {
retentionDays: {
type: 'integer',
minimum: 1,
maximum: 3650,
description: 'How many days a notification is kept, read or not.'
},
emailDelay: {
type: 'string',
maxLength: 16,
description:
'How long a notification waits before it is emailed, e.g. `3m`. Whatever else happens to the same thing in the meantime goes into the same email; once emailed, an entry is not emailed about again until it has been read. At most an hour.'
},
mailBatchSize: {
type: 'integer',
minimum: 1,
maximum: 1000,
description: 'How many people one run of the mail task sends to.'
}
}
})
/**
* NOTIFICATION STATUS - How delivery is doing, for the admin screen
*/
app.addSchema({
$id: 'NotificationStatus',
type: 'object',
properties: {
pendingEvents: {
type: 'integer',
description:
'Events not yet turned into notifications. Anything beyond a handful for long means the fan-out is falling behind.'
},
oldestPendingEventAt: { type: 'string', format: 'date-time', nullable: true },
emailsPending: { type: 'integer', description: 'Emails waiting to be sent.' },
emailsSent24h: { type: 'integer' },
emailsFailed24h: {
type: 'integer',
description: 'Emails given up on after repeated failures to hand them to the relay.'
},
isMailConfigured: { type: 'boolean' },
warnings: {
type: 'array',
items: { type: 'string', enum: ['plainHttp', 'wildcardHostname'] },
description:
'`plainHttp`: the base URL links are built with is not HTTPS, which one-click unsubscribe needs to be honoured by Gmail. `wildcardHostname`: a site answers to any hostname and no base URL is set, so its emails have no address to link to and are not sent.'
}
}
})
}