feat: |Worker| support multi language (#584)

This commit is contained in:
Dream Hunter
2025-02-20 00:37:39 +08:00
committed by GitHub
parent 2426e0b51a
commit 7889d2edea
23 changed files with 911 additions and 850 deletions

View File

@@ -1,7 +1,11 @@
<!-- markdownlint-disable-file MD004 MD024 MD034 MD036 -->
# CHANGE LOG
## main(v0.8.7)
## main(v0.9.0)
- feat: | Worker | 支持多语言
## v0.8.7
- fix: |UI| 修复移动设备日期显示问题
- feat: |Worker| 支持通过 `SMTP` 发送邮件, 使用 [zou-yu/worker-mailer](https://github.com/zou-yu/worker-mailer/blob/main/README_zh-CN.md)

View File

@@ -1,6 +1,6 @@
{
"name": "cloudflare_temp_email",
"version": "0.8.7",
"version": "0.9.0",
"private": true,
"type": "module",
"scripts": {
@@ -40,13 +40,13 @@
"@vicons/material": "^0.13.0",
"@vitejs/plugin-vue": "^5.2.1",
"unplugin-auto-import": "^19.1.0",
"unplugin-vue-components": "^28.1.0",
"vite": "^6.1.0",
"unplugin-vue-components": "^28.4.0",
"vite": "^6.1.1",
"vite-plugin-pwa": "^0.21.1",
"vite-plugin-top-level-await": "^1.5.0",
"vite-plugin-wasm": "^3.4.1",
"workbox-build": "^7.3.0",
"workbox-window": "^7.3.0",
"wrangler": "^3.109.1"
"wrangler": "^3.109.2"
}
}

492
frontend/pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -2,6 +2,8 @@ import { useGlobalState } from '../store'
import { h } from 'vue'
import axios from 'axios'
import i18n from '../i18n'
const API_BASE = import.meta.env.VITE_API_BASE || "";
const {
loading, auth, jwt, settings, openSettings,
@@ -22,6 +24,7 @@ const apiFetch = async (path, options = {}) => {
method: options.method || 'GET',
data: options.body || null,
headers: {
'x-lang': i18n.global.locale.value,
'x-user-token': userJwt.value,
'x-user-access-token': userSettings.value.access_token,
'x-custom-auth': auth.value,
@@ -32,14 +35,12 @@ const apiFetch = async (path, options = {}) => {
});
if (response.status === 401 && path.startsWith("/admin")) {
showAdminAuth.value = true;
throw new Error("Unauthorized, your admin password is wrong")
}
if (response.status === 401 && openSettings.value.auth) {
showAuth.value = true;
throw new Error("Unauthorized, you access password is wrong")
}
if (response.status >= 300) {
throw new Error(`${response.status} ${response.data}` || "error");
throw new Error(`[${response.status}]: ${response.data}` || "error");
}
const data = response.data;
return data;

15
frontend/src/i18n.ts Normal file
View File

@@ -0,0 +1,15 @@
import { createI18n } from 'vue-i18n'
const i18n = createI18n({
legacy: false, // you must set `false`, to use Composition API
locale: 'zh', // set locale
fallbackLocale: 'en', // set fallback locale
'en': {
messages: {}
},
'zh': {
messages: {}
}
})
export default i18n;

View File

@@ -1,20 +1,9 @@
import { createApp } from 'vue'
import App from './App.vue'
import { createI18n } from 'vue-i18n'
import router from './router'
import { createHead } from '@unhead/vue'
const i18n = createI18n({
legacy: false, // you must set `false`, to use Composition API
locale: 'zh', // set locale
fallbackLocale: 'en', // set fallback locale
'en': {
messages: {}
},
'zh': {
messages: {}
}
})
import i18n from './i18n'
router.beforeEach((to, from) => {
if (to.params.lang && ['en', 'zh'].includes(to.params.lang)) {

View File

@@ -1,6 +1,6 @@
{
"name": "temp-email-pages",
"version": "0.8.7",
"version": "0.9.0",
"description": "",
"main": "index.js",
"scripts": {
@@ -11,6 +11,6 @@
"author": "",
"license": "ISC",
"devDependencies": {
"wrangler": "^3.109.1"
"wrangler": "^3.109.2"
}
}

View File

@@ -1,12 +1,12 @@
{
"name": "temp-mail-docs",
"private": true,
"version": "0.8.7",
"version": "0.9.0",
"type": "module",
"devDependencies": {
"@types/node": "^22.13.4",
"vitepress": "^1.6.3",
"wrangler": "^3.109.1"
"wrangler": "^3.109.2"
},
"scripts": {
"dev": "vitepress dev docs",

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{
"name": "cloudflare_temp_email",
"version": "0.8.7",
"version": "0.9.0",
"private": true,
"type": "module",
"scripts": {
@@ -16,14 +16,14 @@
"@simplewebauthn/types": "10.0.0",
"eslint": "9.18.0",
"globals": "^15.15.0",
"typescript-eslint": "^8.24.0",
"wrangler": "^3.109.1"
"typescript-eslint": "^8.24.1",
"wrangler": "^3.109.2"
},
"dependencies": {
"@aws-sdk/client-s3": "^3.749.0",
"@aws-sdk/s3-request-presigner": "^3.749.0",
"@aws-sdk/client-s3": "^3.750.0",
"@aws-sdk/s3-request-presigner": "^3.750.0",
"@simplewebauthn/server": "10.0.1",
"hono": "^4.7.1",
"hono": "^4.7.2",
"mimetext": "^3.0.27",
"postal-mime": "^2.4.3",
"resend": "^4.1.2",

406
worker/pnpm-lock.yaml generated
View File

@@ -14,17 +14,17 @@ importers:
.:
dependencies:
'@aws-sdk/client-s3':
specifier: ^3.749.0
version: 3.749.0
specifier: ^3.750.0
version: 3.750.0
'@aws-sdk/s3-request-presigner':
specifier: ^3.749.0
version: 3.749.0
specifier: ^3.750.0
version: 3.750.0
'@simplewebauthn/server':
specifier: 10.0.1
version: 10.0.1
hono:
specifier: ^4.7.1
version: 4.7.1
specifier: ^4.7.2
version: 4.7.2
mimetext:
specifier: ^3.0.27
version: 3.0.27
@@ -57,11 +57,11 @@ importers:
specifier: ^15.15.0
version: 15.15.0
typescript-eslint:
specifier: ^8.24.0
version: 8.24.0(eslint@9.18.0)(typescript@5.4.5)
specifier: ^8.24.1
version: 8.24.1(eslint@9.18.0)(typescript@5.4.5)
wrangler:
specifier: ^3.109.1
version: 3.109.1(@cloudflare/workers-types@4.20250214.0)
specifier: ^3.109.2
version: 3.109.2(@cloudflare/workers-types@4.20250214.0)
packages:
@@ -88,44 +88,44 @@ packages:
'@aws-crypto/util@5.2.0':
resolution: {integrity: sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==}
'@aws-sdk/client-s3@3.749.0':
resolution: {integrity: sha512-Xi+DaBeYRIa2d+1QTAlBdbRIc9j3+H+H5aMbxIrlyIYE2NOz+4fhIgpUYuF4ln63p9Fby5Wh36DhHJYyN4uE0w==}
'@aws-sdk/client-s3@3.750.0':
resolution: {integrity: sha512-S9G9noCeBxchoMVkHYrRi1A1xW/VOTP2W7X34lP+Y7Wpl32yMA7IJo0fAGAuTc0q1Nu6/pXDm+oDG7rhTCA1tg==}
engines: {node: '>=18.0.0'}
'@aws-sdk/client-sso@3.749.0':
resolution: {integrity: sha512-ecmuDu8EPya1LDpGRtpgN7C9PHayDh8EaW37ZBKhuxA7cg099yvTFqsGngwRXbhNjKJ4oVa9OUe0EDnu60atYA==}
'@aws-sdk/client-sso@3.750.0':
resolution: {integrity: sha512-y0Rx6pTQXw0E61CaptpZF65qNggjqOgymq/RYZU5vWba5DGQ+iqGt8Yq8s+jfBoBBNXshxq8l8Dl5Uq/JTY1wg==}
engines: {node: '>=18.0.0'}
'@aws-sdk/core@3.749.0':
resolution: {integrity: sha512-w5Jj573+XKwrDNZUjUJDXL5upx+RCw64TLq3Zk8FVg9MsgkzAPorQ9qmzffi6os+PWngd3pFmD8q5y+Y35LpFQ==}
'@aws-sdk/core@3.750.0':
resolution: {integrity: sha512-bZ5K7N5L4+Pa2epbVpUQqd1XLG2uU8BGs/Sd+2nbgTf+lNQJyIxAg/Qsrjz9MzmY8zzQIeRQEkNmR6yVAfCmmQ==}
engines: {node: '>=18.0.0'}
'@aws-sdk/credential-provider-env@3.749.0':
resolution: {integrity: sha512-bhB1ds5QzcSfmCTbjVessXy8xHJROota6wOhFtBsL1aZRQyNN2a9h2QS6xkxjmqVE3yHBsPz+OiSOeLn0kxm7Q==}
'@aws-sdk/credential-provider-env@3.750.0':
resolution: {integrity: sha512-In6bsG0p/P31HcH4DBRKBbcDS/3SHvEPjfXV8ODPWZO/l3/p7IRoYBdQ07C9R+VMZU2D0+/Sc/DWK/TUNDk1+Q==}
engines: {node: '>=18.0.0'}
'@aws-sdk/credential-provider-http@3.749.0':
resolution: {integrity: sha512-enFGT8uvETbE6+4bDA2aTOrA/83GrIVPpg2g2r7MwJb36jreXA3KDXaP/5jQsxyIZW70cnYNl/Cawdd4ZXs7CQ==}
'@aws-sdk/credential-provider-http@3.750.0':
resolution: {integrity: sha512-wFB9qqfa20AB0dElsQz5ZlZT5o+a+XzpEpmg0erylmGYqEOvh8NQWfDUVpRmQuGq9VbvW/8cIbxPoNqEbPtuWQ==}
engines: {node: '>=18.0.0'}
'@aws-sdk/credential-provider-ini@3.749.0':
resolution: {integrity: sha512-OB4AGK61lQdoW2mTmaMBw8L+eBo7wF3YJZXwqFI7M2cQe9WtfuKGIxbYWMBMzoLvEtmsbzeppoZZUezooaIclg==}
'@aws-sdk/credential-provider-ini@3.750.0':
resolution: {integrity: sha512-2YIZmyEr5RUd3uxXpxOLD9G67Bibm4I/65M6vKFP17jVMUT+R1nL7mKqmhEVO2p+BoeV+bwMyJ/jpTYG368PCg==}
engines: {node: '>=18.0.0'}
'@aws-sdk/credential-provider-node@3.749.0':
resolution: {integrity: sha512-1QGstZmGmgmY0rLSTAURlBJdR4s2PRYiZh6dS4HkzzQu7xVDWoCMD+2F7dolsNA8ChTNx2OvBW80n3O9QPICCg==}
'@aws-sdk/credential-provider-node@3.750.0':
resolution: {integrity: sha512-THWHHAceLwsOiowPEmKyhWVDlEUxH07GHSw5AQFDvNQtGKOQl0HSIFO1mKObT2Q2Vqzji9Bq8H58SO5BFtNPRw==}
engines: {node: '>=18.0.0'}
'@aws-sdk/credential-provider-process@3.749.0':
resolution: {integrity: sha512-C/cgg/AhRabybZRY9mJ6KDz8uqfasWKuFIFGzTpeb/MIDIL53ZqP61CspiQJTRvC4zlFGqvm43XefphfrBGGlQ==}
'@aws-sdk/credential-provider-process@3.750.0':
resolution: {integrity: sha512-Q78SCH1n0m7tpu36sJwfrUSxI8l611OyysjQeMiIOliVfZICEoHcLHLcLkiR+tnIpZ3rk7d2EQ6R1jwlXnalMQ==}
engines: {node: '>=18.0.0'}
'@aws-sdk/credential-provider-sso@3.749.0':
resolution: {integrity: sha512-bQNgWcYk10fYOvFwcLskYYVNLO3KMgmV1ip9ieapJb9JDg6bSBaXNjIDhdpK4biTOfrV+adtDO5EU93ogpmAWA==}
'@aws-sdk/credential-provider-sso@3.750.0':
resolution: {integrity: sha512-FGYrDjXN/FOQVi/t8fHSv8zCk+NEvtFnuc4cZUj5OIbM4vrfFc5VaPyn41Uza3iv6Qq9rZg0QOwWnqK8lNrqUw==}
engines: {node: '>=18.0.0'}
'@aws-sdk/credential-provider-web-identity@3.749.0':
resolution: {integrity: sha512-jzHk6i4G4dnXL+L+qeILguDCiIhA1rNvJzB5lTts4R8OdmNkG12bGbYL8bL4O1b5qCimlo7HS0IZIby0pS7rcg==}
'@aws-sdk/credential-provider-web-identity@3.750.0':
resolution: {integrity: sha512-Nz8zs3YJ+GOTSrq+LyzbbC1Ffpt7pK38gcOyNZv76pP5MswKTUKNYBJehqwa+i7FcFQHsCk3TdhR8MT1ZR23uA==}
engines: {node: '>=18.0.0'}
'@aws-sdk/middleware-bucket-endpoint@3.734.0':
@@ -136,8 +136,8 @@ packages:
resolution: {integrity: sha512-P38/v1l6HjuB2aFUewt7ueAW5IvKkFcv5dalPtbMGRhLeyivBOHwbCyuRKgVs7z7ClTpu9EaViEGki2jEQqEsQ==}
engines: {node: '>=18.0.0'}
'@aws-sdk/middleware-flexible-checksums@3.749.0':
resolution: {integrity: sha512-LebOuHbO5BPeke0EB7I7aU7EK807XEyHeCQ3El4CztkGr7cY37PiYP5E0bsSs/4dlK534en/oD0dBA82gZ3xcg==}
'@aws-sdk/middleware-flexible-checksums@3.750.0':
resolution: {integrity: sha512-ach0d2buDnX2TUausUbiXXFWFo3IegLnCrA+Rw8I9AYVpLN9lTaRwAYJwYC6zEuW9Golff8MwkYsp/OaC5tKMw==}
engines: {node: '>=18.0.0'}
'@aws-sdk/middleware-host-header@3.734.0':
@@ -156,36 +156,36 @@ packages:
resolution: {integrity: sha512-CUat2d9ITsFc2XsmeiRQO96iWpxSKYFjxvj27Hc7vo87YUHRnfMfnc8jw1EpxEwMcvBD7LsRa6vDNky6AjcrFA==}
engines: {node: '>=18.0.0'}
'@aws-sdk/middleware-sdk-s3@3.749.0':
resolution: {integrity: sha512-A7OaNkSFzI2vCRarSKEzoVejAyiLY1M1Z6PR3TE2woAPUUAgRv5UlFOXSymBx1Ya3HUQzWky7mnpnKAFyRGzSg==}
'@aws-sdk/middleware-sdk-s3@3.750.0':
resolution: {integrity: sha512-3H6Z46cmAQCHQ0z8mm7/cftY5ifiLfCjbObrbyyp2fhQs9zk6gCKzIX8Zjhw0RMd93FZi3ebRuKJWmMglf4Itw==}
engines: {node: '>=18.0.0'}
'@aws-sdk/middleware-ssec@3.734.0':
resolution: {integrity: sha512-d4yd1RrPW/sspEXizq2NSOUivnheac6LPeLSLnaeTbBG9g1KqIqvCzP1TfXEqv2CrWfHEsWtJpX7oyjySSPvDQ==}
engines: {node: '>=18.0.0'}
'@aws-sdk/middleware-user-agent@3.749.0':
resolution: {integrity: sha512-dNRkZtiM8OoGb/h2Fgrgvty9ltYEubzsD5FH+VN14RrluertLQMmqHrgvq7JoAXFf7MJy+uwhRu4V6pf1sZR/w==}
'@aws-sdk/middleware-user-agent@3.750.0':
resolution: {integrity: sha512-YYcslDsP5+2NZoN3UwuhZGkhAHPSli7HlJHBafBrvjGV/I9f8FuOO1d1ebxGdEP4HyRXUGyh+7Ur4q+Psk0ryw==}
engines: {node: '>=18.0.0'}
'@aws-sdk/nested-clients@3.749.0':
resolution: {integrity: sha512-5L8OuVojcVQAZw+iVXTaw88AZTlMw8fD51lB6spzbZdNLl6dd5Iz1JVJAOUl2mTAZXRiN5Q9VECwY1yMgWweAw==}
'@aws-sdk/nested-clients@3.750.0':
resolution: {integrity: sha512-OH68BRF0rt9nDloq4zsfeHI0G21lj11a66qosaljtEP66PWm7tQ06feKbFkXHT5E1K3QhJW3nVyK8v2fEBY5fg==}
engines: {node: '>=18.0.0'}
'@aws-sdk/region-config-resolver@3.734.0':
resolution: {integrity: sha512-Lvj1kPRC5IuJBr9DyJ9T9/plkh+EfKLy+12s/mykOy1JaKHDpvj+XGy2YO6YgYVOb8JFtaqloid+5COtje4JTQ==}
engines: {node: '>=18.0.0'}
'@aws-sdk/s3-request-presigner@3.749.0':
resolution: {integrity: sha512-ZUBBJvKGXNuLTsHymBjGsr6WoouRVojURouAc8ueePWxTCt0u/mOOP0KRFVfwmM166YMr+QWr/ym4bJ8aHLAkA==}
'@aws-sdk/s3-request-presigner@3.750.0':
resolution: {integrity: sha512-G4GNngNQlh9EyJZj2WKOOikX0Fev1WSxTV/XJugaHlpnVriebvi3GzolrgxUpRrcGpFGWjmAxLi/gYxTUla1ow==}
engines: {node: '>=18.0.0'}
'@aws-sdk/signature-v4-multi-region@3.749.0':
resolution: {integrity: sha512-8ZR3vnJn1Tgg/qpalkyQMUILzZhw6XV1aCDxYMevqHYu6/f0ujvytJjiUd+j92sfxgN781f6bWpt/jVY0jarxg==}
'@aws-sdk/signature-v4-multi-region@3.750.0':
resolution: {integrity: sha512-RA9hv1Irro/CrdPcOEXKwJ0DJYJwYCsauGEdRXihrRfy8MNSR9E+mD5/Fr5Rxjaq5AHM05DYnN3mg/DU6VwzSw==}
engines: {node: '>=18.0.0'}
'@aws-sdk/token-providers@3.749.0':
resolution: {integrity: sha512-s3ExVWoNZan6U7ljMqjiHq3bOe4EqL+U+cVPwqNxAsMaJpGyCiA8VQFlXNGg0EPAFbz/0DVBcozYht6/vyH3sg==}
'@aws-sdk/token-providers@3.750.0':
resolution: {integrity: sha512-X/KzqZw41iWolwNdc8e3RMcNSMR364viHv78u6AefXOO5eRM40c4/LuST1jDzq35/LpnqRhL7/MuixOetw+sFw==}
engines: {node: '>=18.0.0'}
'@aws-sdk/types@3.734.0':
@@ -211,8 +211,8 @@ packages:
'@aws-sdk/util-user-agent-browser@3.734.0':
resolution: {integrity: sha512-xQTCus6Q9LwUuALW+S76OL0jcWtMOVu14q+GoLnWPUM7QeUw963oQcLhF7oq0CtaLLKyl4GOUfcwc773Zmwwng==}
'@aws-sdk/util-user-agent-node@3.749.0':
resolution: {integrity: sha512-uBzolGGrwvZKhpYlGIy9tw6gRdqVs2zyjjXUiifdgbr3WiQXJe8sE1KhLjzyN/VOPcZB0rY34ybqiKEDOymOeQ==}
'@aws-sdk/util-user-agent-node@3.750.0':
resolution: {integrity: sha512-84HJj9G9zbrHX2opLk9eHfDceB+UIHVrmflMzWHpsmo9fDuro/flIBqaVDlE021Osj6qIM0SJJcnL6s23j7JEw==}
engines: {node: '>=18.0.0'}
peerDependencies:
aws-crt: '>=1.0.0'
@@ -236,32 +236,32 @@ packages:
resolution: {integrity: sha512-YLPHc8yASwjNkmcDMQMY35yiWjoKAKnhUbPRszBRS0YgH+IXtsMp61j+yTcnCE3oO2DgP0U3iejLC8FTtKDC8Q==}
engines: {node: '>=16.13'}
'@cloudflare/workerd-darwin-64@1.20250204.0':
resolution: {integrity: sha512-HpsgbWEfvdcwuZ8WAZhi1TlSCyyHC3tbghpKsOqGDaQNltyAFAWqa278TPNfcitYf/FmV4961v3eqUE+RFdHNQ==}
'@cloudflare/workerd-darwin-64@1.20250214.0':
resolution: {integrity: sha512-cDvvedWDc5zrgDnuXe2qYcz/TwBvzmweO55C7XpPuAWJ9Oqxv81PkdekYxD8mH989aQ/GI5YD0Fe6fDYlM+T3Q==}
engines: {node: '>=16'}
cpu: [x64]
os: [darwin]
'@cloudflare/workerd-darwin-arm64@1.20250204.0':
resolution: {integrity: sha512-AJ8Tk7KMJqePlch3SH8oL41ROtsrb07hKRHD6M+FvGC3tLtf26rpteAAMNYKMDYKzFNFUIKZNijYDFZjBFndXQ==}
'@cloudflare/workerd-darwin-arm64@1.20250214.0':
resolution: {integrity: sha512-NytCvRveVzu0mRKo+tvZo3d/gCUway3B2ZVqSi/TS6NXDGBYIJo7g6s3BnTLS74kgyzeDOjhu9j/RBJBS809qw==}
engines: {node: '>=16'}
cpu: [arm64]
os: [darwin]
'@cloudflare/workerd-linux-64@1.20250204.0':
resolution: {integrity: sha512-RIUfUSnDC8h73zAa+u1K2Frc7nc+eeQoBBP7SaqsRe6JdX8jfIv/GtWjQWCoj8xQFgLvhpJKZ4sTTTV+AilQbw==}
'@cloudflare/workerd-linux-64@1.20250214.0':
resolution: {integrity: sha512-pQ7+aHNHj8SiYEs4d/6cNoimE5xGeCMfgU1yfDFtA9YGN9Aj2BITZgOWPec+HW7ZkOy9oWlNrO6EvVjGgB4tbQ==}
engines: {node: '>=16'}
cpu: [x64]
os: [linux]
'@cloudflare/workerd-linux-arm64@1.20250204.0':
resolution: {integrity: sha512-8Ql8jDjoIgr2J7oBD01kd9kduUz60njofrBpAOkjCPed15He8e8XHkYaYow3g0xpae4S2ryrPOeoD3M64sRxeg==}
'@cloudflare/workerd-linux-arm64@1.20250214.0':
resolution: {integrity: sha512-Vhlfah6Yd9ny1npNQjNgElLIjR6OFdEbuR3LCfbLDCwzWEBFhIf7yC+Tpp/a0Hq7kLz3sLdktaP7xl3PJhyOjA==}
engines: {node: '>=16'}
cpu: [arm64]
os: [linux]
'@cloudflare/workerd-windows-64@1.20250204.0':
resolution: {integrity: sha512-RpDJO3+to+e17X3EWfRCagboZYwBz2fowc+jL53+fd7uD19v3F59H48lw2BDpHJMRyhg6ouWcpM94OhsHv8ecA==}
'@cloudflare/workerd-windows-64@1.20250214.0':
resolution: {integrity: sha512-GMwMyFbkjBKjYJoKDhGX8nuL4Gqe3IbVnVWf2Q6086CValyIknupk5J6uQWGw2EBU3RGO3x4trDXT5WphQJZDQ==}
engines: {node: '>=16'}
cpu: [x64]
os: [win32]
@@ -436,6 +436,10 @@ packages:
resolution: {integrity: sha512-gFHJ+xBOo4G3WRlR1e/3G8A6/KZAH6zcE/hkLRCZTi/B9avAG365QhFA8uOGzTMqgTghpn7/fSnscW++dpMSAw==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@eslint/core@0.11.0':
resolution: {integrity: sha512-DWUB2pksgNEb6Bz2fggIy1wh6fGgZP4Xyy/Mt0QZPiloKKXerbqq9D3SBQTlCRYOrcRPu4vuz+CGjwdfqxnoWA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@eslint/eslintrc@3.2.0':
resolution: {integrity: sha512-grOjVNN8P3hjJn/eIETF1wwd12DdnwFDoyceUJLYYdkpbwq3nLi+4fqrTAONx7XDALqlL220wC/RHSC/QTI/0w==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
@@ -448,8 +452,8 @@ packages:
resolution: {integrity: sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@eslint/plugin-kit@0.2.5':
resolution: {integrity: sha512-lB05FkqEdUg2AA0xEbUz0SnkXT1LcCTa438W4IWTUh4hdOnVbQyOJ81OrDXsJk/LSiJHubgGEFoR5EHq1NsH1A==}
'@eslint/plugin-kit@0.2.6':
resolution: {integrity: sha512-+0TjwR1eAUdZtvv/ir1mGX+v0tUoR3VEPB8Up0LLJC+whRW0GgBBtpbOkg/a/U4Dxa6l5a3l9AJ1aWIQVyoWJA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@fastify/busboy@2.1.1':
@@ -873,51 +877,51 @@ packages:
'@types/json-schema@7.0.15':
resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==}
'@typescript-eslint/eslint-plugin@8.24.0':
resolution: {integrity: sha512-aFcXEJJCI4gUdXgoo/j9udUYIHgF23MFkg09LFz2dzEmU0+1Plk4rQWv/IYKvPHAtlkkGoB3m5e6oUp+JPsNaQ==}
'@typescript-eslint/eslint-plugin@8.24.1':
resolution: {integrity: sha512-ll1StnKtBigWIGqvYDVuDmXJHVH4zLVot1yQ4fJtLpL7qacwkxJc1T0bptqw+miBQ/QfUbhl1TcQ4accW5KUyA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
'@typescript-eslint/parser': ^8.0.0 || ^8.0.0-alpha.0
eslint: ^8.57.0 || ^9.0.0
typescript: '>=4.8.4 <5.8.0'
'@typescript-eslint/parser@8.24.0':
resolution: {integrity: sha512-MFDaO9CYiard9j9VepMNa9MTcqVvSny2N4hkY6roquzj8pdCBRENhErrteaQuu7Yjn1ppk0v1/ZF9CG3KIlrTA==}
'@typescript-eslint/parser@8.24.1':
resolution: {integrity: sha512-Tqoa05bu+t5s8CTZFaGpCH2ub3QeT9YDkXbPd3uQ4SfsLoh1/vv2GEYAioPoxCWJJNsenXlC88tRjwoHNts1oQ==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
eslint: ^8.57.0 || ^9.0.0
typescript: '>=4.8.4 <5.8.0'
'@typescript-eslint/scope-manager@8.24.0':
resolution: {integrity: sha512-HZIX0UByphEtdVBKaQBgTDdn9z16l4aTUz8e8zPQnyxwHBtf5vtl1L+OhH+m1FGV9DrRmoDuYKqzVrvWDcDozw==}
'@typescript-eslint/scope-manager@8.24.1':
resolution: {integrity: sha512-OdQr6BNBzwRjNEXMQyaGyZzgg7wzjYKfX2ZBV3E04hUCBDv3GQCHiz9RpqdUIiVrMgJGkXm3tcEh4vFSHreS2Q==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@typescript-eslint/type-utils@8.24.0':
resolution: {integrity: sha512-8fitJudrnY8aq0F1wMiPM1UUgiXQRJ5i8tFjq9kGfRajU+dbPyOuHbl0qRopLEidy0MwqgTHDt6CnSeXanNIwA==}
'@typescript-eslint/type-utils@8.24.1':
resolution: {integrity: sha512-/Do9fmNgCsQ+K4rCz0STI7lYB4phTtEXqqCAs3gZW0pnK7lWNkvWd5iW545GSmApm4AzmQXmSqXPO565B4WVrw==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
eslint: ^8.57.0 || ^9.0.0
typescript: '>=4.8.4 <5.8.0'
'@typescript-eslint/types@8.24.0':
resolution: {integrity: sha512-VacJCBTyje7HGAw7xp11q439A+zeGG0p0/p2zsZwpnMzjPB5WteaWqt4g2iysgGFafrqvyLWqq6ZPZAOCoefCw==}
'@typescript-eslint/types@8.24.1':
resolution: {integrity: sha512-9kqJ+2DkUXiuhoiYIUvIYjGcwle8pcPpdlfkemGvTObzgmYfJ5d0Qm6jwb4NBXP9W1I5tss0VIAnWFumz3mC5A==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@typescript-eslint/typescript-estree@8.24.0':
resolution: {integrity: sha512-ITjYcP0+8kbsvT9bysygfIfb+hBj6koDsu37JZG7xrCiy3fPJyNmfVtaGsgTUSEuTzcvME5YI5uyL5LD1EV5ZQ==}
'@typescript-eslint/typescript-estree@8.24.1':
resolution: {integrity: sha512-UPyy4MJ/0RE648DSKQe9g0VDSehPINiejjA6ElqnFaFIhI6ZEiZAkUI0D5MCk0bQcTf/LVqZStvQ6K4lPn/BRg==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
typescript: '>=4.8.4 <5.8.0'
'@typescript-eslint/utils@8.24.0':
resolution: {integrity: sha512-07rLuUBElvvEb1ICnafYWr4hk8/U7X9RDCOqd9JcAMtjh/9oRmcfN4yGzbPVirgMR0+HLVHehmu19CWeh7fsmQ==}
'@typescript-eslint/utils@8.24.1':
resolution: {integrity: sha512-OOcg3PMMQx9EXspId5iktsI3eMaXVwlhC8BvNnX6B5w9a4dVgpkQZuU8Hy67TolKcl+iFWq0XX+jbDGN4xWxjQ==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
eslint: ^8.57.0 || ^9.0.0
typescript: '>=4.8.4 <5.8.0'
'@typescript-eslint/visitor-keys@8.24.0':
resolution: {integrity: sha512-kArLq83QxGLbuHrTMoOEWO+l2MwsNS2TGISEdx8xgqpkbytB07XmlQyQdNDrCc1ecSqx0cnmhGvpX+VBwqqSkg==}
'@typescript-eslint/visitor-keys@8.24.1':
resolution: {integrity: sha512-EwVHlp5l+2vp8CoqJm9KikPZgi3gbdZAtabKT9KPShGeOcJhsv4Zdo3oc8T8I0uKEmYoU4ItyxbptjF08enaxg==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
abbrev@3.0.0:
@@ -1206,8 +1210,8 @@ packages:
resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==}
engines: {node: '>=16'}
flatted@3.3.2:
resolution: {integrity: sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA==}
flatted@3.3.3:
resolution: {integrity: sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==}
foreground-child@3.3.0:
resolution: {integrity: sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==}
@@ -1251,8 +1255,8 @@ packages:
resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==}
engines: {node: '>=8'}
hono@4.7.1:
resolution: {integrity: sha512-V3eWoPkBxoNgFCkSc5Y5rpLF6YoQQx1pkYO4qrF6YfOw8RZbujUNlJLZCxh0z9gZct70+je2Ih7Zrdpv21hP9w==}
hono@4.7.2:
resolution: {integrity: sha512-8V5XxoOF6SI12jkHkzX/6aLBMU5GEF5g387EjVSQipS0DlxWgWGSMeEayY3CRBjtTUQYwLHx9JYouWqKzy2Vng==}
engines: {node: '>=16.9.0'}
html-to-text@9.0.5:
@@ -1381,8 +1385,8 @@ packages:
mimetext@3.0.27:
resolution: {integrity: sha512-mUhWAsZD1N/K6dbN4+a5Yq78OPnYQw1ubOSMasBntsLQ2S7KVNlvDEA8dwpr4a7PszWMzeslKahAprtwYMgaBA==}
miniflare@3.20250204.1:
resolution: {integrity: sha512-B4PQi/Ai4d0ZTWahQwsFe5WAfr1j8ISMYxJZTc56g2/btgbX+Go099LmojAZY/fMRLhIYsglcStW8SeW3f/afA==}
miniflare@3.20250214.0:
resolution: {integrity: sha512-XKwn+X/V2CEpbRhoeaIcJHpV/Duz5Md5rxVT8I6S1oqd3aLZkn8cUX1tuxHpUvfQSPuXwWH+2ESLNnTf9PKEWg==}
engines: {node: '>=16.13'}
hasBin: true
@@ -1663,8 +1667,8 @@ packages:
resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==}
engines: {node: '>= 0.8.0'}
typescript-eslint@8.24.0:
resolution: {integrity: sha512-/lmv4366en/qbB32Vz5+kCNZEMf6xYHwh1z48suBwZvAtnXKbP+YhGe8OLE2BqC67LMqKkCNLtjejdwsdW6uOQ==}
typescript-eslint@8.24.1:
resolution: {integrity: sha512-cw3rEdzDqBs70TIcb0Gdzbt6h11BSs2pS0yaq7hDWDBtCCSei1pPSUXE9qUdQ/Wm9NgFg8mKtMt1b8fTHIl1jA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
eslint: ^8.57.0 || ^9.0.0
@@ -1710,17 +1714,17 @@ packages:
worker-mailer@1.0.1:
resolution: {integrity: sha512-y6U9B2cWGGasj7B+6ZtRBsdTPRAZ0P73ykKq5hsIHXReUB8WAq7feS4JoN2xmAZl7yQpVz/GTLqmqLyDmsOUnw==}
workerd@1.20250204.0:
resolution: {integrity: sha512-zcKufjVFsQMiD3/acg1Ix00HIMCkXCrDxQXYRDn/1AIz3QQGkmbVDwcUk1Ki2jBUoXmBCMsJdycRucgMVEypWg==}
workerd@1.20250214.0:
resolution: {integrity: sha512-QWcqXZLiMpV12wiaVnb3nLmfs/g4ZsFQq2mX85z546r3AX4CTIkXl0VP50W3CwqLADej3PGYiRDOTelDOwVG1g==}
engines: {node: '>=16'}
hasBin: true
wrangler@3.109.1:
resolution: {integrity: sha512-1Jx+nZ6eCXPQ2rsGdrV6Qy/LGvhpqudeuTl4AYHl9P8Zugp44Uzxnj5w11qF4v/rv1dOZoA5TydSt9xMFfhpKg==}
wrangler@3.109.2:
resolution: {integrity: sha512-CT8izugPBth5o1o4gLNcQrDkHKSX2Jthy6gkyhaWiy2pFrx+536NMn/atWilLA1t1uhIgddEI5BXDNudIkPPHA==}
engines: {node: '>=16.17.0'}
hasBin: true
peerDependencies:
'@cloudflare/workers-types': ^4.20250204.0
'@cloudflare/workers-types': ^4.20250214.0
peerDependenciesMeta:
'@cloudflare/workers-types':
optional: true
@@ -1804,29 +1808,29 @@ snapshots:
'@smithy/util-utf8': 2.3.0
tslib: 2.8.1
'@aws-sdk/client-s3@3.749.0':
'@aws-sdk/client-s3@3.750.0':
dependencies:
'@aws-crypto/sha1-browser': 5.2.0
'@aws-crypto/sha256-browser': 5.2.0
'@aws-crypto/sha256-js': 5.2.0
'@aws-sdk/core': 3.749.0
'@aws-sdk/credential-provider-node': 3.749.0
'@aws-sdk/core': 3.750.0
'@aws-sdk/credential-provider-node': 3.750.0
'@aws-sdk/middleware-bucket-endpoint': 3.734.0
'@aws-sdk/middleware-expect-continue': 3.734.0
'@aws-sdk/middleware-flexible-checksums': 3.749.0
'@aws-sdk/middleware-flexible-checksums': 3.750.0
'@aws-sdk/middleware-host-header': 3.734.0
'@aws-sdk/middleware-location-constraint': 3.734.0
'@aws-sdk/middleware-logger': 3.734.0
'@aws-sdk/middleware-recursion-detection': 3.734.0
'@aws-sdk/middleware-sdk-s3': 3.749.0
'@aws-sdk/middleware-sdk-s3': 3.750.0
'@aws-sdk/middleware-ssec': 3.734.0
'@aws-sdk/middleware-user-agent': 3.749.0
'@aws-sdk/middleware-user-agent': 3.750.0
'@aws-sdk/region-config-resolver': 3.734.0
'@aws-sdk/signature-v4-multi-region': 3.749.0
'@aws-sdk/signature-v4-multi-region': 3.750.0
'@aws-sdk/types': 3.734.0
'@aws-sdk/util-endpoints': 3.743.0
'@aws-sdk/util-user-agent-browser': 3.734.0
'@aws-sdk/util-user-agent-node': 3.749.0
'@aws-sdk/util-user-agent-node': 3.750.0
'@aws-sdk/xml-builder': 3.734.0
'@smithy/config-resolver': 4.0.1
'@smithy/core': 3.1.4
@@ -1865,20 +1869,20 @@ snapshots:
transitivePeerDependencies:
- aws-crt
'@aws-sdk/client-sso@3.749.0':
'@aws-sdk/client-sso@3.750.0':
dependencies:
'@aws-crypto/sha256-browser': 5.2.0
'@aws-crypto/sha256-js': 5.2.0
'@aws-sdk/core': 3.749.0
'@aws-sdk/core': 3.750.0
'@aws-sdk/middleware-host-header': 3.734.0
'@aws-sdk/middleware-logger': 3.734.0
'@aws-sdk/middleware-recursion-detection': 3.734.0
'@aws-sdk/middleware-user-agent': 3.749.0
'@aws-sdk/middleware-user-agent': 3.750.0
'@aws-sdk/region-config-resolver': 3.734.0
'@aws-sdk/types': 3.734.0
'@aws-sdk/util-endpoints': 3.743.0
'@aws-sdk/util-user-agent-browser': 3.734.0
'@aws-sdk/util-user-agent-node': 3.749.0
'@aws-sdk/util-user-agent-node': 3.750.0
'@smithy/config-resolver': 4.0.1
'@smithy/core': 3.1.4
'@smithy/fetch-http-handler': 5.0.1
@@ -1908,7 +1912,7 @@ snapshots:
transitivePeerDependencies:
- aws-crt
'@aws-sdk/core@3.749.0':
'@aws-sdk/core@3.750.0':
dependencies:
'@aws-sdk/types': 3.734.0
'@smithy/core': 3.1.4
@@ -1922,17 +1926,17 @@ snapshots:
fast-xml-parser: 4.4.1
tslib: 2.8.1
'@aws-sdk/credential-provider-env@3.749.0':
'@aws-sdk/credential-provider-env@3.750.0':
dependencies:
'@aws-sdk/core': 3.749.0
'@aws-sdk/core': 3.750.0
'@aws-sdk/types': 3.734.0
'@smithy/property-provider': 4.0.1
'@smithy/types': 4.1.0
tslib: 2.8.1
'@aws-sdk/credential-provider-http@3.749.0':
'@aws-sdk/credential-provider-http@3.750.0':
dependencies:
'@aws-sdk/core': 3.749.0
'@aws-sdk/core': 3.750.0
'@aws-sdk/types': 3.734.0
'@smithy/fetch-http-handler': 5.0.1
'@smithy/node-http-handler': 4.0.2
@@ -1943,15 +1947,15 @@ snapshots:
'@smithy/util-stream': 4.1.1
tslib: 2.8.1
'@aws-sdk/credential-provider-ini@3.749.0':
'@aws-sdk/credential-provider-ini@3.750.0':
dependencies:
'@aws-sdk/core': 3.749.0
'@aws-sdk/credential-provider-env': 3.749.0
'@aws-sdk/credential-provider-http': 3.749.0
'@aws-sdk/credential-provider-process': 3.749.0
'@aws-sdk/credential-provider-sso': 3.749.0
'@aws-sdk/credential-provider-web-identity': 3.749.0
'@aws-sdk/nested-clients': 3.749.0
'@aws-sdk/core': 3.750.0
'@aws-sdk/credential-provider-env': 3.750.0
'@aws-sdk/credential-provider-http': 3.750.0
'@aws-sdk/credential-provider-process': 3.750.0
'@aws-sdk/credential-provider-sso': 3.750.0
'@aws-sdk/credential-provider-web-identity': 3.750.0
'@aws-sdk/nested-clients': 3.750.0
'@aws-sdk/types': 3.734.0
'@smithy/credential-provider-imds': 4.0.1
'@smithy/property-provider': 4.0.1
@@ -1961,14 +1965,14 @@ snapshots:
transitivePeerDependencies:
- aws-crt
'@aws-sdk/credential-provider-node@3.749.0':
'@aws-sdk/credential-provider-node@3.750.0':
dependencies:
'@aws-sdk/credential-provider-env': 3.749.0
'@aws-sdk/credential-provider-http': 3.749.0
'@aws-sdk/credential-provider-ini': 3.749.0
'@aws-sdk/credential-provider-process': 3.749.0
'@aws-sdk/credential-provider-sso': 3.749.0
'@aws-sdk/credential-provider-web-identity': 3.749.0
'@aws-sdk/credential-provider-env': 3.750.0
'@aws-sdk/credential-provider-http': 3.750.0
'@aws-sdk/credential-provider-ini': 3.750.0
'@aws-sdk/credential-provider-process': 3.750.0
'@aws-sdk/credential-provider-sso': 3.750.0
'@aws-sdk/credential-provider-web-identity': 3.750.0
'@aws-sdk/types': 3.734.0
'@smithy/credential-provider-imds': 4.0.1
'@smithy/property-provider': 4.0.1
@@ -1978,20 +1982,20 @@ snapshots:
transitivePeerDependencies:
- aws-crt
'@aws-sdk/credential-provider-process@3.749.0':
'@aws-sdk/credential-provider-process@3.750.0':
dependencies:
'@aws-sdk/core': 3.749.0
'@aws-sdk/core': 3.750.0
'@aws-sdk/types': 3.734.0
'@smithy/property-provider': 4.0.1
'@smithy/shared-ini-file-loader': 4.0.1
'@smithy/types': 4.1.0
tslib: 2.8.1
'@aws-sdk/credential-provider-sso@3.749.0':
'@aws-sdk/credential-provider-sso@3.750.0':
dependencies:
'@aws-sdk/client-sso': 3.749.0
'@aws-sdk/core': 3.749.0
'@aws-sdk/token-providers': 3.749.0
'@aws-sdk/client-sso': 3.750.0
'@aws-sdk/core': 3.750.0
'@aws-sdk/token-providers': 3.750.0
'@aws-sdk/types': 3.734.0
'@smithy/property-provider': 4.0.1
'@smithy/shared-ini-file-loader': 4.0.1
@@ -2000,10 +2004,10 @@ snapshots:
transitivePeerDependencies:
- aws-crt
'@aws-sdk/credential-provider-web-identity@3.749.0':
'@aws-sdk/credential-provider-web-identity@3.750.0':
dependencies:
'@aws-sdk/core': 3.749.0
'@aws-sdk/nested-clients': 3.749.0
'@aws-sdk/core': 3.750.0
'@aws-sdk/nested-clients': 3.750.0
'@aws-sdk/types': 3.734.0
'@smithy/property-provider': 4.0.1
'@smithy/types': 4.1.0
@@ -2028,12 +2032,12 @@ snapshots:
'@smithy/types': 4.1.0
tslib: 2.8.1
'@aws-sdk/middleware-flexible-checksums@3.749.0':
'@aws-sdk/middleware-flexible-checksums@3.750.0':
dependencies:
'@aws-crypto/crc32': 5.2.0
'@aws-crypto/crc32c': 5.2.0
'@aws-crypto/util': 5.2.0
'@aws-sdk/core': 3.749.0
'@aws-sdk/core': 3.750.0
'@aws-sdk/types': 3.734.0
'@smithy/is-array-buffer': 4.0.0
'@smithy/node-config-provider': 4.0.1
@@ -2070,9 +2074,9 @@ snapshots:
'@smithy/types': 4.1.0
tslib: 2.8.1
'@aws-sdk/middleware-sdk-s3@3.749.0':
'@aws-sdk/middleware-sdk-s3@3.750.0':
dependencies:
'@aws-sdk/core': 3.749.0
'@aws-sdk/core': 3.750.0
'@aws-sdk/types': 3.734.0
'@aws-sdk/util-arn-parser': 3.723.0
'@smithy/core': 3.1.4
@@ -2093,9 +2097,9 @@ snapshots:
'@smithy/types': 4.1.0
tslib: 2.8.1
'@aws-sdk/middleware-user-agent@3.749.0':
'@aws-sdk/middleware-user-agent@3.750.0':
dependencies:
'@aws-sdk/core': 3.749.0
'@aws-sdk/core': 3.750.0
'@aws-sdk/types': 3.734.0
'@aws-sdk/util-endpoints': 3.743.0
'@smithy/core': 3.1.4
@@ -2103,20 +2107,20 @@ snapshots:
'@smithy/types': 4.1.0
tslib: 2.8.1
'@aws-sdk/nested-clients@3.749.0':
'@aws-sdk/nested-clients@3.750.0':
dependencies:
'@aws-crypto/sha256-browser': 5.2.0
'@aws-crypto/sha256-js': 5.2.0
'@aws-sdk/core': 3.749.0
'@aws-sdk/core': 3.750.0
'@aws-sdk/middleware-host-header': 3.734.0
'@aws-sdk/middleware-logger': 3.734.0
'@aws-sdk/middleware-recursion-detection': 3.734.0
'@aws-sdk/middleware-user-agent': 3.749.0
'@aws-sdk/middleware-user-agent': 3.750.0
'@aws-sdk/region-config-resolver': 3.734.0
'@aws-sdk/types': 3.734.0
'@aws-sdk/util-endpoints': 3.743.0
'@aws-sdk/util-user-agent-browser': 3.734.0
'@aws-sdk/util-user-agent-node': 3.749.0
'@aws-sdk/util-user-agent-node': 3.750.0
'@smithy/config-resolver': 4.0.1
'@smithy/core': 3.1.4
'@smithy/fetch-http-handler': 5.0.1
@@ -2155,9 +2159,9 @@ snapshots:
'@smithy/util-middleware': 4.0.1
tslib: 2.8.1
'@aws-sdk/s3-request-presigner@3.749.0':
'@aws-sdk/s3-request-presigner@3.750.0':
dependencies:
'@aws-sdk/signature-v4-multi-region': 3.749.0
'@aws-sdk/signature-v4-multi-region': 3.750.0
'@aws-sdk/types': 3.734.0
'@aws-sdk/util-format-url': 3.734.0
'@smithy/middleware-endpoint': 4.0.5
@@ -2166,18 +2170,18 @@ snapshots:
'@smithy/types': 4.1.0
tslib: 2.8.1
'@aws-sdk/signature-v4-multi-region@3.749.0':
'@aws-sdk/signature-v4-multi-region@3.750.0':
dependencies:
'@aws-sdk/middleware-sdk-s3': 3.749.0
'@aws-sdk/middleware-sdk-s3': 3.750.0
'@aws-sdk/types': 3.734.0
'@smithy/protocol-http': 5.0.1
'@smithy/signature-v4': 5.0.1
'@smithy/types': 4.1.0
tslib: 2.8.1
'@aws-sdk/token-providers@3.749.0':
'@aws-sdk/token-providers@3.750.0':
dependencies:
'@aws-sdk/nested-clients': 3.749.0
'@aws-sdk/nested-clients': 3.750.0
'@aws-sdk/types': 3.734.0
'@smithy/property-provider': 4.0.1
'@smithy/shared-ini-file-loader': 4.0.1
@@ -2220,9 +2224,9 @@ snapshots:
bowser: 2.11.0
tslib: 2.8.1
'@aws-sdk/util-user-agent-node@3.749.0':
'@aws-sdk/util-user-agent-node@3.750.0':
dependencies:
'@aws-sdk/middleware-user-agent': 3.749.0
'@aws-sdk/middleware-user-agent': 3.750.0
'@aws-sdk/types': 3.734.0
'@smithy/node-config-provider': 4.0.1
'@smithy/types': 4.1.0
@@ -2246,19 +2250,19 @@ snapshots:
dependencies:
mime: 3.0.0
'@cloudflare/workerd-darwin-64@1.20250204.0':
'@cloudflare/workerd-darwin-64@1.20250214.0':
optional: true
'@cloudflare/workerd-darwin-arm64@1.20250204.0':
'@cloudflare/workerd-darwin-arm64@1.20250214.0':
optional: true
'@cloudflare/workerd-linux-64@1.20250204.0':
'@cloudflare/workerd-linux-64@1.20250214.0':
optional: true
'@cloudflare/workerd-linux-arm64@1.20250204.0':
'@cloudflare/workerd-linux-arm64@1.20250214.0':
optional: true
'@cloudflare/workerd-windows-64@1.20250204.0':
'@cloudflare/workerd-windows-64@1.20250214.0':
optional: true
'@cloudflare/workers-types@4.20250214.0': {}
@@ -2367,6 +2371,10 @@ snapshots:
dependencies:
'@types/json-schema': 7.0.15
'@eslint/core@0.11.0':
dependencies:
'@types/json-schema': 7.0.15
'@eslint/eslintrc@3.2.0':
dependencies:
ajv: 6.12.6
@@ -2385,9 +2393,9 @@ snapshots:
'@eslint/object-schema@2.1.6': {}
'@eslint/plugin-kit@0.2.5':
'@eslint/plugin-kit@0.2.6':
dependencies:
'@eslint/core': 0.10.0
'@eslint/core': 0.11.0
levn: 0.4.1
'@fastify/busboy@2.1.1': {}
@@ -2918,14 +2926,14 @@ snapshots:
'@types/json-schema@7.0.15': {}
'@typescript-eslint/eslint-plugin@8.24.0(@typescript-eslint/parser@8.24.0(eslint@9.18.0)(typescript@5.4.5))(eslint@9.18.0)(typescript@5.4.5)':
'@typescript-eslint/eslint-plugin@8.24.1(@typescript-eslint/parser@8.24.1(eslint@9.18.0)(typescript@5.4.5))(eslint@9.18.0)(typescript@5.4.5)':
dependencies:
'@eslint-community/regexpp': 4.12.1
'@typescript-eslint/parser': 8.24.0(eslint@9.18.0)(typescript@5.4.5)
'@typescript-eslint/scope-manager': 8.24.0
'@typescript-eslint/type-utils': 8.24.0(eslint@9.18.0)(typescript@5.4.5)
'@typescript-eslint/utils': 8.24.0(eslint@9.18.0)(typescript@5.4.5)
'@typescript-eslint/visitor-keys': 8.24.0
'@typescript-eslint/parser': 8.24.1(eslint@9.18.0)(typescript@5.4.5)
'@typescript-eslint/scope-manager': 8.24.1
'@typescript-eslint/type-utils': 8.24.1(eslint@9.18.0)(typescript@5.4.5)
'@typescript-eslint/utils': 8.24.1(eslint@9.18.0)(typescript@5.4.5)
'@typescript-eslint/visitor-keys': 8.24.1
eslint: 9.18.0
graphemer: 1.4.0
ignore: 5.3.2
@@ -2935,27 +2943,27 @@ snapshots:
transitivePeerDependencies:
- supports-color
'@typescript-eslint/parser@8.24.0(eslint@9.18.0)(typescript@5.4.5)':
'@typescript-eslint/parser@8.24.1(eslint@9.18.0)(typescript@5.4.5)':
dependencies:
'@typescript-eslint/scope-manager': 8.24.0
'@typescript-eslint/types': 8.24.0
'@typescript-eslint/typescript-estree': 8.24.0(typescript@5.4.5)
'@typescript-eslint/visitor-keys': 8.24.0
'@typescript-eslint/scope-manager': 8.24.1
'@typescript-eslint/types': 8.24.1
'@typescript-eslint/typescript-estree': 8.24.1(typescript@5.4.5)
'@typescript-eslint/visitor-keys': 8.24.1
debug: 4.4.0
eslint: 9.18.0
typescript: 5.4.5
transitivePeerDependencies:
- supports-color
'@typescript-eslint/scope-manager@8.24.0':
'@typescript-eslint/scope-manager@8.24.1':
dependencies:
'@typescript-eslint/types': 8.24.0
'@typescript-eslint/visitor-keys': 8.24.0
'@typescript-eslint/types': 8.24.1
'@typescript-eslint/visitor-keys': 8.24.1
'@typescript-eslint/type-utils@8.24.0(eslint@9.18.0)(typescript@5.4.5)':
'@typescript-eslint/type-utils@8.24.1(eslint@9.18.0)(typescript@5.4.5)':
dependencies:
'@typescript-eslint/typescript-estree': 8.24.0(typescript@5.4.5)
'@typescript-eslint/utils': 8.24.0(eslint@9.18.0)(typescript@5.4.5)
'@typescript-eslint/typescript-estree': 8.24.1(typescript@5.4.5)
'@typescript-eslint/utils': 8.24.1(eslint@9.18.0)(typescript@5.4.5)
debug: 4.4.0
eslint: 9.18.0
ts-api-utils: 2.0.1(typescript@5.4.5)
@@ -2963,12 +2971,12 @@ snapshots:
transitivePeerDependencies:
- supports-color
'@typescript-eslint/types@8.24.0': {}
'@typescript-eslint/types@8.24.1': {}
'@typescript-eslint/typescript-estree@8.24.0(typescript@5.4.5)':
'@typescript-eslint/typescript-estree@8.24.1(typescript@5.4.5)':
dependencies:
'@typescript-eslint/types': 8.24.0
'@typescript-eslint/visitor-keys': 8.24.0
'@typescript-eslint/types': 8.24.1
'@typescript-eslint/visitor-keys': 8.24.1
debug: 4.4.0
fast-glob: 3.3.3
is-glob: 4.0.3
@@ -2979,20 +2987,20 @@ snapshots:
transitivePeerDependencies:
- supports-color
'@typescript-eslint/utils@8.24.0(eslint@9.18.0)(typescript@5.4.5)':
'@typescript-eslint/utils@8.24.1(eslint@9.18.0)(typescript@5.4.5)':
dependencies:
'@eslint-community/eslint-utils': 4.4.1(eslint@9.18.0)
'@typescript-eslint/scope-manager': 8.24.0
'@typescript-eslint/types': 8.24.0
'@typescript-eslint/typescript-estree': 8.24.0(typescript@5.4.5)
'@typescript-eslint/scope-manager': 8.24.1
'@typescript-eslint/types': 8.24.1
'@typescript-eslint/typescript-estree': 8.24.1(typescript@5.4.5)
eslint: 9.18.0
typescript: 5.4.5
transitivePeerDependencies:
- supports-color
'@typescript-eslint/visitor-keys@8.24.0':
'@typescript-eslint/visitor-keys@8.24.1':
dependencies:
'@typescript-eslint/types': 8.24.0
'@typescript-eslint/types': 8.24.1
eslint-visitor-keys: 4.2.0
abbrev@3.0.0: {}
@@ -3210,7 +3218,7 @@ snapshots:
'@eslint/core': 0.10.0
'@eslint/eslintrc': 3.2.0
'@eslint/js': 9.18.0
'@eslint/plugin-kit': 0.2.5
'@eslint/plugin-kit': 0.2.6
'@humanfs/node': 0.16.6
'@humanwhocodes/module-importer': 1.0.1
'@humanwhocodes/retry': 0.4.1
@@ -3304,10 +3312,10 @@ snapshots:
flat-cache@4.0.1:
dependencies:
flatted: 3.3.2
flatted: 3.3.3
keyv: 4.5.4
flatted@3.3.2: {}
flatted@3.3.3: {}
foreground-child@3.3.0:
dependencies:
@@ -3349,7 +3357,7 @@ snapshots:
has-flag@4.0.0: {}
hono@4.7.1: {}
hono@4.7.2: {}
html-to-text@9.0.5:
dependencies:
@@ -3471,7 +3479,7 @@ snapshots:
js-base64: 3.7.7
mime-types: 2.1.35
miniflare@3.20250204.1:
miniflare@3.20250214.0:
dependencies:
'@cspotcode/source-map-support': 0.8.1
acorn: 8.14.0
@@ -3480,7 +3488,7 @@ snapshots:
glob-to-regexp: 0.4.1
stoppable: 1.1.0
undici: 5.28.5
workerd: 1.20250204.0
workerd: 1.20250214.0
ws: 8.18.0
youch: 3.2.3
zod: 3.22.3
@@ -3770,11 +3778,11 @@ snapshots:
dependencies:
prelude-ls: 1.2.1
typescript-eslint@8.24.0(eslint@9.18.0)(typescript@5.4.5):
typescript-eslint@8.24.1(eslint@9.18.0)(typescript@5.4.5):
dependencies:
'@typescript-eslint/eslint-plugin': 8.24.0(@typescript-eslint/parser@8.24.0(eslint@9.18.0)(typescript@5.4.5))(eslint@9.18.0)(typescript@5.4.5)
'@typescript-eslint/parser': 8.24.0(eslint@9.18.0)(typescript@5.4.5)
'@typescript-eslint/utils': 8.24.0(eslint@9.18.0)(typescript@5.4.5)
'@typescript-eslint/eslint-plugin': 8.24.1(@typescript-eslint/parser@8.24.1(eslint@9.18.0)(typescript@5.4.5))(eslint@9.18.0)(typescript@5.4.5)
'@typescript-eslint/parser': 8.24.1(eslint@9.18.0)(typescript@5.4.5)
'@typescript-eslint/utils': 8.24.1(eslint@9.18.0)(typescript@5.4.5)
eslint: 9.18.0
typescript: 5.4.5
transitivePeerDependencies:
@@ -3817,25 +3825,25 @@ snapshots:
worker-mailer@1.0.1: {}
workerd@1.20250204.0:
workerd@1.20250214.0:
optionalDependencies:
'@cloudflare/workerd-darwin-64': 1.20250204.0
'@cloudflare/workerd-darwin-arm64': 1.20250204.0
'@cloudflare/workerd-linux-64': 1.20250204.0
'@cloudflare/workerd-linux-arm64': 1.20250204.0
'@cloudflare/workerd-windows-64': 1.20250204.0
'@cloudflare/workerd-darwin-64': 1.20250214.0
'@cloudflare/workerd-darwin-arm64': 1.20250214.0
'@cloudflare/workerd-linux-64': 1.20250214.0
'@cloudflare/workerd-linux-arm64': 1.20250214.0
'@cloudflare/workerd-windows-64': 1.20250214.0
wrangler@3.109.1(@cloudflare/workers-types@4.20250214.0):
wrangler@3.109.2(@cloudflare/workers-types@4.20250214.0):
dependencies:
'@cloudflare/kv-asset-handler': 0.3.4
'@esbuild-plugins/node-globals-polyfill': 0.2.3(esbuild@0.17.19)
'@esbuild-plugins/node-modules-polyfill': 0.2.2(esbuild@0.17.19)
blake3-wasm: 2.1.5
esbuild: 0.17.19
miniflare: 3.20250204.1
miniflare: 3.20250214.0
path-to-regexp: 6.3.0
unenv: 2.0.0-rc.1
workerd: 1.20250204.0
workerd: 1.20250214.0
optionalDependencies:
'@cloudflare/workers-types': 4.20250214.0
fsevents: 2.3.3

View File

@@ -1,6 +1,7 @@
import { Hono } from 'hono'
import { Jwt } from 'hono/utils/jwt'
import i18n from '../i18n'
import { HonoCustomType } from '../types'
import { sendAdminInternalMail, getJsonSetting, saveSetting, getUserRoles } from '../utils'
import { newAddress, handleListQuery } from '../common'
@@ -40,6 +41,8 @@ api.get('/admin/address', async (c) => {
api.post('/admin/new_address', async (c) => {
const { name, domain, enablePrefix } = await c.req.json();
const lang = c.get("lang") || c.env.DEFAULT_LANG;
const msgs = i18n.getMessages(lang);
if (!name) {
return c.text("Please provide a name", 400)
}
@@ -53,7 +56,7 @@ api.post('/admin/new_address', async (c) => {
});
return c.json(res);
} catch (e) {
return c.text(`Failed create address: ${(e as Error).message}`, 400)
return c.text(`${msgs.FailedCreateAddressMsg}: ${(e as Error).message}`, 400)
}
})

View File

@@ -1,5 +1,5 @@
export const CONSTANTS = {
VERSION: 'v0.8.7',
VERSION: 'v' + '0.9.0',
// DB settings
ADDRESS_BLOCK_LIST_KEY: 'address_block_list',

24
worker/src/i18n/en.ts Normal file
View File

@@ -0,0 +1,24 @@
import { LocaleMessages } from "./type";
const messages: LocaleMessages = {
CustomAuthPasswordMsg: "You have enabled the private site password, please provide the password",
UserTokenExpiredMsg: "Your token has expired, please login again",
UserAcceesTokenExpiredMsg: "Your access token has expired, please refresh the page",
UserRoleIsNotAdminMsg: "Your user role is not admin, no access to visit this page",
NeedAdminPasswordMsg: "You need to provide the admin password to access this page",
KVNotAvailableMsg: "KV is not available, please contact the administrator",
DBNotAvailableMsg: "DB is not available, please contact the administrator",
JWTSecretNotSetMsg: "JWT_SECRET is not set, please contact the administrator",
WebhookNotEnabledMsg: "Webhook is not enabled, please contact the administrator",
DomainsNotSetMsg: "Domains are not set, please contact the administrator",
TurnstileCheckFailedMsg: "Human verification check failed",
NewAddressDisabledMsg: "New address is disabled, please contact the administrator",
NewAddressAnonymousDisabledMsg: "New address for anonymous user is disabled, please contact the administrator",
FailedCreateAddressMsg: "Failed to create address",
InvalidAddressMsg: "Invalid address",
UserDeleteEmailDisabledMsg: "User delete address/email is disabled, please contact the administrator",
}
export default messages;

16
worker/src/i18n/index.ts Normal file
View File

@@ -0,0 +1,16 @@
import { LocaleMessages } from "./type";
import zh from "./zh";
import en from "./en";
export default {
getMessages: (
locale: string | null | undefined
): LocaleMessages => {
// multi-language support
if (locale === "en") return en;
if (locale === "zh") return zh;
// fallback language
return en;
}
}

20
worker/src/i18n/type.ts Normal file
View File

@@ -0,0 +1,20 @@
export type LocaleMessages = {
CustomAuthPasswordMsg: string
UserTokenExpiredMsg: string
UserAcceesTokenExpiredMsg: string
UserRoleIsNotAdminMsg: string
NeedAdminPasswordMsg: string
KVNotAvailableMsg: string
DBNotAvailableMsg: string
JWTSecretNotSetMsg: string
WebhookNotEnabledMsg: string
DomainsNotSetMsg: string
TurnstileCheckFailedMsg: string
NewAddressDisabledMsg: string
NewAddressAnonymousDisabledMsg: string
FailedCreateAddressMsg: string
InvalidAddressMsg: string
UserDeleteEmailDisabledMsg: string
}

24
worker/src/i18n/zh.ts Normal file
View File

@@ -0,0 +1,24 @@
import { LocaleMessages } from "./type";
const messages: LocaleMessages = {
CustomAuthPasswordMsg: "你已启用私有站点密码,请提供密码",
UserTokenExpiredMsg: "您的令牌已过期, 请重新登录",
UserAcceesTokenExpiredMsg: "您的访问令牌已过期, 请刷新页面",
UserRoleIsNotAdminMsg: "您的用户角色不是管理员, 无权访问",
NeedAdminPasswordMsg: "您需要提供管理员密码才能访问此页面",
KVNotAvailableMsg: "KV 不可用, 请联系管理员",
DBNotAvailableMsg: "DB 不可用, 请联系管理员",
JWTSecretNotSetMsg: "JWT_SECRET 未设置, 请联系管理员",
WebhookNotEnabledMsg: "Webhook 未启用, 请联系管理员",
DomainsNotSetMsg: "域名列表未设置, 请联系管理员",
TurnstileCheckFailedMsg: "人机验证检查失败",
NewAddressDisabledMsg: "新建邮箱地址已禁用, 请联系管理员",
NewAddressAnonymousDisabledMsg: "匿名用户新建邮箱地址已禁用, 请联系管理员",
FailedCreateAddressMsg: "创建邮箱地址失败",
InvalidAddressMsg: "无效的邮箱地址",
UserDeleteEmailDisabledMsg: "用户删除邮箱/邮件已禁用, 请联系管理员",
}
export default messages;

View File

@@ -1,5 +1,6 @@
import { Hono } from 'hono'
import i18n from '../i18n';
import { HonoCustomType } from "../types";
import { getBooleanValue, getJsonSetting, checkCfTurnstile, getStringValue } from '../utils';
import { newAddress, handleListQuery, deleteAddressWithData, getAddressPrefix, getAllowDomains } from '../common'
@@ -42,8 +43,10 @@ api.get('/api/mail/:mail_id', async (c) => {
})
api.delete('/api/mails/:id', async (c) => {
const lang = c.get("lang") || c.env.DEFAULT_LANG;
const msgs = i18n.getMessages(lang);
if (!getBooleanValue(c.env.ENABLE_USER_DELETE_EMAIL)) {
return c.text("User delete email is disabled", 403)
return c.text(msgs.UserDeleteEmailDisabledMsg, 403)
}
const { address } = c.get("jwtPayload")
const { id } = c.req.param();
@@ -59,16 +62,18 @@ api.delete('/api/mails/:id', async (c) => {
api.get('/api/settings', async (c) => {
const { address, address_id } = c.get("jwtPayload")
const user_role = c.get("userRolePayload")
const lang = c.get("lang") || c.env.DEFAULT_LANG;
const msgs = i18n.getMessages(lang);
if (address_id && address_id > 0) {
try {
const db_address_id = await c.env.DB.prepare(
`SELECT id FROM address where id = ? `
).bind(address_id).first("id");
if (!db_address_id) {
return c.text("Invalid address", 400)
return c.text(msgs.InvalidAddressMsg, 400)
}
} catch (error) {
return c.text("Invalid address", 400)
return c.text(msgs.InvalidAddressMsg, 400)
}
}
// check address id
@@ -78,11 +83,11 @@ api.get('/api/settings', async (c) => {
`SELECT id FROM address where name = ? `
).bind(address).first("id");
if (!db_address_id) {
return c.text("Invalid address", 400)
return c.text(msgs.InvalidAddressMsg, 400)
}
}
} catch (error) {
return c.text("Invalid address", 400)
return c.text(msgs.InvalidAddressMsg, 400)
}
// update address updated_at
try {
@@ -103,13 +108,15 @@ api.get('/api/settings', async (c) => {
})
api.post('/api/new_address', async (c) => {
const lang = c.get("lang") || c.env.DEFAULT_LANG;
const msgs = i18n.getMessages(lang);
if (getBooleanValue(c.env.DISABLE_ANONYMOUS_USER_CREATE_EMAIL)
&& !c.get("userPayload")
) {
return c.text("New address for anonymous user is disabled", 403)
return c.text(msgs.NewAddressAnonymousDisabledMsg, 403)
}
if (!getBooleanValue(c.env.ENABLE_USER_CREATE_EMAIL)) {
return c.text("New address is disabled", 403)
return c.text(msgs.NewAddressDisabledMsg, 403)
}
// eslint-disable-next-line prefer-const
let { name, domain, cf_token } = await c.req.json();
@@ -117,7 +124,7 @@ api.post('/api/new_address', async (c) => {
try {
await checkCfTurnstile(c, cf_token);
} catch (error) {
return c.text("Failed to check cf turnstile", 500)
return c.text(msgs.TurnstileCheckFailedMsg, 500)
}
// if no name, generate random name
if (!name) {
@@ -143,7 +150,7 @@ api.post('/api/new_address', async (c) => {
});
return c.json(res);
} catch (e) {
return c.text(`Failed create address: ${(e as Error).message}`, 400)
return c.text(`${msgs.FailedCreateAddressMsg}: ${(e as Error).message}`, 400)
}
})

View File

@@ -4,6 +4,7 @@ import { createMimeMessage } from 'mimetext';
import { Resend } from 'resend';
import { WorkerMailer, WorkerMailerOptions } from 'worker-mailer';
import i18n from '../i18n';
import { CONSTANTS } from '../constants'
import { getJsonSetting, getDomains, getIntValue, getBooleanValue, getStringValue, getJsonObjectValue } from '../utils';
import { GeoData } from '../models'
@@ -288,8 +289,10 @@ api.get('/api/sendbox', async (c) => {
})
api.delete('/api/sendbox/:id', async (c) => {
const lang = c.get("lang") || c.env.DEFAULT_LANG;
const msgs = i18n.getMessages(lang);
if (!getBooleanValue(c.env.ENABLE_USER_DELETE_EMAIL)) {
return c.text("User delete email is disabled", 403)
return c.text(msgs.UserDeleteEmailDisabledMsg, 403)
}
const { address } = c.get("jwtPayload")
const { id } = c.req.param();

View File

@@ -5,6 +5,7 @@ import { CONSTANTS } from "../constants";
import { bindTelegramAddress, jwtListToAddressData, tgUserNewAddress, unbindTelegramAddress } from "./common";
import { checkCfTurnstile } from "../utils";
import { TelegramSettings } from "./settings";
import i18n from "../i18n";
const encoder = new TextEncoder();
const TG_AUTH_TIMEOUT = 300;
@@ -84,11 +85,13 @@ async function getTelegramBindAddress(c: Context<HonoCustomType>): Promise<Respo
async function newTelegramAddress(c: Context<HonoCustomType>): Promise<Response> {
const { initData, address, cf_token } = await c.req.json();
const lang = c.get("lang") || c.env.DEFAULT_LANG;
const msgs = i18n.getMessages(lang);
// check cf turnstile
try {
await checkCfTurnstile(c, cf_token);
} catch (error) {
return c.text("Failed to check cf turnstile", 500)
return c.text(msgs.TurnstileCheckFailedMsg, 500)
}
try {
const userId = await checkTelegramAuth(c, initData);

View File

@@ -12,6 +12,7 @@ export type Bindings = {
SEND_MAIL: any
// config
DEFAULT_LANG: string | undefined
TITLE: string | undefined
ANNOUNCEMENT: string | undefined | null
PREFIX: string | undefined
@@ -96,6 +97,7 @@ type Variables = {
userPayload: UserPayload,
userRolePayload: string | undefined | null,
jwtPayload: JwtPayload,
lang: string | undefined | null
}
type HonoCustomType = {

View File

@@ -1,6 +1,7 @@
import { Context } from 'hono';
import { Jwt } from 'hono/utils/jwt'
import i18n from '../i18n';
import { HonoCustomType } from '../types';
import { checkCfTurnstile, getJsonSetting, checkUserPassword, getUserRoles, getStringValue } from "../utils"
import { CONSTANTS } from "../constants";
@@ -10,11 +11,13 @@ import { sendMail } from "../mails_api/send_mail_api";
export default {
verifyCode: async (c: Context<HonoCustomType>) => {
const { email, cf_token } = await c.req.json();
const lang = c.get("lang") || c.env.DEFAULT_LANG;
const msgs = i18n.getMessages(lang);
// check cf turnstile
try {
await checkCfTurnstile(c, cf_token);
} catch (error) {
return c.text("Failed to check cf turnstile", 500)
return c.text(msgs.TurnstileCheckFailedMsg, 500)
}
const value = await getJsonSetting(c, CONSTANTS.USER_SETTINGS_KEY);
const settings = new UserSettings(value)

View File

@@ -10,6 +10,7 @@ import { api as adminApi } from './admin_api';
import { api as apiSendMail } from './mails_api/send_mail_api'
import { api as telegramApi } from './telegram_api'
import i18n from './i18n';
import { email } from './email';
import { scheduled } from './scheduled';
import { getAdminPasswords, getPasswords, getBooleanValue, getStringArray } from './utils';
@@ -25,6 +26,10 @@ app.onError((err, c) => {
})
// rate limit
app.use('/*', async (c, next) => {
// save language in context
const lang = c.req.raw.headers.get("x-lang");
if (lang) { c.set("lang", lang); }
const msgs = i18n.getMessages(lang || c.env.DEFAULT_LANG);
if (
c.req.path.startsWith("/api/new_address")
|| c.req.path.startsWith("/api/send_mail")
@@ -49,17 +54,17 @@ app.use('/*', async (c, next) => {
|| c.req.path.startsWith("/admin/mail_webhook")
) {
if (!c.env.KV) {
return c.text("KV is not available", 400);
return c.text(msgs.KVNotAvailableMsg, 400);
}
if (!getBooleanValue(c.env.ENABLE_WEBHOOK)) {
return c.text("Webhook is disabled", 403);
return c.text(msgs.WebhookNotEnabledMsg, 403);
}
}
if (!c.env.DB) {
return c.text("DB is not available", 400);
return c.text(msgs.DBNotAvailableMsg, 400);
}
if (!c.env.JWT_SECRET) {
return c.text("JWT_SECRET is not set", 400);
return c.text(msgs.JWTSecretNotSetMsg, 400);
}
await next()
});
@@ -110,7 +115,9 @@ app.use('/api/*', async (c, next) => {
if (passwords && passwords.length > 0) {
const auth = c.req.raw.headers.get("x-custom-auth");
if (!auth || !passwords.includes(auth)) {
return c.text("Need Password", 401)
const lang = c.req.raw.headers.get("x-lang") || c.env.DEFAULT_LANG;
const messages = i18n.getMessages(lang);
return c.text(messages.CustomAuthPasswordMsg, 401)
}
}
if (c.req.path.startsWith("/api/new_address")) {
@@ -138,20 +145,24 @@ app.use('/user_api/*', async (c, next) => {
await next();
return;
}
const lang = c.req.raw.headers.get("x-lang") || c.env.DEFAULT_LANG;
const msgs = i18n.getMessages(lang);
try {
const token = c.req.raw.headers.get("x-user-token");
if (!token) return c.text("Need User Token", 401)
if (!token) return c.text(msgs.UserTokenExpiredMsg, 401)
const payload = await Jwt.verify(token, c.env.JWT_SECRET, "HS256");
// check expired
if (!payload.exp) return c.text("Invalid Token", 401);
if (!payload.exp) return c.text(msgs.UserTokenExpiredMsg, 401);
// exp is in seconds
if (payload.exp < Math.floor(Date.now() / 1000)) {
return c.text("Token Expired", 401)
return c.text(msgs.UserTokenExpiredMsg, 401)
}
c.set("userPayload", payload as UserPayload);
} catch (e) {
console.error(e);
return c.text("Need User Token", 401)
return c.text(msgs.UserTokenExpiredMsg, 401)
}
if (c.req.path.startsWith('/user_api/bind_address')
&& c.req.method === 'POST'
@@ -172,19 +183,21 @@ app.use('/admin/*', async (c, next) => {
return;
}
}
const lang = c.req.raw.headers.get("x-lang") || c.env.DEFAULT_LANG;
const msgs = i18n.getMessages(lang);
// check if user is admin
const access_token = c.req.raw.headers.get("x-user-access-token");
if (c.env.ADMIN_USER_ROLE && access_token) {
try {
const payload = await Jwt.verify(access_token, c.env.JWT_SECRET, "HS256");
// check expired
if (!payload.exp) return c.text("Invalid Token", 401);
if (!payload.exp) return c.text(msgs.UserAcceesTokenExpiredMsg, 401);
// exp is in seconds
if (payload.exp < Math.floor(Date.now() / 1000)) {
return c.text("Token Expired", 401)
return c.text(msgs.UserAcceesTokenExpiredMsg, 401)
}
if (payload.user_role !== c.env.ADMIN_USER_ROLE) {
return c.text("Need Admin Role", 401)
return c.text(msgs.UserRoleIsNotAdminMsg, 401)
}
await next();
return;
@@ -199,7 +212,7 @@ app.use('/admin/*', async (c, next) => {
return;
}
return c.text("Need Admin Password", 401)
return c.text(msgs.NeedAdminPasswordMsg, 401)
});
@@ -211,14 +224,16 @@ app.route('/', apiSendMail)
app.route('/', telegramApi)
const health_check = async (c: Context<HonoCustomType>) => {
const lang = c.req.raw.headers.get("x-lang") || c.env.DEFAULT_LANG;
const msgs = i18n.getMessages(lang);
if (!c.env.DB) {
return c.text("DB is not available", 400);
return c.text(msgs.DBNotAvailableMsg, 400);
}
if (!c.env.JWT_SECRET) {
return c.text("JWT_SECRET is not set", 400);
return c.text(msgs.JWTSecretNotSetMsg, 400);
}
if (getStringArray(c.env.DOMAINS).length === 0) {
return c.text("DOMAINS is not set", 400);
return c.text(msgs.DomainsNotSetMsg, 400);
}
return c.text("OK");
}