Add Postbox message authoring and concurrency

This commit is contained in:
2026-07-31 18:40:39 +02:00
parent 0b6ebc3c74
commit dc6f81dd33
12 changed files with 1392 additions and 68 deletions
+78 -20
View File
@@ -40,6 +40,8 @@ export type PostboxDirectoryItem = {
holder_count: number;
vacant: boolean;
access?: PostboxAccessDecision | null;
resource_revision: number;
etag: string;
};
export type PostboxParticipant = {
@@ -78,6 +80,8 @@ export type PostboxMessage = {
producer_module?: string | null;
producer_resource_type?: string | null;
producer_resource_id?: string | null;
in_reply_to_message_id?: string | null;
replaces_message_id?: string | null;
encryption_profile: string;
key_epoch: number;
ciphertext_ref?: string | null;
@@ -92,6 +96,8 @@ export type PostboxGrouping = {
name: string;
is_default: boolean;
postbox_ids: string[];
resource_revision: number;
etag: string;
created_at: string;
updated_at: string;
};
@@ -188,6 +194,8 @@ export type PostboxTemplate = {
description?: string | null;
status: string;
current_revision: number;
resource_revision: number;
etag: string;
published_revision_id?: string | null;
revisions: PostboxTemplateRevision[];
created_at: string;
@@ -221,6 +229,21 @@ export type PostboxExactCreatePayload = {
classification: string;
};
export type PostboxMessageAuthoringPayload = {
idempotency_key: string;
subject: string;
body_text?: string | null;
classification: string;
participants: PostboxParticipant[];
attachments: PostboxAttachment[];
metadata: Record<string, unknown>;
};
type PostboxGroupingPayload = Pick<
PostboxGrouping,
"name" | "is_default" | "postbox_ids"
>;
export async function listPostboxes(settings: ApiSettings): Promise<PostboxDirectoryItem[]> {
const response = await apiFetch<{ postboxes: PostboxDirectoryItem[] }>(
settings,
@@ -271,6 +294,29 @@ export function markPostboxMessage(
);
}
export function createPostboxMessage(
settings: ApiSettings,
postboxId: string,
payload: PostboxMessageAuthoringPayload
): Promise<PostboxMessage> {
return apiPostJson(settings, "/api/v1/postbox/messages", {
...payload,
postbox_id: postboxId
});
}
export function replyToPostboxMessage(
settings: ApiSettings,
messageId: string,
payload: PostboxMessageAuthoringPayload
): Promise<PostboxMessage> {
return apiPostJson(
settings,
`/api/v1/postbox/messages/${encodeURIComponent(messageId)}/replies`,
payload
);
}
export async function listPostboxGroupings(settings: ApiSettings): Promise<PostboxGrouping[]> {
const response = await apiFetch<{ groupings: PostboxGrouping[] }>(
settings,
@@ -281,34 +327,39 @@ export async function listPostboxGroupings(settings: ApiSettings): Promise<Postb
export function createPostboxGrouping(
settings: ApiSettings,
payload: Omit<PostboxGrouping, "id" | "created_at" | "updated_at">
payload: PostboxGroupingPayload
): Promise<PostboxGrouping> {
return apiPostJson(settings, "/api/v1/postbox/groupings", payload);
}
export function updatePostboxGrouping(
settings: ApiSettings,
groupingId: string,
payload: Omit<PostboxGrouping, "id" | "created_at" | "updated_at">
grouping: PostboxGrouping,
payload: PostboxGroupingPayload
): Promise<PostboxGrouping> {
return apiFetch(
settings,
`/api/v1/postbox/groupings/${encodeURIComponent(groupingId)}`,
`/api/v1/postbox/groupings/${encodeURIComponent(grouping.id)}`,
{
method: "PUT",
body: JSON.stringify(payload)
headers: { "If-Match": grouping.etag },
body: JSON.stringify({ ...payload, base_revision: grouping.resource_revision })
}
);
}
export function deletePostboxGrouping(
settings: ApiSettings,
groupingId: string
grouping: PostboxGrouping
): Promise<void> {
return apiFetch(
settings,
`/api/v1/postbox/groupings/${encodeURIComponent(groupingId)}`,
{ method: "DELETE" }
`/api/v1/postbox/groupings/${encodeURIComponent(grouping.id)}`,
{
method: "DELETE",
headers: { "If-Match": grouping.etag },
body: JSON.stringify({ base_revision: grouping.resource_revision })
}
);
}
@@ -338,12 +389,16 @@ export function createExactPostbox(
export function archivePostbox(
settings: ApiSettings,
postboxId: string
postbox: PostboxDirectoryItem
): Promise<PostboxDirectoryItem> {
return apiFetch(
settings,
`/api/v1/postbox/admin/postboxes/${encodeURIComponent(postboxId)}`,
{ method: "DELETE" }
`/api/v1/postbox/admin/postboxes/${encodeURIComponent(postbox.id)}`,
{
method: "DELETE",
headers: { "If-Match": postbox.etag },
body: JSON.stringify({ base_revision: postbox.resource_revision })
}
);
}
@@ -364,36 +419,39 @@ export function createPostboxTemplate(
export function revisePostboxTemplate(
settings: ApiSettings,
templateId: string,
template: PostboxTemplate,
payload: PostboxTemplateRevisionPayload
): Promise<PostboxTemplate> {
return apiPostJson(
settings,
`/api/v1/postbox/admin/templates/${encodeURIComponent(templateId)}/revisions`,
payload
`/api/v1/postbox/admin/templates/${encodeURIComponent(template.id)}/revisions`,
{ ...payload, base_revision: template.resource_revision },
{ headers: { "If-Match": template.etag } }
);
}
export function publishPostboxTemplate(
settings: ApiSettings,
templateId: string,
template: PostboxTemplate,
revision?: number
): Promise<PostboxTemplate> {
return apiPostJson(
settings,
`/api/v1/postbox/admin/templates/${encodeURIComponent(templateId)}/publish`,
{ revision: revision ?? null }
`/api/v1/postbox/admin/templates/${encodeURIComponent(template.id)}/publish`,
{ revision: revision ?? null, base_revision: template.resource_revision },
{ headers: { "If-Match": template.etag } }
);
}
export function retirePostboxTemplate(
settings: ApiSettings,
templateId: string
template: PostboxTemplate
): Promise<PostboxTemplate> {
return apiPostJson(
settings,
`/api/v1/postbox/admin/templates/${encodeURIComponent(templateId)}/retire`,
{}
`/api/v1/postbox/admin/templates/${encodeURIComponent(template.id)}/retire`,
{ base_revision: template.resource_revision },
{ headers: { "If-Match": template.etag } }
);
}