diff --git a/knip.jsonc b/knip.jsonc index 19bbd4d..28f0d09 100644 --- a/knip.jsonc +++ b/knip.jsonc @@ -1,6 +1,7 @@ { "entry": [ // Detect Tanstack Start Routes + "src/server.ts", "src/router.tsx", "src/routes/**/*.tsx", // Drizzle config (plugin disabled due to cloudflare:workers import issues) @@ -9,26 +10,12 @@ "src/db/index.ts", ], "project": ["**/*.{js,mjs,ts,tsx}", "!src/routeTree.gen.ts", "!web/**"], - "ignore": [ - "drizzle-prod.config.ts", - "src/client/features/keywords/utils.ts", - "src/client/hooks/useSearchHistory.ts", - "src/server.ts", - "src/server/lib/audit/progress-kv.ts", - "src/server/lib/audit/types.ts", - "src/server/workflows/SiteAuditWorkflow.ts", - "src/serverFunctions/keywords.ts", - "src/serverFunctions/psi.ts", - "src/types/schemas/audit.ts", - "src/types/schemas/psi.ts", - ], + "ignore": ["drizzle-prod.config.ts"], // Disable Drizzle plugin - it tries to load drizzle.config.ts which imports cloudflare:workers "drizzle": false, "ignoreDependencies": [ // Tailwindcss used via @tailwindcss/vite plugin "tailwindcss", "daisyui", - "@tanstack/query-sync-storage-persister", - "@tanstack/react-query-persist-client", ], } diff --git a/package.json b/package.json index 68f2ef3..de3a30c 100644 --- a/package.json +++ b/package.json @@ -41,10 +41,8 @@ "dependencies": { "@every-app/sdk": "^0.1.14", "@tanstack/query-core": "^5.90.9", - "@tanstack/query-sync-storage-persister": "^5.90.14", "@tanstack/react-form": "^1.25.0", "@tanstack/react-query": "^5.90.9", - "@tanstack/react-query-persist-client": "^5.90.14", "@tanstack/react-router": "^1.136.3", "@tanstack/react-router-devtools": "^1.136.3", "@tanstack/react-start": "^1.136.3", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e7e2884..a511c50 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -14,18 +14,12 @@ importers: '@tanstack/query-core': specifier: ^5.90.9 version: 5.90.20 - '@tanstack/query-sync-storage-persister': - specifier: ^5.90.14 - version: 5.90.22 '@tanstack/react-form': specifier: ^1.25.0 version: 1.28.3(@tanstack/react-start@1.162.4(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(vite@7.3.1(@types/node@22.19.11)(jiti@2.6.1)(lightningcss@1.31.1)(tsx@4.21.0)))(react-dom@19.2.4(react@19.2.4))(react@19.2.4) '@tanstack/react-query': specifier: ^5.90.9 version: 5.90.21(react@19.2.4) - '@tanstack/react-query-persist-client': - specifier: ^5.90.14 - version: 5.90.22(@tanstack/react-query@5.90.21(react@19.2.4))(react@19.2.4) '@tanstack/react-router': specifier: ^1.136.3 version: 1.162.4(react-dom@19.2.4(react@19.2.4))(react@19.2.4) @@ -1655,12 +1649,6 @@ packages: '@tanstack/query-core@5.90.20': resolution: {integrity: sha512-OMD2HLpNouXEfZJWcKeVKUgQ5n+n3A2JFmBaScpNDUqSrQSjiveC7dKMe53uJUg1nDG16ttFPz2xfilz6i2uVg==} - '@tanstack/query-persist-client-core@5.91.19': - resolution: {integrity: sha512-whrASqbVq8261Ue+/ZzpHsrLDYVfRaENs4HTdLuYKxawkGWzdMfV7BmOdWl8ZF0mEBEbrQR8V6oE3R635JF2Fw==} - - '@tanstack/query-sync-storage-persister@5.90.22': - resolution: {integrity: sha512-QoOHewbI9a/7hezbVXlZOOCkF4oTnOpAGNMYiObUZm+jpEoLF5YqGMg0iDv3laSEymz81Zw8HJ8UFxP7mwEmqw==} - '@tanstack/react-devtools@0.9.6': resolution: {integrity: sha512-4wnhqQ1o5PnmEDV8L3yLWaE2ZWD2xjdUw1X8Uv5NK9Ekrz/Qr6iuYl+X4Kq9+Ix2luVGMqd3toFvEwkr3uMFBw==} engines: {node: '>=18'} @@ -1679,12 +1667,6 @@ packages: '@tanstack/react-start': optional: true - '@tanstack/react-query-persist-client@5.90.22': - resolution: {integrity: sha512-BrD3Y/SsrSIDl+t/gpYvjvGHXd7m7oF+GIqktKE8LmTgt7bS1lYHd/CLkVxMPixTU53gHHVFfPNGmY7Hv4L/7g==} - peerDependencies: - '@tanstack/react-query': ^5.90.20 - react: ^18 || ^19 - '@tanstack/react-query@5.90.21': resolution: {integrity: sha512-0Lu6y5t+tvlTJMTO7oh5NSpJfpg/5D41LlThfepTixPYkJ0sE2Jj0m0f6yYqujBwIXlId87e234+MxG3D3g7kg==} peerDependencies: @@ -4186,15 +4168,6 @@ snapshots: '@tanstack/query-core@5.90.20': {} - '@tanstack/query-persist-client-core@5.91.19': - dependencies: - '@tanstack/query-core': 5.90.20 - - '@tanstack/query-sync-storage-persister@5.90.22': - dependencies: - '@tanstack/query-core': 5.90.20 - '@tanstack/query-persist-client-core': 5.91.19 - '@tanstack/react-devtools@0.9.6(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(csstype@3.2.3)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(solid-js@1.9.11)': dependencies: '@tanstack/devtools': 0.10.7(csstype@3.2.3)(solid-js@1.9.11) @@ -4218,12 +4191,6 @@ snapshots: transitivePeerDependencies: - react-dom - '@tanstack/react-query-persist-client@5.90.22(@tanstack/react-query@5.90.21(react@19.2.4))(react@19.2.4)': - dependencies: - '@tanstack/query-persist-client-core': 5.91.19 - '@tanstack/react-query': 5.90.21(react@19.2.4) - react: 19.2.4 - '@tanstack/react-query@5.90.21(react@19.2.4)': dependencies: '@tanstack/query-core': 5.90.20 diff --git a/src/client/features/keywords/utils.ts b/src/client/features/keywords/utils.ts index 8495fcf..922d980 100644 --- a/src/client/features/keywords/utils.ts +++ b/src/client/features/keywords/utils.ts @@ -24,14 +24,6 @@ export function getLanguageCode(locationCode: number): string { return LOCATION_LANGUAGE[locationCode] ?? "en"; } -export function competitionLabel(score: number | null): string { - if (score == null) return "N/A"; - const pct = Math.round(score * 100); - if (pct <= 33) return "low"; - if (pct <= 66) return "medium"; - return "high"; -} - export function scoreTierClass(value: number | null): string { if (value == null) return "score-tier-na"; if (value <= 20) return "score-tier-1"; diff --git a/src/client/hooks/useSearchHistory.ts b/src/client/hooks/useSearchHistory.ts index 30ffe89..c11cf05 100644 --- a/src/client/hooks/useSearchHistory.ts +++ b/src/client/hooks/useSearchHistory.ts @@ -2,7 +2,7 @@ import { useState, useEffect, useCallback } from "react"; import { z } from "zod"; import { jsonCodec } from "@/shared/json"; -export interface SearchHistoryItem { +interface SearchHistoryItem { keyword: string; locationCode: number; locationName: string; diff --git a/src/server/lib/audit/progress-kv.ts b/src/server/lib/audit/progress-kv.ts index 5edf19a..a246796 100644 --- a/src/server/lib/audit/progress-kv.ts +++ b/src/server/lib/audit/progress-kv.ts @@ -16,7 +16,7 @@ const TTL_SECONDS = 30 * 60; // 30 minutes const MAX_ENTRIES = 300; const jsonUnknownCodec = jsonCodec(z.unknown()); -export interface CrawledUrlEntry { +interface CrawledUrlEntry { url: string; statusCode: number; title: string; diff --git a/src/server/lib/audit/types.ts b/src/server/lib/audit/types.ts index 239ed77..eb3470a 100644 --- a/src/server/lib/audit/types.ts +++ b/src/server/lib/audit/types.ts @@ -4,8 +4,6 @@ export type PsiStrategy = "auto" | "all" | "manual" | "none"; -export type AuditStatus = "running" | "completed" | "failed"; - export interface AuditConfig { maxPages: number; psiStrategy: PsiStrategy; diff --git a/src/serverFunctions/keywords.ts b/src/serverFunctions/keywords.ts index b90bc36..3c94ea0 100644 --- a/src/serverFunctions/keywords.ts +++ b/src/serverFunctions/keywords.ts @@ -3,8 +3,6 @@ import { z } from "zod"; import { authenticatedServerFunctionMiddleware } from "@/serverFunctions/middleware"; import { researchKeywordsSchema, - createProjectSchema, - deleteProjectSchema, saveKeywordsSchema, getSavedKeywordsSchema, removeSavedKeywordSchema, @@ -19,26 +17,6 @@ export const researchKeywords = createServerFn({ method: "POST" }) KeywordResearchService.research(context.userId, data), ); -export const listProjects = createServerFn({ method: "POST" }) - .middleware(authenticatedServerFunctionMiddleware) - .handler(async ({ context }) => - KeywordResearchService.listProjects(context.userId), - ); - -export const createProject = createServerFn({ method: "POST" }) - .middleware(authenticatedServerFunctionMiddleware) - .inputValidator((data: unknown) => createProjectSchema.parse(data)) - .handler(async ({ data, context }) => - KeywordResearchService.createProject(context.userId, data), - ); - -export const deleteProject = createServerFn({ method: "POST" }) - .middleware(authenticatedServerFunctionMiddleware) - .inputValidator((data: unknown) => deleteProjectSchema.parse(data)) - .handler(async ({ data, context }) => - KeywordResearchService.deleteProject(context.userId, data), - ); - export const saveKeywords = createServerFn({ method: "POST" }) .middleware(authenticatedServerFunctionMiddleware) .inputValidator((data: unknown) => saveKeywordsSchema.parse(data)) diff --git a/src/serverFunctions/psi.ts b/src/serverFunctions/psi.ts index a15f8c0..11076bb 100644 --- a/src/serverFunctions/psi.ts +++ b/src/serverFunctions/psi.ts @@ -2,29 +2,12 @@ import { createServerFn } from "@tanstack/react-start"; import { PsiAuditService } from "@/server/features/psi/services/PsiAuditService"; import { authenticatedServerFunctionMiddleware } from "@/serverFunctions/middleware"; import { - psiAuditSchema, - psiAuditListSchema, - psiAuditDetailsSchema, - psiIssueFilterSchema, - psiExportSchema, psiUnifiedIssueSchema, psiUnifiedExportSchema, psiProjectKeySchema, psiProjectSchema, } from "@/types/schemas/psi"; -export const runPsiAudit = createServerFn({ method: "POST" }) - .middleware(authenticatedServerFunctionMiddleware) - .inputValidator((data: unknown) => psiAuditSchema.parse(data)) - .handler(async ({ data, context }) => - PsiAuditService.runAudit({ - projectId: data.projectId, - userId: context.userId, - url: data.url, - strategy: data.strategy, - }), - ); - export const getProjectPsiApiKey = createServerFn({ method: "POST" }) .middleware(authenticatedServerFunctionMiddleware) .inputValidator((data: unknown) => psiProjectSchema.parse(data)) @@ -56,54 +39,6 @@ export const clearProjectPsiApiKey = createServerFn({ method: "POST" }) }), ); -export const listProjectPsiAudits = createServerFn({ method: "POST" }) - .middleware(authenticatedServerFunctionMiddleware) - .inputValidator((data: unknown) => psiAuditListSchema.parse(data)) - .handler(async ({ data, context }) => - PsiAuditService.listProjectPsiAudits({ - projectId: data.projectId, - userId: context.userId, - strategy: data.strategy, - limit: data.limit, - }), - ); - -export const getProjectPsiAuditRaw = createServerFn({ method: "POST" }) - .middleware(authenticatedServerFunctionMiddleware) - .inputValidator((data: unknown) => psiAuditDetailsSchema.parse(data)) - .handler(async ({ data, context }) => - PsiAuditService.getProjectPsiAuditRaw({ - projectId: data.projectId, - userId: context.userId, - auditId: data.auditId, - }), - ); - -export const getProjectPsiAuditIssues = createServerFn({ method: "POST" }) - .middleware(authenticatedServerFunctionMiddleware) - .inputValidator((data: unknown) => psiIssueFilterSchema.parse(data)) - .handler(async ({ data, context }) => - PsiAuditService.getProjectPsiAuditIssues({ - projectId: data.projectId, - userId: context.userId, - auditId: data.auditId, - category: data.category, - }), - ); - -export const exportProjectPsiAudit = createServerFn({ method: "POST" }) - .middleware(authenticatedServerFunctionMiddleware) - .inputValidator((data: unknown) => psiExportSchema.parse(data)) - .handler(async ({ data, context }) => - PsiAuditService.exportProjectPsiAudit({ - projectId: data.projectId, - userId: context.userId, - auditId: data.auditId, - mode: data.mode, - category: data.category, - }), - ); - export const getPsiIssuesBySource = createServerFn({ method: "POST" }) .middleware(authenticatedServerFunctionMiddleware) .inputValidator((data: unknown) => psiUnifiedIssueSchema.parse(data)) diff --git a/src/types/schemas/audit.ts b/src/types/schemas/audit.ts index de76317..c4d9939 100644 --- a/src/types/schemas/audit.ts +++ b/src/types/schemas/audit.ts @@ -13,38 +13,26 @@ export const startAuditSchema = z.object({ psiApiKey: z.string().optional(), }); -export type StartAuditInput = z.infer; - export const getAuditStatusSchema = z.object({ auditId: z.string().min(1), }); -export type GetAuditStatusInput = z.infer; - export const getAuditResultsSchema = z.object({ auditId: z.string().min(1), }); -export type GetAuditResultsInput = z.infer; - export const getAuditHistorySchema = z.object({ projectId: z.string().min(1), }); -export type GetAuditHistoryInput = z.infer; - export const deleteAuditSchema = z.object({ auditId: z.string().min(1), }); -export type DeleteAuditInput = z.infer; - export const getCrawlProgressSchema = z.object({ auditId: z.string().min(1), }); -export type GetCrawlProgressInput = z.infer; - // ─── URL search params schema for /p/$projectId/audit ──────────────────────── const auditTabs = ["pages", "performance"] as const; @@ -53,5 +41,3 @@ export const auditSearchSchema = z.object({ auditId: z.string().optional().catch(undefined), tab: z.enum(auditTabs).catch("pages").default("pages"), }); - -export type AuditSearchParams = z.infer; diff --git a/src/types/schemas/psi.ts b/src/types/schemas/psi.ts index 1e9d277..c9312c8 100644 --- a/src/types/schemas/psi.ts +++ b/src/types/schemas/psi.ts @@ -1,6 +1,5 @@ import { z } from "zod"; -const psiStrategies = ["mobile", "desktop"] as const; const psiCategories = [ "performance", "accessibility", @@ -9,21 +8,6 @@ const psiCategories = [ ] as const; const psiSources = ["single", "site"] as const; -export const psiAuditSchema = z.object({ - projectId: z.string().min(1, "Project is required"), - url: z.string().min(1, "URL is required").max(2048), - strategy: z.enum(psiStrategies).default("mobile"), -}); - -export type PsiAuditInput = z.infer; - -export const psiSearchSchema = z.object({ - url: z.string().catch("").default(""), - strategy: z.enum(psiStrategies).catch("mobile").default("mobile"), -}); - -export type PsiSearchParams = z.infer; - export const psiProjectKeySchema = z.object({ projectId: z.string().min(1, "Project is required"), apiKey: z.string().min(1, "API key is required").max(512), @@ -33,30 +17,6 @@ export const psiProjectSchema = z.object({ projectId: z.string().min(1, "Project is required"), }); -export const psiAuditListSchema = z.object({ - projectId: z.string().min(1, "Project is required"), - strategy: z.enum(psiStrategies).optional(), - limit: z.number().int().min(1).max(200).default(50), -}); - -export const psiAuditDetailsSchema = z.object({ - projectId: z.string().min(1, "Project is required"), - auditId: z.string().min(1, "Audit is required"), -}); - -export const psiIssueFilterSchema = z.object({ - projectId: z.string().min(1, "Project is required"), - auditId: z.string().min(1, "Audit is required"), - category: z.enum(psiCategories).optional(), -}); - -export const psiExportSchema = z.object({ - projectId: z.string().min(1, "Project is required"), - auditId: z.string().min(1, "Audit is required"), - mode: z.enum(["full", "issues", "category"]), - category: z.enum(psiCategories).optional(), -}); - export const psiUnifiedIssueSchema = z.object({ projectId: z.string().min(1, "Project is required"), source: z.enum(psiSources),