d6b16f5e06
Auth BFF (OIDC + prompt=none silent SSO), Mongo data layer, admin CRUD (folders/tags/stories/chapters with TipTap), public reader with tag filtering. Built and verified same-session per design-018-stories.md.
22 lines
881 B
JavaScript
22 lines
881 B
JavaScript
// storyAggregate.js — story.word_count is the sum of its published chapters'
|
|
// word counts (design-018 §2.2). Recomputed on every chapter save/publish-
|
|
// toggle/delete — full recount each time, matching this project's established
|
|
// "cheap at this scale, full recount is correct" convention (design-018 §2.6
|
|
// documents the same tradeoff for rating aggregates).
|
|
'use strict';
|
|
|
|
async function recomputeStoryWordCount(db, storyId) {
|
|
const chapters = await db.collection('chapters')
|
|
.find({ story_id: storyId, status: 'published' }, { projection: { word_count: 1 } })
|
|
.toArray();
|
|
const wordCount = chapters.reduce((sum, c) => sum + (c.word_count || 0), 0);
|
|
|
|
await db.collection('stories').updateOne(
|
|
{ _id: storyId },
|
|
{ $set: { word_count: wordCount, updated_at: new Date() } }
|
|
);
|
|
return wordCount;
|
|
}
|
|
|
|
module.exports = { recomputeStoryWordCount };
|