customer-presentation/bin/joins.js
2026-04-23 14:54:25 +02:00

77 lines
3 KiB
JavaScript

#!/usr/bin/env node
// ─────────────────────────────────────────────────────────────
// bin/joins.js — read the Bifrost join-click log.
//
// Every press of the final "Join Project Bifrost" CTA is recorded
// as its own row in the `bifrost_joins` table (who, when, session).
//
// Usage:
// node bin/joins.js list # every click, newest first
// node bin/joins.js summary # one row per user, with click count
// node bin/joins.js for <email> # full click history for one user
// node bin/joins.js stats # totals (clicks + unique users)
// ─────────────────────────────────────────────────────────────
import { q } from '../src/db.js';
const [, , cmd, arg] = process.argv;
const EMAIL_RE = /^[^@\s]+@[^@\s]+\.[^@\s]+$/;
function help() {
console.log('Usage:');
console.log(' joins list # every click, newest first');
console.log(' joins summary # one row per user');
console.log(' joins for <email> # click history for a user');
console.log(' joins stats # totals');
process.exit(1);
}
function iso(t) { return new Date(t).toISOString(); }
function shortSid(s) { return s ? `[${s.slice(0, 8)}…]` : ''; }
switch (cmd) {
case 'list': {
const rows = q.listJoins.all();
if (rows.length === 0) { console.log('(no clicks yet)'); break; }
for (const r of rows) {
console.log(` ${iso(r.clicked_at)} ${r.email.padEnd(32)} ${shortSid(r.session_id)}`);
}
console.log(`\n${rows.length} click${rows.length === 1 ? '' : 's'} total.`);
break;
}
case 'summary': {
const rows = q.summariseJoins.all();
if (rows.length === 0) { console.log('(no clicks yet)'); break; }
console.log(' CLICKS FIRST LAST EMAIL');
for (const r of rows) {
const n = String(r.click_count).padStart(6);
console.log(` ${n} ${iso(r.first_clicked_at)} ${iso(r.last_clicked_at)} ${r.email}`);
}
console.log(`\n${rows.length} unique user${rows.length === 1 ? '' : 's'}.`);
break;
}
case 'for': {
if (!arg || !EMAIL_RE.test(arg)) help();
const email = arg.trim().toLowerCase();
const rows = q.listJoinsForEmail.all(email);
if (rows.length === 0) { console.log(`(no clicks for ${email})`); break; }
console.log(`Clicks by ${email}:`);
for (const r of rows) {
console.log(` ${iso(r.clicked_at)} ${shortSid(r.session_id)}`);
}
console.log(`\n${rows.length} click${rows.length === 1 ? '' : 's'}.`);
break;
}
case 'stats': {
const total = q.countJoins.get().n;
const unique = q.countUniqueJoiners.get().n;
console.log(` total clicks: ${total}`);
console.log(` unique users: ${unique}`);
break;
}
default:
help();
}