diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2b96397..f802958 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,7 +15,7 @@ jobs: TURBO_TEAM: ${{ vars.TURBO_TEAM }} strategy: matrix: - node-version: [18.x, 20.x] + node-version: [20.x] steps: - name: Checkout uses: actions/checkout@v3 @@ -34,8 +34,5 @@ jobs: - name: Install dependencies run: pnpm install --frozen-lockfile - - name: Install Playwright Browsers - run: pnpm exec playwright install --with-deps - - - name: Run tests - run: pnpm test + - name: Build + run: pnpm build \ No newline at end of file diff --git a/README.md b/README.md index aca197d..692b70e 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ For this tutorial you'll need a [Vercel](https://vercel.com/) account. 1. Create a new storage edge config. 2. Create a new vercel project and import configuration-api. 3. Create a new project and import custom-domain-proxy. -4. Connect the storage to the project custom-domain-proxy. +4. Connect the storage to the project custom-domain-proxy. 5. Add the required env vars for the configuration-api ```bash @@ -20,4 +20,4 @@ AUTH_BEARER_TOKEN= # create your own bearer token that can access the projects ``` 6. Add a new domain using the configuration-api -7. Finish the domain configuration \ No newline at end of file +7. Finish the domain configuration diff --git a/apps/configuration-api/README.md b/apps/configuration-api/README.md index e0e0ed3..7773270 100644 --- a/apps/configuration-api/README.md +++ b/apps/configuration-api/README.md @@ -1 +1 @@ -# UI and API to configure custom domains \ No newline at end of file +# UI and API to configure custom domains diff --git a/apps/configuration-api/app/api/assign/route.ts b/apps/configuration-api/app/api/assign/route.ts index 4b49e44..7358b3f 100644 --- a/apps/configuration-api/app/api/assign/route.ts +++ b/apps/configuration-api/app/api/assign/route.ts @@ -1,97 +1,128 @@ - -import { addDomainToEdgeConfig, getEdgeconfigItem, updateEdgeConfigItem, removeDomainFromEdgeConfig, getAllItemsFromEdgeConfig } from "@customdomainready/sdk"; -import { NextResponse } from "next/server"; -import { z } from "zod"; +import { + addDomainToEdgeConfig, + getEdgeconfigItem, + updateEdgeConfigItem, + removeDomainFromEdgeConfig, + getAllItemsFromEdgeConfig, +} from '@customdomainready/sdk'; +import { NextResponse } from 'next/server'; +import { z } from 'zod'; const customDomainSchema = z.object({ - domain: z.string(), - slug: z.string(), - destination: z.string() -}) - -export async function GET( - req: Request, -) { - try { - const response = await getAllItemsFromEdgeConfig(process.env.VERCEL_CUSTOM_DOMAIN_PROXY_EDGE_CONFIG_ID!, process.env.VERCEL_TEAM_ID, process.env.AUTH_BEARER_TOKEN) - console.log(response) - return NextResponse.json({ - response: response.map((item: any) => ({ - id: item.key, - sourceDomain: `https://${item.key.split('-')[0].replace(/_/g, '.')}`, - slug: item.key.split('-').slice(1).join('/').replace(/_/g, '.'), - destinationPath: item.value, - })) - }); - } catch (error) { - console.error(error) - - return new Response("Internal Server Error", { status: 500 }) - } + domain: z.string(), + slug: z.string(), + destination: z.string(), +}); + +export async function GET(req: Request) { + try { + const response = await getAllItemsFromEdgeConfig( + process.env.VERCEL_CUSTOM_DOMAIN_PROXY_EDGE_CONFIG_ID!, + process.env.VERCEL_TEAM_ID, + process.env.AUTH_BEARER_TOKEN, + ); + console.log(response); + return NextResponse.json({ + response: response.map((item: any) => ({ + id: item.key, + sourceDomain: `https://${item.key.split('-')[0].replace(/_/g, '.')}`, + slug: item.key.split('-').slice(1).join('/').replace(/_/g, '.'), + destinationPath: item.value, + })), + }); + } catch (error) { + console.error(error); + + return new Response('Internal Server Error', { status: 500 }); + } } - - -export async function PATCH( - req: Request -) { - try { - const body = await req.json() - const payload = customDomainSchema.parse(body) - - const domainWithoutProtocol = payload.domain.replace(/^https?:\/\//, ''); - const key = `${domainWithoutProtocol.replace(/\./g, '_')}${payload.slug.replace(/\//g, '-')}`; - - // validate if key already exist and if yes update it instead of creating - const existingDomain = await getEdgeconfigItem(key, process.env.VERCEL_CUSTOM_DOMAIN_PROXY_EDGE_CONFIG_ID!, process.env.VERCEL_TEAM_ID, process.env.AUTH_BEARER_TOKEN); - - if (existingDomain){ - const updateResponse = await updateEdgeConfigItem(key, payload.destination, process.env.VERCEL_CUSTOM_DOMAIN_PROXY_EDGE_CONFIG_ID!, process.env.VERCEL_TEAM_ID, process.env.AUTH_BEARER_TOKEN); - console.log(updateResponse); - } else { - const createResponse = await addDomainToEdgeConfig(key, payload.destination, process.env.VERCEL_CUSTOM_DOMAIN_PROXY_EDGE_CONFIG_ID!, process.env.VERCEL_TEAM_ID, process.env.AUTH_BEARER_TOKEN); - console.log(createResponse); - } - - return new Response('created', { status: 201}) - } catch (error) { - console.log(error) - if (error instanceof z.ZodError) { - return new Response(JSON.stringify(error.issues), { status: 422 }) - } - - return new Response(null, { status: 500 }) +export async function PATCH(req: Request) { + try { + const body = await req.json(); + const payload = customDomainSchema.parse(body); + + const domainWithoutProtocol = payload.domain.replace(/^https?:\/\//, ''); + const key = `${domainWithoutProtocol.replace( + /\./g, + '_', + )}${payload.slug.replace(/\//g, '-')}`; + + // validate if key already exist and if yes update it instead of creating + const existingDomain = await getEdgeconfigItem( + key, + process.env.VERCEL_CUSTOM_DOMAIN_PROXY_EDGE_CONFIG_ID!, + process.env.VERCEL_TEAM_ID, + process.env.AUTH_BEARER_TOKEN, + ); + + if (existingDomain) { + const updateResponse = await updateEdgeConfigItem( + key, + payload.destination, + process.env.VERCEL_CUSTOM_DOMAIN_PROXY_EDGE_CONFIG_ID!, + process.env.VERCEL_TEAM_ID, + process.env.AUTH_BEARER_TOKEN, + ); + console.log(updateResponse); + } else { + const createResponse = await addDomainToEdgeConfig( + key, + payload.destination, + process.env.VERCEL_CUSTOM_DOMAIN_PROXY_EDGE_CONFIG_ID!, + process.env.VERCEL_TEAM_ID, + process.env.AUTH_BEARER_TOKEN, + ); + console.log(createResponse); } -} - -export async function DELETE( - req: Request -) { - try { - const body = await req.json(); - const payload = customDomainSchema.parse(body); - - const domainWithoutProtocol = payload.domain.replace(/^https?:\/\//, ''); - const key = `${domainWithoutProtocol.replace(/\./g, '_')}${payload.slug.replace(/\//g, '-')}`; - - const existingDomain = await getEdgeconfigItem(key, process.env.VERCEL_CUSTOM_DOMAIN_PROXY_EDGE_CONFIG_ID!, process.env.VERCEL_TEAM_ID, process.env.AUTH_BEARER_TOKEN); - - if (existingDomain) { - const deleteResponse = await removeDomainFromEdgeConfig(key, process.env.VERCEL_CUSTOM_DOMAIN_PROXY_EDGE_CONFIG_ID!, process.env.VERCEL_TEAM_ID, process.env.AUTH_BEARER_TOKEN); - console.log(deleteResponse); - return NextResponse.json('deleted', { status: 204 }); - } else { - return NextResponse.json('Domain not found', { status: 404 }); - } - } catch (error) { - console.log(error); - if (error instanceof z.ZodError) { - return NextResponse.json(JSON.stringify(error.issues), { status: 422 }); - } - return NextResponse.json(null, { status: 500 }); + return new Response('created', { status: 201 }); + } catch (error) { + console.log(error); + if (error instanceof z.ZodError) { + return new Response(JSON.stringify(error.issues), { status: 422 }); } + + return new Response(null, { status: 500 }); + } } +export async function DELETE(req: Request) { + try { + const body = await req.json(); + const payload = customDomainSchema.parse(body); + + const domainWithoutProtocol = payload.domain.replace(/^https?:\/\//, ''); + const key = `${domainWithoutProtocol.replace( + /\./g, + '_', + )}${payload.slug.replace(/\//g, '-')}`; + + const existingDomain = await getEdgeconfigItem( + key, + process.env.VERCEL_CUSTOM_DOMAIN_PROXY_EDGE_CONFIG_ID!, + process.env.VERCEL_TEAM_ID, + process.env.AUTH_BEARER_TOKEN, + ); + + if (existingDomain) { + const deleteResponse = await removeDomainFromEdgeConfig( + key, + process.env.VERCEL_CUSTOM_DOMAIN_PROXY_EDGE_CONFIG_ID!, + process.env.VERCEL_TEAM_ID, + process.env.AUTH_BEARER_TOKEN, + ); + console.log(deleteResponse); + return NextResponse.json('deleted', { status: 204 }); + } else { + return NextResponse.json('Domain not found', { status: 404 }); + } + } catch (error) { + console.log(error); + if (error instanceof z.ZodError) { + return NextResponse.json(JSON.stringify(error.issues), { status: 422 }); + } - \ No newline at end of file + return NextResponse.json(null, { status: 500 }); + } +} diff --git a/apps/configuration-api/app/api/domain/[slug]/route.ts b/apps/configuration-api/app/api/domain/[slug]/route.ts index 3efbc36..30f8dca 100644 --- a/apps/configuration-api/app/api/domain/[slug]/route.ts +++ b/apps/configuration-api/app/api/domain/[slug]/route.ts @@ -1,17 +1,20 @@ -import { - removeDomainFromVercelProject, -} from "@customdomainready/sdk"; +import { removeDomainFromVercelProject } from '@customdomainready/sdk'; export async function DELETE( - req: Request, - { params }: { params: { slug: string } }, + req: Request, + { params }: { params: { slug: string } }, ) { - const domain = decodeURIComponent(params.slug); - const response = await removeDomainFromVercelProject(domain, process.env.VERCEL_PROJECT_ID!, process.env.VERCEL_TEAM_ID, process.env.AUTH_BEARER_TOKEN); + const domain = decodeURIComponent(params.slug); + const response = await removeDomainFromVercelProject( + domain, + process.env.VERCEL_PROJECT_ID!, + process.env.VERCEL_TEAM_ID, + process.env.AUTH_BEARER_TOKEN, + ); - if (response.error) { - return new Response(response.error.message, { status: 400 }) - } + if (response.error) { + return new Response(response.error.message, { status: 400 }); + } - return new Response(null, { status: 204 }) -} \ No newline at end of file + return new Response(null, { status: 204 }); +} diff --git a/apps/configuration-api/app/api/domain/[slug]/verify/route.ts b/apps/configuration-api/app/api/domain/[slug]/verify/route.ts index 815c61a..20f172a 100644 --- a/apps/configuration-api/app/api/domain/[slug]/verify/route.ts +++ b/apps/configuration-api/app/api/domain/[slug]/verify/route.ts @@ -1,55 +1,69 @@ import { - getConfigResponse, - getDomainResponse, - verifyDomain, -} from "@customdomainready/sdk"; -import { NextResponse } from "next/server"; + getConfigResponse, + getDomainResponse, + verifyDomain, +} from '@customdomainready/sdk'; +import { NextResponse } from 'next/server'; export type DomainVerificationStatusProps = -| "Valid Configuration" -| "Invalid Configuration" -| "Pending Verification" -| "Domain Not Found" -| "Unknown Error"; + | 'Valid Configuration' + | 'Invalid Configuration' + | 'Pending Verification' + | 'Domain Not Found' + | 'Unknown Error'; export async function GET( - _req: Request, - { params }: { params: { slug: string } }, + _req: Request, + { params }: { params: { slug: string } }, ) { - const domain = decodeURIComponent(params.slug); - - let status: DomainVerificationStatusProps = "Valid Configuration"; - - const [domainJson, configJson] = await Promise.all([ - getDomainResponse(domain, process.env.VERCEL_PROJECT_ID!, process.env.VERCEL_TEAM_ID, process.env.AUTH_BEARER_TOKEN), - getConfigResponse(domain, process.env.VERCEL_TEAM_ID, process.env.AUTH_BEARER_TOKEN), - ]); - - if (domainJson?.error?.code === "not_found") { - // domain not found on Vercel project - status = "Domain Not Found"; - - // unknown error - } else if (domainJson.error) { - status = "Unknown Error"; - - // if domain is not verified, we try to verify now - } else if (!domainJson.verified) { - status = "Pending Verification"; - const verificationJson = await verifyDomain(domain, process.env.VERCEL_PROJECT_ID!, process.env.VERCEL_TEAM_ID, process.env.AUTH_BEARER_TOKEN); - - // domain was just verified - if (verificationJson && verificationJson.verified) { - status = "Valid Configuration"; - } - } else if (configJson.misconfigured) { - status = "Invalid Configuration"; - } else { - status = "Valid Configuration"; + const domain = decodeURIComponent(params.slug); + + let status: DomainVerificationStatusProps = 'Valid Configuration'; + + const [domainJson, configJson] = await Promise.all([ + getDomainResponse( + domain, + process.env.VERCEL_PROJECT_ID!, + process.env.VERCEL_TEAM_ID, + process.env.AUTH_BEARER_TOKEN, + ), + getConfigResponse( + domain, + process.env.VERCEL_TEAM_ID, + process.env.AUTH_BEARER_TOKEN, + ), + ]); + + if (domainJson?.error?.code === 'not_found') { + // domain not found on Vercel project + status = 'Domain Not Found'; + + // unknown error + } else if (domainJson.error) { + status = 'Unknown Error'; + + // if domain is not verified, we try to verify now + } else if (!domainJson.verified) { + status = 'Pending Verification'; + const verificationJson = await verifyDomain( + domain, + process.env.VERCEL_PROJECT_ID!, + process.env.VERCEL_TEAM_ID, + process.env.AUTH_BEARER_TOKEN, + ); + + // domain was just verified + if (verificationJson && verificationJson.verified) { + status = 'Valid Configuration'; } + } else if (configJson.misconfigured) { + status = 'Invalid Configuration'; + } else { + status = 'Valid Configuration'; + } - return NextResponse.json({ - status, - domainJson, - }); -} \ No newline at end of file + return NextResponse.json({ + status, + domainJson, + }); +} diff --git a/apps/configuration-api/app/api/domain/route.ts b/apps/configuration-api/app/api/domain/route.ts index 7280cf1..a17d12b 100644 --- a/apps/configuration-api/app/api/domain/route.ts +++ b/apps/configuration-api/app/api/domain/route.ts @@ -1,42 +1,51 @@ -import { addDomainToVercel, getDomains, getAllItemsFromEdgeConfig } from "@customdomainready/sdk"; -import { NextResponse } from "next/server"; +import { + addDomainToVercel, + getDomains, + getAllItemsFromEdgeConfig, +} from '@customdomainready/sdk'; +import { NextResponse } from 'next/server'; -import * as z from "zod" +import * as z from 'zod'; const customDomainSchema = z.object({ - domain: z.string(), -}) - -export async function POST( - req: Request, -) { - try { - // Get the request body and validate it. - const body = await req.json() - const payload = customDomainSchema.parse(body) - - const domain = payload.domain; - - // Check if the domain already exists - const existingDomains = await getDomains(process.env.VERCEL_PROJECT_ID!, process.env.VERCEL_TEAM_ID, process.env.AUTH_BEARER_TOKEN); - if (existingDomains.domains.some((d: any) => d.name === domain)) { - return new Response("Domain already exists", { status: 200 }); - } - - const response = await addDomainToVercel(domain, process.env.VERCEL_PROJECT_ID!, process.env.VERCEL_TEAM_ID, process.env.AUTH_BEARER_TOKEN); - - if (response.error) { - return new Response(response.error.message, { status: 400 }) - } - - return NextResponse.json({ - response - }); - } catch (error) { - console.error(error) - - return new Response("Internal Server Error", { status: 500 }) + domain: z.string(), +}); + +export async function POST(req: Request) { + try { + // Get the request body and validate it. + const body = await req.json(); + const payload = customDomainSchema.parse(body); + + const domain = payload.domain; + + // Check if the domain already exists + const existingDomains = await getDomains( + process.env.VERCEL_PROJECT_ID!, + process.env.VERCEL_TEAM_ID, + process.env.AUTH_BEARER_TOKEN, + ); + if (existingDomains.domains.some((d: any) => d.name === domain)) { + return new Response('Domain already exists', { status: 200 }); } -} + const response = await addDomainToVercel( + domain, + process.env.VERCEL_PROJECT_ID!, + process.env.VERCEL_TEAM_ID, + process.env.AUTH_BEARER_TOKEN, + ); + + if (response.error) { + return new Response(response.error.message, { status: 400 }); + } + return NextResponse.json({ + response, + }); + } catch (error) { + console.error(error); + + return new Response('Internal Server Error', { status: 500 }); + } +} diff --git a/apps/configuration-api/app/layout.tsx b/apps/configuration-api/app/layout.tsx index 94657d6..28b7e42 100644 --- a/apps/configuration-api/app/layout.tsx +++ b/apps/configuration-api/app/layout.tsx @@ -1,6 +1,6 @@ import { Inter } from 'next/font/google'; -import './global.css' +import './global.css'; const inter = Inter({ subsets: ['latin'] }); diff --git a/apps/configuration-api/app/page.tsx b/apps/configuration-api/app/page.tsx index a7661f5..7a621a0 100644 --- a/apps/configuration-api/app/page.tsx +++ b/apps/configuration-api/app/page.tsx @@ -1,4 +1,4 @@ -import CustomDomainConfig from "@/components/custom-domain-config" +import CustomDomainConfig from '@/components/custom-domain-config'; export default function Home() { return ( @@ -6,6 +6,5 @@ export default function Home() {

Custom Domain Ready

- ) + ); } - diff --git a/apps/configuration-api/components/custom-domain-config.tsx b/apps/configuration-api/components/custom-domain-config.tsx index 79e929d..33b63f2 100644 --- a/apps/configuration-api/components/custom-domain-config.tsx +++ b/apps/configuration-api/components/custom-domain-config.tsx @@ -1,39 +1,41 @@ -"use client" +'use client'; -import { useState, useEffect } from "react" -import { Button } from "@/components/ui/button" -import { Input } from "@/components/ui/input" -import { Label } from "@/components/ui/label" -import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card" -import { Trash2, RefreshCw } from 'lucide-react' +import { useState, useEffect } from 'react'; +import { Button } from '@/components/ui/button'; +import { Input } from '@/components/ui/input'; +import { Label } from '@/components/ui/label'; +import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; +import { Trash2, RefreshCw } from 'lucide-react'; interface DomainConfig { - id: string - sourceDomain: string - slug: string - destinationPath: string + id: string; + sourceDomain: string; + slug: string; + destinationPath: string; } export default function CustomDomainConfig() { - const [configs, setConfigs] = useState([]) - const [newConfig, setNewConfig] = useState>({ - sourceDomain: "", - slug: "", - destinationPath: "", - }) + const [configs, setConfigs] = useState([]); + const [newConfig, setNewConfig] = useState>({ + sourceDomain: '', + slug: '', + destinationPath: '', + }); const fetchConfigs = async () => { try { const response = await fetch('/api/assign'); const data = await response.json(); - console.log(data) - setConfigs(data.response.map((domain: any) => ({ - id: domain.id, - sourceDomain: domain.sourceDomain, - slug: domain.slug, - destinationPath: domain.destinationPath, - }))); + console.log(data); + setConfigs( + data.response.map((domain: any) => ({ + id: domain.id, + sourceDomain: domain.sourceDomain, + slug: domain.slug, + destinationPath: domain.destinationPath, + })), + ); } catch (error) { - console.error("Failed to fetch domain configurations:", error); + console.error('Failed to fetch domain configurations:', error); } }; @@ -43,7 +45,9 @@ export default function CustomDomainConfig() { const handleAddDomainAndAlias = async () => { try { - const domainExists = configs.some(config => config.sourceDomain === newConfig.sourceDomain); + const domainExists = configs.some( + config => config.sourceDomain === newConfig.sourceDomain, + ); if (!domainExists) { const domainResponse = await fetch('/api/domain', { @@ -76,48 +80,56 @@ export default function CustomDomainConfig() { } const newAlias = await aliasResponse.json(); - setConfigs((prevConfigs) => [...prevConfigs, newAlias]); + setConfigs(prevConfigs => [...prevConfigs, newAlias]); setNewConfig({ - sourceDomain: "", - slug: "", - destinationPath: "", + sourceDomain: '', + slug: '', + destinationPath: '', }); - } catch (error) { - console.error("Error adding domain and alias:", error); + console.error('Error adding domain and alias:', error); } }; - const removeConfig = async (sourceDomain: string, slug: string, destination: string) => { + const removeConfig = async ( + sourceDomain: string, + slug: string, + destination: string, + ) => { try { const response = await fetch('/api/assign', { method: 'DELETE', headers: { 'Content-Type': 'application/json', }, - body: JSON.stringify({ domain: sourceDomain, slug: slug, destination: destination}), + body: JSON.stringify({ + domain: sourceDomain, + slug: slug, + destination: destination, + }), }); if (!response.ok) { throw new Error('Failed to remove config'); } - fetchConfigs(); } catch (error) { - console.error("Error removing config:", error); + console.error('Error removing config:', error); } - } + }; const refreshDomainStatus = async (sourceDomain: string) => { try { - const response = await fetch(`/api/domain/${sourceDomain.replace(/^https?:\/\//, '')}/verify`); + const response = await fetch( + `/api/domain/${sourceDomain.replace(/^https?:\/\//, '')}/verify`, + ); const data = await response.json(); alert(`Domain Status: ${data.status}`); } catch (error) { - console.error("Failed to verify domain status:", error); + console.error('Failed to verify domain status:', error); } - } + }; return ( @@ -125,14 +137,14 @@ export default function CustomDomainConfig() { Custom Domain Configuration -
e.preventDefault()} className="space-y-4"> + e.preventDefault()} className="space-y-4">
+ onChange={e => setNewConfig({ ...newConfig, sourceDomain: e.target.value }) } placeholder="example.com" @@ -143,7 +155,7 @@ export default function CustomDomainConfig() { + onChange={e => setNewConfig({ ...newConfig, slug: e.target.value }) } placeholder="blog" @@ -154,8 +166,11 @@ export default function CustomDomainConfig() { - setNewConfig({ ...newConfig, destinationPath: e.target.value }) + onChange={e => + setNewConfig({ + ...newConfig, + destinationPath: e.target.value, + }) } placeholder="/posts" /> @@ -166,7 +181,7 @@ export default function CustomDomainConfig() {

Current Configurations

- {configs.map((config) => ( + {configs.map(config => (
@@ -181,7 +196,13 @@ export default function CustomDomainConfig() { @@ -199,6 +220,5 @@ export default function CustomDomainConfig() {
- ) + ); } - diff --git a/apps/configuration-api/components/ui/button.tsx b/apps/configuration-api/components/ui/button.tsx index 65d4fcd..5b1de3b 100644 --- a/apps/configuration-api/components/ui/button.tsx +++ b/apps/configuration-api/components/ui/button.tsx @@ -1,57 +1,57 @@ -import * as React from "react" -import { Slot } from "@radix-ui/react-slot" -import { cva, type VariantProps } from "class-variance-authority" +import * as React from 'react'; +import { Slot } from '@radix-ui/react-slot'; +import { cva, type VariantProps } from 'class-variance-authority'; -import { cn } from "@/lib/utils" +import { cn } from '@/lib/utils'; const buttonVariants = cva( - "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0", + 'inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0', { variants: { variant: { default: - "bg-primary text-primary-foreground shadow hover:bg-primary/90", + 'bg-primary text-primary-foreground shadow hover:bg-primary/90', destructive: - "bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90", + 'bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90', outline: - "border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground", + 'border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground', secondary: - "bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80", - ghost: "hover:bg-accent hover:text-accent-foreground", - link: "text-primary underline-offset-4 hover:underline", + 'bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80', + ghost: 'hover:bg-accent hover:text-accent-foreground', + link: 'text-primary underline-offset-4 hover:underline', }, size: { - default: "h-9 px-4 py-2", - sm: "h-8 rounded-md px-3 text-xs", - lg: "h-10 rounded-md px-8", - icon: "h-9 w-9", + default: 'h-9 px-4 py-2', + sm: 'h-8 rounded-md px-3 text-xs', + lg: 'h-10 rounded-md px-8', + icon: 'h-9 w-9', }, }, defaultVariants: { - variant: "default", - size: "default", + variant: 'default', + size: 'default', }, - } -) + }, +); export interface ButtonProps extends React.ButtonHTMLAttributes, VariantProps { - asChild?: boolean + asChild?: boolean; } const Button = React.forwardRef( ({ className, variant, size, asChild = false, ...props }, ref) => { - const Comp = asChild ? Slot : "button" + const Comp = asChild ? Slot : 'button'; return ( - ) - } -) -Button.displayName = "Button" + ); + }, +); +Button.displayName = 'Button'; -export { Button, buttonVariants } +export { Button, buttonVariants }; diff --git a/apps/configuration-api/components/ui/card.tsx b/apps/configuration-api/components/ui/card.tsx index cabfbfc..a9a6a6a 100644 --- a/apps/configuration-api/components/ui/card.tsx +++ b/apps/configuration-api/components/ui/card.tsx @@ -1,6 +1,6 @@ -import * as React from "react" +import * as React from 'react'; -import { cn } from "@/lib/utils" +import { cn } from '@/lib/utils'; const Card = React.forwardRef< HTMLDivElement, @@ -9,13 +9,13 @@ const Card = React.forwardRef<
-)) -Card.displayName = "Card" +)); +Card.displayName = 'Card'; const CardHeader = React.forwardRef< HTMLDivElement, @@ -23,11 +23,11 @@ const CardHeader = React.forwardRef< >(({ className, ...props }, ref) => (
-)) -CardHeader.displayName = "CardHeader" +)); +CardHeader.displayName = 'CardHeader'; const CardTitle = React.forwardRef< HTMLDivElement, @@ -35,11 +35,11 @@ const CardTitle = React.forwardRef< >(({ className, ...props }, ref) => (
-)) -CardTitle.displayName = "CardTitle" +)); +CardTitle.displayName = 'CardTitle'; const CardDescription = React.forwardRef< HTMLDivElement, @@ -47,19 +47,19 @@ const CardDescription = React.forwardRef< >(({ className, ...props }, ref) => (
-)) -CardDescription.displayName = "CardDescription" +)); +CardDescription.displayName = 'CardDescription'; const CardContent = React.forwardRef< HTMLDivElement, React.HTMLAttributes >(({ className, ...props }, ref) => ( -
-)) -CardContent.displayName = "CardContent" +
+)); +CardContent.displayName = 'CardContent'; const CardFooter = React.forwardRef< HTMLDivElement, @@ -67,10 +67,17 @@ const CardFooter = React.forwardRef< >(({ className, ...props }, ref) => (
-)) -CardFooter.displayName = "CardFooter" +)); +CardFooter.displayName = 'CardFooter'; -export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent } +export { + Card, + CardHeader, + CardFooter, + CardTitle, + CardDescription, + CardContent, +}; diff --git a/apps/configuration-api/components/ui/input.tsx b/apps/configuration-api/components/ui/input.tsx index 69b64fb..389bf52 100644 --- a/apps/configuration-api/components/ui/input.tsx +++ b/apps/configuration-api/components/ui/input.tsx @@ -1,22 +1,22 @@ -import * as React from "react" +import * as React from 'react'; -import { cn } from "@/lib/utils" +import { cn } from '@/lib/utils'; -const Input = React.forwardRef>( +const Input = React.forwardRef>( ({ className, type, ...props }, ref) => { return ( - ) - } -) -Input.displayName = "Input" + ); + }, +); +Input.displayName = 'Input'; -export { Input } +export { Input }; diff --git a/apps/configuration-api/components/ui/label.tsx b/apps/configuration-api/components/ui/label.tsx index 5341821..7114fb0 100644 --- a/apps/configuration-api/components/ui/label.tsx +++ b/apps/configuration-api/components/ui/label.tsx @@ -1,14 +1,14 @@ -"use client" +'use client'; -import * as React from "react" -import * as LabelPrimitive from "@radix-ui/react-label" -import { cva, type VariantProps } from "class-variance-authority" +import * as React from 'react'; +import * as LabelPrimitive from '@radix-ui/react-label'; +import { cva, type VariantProps } from 'class-variance-authority'; -import { cn } from "@/lib/utils" +import { cn } from '@/lib/utils'; const labelVariants = cva( - "text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70" -) + 'text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70', +); const Label = React.forwardRef< React.ElementRef, @@ -20,7 +20,7 @@ const Label = React.forwardRef< className={cn(labelVariants(), className)} {...props} /> -)) -Label.displayName = LabelPrimitive.Root.displayName +)); +Label.displayName = LabelPrimitive.Root.displayName; -export { Label } +export { Label }; diff --git a/apps/configuration-api/lib/utils.ts b/apps/configuration-api/lib/utils.ts index bd0c391..2819a83 100644 --- a/apps/configuration-api/lib/utils.ts +++ b/apps/configuration-api/lib/utils.ts @@ -1,6 +1,6 @@ -import { clsx, type ClassValue } from "clsx" -import { twMerge } from "tailwind-merge" +import { clsx, type ClassValue } from 'clsx'; +import { twMerge } from 'tailwind-merge'; export function cn(...inputs: ClassValue[]) { - return twMerge(clsx(inputs)) + return twMerge(clsx(inputs)); } diff --git a/apps/configuration-api/tailwind.config.ts b/apps/configuration-api/tailwind.config.ts index abf7257..776275d 100644 --- a/apps/configuration-api/tailwind.config.ts +++ b/apps/configuration-api/tailwind.config.ts @@ -1,21 +1,21 @@ -import type { Config } from 'tailwindcss' - +import type { Config } from 'tailwindcss'; + const config: Config = { - content: [ - "./app/**/*.{js,ts,jsx,tsx,mdx}", - "./pages/**/*.{js,ts,jsx,tsx,mdx}", - "./components/**/*.{js,ts,jsx,tsx,mdx}", - ], - theme: { - extend: { - backgroundImage: { - 'gradient-radial': 'radial-gradient(var(--tw-gradient-stops))', - 'gradient-conic': - 'conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))', - }, - }, - }, - plugins: [], + content: [ + './app/**/*.{js,ts,jsx,tsx,mdx}', + './pages/**/*.{js,ts,jsx,tsx,mdx}', + './components/**/*.{js,ts,jsx,tsx,mdx}', + ], + theme: { + extend: { + backgroundImage: { + 'gradient-radial': 'radial-gradient(var(--tw-gradient-stops))', + 'gradient-conic': + 'conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))', + }, + }, + }, + plugins: [], }; -export default config +export default config; diff --git a/apps/custom-domain-proxy/README.md b/apps/custom-domain-proxy/README.md index 8befc5f..e2ee31a 100644 --- a/apps/custom-domain-proxy/README.md +++ b/apps/custom-domain-proxy/README.md @@ -1 +1 @@ -# Reverse proxy for custom domains \ No newline at end of file +# Reverse proxy for custom domains diff --git a/apps/custom-domain-proxy/app/page.tsx b/apps/custom-domain-proxy/app/page.tsx index 7a02cab..c0efefa 100644 --- a/apps/custom-domain-proxy/app/page.tsx +++ b/apps/custom-domain-proxy/app/page.tsx @@ -3,6 +3,5 @@ export default function Page() {

Custom Domain Ready

- ) + ); } - diff --git a/apps/custom-domain-proxy/middleware.ts b/apps/custom-domain-proxy/middleware.ts index 35123d4..e2553f1 100644 --- a/apps/custom-domain-proxy/middleware.ts +++ b/apps/custom-domain-proxy/middleware.ts @@ -2,21 +2,21 @@ import { NextResponse } from 'next/server'; import { get } from '@vercel/edge-config'; export const config = { - matcher: ['/(.*)'], + matcher: ['/(.*)'], }; export async function middleware(req: Request) { - console.log(req.url) + console.log(req.url); - const urlWithoutProtocol = req.url.replace(/^https?:\/\//, ''); - const key = urlWithoutProtocol.replace(/\./g, '_').replace(/\//g, '-'); - const destination = await get(key); - const destinationURL = new URL(destination?.toString() || ''); + const urlWithoutProtocol = req.url.replace(/^https?:\/\//, ''); + const key = urlWithoutProtocol.replace(/\./g, '_').replace(/\//g, '-'); + const destination = await get(key); + const destinationURL = new URL(destination?.toString() || ''); - if (destinationURL) { - destinationURL.search = new URL(req.url).search; // Preserve query params - return NextResponse.rewrite(destinationURL); - } + if (destinationURL) { + destinationURL.search = new URL(req.url).search; // Preserve query params + return NextResponse.rewrite(destinationURL); + } - return new NextResponse('Not Found', { status: 404 }); -} \ No newline at end of file + return new NextResponse('Not Found', { status: 404 }); +} diff --git a/packages/sdk/README.md b/packages/sdk/README.md index 55b498f..2f423a4 100644 --- a/packages/sdk/README.md +++ b/packages/sdk/README.md @@ -1,3 +1,3 @@ # CustomDomainReady SDK -Manage your vercel accounts. \ No newline at end of file +Manage your vercel accounts. diff --git a/packages/sdk/lib/domains.ts b/packages/sdk/lib/domains.ts index 9a67523..e3777ba 100644 --- a/packages/sdk/lib/domains.ts +++ b/packages/sdk/lib/domains.ts @@ -1,158 +1,166 @@ import { - DomainResponse, - DomainConfigResponse, - DomainVerificationResponse, -} from "../types"; + DomainResponse, + DomainConfigResponse, + DomainVerificationResponse, +} from '../types'; export const getDomains = async ( - projectIdVercel: string, - teamIdVercel?: string, - authBearerToken?: string + projectIdVercel: string, + teamIdVercel?: string, + authBearerToken?: string, ) => { - return await fetch( - `https://api.vercel.com/v9/projects/${projectIdVercel}/domains${teamIdVercel ? `?teamId=${teamIdVercel}` : ""}`, - { - headers: { - Authorization: `Bearer ${authBearerToken}`, - }, - } - ).then((res) => res.json()); + return await fetch( + `https://api.vercel.com/v9/projects/${projectIdVercel}/domains${ + teamIdVercel ? `?teamId=${teamIdVercel}` : '' + }`, + { + headers: { + Authorization: `Bearer ${authBearerToken}`, + }, + }, + ).then(res => res.json()); }; export const addDomainToVercel = async ( - domain: string, - projectIdVercel: string, - teamIdVercel?: string, - authBearerToken?: string + domain: string, + projectIdVercel: string, + teamIdVercel?: string, + authBearerToken?: string, ) => { - return await fetch( - `https://api.vercel.com/v10/projects/${projectIdVercel}/domains${teamIdVercel ? `?teamId=${teamIdVercel}` : "" - }`, - { - method: "POST", - headers: { - Authorization: `Bearer ${authBearerToken}`, - "Content-Type": "application/json", - }, - body: JSON.stringify({ - name: domain, - }), - } - ).then((res) => res.json()); + return await fetch( + `https://api.vercel.com/v10/projects/${projectIdVercel}/domains${ + teamIdVercel ? `?teamId=${teamIdVercel}` : '' + }`, + { + method: 'POST', + headers: { + Authorization: `Bearer ${authBearerToken}`, + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + name: domain, + }), + }, + ).then(res => res.json()); }; export const removeDomainFromVercelProject = async ( - domain: string, - projectIdVercel: string, - teamIdVercel?: string, - authBearerToken?: string + domain: string, + projectIdVercel: string, + teamIdVercel?: string, + authBearerToken?: string, ) => { - return await fetch( - `https://api.vercel.com/v9/projects/${projectIdVercel}/domains/${domain}${teamIdVercel ? `?teamId=${teamIdVercel}` : "" - }`, - { - headers: { - Authorization: `Bearer ${authBearerToken}`, - }, - method: "DELETE", - } - ).then((res) => res.json()); + return await fetch( + `https://api.vercel.com/v9/projects/${projectIdVercel}/domains/${domain}${ + teamIdVercel ? `?teamId=${teamIdVercel}` : '' + }`, + { + headers: { + Authorization: `Bearer ${authBearerToken}`, + }, + method: 'DELETE', + }, + ).then(res => res.json()); }; export const removeDomainFromVercelTeam = async ( - domain: string, - teamIdVercel?: string, - authBearerToken?: string + domain: string, + teamIdVercel?: string, + authBearerToken?: string, ) => { - return await fetch( - `https://api.vercel.com/v6/domains/${domain}${teamIdVercel ? `?teamId=${teamIdVercel}` : "" - }`, - { - headers: { - Authorization: `Bearer ${authBearerToken}`, - }, - method: "DELETE", - } - ).then((res) => res.json()); + return await fetch( + `https://api.vercel.com/v6/domains/${domain}${ + teamIdVercel ? `?teamId=${teamIdVercel}` : '' + }`, + { + headers: { + Authorization: `Bearer ${authBearerToken}`, + }, + method: 'DELETE', + }, + ).then(res => res.json()); }; export const getDomainResponse = async ( - domain: string, - projectIdVercel: string, - teamIdVercel?: string, - authBearerToken?: string + domain: string, + projectIdVercel: string, + teamIdVercel?: string, + authBearerToken?: string, ): Promise => { - return await fetch( - `https://api.vercel.com/v9/projects/${projectIdVercel}/domains/${domain}${teamIdVercel ? `?teamId=${teamIdVercel}` : "" - }`, - { - method: "GET", - headers: { - Authorization: `Bearer ${authBearerToken}`, - "Content-Type": "application/json", - }, - } - ).then((res) => { - return res.json(); - }); + return await fetch( + `https://api.vercel.com/v9/projects/${projectIdVercel}/domains/${domain}${ + teamIdVercel ? `?teamId=${teamIdVercel}` : '' + }`, + { + method: 'GET', + headers: { + Authorization: `Bearer ${authBearerToken}`, + 'Content-Type': 'application/json', + }, + }, + ).then(res => { + return res.json(); + }); }; export const getConfigResponse = async ( - domain: string, - teamIdVercel?: string, - authBearerToken?: string + domain: string, + teamIdVercel?: string, + authBearerToken?: string, ): Promise => { - return await fetch( - `https://api.vercel.com/v6/domains/${domain}/config${teamIdVercel ? `?teamId=${teamIdVercel}` : "" - }`, - { - method: "GET", - headers: { - Authorization: `Bearer ${authBearerToken}`, - "Content-Type": "application/json", - }, - } - ).then((res) => res.json()); + return await fetch( + `https://api.vercel.com/v6/domains/${domain}/config${ + teamIdVercel ? `?teamId=${teamIdVercel}` : '' + }`, + { + method: 'GET', + headers: { + Authorization: `Bearer ${authBearerToken}`, + 'Content-Type': 'application/json', + }, + }, + ).then(res => res.json()); }; export const verifyDomain = async ( - domain: string, - projectIdVercel: string, - teamIdVercel?: string, - authBearerToken?: string + domain: string, + projectIdVercel: string, + teamIdVercel?: string, + authBearerToken?: string, ): Promise => { - return await fetch( - `https://api.vercel.com/v9/projects/${projectIdVercel}/domains/${domain}/verify${teamIdVercel ? `?teamId=${teamIdVercel}` : "" - }`, - { - method: "POST", - headers: { - Authorization: `Bearer ${authBearerToken}`, - "Content-Type": "application/json", - }, - } - ).then((res) => res.json()); + return await fetch( + `https://api.vercel.com/v9/projects/${projectIdVercel}/domains/${domain}/verify${ + teamIdVercel ? `?teamId=${teamIdVercel}` : '' + }`, + { + method: 'POST', + headers: { + Authorization: `Bearer ${authBearerToken}`, + 'Content-Type': 'application/json', + }, + }, + ).then(res => res.json()); }; export const getSubdomain = (name: string, apexName: string) => { - if (name === apexName) return null; - return name.slice(0, name.length - apexName.length - 1); + if (name === apexName) return null; + return name.slice(0, name.length - apexName.length - 1); }; export const getApexDomain = (url: string) => { - let domain; - try { - domain = new URL(url).hostname; - } catch (e) { - return ""; - } - const parts = domain.split("."); - if (parts.length > 2) { - return parts.slice(-2).join("."); - } - return domain; + let domain; + try { + domain = new URL(url).hostname; + } catch (e) { + return ''; + } + const parts = domain.split('.'); + if (parts.length > 2) { + return parts.slice(-2).join('.'); + } + return domain; }; export const validDomainRegex = new RegExp( - /^([a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,}$/ -); \ No newline at end of file + /^([a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,}$/, +); diff --git a/packages/sdk/lib/edge-config.ts b/packages/sdk/lib/edge-config.ts index 0e56fda..30d5acb 100644 --- a/packages/sdk/lib/edge-config.ts +++ b/packages/sdk/lib/edge-config.ts @@ -1,115 +1,114 @@ - export const updateEdgeConfigItem = async ( - key: string, - value: string, - edgeConfigName: string, - teamIdVercel?: string, - authBearerToken?: string + key: string, + value: string, + edgeConfigName: string, + teamIdVercel?: string, + authBearerToken?: string, ) => { - return await fetch(`https://api.vercel.com/v1/edge-config/${edgeConfigName}/items?edgeConfigId=${edgeConfigName}&teamId=${teamIdVercel}`, - { - method: "PATCH", - headers: { - Authorization: `Bearer ${authBearerToken}`, - "Content-Type": "application/json", - }, - body: JSON.stringify({ - items: [ - { - "operation": "update", - "key": key, - "value": value, - } - ] - }), - } - ).then((res) => res.json()); -} - + return await fetch( + `https://api.vercel.com/v1/edge-config/${edgeConfigName}/items?edgeConfigId=${edgeConfigName}&teamId=${teamIdVercel}`, + { + method: 'PATCH', + headers: { + Authorization: `Bearer ${authBearerToken}`, + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + items: [ + { + operation: 'update', + key: key, + value: value, + }, + ], + }), + }, + ).then(res => res.json()); +}; export const getEdgeconfigItem = async ( - key: string, - edgeConfigName: string, - teamIdVercel?: string, - authBearerToken?: string + key: string, + edgeConfigName: string, + teamIdVercel?: string, + authBearerToken?: string, ) => { - return await fetch(`https://api.vercel.com/v1/edge-config/${edgeConfigName}/item/${key}?teamId=${teamIdVercel}`, - { - headers: { - Authorization: `Bearer ${authBearerToken}`, - }, - } - ).then((res) => - res.body === null ? null : res.json() - ); -} - + return await fetch( + `https://api.vercel.com/v1/edge-config/${edgeConfigName}/item/${key}?teamId=${teamIdVercel}`, + { + headers: { + Authorization: `Bearer ${authBearerToken}`, + }, + }, + ).then(res => (res.body === null ? null : res.json())); +}; export const addDomainToEdgeConfig = async ( - chatbotId: string, - domain: string, - edgeConfigName: string, - teamIdVercel?: string, - authBearerToken?: string + chatbotId: string, + domain: string, + edgeConfigName: string, + teamIdVercel?: string, + authBearerToken?: string, ) => { - return await fetch(`https://api.vercel.com/v1/edge-config/${edgeConfigName}/items?edgeConfigId=${edgeConfigName}&teamId=${teamIdVercel}`, - { - method: "PATCH", - headers: { - Authorization: `Bearer ${authBearerToken}`, - "Content-Type": "application/json", - }, - body: JSON.stringify({ - items: [ - { - "operation": "create", - "key": chatbotId, - "value": domain, - } - ] - }), - } - ).then((res) => res.json()); + return await fetch( + `https://api.vercel.com/v1/edge-config/${edgeConfigName}/items?edgeConfigId=${edgeConfigName}&teamId=${teamIdVercel}`, + { + method: 'PATCH', + headers: { + Authorization: `Bearer ${authBearerToken}`, + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + items: [ + { + operation: 'create', + key: chatbotId, + value: domain, + }, + ], + }), + }, + ).then(res => res.json()); }; export const removeDomainFromEdgeConfig = async ( - key: string, - edgeConfigName: string, - teamIdVercel?: string, - authBearerToken?: string + key: string, + edgeConfigName: string, + teamIdVercel?: string, + authBearerToken?: string, ) => { - return await fetch(`https://api.vercel.com/v1/edge-config/${edgeConfigName}/items?edgeConfigId=${edgeConfigName}&teamId=${teamIdVercel}`, - { - method: "PATCH", - headers: { - Authorization: `Bearer ${authBearerToken}`, - "Content-Type": "application/json", - }, - body: JSON.stringify({ - items: [ - { - "operation": "delete", - "key": key, - } - ] - }), - } - ).then((res) => res.json()); + return await fetch( + `https://api.vercel.com/v1/edge-config/${edgeConfigName}/items?edgeConfigId=${edgeConfigName}&teamId=${teamIdVercel}`, + { + method: 'PATCH', + headers: { + Authorization: `Bearer ${authBearerToken}`, + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + items: [ + { + operation: 'delete', + key: key, + }, + ], + }), + }, + ).then(res => res.json()); }; - export const getAllItemsFromEdgeConfig = async ( - edgeConfigName: string, - teamIdVercel?: string, - authBearerToken?: string + edgeConfigName: string, + teamIdVercel?: string, + authBearerToken?: string, ) => { - return await fetch(`https://api.vercel.com/v1/edge-config/${edgeConfigName}/items?edgeConfigId=${edgeConfigName}&teamId=${teamIdVercel}`, - { - method: "GET", - headers: { - Authorization: `Bearer ${authBearerToken}`, - "Content-Type": "application/json", - } - } - ).then((res) => res.json()); + return await fetch( + `https://api.vercel.com/v1/edge-config/${edgeConfigName}/items?edgeConfigId=${edgeConfigName}&teamId=${teamIdVercel}`, + { + method: 'GET', + headers: { + Authorization: `Bearer ${authBearerToken}`, + 'Content-Type': 'application/json', + }, + }, + ).then(res => res.json()); }; diff --git a/packages/sdk/src/index.ts b/packages/sdk/src/index.ts index 001d5de..7a935de 100644 --- a/packages/sdk/src/index.ts +++ b/packages/sdk/src/index.ts @@ -1,2 +1,2 @@ -export * from "@/lib/domains" -export * from "@/lib/edge-config" \ No newline at end of file +export * from '@/lib/domains'; +export * from '@/lib/edge-config'; diff --git a/packages/sdk/types/index.d.ts b/packages/sdk/types/index.d.ts index 30b86d6..9616af0 100644 --- a/packages/sdk/types/index.d.ts +++ b/packages/sdk/types/index.d.ts @@ -1,52 +1,51 @@ // From https://vercel.com/docs/rest-api/endpoints#get-a-project-domain export interface DomainResponse { - name: string; - apexName: string; - projectId: string; - redirect?: string | null; - redirectStatusCode?: (307 | 301 | 302 | 308) | null; - gitBranch?: string | null; - updatedAt?: number; - createdAt?: number; - /** `true` if the domain is verified for use with the project. If `false` it will not be used as an alias on this project until the challenge in `verification` is completed. */ - verified: boolean; - /** A list of verification challenges, one of which must be completed to verify the domain for use on the project. After the challenge is complete `POST /projects/:idOrName/domains/:domain/verify` to verify the domain. Possible challenges: - If `verification.type = TXT` the `verification.domain` will be checked for a TXT record matching `verification.value`. */ - verification: { - type: string; - domain: string; - value: string; - reason: string; - }[]; - } - - // From https://vercel.com/docs/rest-api/endpoints#get-a-domain-s-configuration - export interface DomainConfigResponse { - /** How we see the domain's configuration. - `CNAME`: Domain has a CNAME pointing to Vercel. - `A`: Domain's A record is resolving to Vercel. - `http`: Domain is resolving to Vercel but may be behind a Proxy. - `null`: Domain is not resolving to Vercel. */ - configuredBy?: ("CNAME" | "A" | "http") | null; - /** Which challenge types the domain can use for issuing certs. */ - acceptedChallenges?: ("dns-01" | "http-01")[]; - /** Whether or not the domain is configured AND we can automatically generate a TLS certificate. */ - misconfigured: boolean; - } - - // From https://vercel.com/docs/rest-api/endpoints#verify-project-domain - export interface DomainVerificationResponse { - name: string; - apexName: string; - projectId: string; - redirect?: string | null; - redirectStatusCode?: (307 | 301 | 302 | 308) | null; - gitBranch?: string | null; - updatedAt?: number; - createdAt?: number; - /** `true` if the domain is verified for use with the project. If `false` it will not be used as an alias on this project until the challenge in `verification` is completed. */ - verified: boolean; - /** A list of verification challenges, one of which must be completed to verify the domain for use on the project. After the challenge is complete `POST /projects/:idOrName/domains/:domain/verify` to verify the domain. Possible challenges: - If `verification.type = TXT` the `verification.domain` will be checked for a TXT record matching `verification.value`. */ - verification?: { - type: string; - domain: string; - value: string; - reason: string; - }[]; - } - \ No newline at end of file + name: string; + apexName: string; + projectId: string; + redirect?: string | null; + redirectStatusCode?: (307 | 301 | 302 | 308) | null; + gitBranch?: string | null; + updatedAt?: number; + createdAt?: number; + /** `true` if the domain is verified for use with the project. If `false` it will not be used as an alias on this project until the challenge in `verification` is completed. */ + verified: boolean; + /** A list of verification challenges, one of which must be completed to verify the domain for use on the project. After the challenge is complete `POST /projects/:idOrName/domains/:domain/verify` to verify the domain. Possible challenges: - If `verification.type = TXT` the `verification.domain` will be checked for a TXT record matching `verification.value`. */ + verification: { + type: string; + domain: string; + value: string; + reason: string; + }[]; +} + +// From https://vercel.com/docs/rest-api/endpoints#get-a-domain-s-configuration +export interface DomainConfigResponse { + /** How we see the domain's configuration. - `CNAME`: Domain has a CNAME pointing to Vercel. - `A`: Domain's A record is resolving to Vercel. - `http`: Domain is resolving to Vercel but may be behind a Proxy. - `null`: Domain is not resolving to Vercel. */ + configuredBy?: ('CNAME' | 'A' | 'http') | null; + /** Which challenge types the domain can use for issuing certs. */ + acceptedChallenges?: ('dns-01' | 'http-01')[]; + /** Whether or not the domain is configured AND we can automatically generate a TLS certificate. */ + misconfigured: boolean; +} + +// From https://vercel.com/docs/rest-api/endpoints#verify-project-domain +export interface DomainVerificationResponse { + name: string; + apexName: string; + projectId: string; + redirect?: string | null; + redirectStatusCode?: (307 | 301 | 302 | 308) | null; + gitBranch?: string | null; + updatedAt?: number; + createdAt?: number; + /** `true` if the domain is verified for use with the project. If `false` it will not be used as an alias on this project until the challenge in `verification` is completed. */ + verified: boolean; + /** A list of verification challenges, one of which must be completed to verify the domain for use on the project. After the challenge is complete `POST /projects/:idOrName/domains/:domain/verify` to verify the domain. Possible challenges: - If `verification.type = TXT` the `verification.domain` will be checked for a TXT record matching `verification.value`. */ + verification?: { + type: string; + domain: string; + value: string; + reason: string; + }[]; +}