205 lines
7.1 KiB
TypeScript
205 lines
7.1 KiB
TypeScript
// Generated SDK adapter. Production dispatch requires a server-prepared request binding.
|
|
|
|
import { businessAppError, type Client, requestBusinessBinding, toBusinessError } from "@conusai-kit/business"
|
|
import type { Container, ProcedureKind } from "@conusai-kit/core"
|
|
import {
|
|
archiveAddVersion,
|
|
archiveCreateRetentionClass,
|
|
archiveDisposeDocument,
|
|
archiveFindDocuments,
|
|
archiveGetDocument,
|
|
archiveListDisposalDue,
|
|
archiveListRetentionClasses,
|
|
archiveListVersions,
|
|
archiveRegisterDocument,
|
|
archiveSetLegalHold,
|
|
type Document,
|
|
type DocumentVersion,
|
|
type Receipt,
|
|
type RetentionClass,
|
|
type VersionInput,
|
|
} from "@conusai-sdk/archive"
|
|
import { createClient } from "@conusai-sdk/archive/client"
|
|
import type { DocumentReceipt, DocumentView, RetentionClassView, VersionFacts, VersionView } from "../contract/index.js"
|
|
import { ARCHIVE_SERVICE, type ArchiveReads, type ArchiveService, archiveReadsOf } from "../core/ports.js"
|
|
|
|
const documentView = (document: Document): DocumentView => ({
|
|
documentId: document.id,
|
|
title: document.title,
|
|
kind: document.kind ?? null,
|
|
retentionClass: document.retention_class,
|
|
legalHold: document.legal_hold,
|
|
status: document.status as DocumentView["status"],
|
|
disposed: document.status !== "active" || Boolean(document.erased_at),
|
|
revision: String(document.revision),
|
|
createdAt: document.created_at,
|
|
lastVersionAt: document.last_version_at,
|
|
disposedAt: document.disposed_at ?? null,
|
|
})
|
|
|
|
const versionView = (version: DocumentVersion): VersionView => ({
|
|
versionId: version.id,
|
|
sequence: Number(version.sequence),
|
|
sha256: version.sha256,
|
|
mediaType: version.media_type,
|
|
size: String(version.size),
|
|
createdAt: version.created_at,
|
|
})
|
|
|
|
const retentionView = (retention: RetentionClass): RetentionClassView => ({
|
|
code: retention.code,
|
|
keepFor: retention.keep_for,
|
|
from: retention.from as RetentionClassView["from"],
|
|
createdAt: retention.created_at,
|
|
})
|
|
|
|
const versionInput = (version: VersionFacts): VersionInput => ({
|
|
sha256: version.sha256,
|
|
media_type: version.mediaType,
|
|
size: BigInt(version.size),
|
|
blob_ref: version.blobRef,
|
|
})
|
|
|
|
const receiptView = (receipt: Receipt): DocumentReceipt => ({
|
|
documentId: receipt.id,
|
|
revision: String(receipt.revision ?? 0),
|
|
})
|
|
|
|
/** What a generated operation answered: its data, or the kit's typed app error for the refusal. */
|
|
async function answer<T>(
|
|
call: Promise<{ data?: T; error?: unknown; response?: Response }>,
|
|
): Promise<Exclude<T, undefined>> {
|
|
let result: { data?: T; error?: unknown; response?: Response }
|
|
try {
|
|
result = await call
|
|
} catch (error) {
|
|
throw businessAppError(toBusinessError(error, undefined))
|
|
}
|
|
if (result.error !== undefined || result.data === undefined) {
|
|
throw businessAppError(toBusinessError(result.error, result.response))
|
|
}
|
|
return result.data as Exclude<T, undefined>
|
|
}
|
|
|
|
const pageQuery = (query: { after?: string; limit: number }) => ({
|
|
...(query.after === undefined ? {} : { after: query.after }),
|
|
limit: BigInt(query.limit),
|
|
})
|
|
|
|
const pageOf = <S, T>(page: { data: S[]; next_after?: string | null }, view: (row: S) => T) => ({
|
|
rows: page.data.map(view),
|
|
...(page.next_after ? { after: page.next_after } : {}),
|
|
})
|
|
|
|
/** The port over one client, in one organization. */
|
|
export function sdkArchiveService(binding: { client: Client; orgSlug: string }): ArchiveService {
|
|
const { client } = binding
|
|
const org = { org_slug: binding.orgSlug }
|
|
return {
|
|
async listDocuments(query) {
|
|
const page = await answer(
|
|
archiveFindDocuments({
|
|
client,
|
|
path: org,
|
|
query: { ...(query.q === undefined ? {} : { q: query.q }), ...pageQuery(query) },
|
|
}),
|
|
)
|
|
return pageOf(page, documentView)
|
|
},
|
|
async getDocument(documentId) {
|
|
return documentView(await answer(archiveGetDocument({ client, path: { ...org, document_id: documentId } })))
|
|
},
|
|
async listVersions(documentId, query) {
|
|
const page = await answer(
|
|
archiveListVersions({ client, path: { ...org, document_id: documentId }, query: pageQuery(query) }),
|
|
)
|
|
return pageOf(page, versionView)
|
|
},
|
|
async listRetentionClasses(query) {
|
|
const page = await answer(archiveListRetentionClasses({ client, path: org, query: pageQuery(query) }))
|
|
return pageOf(page, retentionView)
|
|
},
|
|
async listDisposalDue(query) {
|
|
const page = await answer(archiveListDisposalDue({ client, path: org, query: pageQuery(query) }))
|
|
return pageOf(page, documentView)
|
|
},
|
|
async registerDocument(input) {
|
|
const receipt = await answer(
|
|
archiveRegisterDocument({
|
|
client,
|
|
path: org,
|
|
body: {
|
|
title: input.title,
|
|
...(input.kind === undefined ? {} : { kind: input.kind }),
|
|
retention_class: input.retentionClass,
|
|
version: versionInput(input.version),
|
|
idempotency_key: input.key,
|
|
},
|
|
}),
|
|
)
|
|
return receiptView(receipt)
|
|
},
|
|
async addVersion(input) {
|
|
const receipt = await answer(
|
|
archiveAddVersion({
|
|
client,
|
|
path: { ...org, document_id: input.documentId },
|
|
body: {
|
|
revision: BigInt(input.revision),
|
|
version: versionInput(input.version),
|
|
idempotency_key: input.key,
|
|
},
|
|
}),
|
|
)
|
|
return receiptView(receipt)
|
|
},
|
|
async setLegalHold(input) {
|
|
const receipt = await answer(
|
|
archiveSetLegalHold({
|
|
client,
|
|
path: { ...org, document_id: input.documentId },
|
|
body: { revision: BigInt(input.revision), legal_hold: input.legalHold, idempotency_key: input.key },
|
|
}),
|
|
)
|
|
return receiptView(receipt)
|
|
},
|
|
async disposeDocument(input) {
|
|
const receipt = await answer(
|
|
archiveDisposeDocument({
|
|
client,
|
|
path: { ...org, document_id: input.documentId },
|
|
body: { revision: BigInt(input.revision), idempotency_key: input.key },
|
|
}),
|
|
)
|
|
return receiptView(receipt)
|
|
},
|
|
async createRetentionClass(input) {
|
|
await answer(
|
|
archiveCreateRetentionClass({
|
|
client,
|
|
path: org,
|
|
body: { code: input.code, keep_for: input.keepFor, from: input.from, idempotency_key: input.key },
|
|
}),
|
|
)
|
|
},
|
|
}
|
|
}
|
|
|
|
/**
|
|
* The service a handler of `kind` may use: the bound one (the token's view for the kind applies), or
|
|
* the current verified request's, narrowed to its reads for a `read` or `write` handler as the token would.
|
|
*/
|
|
export function archiveServiceOf(container: Container, kind: "effect"): ArchiveService
|
|
export function archiveServiceOf(container: Container, kind: ProcedureKind): ArchiveReads
|
|
export function archiveServiceOf(container: Container, kind: ProcedureKind): ArchiveReads {
|
|
if (container.has(ARCHIVE_SERVICE)) return container.resolve(ARCHIVE_SERVICE) as ArchiveReads
|
|
let service: ArchiveService
|
|
try {
|
|
const binding = requestBusinessBinding(container)
|
|
service = sdkArchiveService({ client: binding.client(createClient), orgSlug: binding.orgSlug })
|
|
} catch (error) {
|
|
throw businessAppError(error)
|
|
}
|
|
return kind === "effect" ? service : archiveReadsOf(service)
|
|
}
|