Skip to content

Commit

Permalink
Merge pull request #3 from hocgin/develop
Browse files Browse the repository at this point in the history
Develop
  • Loading branch information
hocgin authored Jun 10, 2024
2 parents 771ac9d + 7fdadb7 commit b44e4c4
Show file tree
Hide file tree
Showing 9 changed files with 284 additions and 200 deletions.
110 changes: 110 additions & 0 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
name: Deploy to Cloudflare

on:
push:
branches: [ 'main' ]

jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3

- name: Setup Terraform
uses: hashicorp/[email protected]
with:
terraform_version: 1.6.4

- name: Setup Node
uses: actions/setup-node@v3
with:
node-version: '18'

- uses: pnpm/action-setup@v2
name: Install pnpm
id: pnpm-install
with:
version: 8
run_install: false

- name: Fetch Account ID
id: fetch_account_id
run: |
if [[ -n "${{ secrets.CLOUDFLARE_ACCOUNT_ID }}" ]]; then
ACCOUNT_ID="${{ secrets.CLOUDFLARE_ACCOUNT_ID }}"
echo "Using provided CLOUDFLARE_ACCOUNT_ID from secrets."
else
ACCOUNT_ID=$(curl -X GET "https://api.cloudflare.com/client/v4/accounts" -H "Authorization: Bearer ${CLOUDFLARE_API_TOKEN}" -H "Content-Type:application/json" | jq ".result[0].id" -r)
if [[ "$ACCOUNT_ID" == "null" ]]; then
echo "Failed to get an account id, please make sure you have set up CLOUDFLARE_API_TOKEN correctly!"
exit 1
fi
fi
echo 'account_id='$ACCOUNT_ID >> $GITHUB_OUTPUT
env:
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}

# https://github.com/cloudflare/terraform-provider-cloudflare/issues/3304
- name: Create worker subdomain
id: create_dummy_worker
run: |
curl --request PUT --fail-with-body \
--url https://api.cloudflare.com/client/v4/accounts/$CLOUDFLARE_ACCOUNT_ID/workers/scripts/dummy-ib4db6ntj5csdef3 \
--header 'Authorization: Bearer '$CLOUDFLARE_API_TOKEN \
--header 'Content-Type: application/javascript' \
--data 'addEventListener('\''fetch'\'', (event) => event.respondWith(new Response('\''OK'\'')))'\
curl --request DELETE --fail-with-body \
--url https://api.cloudflare.com/client/v4/accounts/$CLOUDFLARE_ACCOUNT_ID/workers/scripts/dummy-ib4db6ntj5csdef3 \
--header 'Authorization: Bearer '$CLOUDFLARE_API_TOKEN \
--header 'Content-Type: application/json'
env:
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
CLOUDFLARE_ACCOUNT_ID: ${{ steps.fetch_account_id.outputs.account_id }}

- name: Install Workers packages
run: |
cd workers
pnpm install
- name: Install Pages packages
run: |
cd pages
pnpm install
- name: Build worker
run: |
cd workers
pnpm npx wrangler deploy src/index.ts --outdir dist --dry-run
- name: Build page
run: |
cd pages
pnpm npx @cloudflare/next-on-pages
- name: Deploy using Terraform
continue-on-error: true

run: |
terraform init
terraform apply -auto-approve -input=false
env:
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
TF_VAR_CLOUDFLARE_ACCOUNT_ID: ${{ steps.fetch_account_id.outputs.account_id }}

- name: Upload worker
run: |
cd workers
curl --fail-with-body -X PUT https://api.cloudflare.com/client/v4/accounts/$CLOUDFLARE_ACCOUNT_ID/workers/scripts/yourselfemail_worker/content --header 'Authorization: Bearer '$CLOUDFLARE_API_TOKEN -F 'index.js=@dist/index.js;type=application/javascript+module' -F 'metadata={"main_module": "index.js"}'
env:
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
CLOUDFLARE_ACCOUNT_ID: ${{ steps.fetch_account_id.outputs.account_id }}

- name: Upload pages
run: |
cd pages
pnpm npx wrangler pages deploy .vercel/output/static --project-name yourselfemail
env:
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
CLOUDFLARE_ACCOUNT_ID: ${{ steps.fetch_account_id.outputs.account_id }}
25 changes: 25 additions & 0 deletions .terraform.lock.hcl

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

119 changes: 119 additions & 0 deletions deploy.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
terraform {
required_providers {
cloudflare = {
source = "cloudflare/cloudflare"
version = "~> 4"
}
}
}

provider "cloudflare" {
# read token from $CLOUDFLARE_API_TOKEN
}

variable "CLOUDFLARE_ACCOUNT_ID" {
type = string
}

variable "CLOUDFLARE_EMAIL_ADDRESS" {
type = string
}

variable "CLOUDFLARE_DOMAIN_ZONE_ID" {
type = string
}

resource "cloudflare_workers_kv_namespace" "yourselfemail_kv" {
account_id = var.CLOUDFLARE_ACCOUNT_ID
title = "yourselfemail_kv"
}

resource "cloudflare_d1_database" "yourselfemail_db" {
account_id = var.CLOUDFLARE_ACCOUNT_ID
name = "yourselfemail_db"
}

# 图片存储
#resource "cloudflare_r2_bucket" "yourselfemail_bucket" {
# account_id = var.CLOUDFLARE_ACCOUNT_ID
# name = "yourselfemail_bucket"
#}


resource "cloudflare_worker_script" "yourselfemail_worker" {
account_id = var.CLOUDFLARE_ACCOUNT_ID
name = "yourselfemail_worker"
content = file("workers/dist/index.js")
module = true
compatibility_date = "2024-04-05"

kv_namespace_binding {
name = "KV"
namespace_id = cloudflare_workers_kv_namespace.yourselfemail_kv.id
}

# r2_bucket_binding {
# name = "R2"
# bucket_name = cloudflare_r2_bucket.yourselfemail_bucket.id
# }

d1_database_binding {
name = "DB"
database_id = cloudflare_d1_database.yourselfemail_db.id
}

}


resource "cloudflare_email_routing_address" "yourselfemail_email_routing_address" {
account_id = var.CLOUDFLARE_ACCOUNT_ID
email = var.CLOUDFLARE_EMAIL_ADDRESS
}

# 邮件路由转发
resource "cloudflare_email_routing_catch_all" "yourselfemail_email_routing_catch_all" {
name = "yourselfemail_email_routing_catch_all"
zone_id = var.CLOUDFLARE_DOMAIN_ZONE_ID
enabled = true

matcher {
type = "all"
}

action {
type = "worker"
value = [cloudflare_worker_script.yourselfemail_worker.name]
}
}

# 定时发送
resource "cloudflare_worker_cron_trigger" "yourselfemail_worker_cron" {
account_id = var.CLOUDFLARE_ACCOUNT_ID
script_name = cloudflare_worker_script.yourselfemail_worker.name
schedules = [
"* * * * *",
]
}

resource "cloudflare_pages_project" "yourselfemail" {
account_id = var.CLOUDFLARE_ACCOUNT_ID
name = "yourselfemail"
production_branch = "main"

deployment_configs {
production {
kv_namespaces = {
KV = cloudflare_workers_kv_namespace.yourselfemail_kv.id
}
d1_databases = {
DB = cloudflare_d1_database.yourselfemail_db.id
}
# r2_buckets = {
# BUCKET = cloudflare_r2_bucket.yourselfemail_bucket.id
# }

compatibility_date = "2024-04-05"
compatibility_flags = ["nodejs_compat"]
}
}
}
Binary file modified pages/app/favicon.ico
Binary file not shown.
2 changes: 1 addition & 1 deletion pages/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export const metadata: Metadata = {
template: `%s - ${siteConfig.name}`,
},
description: siteConfig.description,
applicationName: `Dove-Mail`,
applicationName: `Mail`,
manifest: '/manifest.json',
icons: {
icon: "/logo.png",
Expand Down
4 changes: 2 additions & 2 deletions pages/components/mail/mail-list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ export function MailList({contentRef, path, items, selected, onClick}: MailListP
selected === item.id && "bg-muted"
)} onClick={() => onClick(item)}>
<div className="flex w-full flex-col gap-1">
<div className="flex items-center">
<div className="flex items-center gap-2">
<div className="flex items-center gap-2">
<div className="flex items-center gap-2 overflow-hidden line-clamp-1 flex-1">
{/* 发件 */}
{path === RouteKey.Sent ? <MailAddresses mails={item.toAddress} maxSize={1} /> : null}
{/* 收件 */}
Expand Down
29 changes: 23 additions & 6 deletions pages/lib/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,32 @@ export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs))
}

function isSameDay(date1: Date, date2: Date) {
// 获取两个日期的年月日
const date1Year = date1.getUTCFullYear();
const date1Month = date1.getUTCMonth();
const date1Day = date1.getUTCDate();

const date2Year = date2.getUTCFullYear();
const date2Month = date2.getUTCMonth();
const date2Day = date2.getUTCDate();

// 比较年月日
return date1Year === date2Year &&
date1Month === date2Month &&
date1Day === date2Day;
}

export function formatDistanceDay(date: Date): string {
const oneDay = 1000 * 3600 * 24;
const distance = Date.now() - date.getTime();
if (distance < oneDay && distance > 0) {
return "today";
let now = new Date();
if (isSameDay(date, now)) {
return format(date, "HH:mm:ss");
}

if (distance > 7 * oneDay) {
return format(date, "yyyy-MM-dd HH:mm:ss");
const timeDiff = Math.abs(date.getTime() - now.getTime());
const daysApart = Math.ceil(timeDiff / (1000 * 3600 * 24));
if (daysApart > 7) {
return format(date, "yyyy-MM-dd");
}

return formatDistanceToNow(date, {addSuffix: true})
Expand Down
4 changes: 4 additions & 0 deletions pages/styles/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,7 @@
border-color: gray; /* 2 */
border-collapse: separate; /* 3 */
}

div[data-radix-scroll-area-viewport] > div {
display: unset !important;
}
Loading

0 comments on commit b44e4c4

Please sign in to comment.