mirror of https://github.com/TZGyn/shortener
migrate redirect to flyio for cheaper domain certs
parent
e7edf16138
commit
2723a9391c
Binary file not shown.
@ -0,0 +1,122 @@
|
|||||||
|
import { env } from '$env/dynamic/private'
|
||||||
|
|
||||||
|
class FlyioAPI {
|
||||||
|
constructor(private apiKey: string) {}
|
||||||
|
|
||||||
|
private sendRequest(query: string, variables: any) {
|
||||||
|
return fetch(`https://api.fly.io/graphql`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
Authorization: `Bearer ${this.apiKey}`,
|
||||||
|
},
|
||||||
|
body: JSON.stringify({ query, variables }),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
async checkDomain(domain: string) {
|
||||||
|
const query = `
|
||||||
|
query customDomainAvailable($domain: String!) {
|
||||||
|
customDomainAvailable(domain: $domain) {
|
||||||
|
__typename
|
||||||
|
available
|
||||||
|
message
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
const variables = {
|
||||||
|
domain: domain,
|
||||||
|
}
|
||||||
|
const response = await this.sendRequest(query, variables)
|
||||||
|
if (response.ok) {
|
||||||
|
const data: any = await response.json()
|
||||||
|
if (data.data.customDomainAvailable.available) {
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async createCustomDomain(domain: string) {
|
||||||
|
const query = `
|
||||||
|
mutation($appId: ID!, $hostname: String!) {
|
||||||
|
addCertificate(appId: $appId, hostname: $hostname) {
|
||||||
|
certificate {
|
||||||
|
configured
|
||||||
|
acmeDnsConfigured
|
||||||
|
acmeAlpnConfigured
|
||||||
|
certificateAuthority
|
||||||
|
certificateRequestedAt
|
||||||
|
dnsProvider
|
||||||
|
dnsValidationInstructions
|
||||||
|
dnsValidationHostname
|
||||||
|
dnsValidationTarget
|
||||||
|
hostname
|
||||||
|
id
|
||||||
|
source
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
const variables = {
|
||||||
|
appId: env.PRIVATE_FLYIO_APP_ID,
|
||||||
|
hostname: domain,
|
||||||
|
}
|
||||||
|
const response = await this.sendRequest(query, variables)
|
||||||
|
const data: any = await response.json()
|
||||||
|
if (!data.errors) {
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
} as const
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
message: 'Something went wrong',
|
||||||
|
} as const
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async deleteCustomDomain(domain: string) {
|
||||||
|
const query = `
|
||||||
|
mutation ($appId: ID!, $hostname: String!) {
|
||||||
|
deleteCertificate(appId: $appId, hostname: $hostname) {
|
||||||
|
certificate {
|
||||||
|
configured
|
||||||
|
acmeDnsConfigured
|
||||||
|
acmeAlpnConfigured
|
||||||
|
certificateAuthority
|
||||||
|
certificateRequestedAt
|
||||||
|
dnsProvider
|
||||||
|
dnsValidationInstructions
|
||||||
|
dnsValidationHostname
|
||||||
|
dnsValidationTarget
|
||||||
|
hostname
|
||||||
|
id
|
||||||
|
source
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
const variables = {
|
||||||
|
appId: env.PRIVATE_FLYIO_APP_ID,
|
||||||
|
hostname: domain,
|
||||||
|
}
|
||||||
|
const response = await this.sendRequest(query, variables)
|
||||||
|
const data: any = await response.json()
|
||||||
|
if (!data.errors) {
|
||||||
|
console.log('Fly.io Delete Domain', data)
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
} as const
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
} as const
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const flyioClient = new FlyioAPI(env.PRIVATE_FLYIO_API_KEY)
|
||||||
@ -0,0 +1,72 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import * as Tabs from '$lib/components/ui/tabs/index.js'
|
||||||
|
import * as Card from '$lib/components/ui/card/index.js'
|
||||||
|
import { Button } from '$lib/components/ui/button/index.js'
|
||||||
|
import { Input } from '$lib/components/ui/input/index.js'
|
||||||
|
import { Label } from '$lib/components/ui/label/index.js'
|
||||||
|
|
||||||
|
export let cname_record: string
|
||||||
|
export let a_record: string
|
||||||
|
export let aaaa_record: string
|
||||||
|
|
||||||
|
const defaultValue = cname_record ? 'cname' : 'a'
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<Tabs.Root value={defaultValue}>
|
||||||
|
<Tabs.List>
|
||||||
|
{#if cname_record}
|
||||||
|
<Tabs.Trigger value="cname">CNAME</Tabs.Trigger>
|
||||||
|
{/if}
|
||||||
|
{#if a_record || aaaa_record}
|
||||||
|
<Tabs.Trigger value="a">A and AAAA</Tabs.Trigger>
|
||||||
|
{/if}
|
||||||
|
</Tabs.List>
|
||||||
|
{#if cname_record}
|
||||||
|
<Tabs.Content value="cname">
|
||||||
|
<Card.Root>
|
||||||
|
<Card.Header class="grid grid-cols-[80px_1fr] space-y-0 py-4">
|
||||||
|
<Card.Title>Type</Card.Title>
|
||||||
|
<Card.Title>Value</Card.Title>
|
||||||
|
</Card.Header>
|
||||||
|
<Card.Footer class="bg-muted grid grid-cols-[80px_1fr] py-4">
|
||||||
|
<Card.Description>CNAME</Card.Description>
|
||||||
|
<Card.Description>{cname_record}</Card.Description>
|
||||||
|
</Card.Footer>
|
||||||
|
</Card.Root>
|
||||||
|
</Tabs.Content>
|
||||||
|
{/if}
|
||||||
|
{#if a_record || aaaa_record}
|
||||||
|
<Tabs.Content value="a">
|
||||||
|
<div class="flex flex-col gap-4">
|
||||||
|
{#if a_record}
|
||||||
|
<Card.Root>
|
||||||
|
<Card.Header
|
||||||
|
class="grid grid-cols-[80px_1fr] space-y-0 py-4">
|
||||||
|
<Card.Title>Type</Card.Title>
|
||||||
|
<Card.Title>Value</Card.Title>
|
||||||
|
</Card.Header>
|
||||||
|
<Card.Footer
|
||||||
|
class="bg-muted grid grid-cols-[80px_1fr] py-4">
|
||||||
|
<Card.Description>A</Card.Description>
|
||||||
|
<Card.Description>{a_record}</Card.Description>
|
||||||
|
</Card.Footer>
|
||||||
|
</Card.Root>
|
||||||
|
{/if}
|
||||||
|
{#if aaaa_record}
|
||||||
|
<Card.Root>
|
||||||
|
<Card.Header
|
||||||
|
class="grid grid-cols-[80px_1fr] space-y-0 py-4">
|
||||||
|
<Card.Title>Type</Card.Title>
|
||||||
|
<Card.Title>Value</Card.Title>
|
||||||
|
</Card.Header>
|
||||||
|
<Card.Footer
|
||||||
|
class="bg-muted grid grid-cols-[80px_1fr] py-4">
|
||||||
|
<Card.Description>AAAA</Card.Description>
|
||||||
|
<Card.Description>{aaaa_record}</Card.Description>
|
||||||
|
</Card.Footer>
|
||||||
|
</Card.Root>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
</Tabs.Content>
|
||||||
|
{/if}
|
||||||
|
</Tabs.Root>
|
||||||
@ -0,0 +1,61 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import * as Tooltip from '$lib/components/ui/tooltip/index.js'
|
||||||
|
import { InfoIcon } from 'lucide-svelte'
|
||||||
|
|
||||||
|
export let domain: string
|
||||||
|
export let custom_ip: string | null
|
||||||
|
export let cname_record: string
|
||||||
|
export let a_record: string
|
||||||
|
export let aaaa_record: string
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<Tooltip.Root>
|
||||||
|
<Tooltip.Trigger class="flex items-center gap-1">
|
||||||
|
<InfoIcon class="h-4 w-4" />
|
||||||
|
{#if custom_ip}
|
||||||
|
{custom_ip}
|
||||||
|
{:else if cname_record}
|
||||||
|
{cname_record}
|
||||||
|
{:else if a_record}
|
||||||
|
{a_record}
|
||||||
|
{:else if aaaa_record}
|
||||||
|
{aaaa_record}
|
||||||
|
{:else}
|
||||||
|
{'Public IP not found'}
|
||||||
|
{/if}
|
||||||
|
</Tooltip.Trigger>
|
||||||
|
<Tooltip.Content>
|
||||||
|
{#if custom_ip}
|
||||||
|
<div>
|
||||||
|
{'Create a CNAME/ALIAS record for ' +
|
||||||
|
domain +
|
||||||
|
' to ' +
|
||||||
|
custom_ip}
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
{#if cname_record}
|
||||||
|
<div>
|
||||||
|
{'Create a CNAME/ALIAS record for ' +
|
||||||
|
domain +
|
||||||
|
' to ' +
|
||||||
|
cname_record}
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
{#if a_record}
|
||||||
|
<div>
|
||||||
|
{'Create a A record for ' + domain + ' to ' + a_record}
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
{#if aaaa_record}
|
||||||
|
<div>
|
||||||
|
{'Create a AAAA record for ' + domain + ' to ' + aaaa_record}
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
{#if !(custom_ip || cname_record || a_record || aaaa_record)}
|
||||||
|
<div>
|
||||||
|
{'Public IP not found'}
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
</Tooltip.Content>
|
||||||
|
</Tooltip.Root>
|
||||||
Binary file not shown.
@ -0,0 +1,22 @@
|
|||||||
|
# fly.toml app configuration file generated for kon on 2024-07-28T10:01:44+08:00
|
||||||
|
#
|
||||||
|
# See https://fly.io/docs/reference/configuration/ for information about how to use this file.
|
||||||
|
#
|
||||||
|
|
||||||
|
app = 'kon'
|
||||||
|
primary_region = 'dfw'
|
||||||
|
|
||||||
|
[build]
|
||||||
|
|
||||||
|
[http_service]
|
||||||
|
internal_port = 3000
|
||||||
|
force_https = true
|
||||||
|
auto_stop_machines = 'off'
|
||||||
|
auto_start_machines = true
|
||||||
|
min_machines_running = 0
|
||||||
|
processes = ['app']
|
||||||
|
|
||||||
|
[[vm]]
|
||||||
|
memory = '1gb'
|
||||||
|
cpu_kind = 'shared'
|
||||||
|
cpus = 1
|
||||||
Loading…
Reference in New Issue