Skip to content
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions packages/fern-dashboard/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@
"@react-three/fiber": "9.0.4",
"@sentry/nextjs": "^10.12.0",
"@sparticuz/chromium": "^133.0.0",
"@supabase/supabase-js": "^2.84.0",
"@tailwindcss/container-queries": "^0.1.1",
"@tailwindcss/typography": "^0.5.16",
"@tanstack/react-query": "^5.71.1",
Expand Down Expand Up @@ -105,6 +106,7 @@
"@types/uuid": "^9.0.8",
"@upstash/redis": "^1.34.6",
"@vercel/analytics": "^1.5.0",
"@vercel/kv": "^3.0.0",
"@vercel/speed-insights": "^1.2.0",
"algoliasearch": "^5.40.1",
"archiver": "^7.0.1",
Expand Down Expand Up @@ -132,6 +134,8 @@
"motion": "^12.4.7",
"next": "catalog:",
"next-themes": "^0.4.4",
"p-limit": "^7.2.0",
"pg": "^8.16.3",
"posthog-js": "^1.258.2",
"posthog-node": "^5.10.0",
"puppeteer-core": "^24.4.0",
Expand Down
102 changes: 102 additions & 0 deletions packages/fern-dashboard/scripts/list-production-domains.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
#!/usr/bin/env npx tsx
/**
* List all production domains from the KV store
*
* Usage:
* npx tsx scripts/list-production-domains.ts
* npx tsx scripts/list-production-domains.ts --include-previews
* npx tsx scripts/list-production-domains.ts --json
*/

import { config } from "dotenv";
import { dirname, resolve } from "path";
import { fileURLToPath } from "url";
import { parseArgs } from "util";

const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);

config({ path: resolve(__dirname, "../.env.local") });

process.env.NODE_ENV = "test";

async function main() {
const { values } = parseArgs({
options: {
"include-previews": { type: "boolean", default: false },
json: { type: "boolean", default: false },
help: { type: "boolean", short: "h" }
},
allowPositionals: false
});

if (values.help) {
console.log(`
List Production Domains

Usage:
npx tsx scripts/list-production-domains.ts [options]

Options:
--include-previews Include Fern-hosted preview domains (*.docs.buildwithfern.com)
--json Output as JSON
-h, --help Show this help message
`);
process.exit(0);
}

// Check for either KV (with CDN_URI) or FDR credentials
const hasKV = process.env.KV_REST_API_URL && process.env.KV_REST_API_TOKEN && process.env.NEXT_PUBLIC_CDN_URI;
const hasFDR = (process.env.FDR_SERVER_URL || process.env.NEXT_PUBLIC_FDR_ORIGIN) && process.env.FERN_TOKEN;

if (!hasKV && !hasFDR) {
console.error("Error: Either KV credentials (KV_REST_API_URL, KV_REST_API_TOKEN, NEXT_PUBLIC_CDN_URI)");
console.error(" or FDR credentials (FDR_SERVER_URL/NEXT_PUBLIC_FDR_ORIGIN, FERN_TOKEN) are required");
process.exit(1);
}

console.log(`Using ${hasKV ? "KV store" : "FDR"} to fetch domains...\n`);

const { getAllProductionDomains, getAllDomainsIncludingPreviews } = await import(
"../src/app/services/analyticsCron/getAllProductionDomains"
);

try {
if (values["include-previews"]) {
const domains = await getAllDomainsIncludingPreviews();

if (values.json) {
console.log(JSON.stringify(domains, null, 2));
} else {
console.log(`\nFound ${domains.length} domains (including previews):\n`);
for (const domain of domains) {
console.log(` ${domain}`);
}
}
} else {
const domains = await getAllProductionDomains();

if (values.json) {
console.log(JSON.stringify(domains, null, 2));
} else {
const customDomains = domains.filter((d) => d.isCustomDomain);
const fernDomains = domains.filter((d) => !d.isCustomDomain);

console.log(`\nFound ${domains.length} production domains:\n`);
console.log(`Custom domains (${customDomains.length}):`);
for (const d of customDomains) {
console.log(` ${d.domain}`);
}
console.log(`\nFern-hosted domains (${fernDomains.length}):`);
for (const d of fernDomains) {
console.log(` ${d.domain}`);
}
}
}
} catch (error) {
console.error("Error fetching domains:", error);
process.exit(1);
}
}

main();
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import type { Auth0OrgName } from "@/app/services/auth0/types";
import { getAuthenticatedSessionOrRedirect } from "@/app/services/dal/organization";
import WebAnalyticsPage from "@/components/web-analytics/WebAnalyticsPage";
import type { DocsUrl } from "@/utils/types";

export default async function Page(props: { params: Promise<{ orgName: Auth0OrgName; docsUrl: string }> }) {
const params = await props.params;
await getAuthenticatedSessionOrRedirect(params.orgName);

return <WebAnalyticsPage docsUrl={params.docsUrl} />;
return <WebAnalyticsPage docsUrl={params.docsUrl as DocsUrl} />;
}
Loading
Loading