mirror of
https://github.com/Xevion/fastmail-cloudflare.git
synced 2025-12-06 01:14:59 -06:00
initial commit
This commit is contained in:
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
.vscode
|
||||||
|
node_modules
|
||||||
|
.env
|
||||||
|
.tool-versions
|
||||||
4
.prettierrc
Normal file
4
.prettierrc
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"tabWidth": 2,
|
||||||
|
"useTabs": false
|
||||||
|
}
|
||||||
3
README.md
Normal file
3
README.md
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
# fastmail-cloudflare
|
||||||
|
|
||||||
|
This is a simple script to update the DNS records of a domain in Cloudflare to point to the Fastmail mail servers.
|
||||||
18
package.json
Normal file
18
package.json
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"name": "fastmail-cloudflare",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"description": "Quickly setup Fastmail with Cloudflare",
|
||||||
|
"scripts": {
|
||||||
|
"start": "tsx src/index.ts"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"cloudflare": "^3.5.0",
|
||||||
|
"dotenv": "^16.4.5",
|
||||||
|
"iter-ops": "^3.5.0",
|
||||||
|
"prettier": "^3.3.3"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/node": "^22.7.5",
|
||||||
|
"tsx": "^4.19.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
652
pnpm-lock.yaml
generated
Normal file
652
pnpm-lock.yaml
generated
Normal file
@@ -0,0 +1,652 @@
|
|||||||
|
lockfileVersion: '9.0'
|
||||||
|
|
||||||
|
settings:
|
||||||
|
autoInstallPeers: true
|
||||||
|
excludeLinksFromLockfile: false
|
||||||
|
|
||||||
|
importers:
|
||||||
|
|
||||||
|
.:
|
||||||
|
dependencies:
|
||||||
|
cloudflare:
|
||||||
|
specifier: ^3.5.0
|
||||||
|
version: 3.5.0
|
||||||
|
dotenv:
|
||||||
|
specifier: ^16.4.5
|
||||||
|
version: 16.4.5
|
||||||
|
iter-ops:
|
||||||
|
specifier: ^3.5.0
|
||||||
|
version: 3.5.0
|
||||||
|
prettier:
|
||||||
|
specifier: ^3.3.3
|
||||||
|
version: 3.3.3
|
||||||
|
devDependencies:
|
||||||
|
'@types/node':
|
||||||
|
specifier: ^22.7.5
|
||||||
|
version: 22.7.5
|
||||||
|
tsx:
|
||||||
|
specifier: ^4.19.1
|
||||||
|
version: 4.19.1
|
||||||
|
|
||||||
|
packages:
|
||||||
|
|
||||||
|
'@esbuild/aix-ppc64@0.23.1':
|
||||||
|
resolution: {integrity: sha512-6VhYk1diRqrhBAqpJEdjASR/+WVRtfjpqKuNw11cLiaWpAT/Uu+nokB+UJnevzy/P9C/ty6AOe0dwueMrGh/iQ==}
|
||||||
|
engines: {node: '>=18'}
|
||||||
|
cpu: [ppc64]
|
||||||
|
os: [aix]
|
||||||
|
|
||||||
|
'@esbuild/android-arm64@0.23.1':
|
||||||
|
resolution: {integrity: sha512-xw50ipykXcLstLeWH7WRdQuysJqejuAGPd30vd1i5zSyKK3WE+ijzHmLKxdiCMtH1pHz78rOg0BKSYOSB/2Khw==}
|
||||||
|
engines: {node: '>=18'}
|
||||||
|
cpu: [arm64]
|
||||||
|
os: [android]
|
||||||
|
|
||||||
|
'@esbuild/android-arm@0.23.1':
|
||||||
|
resolution: {integrity: sha512-uz6/tEy2IFm9RYOyvKl88zdzZfwEfKZmnX9Cj1BHjeSGNuGLuMD1kR8y5bteYmwqKm1tj8m4cb/aKEorr6fHWQ==}
|
||||||
|
engines: {node: '>=18'}
|
||||||
|
cpu: [arm]
|
||||||
|
os: [android]
|
||||||
|
|
||||||
|
'@esbuild/android-x64@0.23.1':
|
||||||
|
resolution: {integrity: sha512-nlN9B69St9BwUoB+jkyU090bru8L0NA3yFvAd7k8dNsVH8bi9a8cUAUSEcEEgTp2z3dbEDGJGfP6VUnkQnlReg==}
|
||||||
|
engines: {node: '>=18'}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [android]
|
||||||
|
|
||||||
|
'@esbuild/darwin-arm64@0.23.1':
|
||||||
|
resolution: {integrity: sha512-YsS2e3Wtgnw7Wq53XXBLcV6JhRsEq8hkfg91ESVadIrzr9wO6jJDMZnCQbHm1Guc5t/CdDiFSSfWP58FNuvT3Q==}
|
||||||
|
engines: {node: '>=18'}
|
||||||
|
cpu: [arm64]
|
||||||
|
os: [darwin]
|
||||||
|
|
||||||
|
'@esbuild/darwin-x64@0.23.1':
|
||||||
|
resolution: {integrity: sha512-aClqdgTDVPSEGgoCS8QDG37Gu8yc9lTHNAQlsztQ6ENetKEO//b8y31MMu2ZaPbn4kVsIABzVLXYLhCGekGDqw==}
|
||||||
|
engines: {node: '>=18'}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [darwin]
|
||||||
|
|
||||||
|
'@esbuild/freebsd-arm64@0.23.1':
|
||||||
|
resolution: {integrity: sha512-h1k6yS8/pN/NHlMl5+v4XPfikhJulk4G+tKGFIOwURBSFzE8bixw1ebjluLOjfwtLqY0kewfjLSrO6tN2MgIhA==}
|
||||||
|
engines: {node: '>=18'}
|
||||||
|
cpu: [arm64]
|
||||||
|
os: [freebsd]
|
||||||
|
|
||||||
|
'@esbuild/freebsd-x64@0.23.1':
|
||||||
|
resolution: {integrity: sha512-lK1eJeyk1ZX8UklqFd/3A60UuZ/6UVfGT2LuGo3Wp4/z7eRTRYY+0xOu2kpClP+vMTi9wKOfXi2vjUpO1Ro76g==}
|
||||||
|
engines: {node: '>=18'}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [freebsd]
|
||||||
|
|
||||||
|
'@esbuild/linux-arm64@0.23.1':
|
||||||
|
resolution: {integrity: sha512-/93bf2yxencYDnItMYV/v116zff6UyTjo4EtEQjUBeGiVpMmffDNUyD9UN2zV+V3LRV3/on4xdZ26NKzn6754g==}
|
||||||
|
engines: {node: '>=18'}
|
||||||
|
cpu: [arm64]
|
||||||
|
os: [linux]
|
||||||
|
|
||||||
|
'@esbuild/linux-arm@0.23.1':
|
||||||
|
resolution: {integrity: sha512-CXXkzgn+dXAPs3WBwE+Kvnrf4WECwBdfjfeYHpMeVxWE0EceB6vhWGShs6wi0IYEqMSIzdOF1XjQ/Mkm5d7ZdQ==}
|
||||||
|
engines: {node: '>=18'}
|
||||||
|
cpu: [arm]
|
||||||
|
os: [linux]
|
||||||
|
|
||||||
|
'@esbuild/linux-ia32@0.23.1':
|
||||||
|
resolution: {integrity: sha512-VTN4EuOHwXEkXzX5nTvVY4s7E/Krz7COC8xkftbbKRYAl96vPiUssGkeMELQMOnLOJ8k3BY1+ZY52tttZnHcXQ==}
|
||||||
|
engines: {node: '>=18'}
|
||||||
|
cpu: [ia32]
|
||||||
|
os: [linux]
|
||||||
|
|
||||||
|
'@esbuild/linux-loong64@0.23.1':
|
||||||
|
resolution: {integrity: sha512-Vx09LzEoBa5zDnieH8LSMRToj7ir/Jeq0Gu6qJ/1GcBq9GkfoEAoXvLiW1U9J1qE/Y/Oyaq33w5p2ZWrNNHNEw==}
|
||||||
|
engines: {node: '>=18'}
|
||||||
|
cpu: [loong64]
|
||||||
|
os: [linux]
|
||||||
|
|
||||||
|
'@esbuild/linux-mips64el@0.23.1':
|
||||||
|
resolution: {integrity: sha512-nrFzzMQ7W4WRLNUOU5dlWAqa6yVeI0P78WKGUo7lg2HShq/yx+UYkeNSE0SSfSure0SqgnsxPvmAUu/vu0E+3Q==}
|
||||||
|
engines: {node: '>=18'}
|
||||||
|
cpu: [mips64el]
|
||||||
|
os: [linux]
|
||||||
|
|
||||||
|
'@esbuild/linux-ppc64@0.23.1':
|
||||||
|
resolution: {integrity: sha512-dKN8fgVqd0vUIjxuJI6P/9SSSe/mB9rvA98CSH2sJnlZ/OCZWO1DJvxj8jvKTfYUdGfcq2dDxoKaC6bHuTlgcw==}
|
||||||
|
engines: {node: '>=18'}
|
||||||
|
cpu: [ppc64]
|
||||||
|
os: [linux]
|
||||||
|
|
||||||
|
'@esbuild/linux-riscv64@0.23.1':
|
||||||
|
resolution: {integrity: sha512-5AV4Pzp80fhHL83JM6LoA6pTQVWgB1HovMBsLQ9OZWLDqVY8MVobBXNSmAJi//Csh6tcY7e7Lny2Hg1tElMjIA==}
|
||||||
|
engines: {node: '>=18'}
|
||||||
|
cpu: [riscv64]
|
||||||
|
os: [linux]
|
||||||
|
|
||||||
|
'@esbuild/linux-s390x@0.23.1':
|
||||||
|
resolution: {integrity: sha512-9ygs73tuFCe6f6m/Tb+9LtYxWR4c9yg7zjt2cYkjDbDpV/xVn+68cQxMXCjUpYwEkze2RcU/rMnfIXNRFmSoDw==}
|
||||||
|
engines: {node: '>=18'}
|
||||||
|
cpu: [s390x]
|
||||||
|
os: [linux]
|
||||||
|
|
||||||
|
'@esbuild/linux-x64@0.23.1':
|
||||||
|
resolution: {integrity: sha512-EV6+ovTsEXCPAp58g2dD68LxoP/wK5pRvgy0J/HxPGB009omFPv3Yet0HiaqvrIrgPTBuC6wCH1LTOY91EO5hQ==}
|
||||||
|
engines: {node: '>=18'}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [linux]
|
||||||
|
|
||||||
|
'@esbuild/netbsd-x64@0.23.1':
|
||||||
|
resolution: {integrity: sha512-aevEkCNu7KlPRpYLjwmdcuNz6bDFiE7Z8XC4CPqExjTvrHugh28QzUXVOZtiYghciKUacNktqxdpymplil1beA==}
|
||||||
|
engines: {node: '>=18'}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [netbsd]
|
||||||
|
|
||||||
|
'@esbuild/openbsd-arm64@0.23.1':
|
||||||
|
resolution: {integrity: sha512-3x37szhLexNA4bXhLrCC/LImN/YtWis6WXr1VESlfVtVeoFJBRINPJ3f0a/6LV8zpikqoUg4hyXw0sFBt5Cr+Q==}
|
||||||
|
engines: {node: '>=18'}
|
||||||
|
cpu: [arm64]
|
||||||
|
os: [openbsd]
|
||||||
|
|
||||||
|
'@esbuild/openbsd-x64@0.23.1':
|
||||||
|
resolution: {integrity: sha512-aY2gMmKmPhxfU+0EdnN+XNtGbjfQgwZj43k8G3fyrDM/UdZww6xrWxmDkuz2eCZchqVeABjV5BpildOrUbBTqA==}
|
||||||
|
engines: {node: '>=18'}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [openbsd]
|
||||||
|
|
||||||
|
'@esbuild/sunos-x64@0.23.1':
|
||||||
|
resolution: {integrity: sha512-RBRT2gqEl0IKQABT4XTj78tpk9v7ehp+mazn2HbUeZl1YMdaGAQqhapjGTCe7uw7y0frDi4gS0uHzhvpFuI1sA==}
|
||||||
|
engines: {node: '>=18'}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [sunos]
|
||||||
|
|
||||||
|
'@esbuild/win32-arm64@0.23.1':
|
||||||
|
resolution: {integrity: sha512-4O+gPR5rEBe2FpKOVyiJ7wNDPA8nGzDuJ6gN4okSA1gEOYZ67N8JPk58tkWtdtPeLz7lBnY6I5L3jdsr3S+A6A==}
|
||||||
|
engines: {node: '>=18'}
|
||||||
|
cpu: [arm64]
|
||||||
|
os: [win32]
|
||||||
|
|
||||||
|
'@esbuild/win32-ia32@0.23.1':
|
||||||
|
resolution: {integrity: sha512-BcaL0Vn6QwCwre3Y717nVHZbAa4UBEigzFm6VdsVdT/MbZ38xoj1X9HPkZhbmaBGUD1W8vxAfffbDe8bA6AKnQ==}
|
||||||
|
engines: {node: '>=18'}
|
||||||
|
cpu: [ia32]
|
||||||
|
os: [win32]
|
||||||
|
|
||||||
|
'@esbuild/win32-x64@0.23.1':
|
||||||
|
resolution: {integrity: sha512-BHpFFeslkWrXWyUPnbKm+xYYVYruCinGcftSBaa8zoF9hZO4BcSCFUvHVTtzpIY6YzUnYtuEhZ+C9iEXjxnasg==}
|
||||||
|
engines: {node: '>=18'}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [win32]
|
||||||
|
|
||||||
|
'@types/node-fetch@2.6.11':
|
||||||
|
resolution: {integrity: sha512-24xFj9R5+rfQJLRyM56qh+wnVSYhyXC2tkoBndtY0U+vubqNsYXGjufB2nn8Q6gt0LrARwL6UBtMCSVCwl4B1g==}
|
||||||
|
|
||||||
|
'@types/node@18.19.55':
|
||||||
|
resolution: {integrity: sha512-zzw5Vw52205Zr/nmErSEkN5FLqXPuKX/k5d1D7RKHATGqU7y6YfX9QxZraUzUrFGqH6XzOzG196BC35ltJC4Cw==}
|
||||||
|
|
||||||
|
'@types/node@22.7.5':
|
||||||
|
resolution: {integrity: sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ==}
|
||||||
|
|
||||||
|
'@types/qs@6.9.16':
|
||||||
|
resolution: {integrity: sha512-7i+zxXdPD0T4cKDuxCUXJ4wHcsJLwENa6Z3dCu8cfCK743OGy5Nu1RmAGqDPsoTDINVEcdXKRvR/zre+P2Ku1A==}
|
||||||
|
|
||||||
|
abort-controller@3.0.0:
|
||||||
|
resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==}
|
||||||
|
engines: {node: '>=6.5'}
|
||||||
|
|
||||||
|
agentkeepalive@4.5.0:
|
||||||
|
resolution: {integrity: sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==}
|
||||||
|
engines: {node: '>= 8.0.0'}
|
||||||
|
|
||||||
|
asynckit@0.4.0:
|
||||||
|
resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==}
|
||||||
|
|
||||||
|
call-bind@1.0.7:
|
||||||
|
resolution: {integrity: sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==}
|
||||||
|
engines: {node: '>= 0.4'}
|
||||||
|
|
||||||
|
cloudflare@3.5.0:
|
||||||
|
resolution: {integrity: sha512-sIRZ4K2WQf8tZ74gZGan3u6+50VY1cB6uNc9XIGGLQa7Ti/nrvvadirm8EPVFlQMG11PUXPsX1Buheh4MPLiew==}
|
||||||
|
|
||||||
|
combined-stream@1.0.8:
|
||||||
|
resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==}
|
||||||
|
engines: {node: '>= 0.8'}
|
||||||
|
|
||||||
|
define-data-property@1.1.4:
|
||||||
|
resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==}
|
||||||
|
engines: {node: '>= 0.4'}
|
||||||
|
|
||||||
|
delayed-stream@1.0.0:
|
||||||
|
resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
|
||||||
|
engines: {node: '>=0.4.0'}
|
||||||
|
|
||||||
|
dotenv@16.4.5:
|
||||||
|
resolution: {integrity: sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==}
|
||||||
|
engines: {node: '>=12'}
|
||||||
|
|
||||||
|
es-define-property@1.0.0:
|
||||||
|
resolution: {integrity: sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==}
|
||||||
|
engines: {node: '>= 0.4'}
|
||||||
|
|
||||||
|
es-errors@1.3.0:
|
||||||
|
resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==}
|
||||||
|
engines: {node: '>= 0.4'}
|
||||||
|
|
||||||
|
esbuild@0.23.1:
|
||||||
|
resolution: {integrity: sha512-VVNz/9Sa0bs5SELtn3f7qhJCDPCF5oMEl5cO9/SSinpE9hbPVvxbd572HH5AKiP7WD8INO53GgfDDhRjkylHEg==}
|
||||||
|
engines: {node: '>=18'}
|
||||||
|
hasBin: true
|
||||||
|
|
||||||
|
event-target-shim@5.0.1:
|
||||||
|
resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==}
|
||||||
|
engines: {node: '>=6'}
|
||||||
|
|
||||||
|
form-data-encoder@1.7.2:
|
||||||
|
resolution: {integrity: sha512-qfqtYan3rxrnCk1VYaA4H+Ms9xdpPqvLZa6xmMgFvhO32x7/3J/ExcTd6qpxM0vH2GdMI+poehyBZvqfMTto8A==}
|
||||||
|
|
||||||
|
form-data@4.0.1:
|
||||||
|
resolution: {integrity: sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==}
|
||||||
|
engines: {node: '>= 6'}
|
||||||
|
|
||||||
|
formdata-node@4.4.1:
|
||||||
|
resolution: {integrity: sha512-0iirZp3uVDjVGt9p49aTaqjk84TrglENEDuqfdlZQ1roC9CWlPk6Avf8EEnZNcAqPonwkG35x4n3ww/1THYAeQ==}
|
||||||
|
engines: {node: '>= 12.20'}
|
||||||
|
|
||||||
|
fsevents@2.3.3:
|
||||||
|
resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
|
||||||
|
engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
|
||||||
|
os: [darwin]
|
||||||
|
|
||||||
|
function-bind@1.1.2:
|
||||||
|
resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==}
|
||||||
|
|
||||||
|
get-intrinsic@1.2.4:
|
||||||
|
resolution: {integrity: sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==}
|
||||||
|
engines: {node: '>= 0.4'}
|
||||||
|
|
||||||
|
get-tsconfig@4.8.1:
|
||||||
|
resolution: {integrity: sha512-k9PN+cFBmaLWtVz29SkUoqU5O0slLuHJXt/2P+tMVFT+phsSGXGkp9t3rQIqdz0e+06EHNGs3oM6ZX1s2zHxRg==}
|
||||||
|
|
||||||
|
gopd@1.0.1:
|
||||||
|
resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==}
|
||||||
|
|
||||||
|
has-property-descriptors@1.0.2:
|
||||||
|
resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==}
|
||||||
|
|
||||||
|
has-proto@1.0.3:
|
||||||
|
resolution: {integrity: sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==}
|
||||||
|
engines: {node: '>= 0.4'}
|
||||||
|
|
||||||
|
has-symbols@1.0.3:
|
||||||
|
resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==}
|
||||||
|
engines: {node: '>= 0.4'}
|
||||||
|
|
||||||
|
hasown@2.0.2:
|
||||||
|
resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==}
|
||||||
|
engines: {node: '>= 0.4'}
|
||||||
|
|
||||||
|
humanize-ms@1.2.1:
|
||||||
|
resolution: {integrity: sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==}
|
||||||
|
|
||||||
|
iter-ops@3.5.0:
|
||||||
|
resolution: {integrity: sha512-0/DU67w30nLAyyYETTAVOwtts871N6jjQEY9NAzSXqtlAGuo8CX6O+/Hx11eRZIchACaAMUn6alEndINx27j/Q==}
|
||||||
|
engines: {node: '>=18'}
|
||||||
|
|
||||||
|
mime-db@1.52.0:
|
||||||
|
resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==}
|
||||||
|
engines: {node: '>= 0.6'}
|
||||||
|
|
||||||
|
mime-types@2.1.35:
|
||||||
|
resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==}
|
||||||
|
engines: {node: '>= 0.6'}
|
||||||
|
|
||||||
|
ms@2.1.3:
|
||||||
|
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
|
||||||
|
|
||||||
|
node-domexception@1.0.0:
|
||||||
|
resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==}
|
||||||
|
engines: {node: '>=10.5.0'}
|
||||||
|
|
||||||
|
node-fetch@2.7.0:
|
||||||
|
resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==}
|
||||||
|
engines: {node: 4.x || >=6.0.0}
|
||||||
|
peerDependencies:
|
||||||
|
encoding: ^0.1.0
|
||||||
|
peerDependenciesMeta:
|
||||||
|
encoding:
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
object-inspect@1.13.2:
|
||||||
|
resolution: {integrity: sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==}
|
||||||
|
engines: {node: '>= 0.4'}
|
||||||
|
|
||||||
|
prettier@3.3.3:
|
||||||
|
resolution: {integrity: sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==}
|
||||||
|
engines: {node: '>=14'}
|
||||||
|
hasBin: true
|
||||||
|
|
||||||
|
qs@6.13.0:
|
||||||
|
resolution: {integrity: sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==}
|
||||||
|
engines: {node: '>=0.6'}
|
||||||
|
|
||||||
|
resolve-pkg-maps@1.0.0:
|
||||||
|
resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==}
|
||||||
|
|
||||||
|
set-function-length@1.2.2:
|
||||||
|
resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==}
|
||||||
|
engines: {node: '>= 0.4'}
|
||||||
|
|
||||||
|
side-channel@1.0.6:
|
||||||
|
resolution: {integrity: sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==}
|
||||||
|
engines: {node: '>= 0.4'}
|
||||||
|
|
||||||
|
tr46@0.0.3:
|
||||||
|
resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==}
|
||||||
|
|
||||||
|
tsx@4.19.1:
|
||||||
|
resolution: {integrity: sha512-0flMz1lh74BR4wOvBjuh9olbnwqCPc35OOlfyzHba0Dc+QNUeWX/Gq2YTbnwcWPO3BMd8fkzRVrHcsR+a7z7rA==}
|
||||||
|
engines: {node: '>=18.0.0'}
|
||||||
|
hasBin: true
|
||||||
|
|
||||||
|
undici-types@5.26.5:
|
||||||
|
resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==}
|
||||||
|
|
||||||
|
undici-types@6.19.8:
|
||||||
|
resolution: {integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==}
|
||||||
|
|
||||||
|
web-streams-polyfill@3.3.3:
|
||||||
|
resolution: {integrity: sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==}
|
||||||
|
engines: {node: '>= 8'}
|
||||||
|
|
||||||
|
web-streams-polyfill@4.0.0-beta.3:
|
||||||
|
resolution: {integrity: sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug==}
|
||||||
|
engines: {node: '>= 14'}
|
||||||
|
|
||||||
|
webidl-conversions@3.0.1:
|
||||||
|
resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==}
|
||||||
|
|
||||||
|
whatwg-url@5.0.0:
|
||||||
|
resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==}
|
||||||
|
|
||||||
|
snapshots:
|
||||||
|
|
||||||
|
'@esbuild/aix-ppc64@0.23.1':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@esbuild/android-arm64@0.23.1':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@esbuild/android-arm@0.23.1':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@esbuild/android-x64@0.23.1':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@esbuild/darwin-arm64@0.23.1':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@esbuild/darwin-x64@0.23.1':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@esbuild/freebsd-arm64@0.23.1':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@esbuild/freebsd-x64@0.23.1':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@esbuild/linux-arm64@0.23.1':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@esbuild/linux-arm@0.23.1':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@esbuild/linux-ia32@0.23.1':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@esbuild/linux-loong64@0.23.1':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@esbuild/linux-mips64el@0.23.1':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@esbuild/linux-ppc64@0.23.1':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@esbuild/linux-riscv64@0.23.1':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@esbuild/linux-s390x@0.23.1':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@esbuild/linux-x64@0.23.1':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@esbuild/netbsd-x64@0.23.1':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@esbuild/openbsd-arm64@0.23.1':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@esbuild/openbsd-x64@0.23.1':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@esbuild/sunos-x64@0.23.1':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@esbuild/win32-arm64@0.23.1':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@esbuild/win32-ia32@0.23.1':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@esbuild/win32-x64@0.23.1':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@types/node-fetch@2.6.11':
|
||||||
|
dependencies:
|
||||||
|
'@types/node': 22.7.5
|
||||||
|
form-data: 4.0.1
|
||||||
|
|
||||||
|
'@types/node@18.19.55':
|
||||||
|
dependencies:
|
||||||
|
undici-types: 5.26.5
|
||||||
|
|
||||||
|
'@types/node@22.7.5':
|
||||||
|
dependencies:
|
||||||
|
undici-types: 6.19.8
|
||||||
|
|
||||||
|
'@types/qs@6.9.16': {}
|
||||||
|
|
||||||
|
abort-controller@3.0.0:
|
||||||
|
dependencies:
|
||||||
|
event-target-shim: 5.0.1
|
||||||
|
|
||||||
|
agentkeepalive@4.5.0:
|
||||||
|
dependencies:
|
||||||
|
humanize-ms: 1.2.1
|
||||||
|
|
||||||
|
asynckit@0.4.0: {}
|
||||||
|
|
||||||
|
call-bind@1.0.7:
|
||||||
|
dependencies:
|
||||||
|
es-define-property: 1.0.0
|
||||||
|
es-errors: 1.3.0
|
||||||
|
function-bind: 1.1.2
|
||||||
|
get-intrinsic: 1.2.4
|
||||||
|
set-function-length: 1.2.2
|
||||||
|
|
||||||
|
cloudflare@3.5.0:
|
||||||
|
dependencies:
|
||||||
|
'@types/node': 18.19.55
|
||||||
|
'@types/node-fetch': 2.6.11
|
||||||
|
'@types/qs': 6.9.16
|
||||||
|
abort-controller: 3.0.0
|
||||||
|
agentkeepalive: 4.5.0
|
||||||
|
form-data-encoder: 1.7.2
|
||||||
|
formdata-node: 4.4.1
|
||||||
|
node-fetch: 2.7.0
|
||||||
|
qs: 6.13.0
|
||||||
|
web-streams-polyfill: 3.3.3
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- encoding
|
||||||
|
|
||||||
|
combined-stream@1.0.8:
|
||||||
|
dependencies:
|
||||||
|
delayed-stream: 1.0.0
|
||||||
|
|
||||||
|
define-data-property@1.1.4:
|
||||||
|
dependencies:
|
||||||
|
es-define-property: 1.0.0
|
||||||
|
es-errors: 1.3.0
|
||||||
|
gopd: 1.0.1
|
||||||
|
|
||||||
|
delayed-stream@1.0.0: {}
|
||||||
|
|
||||||
|
dotenv@16.4.5: {}
|
||||||
|
|
||||||
|
es-define-property@1.0.0:
|
||||||
|
dependencies:
|
||||||
|
get-intrinsic: 1.2.4
|
||||||
|
|
||||||
|
es-errors@1.3.0: {}
|
||||||
|
|
||||||
|
esbuild@0.23.1:
|
||||||
|
optionalDependencies:
|
||||||
|
'@esbuild/aix-ppc64': 0.23.1
|
||||||
|
'@esbuild/android-arm': 0.23.1
|
||||||
|
'@esbuild/android-arm64': 0.23.1
|
||||||
|
'@esbuild/android-x64': 0.23.1
|
||||||
|
'@esbuild/darwin-arm64': 0.23.1
|
||||||
|
'@esbuild/darwin-x64': 0.23.1
|
||||||
|
'@esbuild/freebsd-arm64': 0.23.1
|
||||||
|
'@esbuild/freebsd-x64': 0.23.1
|
||||||
|
'@esbuild/linux-arm': 0.23.1
|
||||||
|
'@esbuild/linux-arm64': 0.23.1
|
||||||
|
'@esbuild/linux-ia32': 0.23.1
|
||||||
|
'@esbuild/linux-loong64': 0.23.1
|
||||||
|
'@esbuild/linux-mips64el': 0.23.1
|
||||||
|
'@esbuild/linux-ppc64': 0.23.1
|
||||||
|
'@esbuild/linux-riscv64': 0.23.1
|
||||||
|
'@esbuild/linux-s390x': 0.23.1
|
||||||
|
'@esbuild/linux-x64': 0.23.1
|
||||||
|
'@esbuild/netbsd-x64': 0.23.1
|
||||||
|
'@esbuild/openbsd-arm64': 0.23.1
|
||||||
|
'@esbuild/openbsd-x64': 0.23.1
|
||||||
|
'@esbuild/sunos-x64': 0.23.1
|
||||||
|
'@esbuild/win32-arm64': 0.23.1
|
||||||
|
'@esbuild/win32-ia32': 0.23.1
|
||||||
|
'@esbuild/win32-x64': 0.23.1
|
||||||
|
|
||||||
|
event-target-shim@5.0.1: {}
|
||||||
|
|
||||||
|
form-data-encoder@1.7.2: {}
|
||||||
|
|
||||||
|
form-data@4.0.1:
|
||||||
|
dependencies:
|
||||||
|
asynckit: 0.4.0
|
||||||
|
combined-stream: 1.0.8
|
||||||
|
mime-types: 2.1.35
|
||||||
|
|
||||||
|
formdata-node@4.4.1:
|
||||||
|
dependencies:
|
||||||
|
node-domexception: 1.0.0
|
||||||
|
web-streams-polyfill: 4.0.0-beta.3
|
||||||
|
|
||||||
|
fsevents@2.3.3:
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
function-bind@1.1.2: {}
|
||||||
|
|
||||||
|
get-intrinsic@1.2.4:
|
||||||
|
dependencies:
|
||||||
|
es-errors: 1.3.0
|
||||||
|
function-bind: 1.1.2
|
||||||
|
has-proto: 1.0.3
|
||||||
|
has-symbols: 1.0.3
|
||||||
|
hasown: 2.0.2
|
||||||
|
|
||||||
|
get-tsconfig@4.8.1:
|
||||||
|
dependencies:
|
||||||
|
resolve-pkg-maps: 1.0.0
|
||||||
|
|
||||||
|
gopd@1.0.1:
|
||||||
|
dependencies:
|
||||||
|
get-intrinsic: 1.2.4
|
||||||
|
|
||||||
|
has-property-descriptors@1.0.2:
|
||||||
|
dependencies:
|
||||||
|
es-define-property: 1.0.0
|
||||||
|
|
||||||
|
has-proto@1.0.3: {}
|
||||||
|
|
||||||
|
has-symbols@1.0.3: {}
|
||||||
|
|
||||||
|
hasown@2.0.2:
|
||||||
|
dependencies:
|
||||||
|
function-bind: 1.1.2
|
||||||
|
|
||||||
|
humanize-ms@1.2.1:
|
||||||
|
dependencies:
|
||||||
|
ms: 2.1.3
|
||||||
|
|
||||||
|
iter-ops@3.5.0: {}
|
||||||
|
|
||||||
|
mime-db@1.52.0: {}
|
||||||
|
|
||||||
|
mime-types@2.1.35:
|
||||||
|
dependencies:
|
||||||
|
mime-db: 1.52.0
|
||||||
|
|
||||||
|
ms@2.1.3: {}
|
||||||
|
|
||||||
|
node-domexception@1.0.0: {}
|
||||||
|
|
||||||
|
node-fetch@2.7.0:
|
||||||
|
dependencies:
|
||||||
|
whatwg-url: 5.0.0
|
||||||
|
|
||||||
|
object-inspect@1.13.2: {}
|
||||||
|
|
||||||
|
prettier@3.3.3: {}
|
||||||
|
|
||||||
|
qs@6.13.0:
|
||||||
|
dependencies:
|
||||||
|
side-channel: 1.0.6
|
||||||
|
|
||||||
|
resolve-pkg-maps@1.0.0: {}
|
||||||
|
|
||||||
|
set-function-length@1.2.2:
|
||||||
|
dependencies:
|
||||||
|
define-data-property: 1.1.4
|
||||||
|
es-errors: 1.3.0
|
||||||
|
function-bind: 1.1.2
|
||||||
|
get-intrinsic: 1.2.4
|
||||||
|
gopd: 1.0.1
|
||||||
|
has-property-descriptors: 1.0.2
|
||||||
|
|
||||||
|
side-channel@1.0.6:
|
||||||
|
dependencies:
|
||||||
|
call-bind: 1.0.7
|
||||||
|
es-errors: 1.3.0
|
||||||
|
get-intrinsic: 1.2.4
|
||||||
|
object-inspect: 1.13.2
|
||||||
|
|
||||||
|
tr46@0.0.3: {}
|
||||||
|
|
||||||
|
tsx@4.19.1:
|
||||||
|
dependencies:
|
||||||
|
esbuild: 0.23.1
|
||||||
|
get-tsconfig: 4.8.1
|
||||||
|
optionalDependencies:
|
||||||
|
fsevents: 2.3.3
|
||||||
|
|
||||||
|
undici-types@5.26.5: {}
|
||||||
|
|
||||||
|
undici-types@6.19.8: {}
|
||||||
|
|
||||||
|
web-streams-polyfill@3.3.3: {}
|
||||||
|
|
||||||
|
web-streams-polyfill@4.0.0-beta.3: {}
|
||||||
|
|
||||||
|
webidl-conversions@3.0.1: {}
|
||||||
|
|
||||||
|
whatwg-url@5.0.0:
|
||||||
|
dependencies:
|
||||||
|
tr46: 0.0.3
|
||||||
|
webidl-conversions: 3.0.1
|
||||||
240
src/index.ts
Normal file
240
src/index.ts
Normal file
@@ -0,0 +1,240 @@
|
|||||||
|
import Cloudflare from "cloudflare";
|
||||||
|
import "dotenv/config";
|
||||||
|
import { exit, stdin, stdout } from "node:process";
|
||||||
|
import { createInterface } from "node:readline/promises";
|
||||||
|
const packageJson = require("../package.json");
|
||||||
|
|
||||||
|
const cloudflare = new Cloudflare({
|
||||||
|
apiToken: process.env.CLOUDFLARE_API_TOKEN,
|
||||||
|
});
|
||||||
|
|
||||||
|
const targetZone = process.env.TARGET_ZONE_ID!;
|
||||||
|
const commentTag = `${packageJson.name} v${packageJson.version}`;
|
||||||
|
|
||||||
|
type Context = {
|
||||||
|
targetZone: string;
|
||||||
|
domain: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
async function confirmAction(message: string): Promise<void> {
|
||||||
|
const readline = createInterface({ input: stdin, output: stdout });
|
||||||
|
const answer = await readline.question(`${message} (y/n) `);
|
||||||
|
readline.close();
|
||||||
|
if (answer.toLowerCase() !== "y") exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function list(
|
||||||
|
params: Cloudflare.DNS.RecordListParams,
|
||||||
|
options?: Cloudflare.RequestOptions,
|
||||||
|
): Promise<Cloudflare.DNS.Record[]> {
|
||||||
|
const records: Cloudflare.DNS.Record[] = [];
|
||||||
|
const response = await cloudflare.dns.records.list(params, options);
|
||||||
|
for await (const page of response.iterPages())
|
||||||
|
records.push(...page.getPaginatedItems());
|
||||||
|
return records;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function handleMxRecords(ctx: Context) {
|
||||||
|
// Get all existing MX records
|
||||||
|
const existingRecords = await list({
|
||||||
|
zone_id: targetZone,
|
||||||
|
type: "MX",
|
||||||
|
per_page: 50,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Implied: name = @
|
||||||
|
const mxRecords: [string, number, boolean][] = [
|
||||||
|
["in1-smtp.messagingengine.com", 10, false],
|
||||||
|
["in2-smtp.messagingengine.com", 20, false],
|
||||||
|
];
|
||||||
|
|
||||||
|
// Update or delete existing records
|
||||||
|
for await (const record of existingRecords) {
|
||||||
|
// if the record's content doesn't match any of the required records, delete it
|
||||||
|
const matchIndex: number = mxRecords.findIndex(
|
||||||
|
([content, _]) => record.name == ctx.domain && content === record.content,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Delete the record if it doesn't match any of the required records
|
||||||
|
if (matchIndex === -1) {
|
||||||
|
console.log(`[DELETE] MX ${record.name} -> ${record.content}`);
|
||||||
|
await cloudflare.dns.records.delete(record.id!, {
|
||||||
|
zone_id: targetZone,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Skip to the next record, nothing to be updated
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
// Mark the required record as existing, so we don't create it later
|
||||||
|
mxRecords[matchIndex][2] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the record's priority matches the required priority
|
||||||
|
const requiredPriority = mxRecords[matchIndex][1];
|
||||||
|
if ((record as Cloudflare.DNS.MXRecord).priority !== requiredPriority) {
|
||||||
|
console.log(`[UPDATE] MX ${record.name} -> ${record.content}`);
|
||||||
|
await cloudflare.dns.records.update(record.id!, {
|
||||||
|
zone_id: targetZone,
|
||||||
|
name: record.name,
|
||||||
|
type: "MX",
|
||||||
|
content: record.content as string,
|
||||||
|
priority: requiredPriority,
|
||||||
|
comment:
|
||||||
|
record.comment != undefined
|
||||||
|
? `${record.comment}, Updated by ${commentTag}`
|
||||||
|
: `Updated by ${commentTag}`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create new records
|
||||||
|
for (const [content, priority, exists] of mxRecords) {
|
||||||
|
if (exists) continue;
|
||||||
|
console.log(`[CREATE] MX ${ctx.domain} -> ${content}`);
|
||||||
|
await cloudflare.dns.records.create({
|
||||||
|
zone_id: targetZone,
|
||||||
|
name: "@",
|
||||||
|
type: "MX",
|
||||||
|
content: content,
|
||||||
|
priority: priority,
|
||||||
|
comment: `Generated by ${commentTag}`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("MX records updated successfully.");
|
||||||
|
}
|
||||||
|
|
||||||
|
async function handleCnameRecords(ctx: Context) {
|
||||||
|
const requiredRecords = [
|
||||||
|
["fm1._domainkey", `fm1.${ctx.domain}.dkim.fmhosted.com`],
|
||||||
|
["fm2._domainkey", `fm2.${ctx.domain}.dkim.fmhosted.com`],
|
||||||
|
["fm3._domainkey", `fm3.${ctx.domain}.dkim.fmhosted.com`],
|
||||||
|
];
|
||||||
|
|
||||||
|
// Get all existing CNAME records
|
||||||
|
const existingRecords = await list({
|
||||||
|
zone_id: targetZone,
|
||||||
|
type: "CNAME",
|
||||||
|
per_page: 50,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Iterate all required records, update or create them
|
||||||
|
for (const [requiredName, requiredContent] of requiredRecords) {
|
||||||
|
const recordExists = existingRecords.find(
|
||||||
|
(record) => record.name === requiredName + "." + ctx.domain,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Update existing record
|
||||||
|
if (recordExists) {
|
||||||
|
// Skip if the record's content is already correct
|
||||||
|
if (recordExists.content === requiredContent) continue;
|
||||||
|
|
||||||
|
console.log(`[UPDATE] CNAME ${requiredName} -> ${requiredContent}`);
|
||||||
|
await cloudflare.dns.records.update(recordExists.id!, {
|
||||||
|
zone_id: targetZone,
|
||||||
|
name: recordExists.name,
|
||||||
|
type: "CNAME",
|
||||||
|
content: requiredContent,
|
||||||
|
comment:
|
||||||
|
recordExists.comment != undefined
|
||||||
|
? `${recordExists.comment}, Updated by ${commentTag}`
|
||||||
|
: `Updated by ${commentTag}`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create new record
|
||||||
|
console.log(`[CREATE] CNAME ${requiredName} -> ${requiredContent}`);
|
||||||
|
await cloudflare.dns.records.create({
|
||||||
|
zone_id: targetZone,
|
||||||
|
name: requiredName,
|
||||||
|
type: "CNAME",
|
||||||
|
content: requiredContent,
|
||||||
|
comment: `Generated by ${commentTag}`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("CNAME/DKIM records updated successfully.");
|
||||||
|
}
|
||||||
|
|
||||||
|
async function handleSpfRecords() {
|
||||||
|
const spfRecord = "v=spf1 include:spf.messagingengine.com ?all";
|
||||||
|
|
||||||
|
// Get all existing SPF records
|
||||||
|
const existingRecords = await list({
|
||||||
|
zone_id: targetZone,
|
||||||
|
type: "TXT",
|
||||||
|
per_page: 50,
|
||||||
|
});
|
||||||
|
let recordAlreadyExists = false;
|
||||||
|
|
||||||
|
// Check if the SPF record already exists
|
||||||
|
for await (const record of existingRecords) {
|
||||||
|
if (record.content === spfRecord) {
|
||||||
|
recordAlreadyExists = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If record was not found, delete all existing SPF records
|
||||||
|
if (!recordAlreadyExists) {
|
||||||
|
for await (const record of existingRecords) {
|
||||||
|
if ((record.content as string).startsWith("v=spf1")) {
|
||||||
|
console.log(`[DELETE] SPF @ -> ${record.content}`);
|
||||||
|
|
||||||
|
// Confirm with user
|
||||||
|
await confirmAction(
|
||||||
|
`SPF record found: ${record.content}. Do you want to delete it?`,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Delete the record
|
||||||
|
await cloudflare.dns.records.delete(record.id!, {
|
||||||
|
zone_id: targetZone,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add new SPF record
|
||||||
|
if (!recordAlreadyExists) {
|
||||||
|
console.log(`[CREATE] SPF @ -> ${spfRecord}`);
|
||||||
|
await cloudflare.dns.records.create({
|
||||||
|
zone_id: targetZone,
|
||||||
|
type: "TXT",
|
||||||
|
name: "@",
|
||||||
|
content: spfRecord,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("SPF records updated successfully.");
|
||||||
|
}
|
||||||
|
|
||||||
|
async function main() {
|
||||||
|
// If target zone is not provided, list all zones with name + id
|
||||||
|
if (!targetZone) {
|
||||||
|
const response = await cloudflare.zones.list({ per_page: 2 });
|
||||||
|
for await (const page of response.iterPages()) {
|
||||||
|
page.getPaginatedItems().forEach((zone) => {
|
||||||
|
console.log(`Zone: ${zone.name} (${zone.id})`);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
console.log("Please provide a target zone id via TARGET_ZONE_ID");
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get zone details
|
||||||
|
const zone = await cloudflare.zones.get({ zone_id: targetZone });
|
||||||
|
const ctx = { targetZone, domain: zone.name };
|
||||||
|
|
||||||
|
// Clears MX records, then adds required ones
|
||||||
|
await handleMxRecords(ctx);
|
||||||
|
|
||||||
|
// Replace or Add CNAME records
|
||||||
|
await handleCnameRecords(ctx);
|
||||||
|
|
||||||
|
// Replace or Add SPF records
|
||||||
|
await handleSpfRecords();
|
||||||
|
|
||||||
|
console.log("Done.");
|
||||||
|
}
|
||||||
|
|
||||||
|
main();
|
||||||
Reference in New Issue
Block a user