style(13-03): apply Prettier formatting across repo

Mechanical reformat — no logic changes. 398 files changed, 19125
insertions(+), 16457 deletions(-). Prettier 3.8.4 with .prettierrc
(singleQuote:true, semi:true, tabWidth:2, trailingComma:all,
printWidth:100). Isolated per D-13-08 for reviewability.
This commit is contained in:
Lucas Berger
2026-06-11 20:35:18 -04:00
parent 4bc0445173
commit 982438dc10
398 changed files with 19050 additions and 16382 deletions
+36 -42
View File
@@ -15,14 +15,14 @@
* Fire-and-forget: sync correctness does not depend on push success.
*/
import { eq, ne } from 'drizzle-orm'
import { db } from '../db/client.js'
import { users, pushSubscriptions } from '../db/schema.js'
import { dispatchPush } from './pushDispatcher.js'
import { eq, ne } from 'drizzle-orm';
import { db } from '../db/client.js';
import { users, pushSubscriptions } from '../db/schema.js';
import { dispatchPush } from './pushDispatcher.js';
// ── Types ────────────────────────────────────────────────────────────────────
export type EventChangeOperation = 'create' | 'update' | 'delete'
export type EventChangeOperation = 'create' | 'update' | 'delete';
/**
* Meaningful fields whose change triggers a push notification (D-04).
@@ -34,21 +34,21 @@ export const MEANINGFUL_FIELDS = new Set([
'allDay',
'title',
'location',
])
]);
/**
* Payload describing a detected calendar event change.
* Produced by syncCalendar and consumed by poller + outboxWorker.
*/
export interface EventChange {
uid: string
title: string | null
operation: EventChangeOperation
uid: string;
title: string | null;
operation: EventChangeOperation;
/** For 'update': which fields changed. Omit for 'create' and 'delete'. */
changedFields?: string[]
changedFields?: string[];
/** UTC timestamp of the event start (for notification copy). */
dtstartUtc?: Date | null
allDay?: boolean
dtstartUtc?: Date | null;
allDay?: boolean;
}
// ── Core logic ───────────────────────────────────────────────────────────────
@@ -63,11 +63,11 @@ export interface EventChange {
*/
export function isMeaningfulChange(change: EventChange): boolean {
if (change.operation === 'create' || change.operation === 'delete') {
return true
return true;
}
// update: require at least one meaningful field
const fields = change.changedFields ?? []
return fields.some((f) => MEANINGFUL_FIELDS.has(f))
const fields = change.changedFields ?? [];
return fields.some((f) => MEANINGFUL_FIELDS.has(f));
}
/**
@@ -81,32 +81,32 @@ function buildCopy(
change: EventChange,
actorName: string,
): { notifTitle: string; notifBody: string; navigate: string } {
const eventTitle = change.title ?? change.uid
const eventTitle = change.title ?? change.uid;
let notifTitle: string
let notifBody: string
let notifTitle: string;
let notifBody: string;
// D-02: event notifications show specifics — actor + title.
// D-03: name the actor in every change notification.
if (change.operation === 'create') {
notifTitle = `${actorName} added an event`
notifBody = eventTitle
notifTitle = `${actorName} added an event`;
notifBody = eventTitle;
} else if (change.operation === 'delete') {
notifTitle = `${actorName} removed an event`
notifBody = eventTitle
notifTitle = `${actorName} removed an event`;
notifBody = eventTitle;
} else {
// update
notifTitle = `${actorName} updated an event`
notifBody = eventTitle
notifTitle = `${actorName} updated an event`;
notifBody = eventTitle;
}
// Navigate: /calendar?event=uid for create/update; /calendar for delete
const navigate =
change.operation === 'delete'
? '/calendar'
: `/calendar?event=${encodeURIComponent(change.uid)}`
: `/calendar?event=${encodeURIComponent(change.uid)}`;
return { notifTitle, notifBody, navigate }
return { notifTitle, notifBody, navigate };
}
/**
@@ -119,13 +119,10 @@ function buildCopy(
*
* Fire-and-forget: resolves after dispatching without awaiting push ACKs.
*/
export async function dispatchEventChange(
change: EventChange,
actorUserId: number,
): Promise<void> {
export async function dispatchEventChange(change: EventChange, actorUserId: number): Promise<void> {
// D-04: skip description-only edits
if (!isMeaningfulChange(change)) {
return
return;
}
// IN-01: resolve actor display name for D-02/D-03 notification copy.
@@ -139,22 +136,19 @@ export async function dispatchEventChange(
// D-13: query push_subscriptions from MariaDB only
// D-03: ne() filter excludes the actor at DB level; application-level filter
// below provides defence-in-depth (also makes the mock-based tests deterministic).
db
.select()
.from(pushSubscriptions)
.where(ne(pushSubscriptions.userId, actorUserId)),
])
db.select().from(pushSubscriptions).where(ne(pushSubscriptions.userId, actorUserId)),
]);
const actorName: string = actorRows[0]?.displayName ?? 'A family member'
const actorName: string = actorRows[0]?.displayName ?? 'A family member';
// D-03: additional application-level actor exclusion (defence-in-depth)
const subs = allSubs.filter((s) => s.userId !== actorUserId)
const subs = allSubs.filter((s) => s.userId !== actorUserId);
if (subs.length === 0) {
return
return;
}
const { notifTitle, notifBody, navigate } = buildCopy(change, actorName)
const { notifTitle, notifBody, navigate } = buildCopy(change, actorName);
// Fan out to all non-actor subscriptions (D-03 already enforced by ne() filter)
for (const sub of subs) {
@@ -164,12 +158,12 @@ export async function dispatchEventChange(
body: notifBody,
tag: `event-change-${change.uid}`,
navigate,
})
});
} catch (err) {
console.error(
`[eventChangeDispatcher] Error dispatching for uid=${change.uid} sub.id=${sub.id}:`,
err instanceof Error ? err.message : String(err),
)
);
}
}
}