From c768fd1460eba4926bb7d12e5590741559a9f46b Mon Sep 17 00:00:00 2001 From: Jake Jarvis Date: Fri, 3 Oct 2025 20:26:04 -0400 Subject: [PATCH] Update DNS schemas and service to use 'resolver' terminology; add retry option in Screenshot component for improved reliability --- codecov.yml | 11 +++++++++++ components/domain/domain-report-view.test.tsx | 6 +++--- components/domain/domain-report-view.tsx | 6 +++--- components/domain/screenshot.tsx | 1 + lib/providers/catalog.ts | 12 ++++++++++++ lib/schemas/dns.ts | 6 +++--- lib/schemas/export.ts | 4 ++-- server/services/dns.ts | 6 +++--- 8 files changed, 38 insertions(+), 14 deletions(-) create mode 100644 codecov.yml diff --git a/codecov.yml b/codecov.yml new file mode 100644 index 0000000..9386134 --- /dev/null +++ b/codecov.yml @@ -0,0 +1,11 @@ +# yaml-language-server: $schema=https://json.schemastore.org/codecov +coverage: + status: + project: + default: + target: auto + informational: true + patch: + default: + target: auto + informational: true diff --git a/components/domain/domain-report-view.test.tsx b/components/domain/domain-report-view.test.tsx index 9a1884a..d86b41e 100644 --- a/components/domain/domain-report-view.test.tsx +++ b/components/domain/domain-report-view.test.tsx @@ -127,7 +127,7 @@ describe("DomainReportView", () => { expect(screen.getByText("SSL Certificates")).toBeInTheDocument(); expect(screen.getByText("HTTP Headers")).toBeInTheDocument(); // Export button enabled when all sections are settled - const exportBtn = screen.getByRole("button", { name: /Export JSON/i }); + const exportBtn = screen.getByRole("button", { name: /Export/i }); expect(exportBtn).not.toBeDisabled(); }); @@ -168,7 +168,7 @@ describe("DomainReportView", () => { }, }; render(); - const exportBtn = screen.getByRole("button", { name: /Export JSON/i }); + const exportBtn = screen.getByRole("button", { name: /Export/i }); expect(exportBtn).toBeDisabled(); }); @@ -209,7 +209,7 @@ describe("DomainReportView", () => { }, }; render(); - const exportBtn = screen.getByRole("button", { name: /Export JSON/i }); + const exportBtn = screen.getByRole("button", { name: /Export/i }); expect(exportBtn).not.toBeDisabled(); }); }); diff --git a/components/domain/domain-report-view.tsx b/components/domain/domain-report-view.tsx index 2419035..8cfd4ff 100644 --- a/components/domain/domain-report-view.tsx +++ b/components/domain/domain-report-view.tsx @@ -1,6 +1,6 @@ "use client"; -import { ExternalLink, FileJson2 } from "lucide-react"; +import { Download, ExternalLink } from "lucide-react"; import Link from "next/link"; import { DomainLoadingState } from "@/components/domain/domain-loading-state"; import { DomainUnregisteredState } from "@/components/domain/domain-unregistered-state"; @@ -95,8 +95,8 @@ export function DomainReportView({ domain }: { domain: string }) { onClick={handleExportJson} disabled={areSecondarySectionsLoading} > - - Export JSON + + Export diff --git a/components/domain/screenshot.tsx b/components/domain/screenshot.tsx index 0ecf70c..5864036 100644 --- a/components/domain/screenshot.tsx +++ b/components/domain/screenshot.tsx @@ -29,6 +29,7 @@ export function Screenshot({ { domain }, { staleTime: 24 * 60 * 60_000, // 24h in ms + retry: 5, enabled, }, ), diff --git a/lib/providers/catalog.ts b/lib/providers/catalog.ts index 775f6e0..702f52c 100644 --- a/lib/providers/catalog.ts +++ b/lib/providers/catalog.ts @@ -187,6 +187,18 @@ export const HOSTING_PROVIDERS: Array< category: "hosting", rule: { kind: "headerPresent", name: "x-kinsta-cache" }, }, + { + name: "Railway", + domain: "railway.app", + category: "hosting", + rule: { + any: [ + { kind: "headerPresent", name: "x-railway-request-id" }, + { kind: "headerPresent", name: "x-railway-edge" }, + { kind: "headerIncludes", name: "server", substr: "railway" }, + ], + }, + }, { name: "Bunny.net", domain: "bunny.net", diff --git a/lib/schemas/dns.ts b/lib/schemas/dns.ts index 09a63cf..5f088ea 100644 --- a/lib/schemas/dns.ts +++ b/lib/schemas/dns.ts @@ -1,6 +1,6 @@ import { z } from "zod"; -export const DnsSourceSchema = z.enum(["cloudflare", "google"]); +export const DnsResolverSchema = z.enum(["cloudflare", "google"]); export const DnsTypeSchema = z.enum(["A", "AAAA", "MX", "TXT", "NS"]); @@ -15,10 +15,10 @@ export const DnsRecordSchema = z.object({ export const DnsResolveResultSchema = z.object({ records: z.array(DnsRecordSchema), - source: DnsSourceSchema, + resolver: DnsResolverSchema, }); -export type DnsSource = z.infer; +export type DnsResolver = z.infer; export type DnsType = z.infer; export type DnsRecord = z.infer; export type DnsResolveResult = z.infer; diff --git a/lib/schemas/export.ts b/lib/schemas/export.ts index 25c9f1a..7823865 100644 --- a/lib/schemas/export.ts +++ b/lib/schemas/export.ts @@ -1,5 +1,5 @@ import { z } from "zod"; -import { DnsRecordSchema, DnsSourceSchema } from "./dns"; +import { DnsRecordSchema, DnsResolverSchema } from "./dns"; import { HostingSchema } from "./hosting"; import { HttpHeadersSchema } from "./http"; import { RegistrationSchema } from "./registration"; @@ -22,7 +22,7 @@ export const DomainExportSchema = z.object({ dns: z .object({ records: z.array(DnsRecordSchema.omit({ isCloudflare: true })), - source: DnsSourceSchema, + resolver: DnsResolverSchema, }) .nullish(), hosting: HostingSchema.transform((h) => ({ diff --git a/server/services/dns.ts b/server/services/dns.ts index a58171a..02b4c6d 100644 --- a/server/services/dns.ts +++ b/server/services/dns.ts @@ -6,13 +6,13 @@ import { type DnsRecord, DnsRecordSchema, type DnsResolveResult, - type DnsSource, + type DnsResolver, type DnsType, DnsTypeSchema, } from "@/lib/schemas"; export type DohProvider = { - key: DnsSource; + key: DnsResolver; buildUrl: (domain: string, type: DnsType) => URL; headers?: Record; }; @@ -89,7 +89,7 @@ export async function resolveAll(domain: string): Promise { provider_attempts: attemptIndex + 1, duration_ms_by_provider: durationByProvider, }); - return { records: flat, source: provider.key } as DnsResolveResult; + return { records: flat, resolver: provider.key } as DnsResolveResult; } catch (err) { durationByProvider[provider.key] = Date.now() - attemptStart; lastError = err;