1
mirror of https://github.com/jakejarvis/domainstack.io.git synced 2025-12-02 19:33:48 -05:00

Update DNS schemas and service to use 'resolver' terminology; add retry option in Screenshot component for improved reliability

This commit is contained in:
2025-10-03 20:26:04 -04:00
parent 47d20ce007
commit c768fd1460
8 changed files with 38 additions and 14 deletions

11
codecov.yml Normal file
View File

@@ -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

View File

@@ -127,7 +127,7 @@ describe("DomainReportView", () => {
expect(screen.getByText("SSL Certificates")).toBeInTheDocument(); expect(screen.getByText("SSL Certificates")).toBeInTheDocument();
expect(screen.getByText("HTTP Headers")).toBeInTheDocument(); expect(screen.getByText("HTTP Headers")).toBeInTheDocument();
// Export button enabled when all sections are settled // 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(); expect(exportBtn).not.toBeDisabled();
}); });
@@ -168,7 +168,7 @@ describe("DomainReportView", () => {
}, },
}; };
render(<DomainReportView domain="loading.com" />); render(<DomainReportView domain="loading.com" />);
const exportBtn = screen.getByRole("button", { name: /Export JSON/i }); const exportBtn = screen.getByRole("button", { name: /Export/i });
expect(exportBtn).toBeDisabled(); expect(exportBtn).toBeDisabled();
}); });
@@ -209,7 +209,7 @@ describe("DomainReportView", () => {
}, },
}; };
render(<DomainReportView domain="errors.com" />); render(<DomainReportView domain="errors.com" />);
const exportBtn = screen.getByRole("button", { name: /Export JSON/i }); const exportBtn = screen.getByRole("button", { name: /Export/i });
expect(exportBtn).not.toBeDisabled(); expect(exportBtn).not.toBeDisabled();
}); });
}); });

View File

@@ -1,6 +1,6 @@
"use client"; "use client";
import { ExternalLink, FileJson2 } from "lucide-react"; import { Download, ExternalLink } from "lucide-react";
import Link from "next/link"; import Link from "next/link";
import { DomainLoadingState } from "@/components/domain/domain-loading-state"; import { DomainLoadingState } from "@/components/domain/domain-loading-state";
import { DomainUnregisteredState } from "@/components/domain/domain-unregistered-state"; import { DomainUnregisteredState } from "@/components/domain/domain-unregistered-state";
@@ -95,8 +95,8 @@ export function DomainReportView({ domain }: { domain: string }) {
onClick={handleExportJson} onClick={handleExportJson}
disabled={areSecondarySectionsLoading} disabled={areSecondarySectionsLoading}
> >
<FileJson2 /> <Download />
Export JSON <span className="hidden sm:inline-block">Export</span>
</Button> </Button>
</div> </div>
</div> </div>

View File

@@ -29,6 +29,7 @@ export function Screenshot({
{ domain }, { domain },
{ {
staleTime: 24 * 60 * 60_000, // 24h in ms staleTime: 24 * 60 * 60_000, // 24h in ms
retry: 5,
enabled, enabled,
}, },
), ),

View File

@@ -187,6 +187,18 @@ export const HOSTING_PROVIDERS: Array<
category: "hosting", category: "hosting",
rule: { kind: "headerPresent", name: "x-kinsta-cache" }, 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", name: "Bunny.net",
domain: "bunny.net", domain: "bunny.net",

View File

@@ -1,6 +1,6 @@
import { z } from "zod"; 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"]); export const DnsTypeSchema = z.enum(["A", "AAAA", "MX", "TXT", "NS"]);
@@ -15,10 +15,10 @@ export const DnsRecordSchema = z.object({
export const DnsResolveResultSchema = z.object({ export const DnsResolveResultSchema = z.object({
records: z.array(DnsRecordSchema), records: z.array(DnsRecordSchema),
source: DnsSourceSchema, resolver: DnsResolverSchema,
}); });
export type DnsSource = z.infer<typeof DnsSourceSchema>; export type DnsResolver = z.infer<typeof DnsResolverSchema>;
export type DnsType = z.infer<typeof DnsTypeSchema>; export type DnsType = z.infer<typeof DnsTypeSchema>;
export type DnsRecord = z.infer<typeof DnsRecordSchema>; export type DnsRecord = z.infer<typeof DnsRecordSchema>;
export type DnsResolveResult = z.infer<typeof DnsResolveResultSchema>; export type DnsResolveResult = z.infer<typeof DnsResolveResultSchema>;

View File

@@ -1,5 +1,5 @@
import { z } from "zod"; import { z } from "zod";
import { DnsRecordSchema, DnsSourceSchema } from "./dns"; import { DnsRecordSchema, DnsResolverSchema } from "./dns";
import { HostingSchema } from "./hosting"; import { HostingSchema } from "./hosting";
import { HttpHeadersSchema } from "./http"; import { HttpHeadersSchema } from "./http";
import { RegistrationSchema } from "./registration"; import { RegistrationSchema } from "./registration";
@@ -22,7 +22,7 @@ export const DomainExportSchema = z.object({
dns: z dns: z
.object({ .object({
records: z.array(DnsRecordSchema.omit({ isCloudflare: true })), records: z.array(DnsRecordSchema.omit({ isCloudflare: true })),
source: DnsSourceSchema, resolver: DnsResolverSchema,
}) })
.nullish(), .nullish(),
hosting: HostingSchema.transform((h) => ({ hosting: HostingSchema.transform((h) => ({

View File

@@ -6,13 +6,13 @@ import {
type DnsRecord, type DnsRecord,
DnsRecordSchema, DnsRecordSchema,
type DnsResolveResult, type DnsResolveResult,
type DnsSource, type DnsResolver,
type DnsType, type DnsType,
DnsTypeSchema, DnsTypeSchema,
} from "@/lib/schemas"; } from "@/lib/schemas";
export type DohProvider = { export type DohProvider = {
key: DnsSource; key: DnsResolver;
buildUrl: (domain: string, type: DnsType) => URL; buildUrl: (domain: string, type: DnsType) => URL;
headers?: Record<string, string>; headers?: Record<string, string>;
}; };
@@ -89,7 +89,7 @@ export async function resolveAll(domain: string): Promise<DnsResolveResult> {
provider_attempts: attemptIndex + 1, provider_attempts: attemptIndex + 1,
duration_ms_by_provider: durationByProvider, duration_ms_by_provider: durationByProvider,
}); });
return { records: flat, source: provider.key } as DnsResolveResult; return { records: flat, resolver: provider.key } as DnsResolveResult;
} catch (err) { } catch (err) {
durationByProvider[provider.key] = Date.now() - attemptStart; durationByProvider[provider.key] = Date.now() - attemptStart;
lastError = err; lastError = err;