106 lines
3.6 KiB
TypeScript
106 lines
3.6 KiB
TypeScript
// The procedure contracts of the notes module: schemas and names, no handler and no port.
|
|
//
|
|
// An attachment is uploaded through the files module's own upload procedures (`files.file.beginUpload`,
|
|
// `files.file.putPart` and `files.file.completeUpload`: the bytes go to the platform's Blob store,
|
|
// which is where the usage fact and the audit event of an upload are recorded), and then linked to a
|
|
// note by `notes.attachment.add`. This module never takes bytes.
|
|
|
|
import { procedure } from "@conusai-kit/core"
|
|
import { z } from "zod"
|
|
|
|
const inProject = { org: z.string(), workspace: z.string(), project: z.string() }
|
|
const title = z.string().min(1).max(200)
|
|
const body = z.string().max(20_000)
|
|
|
|
export const noteViewSchema = z.object({
|
|
noteId: z.string(),
|
|
title: z.string(),
|
|
body: z.string(),
|
|
/** What `notes.note.update` is called with as `expectedVersion`. */
|
|
version: z.number().int(),
|
|
createdBy: z.string(),
|
|
createdAt: z.string(),
|
|
updatedAt: z.string(),
|
|
attachmentCount: z.number().int(),
|
|
})
|
|
|
|
export type NoteView = z.output<typeof noteViewSchema>
|
|
|
|
export const attachmentViewSchema = z.object({
|
|
attachmentId: z.string(),
|
|
fileId: z.string(),
|
|
filename: z.string(),
|
|
contentType: z.string(),
|
|
size: z.number().int(),
|
|
attachedAt: z.string(),
|
|
})
|
|
|
|
export type AttachmentView = z.output<typeof attachmentViewSchema>
|
|
|
|
export const noteList = procedure("notes.note.list")
|
|
.kind("read")
|
|
.scope("project")
|
|
.permission("notes.note.read")
|
|
.tool()
|
|
.input(z.object({ ...inProject, cursor: z.string().optional(), limit: z.number().int().min(1).max(200).optional() }))
|
|
.output(z.object({ notes: z.array(noteViewSchema), cursor: z.string().optional(), hasMore: z.boolean() }))
|
|
.contract()
|
|
|
|
export const noteGet = procedure("notes.note.get")
|
|
.kind("read")
|
|
.scope("project")
|
|
.permission("notes.note.read")
|
|
.input(z.object({ ...inProject, noteId: z.string() }))
|
|
.output(
|
|
z.object({
|
|
note: noteViewSchema,
|
|
attachments: z.array(attachmentViewSchema),
|
|
/** The feature flag's answer for this project, so a page does not offer what a call would refuse. */
|
|
attachmentsEnabled: z.boolean(),
|
|
}),
|
|
)
|
|
.contract()
|
|
|
|
// No `.audit()` and no `.usage()` on the write contracts: this module's audit events and usage
|
|
// facts are written by the subscribers to its outbox records (core/subscribers.ts), which is the
|
|
// exactly-once path — the transport's own `.audit()`/`.usage()` recording would write each one a
|
|
// second time (and under a different customer key).
|
|
|
|
export const noteCreate = procedure("notes.note.create")
|
|
.kind("write")
|
|
.scope("project")
|
|
.permission("notes.note.write")
|
|
.input(z.object({ ...inProject, title, body }))
|
|
.output(noteViewSchema)
|
|
.contract()
|
|
|
|
export const noteUpdate = procedure("notes.note.update")
|
|
.kind("write")
|
|
.scope("project")
|
|
.permission("notes.note.write")
|
|
.input(z.object({ ...inProject, noteId: z.string(), title, body, expectedVersion: z.number().int().min(1) }))
|
|
.output(noteViewSchema)
|
|
.contract()
|
|
|
|
export const noteDelete = procedure("notes.note.delete")
|
|
.kind("write")
|
|
.scope("project")
|
|
.permission("notes.note.delete")
|
|
.input(z.object({ ...inProject, noteId: z.string() }))
|
|
.contract()
|
|
|
|
export const attachmentAdd = procedure("notes.attachment.add")
|
|
.kind("write")
|
|
.scope("project")
|
|
.permission("notes.attachment.write")
|
|
.input(z.object({ ...inProject, noteId: z.string(), fileId: z.string() }))
|
|
.output(attachmentViewSchema)
|
|
.contract()
|
|
|
|
export const attachmentRemove = procedure("notes.attachment.remove")
|
|
.kind("write")
|
|
.scope("project")
|
|
.permission("notes.attachment.write")
|
|
.input(z.object({ ...inProject, noteId: z.string(), attachmentId: z.string() }))
|
|
.contract()
|