/** * Backfill `readingMinutes` on every post from its body (L-07). * No schema change — safe to re-run any time. * * Usage: cd web && npx tsx scripts/backfill-reading-minutes.ts */ import { getPayload } from 'payload' import configPromise from '@payload-config' import { countLexicalWords } from '../src/lib/lexical' import { READING_WORDS_PER_MINUTE } from '../src/lib/launch' const payload = await getPayload({ config: configPromise }) const { docs } = await payload.find({ collection: 'posts', limit: 500, depth: 0, overrideAccess: true, }) let updated = 0 for (const post of docs) { const words = countLexicalWords(post.content) const readingMinutes = Math.max(1, Math.round(words / READING_WORDS_PER_MINUTE)) if (readingMinutes !== post.readingMinutes) { await payload.update({ collection: 'posts', id: post.id, data: { readingMinutes }, overrideAccess: true, context: { systemBackfill: true }, }) payload.logger.info(`backfill: ${post.slug} ${post.readingMinutes} → ${readingMinutes} (${words} words)`) updated += 1 } } payload.logger.info(`backfill complete: ${docs.length} scanned, ${updated} updated`) // Postgres pool keeps the loop alive — release it so the script exits. await payload.db.destroy?.()