Files
study-bible-project/server/versions.js
T
nmemmertandClaude Sonnet 5.5 207bfcb919
Build and Push Docker Image / build-and-push (push) Successful in 5m13s
Version history, notes on highlights and bookmarks, "you've studied this", prayer journal
- Earlier versions of a study: the server keeps compressed copies (about one per ten minutes of
  editing, the latest 30); Export shows what differs and puts one back (the replaced copy is kept)
- Notes on highlights and bookmarks: synced, merged without loss, in exports and backups
- Reader verse panel lists your studies and chunks that cover the verse, and opens them
- Prayer journal: requests, who for, linked verses, days prayed, answers; synced, in backups
  and the account export; daily prayer reminder through ntfy
- TODO.md lists the ideas not built yet

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-06 10:45:32 -04:00

33 lines
1.5 KiB
JavaScript

// Earlier versions of a study. Just before a save replaces what the server holds, that copy can be kept, so a
// bad merge or an accidental delete can be undone. To stay small, a copy is kept at most once per window of
// editing, it is compressed, and only the newest few are kept.
import { gunzipSync, gzipSync } from 'zlib';
export const MIN_GAP_MS = 10 * 60 * 1000; // one version per ten minutes of editing history
export const MAX_VERSIONS = 30;
// `prevEditedAt` is when the copy about to be replaced was saved; `lastKeptAt` is when the newest kept version was.
export function shouldSnapshot({ prevEditedAt, lastKeptAt, force = false, minGap = MIN_GAP_MS }) {
if (!Number.isFinite(prevEditedAt)) return false;
if (force) return true;
return !Number.isFinite(lastKeptAt) || prevEditedAt - lastKeptAt >= minGap;
}
export const pack = (json) => gzipSync(Buffer.from(typeof json === 'string' ? json : JSON.stringify(json)));
export const unpack = (buf) => JSON.parse(gunzipSync(buf).toString('utf8'));
const words = (s) => (String(s ?? '').trim() ? String(s).trim().split(/\s+/).length : 0);
// How big a study is: chunks and the words in its notes and scripts.
export function summarizeProject(project) {
let chunks = 0;
let noteWords = 0;
for (const chapter of project?.chapters ?? []) {
for (const chunk of chapter.chunks ?? []) {
chunks += 1;
for (const f of ['observation', 'interpretation', 'application', 'generalNotes', 'finalScript']) noteWords += words(chunk[f]);
}
}
return { chunks, words: noteWords };
}