import { type Kysely } from 'kysely'; import type { BatchStatement } from '../db/batch.js'; import type { TaprootDb } from '../db/client.js'; import type { Database, FieldRow, FieldType } from '../db/schema.js'; /** How a field's values are compared, which decides which column carries them. */ export type IndexedValueKind = 'date' | 'number' | 'text'; export declare function indexedValueKind(type: FieldType): IndexedValueKind | null; /** * Retract a deleted item's terms, for the one path that removes the row rather than rewriting it. * * `content_item_text` cascades on the item delete; a virtual table has no foreign key to cascade * along, so it is not told. Left alone the entries are *harmless to correctness* — every read joins * back through `content_item_text`, whose row is gone, so nothing matches — but they accumulate, they * skew `bm25`'s corpus statistics, and SQLite reuses rowids, so an orphan can eventually sit on the * rowid a future item is given. Must be batched **before** the delete that cascades: after it, the * subquery that finds the rowid has nothing to find. */ export declare function planTextIndexDelete(db: Kysely, contentItemId: string): BatchStatement; export interface DerivedIndexOptions { /** * Block type schemas keyed by `api_id`, from `blockTypeRegistry`. * * Omitted, a block's contents are not indexed — which is right for a caller that has no registry * in hand and wrong for a write. Both write paths already load one for `validateItemData`, so * passing it costs nothing. */ blockTypes?: Map; } /** * Every derived-index statement for one item, for the one call site shape that must not drift. * * Synchronous and read-free, unlike `planAssignmentIndex` — there is nothing to check the existence * of, because a value is not a reference. That is what lets it be called from the paths where a read * is not available. */ export declare function planDerivedIndexes(db: Kysely, contentItemId: string, fields: FieldRow[], data: Record, options?: DerivedIndexOptions): BatchStatement[]; /** * Rebuild every derived index for every item. * * **Required after the migrations that add them, not optional.** Both tables are created empty, so * until this has run a query field answers as though nothing matched and a search finds only what * its title says — and a migration cannot do it, because it needs each content type's field * definitions and a walk over stored JSON. * * One walk rebuilds both, which is the same argument `planDerivedIndexes` makes: a command that * rebuilt one of them would leave a database half-indexed by whoever ran the older version. * * Batched per item rather than per row, and sequential rather than parallel: this runs against a * production database and finishing a minute later is a better trade than saturating D1's * connection budget. */ export declare function reindexDerived(handle: TaprootDb, onProgress?: (done: number, total: number) => void): Promise<{ items: number; }>;