forked from Mike/freno-dev
chore: remediate pygienium audit findings
Dead code: 77 verified-unused exports, files (BackArrow, MenuBars, cookies.ts, db/create.ts, schemas/comment.ts, security-headers.ts) and 12 unused dependencies removed Comments: ~370 RESTATE comments stripped across 53 files; 2 verbose blocks tightened; dead commented-out config removed Complexity: bulkUpsert extracted into 11 per-entity helpers (CCN 156->~10); login formHandler split into 3 submitters (CCN 63->~5); account page render split into 8 section components (CCN 40); updatePost SQL builder rebuilt; assert*Owned consolidated behind generic assertOwnedBy Defensive guards: 4 redundant rethrow/nullish guards removed
This commit is contained in:
@@ -80,7 +80,6 @@ export const getUserState = query(async (): Promise<UserState> => {
|
||||
* Call this after login, logout, token refresh, email verification
|
||||
*/
|
||||
export function revalidateAuth() {
|
||||
// Revalidate the cache
|
||||
revalidateKey("user-auth-state");
|
||||
|
||||
// Dispatch event to trigger UI updates (client-side only)
|
||||
|
||||
@@ -3,21 +3,6 @@
|
||||
* Note: These utilities should only run in the browser
|
||||
*/
|
||||
|
||||
/**
|
||||
* Fetch wrapper for auth checks where 401s are expected and should not trigger console errors
|
||||
*/
|
||||
export async function safeFetch(
|
||||
input: RequestInfo | URL,
|
||||
init?: RequestInit
|
||||
): Promise<Response> {
|
||||
try {
|
||||
const response = await fetch(input, init);
|
||||
return response;
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode JWT payload without verification (client-side only)
|
||||
* @param token - JWT token string
|
||||
|
||||
@@ -1,111 +0,0 @@
|
||||
/**
|
||||
* Cookie utilities for SolidStart
|
||||
* Provides client and server-side cookie management
|
||||
*/
|
||||
|
||||
import { getCookie as getServerCookie, setCookie as setServerCookie } from "vinxi/http";
|
||||
import type { H3Event } from "vinxi/http";
|
||||
|
||||
/**
|
||||
* Get cookie value on the server
|
||||
*/
|
||||
export function getCookie(event: H3Event, name: string): string | undefined {
|
||||
return getServerCookie(event, name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set cookie on the server
|
||||
*/
|
||||
export function setCookie(
|
||||
event: H3Event,
|
||||
name: string,
|
||||
value: string,
|
||||
options?: {
|
||||
maxAge?: number;
|
||||
expires?: Date;
|
||||
httpOnly?: boolean;
|
||||
secure?: boolean;
|
||||
sameSite?: "strict" | "lax" | "none";
|
||||
path?: string;
|
||||
}
|
||||
) {
|
||||
setServerCookie(event, name, value, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete cookie on the server
|
||||
*/
|
||||
export function deleteCookie(event: H3Event, name: string) {
|
||||
setServerCookie(event, name, "", {
|
||||
maxAge: 0,
|
||||
expires: new Date("2016-10-05"),
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get cookie value on the client (browser)
|
||||
*/
|
||||
export function getClientCookie(name: string): string | undefined {
|
||||
if (typeof document === "undefined") return undefined;
|
||||
|
||||
const value = `; ${document.cookie}`;
|
||||
const parts = value.split(`; ${name}=`);
|
||||
|
||||
if (parts.length === 2) {
|
||||
return parts.pop()?.split(";").shift();
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set cookie on the client (browser)
|
||||
*/
|
||||
export function setClientCookie(
|
||||
name: string,
|
||||
value: string,
|
||||
options?: {
|
||||
maxAge?: number;
|
||||
expires?: Date;
|
||||
path?: string;
|
||||
secure?: boolean;
|
||||
sameSite?: "strict" | "lax" | "none";
|
||||
}
|
||||
) {
|
||||
if (typeof document === "undefined") return;
|
||||
|
||||
let cookieString = `${name}=${value}`;
|
||||
|
||||
if (options?.maxAge) {
|
||||
cookieString += `; max-age=${options.maxAge}`;
|
||||
}
|
||||
|
||||
if (options?.expires) {
|
||||
cookieString += `; expires=${options.expires.toUTCString()}`;
|
||||
}
|
||||
|
||||
if (options?.path) {
|
||||
cookieString += `; path=${options.path}`;
|
||||
} else {
|
||||
cookieString += "; path=/";
|
||||
}
|
||||
|
||||
if (options?.secure) {
|
||||
cookieString += "; secure";
|
||||
}
|
||||
|
||||
if (options?.sameSite) {
|
||||
cookieString += `; samesite=${options.sameSite}`;
|
||||
}
|
||||
|
||||
document.cookie = cookieString;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete cookie on the client (browser)
|
||||
*/
|
||||
export function deleteClientCookie(name: string) {
|
||||
if (typeof document === "undefined") return;
|
||||
|
||||
document.cookie = `${name}=; max-age=0; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/`;
|
||||
}
|
||||
@@ -81,7 +81,6 @@ export function formatRelativeTime(
|
||||
return `${diffDay}d ago`;
|
||||
}
|
||||
} else {
|
||||
// style === "long"
|
||||
if (includeSeconds && diffSec < 60) {
|
||||
return `${diffSec} second${diffSec === 1 ? "" : "s"} ago`;
|
||||
}
|
||||
|
||||
@@ -12,14 +12,12 @@ const VERSION_STORAGE_KEY = "app-version-hash";
|
||||
*/
|
||||
function getCurrentVersionHash(): string {
|
||||
try {
|
||||
// Use a combination of script tags to detect version
|
||||
const scripts = Array.from(document.querySelectorAll("script[src]"))
|
||||
.map((s) => (s as HTMLScriptElement).src)
|
||||
.filter((src) => src.includes("/_build/"))
|
||||
.sort()
|
||||
.join(",");
|
||||
|
||||
// Simple hash function
|
||||
let hash = 0;
|
||||
for (let i = 0; i < scripts.length; i++) {
|
||||
const char = scripts.charCodeAt(i);
|
||||
@@ -39,7 +37,6 @@ function getCurrentVersionHash(): string {
|
||||
*/
|
||||
async function checkForNewVersion(): Promise<boolean> {
|
||||
try {
|
||||
// Fetch current page HTML
|
||||
const response = await fetch(window.location.pathname, {
|
||||
method: "HEAD",
|
||||
cache: "no-cache"
|
||||
@@ -64,7 +61,6 @@ async function checkForNewVersion(): Promise<boolean> {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Store current ETag for future checks
|
||||
if (newEtag) {
|
||||
sessionStorage.setItem("app-etag", newEtag);
|
||||
}
|
||||
@@ -80,7 +76,6 @@ async function checkForNewVersion(): Promise<boolean> {
|
||||
* Show update notification to user
|
||||
*/
|
||||
function showUpdateNotification(): void {
|
||||
// Only show once per session
|
||||
if (sessionStorage.getItem("update-notification-shown")) {
|
||||
return;
|
||||
}
|
||||
@@ -147,7 +142,6 @@ function showUpdateNotification(): void {
|
||||
|
||||
document.body.appendChild(notification);
|
||||
|
||||
// Auto-remove after 30 seconds
|
||||
setTimeout(() => {
|
||||
if (notification.parentElement) {
|
||||
notification.style.animation = "slideIn 0.3s ease-out reverse";
|
||||
@@ -162,11 +156,9 @@ function showUpdateNotification(): void {
|
||||
export function startDeploymentMonitoring(): void {
|
||||
if (typeof window === "undefined") return;
|
||||
|
||||
// Store initial version
|
||||
const initialVersion = getCurrentVersionHash();
|
||||
sessionStorage.setItem(VERSION_STORAGE_KEY, initialVersion);
|
||||
|
||||
// Periodic version check
|
||||
const intervalId = setInterval(async () => {
|
||||
const hasNewVersion = await checkForNewVersion();
|
||||
if (hasNewVersion) {
|
||||
@@ -174,7 +166,6 @@ export function startDeploymentMonitoring(): void {
|
||||
}
|
||||
}, VERSION_CHECK_INTERVAL);
|
||||
|
||||
// Check on visibility change (user returns to tab)
|
||||
const handleVisibilityChange = async () => {
|
||||
if (document.visibilityState === "visible") {
|
||||
const hasNewVersion = await checkForNewVersion();
|
||||
@@ -186,7 +177,6 @@ export function startDeploymentMonitoring(): void {
|
||||
|
||||
document.addEventListener("visibilitychange", handleVisibilityChange);
|
||||
|
||||
// Cleanup function
|
||||
if (typeof window !== "undefined") {
|
||||
(window as any).__cleanupDeploymentMonitoring = () => {
|
||||
clearInterval(intervalId);
|
||||
|
||||
@@ -26,7 +26,6 @@ export function initPerformanceTracking() {
|
||||
|
||||
const supported = new Set(PerformanceObserver.supportedEntryTypes ?? []);
|
||||
|
||||
// Observe LCP
|
||||
if (supported.has("largest-contentful-paint")) {
|
||||
try {
|
||||
const lcpObserver = new PerformanceObserver((entryList) => {
|
||||
@@ -40,7 +39,6 @@ export function initPerformanceTracking() {
|
||||
}
|
||||
}
|
||||
|
||||
// Observe CLS
|
||||
if (supported.has("layout-shift")) {
|
||||
try {
|
||||
const clsObserver = new PerformanceObserver((entryList) => {
|
||||
@@ -59,7 +57,6 @@ export function initPerformanceTracking() {
|
||||
}
|
||||
}
|
||||
|
||||
// Observe FID
|
||||
if (supported.has("first-input")) {
|
||||
try {
|
||||
const fidObserver = new PerformanceObserver((entryList) => {
|
||||
@@ -74,7 +71,6 @@ export function initPerformanceTracking() {
|
||||
}
|
||||
}
|
||||
|
||||
// Observe INP (event timing)
|
||||
if (supported.has("event")) {
|
||||
try {
|
||||
const interactions: number[] = [];
|
||||
@@ -96,7 +92,6 @@ export function initPerformanceTracking() {
|
||||
}
|
||||
}
|
||||
|
||||
// Get navigation timing metrics
|
||||
window.addEventListener("load", () => {
|
||||
setTimeout(() => {
|
||||
const navTiming = performance.getEntriesByType(
|
||||
@@ -110,7 +105,6 @@ export function initPerformanceTracking() {
|
||||
metrics.loadComplete = navTiming.loadEventEnd - navTiming.fetchStart;
|
||||
}
|
||||
|
||||
// Get FCP
|
||||
const paintEntries = performance.getEntriesByType("paint");
|
||||
const fcpEntry = paintEntries.find(
|
||||
(entry) => entry.name === "first-contentful-paint"
|
||||
@@ -135,7 +129,6 @@ export function initPerformanceTracking() {
|
||||
}
|
||||
|
||||
function sendMetrics() {
|
||||
// Only send if we have at least one metric
|
||||
if (Object.keys(metrics).length === 0) {
|
||||
return;
|
||||
}
|
||||
@@ -157,7 +150,6 @@ function sendMetrics() {
|
||||
const blob = new Blob([payload], { type: "application/json" });
|
||||
navigator.sendBeacon(apiUrl, blob);
|
||||
} else {
|
||||
// Fallback to fetch with keepalive
|
||||
fetch(apiUrl, {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
@@ -168,6 +160,5 @@ function sendMetrics() {
|
||||
);
|
||||
}
|
||||
|
||||
// Clear metrics after sending
|
||||
metrics = {};
|
||||
}
|
||||
|
||||
@@ -61,7 +61,6 @@ export default async function AddImageToS3(
|
||||
throw new Error("Failed to upload file to S3");
|
||||
}
|
||||
|
||||
// Create thumbnails for images (blog posts only)
|
||||
if (type === "blog" && isImage) {
|
||||
try {
|
||||
const thumbnail = await resizeImage(file, 200, 200, 0.8);
|
||||
|
||||
@@ -22,7 +22,7 @@ function xmlEscape(s: string): string {
|
||||
/**
|
||||
* Generate a single `<url>` element for a given entry on a site.
|
||||
*/
|
||||
export function urlElement(site: Site, entry: SitemapEntry): string {
|
||||
function urlElement(site: Site, entry: SitemapEntry): string {
|
||||
const loc = `https://${site.domain}${entry.path}`;
|
||||
return ` <url>
|
||||
<loc>${xmlEscape(loc)}</loc>
|
||||
|
||||
@@ -28,13 +28,11 @@ describe("generateSitemap", () => {
|
||||
it("generates valid XML for main site with all expected routes", () => {
|
||||
const xml = generateSitemap(SITE_CONFIG.main, SITEMAP_ROUTES.main);
|
||||
|
||||
// Basic structure
|
||||
expect(xml).toContain('<?xml version="1.0" encoding="UTF-8"?>');
|
||||
expect(xml).toContain(
|
||||
'<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">'
|
||||
);
|
||||
|
||||
// All main site paths present with freno.me domain
|
||||
const locs = extractLocs(xml);
|
||||
expect(locs).toContain("https://freno.me/");
|
||||
expect(locs).toContain("https://freno.me/blog");
|
||||
@@ -43,10 +41,8 @@ describe("generateSitemap", () => {
|
||||
expect(locs).toContain("https://freno.me/resume");
|
||||
expect(locs).toContain("https://freno.me/downloads");
|
||||
|
||||
// Exactly 6 entries
|
||||
expect(locs.length).toBe(6);
|
||||
|
||||
// Verify well-formedness by checking balanced tags
|
||||
expect(xml).toContain("</urlset>");
|
||||
const urlOpens = (xml.match(/<url>/g) || []).length;
|
||||
const urlCloses = (xml.match(/<\/url>/g) || []).length;
|
||||
@@ -56,7 +52,6 @@ describe("generateSitemap", () => {
|
||||
|
||||
it("generates valid parseable XML for lineage site", () => {
|
||||
const xml = generateSitemap(SITE_CONFIG.lineage, SITEMAP_ROUTES.lineage);
|
||||
// Verify balanced tags
|
||||
expect(xml).toContain("</urlset>");
|
||||
const urlOpens = (xml.match(/<url>/g) || []).length;
|
||||
const urlCloses = (xml.match(/<\/url>/g) || []).length;
|
||||
@@ -73,7 +68,6 @@ describe("generateSitemap", () => {
|
||||
expect(locs).toContain("https://nessa.freno.me/privacy");
|
||||
expect(locs.length).toBe(3);
|
||||
|
||||
// No leakage from main site
|
||||
for (const loc of locs) {
|
||||
expect(loc).not.toContain("://freno.me/");
|
||||
expect(loc).not.toContain("://freno.me/blog");
|
||||
|
||||
@@ -45,15 +45,12 @@ export function useCountdown(options: UseCountdownOptions = {}) {
|
||||
};
|
||||
|
||||
const startCountdown = (expiresAt: string | Date) => {
|
||||
// Clear any existing interval
|
||||
if (intervalId !== null) {
|
||||
clearInterval(intervalId);
|
||||
}
|
||||
|
||||
// Calculate immediately
|
||||
calculateRemaining(expiresAt);
|
||||
|
||||
// Then update every second
|
||||
intervalId = setInterval(() => calculateRemaining(expiresAt), 1000);
|
||||
};
|
||||
|
||||
@@ -64,7 +61,6 @@ export function useCountdown(options: UseCountdownOptions = {}) {
|
||||
}
|
||||
};
|
||||
|
||||
// Cleanup on unmount
|
||||
onCleanup(() => {
|
||||
stopCountdown();
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user