diff --git a/src/routes/api/cloudflare/+server.ts b/src/routes/api/cloudflare/+server.ts new file mode 100644 index 0000000..e580fa2 --- /dev/null +++ b/src/routes/api/cloudflare/+server.ts @@ -0,0 +1,136 @@ +import type { RequestEvent } from '@sveltejs/kit'; +import { env } from '$env/dynamic/private'; + +const ACCOUNT_ID = env.CLOUDFLARE_ACCOUNT_ID; +const ZONE_ID = env.CLOUDFLARE_ZONE_ID; +const PAGES_TOKEN = env.CLOUDFLARE_API_TOKEN_PAGES; +const ZONES_TOKEN = env.CLOUDFLARE_API_TOKEN_ZONES; + +async function createPagesProject(projectName: string, profileHandle: string) { + const url = `https://api.cloudflare.com/client/v4/accounts/${ACCOUNT_ID}/pages/projects`; + const payload = { + name: projectName, + production_branch: 'main', + build_config: { + build_caching: true, + build_command: 'npm run build', + destination_dir: 'dist' + }, + deployment_configs: { + production: { + env_vars: { + HANDLE: { type: 'plain_text', value: profileHandle } + } + } + }, + source: { + type: 'github', + config: { + owner: 'polijn', + repo_name: 'bluesky-home', + deployments_enabled: false + } + } + }; + + const res = await fetch(url, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + Authorization: `Bearer ${PAGES_TOKEN}` + }, + body: JSON.stringify(payload) + }); + + const data = await res.json(); + console.log('createPagesProject:'); + console.log(data); + if (!data.success) throw new Error(JSON.stringify(data.errors)); + return data.result; +} + +async function triggerDeployment(projectName: string) { + const url = `https://api.cloudflare.com/client/v4/accounts/${ACCOUNT_ID}/pages/projects/${projectName}/deployments`; + const form = new FormData(); + form.append('branch', 'main'); + + const res = await fetch(url, { + method: 'POST', + headers: { Authorization: `Bearer ${PAGES_TOKEN}` }, + body: form + }); + + const data = await res.json(); + console.log('triggerDeployment:'); + console.log(data); + if (!data.success) throw new Error(JSON.stringify(data.errors)); + return data.result; +} + +async function addCustomDomain(projectName: string, domain: string) { + const url = `https://api.cloudflare.com/client/v4/accounts/${ACCOUNT_ID}/pages/projects/${projectName}/domains`; + const res = await fetch(url, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + Authorization: `Bearer ${PAGES_TOKEN}` + }, + body: JSON.stringify({ name: domain }) + }); + + const data = await res.json(); + console.log('addCustomDomain:'); + console.log(data); + if (!data.success) throw new Error(JSON.stringify(data.errors)); + return data.result; +} + +async function createDNSRecord(name: string, target: string) { + const url = `https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/dns_records`; + const payload = { + type: 'CNAME', + name, + content: target, + ttl: 3600, + proxied: true, + comment: 'personal subdomain' + }; + + const res = await fetch(url, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + Authorization: `Bearer ${ZONES_TOKEN}` + }, + body: JSON.stringify(payload) + }); + + const data = await res.json(); + console.log('createDNSRecord:'); + console.log(data); + if (!data.success) throw new Error(JSON.stringify(data.errors)); + return data.result; +} + +export async function POST(event: RequestEvent) { + const { projectName, domain, profileHandle } = await event.request.json(); + + try { + const project = await createPagesProject(projectName, profileHandle); + const devSubdomain = project.subdomain; + await new Promise((resolve) => setTimeout(resolve, 2000)); + const domainResult = await addCustomDomain(projectName, domain); + await new Promise((resolve) => setTimeout(resolve, 2000)); + const dnsRecordId = await createDNSRecord(domain, devSubdomain); + await new Promise((resolve) => setTimeout(resolve, 2000)); + const deploymentResult = await triggerDeployment(projectName); + + // , devSubdomain, bindingId, dnsRecordId + return new Response(JSON.stringify({ project }), { + status: 200, + headers: { 'Content-Type': 'application/json' } + }); + } catch (error) { + return new Response(JSON.stringify({ error: error.message }), { status: 500 }); + } +} -- 2.51.2 From cc2afb947e1a16875e327dccca93fffda0b748f7 Mon Sep 17 00:00:00 2001 From: polijn Date: Mon, 5 May 2025 02:02:56 +0200 Subject: [PATCH 2/2] cloudflare create & deploy --- src/routes/+page.svelte | 39 ++++++++++++++++++++++++---- src/routes/api/cloudflare/+server.ts | 3 ++- 2 files changed, 36 insertions(+), 6 deletions(-) diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index ffd5c09..530fa63 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -1,10 +1,30 @@
@@ -12,7 +32,7 @@ { // create and submit form with handle - + if (!form) { console.error('Form not found'); return false; @@ -31,12 +51,21 @@ /> {:else} + - + + + +