81 lines
3.0 KiB
TypeScript
81 lines
3.0 KiB
TypeScript
// The procedure contracts of the documents module. This file is what another module, a browser and
|
|
// the OpenAPI document may import: schemas and names, no handler and no port.
|
|
//
|
|
// Approving and rejecting a line are not here. They are the proposals module's own procedures
|
|
// (`proposals.proposal.approve`, `.reject`, `.approveMany`), which this module's writer is called
|
|
// from, so a review decision has one implementation, one permission and one audit event whichever
|
|
// screen it was made on (decision AT-D22).
|
|
|
|
import { procedure } from "@conusai-kit/core"
|
|
import { z } from "zod"
|
|
import { DOCUMENT_STATUSES, FAILURE_CODES, PAGE_CLASSES } from "./constants.js"
|
|
import { EXPORT_CREATED, LINE_EDITED, lineViewSchema } from "./lines.js"
|
|
|
|
const inProject = { org: z.string(), workspace: z.string(), project: z.string() }
|
|
|
|
/** A file with no document row yet has been uploaded and not picked up by the job: `queued`. */
|
|
export const documentViewSchema = z.object({
|
|
fileId: z.string(),
|
|
filename: z.string(),
|
|
status: z.enum(["queued", ...DOCUMENT_STATUSES]),
|
|
failureCode: z.enum(FAILURE_CODES).nullable(),
|
|
pageCount: z.number().int().nullable(),
|
|
/** The pages the extraction left out, with the class that excluded each: a reviewer sees what was not read. */
|
|
skippedPages: z.array(z.object({ page: z.number().int().min(1), pageClass: z.enum(PAGE_CLASSES) })),
|
|
/** Lines waiting for a decision, and lines approved: the two numbers a reviewer scans a list for. */
|
|
pending: z.number().int(),
|
|
approved: z.number().int(),
|
|
uploadedAt: z.string(),
|
|
})
|
|
|
|
export type DocumentView = z.output<typeof documentViewSchema>
|
|
|
|
export const documentList = procedure("documents.document.list")
|
|
.kind("read")
|
|
.scope("project")
|
|
.permission("documents.document.read")
|
|
.input(z.object({ ...inProject }))
|
|
.output(z.object({ documents: z.array(documentViewSchema) }))
|
|
.contract()
|
|
|
|
export const documentGet = procedure("documents.document.get")
|
|
.kind("read")
|
|
.scope("project")
|
|
.permission("documents.document.read")
|
|
.input(z.object({ ...inProject, fileId: z.string() }))
|
|
.output(z.object({ document: documentViewSchema, lines: z.array(lineViewSchema) }))
|
|
.contract()
|
|
|
|
export const lineEdit = procedure("documents.line.edit")
|
|
.kind("write")
|
|
.scope("project")
|
|
.permission("documents.line.edit")
|
|
.input(
|
|
z.object({
|
|
...inProject,
|
|
lineId: z.string(),
|
|
label: z.string().min(1).max(200),
|
|
value: z.string().min(1).max(2_000),
|
|
}),
|
|
)
|
|
.output(lineViewSchema)
|
|
.audit(LINE_EDITED)
|
|
.contract()
|
|
|
|
export const exportCreate = procedure("documents.export.create")
|
|
.kind("effect")
|
|
.scope("project")
|
|
.permission("documents.export.create")
|
|
.input(z.object({ ...inProject, fileId: z.string() }))
|
|
.output(
|
|
z.object({
|
|
filename: z.string(),
|
|
contentType: z.string(),
|
|
/** The workbook, standard base64: a procedure's answer has to survive JSON on every transport. */
|
|
body: z.string(),
|
|
lineCount: z.number().int(),
|
|
}),
|
|
)
|
|
.audit(EXPORT_CREATED)
|
|
.contract()
|