import type { CommitSummary } from "~/lib/types";
const WEEK_MS = 7 * 24 * 60 * 60 * 1000;
const MAX_EMAIL_LENGTH = 254;
const MAX_LOOKUP_EMAILS = 40;
export type IndexedCommit = Pick<CommitSummary, "sha" | "authorName" | "authorEmail" | "authoredAt"> & {
coAuthors: string[];
};
export type EmailDay = { email: string; day: string; commits: number };
export type ContributorRow = { email: string; name: string; commits: number; first: number; last: number };
function normalizeEmail(email: string): string {
return email.trim().toLowerCase().slice(0, MAX_EMAIL_LENGTH);
}
export function utcDay(timestamp: number): string {
return new Date(timestamp).toISOString().slice(0, 10);
}
/**
* The set of commits reachable from one repo's default branch head, in Durable Object SQLite. The set is
* kept closed under ancestry, which is what lets a fast-forward be indexed by walking only new commits.
* `gen` tags rows written by a rebuild so a finished rebuild can drop everything no longer reachable.
*/
export class CommitIndex {
constructor(private readonly sql: SqlStorage) {
sql.exec(`CREATE TABLE IF NOT EXISTS commits (
sha TEXT PRIMARY KEY,
email TEXT NOT NULL,
name TEXT NOT NULL,
authored_at INTEGER NOT NULL,
day TEXT NOT NULL,
gen INTEGER NOT NULL
)`);
sql.exec("CREATE INDEX IF NOT EXISTS commits_email_day ON commits(email, day)");
sql.exec("CREATE INDEX IF NOT EXISTS commits_authored ON commits(authored_at)");
sql.exec("CREATE INDEX IF NOT EXISTS commits_gen ON commits(gen)");
sql.exec(`CREATE TABLE IF NOT EXISTS coauthors (
sha TEXT NOT NULL,