Files
template-app/modules/knowledge/core/auto-index.ts
T
2026-11-14 09:56:45 +00:00

47 lines
2.0 KiB
TypeScript

// A project's automatic PDF indexing (template lesson core-11): an administrator opts the project in,
// naming the collection its uploaded PDFs go into; no row is off. The administrator is recorded,
// because the indexing job runs for nobody and re-checks that person's permission before each file.
import { forbidden } from "@conusai-kit/core"
import { autoIndex } from "../contract/index.js"
import { requireCollection } from "./collections.js"
import { type KnowledgeDeps, type KnowledgeScope, knowledgeEnabled } from "./ports.js"
export interface AutoIndexView {
/** The collection uploaded PDFs are indexed into, or null when automatic indexing is off. */
collectionName: string | null
}
export async function getAutoIndex(deps: Pick<KnowledgeDeps, "data">, scope: KnowledgeScope): Promise<AutoIndexView> {
const row = (await deps.data.forScope(scope).of(autoIndex).list({ limit: 1 })).items[0]
return { collectionName: row?.collectionName ?? null }
}
/** Turns automatic indexing on into `collectionName` (which must exist), or off with `null`. */
export async function setAutoIndex(
deps: KnowledgeDeps & { now?: () => number },
scope: KnowledgeScope,
collectionName: string | null,
): Promise<AutoIndexView> {
if (collectionName !== null) {
// The tenant-wall read first: another project's collection answers NotFound, never a policy refusal.
await requireCollection(deps, scope, collectionName)
if (!(await knowledgeEnabled(deps, scope))) throw forbidden("knowledge is switched off for this project")
}
await deps.data.unitOfWork.run(scope, async (tx) => {
const row = (await tx.of(autoIndex).list({ limit: 1 })).items[0]
if (collectionName === null) {
if (row) await tx.of(autoIndex).delete(row.id)
return
}
const patch = {
collectionName,
enabledBy: scope.actor.userId,
enabledAt: new Date((deps.now ?? Date.now)()).toISOString(),
}
if (row) await tx.of(autoIndex).update(row.id, patch, row.version)
else await tx.of(autoIndex).insert(patch)
})
return { collectionName }
}