feature: add /user_api/mails with filter params address and keyword (#639)

This commit is contained in:
Dream Hunter
2025-04-24 02:01:21 +08:00
committed by GitHub
parent c6afc5d425
commit 95f361743b
19 changed files with 1124 additions and 887 deletions
+5 -1
View File
@@ -1,7 +1,11 @@
<!-- markdownlint-disable-file MD004 MD024 MD034 MD036 --> <!-- markdownlint-disable-file MD004 MD024 MD034 MD036 -->
# CHANGE LOG # CHANGE LOG
## main(v0.9.1) ## v0.10.0
- feat: 支持 User 查看收件箱,`/user_api/mails` 接口, 支持 `address``keyword` 过滤
## v0.9.1
- feat: |UI| support google ads - feat: |UI| support google ads
- feat: |UI| 使用 shadow DOM 防止样式污染 - feat: |UI| 使用 shadow DOM 防止样式污染
+4 -4
View File
@@ -1,6 +1,6 @@
{ {
"name": "cloudflare_temp_email", "name": "cloudflare_temp_email",
"version": "0.9.1", "version": "0.10.9",
"private": true, "private": true,
"type": "module", "type": "module",
"scripts": { "scripts": {
@@ -40,13 +40,13 @@
"@vicons/material": "^0.13.0", "@vicons/material": "^0.13.0",
"@vitejs/plugin-vue": "^5.2.3", "@vitejs/plugin-vue": "^5.2.3",
"unplugin-auto-import": "^19.1.2", "unplugin-auto-import": "^19.1.2",
"unplugin-vue-components": "^28.4.1", "unplugin-vue-components": "^28.5.0",
"vite": "^6.2.6", "vite": "^6.3.2",
"vite-plugin-pwa": "^1.0.0", "vite-plugin-pwa": "^1.0.0",
"vite-plugin-top-level-await": "^1.5.0", "vite-plugin-top-level-await": "^1.5.0",
"vite-plugin-wasm": "^3.4.1", "vite-plugin-wasm": "^3.4.1",
"workbox-build": "^7.3.0", "workbox-build": "^7.3.0",
"workbox-window": "^7.3.0", "workbox-window": "^7.3.0",
"wrangler": "^4.10.0" "wrangler": "^4.13.0"
} }
} }
+284 -281
View File
File diff suppressed because it is too large Load Diff
+6
View File
@@ -7,6 +7,7 @@ import AddressMangement from './user/AddressManagement.vue';
import UserSettingsPage from './user/UserSettings.vue'; import UserSettingsPage from './user/UserSettings.vue';
import UserBar from './user/UserBar.vue'; import UserBar from './user/UserBar.vue';
import BindAddress from './user/BindAddress.vue'; import BindAddress from './user/BindAddress.vue';
import UserMailBox from './user/UserMailBox.vue';
const { const {
userTab, globalTabplacement, userSettings userTab, globalTabplacement, userSettings
@@ -16,11 +17,13 @@ const { t } = useI18n({
messages: { messages: {
en: { en: {
address_management: 'Address Management', address_management: 'Address Management',
user_mail_box_tab: 'Mail Box',
user_settings: 'User Settings', user_settings: 'User Settings',
bind_address: 'Bind Mail Address', bind_address: 'Bind Mail Address',
}, },
zh: { zh: {
address_management: '地址管理', address_management: '地址管理',
user_mail_box_tab: '收件箱',
user_settings: '用户设置', user_settings: '用户设置',
bind_address: '绑定邮箱地址', bind_address: '绑定邮箱地址',
} }
@@ -36,6 +39,9 @@ const { t } = useI18n({
<n-tab-pane name="address_management" :tab="t('address_management')"> <n-tab-pane name="address_management" :tab="t('address_management')">
<AddressMangement /> <AddressMangement />
</n-tab-pane> </n-tab-pane>
<n-tab-pane name="user_mail_box_tab" :tab="t('user_mail_box_tab')">
<UserMailBox />
</n-tab-pane>
<n-tab-pane name="user_settings" :tab="t('user_settings')"> <n-tab-pane name="user_settings" :tab="t('user_settings')">
<UserSettingsPage /> <UserSettingsPage />
</n-tab-pane> </n-tab-pane>
+90
View File
@@ -0,0 +1,90 @@
<script setup>
import { onMounted, ref, watch } from 'vue';
import { useI18n } from 'vue-i18n'
import { api } from '../../api'
import MailBox from '../../components/MailBox.vue';
const { t } = useI18n({
messages: {
en: {
addressQueryTip: 'Leave blank to query all addresses',
keywordQueryTip: 'Leave blank to not query by keyword',
query: 'Query',
},
zh: {
addressQueryTip: '留空查询所有地址',
keywordQueryTip: '留空不按关键字查询',
query: '查询',
}
}
});
const mailBoxKey = ref("")
const addressFilter = ref();
const mailKeyword = ref("")
const addressFilterOptions = ref([]);
const queryMail = () => {
addressFilter.value = addressFilter.value.trim();
mailKeyword.value = mailKeyword.value.trim();
mailBoxKey.value = Date.now();
}
const fetchMailData = async (limit, offset) => {
return await api.fetch(
`/user_api/mails`
+ `?limit=${limit}`
+ `&offset=${offset}`
+ (addressFilter.value ? `&address=${addressFilter.value}` : '')
+ (mailKeyword.value ? `&keyword=${mailKeyword.value}` : '')
);
}
const fetchAddresData = async () => {
try {
const { results } = await api.fetch(
`/user_api/bind_address`
);
addressFilterOptions.value = results.map((item) => {
return {
label: item.name,
value: item.name
}
});
} catch (error) {
console.log(error)
message.error(error.message || "error");
}
}
const deleteMail = async (curMailId) => {
await api.fetch(`/user_api/mails/${curMailId}`, { method: 'DELETE' });
};
watch(addressFilter, async (newValue) => {
console.log("addressFilter", newValue);
queryMail();
});
onMounted(() => {
fetchAddresData();
});
</script>
<template>
<div style="margin-top: 10px;">
<n-input-group>
<n-select v-model:value="addressFilter" :options="addressFilterOptions" clearable
:placeholder="t('addressQueryTip')" />
<n-input v-model:value="mailKeyword" :placeholder="t('keywordQueryTip')" @keydown.enter="queryMail" />
<n-button @click="queryMail" type="primary" tertiary>
{{ t('query') }}
</n-button>
</n-input-group>
<div style="margin-top: 10px;"></div>
<MailBox :key="mailBoxKey" :enableUserDeleteEmail="true" :fetchMailData="fetchMailData"
:deleteMail="deleteMail" />
</div>
</template>
+2 -2
View File
@@ -1,6 +1,6 @@
{ {
"name": "temp-email-pages", "name": "temp-email-pages",
"version": "0.9.1", "version": "0.10.9",
"description": "", "description": "",
"main": "index.js", "main": "index.js",
"scripts": { "scripts": {
@@ -11,6 +11,6 @@
"author": "", "author": "",
"license": "ISC", "license": "ISC",
"devDependencies": { "devDependencies": {
"wrangler": "^4.10.0" "wrangler": "^4.13.0"
} }
} }
@@ -1,6 +1,6 @@
# 查看邮件 API # 查看邮件 API
## 通过 HTTP API 查看邮件 ## 通过 邮件 API 查看邮件
这是一个 `python` 的例子,使用 `requests` 库查看邮件。 这是一个 `python` 的例子,使用 `requests` 库查看邮件。
@@ -8,7 +8,7 @@
limit = 10 limit = 10
offset = 0 offset = 0
res = requests.get( res = requests.get(
f"http://localhost:8787/api/mails?limit={limit}&offset={offset}", f"https://<你的worker地址>/api/mails?limit={limit}&offset={offset}",
headers={ headers={
"Authorization": f"Bearer {你的JWT密码}", "Authorization": f"Bearer {你的JWT密码}",
# "x-custom-auth": "<你的网站密码>", # 如果启用了自定义密码 # "x-custom-auth": "<你的网站密码>", # 如果启用了自定义密码
@@ -16,3 +16,51 @@ res = requests.get(
} }
) )
``` ```
## admin 邮件 API
支持 `address` filter 和 `keyword` filter
```python
import requests
url = "https://<你的worker地址>/admin/mails"
querystring = {
"limit":"20",
"offset":"0",
# adress 和 keyword 为可选参数
"address":"xxxx@awsl.uk",
"keyword":"xxxx"
}
headers = {"x-admin-auth": "<你的Admin密码>"}
response = requests.get(url, headers=headers, params=querystring)
print(response.json())
```
## user 邮件 API
支持 `address` filter 和 `keyword` filter
```python
import requests
url = "https://<你的worker地址>/user_api/mails"
querystring = {
"limit":"20",
"offset":"0",
# adress 和 keyword 为可选参数
"address":"xxxx@awsl.uk",
"keyword":"xxxx"
}
headers = {"x-admin-auth": "<你的Admin密码>"}
response = requests.get(url, headers=headers, params=querystring)
print(response.json())
```
+2 -2
View File
@@ -1,12 +1,12 @@
{ {
"name": "temp-mail-docs", "name": "temp-mail-docs",
"private": true, "private": true,
"version": "0.9.1", "version": "0.10.9",
"type": "module", "type": "module",
"devDependencies": { "devDependencies": {
"@types/node": "^22.14.1", "@types/node": "^22.14.1",
"vitepress": "^1.6.3", "vitepress": "^1.6.3",
"wrangler": "^4.10.0" "wrangler": "^4.13.0"
}, },
"scripts": { "scripts": {
"dev": "vitepress dev docs", "dev": "vitepress dev docs",
+289 -289
View File
File diff suppressed because it is too large Load Diff
+7 -7
View File
@@ -1,6 +1,6 @@
{ {
"name": "cloudflare_temp_email", "name": "cloudflare_temp_email",
"version": "0.9.1", "version": "0.10.9",
"private": true, "private": true,
"type": "module", "type": "module",
"scripts": { "scripts": {
@@ -11,25 +11,25 @@
"build": "wrangler deploy --dry-run --outdir dist --minify" "build": "wrangler deploy --dry-run --outdir dist --minify"
}, },
"devDependencies": { "devDependencies": {
"@cloudflare/workers-types": "^4.20250412.0", "@cloudflare/workers-types": "^4.20250423.0",
"@eslint/js": "9.18.0", "@eslint/js": "9.18.0",
"@simplewebauthn/types": "10.0.0", "@simplewebauthn/types": "10.0.0",
"eslint": "9.18.0", "eslint": "9.18.0",
"globals": "^15.15.0", "globals": "^15.15.0",
"typescript-eslint": "^8.29.1", "typescript-eslint": "^8.31.0",
"wrangler": "^4.10.0" "wrangler": "^4.13.0"
}, },
"dependencies": { "dependencies": {
"@aws-sdk/client-s3": "^3.787.0", "@aws-sdk/client-s3": "^3.787.0",
"@aws-sdk/s3-request-presigner": "^3.787.0", "@aws-sdk/s3-request-presigner": "^3.787.0",
"@simplewebauthn/server": "10.0.1", "@simplewebauthn/server": "10.0.1",
"hono": "^4.7.6", "hono": "^4.7.7",
"jsonpath-plus": "^10.3.0", "jsonpath-plus": "^10.3.0",
"mimetext": "^3.0.27", "mimetext": "^3.0.27",
"postal-mime": "^2.4.3", "postal-mime": "^2.4.3",
"resend": "^4.2.0", "resend": "^4.4.0",
"telegraf": "4.16.3", "telegraf": "4.16.3",
"worker-mailer": "^1.1.1" "worker-mailer": "^1.1.3"
}, },
"pnpm": { "pnpm": {
"patchedDependencies": { "patchedDependencies": {
+239 -239
View File
@@ -23,8 +23,8 @@ importers:
specifier: 10.0.1 specifier: 10.0.1
version: 10.0.1 version: 10.0.1
hono: hono:
specifier: ^4.7.6 specifier: ^4.7.7
version: 4.7.6 version: 4.7.7
jsonpath-plus: jsonpath-plus:
specifier: ^10.3.0 specifier: ^10.3.0
version: 10.3.0 version: 10.3.0
@@ -35,18 +35,18 @@ importers:
specifier: ^2.4.3 specifier: ^2.4.3
version: 2.4.3 version: 2.4.3
resend: resend:
specifier: ^4.2.0 specifier: ^4.4.0
version: 4.2.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) version: 4.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
telegraf: telegraf:
specifier: 4.16.3 specifier: 4.16.3
version: 4.16.3(patch_hash=7d0a1784bb35f50fee25f26a14017734b9461612c635e71734b59527280c9563) version: 4.16.3(patch_hash=7d0a1784bb35f50fee25f26a14017734b9461612c635e71734b59527280c9563)
worker-mailer: worker-mailer:
specifier: ^1.1.1 specifier: ^1.1.3
version: 1.1.1 version: 1.1.3
devDependencies: devDependencies:
'@cloudflare/workers-types': '@cloudflare/workers-types':
specifier: ^4.20250412.0 specifier: ^4.20250423.0
version: 4.20250412.0 version: 4.20250423.0
'@eslint/js': '@eslint/js':
specifier: 9.18.0 specifier: 9.18.0
version: 9.18.0 version: 9.18.0
@@ -60,11 +60,11 @@ importers:
specifier: ^15.15.0 specifier: ^15.15.0
version: 15.15.0 version: 15.15.0
typescript-eslint: typescript-eslint:
specifier: ^8.29.1 specifier: ^8.31.0
version: 8.29.1(eslint@9.18.0)(typescript@5.4.5) version: 8.31.0(eslint@9.18.0)(typescript@5.4.5)
wrangler: wrangler:
specifier: ^4.10.0 specifier: ^4.13.0
version: 4.10.0(@cloudflare/workers-types@4.20250412.0) version: 4.13.0(@cloudflare/workers-types@4.20250423.0)
packages: packages:
@@ -248,198 +248,198 @@ packages:
workerd: workerd:
optional: true optional: true
'@cloudflare/workerd-darwin-64@1.20250409.0': '@cloudflare/workerd-darwin-64@1.20250422.0':
resolution: {integrity: sha512-smA9yq77xsdQ1NMLhFz3JZxMHGd01lg0bE+X3dTFmIUs+hHskJ+HJ/IkMFInkCCeEFlUkoL4yO7ilaU/fin/xA==} resolution: {integrity: sha512-2FWl8TLpC4Knuyw8GmNgUSoJCNJNNGJ7Xv90j2n8FiXR5Clp9jSpm2ovK8RP9P751yX1/iIp8e7QufR/XDB6ow==}
engines: {node: '>=16'} engines: {node: '>=16'}
cpu: [x64] cpu: [x64]
os: [darwin] os: [darwin]
'@cloudflare/workerd-darwin-arm64@1.20250409.0': '@cloudflare/workerd-darwin-arm64@1.20250422.0':
resolution: {integrity: sha512-oLVcf+Y5Qun8JHcy1VcR/YnbA5U2ne0czh3XNhDqdHZFK8+vKeC7MnVPX+kEqQA3+uLcMM1/FsIDU1U4Na0h1g==} resolution: {integrity: sha512-GY3W74ivqxsYldacEbMtcSbG7LsS9hPo5UybKIw4RO9GzP7UC5WGnPfuI4PE2SnJOnw7nwSrBLuhGRPe/QQHkQ==}
engines: {node: '>=16'} engines: {node: '>=16'}
cpu: [arm64] cpu: [arm64]
os: [darwin] os: [darwin]
'@cloudflare/workerd-linux-64@1.20250409.0': '@cloudflare/workerd-linux-64@1.20250422.0':
resolution: {integrity: sha512-D31B4kdC3a0RD5yfpdIa89//kGHbYsYihZmejm1k4S4NHOho3MUDHAEh4aHtafQNXbZdydGHlSyiVYjTdQ9ILQ==} resolution: {integrity: sha512-mtNkEygKtlRq9pMRlm9J4nX4uVHU1AtJ3mSkdNwPwhisTpo989O5Zd0SH9CYwAk8+NmlZsXELpODUVQxQ7FJgw==}
engines: {node: '>=16'} engines: {node: '>=16'}
cpu: [x64] cpu: [x64]
os: [linux] os: [linux]
'@cloudflare/workerd-linux-arm64@1.20250409.0': '@cloudflare/workerd-linux-arm64@1.20250422.0':
resolution: {integrity: sha512-Sr59P0TREayil5OQ7kcbjuIn6L6OTSRLI91LKu0D8vi1hss2q9FUwBcwxg0+Yd/x+ty/x7IISiAK5QBkAMeITQ==} resolution: {integrity: sha512-ILlW4/kAoFJvSryrr/QJsiHBdMTf/fjUrIM0hxeuQue8zIEvAVqM1tzpUh8bPJT6AQEbk5ziwkfucA939Z6Tnw==}
engines: {node: '>=16'} engines: {node: '>=16'}
cpu: [arm64] cpu: [arm64]
os: [linux] os: [linux]
'@cloudflare/workerd-windows-64@1.20250409.0': '@cloudflare/workerd-windows-64@1.20250422.0':
resolution: {integrity: sha512-dK9I8zBX5rR7MtaaP2AhICQTEw3PVzHcsltN8o46w7JsbYlMvFOj27FfYH5dhs3IahgmIfw2e572QXW2o/dbpg==} resolution: {integrity: sha512-O2f6f7oxU/oaWX/3/5d/9qvzNSKsw72RsQFjpew2va7KwnnUciI2LnbYR6KYOqRGYrEoiMJxpWPQaYaFVj8t1w==}
engines: {node: '>=16'} engines: {node: '>=16'}
cpu: [x64] cpu: [x64]
os: [win32] os: [win32]
'@cloudflare/workers-types@4.20250412.0': '@cloudflare/workers-types@4.20250423.0':
resolution: {integrity: sha512-ukQE+TRc5HNkM6VvGfTNC9x54TLQKjdcm624F8Qh1ZRe0iJrW2/j1eYgvJABJPexDousYCR7VzCGteShLcBJYQ==} resolution: {integrity: sha512-uzy7fvgYIs9YCEaPScC+RnZvd+yJJCqLCEe/n/6p2PZTxWbDmiZjtJQiP5Zx6G0p64ZD/0ZRmtALfDZDNYBDHg==}
'@cspotcode/source-map-support@0.8.1': '@cspotcode/source-map-support@0.8.1':
resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==}
engines: {node: '>=12'} engines: {node: '>=12'}
'@emnapi/runtime@1.4.1': '@emnapi/runtime@1.4.3':
resolution: {integrity: sha512-LMshMVP0ZhACNjQNYXiU1iZJ6QCcv0lUdPDPugqGvCGXt5xtRVBPdtA0qU12pEXZzpWAhWlZYptfdAFq10DOVQ==} resolution: {integrity: sha512-pBPWdu6MLKROBX05wSNKcNb++m5Er+KQ9QkB+WVM+pW2Kx9hoSrVTnu3BdkI5eBLZoKu/J6mW/B6i6bJB2ytXQ==}
'@esbuild/aix-ppc64@0.24.2': '@esbuild/aix-ppc64@0.25.2':
resolution: {integrity: sha512-thpVCb/rhxE/BnMLQ7GReQLLN8q9qbHmI55F4489/ByVg2aQaQ6kbcLb6FHkocZzQhxc4gx0sCk0tJkKBFzDhA==} resolution: {integrity: sha512-wCIboOL2yXZym2cgm6mlA742s9QeJ8DjGVaL39dLN4rRwrOgOyYSnOaFPhKZGLb2ngj4EyfAFjsNJwPXZvseag==}
engines: {node: '>=18'} engines: {node: '>=18'}
cpu: [ppc64] cpu: [ppc64]
os: [aix] os: [aix]
'@esbuild/android-arm64@0.24.2': '@esbuild/android-arm64@0.25.2':
resolution: {integrity: sha512-cNLgeqCqV8WxfcTIOeL4OAtSmL8JjcN6m09XIgro1Wi7cF4t/THaWEa7eL5CMoMBdjoHOTh/vwTO/o2TRXIyzg==} resolution: {integrity: sha512-5ZAX5xOmTligeBaeNEPnPaeEuah53Id2tX4c2CVP3JaROTH+j4fnfHCkr1PjXMd78hMst+TlkfKcW/DlTq0i4w==}
engines: {node: '>=18'} engines: {node: '>=18'}
cpu: [arm64] cpu: [arm64]
os: [android] os: [android]
'@esbuild/android-arm@0.24.2': '@esbuild/android-arm@0.25.2':
resolution: {integrity: sha512-tmwl4hJkCfNHwFB3nBa8z1Uy3ypZpxqxfTQOcHX+xRByyYgunVbZ9MzUUfb0RxaHIMnbHagwAxuTL+tnNM+1/Q==} resolution: {integrity: sha512-NQhH7jFstVY5x8CKbcfa166GoV0EFkaPkCKBQkdPJFvo5u+nGXLEH/ooniLb3QI8Fk58YAx7nsPLozUWfCBOJA==}
engines: {node: '>=18'} engines: {node: '>=18'}
cpu: [arm] cpu: [arm]
os: [android] os: [android]
'@esbuild/android-x64@0.24.2': '@esbuild/android-x64@0.25.2':
resolution: {integrity: sha512-B6Q0YQDqMx9D7rvIcsXfmJfvUYLoP722bgfBlO5cGvNVb5V/+Y7nhBE3mHV9OpxBf4eAS2S68KZztiPaWq4XYw==} resolution: {integrity: sha512-Ffcx+nnma8Sge4jzddPHCZVRvIfQ0kMsUsCMcJRHkGJ1cDmhe4SsrYIjLUKn1xpHZybmOqCWwB0zQvsjdEHtkg==}
engines: {node: '>=18'} engines: {node: '>=18'}
cpu: [x64] cpu: [x64]
os: [android] os: [android]
'@esbuild/darwin-arm64@0.24.2': '@esbuild/darwin-arm64@0.25.2':
resolution: {integrity: sha512-kj3AnYWc+CekmZnS5IPu9D+HWtUI49hbnyqk0FLEJDbzCIQt7hg7ucF1SQAilhtYpIujfaHr6O0UHlzzSPdOeA==} resolution: {integrity: sha512-MpM6LUVTXAzOvN4KbjzU/q5smzryuoNjlriAIx+06RpecwCkL9JpenNzpKd2YMzLJFOdPqBpuub6eVRP5IgiSA==}
engines: {node: '>=18'} engines: {node: '>=18'}
cpu: [arm64] cpu: [arm64]
os: [darwin] os: [darwin]
'@esbuild/darwin-x64@0.24.2': '@esbuild/darwin-x64@0.25.2':
resolution: {integrity: sha512-WeSrmwwHaPkNR5H3yYfowhZcbriGqooyu3zI/3GGpF8AyUdsrrP0X6KumITGA9WOyiJavnGZUwPGvxvwfWPHIA==} resolution: {integrity: sha512-5eRPrTX7wFyuWe8FqEFPG2cU0+butQQVNcT4sVipqjLYQjjh8a8+vUTfgBKM88ObB85ahsnTwF7PSIt6PG+QkA==}
engines: {node: '>=18'} engines: {node: '>=18'}
cpu: [x64] cpu: [x64]
os: [darwin] os: [darwin]
'@esbuild/freebsd-arm64@0.24.2': '@esbuild/freebsd-arm64@0.25.2':
resolution: {integrity: sha512-UN8HXjtJ0k/Mj6a9+5u6+2eZ2ERD7Edt1Q9IZiB5UZAIdPnVKDoG7mdTVGhHJIeEml60JteamR3qhsr1r8gXvg==} resolution: {integrity: sha512-mLwm4vXKiQ2UTSX4+ImyiPdiHjiZhIaE9QvC7sw0tZ6HoNMjYAqQpGyui5VRIi5sGd+uWq940gdCbY3VLvsO1w==}
engines: {node: '>=18'} engines: {node: '>=18'}
cpu: [arm64] cpu: [arm64]
os: [freebsd] os: [freebsd]
'@esbuild/freebsd-x64@0.24.2': '@esbuild/freebsd-x64@0.25.2':
resolution: {integrity: sha512-TvW7wE/89PYW+IevEJXZ5sF6gJRDY/14hyIGFXdIucxCsbRmLUcjseQu1SyTko+2idmCw94TgyaEZi9HUSOe3Q==} resolution: {integrity: sha512-6qyyn6TjayJSwGpm8J9QYYGQcRgc90nmfdUb0O7pp1s4lTY+9D0H9O02v5JqGApUyiHOtkz6+1hZNvNtEhbwRQ==}
engines: {node: '>=18'} engines: {node: '>=18'}
cpu: [x64] cpu: [x64]
os: [freebsd] os: [freebsd]
'@esbuild/linux-arm64@0.24.2': '@esbuild/linux-arm64@0.25.2':
resolution: {integrity: sha512-7HnAD6074BW43YvvUmE/35Id9/NB7BeX5EoNkK9obndmZBUk8xmJJeU7DwmUeN7tkysslb2eSl6CTrYz6oEMQg==} resolution: {integrity: sha512-gq/sjLsOyMT19I8obBISvhoYiZIAaGF8JpeXu1u8yPv8BE5HlWYobmlsfijFIZ9hIVGYkbdFhEqC0NvM4kNO0g==}
engines: {node: '>=18'} engines: {node: '>=18'}
cpu: [arm64] cpu: [arm64]
os: [linux] os: [linux]
'@esbuild/linux-arm@0.24.2': '@esbuild/linux-arm@0.25.2':
resolution: {integrity: sha512-n0WRM/gWIdU29J57hJyUdIsk0WarGd6To0s+Y+LwvlC55wt+GT/OgkwoXCXvIue1i1sSNWblHEig00GBWiJgfA==} resolution: {integrity: sha512-UHBRgJcmjJv5oeQF8EpTRZs/1knq6loLxTsjc3nxO9eXAPDLcWW55flrMVc97qFPbmZP31ta1AZVUKQzKTzb0g==}
engines: {node: '>=18'} engines: {node: '>=18'}
cpu: [arm] cpu: [arm]
os: [linux] os: [linux]
'@esbuild/linux-ia32@0.24.2': '@esbuild/linux-ia32@0.25.2':
resolution: {integrity: sha512-sfv0tGPQhcZOgTKO3oBE9xpHuUqguHvSo4jl+wjnKwFpapx+vUDcawbwPNuBIAYdRAvIDBfZVvXprIj3HA+Ugw==} resolution: {integrity: sha512-bBYCv9obgW2cBP+2ZWfjYTU+f5cxRoGGQ5SeDbYdFCAZpYWrfjjfYwvUpP8MlKbP0nwZ5gyOU/0aUzZ5HWPuvQ==}
engines: {node: '>=18'} engines: {node: '>=18'}
cpu: [ia32] cpu: [ia32]
os: [linux] os: [linux]
'@esbuild/linux-loong64@0.24.2': '@esbuild/linux-loong64@0.25.2':
resolution: {integrity: sha512-CN9AZr8kEndGooS35ntToZLTQLHEjtVB5n7dl8ZcTZMonJ7CCfStrYhrzF97eAecqVbVJ7APOEe18RPI4KLhwQ==} resolution: {integrity: sha512-SHNGiKtvnU2dBlM5D8CXRFdd+6etgZ9dXfaPCeJtz+37PIUlixvlIhI23L5khKXs3DIzAn9V8v+qb1TRKrgT5w==}
engines: {node: '>=18'} engines: {node: '>=18'}
cpu: [loong64] cpu: [loong64]
os: [linux] os: [linux]
'@esbuild/linux-mips64el@0.24.2': '@esbuild/linux-mips64el@0.25.2':
resolution: {integrity: sha512-iMkk7qr/wl3exJATwkISxI7kTcmHKE+BlymIAbHO8xanq/TjHaaVThFF6ipWzPHryoFsesNQJPE/3wFJw4+huw==} resolution: {integrity: sha512-hDDRlzE6rPeoj+5fsADqdUZl1OzqDYow4TB4Y/3PlKBD0ph1e6uPHzIQcv2Z65u2K0kpeByIyAjCmjn1hJgG0Q==}
engines: {node: '>=18'} engines: {node: '>=18'}
cpu: [mips64el] cpu: [mips64el]
os: [linux] os: [linux]
'@esbuild/linux-ppc64@0.24.2': '@esbuild/linux-ppc64@0.25.2':
resolution: {integrity: sha512-shsVrgCZ57Vr2L8mm39kO5PPIb+843FStGt7sGGoqiiWYconSxwTiuswC1VJZLCjNiMLAMh34jg4VSEQb+iEbw==} resolution: {integrity: sha512-tsHu2RRSWzipmUi9UBDEzc0nLc4HtpZEI5Ba+Omms5456x5WaNuiG3u7xh5AO6sipnJ9r4cRWQB2tUjPyIkc6g==}
engines: {node: '>=18'} engines: {node: '>=18'}
cpu: [ppc64] cpu: [ppc64]
os: [linux] os: [linux]
'@esbuild/linux-riscv64@0.24.2': '@esbuild/linux-riscv64@0.25.2':
resolution: {integrity: sha512-4eSFWnU9Hhd68fW16GD0TINewo1L6dRrB+oLNNbYyMUAeOD2yCK5KXGK1GH4qD/kT+bTEXjsyTCiJGHPZ3eM9Q==} resolution: {integrity: sha512-k4LtpgV7NJQOml/10uPU0s4SAXGnowi5qBSjaLWMojNCUICNu7TshqHLAEbkBdAszL5TabfvQ48kK84hyFzjnw==}
engines: {node: '>=18'} engines: {node: '>=18'}
cpu: [riscv64] cpu: [riscv64]
os: [linux] os: [linux]
'@esbuild/linux-s390x@0.24.2': '@esbuild/linux-s390x@0.25.2':
resolution: {integrity: sha512-S0Bh0A53b0YHL2XEXC20bHLuGMOhFDO6GN4b3YjRLK//Ep3ql3erpNcPlEFed93hsQAjAQDNsvcK+hV90FubSw==} resolution: {integrity: sha512-GRa4IshOdvKY7M/rDpRR3gkiTNp34M0eLTaC1a08gNrh4u488aPhuZOCpkF6+2wl3zAN7L7XIpOFBhnaE3/Q8Q==}
engines: {node: '>=18'} engines: {node: '>=18'}
cpu: [s390x] cpu: [s390x]
os: [linux] os: [linux]
'@esbuild/linux-x64@0.24.2': '@esbuild/linux-x64@0.25.2':
resolution: {integrity: sha512-8Qi4nQcCTbLnK9WoMjdC9NiTG6/E38RNICU6sUNqK0QFxCYgoARqVqxdFmWkdonVsvGqWhmm7MO0jyTqLqwj0Q==} resolution: {integrity: sha512-QInHERlqpTTZ4FRB0fROQWXcYRD64lAoiegezDunLpalZMjcUcld3YzZmVJ2H/Cp0wJRZ8Xtjtj0cEHhYc/uUg==}
engines: {node: '>=18'} engines: {node: '>=18'}
cpu: [x64] cpu: [x64]
os: [linux] os: [linux]
'@esbuild/netbsd-arm64@0.24.2': '@esbuild/netbsd-arm64@0.25.2':
resolution: {integrity: sha512-wuLK/VztRRpMt9zyHSazyCVdCXlpHkKm34WUyinD2lzK07FAHTq0KQvZZlXikNWkDGoT6x3TD51jKQ7gMVpopw==} resolution: {integrity: sha512-talAIBoY5M8vHc6EeI2WW9d/CkiO9MQJ0IOWX8hrLhxGbro/vBXJvaQXefW2cP0z0nQVTdQ/eNyGFV1GSKrxfw==}
engines: {node: '>=18'} engines: {node: '>=18'}
cpu: [arm64] cpu: [arm64]
os: [netbsd] os: [netbsd]
'@esbuild/netbsd-x64@0.24.2': '@esbuild/netbsd-x64@0.25.2':
resolution: {integrity: sha512-VefFaQUc4FMmJuAxmIHgUmfNiLXY438XrL4GDNV1Y1H/RW3qow68xTwjZKfj/+Plp9NANmzbH5R40Meudu8mmw==} resolution: {integrity: sha512-voZT9Z+tpOxrvfKFyfDYPc4DO4rk06qamv1a/fkuzHpiVBMOhpjK+vBmWM8J1eiB3OLSMFYNaOaBNLXGChf5tg==}
engines: {node: '>=18'} engines: {node: '>=18'}
cpu: [x64] cpu: [x64]
os: [netbsd] os: [netbsd]
'@esbuild/openbsd-arm64@0.24.2': '@esbuild/openbsd-arm64@0.25.2':
resolution: {integrity: sha512-YQbi46SBct6iKnszhSvdluqDmxCJA+Pu280Av9WICNwQmMxV7nLRHZfjQzwbPs3jeWnuAhE9Jy0NrnJ12Oz+0A==} resolution: {integrity: sha512-dcXYOC6NXOqcykeDlwId9kB6OkPUxOEqU+rkrYVqJbK2hagWOMrsTGsMr8+rW02M+d5Op5NNlgMmjzecaRf7Tg==}
engines: {node: '>=18'} engines: {node: '>=18'}
cpu: [arm64] cpu: [arm64]
os: [openbsd] os: [openbsd]
'@esbuild/openbsd-x64@0.24.2': '@esbuild/openbsd-x64@0.25.2':
resolution: {integrity: sha512-+iDS6zpNM6EnJyWv0bMGLWSWeXGN/HTaF/LXHXHwejGsVi+ooqDfMCCTerNFxEkM3wYVcExkeGXNqshc9iMaOA==} resolution: {integrity: sha512-t/TkWwahkH0Tsgoq1Ju7QfgGhArkGLkF1uYz8nQS/PPFlXbP5YgRpqQR3ARRiC2iXoLTWFxc6DJMSK10dVXluw==}
engines: {node: '>=18'} engines: {node: '>=18'}
cpu: [x64] cpu: [x64]
os: [openbsd] os: [openbsd]
'@esbuild/sunos-x64@0.24.2': '@esbuild/sunos-x64@0.25.2':
resolution: {integrity: sha512-hTdsW27jcktEvpwNHJU4ZwWFGkz2zRJUz8pvddmXPtXDzVKTTINmlmga3ZzwcuMpUvLw7JkLy9QLKyGpD2Yxig==} resolution: {integrity: sha512-cfZH1co2+imVdWCjd+D1gf9NjkchVhhdpgb1q5y6Hcv9TP6Zi9ZG/beI3ig8TvwT9lH9dlxLq5MQBBgwuj4xvA==}
engines: {node: '>=18'} engines: {node: '>=18'}
cpu: [x64] cpu: [x64]
os: [sunos] os: [sunos]
'@esbuild/win32-arm64@0.24.2': '@esbuild/win32-arm64@0.25.2':
resolution: {integrity: sha512-LihEQ2BBKVFLOC9ZItT9iFprsE9tqjDjnbulhHoFxYQtQfai7qfluVODIYxt1PgdoyQkz23+01rzwNwYfutxUQ==} resolution: {integrity: sha512-7Loyjh+D/Nx/sOTzV8vfbB3GJuHdOQyrOryFdZvPHLf42Tk9ivBU5Aedi7iyX+x6rbn2Mh68T4qq1SDqJBQO5Q==}
engines: {node: '>=18'} engines: {node: '>=18'}
cpu: [arm64] cpu: [arm64]
os: [win32] os: [win32]
'@esbuild/win32-ia32@0.24.2': '@esbuild/win32-ia32@0.25.2':
resolution: {integrity: sha512-q+iGUwfs8tncmFC9pcnD5IvRHAzmbwQ3GPS5/ceCyHdjXubwQWI12MKWSNSMYLJMq23/IUCvJMS76PDqXe1fxA==} resolution: {integrity: sha512-WRJgsz9un0nqZJ4MfhabxaD9Ft8KioqU3JMinOTvobbX6MOSUigSBlogP8QB3uxpJDsFS6yN+3FDBdqE5lg9kg==}
engines: {node: '>=18'} engines: {node: '>=18'}
cpu: [ia32] cpu: [ia32]
os: [win32] os: [win32]
'@esbuild/win32-x64@0.24.2': '@esbuild/win32-x64@0.25.2':
resolution: {integrity: sha512-7VTgWzgMGvup6aSqDPLiW5zHaxYJGTO4OokMjIlrCtf+VpEL+cXKtCvg723iguPYI5oaUNdS+/V7OU2gvXVWEg==} resolution: {integrity: sha512-kM3HKb16VIXZyIeVrM1ygYmZBKybX8N4p754bw390wGO3Tf2j4L2/WYL+4suWujpgf6GBYs3jv7TyUivdd05JA==}
engines: {node: '>=18'} engines: {node: '>=18'}
cpu: [x64] cpu: [x64]
os: [win32] os: [win32]
'@eslint-community/eslint-utils@4.5.1': '@eslint-community/eslint-utils@4.6.1':
resolution: {integrity: sha512-soEIOALTfTK6EjmKMMoLugwaP0rzkad90iIWd1hMO9ARkSAyjfMfkRRhLvD5qH7vvM0Cg72pieUfR6yh6XxC4w==} resolution: {integrity: sha512-KTsJMmobmbrFLe3LDh0PC2FXpcSYJt/MLjlkh/9LEnmKYLSYmT/0EW9JWANjeoemiuZrmogti0tW5Ch+qNUYDw==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
peerDependencies: peerDependencies:
eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 eslint: ^6.0.0 || ^7.0.0 || >=8.0.0
@@ -660,8 +660,8 @@ packages:
'@peculiar/asn1-x509@2.3.15': '@peculiar/asn1-x509@2.3.15':
resolution: {integrity: sha512-0dK5xqTqSLaxv1FHXIcd4Q/BZNuopg+u1l23hT9rOmQ1g4dNtw0g/RnEi+TboB0gOwGtrWn269v27cMgchFIIg==} resolution: {integrity: sha512-0dK5xqTqSLaxv1FHXIcd4Q/BZNuopg+u1l23hT9rOmQ1g4dNtw0g/RnEi+TboB0gOwGtrWn269v27cMgchFIIg==}
'@react-email/render@1.0.5': '@react-email/render@1.0.6':
resolution: {integrity: sha512-CA69HYXPk21HhtAXATIr+9JJwpDNmAFCvdMUjWmeoD1+KhJ9NAxusMRxKNeibdZdslmq3edaeOKGbdQ9qjK8LQ==} resolution: {integrity: sha512-zNueW5Wn/4jNC1c5LFgXzbUdv5Lhms+FWjOvWAhal7gx5YVf0q6dPJ0dnR70+ifo59gcMLwCZEaTS9EEuUhKvQ==}
engines: {node: '>=18.0.0'} engines: {node: '>=18.0.0'}
peerDependencies: peerDependencies:
react: ^18.0 || ^19.0 || ^19.0.0-rc react: ^18.0 || ^19.0 || ^19.0.0-rc
@@ -898,51 +898,51 @@ packages:
'@types/json-schema@7.0.15': '@types/json-schema@7.0.15':
resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==}
'@typescript-eslint/eslint-plugin@8.29.1': '@typescript-eslint/eslint-plugin@8.31.0':
resolution: {integrity: sha512-ba0rr4Wfvg23vERs3eB+P3lfj2E+2g3lhWcCVukUuhtcdUx5lSIFZlGFEBHKr+3zizDa/TvZTptdNHVZWAkSBg==} resolution: {integrity: sha512-evaQJZ/J/S4wisevDvC1KFZkPzRetH8kYZbkgcTRyql3mcKsf+ZFDV1BVWUGTCAW5pQHoqn5gK5b8kn7ou9aFQ==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies: peerDependencies:
'@typescript-eslint/parser': ^8.0.0 || ^8.0.0-alpha.0 '@typescript-eslint/parser': ^8.0.0 || ^8.0.0-alpha.0
eslint: ^8.57.0 || ^9.0.0 eslint: ^8.57.0 || ^9.0.0
typescript: '>=4.8.4 <5.9.0' typescript: '>=4.8.4 <5.9.0'
'@typescript-eslint/parser@8.29.1': '@typescript-eslint/parser@8.31.0':
resolution: {integrity: sha512-zczrHVEqEaTwh12gWBIJWj8nx+ayDcCJs06yoNMY0kwjMWDM6+kppljY+BxWI06d2Ja+h4+WdufDcwMnnMEWmg==} resolution: {integrity: sha512-67kYYShjBR0jNI5vsf/c3WG4u+zDnCTHTPqVMQguffaWWFs7artgwKmfwdifl+r6XyM5LYLas/dInj2T0SgJyw==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies: peerDependencies:
eslint: ^8.57.0 || ^9.0.0 eslint: ^8.57.0 || ^9.0.0
typescript: '>=4.8.4 <5.9.0' typescript: '>=4.8.4 <5.9.0'
'@typescript-eslint/scope-manager@8.29.1': '@typescript-eslint/scope-manager@8.31.0':
resolution: {integrity: sha512-2nggXGX5F3YrsGN08pw4XpMLO1Rgtnn4AzTegC2MDesv6q3QaTU5yU7IbS1tf1IwCR0Hv/1EFygLn9ms6LIpDA==} resolution: {integrity: sha512-knO8UyF78Nt8O/B64i7TlGXod69ko7z6vJD9uhSlm0qkAbGeRUSudcm0+K/4CrRjrpiHfBCjMWlc08Vav1xwcw==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@typescript-eslint/type-utils@8.29.1': '@typescript-eslint/type-utils@8.31.0':
resolution: {integrity: sha512-DkDUSDwZVCYN71xA4wzySqqcZsHKic53A4BLqmrWFFpOpNSoxX233lwGu/2135ymTCR04PoKiEEEvN1gFYg4Tw==} resolution: {integrity: sha512-DJ1N1GdjI7IS7uRlzJuEDCgDQix3ZVYVtgeWEyhyn4iaoitpMBX6Ndd488mXSx0xah/cONAkEaYyylDyAeHMHg==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies: peerDependencies:
eslint: ^8.57.0 || ^9.0.0 eslint: ^8.57.0 || ^9.0.0
typescript: '>=4.8.4 <5.9.0' typescript: '>=4.8.4 <5.9.0'
'@typescript-eslint/types@8.29.1': '@typescript-eslint/types@8.31.0':
resolution: {integrity: sha512-VT7T1PuJF1hpYC3AGm2rCgJBjHL3nc+A/bhOp9sGMKfi5v0WufsX/sHCFBfNTx2F+zA6qBc/PD0/kLRLjdt8mQ==} resolution: {integrity: sha512-Ch8oSjVyYyJxPQk8pMiP2FFGYatqXQfQIaMp+TpuuLlDachRWpUAeEu1u9B/v/8LToehUIWyiKcA/w5hUFRKuQ==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@typescript-eslint/typescript-estree@8.29.1': '@typescript-eslint/typescript-estree@8.31.0':
resolution: {integrity: sha512-l1enRoSaUkQxOQnbi0KPUtqeZkSiFlqrx9/3ns2rEDhGKfTa+88RmXqedC1zmVTOWrLc2e6DEJrTA51C9iLH5g==} resolution: {integrity: sha512-xLmgn4Yl46xi6aDSZ9KkyfhhtnYI15/CvHbpOy/eR5NWhK/BK8wc709KKwhAR0m4ZKRP7h07bm4BWUYOCuRpQQ==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies: peerDependencies:
typescript: '>=4.8.4 <5.9.0' typescript: '>=4.8.4 <5.9.0'
'@typescript-eslint/utils@8.29.1': '@typescript-eslint/utils@8.31.0':
resolution: {integrity: sha512-QAkFEbytSaB8wnmB+DflhUPz6CLbFWE2SnSCrRMEa+KnXIzDYbpsn++1HGvnfAsUY44doDXmvRkO5shlM/3UfA==} resolution: {integrity: sha512-qi6uPLt9cjTFxAb1zGNgTob4x9ur7xC6mHQJ8GwEzGMGE9tYniublmJaowOJ9V2jUzxrltTPfdG2nKlWsq0+Ww==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies: peerDependencies:
eslint: ^8.57.0 || ^9.0.0 eslint: ^8.57.0 || ^9.0.0
typescript: '>=4.8.4 <5.9.0' typescript: '>=4.8.4 <5.9.0'
'@typescript-eslint/visitor-keys@8.29.1': '@typescript-eslint/visitor-keys@8.31.0':
resolution: {integrity: sha512-RGLh5CRaUEf02viP5c1Vh1cMGffQscyHe7HPAzGpfmfflFg1wUz2rYxd+OZqwpeypYvZ8UxSxuIpF++fmOzEcg==} resolution: {integrity: sha512-QcGHmlRHWOl93o64ZUMNewCdwKGU6WItOU52H0djgNmn1EOrhVudrDzXz4OycCRSCPwFCDrE2iIt5vmuUdHxuQ==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
abort-controller@3.0.0: abort-controller@3.0.0:
@@ -1074,8 +1074,8 @@ packages:
defu@6.1.4: defu@6.1.4:
resolution: {integrity: sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==} resolution: {integrity: sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==}
detect-libc@2.0.3: detect-libc@2.0.4:
resolution: {integrity: sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==} resolution: {integrity: sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==}
engines: {node: '>=8'} engines: {node: '>=8'}
dom-serializer@2.0.0: dom-serializer@2.0.0:
@@ -1095,8 +1095,8 @@ packages:
resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==}
engines: {node: '>=0.12'} engines: {node: '>=0.12'}
esbuild@0.24.2: esbuild@0.25.2:
resolution: {integrity: sha512-+9egpBW8I3CD5XPe0n6BfT5fxLzxrlDzqydF3aviG+9ni1lDC/OvMHcxqEFV0+LANZG5R1bFMWfUrjVsdwxJvA==} resolution: {integrity: sha512-16854zccKPnC+toMywC+uKNeYSv+/eXkevRAfwRD/G9Cleq66m8XFIrigkbvauLLlCfDL45Q2cWegSg53gGBnQ==}
engines: {node: '>=18'} engines: {node: '>=18'}
hasBin: true hasBin: true
@@ -1154,8 +1154,8 @@ packages:
resolution: {integrity: sha512-eNTPlAD67BmP31LDINZ3U7HSF8l57TxOY2PmBJ1shpCvpnxBF93mWCE8YHBnXs8qiUZJc9WDcWIeC3a2HIAMfw==} resolution: {integrity: sha512-eNTPlAD67BmP31LDINZ3U7HSF8l57TxOY2PmBJ1shpCvpnxBF93mWCE8YHBnXs8qiUZJc9WDcWIeC3a2HIAMfw==}
engines: {node: '>=6'} engines: {node: '>=6'}
exsolve@1.0.4: exsolve@1.0.5:
resolution: {integrity: sha512-xsZH6PXaER4XoV+NiT7JHp1bJodJVT+cxeSH1G0f0tlT0lJqYuHUP3bUx2HtfTDvOagMINYp8rsqusxud3RXhw==} resolution: {integrity: sha512-pz5dvkYYKQ1AHVrgOzBKWeP4u4FRb3a6DNK2ucr0OoNwYIU4QWsJ+NM36LLzORT+z845MzKHHhpXiUF5nvQoJg==}
fast-deep-equal@2.0.1: fast-deep-equal@2.0.1:
resolution: {integrity: sha512-bCK/2Z4zLidyB4ReuIsvALH6w31YfAQDmXMqMx6FyfHqvBxtjC0eRumeSu4Bs3XtXwpyIywtSTrVT99BxY1f9w==} resolution: {integrity: sha512-bCK/2Z4zLidyB4ReuIsvALH6w31YfAQDmXMqMx6FyfHqvBxtjC0eRumeSu4Bs3XtXwpyIywtSTrVT99BxY1f9w==}
@@ -1233,8 +1233,8 @@ packages:
resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==}
engines: {node: '>=8'} engines: {node: '>=8'}
hono@4.7.6: hono@4.7.7:
resolution: {integrity: sha512-564rVzELU+9BRqqx5k8sT2NFwGD3I3Vifdb6P7CmM6FiarOSY+fDC+6B+k9wcCb86ReoayteZP2ki0cRLN1jbw==} resolution: {integrity: sha512-2PCpQRbN87Crty8/L/7akZN3UyZIAopSoRxCwRbJgUuV1+MHNFHzYFxZTg4v/03cXUm+jce/qa2VSBZpKBm3Qw==}
engines: {node: '>=16.9.0'} engines: {node: '>=16.9.0'}
html-to-text@9.0.5: html-to-text@9.0.5:
@@ -1347,8 +1347,8 @@ packages:
mimetext@3.0.27: mimetext@3.0.27:
resolution: {integrity: sha512-mUhWAsZD1N/K6dbN4+a5Yq78OPnYQw1ubOSMasBntsLQ2S7KVNlvDEA8dwpr4a7PszWMzeslKahAprtwYMgaBA==} resolution: {integrity: sha512-mUhWAsZD1N/K6dbN4+a5Yq78OPnYQw1ubOSMasBntsLQ2S7KVNlvDEA8dwpr4a7PszWMzeslKahAprtwYMgaBA==}
miniflare@4.20250409.0: miniflare@4.20250422.0:
resolution: {integrity: sha512-Hu02dYZvFR+MyrI57O6rSrOUTofcO9EIvcodgq2SAHzAeWSJw2E0oq9lylOrcckFwPMcwxUAb/cQN1LIoCyySw==} resolution: {integrity: sha512-3frXK9EZEWQkHMDyppeIbUKwd7OQkNOm2gBtQQzjQ4gtzQmh+yxkyJiiylf+fGbz86djQTLKKQdQ1FC4yM3AMg==}
engines: {node: '>=18.0.0'} engines: {node: '>=18.0.0'}
hasBin: true hasBin: true
@@ -1436,8 +1436,8 @@ packages:
resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==}
engines: {node: '>= 0.8.0'} engines: {node: '>= 0.8.0'}
prettier@3.4.2: prettier@3.5.3:
resolution: {integrity: sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ==} resolution: {integrity: sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==}
engines: {node: '>=14'} engines: {node: '>=14'}
hasBin: true hasBin: true
@@ -1473,8 +1473,8 @@ packages:
regenerator-runtime@0.14.1: regenerator-runtime@0.14.1:
resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==} resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==}
resend@4.2.0: resend@4.4.0:
resolution: {integrity: sha512-s6ogU+BBYH1H6Zl926cpddtLRAJWeFv5cIKcuHLWk1QYhFTbpFJlhqx31pnN2f0CB075KFSrc1Xf6HG690wzuw==} resolution: {integrity: sha512-SmVI3JCpgPNt4/m3Uy403LjoSeeleUE2X+KwPYQZcw+jiBCFsqL6vdf1r/XuQ7yOjvxYmlI8GD/oIWonFF9t9w==}
engines: {node: '>=18'} engines: {node: '>=18'}
resolve-from@4.0.0: resolve-from@4.0.0:
@@ -1568,8 +1568,8 @@ packages:
resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==}
engines: {node: '>= 0.8.0'} engines: {node: '>= 0.8.0'}
typescript-eslint@8.29.1: typescript-eslint@8.31.0:
resolution: {integrity: sha512-f8cDkvndhbQMPcysk6CUSGBWV+g1utqdn71P5YKwMumVMOG/5k7cHq0KyG4O52nB0oKS4aN2Tp5+wB4APJGC+w==} resolution: {integrity: sha512-u+93F0sB0An8WEAPtwxVhFby573E8ckdjwUUQUj9QA4v8JAvgtoDdIyYR3XFwFHq2W1KJ1AurwJCO+w+Y1ixyQ==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies: peerDependencies:
eslint: ^8.57.0 || ^9.0.0 eslint: ^8.57.0 || ^9.0.0
@@ -1612,20 +1612,20 @@ packages:
resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==}
engines: {node: '>=0.10.0'} engines: {node: '>=0.10.0'}
worker-mailer@1.1.1: worker-mailer@1.1.3:
resolution: {integrity: sha512-UPPd48aBMVuAE2j9ha7wDEhBakM23zKBk8wd9lLUhChExPeq8B8cO6C1ur4hMOypmJO7mZ+xTZff1KoCKprvGA==} resolution: {integrity: sha512-8jkbf843tAV9KMWQESrduMt6LKolYXJ9rmWO0W8ZM3CW0Mb+qaVaktXhqvAo7cLvYnYSxYBS8oJl0pgr75XipQ==}
workerd@1.20250409.0: workerd@1.20250422.0:
resolution: {integrity: sha512-hqjX9swiHvrkOI3jlH9lrZsZRRv9lddUwcMe8Ua76jnyQz+brybWznNjHu8U5oswwcrFwvky1A4CcLjcLY31gQ==} resolution: {integrity: sha512-q3ws6MIa9GJQqq1Q52qoD7vCx1203fjKNPmtRV1vvplrsfYphjr5pOAnZGUODFB1BnsDWypr71Luy7OonT0vug==}
engines: {node: '>=16'} engines: {node: '>=16'}
hasBin: true hasBin: true
wrangler@4.10.0: wrangler@4.13.0:
resolution: {integrity: sha512-fTE4hZ79msEUt8+HEjl/8Q72haCyzPLu4PgrU3L81ysmjrMEdiYfUPqnvCkBUVtJvrDNdctTEimkufT1Y0ipNg==} resolution: {integrity: sha512-CVRNL0unLmzhVeUkW+9neZHFITSo7UDROz8VYxi8YhitV9Rr1xMojS1cGjQTaQX8F3nAEsTRJXTwwTZ0JoJm6g==}
engines: {node: '>=18.0.0'} engines: {node: '>=18.0.0'}
hasBin: true hasBin: true
peerDependencies: peerDependencies:
'@cloudflare/workers-types': ^4.20250409.0 '@cloudflare/workers-types': ^4.20250422.0
peerDependenciesMeta: peerDependenciesMeta:
'@cloudflare/workers-types': '@cloudflare/workers-types':
optional: true optional: true
@@ -2143,114 +2143,114 @@ snapshots:
dependencies: dependencies:
mime: 3.0.0 mime: 3.0.0
'@cloudflare/unenv-preset@2.3.1(unenv@2.0.0-rc.15)(workerd@1.20250409.0)': '@cloudflare/unenv-preset@2.3.1(unenv@2.0.0-rc.15)(workerd@1.20250422.0)':
dependencies: dependencies:
unenv: 2.0.0-rc.15 unenv: 2.0.0-rc.15
optionalDependencies: optionalDependencies:
workerd: 1.20250409.0 workerd: 1.20250422.0
'@cloudflare/workerd-darwin-64@1.20250409.0': '@cloudflare/workerd-darwin-64@1.20250422.0':
optional: true optional: true
'@cloudflare/workerd-darwin-arm64@1.20250409.0': '@cloudflare/workerd-darwin-arm64@1.20250422.0':
optional: true optional: true
'@cloudflare/workerd-linux-64@1.20250409.0': '@cloudflare/workerd-linux-64@1.20250422.0':
optional: true optional: true
'@cloudflare/workerd-linux-arm64@1.20250409.0': '@cloudflare/workerd-linux-arm64@1.20250422.0':
optional: true optional: true
'@cloudflare/workerd-windows-64@1.20250409.0': '@cloudflare/workerd-windows-64@1.20250422.0':
optional: true optional: true
'@cloudflare/workers-types@4.20250412.0': {} '@cloudflare/workers-types@4.20250423.0': {}
'@cspotcode/source-map-support@0.8.1': '@cspotcode/source-map-support@0.8.1':
dependencies: dependencies:
'@jridgewell/trace-mapping': 0.3.9 '@jridgewell/trace-mapping': 0.3.9
'@emnapi/runtime@1.4.1': '@emnapi/runtime@1.4.3':
dependencies: dependencies:
tslib: 2.8.1 tslib: 2.8.1
optional: true optional: true
'@esbuild/aix-ppc64@0.24.2': '@esbuild/aix-ppc64@0.25.2':
optional: true optional: true
'@esbuild/android-arm64@0.24.2': '@esbuild/android-arm64@0.25.2':
optional: true optional: true
'@esbuild/android-arm@0.24.2': '@esbuild/android-arm@0.25.2':
optional: true optional: true
'@esbuild/android-x64@0.24.2': '@esbuild/android-x64@0.25.2':
optional: true optional: true
'@esbuild/darwin-arm64@0.24.2': '@esbuild/darwin-arm64@0.25.2':
optional: true optional: true
'@esbuild/darwin-x64@0.24.2': '@esbuild/darwin-x64@0.25.2':
optional: true optional: true
'@esbuild/freebsd-arm64@0.24.2': '@esbuild/freebsd-arm64@0.25.2':
optional: true optional: true
'@esbuild/freebsd-x64@0.24.2': '@esbuild/freebsd-x64@0.25.2':
optional: true optional: true
'@esbuild/linux-arm64@0.24.2': '@esbuild/linux-arm64@0.25.2':
optional: true optional: true
'@esbuild/linux-arm@0.24.2': '@esbuild/linux-arm@0.25.2':
optional: true optional: true
'@esbuild/linux-ia32@0.24.2': '@esbuild/linux-ia32@0.25.2':
optional: true optional: true
'@esbuild/linux-loong64@0.24.2': '@esbuild/linux-loong64@0.25.2':
optional: true optional: true
'@esbuild/linux-mips64el@0.24.2': '@esbuild/linux-mips64el@0.25.2':
optional: true optional: true
'@esbuild/linux-ppc64@0.24.2': '@esbuild/linux-ppc64@0.25.2':
optional: true optional: true
'@esbuild/linux-riscv64@0.24.2': '@esbuild/linux-riscv64@0.25.2':
optional: true optional: true
'@esbuild/linux-s390x@0.24.2': '@esbuild/linux-s390x@0.25.2':
optional: true optional: true
'@esbuild/linux-x64@0.24.2': '@esbuild/linux-x64@0.25.2':
optional: true optional: true
'@esbuild/netbsd-arm64@0.24.2': '@esbuild/netbsd-arm64@0.25.2':
optional: true optional: true
'@esbuild/netbsd-x64@0.24.2': '@esbuild/netbsd-x64@0.25.2':
optional: true optional: true
'@esbuild/openbsd-arm64@0.24.2': '@esbuild/openbsd-arm64@0.25.2':
optional: true optional: true
'@esbuild/openbsd-x64@0.24.2': '@esbuild/openbsd-x64@0.25.2':
optional: true optional: true
'@esbuild/sunos-x64@0.24.2': '@esbuild/sunos-x64@0.25.2':
optional: true optional: true
'@esbuild/win32-arm64@0.24.2': '@esbuild/win32-arm64@0.25.2':
optional: true optional: true
'@esbuild/win32-ia32@0.24.2': '@esbuild/win32-ia32@0.25.2':
optional: true optional: true
'@esbuild/win32-x64@0.24.2': '@esbuild/win32-x64@0.25.2':
optional: true optional: true
'@eslint-community/eslint-utils@4.5.1(eslint@9.18.0)': '@eslint-community/eslint-utils@4.6.1(eslint@9.18.0)':
dependencies: dependencies:
eslint: 9.18.0 eslint: 9.18.0
eslint-visitor-keys: 3.4.3 eslint-visitor-keys: 3.4.3
@@ -2379,7 +2379,7 @@ snapshots:
'@img/sharp-wasm32@0.33.5': '@img/sharp-wasm32@0.33.5':
dependencies: dependencies:
'@emnapi/runtime': 1.4.1 '@emnapi/runtime': 1.4.3
optional: true optional: true
'@img/sharp-win32-ia32@0.33.5': '@img/sharp-win32-ia32@0.33.5':
@@ -2452,10 +2452,10 @@ snapshots:
pvtsutils: 1.3.6 pvtsutils: 1.3.6
tslib: 2.8.1 tslib: 2.8.1
'@react-email/render@1.0.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': '@react-email/render@1.0.6(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
dependencies: dependencies:
html-to-text: 9.0.5 html-to-text: 9.0.5
prettier: 3.4.2 prettier: 3.5.3
react: 18.3.1 react: 18.3.1
react-dom: 18.3.1(react@18.3.1) react-dom: 18.3.1(react@18.3.1)
react-promise-suspense: 0.3.4 react-promise-suspense: 0.3.4
@@ -2818,14 +2818,14 @@ snapshots:
'@types/json-schema@7.0.15': {} '@types/json-schema@7.0.15': {}
'@typescript-eslint/eslint-plugin@8.29.1(@typescript-eslint/parser@8.29.1(eslint@9.18.0)(typescript@5.4.5))(eslint@9.18.0)(typescript@5.4.5)': '@typescript-eslint/eslint-plugin@8.31.0(@typescript-eslint/parser@8.31.0(eslint@9.18.0)(typescript@5.4.5))(eslint@9.18.0)(typescript@5.4.5)':
dependencies: dependencies:
'@eslint-community/regexpp': 4.12.1 '@eslint-community/regexpp': 4.12.1
'@typescript-eslint/parser': 8.29.1(eslint@9.18.0)(typescript@5.4.5) '@typescript-eslint/parser': 8.31.0(eslint@9.18.0)(typescript@5.4.5)
'@typescript-eslint/scope-manager': 8.29.1 '@typescript-eslint/scope-manager': 8.31.0
'@typescript-eslint/type-utils': 8.29.1(eslint@9.18.0)(typescript@5.4.5) '@typescript-eslint/type-utils': 8.31.0(eslint@9.18.0)(typescript@5.4.5)
'@typescript-eslint/utils': 8.29.1(eslint@9.18.0)(typescript@5.4.5) '@typescript-eslint/utils': 8.31.0(eslint@9.18.0)(typescript@5.4.5)
'@typescript-eslint/visitor-keys': 8.29.1 '@typescript-eslint/visitor-keys': 8.31.0
eslint: 9.18.0 eslint: 9.18.0
graphemer: 1.4.0 graphemer: 1.4.0
ignore: 5.3.2 ignore: 5.3.2
@@ -2835,27 +2835,27 @@ snapshots:
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
'@typescript-eslint/parser@8.29.1(eslint@9.18.0)(typescript@5.4.5)': '@typescript-eslint/parser@8.31.0(eslint@9.18.0)(typescript@5.4.5)':
dependencies: dependencies:
'@typescript-eslint/scope-manager': 8.29.1 '@typescript-eslint/scope-manager': 8.31.0
'@typescript-eslint/types': 8.29.1 '@typescript-eslint/types': 8.31.0
'@typescript-eslint/typescript-estree': 8.29.1(typescript@5.4.5) '@typescript-eslint/typescript-estree': 8.31.0(typescript@5.4.5)
'@typescript-eslint/visitor-keys': 8.29.1 '@typescript-eslint/visitor-keys': 8.31.0
debug: 4.4.0 debug: 4.4.0
eslint: 9.18.0 eslint: 9.18.0
typescript: 5.4.5 typescript: 5.4.5
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
'@typescript-eslint/scope-manager@8.29.1': '@typescript-eslint/scope-manager@8.31.0':
dependencies: dependencies:
'@typescript-eslint/types': 8.29.1 '@typescript-eslint/types': 8.31.0
'@typescript-eslint/visitor-keys': 8.29.1 '@typescript-eslint/visitor-keys': 8.31.0
'@typescript-eslint/type-utils@8.29.1(eslint@9.18.0)(typescript@5.4.5)': '@typescript-eslint/type-utils@8.31.0(eslint@9.18.0)(typescript@5.4.5)':
dependencies: dependencies:
'@typescript-eslint/typescript-estree': 8.29.1(typescript@5.4.5) '@typescript-eslint/typescript-estree': 8.31.0(typescript@5.4.5)
'@typescript-eslint/utils': 8.29.1(eslint@9.18.0)(typescript@5.4.5) '@typescript-eslint/utils': 8.31.0(eslint@9.18.0)(typescript@5.4.5)
debug: 4.4.0 debug: 4.4.0
eslint: 9.18.0 eslint: 9.18.0
ts-api-utils: 2.1.0(typescript@5.4.5) ts-api-utils: 2.1.0(typescript@5.4.5)
@@ -2863,12 +2863,12 @@ snapshots:
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
'@typescript-eslint/types@8.29.1': {} '@typescript-eslint/types@8.31.0': {}
'@typescript-eslint/typescript-estree@8.29.1(typescript@5.4.5)': '@typescript-eslint/typescript-estree@8.31.0(typescript@5.4.5)':
dependencies: dependencies:
'@typescript-eslint/types': 8.29.1 '@typescript-eslint/types': 8.31.0
'@typescript-eslint/visitor-keys': 8.29.1 '@typescript-eslint/visitor-keys': 8.31.0
debug: 4.4.0 debug: 4.4.0
fast-glob: 3.3.3 fast-glob: 3.3.3
is-glob: 4.0.3 is-glob: 4.0.3
@@ -2879,20 +2879,20 @@ snapshots:
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
'@typescript-eslint/utils@8.29.1(eslint@9.18.0)(typescript@5.4.5)': '@typescript-eslint/utils@8.31.0(eslint@9.18.0)(typescript@5.4.5)':
dependencies: dependencies:
'@eslint-community/eslint-utils': 4.5.1(eslint@9.18.0) '@eslint-community/eslint-utils': 4.6.1(eslint@9.18.0)
'@typescript-eslint/scope-manager': 8.29.1 '@typescript-eslint/scope-manager': 8.31.0
'@typescript-eslint/types': 8.29.1 '@typescript-eslint/types': 8.31.0
'@typescript-eslint/typescript-estree': 8.29.1(typescript@5.4.5) '@typescript-eslint/typescript-estree': 8.31.0(typescript@5.4.5)
eslint: 9.18.0 eslint: 9.18.0
typescript: 5.4.5 typescript: 5.4.5
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
'@typescript-eslint/visitor-keys@8.29.1': '@typescript-eslint/visitor-keys@8.31.0':
dependencies: dependencies:
'@typescript-eslint/types': 8.29.1 '@typescript-eslint/types': 8.31.0
eslint-visitor-keys: 4.2.0 eslint-visitor-keys: 4.2.0
abort-controller@3.0.0: abort-controller@3.0.0:
@@ -3015,7 +3015,7 @@ snapshots:
defu@6.1.4: {} defu@6.1.4: {}
detect-libc@2.0.3: detect-libc@2.0.4:
optional: true optional: true
dom-serializer@2.0.0: dom-serializer@2.0.0:
@@ -3038,33 +3038,33 @@ snapshots:
entities@4.5.0: {} entities@4.5.0: {}
esbuild@0.24.2: esbuild@0.25.2:
optionalDependencies: optionalDependencies:
'@esbuild/aix-ppc64': 0.24.2 '@esbuild/aix-ppc64': 0.25.2
'@esbuild/android-arm': 0.24.2 '@esbuild/android-arm': 0.25.2
'@esbuild/android-arm64': 0.24.2 '@esbuild/android-arm64': 0.25.2
'@esbuild/android-x64': 0.24.2 '@esbuild/android-x64': 0.25.2
'@esbuild/darwin-arm64': 0.24.2 '@esbuild/darwin-arm64': 0.25.2
'@esbuild/darwin-x64': 0.24.2 '@esbuild/darwin-x64': 0.25.2
'@esbuild/freebsd-arm64': 0.24.2 '@esbuild/freebsd-arm64': 0.25.2
'@esbuild/freebsd-x64': 0.24.2 '@esbuild/freebsd-x64': 0.25.2
'@esbuild/linux-arm': 0.24.2 '@esbuild/linux-arm': 0.25.2
'@esbuild/linux-arm64': 0.24.2 '@esbuild/linux-arm64': 0.25.2
'@esbuild/linux-ia32': 0.24.2 '@esbuild/linux-ia32': 0.25.2
'@esbuild/linux-loong64': 0.24.2 '@esbuild/linux-loong64': 0.25.2
'@esbuild/linux-mips64el': 0.24.2 '@esbuild/linux-mips64el': 0.25.2
'@esbuild/linux-ppc64': 0.24.2 '@esbuild/linux-ppc64': 0.25.2
'@esbuild/linux-riscv64': 0.24.2 '@esbuild/linux-riscv64': 0.25.2
'@esbuild/linux-s390x': 0.24.2 '@esbuild/linux-s390x': 0.25.2
'@esbuild/linux-x64': 0.24.2 '@esbuild/linux-x64': 0.25.2
'@esbuild/netbsd-arm64': 0.24.2 '@esbuild/netbsd-arm64': 0.25.2
'@esbuild/netbsd-x64': 0.24.2 '@esbuild/netbsd-x64': 0.25.2
'@esbuild/openbsd-arm64': 0.24.2 '@esbuild/openbsd-arm64': 0.25.2
'@esbuild/openbsd-x64': 0.24.2 '@esbuild/openbsd-x64': 0.25.2
'@esbuild/sunos-x64': 0.24.2 '@esbuild/sunos-x64': 0.25.2
'@esbuild/win32-arm64': 0.24.2 '@esbuild/win32-arm64': 0.25.2
'@esbuild/win32-ia32': 0.24.2 '@esbuild/win32-ia32': 0.25.2
'@esbuild/win32-x64': 0.24.2 '@esbuild/win32-x64': 0.25.2
escape-string-regexp@4.0.0: {} escape-string-regexp@4.0.0: {}
@@ -3079,7 +3079,7 @@ snapshots:
eslint@9.18.0: eslint@9.18.0:
dependencies: dependencies:
'@eslint-community/eslint-utils': 4.5.1(eslint@9.18.0) '@eslint-community/eslint-utils': 4.6.1(eslint@9.18.0)
'@eslint-community/regexpp': 4.12.1 '@eslint-community/regexpp': 4.12.1
'@eslint/config-array': 0.19.2 '@eslint/config-array': 0.19.2
'@eslint/core': 0.10.0 '@eslint/core': 0.10.0
@@ -3138,7 +3138,7 @@ snapshots:
exit-hook@2.2.1: {} exit-hook@2.2.1: {}
exsolve@1.0.4: {} exsolve@1.0.5: {}
fast-deep-equal@2.0.1: {} fast-deep-equal@2.0.1: {}
@@ -3210,7 +3210,7 @@ snapshots:
has-flag@4.0.0: {} has-flag@4.0.0: {}
hono@4.7.6: {} hono@4.7.7: {}
html-to-text@9.0.5: html-to-text@9.0.5:
dependencies: dependencies:
@@ -3314,7 +3314,7 @@ snapshots:
js-base64: 3.7.7 js-base64: 3.7.7
mime-types: 2.1.35 mime-types: 2.1.35
miniflare@4.20250409.0: miniflare@4.20250422.0:
dependencies: dependencies:
'@cspotcode/source-map-support': 0.8.1 '@cspotcode/source-map-support': 0.8.1
acorn: 8.14.0 acorn: 8.14.0
@@ -3323,7 +3323,7 @@ snapshots:
glob-to-regexp: 0.4.1 glob-to-regexp: 0.4.1
stoppable: 1.1.0 stoppable: 1.1.0
undici: 5.29.0 undici: 5.29.0
workerd: 1.20250409.0 workerd: 1.20250422.0
ws: 8.18.0 ws: 8.18.0
youch: 3.3.4 youch: 3.3.4
zod: 3.22.3 zod: 3.22.3
@@ -3397,7 +3397,7 @@ snapshots:
prelude-ls@1.2.1: {} prelude-ls@1.2.1: {}
prettier@3.4.2: {} prettier@3.5.3: {}
printable-characters@1.0.42: {} printable-characters@1.0.42: {}
@@ -3427,9 +3427,9 @@ snapshots:
regenerator-runtime@0.14.1: {} regenerator-runtime@0.14.1: {}
resend@4.2.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): resend@4.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
dependencies: dependencies:
'@react-email/render': 1.0.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-email/render': 1.0.6(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
transitivePeerDependencies: transitivePeerDependencies:
- react - react
- react-dom - react-dom
@@ -3461,7 +3461,7 @@ snapshots:
sharp@0.33.5: sharp@0.33.5:
dependencies: dependencies:
color: 4.2.3 color: 4.2.3
detect-libc: 2.0.3 detect-libc: 2.0.4
semver: 7.7.1 semver: 7.7.1
optionalDependencies: optionalDependencies:
'@img/sharp-darwin-arm64': 0.33.5 '@img/sharp-darwin-arm64': 0.33.5
@@ -3543,11 +3543,11 @@ snapshots:
dependencies: dependencies:
prelude-ls: 1.2.1 prelude-ls: 1.2.1
typescript-eslint@8.29.1(eslint@9.18.0)(typescript@5.4.5): typescript-eslint@8.31.0(eslint@9.18.0)(typescript@5.4.5):
dependencies: dependencies:
'@typescript-eslint/eslint-plugin': 8.29.1(@typescript-eslint/parser@8.29.1(eslint@9.18.0)(typescript@5.4.5))(eslint@9.18.0)(typescript@5.4.5) '@typescript-eslint/eslint-plugin': 8.31.0(@typescript-eslint/parser@8.31.0(eslint@9.18.0)(typescript@5.4.5))(eslint@9.18.0)(typescript@5.4.5)
'@typescript-eslint/parser': 8.29.1(eslint@9.18.0)(typescript@5.4.5) '@typescript-eslint/parser': 8.31.0(eslint@9.18.0)(typescript@5.4.5)
'@typescript-eslint/utils': 8.29.1(eslint@9.18.0)(typescript@5.4.5) '@typescript-eslint/utils': 8.31.0(eslint@9.18.0)(typescript@5.4.5)
eslint: 9.18.0 eslint: 9.18.0
typescript: 5.4.5 typescript: 5.4.5
transitivePeerDependencies: transitivePeerDependencies:
@@ -3564,7 +3564,7 @@ snapshots:
unenv@2.0.0-rc.15: unenv@2.0.0-rc.15:
dependencies: dependencies:
defu: 6.1.4 defu: 6.1.4
exsolve: 1.0.4 exsolve: 1.0.5
ohash: 2.0.11 ohash: 2.0.11
pathe: 2.0.3 pathe: 2.0.3
ufo: 1.6.1 ufo: 1.6.1
@@ -3588,28 +3588,28 @@ snapshots:
word-wrap@1.2.5: {} word-wrap@1.2.5: {}
worker-mailer@1.1.1: {} worker-mailer@1.1.3: {}
workerd@1.20250409.0: workerd@1.20250422.0:
optionalDependencies: optionalDependencies:
'@cloudflare/workerd-darwin-64': 1.20250409.0 '@cloudflare/workerd-darwin-64': 1.20250422.0
'@cloudflare/workerd-darwin-arm64': 1.20250409.0 '@cloudflare/workerd-darwin-arm64': 1.20250422.0
'@cloudflare/workerd-linux-64': 1.20250409.0 '@cloudflare/workerd-linux-64': 1.20250422.0
'@cloudflare/workerd-linux-arm64': 1.20250409.0 '@cloudflare/workerd-linux-arm64': 1.20250422.0
'@cloudflare/workerd-windows-64': 1.20250409.0 '@cloudflare/workerd-windows-64': 1.20250422.0
wrangler@4.10.0(@cloudflare/workers-types@4.20250412.0): wrangler@4.13.0(@cloudflare/workers-types@4.20250423.0):
dependencies: dependencies:
'@cloudflare/kv-asset-handler': 0.4.0 '@cloudflare/kv-asset-handler': 0.4.0
'@cloudflare/unenv-preset': 2.3.1(unenv@2.0.0-rc.15)(workerd@1.20250409.0) '@cloudflare/unenv-preset': 2.3.1(unenv@2.0.0-rc.15)(workerd@1.20250422.0)
blake3-wasm: 2.1.5 blake3-wasm: 2.1.5
esbuild: 0.24.2 esbuild: 0.25.2
miniflare: 4.20250409.0 miniflare: 4.20250422.0
path-to-regexp: 6.3.0 path-to-regexp: 6.3.0
unenv: 2.0.0-rc.15 unenv: 2.0.0-rc.15
workerd: 1.20250409.0 workerd: 1.20250422.0
optionalDependencies: optionalDependencies:
'@cloudflare/workers-types': 4.20250412.0 '@cloudflare/workers-types': 4.20250423.0
fsevents: 2.3.3 fsevents: 2.3.3
sharp: 0.33.5 sharp: 0.33.5
transitivePeerDependencies: transitivePeerDependencies:
+39
View File
@@ -0,0 +1,39 @@
import { Context } from "hono";
import { HonoCustomType } from "../types";
import { handleListQuery } from "../common";
export default {
getMails: async (c: Context<HonoCustomType>) => {
const { address, limit, offset, keyword } = c.req.query();
const addressQuery = address ? `address = ?` : "";
const addressParams = address ? [address] : [];
const keywordQuery = keyword ? `raw like ?` : "";
const keywordParams = keyword ? [`%${keyword}%`] : [];
const filterQuerys = [addressQuery, keywordQuery].filter((item) => item).join(" and ");
const finalQuery = filterQuerys.length > 0 ? `where ${filterQuerys}` : "";
const filterParams = [...addressParams, ...keywordParams]
return await handleListQuery(c,
`SELECT * FROM raw_mails ${finalQuery}`,
`SELECT count(*) as count FROM raw_mails ${finalQuery}`,
filterParams, limit, offset
);
},
getUnknowMails: async (c: Context<HonoCustomType>) => {
const { limit, offset } = c.req.query();
return await handleListQuery(c,
`SELECT * FROM raw_mails where address NOT IN (select name from address) `,
`SELECT count(*) as count FROM raw_mails`
+ ` where address NOT IN (select name from address) `,
[], limit, offset
);
},
deleteMail: async (c: Context<HonoCustomType>) => {
const { id } = c.req.param();
const { success } = await c.env.DB.prepare(
`DELETE FROM raw_mails WHERE id = ? `
).bind(id).run();
return c.json({
success: success
})
}
}
+9 -3
View File
@@ -6,6 +6,7 @@ import { UserSettings, GeoData, UserInfo } from "../models";
import { handleListQuery } from '../common' import { handleListQuery } from '../common'
import { HonoCustomType } from '../types'; import { HonoCustomType } from '../types';
import UserBindAddressModule from '../user_api/bind_address'; import UserBindAddressModule from '../user_api/bind_address';
import i18n from '../i18n';
export default { export default {
getSetting: async (c: Context<HonoCustomType>) => { getSetting: async (c: Context<HonoCustomType>) => {
@@ -90,7 +91,8 @@ export default {
}, },
deleteUser: async (c: Context<HonoCustomType>) => { deleteUser: async (c: Context<HonoCustomType>) => {
const { user_id } = c.req.param(); const { user_id } = c.req.param();
if (!user_id) return c.text("Invalid user_id", 400); const msgs = i18n.getMessagesbyContext(c);
if (!user_id) return c.text(msgs.UserNotFoundMsg, 400);
const { success } = await c.env.DB.prepare( const { success } = await c.env.DB.prepare(
`DELETE FROM users WHERE id = ?` `DELETE FROM users WHERE id = ?`
).bind(user_id).run(); ).bind(user_id).run();
@@ -105,7 +107,8 @@ export default {
resetPassword: async (c: Context<HonoCustomType>) => { resetPassword: async (c: Context<HonoCustomType>) => {
const { user_id } = c.req.param(); const { user_id } = c.req.param();
const { password } = await c.req.json(); const { password } = await c.req.json();
if (!user_id) return c.text("Invalid user_id", 400); const msgs = i18n.getMessagesbyContext(c);
if (!user_id) return c.text(msgs.UserNotFoundMsg, 400);
try { try {
checkUserPassword(password); checkUserPassword(password);
const { success } = await c.env.DB.prepare( const { success } = await c.env.DB.prepare(
@@ -159,6 +162,9 @@ export default {
}, },
getBindedAddresses: async (c: Context<HonoCustomType>) => { getBindedAddresses: async (c: Context<HonoCustomType>) => {
const { user_id } = c.req.param(); const { user_id } = c.req.param();
return await UserBindAddressModule.getBindedAddressesById(c, user_id); const results = await UserBindAddressModule.getBindedAddressesById(c, user_id);
return c.json({
results: results,
});
}, },
} }
+5 -48
View File
@@ -12,6 +12,7 @@ import webhook_settings from './webhook_settings'
import mail_webhook_settings from './mail_webhook_settings' import mail_webhook_settings from './mail_webhook_settings'
import oauth2_settings from './oauth2_settings' import oauth2_settings from './oauth2_settings'
import worker_config from './worker_config' import worker_config from './worker_config'
import admin_mail_api from './admin_mail_api'
import { sendMailbyAdmin } from './send_mail' import { sendMailbyAdmin } from './send_mail'
export const api = new Hono<HonoCustomType>() export const api = new Hono<HonoCustomType>()
@@ -101,54 +102,10 @@ api.get('/admin/show_password/:id', async (c) => {
}) })
}) })
api.get('/admin/mails', async (c) => { // mail api
const { address, limit, offset, keyword } = c.req.query(); api.get('/admin/mails', admin_mail_api.getMails);
if (address && keyword) { api.get('/admin/mails_unknow', admin_mail_api.getUnknowMails);
return await handleListQuery(c, api.delete('/admin/mails/:id', admin_mail_api.deleteMail)
`SELECT * FROM raw_mails where address = ? and raw like ? `,
`SELECT count(*) as count FROM raw_mails where address = ? and raw like ? `,
[address, `%${keyword}%`], limit, offset
);
} else if (keyword) {
return await handleListQuery(c,
`SELECT * FROM raw_mails where raw like ? `,
`SELECT count(*) as count FROM raw_mails where raw like ? `,
[`%${keyword}%`], limit, offset
);
} else if (address) {
return await handleListQuery(c,
`SELECT * FROM raw_mails where address = ? `,
`SELECT count(*) as count FROM raw_mails where address = ? `,
[address], limit, offset
);
} else {
return await handleListQuery(c,
`SELECT * FROM raw_mails `,
`SELECT count(*) as count FROM raw_mails `,
[], limit, offset
);
}
});
api.get('/admin/mails_unknow', async (c) => {
const { limit, offset } = c.req.query();
return await handleListQuery(c,
`SELECT * FROM raw_mails where address NOT IN (select name from address) `,
`SELECT count(*) as count FROM raw_mails`
+ ` where address NOT IN (select name from address) `,
[], limit, offset
);
});
api.delete('/admin/mails/:id', async (c) => {
const { id } = c.req.param();
const { success } = await c.env.DB.prepare(
`DELETE FROM raw_mails WHERE id = ? `
).bind(id).run();
return c.json({
success: success
})
})
api.get('/admin/address_sender', async (c) => { api.get('/admin/address_sender', async (c) => {
const { address, limit, offset } = c.req.query(); const { address, limit, offset } = c.req.query();
+1 -1
View File
@@ -1,5 +1,5 @@
export const CONSTANTS = { export const CONSTANTS = {
VERSION: 'v' + '0.9.1', VERSION: 'v' + '0.10.9',
// DB settings // DB settings
ADDRESS_BLOCK_LIST_KEY: 'address_block_list', ADDRESS_BLOCK_LIST_KEY: 'address_block_list',
+13
View File
@@ -1,6 +1,8 @@
import { LocaleMessages } from "./type"; import { LocaleMessages } from "./type";
import zh from "./zh"; import zh from "./zh";
import en from "./en"; import en from "./en";
import { HonoCustomType } from "../types";
import { Context } from "hono";
export default { export default {
getMessages: ( getMessages: (
@@ -10,6 +12,17 @@ export default {
if (locale === "en") return en; if (locale === "en") return en;
if (locale === "zh") return zh; if (locale === "zh") return zh;
// fallback language
return en;
},
getMessagesbyContext: (
c: Context<HonoCustomType>
): LocaleMessages => {
const locale = c.get("lang") || c.env.DEFAULT_LANG;
// multi-language support
if (locale === "en") return en;
if (locale === "zh") return zh;
// fallback language // fallback language
return en; return en;
} }
+31 -8
View File
@@ -6,6 +6,7 @@ import { UserSettings } from "../models";
import { getJsonSetting } from "../utils" import { getJsonSetting } from "../utils"
import { CONSTANTS } from "../constants"; import { CONSTANTS } from "../constants";
import { unbindTelegramByAddress } from '../telegram_api/common'; import { unbindTelegramByAddress } from '../telegram_api/common';
import i18n from '../i18n';
const UserBindAddressModule = { const UserBindAddressModule = {
bind: async (c: Context<HonoCustomType>) => { bind: async (c: Context<HonoCustomType>) => {
@@ -102,13 +103,30 @@ const UserBindAddressModule = {
}, },
getBindedAddresses: async (c: Context<HonoCustomType>) => { getBindedAddresses: async (c: Context<HonoCustomType>) => {
const { user_id } = c.get("userPayload"); const { user_id } = c.get("userPayload");
return await UserBindAddressModule.getBindedAddressesById(c, user_id); const results = await UserBindAddressModule.getBindedAddressesById(c, user_id);
return c.json({
results: results,
});
},
getBindedAddressListById: async (
c: Context<HonoCustomType>, user_id: number | string
): Promise<string[]> => {
const bindedAddressList = await UserBindAddressModule.getBindedAddressesById(c, user_id);
return bindedAddressList.map((item) => item.name);
}, },
getBindedAddressesById: async ( getBindedAddressesById: async (
c: Context<HonoCustomType>, user_id: number | string c: Context<HonoCustomType>, user_id: number | string
) => { ): Promise<{
id: number;
name: string;
mail_count: number;
send_count: number;
created_at: string;
updated_at: string;
}[]> => {
const msgs = i18n.getMessagesbyContext(c);
if (!user_id) { if (!user_id) {
return c.text("No user token", 400) throw new Error(msgs.UserNotFoundMsg);
} }
// select binded address // select binded address
const { results } = await c.env.DB.prepare( const { results } = await c.env.DB.prepare(
@@ -120,10 +138,15 @@ const UserBindAddressModule = {
+ ` ON ua.address_id = a.id ` + ` ON ua.address_id = a.id `
+ ` WHERE ua.user_id = ?` + ` WHERE ua.user_id = ?`
+ ` ORDER BY a.id DESC` + ` ORDER BY a.id DESC`
).bind(user_id).all(); ).bind(user_id).all<{
return c.json({ id: number;
results: results, name: string;
}) mail_count: number;
send_count: number;
created_at: string;
updated_at: string;
}>();
return results || [];
}, },
getBindedAddressJwt: async (c: Context<HonoCustomType>) => { getBindedAddressJwt: async (c: Context<HonoCustomType>) => {
const { address_id } = c.req.param(); const { address_id } = c.req.param();
@@ -216,7 +239,7 @@ const UserBindAddressModule = {
throw new Error("Failed to create address") throw new Error("Failed to create address")
} }
// find new address id // find new address id
let new_address_id = await c.env.DB.prepare( const new_address_id = await c.env.DB.prepare(
`SELECT id FROM address WHERE name = ?` `SELECT id FROM address WHERE name = ?`
).bind(address).first<number | null | undefined>("id"); ).bind(address).first<number | null | undefined>("id");
if (!new_address_id) { if (!new_address_id) {
+5
View File
@@ -6,6 +6,7 @@ import user from './user';
import bind_address from './bind_address'; import bind_address from './bind_address';
import passkey from './passkey'; import passkey from './passkey';
import oauth2 from './oauth2'; import oauth2 from './oauth2';
import user_mail_api from './user_mail_api';
export const api = new Hono<HonoCustomType>(); export const api = new Hono<HonoCustomType>();
@@ -13,6 +14,10 @@ export const api = new Hono<HonoCustomType>();
api.get('/user_api/open_settings', settings.openSettings); api.get('/user_api/open_settings', settings.openSettings);
api.get('/user_api/settings', settings.settings); api.get('/user_api/settings', settings.settings);
// mail api
api.get('/user_api/mails', user_mail_api.getMails);
api.delete('/user_api/mails/:id', user_mail_api.deleteMail);
// user api // user api
api.post('/user_api/login', user.login); api.post('/user_api/login', user.login);
api.post('/user_api/verify_code', user.verifyCode); api.post('/user_api/verify_code', user.verifyCode);
+43
View File
@@ -0,0 +1,43 @@
import { Context } from "hono";
import { handleListQuery } from "../common";
import { HonoCustomType } from "../types";
import UserBindAddressModule from "./bind_address";
export default {
getMails: async (c: Context<HonoCustomType>) => {
const { user_id } = c.get("userPayload");
const { address, limit, offset, keyword } = c.req.query();
const bindedAddressList = await UserBindAddressModule.getBindedAddressListById(c, user_id);
const addressList = address ? bindedAddressList.filter((item) => item == address) : bindedAddressList;
const addressQuery = `address IN (${addressList.map(() => "?").join(",")})`;
const addressParams = addressList;
const keywordQuery = keyword ? `raw like ?` : "";
const keywordParams = keyword ? [`%${keyword}%`] : [];
// user must have at least one binded address to query mails
if (addressList.length <= 0) {
return c.json({ results: [], count: 0 });
}
const filterQuerys = [addressQuery, keywordQuery].filter((item) => item).join(" and ");
const finalQuery = filterQuerys.length > 0 ? `where ${filterQuerys}` : "";
const filterParams = [...addressParams, ...keywordParams]
return await handleListQuery(c,
`SELECT * FROM raw_mails ${finalQuery}`,
`SELECT count(*) as count FROM raw_mails ${finalQuery}`,
filterParams, limit, offset
);
},
deleteMail: async (c: Context<HonoCustomType>) => {
const { id } = c.req.param();
const { user_id } = c.get("userPayload");
const bindedAddressList = await UserBindAddressModule.getBindedAddressListById(c, user_id);
const { success } = await c.env.DB.prepare(
`DELETE FROM raw_mails WHERE id = ?`
+ ` and address IN (${bindedAddressList.map(() => "?").join(",")})`
).bind(id, ...bindedAddressList).run();
return c.json({
success: success
})
}
}