- pnpm dev:local/dev:reset: orchestrate DB container, migrations, seed, and Next.js dev server in one command; Caddy snippet + docs for HTTPS via dev.ginnoir.com - Fix dev login on HTTPS: set both authjs.session-token and __Secure-authjs.session-token so Auth.js finds the session regardless of cookie name resolution - Suppress hydration mismatch on <html> caused by pre-paint script changing data-nav before React hydrates - VAPID startup warning if keys not configured; remove dead NEXT_PUBLIC_VAPID_PUBLIC_KEY var - PushOptIn: hydrate subscription state on mount; reuse existing subscription on iOS to avoid redundant prompts - sendPushToEndpoint: new function to send to a single device endpoint - sendTestNotification: scoped to the calling device's endpoint (ownership-verified) instead of all user subscriptions
49 lines
1.5 KiB
TypeScript
49 lines
1.5 KiB
TypeScript
/**
|
|
* Dev script: send a test push notification to all subscriptions for the dev user.
|
|
* Usage: tsx --env-file=.env scripts/send-test-push.mts
|
|
*/
|
|
import webPush from "web-push";
|
|
import postgres from "postgres";
|
|
|
|
const subject = process.env["VAPID_SUBJECT"];
|
|
const publicKey = process.env["VAPID_PUBLIC_KEY"];
|
|
const privateKey = process.env["VAPID_PRIVATE_KEY"];
|
|
const databaseUrl = process.env["DATABASE_URL"];
|
|
|
|
if (!subject || !publicKey || !privateKey) {
|
|
console.error("VAPID env vars not set");
|
|
process.exit(1);
|
|
}
|
|
if (!databaseUrl) {
|
|
console.error("DATABASE_URL not set");
|
|
process.exit(1);
|
|
}
|
|
|
|
webPush.setVapidDetails(subject, publicKey, privateKey);
|
|
|
|
const sql = postgres(databaseUrl);
|
|
|
|
const subs = await sql`SELECT id, user_id, endpoint, p256dh, auth FROM push_subscriptions`;
|
|
console.log(`Found ${subs.length} push subscription(s)`);
|
|
|
|
if (subs.length === 0) {
|
|
console.log("No subscriptions — enable push notifications in Settings first.");
|
|
await sql.end();
|
|
process.exit(0);
|
|
}
|
|
|
|
for (const sub of subs) {
|
|
try {
|
|
await webPush.sendNotification(
|
|
{ endpoint: sub.endpoint, keys: { p256dh: sub.p256dh, auth: sub.auth } },
|
|
JSON.stringify({ title: "famapp test", body: "Push notifications are working!", url: "/settings" }),
|
|
);
|
|
console.log(`Sent to ${sub.endpoint.slice(0, 60)}...`);
|
|
} catch (err: unknown) {
|
|
const e = err as { statusCode?: number; message?: string };
|
|
console.error(`Failed (${e.statusCode ?? "?"}): ${e.message}`);
|
|
}
|
|
}
|
|
|
|
await sql.end();
|