updates
This commit is contained in:
parent
cae2a37783
commit
b263580117
|
|
@ -13,6 +13,6 @@
|
|||
"devDependencies": {
|
||||
"@cloudflare/workers-types": "^4.20260617.1",
|
||||
"typescript": "^6.0.3",
|
||||
"wrangler": "^4.101.0"
|
||||
"wrangler": "^4.103.0"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
308
pnpm-lock.yaml
308
pnpm-lock.yaml
|
|
@ -15,8 +15,8 @@ importers:
|
|||
specifier: ^6.0.3
|
||||
version: 6.0.3
|
||||
wrangler:
|
||||
specifier: ^4.101.0
|
||||
version: 4.101.0(@cloudflare/workers-types@4.20260617.1)
|
||||
specifier: ^4.103.0
|
||||
version: 4.103.0(@cloudflare/workers-types@4.20260617.1)
|
||||
|
||||
packages:
|
||||
|
||||
|
|
@ -33,32 +33,32 @@ packages:
|
|||
workerd:
|
||||
optional: true
|
||||
|
||||
'@cloudflare/workerd-darwin-64@1.20260616.1':
|
||||
resolution: {integrity: sha512-8QaDRQABkwkwoeviNiyScol7EQgXfGsPNSyUn52GiXObthY4XPiokoJsgDSDNcAelHjEvDLmdvQBHPK8YvGn4A==}
|
||||
'@cloudflare/workerd-darwin-64@1.20260617.1':
|
||||
resolution: {integrity: sha512-jWwmgEVVWbsHNrLSNXzwjJaH90VzRxq1cWkQFUidxyeUPnMxemeNE8I9qFAfrpzGgE11e9sKDcE3ettJW08swQ==}
|
||||
engines: {node: '>=16'}
|
||||
cpu: [x64]
|
||||
os: [darwin]
|
||||
|
||||
'@cloudflare/workerd-darwin-arm64@1.20260616.1':
|
||||
resolution: {integrity: sha512-xEhiZQ62CBJ+vyKSmM13rkK/wB1kLP5sKFkF3+P+3R/c2bmnSG3Vcd5FfXUu9V0PdC+KlR02nByvZjqEw2N6Ag==}
|
||||
'@cloudflare/workerd-darwin-arm64@1.20260617.1':
|
||||
resolution: {integrity: sha512-LHH7b565g9znfCUOkwbec6FG2rmRbsgCy6aJiU9KN662mNheWl5sw/iKleiFSiljPKQQP3HkjnC/NSkdgi/aSA==}
|
||||
engines: {node: '>=16'}
|
||||
cpu: [arm64]
|
||||
os: [darwin]
|
||||
|
||||
'@cloudflare/workerd-linux-64@1.20260616.1':
|
||||
resolution: {integrity: sha512-p5laSYPiRUMHaLkneaZ9ZfIkNpmEnGFwgYmXtfcHJutTfEd8o3IBnsUVRSbPL+phcshKqmapLsQSxDEX6WSFfA==}
|
||||
'@cloudflare/workerd-linux-64@1.20260617.1':
|
||||
resolution: {integrity: sha512-FMnaAKXe4Cfd8TQurCVd9fs2XQVBFRCsP+Id/SRdUv89MlwYu9zXfoyx6BxM+brPTIUK38SHbo8iaxiwzLi9JQ==}
|
||||
engines: {node: '>=16'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
|
||||
'@cloudflare/workerd-linux-arm64@1.20260616.1':
|
||||
resolution: {integrity: sha512-XQ7GonEl8ORvbz5fhe8Eyw2t/j09Li0KbXJxaldA318E+syF+PPTc4IRQudgqPWzzdzkH5nF7PuMOGySLSjFFw==}
|
||||
'@cloudflare/workerd-linux-arm64@1.20260617.1':
|
||||
resolution: {integrity: sha512-MRoifFYcqbxxIIQy7PqO5tFY/qPFSnjXzakWl0sO93l+HLyG35jRAgOi6jfqa4kBxc7gKKtH861DcewjxUfkjA==}
|
||||
engines: {node: '>=16'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
|
||||
'@cloudflare/workerd-windows-64@1.20260616.1':
|
||||
resolution: {integrity: sha512-RaDVF9bSbPiPTq6vHYrgnv1TcQEcYnOr0WB3hWJ4yg2fBfpi2ygU6cYPuFeDwyFE9aPW5S6FBAkNmpKYueK4DQ==}
|
||||
'@cloudflare/workerd-windows-64@1.20260617.1':
|
||||
resolution: {integrity: sha512-rgBV9wQrv0OSKgCTTbhFUFY3sLGNANZ88aqaLvtmEn2gmbFVb1J4PDGochVUdB7NSEp4D/ghHva6/8SZmbONpw==}
|
||||
engines: {node: '>=16'}
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
|
|
@ -73,158 +73,158 @@ packages:
|
|||
'@emnapi/runtime@1.11.1':
|
||||
resolution: {integrity: sha512-vgj7R3y3Wgx24IQaGPA/R6YFXLHVMOZ0uVEyIQPaWs+rd1AzfEMXlAC22FYwO1XkKR6NPsq7mUandH8oIRdZFw==}
|
||||
|
||||
'@esbuild/aix-ppc64@0.27.3':
|
||||
resolution: {integrity: sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg==}
|
||||
'@esbuild/aix-ppc64@0.28.1':
|
||||
resolution: {integrity: sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [ppc64]
|
||||
os: [aix]
|
||||
|
||||
'@esbuild/android-arm64@0.27.3':
|
||||
resolution: {integrity: sha512-YdghPYUmj/FX2SYKJ0OZxf+iaKgMsKHVPF1MAq/P8WirnSpCStzKJFjOjzsW0QQ7oIAiccHdcqjbHmJxRb/dmg==}
|
||||
'@esbuild/android-arm64@0.28.1':
|
||||
resolution: {integrity: sha512-34EGEbCIAgosYz6goLcopX6Mo7NyGv9tfwEM2/7Ce2VcVRk568iSvniGWcUXIy7wEDR1wzolcxcriFVrWYcwBg==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm64]
|
||||
os: [android]
|
||||
|
||||
'@esbuild/android-arm@0.27.3':
|
||||
resolution: {integrity: sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA==}
|
||||
'@esbuild/android-arm@0.28.1':
|
||||
resolution: {integrity: sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm]
|
||||
os: [android]
|
||||
|
||||
'@esbuild/android-x64@0.27.3':
|
||||
resolution: {integrity: sha512-IN/0BNTkHtk8lkOM8JWAYFg4ORxBkZQf9zXiEOfERX/CzxW3Vg1ewAhU7QSWQpVIzTW+b8Xy+lGzdYXV6UZObQ==}
|
||||
'@esbuild/android-x64@0.28.1':
|
||||
resolution: {integrity: sha512-dbwY7ltSMDWsRatcRpCnES4F+im88OCUgGZjy52shC7GqHRE/cYlxNbB4Z4UpJswpcc4Qxd2oE/ufM0p61IKng==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [x64]
|
||||
os: [android]
|
||||
|
||||
'@esbuild/darwin-arm64@0.27.3':
|
||||
resolution: {integrity: sha512-Re491k7ByTVRy0t3EKWajdLIr0gz2kKKfzafkth4Q8A5n1xTHrkqZgLLjFEHVD+AXdUGgQMq+Godfq45mGpCKg==}
|
||||
'@esbuild/darwin-arm64@0.28.1':
|
||||
resolution: {integrity: sha512-TZbWkQY7kvTAXbXUT7uVACR5cMHsDiSz9z7ZKAX/RTq/WJEk3QyRr0wZpNhBDX+/0CtdqUIJlOiodQcta6tY3Q==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm64]
|
||||
os: [darwin]
|
||||
|
||||
'@esbuild/darwin-x64@0.27.3':
|
||||
resolution: {integrity: sha512-vHk/hA7/1AckjGzRqi6wbo+jaShzRowYip6rt6q7VYEDX4LEy1pZfDpdxCBnGtl+A5zq8iXDcyuxwtv3hNtHFg==}
|
||||
'@esbuild/darwin-x64@0.28.1':
|
||||
resolution: {integrity: sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [x64]
|
||||
os: [darwin]
|
||||
|
||||
'@esbuild/freebsd-arm64@0.27.3':
|
||||
resolution: {integrity: sha512-ipTYM2fjt3kQAYOvo6vcxJx3nBYAzPjgTCk7QEgZG8AUO3ydUhvelmhrbOheMnGOlaSFUoHXB6un+A7q4ygY9w==}
|
||||
'@esbuild/freebsd-arm64@0.28.1':
|
||||
resolution: {integrity: sha512-wG2EA8ENdEI0qhkSZMjfqrdY+ziCYCPMmtZjjIwOmXFjmyzEHn+UUxk5of+SYsjtfs3VpnlC7QLzSI5hY/rOAw==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm64]
|
||||
os: [freebsd]
|
||||
|
||||
'@esbuild/freebsd-x64@0.27.3':
|
||||
resolution: {integrity: sha512-dDk0X87T7mI6U3K9VjWtHOXqwAMJBNN2r7bejDsc+j03SEjtD9HrOl8gVFByeM0aJksoUuUVU9TBaZa2rgj0oA==}
|
||||
'@esbuild/freebsd-x64@0.28.1':
|
||||
resolution: {integrity: sha512-i7dZ9vQgnvSCzi/rYCXNgtF/U+eKZNJBzu3eTQbRgHnM7tNSizLOkRFAl3qzVc/Op/u5YkHHa4pf/3DOYHthLQ==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [x64]
|
||||
os: [freebsd]
|
||||
|
||||
'@esbuild/linux-arm64@0.27.3':
|
||||
resolution: {integrity: sha512-sZOuFz/xWnZ4KH3YfFrKCf1WyPZHakVzTiqji3WDc0BCl2kBwiJLCXpzLzUBLgmp4veFZdvN5ChW4Eq/8Fc2Fg==}
|
||||
'@esbuild/linux-arm64@0.28.1':
|
||||
resolution: {integrity: sha512-yHs+0uc8+nvEAfAfxrWQKK5peSNzBc4PegcMO0EJ2hT71uA7vB8Ihg2e77R2P7SG5uYjPbHlLLmve4LLLRCf0g==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-arm@0.27.3':
|
||||
resolution: {integrity: sha512-s6nPv2QkSupJwLYyfS+gwdirm0ukyTFNl3KTgZEAiJDd+iHZcbTPPcWCcRYH+WlNbwChgH2QkE9NSlNrMT8Gfw==}
|
||||
'@esbuild/linux-arm@0.28.1':
|
||||
resolution: {integrity: sha512-qVXBOHQS+d5Y722GwJzJUtOLlX7km3CraOaGormF1pDtPd2C/l1SHRPgjLunLGe51Sh5YYWKMFDyV4SxgMQYTQ==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-ia32@0.27.3':
|
||||
resolution: {integrity: sha512-yGlQYjdxtLdh0a3jHjuwOrxQjOZYD/C9PfdbgJJF3TIZWnm/tMd/RcNiLngiu4iwcBAOezdnSLAwQDPqTmtTYg==}
|
||||
'@esbuild/linux-ia32@0.28.1':
|
||||
resolution: {integrity: sha512-d1z4ZuP0ajrfz/FhGT4vv278rX8KnPPJx8i5+AtK7TYbx9Le9F1hyzurZpkEyjkGa9dUGhQow4C1NmeGvqxN2w==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [ia32]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-loong64@0.27.3':
|
||||
resolution: {integrity: sha512-WO60Sn8ly3gtzhyjATDgieJNet/KqsDlX5nRC5Y3oTFcS1l0KWba+SEa9Ja1GfDqSF1z6hif/SkpQJbL63cgOA==}
|
||||
'@esbuild/linux-loong64@0.28.1':
|
||||
resolution: {integrity: sha512-M5sRjUVZrkm1OAPR3dlOYzNmN+loZKGVi1VUQGrwuqLcbR6qeAz+famMhjASeH3YVKvZz+zT1jlh/keC3Rj/lg==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [loong64]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-mips64el@0.27.3':
|
||||
resolution: {integrity: sha512-APsymYA6sGcZ4pD6k+UxbDjOFSvPWyZhjaiPyl/f79xKxwTnrn5QUnXR5prvetuaSMsb4jgeHewIDCIWljrSxw==}
|
||||
'@esbuild/linux-mips64el@0.28.1':
|
||||
resolution: {integrity: sha512-mRObBZeHh2OxcBFPWE/FjylkRgZdYuiTR3vaTozquCGOH14iP9oN4x4Ge81CoIDYQrXmIxpFumJBu5MtZpnQJQ==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [mips64el]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-ppc64@0.27.3':
|
||||
resolution: {integrity: sha512-eizBnTeBefojtDb9nSh4vvVQ3V9Qf9Df01PfawPcRzJH4gFSgrObw+LveUyDoKU3kxi5+9RJTCWlj4FjYXVPEA==}
|
||||
'@esbuild/linux-ppc64@0.28.1':
|
||||
resolution: {integrity: sha512-slScBsMAb3GFDcdrCgLwZtPYRoH2H/youv10QiZyRjmsP48fznoveWytSgCI/R0ZcUgpc0ZhIUEx6LHts8yrfQ==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [ppc64]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-riscv64@0.27.3':
|
||||
resolution: {integrity: sha512-3Emwh0r5wmfm3ssTWRQSyVhbOHvqegUDRd0WhmXKX2mkHJe1SFCMJhagUleMq+Uci34wLSipf8Lagt4LlpRFWQ==}
|
||||
'@esbuild/linux-riscv64@0.28.1':
|
||||
resolution: {integrity: sha512-kw0owk1o0GFETUJyW0jc0G4Yzs0BHZn0JDZ8JRT088vjJYX777BAs1fDGxAC+q831qOs2DTC96mNsG2opdfyyQ==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [riscv64]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-s390x@0.27.3':
|
||||
resolution: {integrity: sha512-pBHUx9LzXWBc7MFIEEL0yD/ZVtNgLytvx60gES28GcWMqil8ElCYR4kvbV2BDqsHOvVDRrOxGySBM9Fcv744hw==}
|
||||
'@esbuild/linux-s390x@0.28.1':
|
||||
resolution: {integrity: sha512-/lAIjX8aYFRByhh6L5rYtPEDRqa9de/4V/juOXcta5frjvzXO4/sqEtyytse0g3zZFuWu5cDN0MkLz2qRDD2Ag==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [s390x]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-x64@0.27.3':
|
||||
resolution: {integrity: sha512-Czi8yzXUWIQYAtL/2y6vogER8pvcsOsk5cpwL4Gk5nJqH5UZiVByIY8Eorm5R13gq+DQKYg0+JyQoytLQas4dA==}
|
||||
'@esbuild/linux-x64@0.28.1':
|
||||
resolution: {integrity: sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/netbsd-arm64@0.27.3':
|
||||
resolution: {integrity: sha512-sDpk0RgmTCR/5HguIZa9n9u+HVKf40fbEUt+iTzSnCaGvY9kFP0YKBWZtJaraonFnqef5SlJ8/TiPAxzyS+UoA==}
|
||||
'@esbuild/netbsd-arm64@0.28.1':
|
||||
resolution: {integrity: sha512-oks0DYbLwWMmaakTsCb+zL4E+aHRVLom9IJZOAthMQEPiQmydXHkziYEsGYRx0uNV/IjEKGAV941JzH02pflqw==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm64]
|
||||
os: [netbsd]
|
||||
|
||||
'@esbuild/netbsd-x64@0.27.3':
|
||||
resolution: {integrity: sha512-P14lFKJl/DdaE00LItAukUdZO5iqNH7+PjoBm+fLQjtxfcfFE20Xf5CrLsmZdq5LFFZzb5JMZ9grUwvtVYzjiA==}
|
||||
'@esbuild/netbsd-x64@0.28.1':
|
||||
resolution: {integrity: sha512-aeL6lAnN89Hz43Mlh1G8ARasbuoYvSITDEx0tHh5b7jJnHcssqgjy9Yx430GDpmCa6OyrKoS0aNRjKundRizGg==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [x64]
|
||||
os: [netbsd]
|
||||
|
||||
'@esbuild/openbsd-arm64@0.27.3':
|
||||
resolution: {integrity: sha512-AIcMP77AvirGbRl/UZFTq5hjXK+2wC7qFRGoHSDrZ5v5b8DK/GYpXW3CPRL53NkvDqb9D+alBiC/dV0Fb7eJcw==}
|
||||
'@esbuild/openbsd-arm64@0.28.1':
|
||||
resolution: {integrity: sha512-MEFJe5C3R8pwXdZ5Y21oo6m7ePiS0d9pWucn99O/wvyJZChoIQKrQDxKrGeW8F5+T0okTHesAmDeiHDTIq0V/Q==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm64]
|
||||
os: [openbsd]
|
||||
|
||||
'@esbuild/openbsd-x64@0.27.3':
|
||||
resolution: {integrity: sha512-DnW2sRrBzA+YnE70LKqnM3P+z8vehfJWHXECbwBmH/CU51z6FiqTQTHFenPlHmo3a8UgpLyH3PT+87OViOh1AQ==}
|
||||
'@esbuild/openbsd-x64@0.28.1':
|
||||
resolution: {integrity: sha512-i/ZLIOafE0Z8cI/XANJAixoJL/uRAoS2xOA3rb0xN+KK0K177cMAsQYkzHtBrtMXAKuAc7HGgcWiZ/sRC1Nxgw==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [x64]
|
||||
os: [openbsd]
|
||||
|
||||
'@esbuild/openharmony-arm64@0.27.3':
|
||||
resolution: {integrity: sha512-NinAEgr/etERPTsZJ7aEZQvvg/A6IsZG/LgZy+81wON2huV7SrK3e63dU0XhyZP4RKGyTm7aOgmQk0bGp0fy2g==}
|
||||
'@esbuild/openharmony-arm64@0.28.1':
|
||||
resolution: {integrity: sha512-ge+Z7EXFNt2BO1oAMsVpiQ8EwndV9i1xXerAeTIK7AtPs3bKFXQM7nlRxDSIUIMeueR1CNXxqztLzdNeReKBJg==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm64]
|
||||
os: [openharmony]
|
||||
|
||||
'@esbuild/sunos-x64@0.27.3':
|
||||
resolution: {integrity: sha512-PanZ+nEz+eWoBJ8/f8HKxTTD172SKwdXebZ0ndd953gt1HRBbhMsaNqjTyYLGLPdoWHy4zLU7bDVJztF5f3BHA==}
|
||||
'@esbuild/sunos-x64@0.28.1':
|
||||
resolution: {integrity: sha512-BEjgtECkL3vY+SaSQ6nzVfiALUeFxpawyp8Jmf5PtYhf1Ug40N1h/hxlhts+f1FvSvarEigdxS3BlSMI2PJLcQ==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [x64]
|
||||
os: [sunos]
|
||||
|
||||
'@esbuild/win32-arm64@0.27.3':
|
||||
resolution: {integrity: sha512-B2t59lWWYrbRDw/tjiWOuzSsFh1Y/E95ofKz7rIVYSQkUYBjfSgf6oeYPNWHToFRr2zx52JKApIcAS/D5TUBnA==}
|
||||
'@esbuild/win32-arm64@0.28.1':
|
||||
resolution: {integrity: sha512-lCv9eK/H6ZJWbE7bh2nw54CZ9M2nupBxJcTsdk/QQnWkdSjKGuxmmH8/GWrlT1eMmZfn4dGcCjRte397WqfQXA==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm64]
|
||||
os: [win32]
|
||||
|
||||
'@esbuild/win32-ia32@0.27.3':
|
||||
resolution: {integrity: sha512-QLKSFeXNS8+tHW7tZpMtjlNb7HKau0QDpwm49u0vUp9y1WOF+PEzkU84y9GqYaAVW8aH8f3GcBck26jh54cX4Q==}
|
||||
'@esbuild/win32-ia32@0.28.1':
|
||||
resolution: {integrity: sha512-zvb/mB2bSCoJOpoCBgYKKpX6YM6mJBlBUVUtVj41DlZJVEB6/0CKlRYxP5wWl1C1ILiCoAU5wZZ4q1P3qeS6Eg==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [ia32]
|
||||
os: [win32]
|
||||
|
||||
'@esbuild/win32-x64@0.27.3':
|
||||
resolution: {integrity: sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA==}
|
||||
'@esbuild/win32-x64@0.28.1':
|
||||
resolution: {integrity: sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
|
|
@ -422,8 +422,8 @@ packages:
|
|||
error-stack-parser-es@1.0.5:
|
||||
resolution: {integrity: sha512-5qucVt2XcuGMcEGgWI7i+yZpmpByQ8J1lHhcL7PwqCwu9FPP3VUXzT4ltHe5i2z9dePwEHcDVOAfSnHsOlCXRA==}
|
||||
|
||||
esbuild@0.27.3:
|
||||
resolution: {integrity: sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg==}
|
||||
esbuild@0.28.1:
|
||||
resolution: {integrity: sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw==}
|
||||
engines: {node: '>=18'}
|
||||
hasBin: true
|
||||
|
||||
|
|
@ -436,8 +436,8 @@ packages:
|
|||
resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==}
|
||||
engines: {node: '>=6'}
|
||||
|
||||
miniflare@4.20260616.0:
|
||||
resolution: {integrity: sha512-cEpzoNgSWjedzYmhJvttUPmL4Jk6nSzzeNNi118T5zwnmYP9fnM8UXwFU/Qa/1qoQ4SzGqtM1Q7tinHvHvIGtw==}
|
||||
miniflare@4.20260617.1:
|
||||
resolution: {integrity: sha512-Go3/gzStm99QHptsSgU+q1S+xDfLoRgwjJNY80kaTVi0ENhTyqKq+sc4xZiWBSbM7uUcJwmzm8+QFKtcYLJ9nw==}
|
||||
engines: {node: '>=22.0.0'}
|
||||
hasBin: true
|
||||
|
||||
|
|
@ -468,30 +468,30 @@ packages:
|
|||
engines: {node: '>=14.17'}
|
||||
hasBin: true
|
||||
|
||||
undici@7.24.8:
|
||||
resolution: {integrity: sha512-6KQ/+QxK49Z/p3HO6E5ZCZWNnCasyZLa5ExaVYyvPxUwKtbCPMKELJOqh7EqOle0t9cH/7d2TaaTRRa6Nhs4YQ==}
|
||||
undici@7.28.0:
|
||||
resolution: {integrity: sha512-cRZYrTDwWznlnRiPjggAGxZXanty6M8RV1ff8Wm4LWXBp7/IG8v5DnOm74DtUBp9OONpK75YlPnIjQqX0dBDtA==}
|
||||
engines: {node: '>=20.18.1'}
|
||||
|
||||
unenv@2.0.0-rc.24:
|
||||
resolution: {integrity: sha512-i7qRCmY42zmCwnYlh9H2SvLEypEFGye5iRmEMKjcGi7zk9UquigRjFtTLz0TYqr0ZGLZhaMHl/foy1bZR+Cwlw==}
|
||||
|
||||
workerd@1.20260616.1:
|
||||
resolution: {integrity: sha512-aRGWYxviSjYZwyu97pCr5GyJ9ObpgmNcfZZs3/o+kG7Wz3SBTqA8d8uhNueY5u7ADeUp2ibJvK6mXkFLrUmPgg==}
|
||||
workerd@1.20260617.1:
|
||||
resolution: {integrity: sha512-Re5pl6pdowt3ZmWUzGlOuB7jbRIIPetgKalmo4cYmucQnVhpo7/3e4MfpekbhLi2EhZZz5EY9NWRu8zFzuEZew==}
|
||||
engines: {node: '>=16'}
|
||||
hasBin: true
|
||||
|
||||
wrangler@4.101.0:
|
||||
resolution: {integrity: sha512-dZDDiRcT7MiA09lBDxWKmiL/iybEZ+SZe3IZmnVx1m1n1DOo730vOY5SeO7z9xFK8a/+vhGKDYB8mDXrvzEr5g==}
|
||||
wrangler@4.103.0:
|
||||
resolution: {integrity: sha512-3Lv1P5t2xcSEkSTKtG+Lz+3JFryuU7YPLkaCUj7gNe+CJsjZJLtUwqsh1x595QBxkIbCE0GAvDx2DCJUU4+oqw==}
|
||||
engines: {node: '>=22.0.0'}
|
||||
hasBin: true
|
||||
peerDependencies:
|
||||
'@cloudflare/workers-types': ^4.20260616.1
|
||||
'@cloudflare/workers-types': ^4.20260617.1
|
||||
peerDependenciesMeta:
|
||||
'@cloudflare/workers-types':
|
||||
optional: true
|
||||
|
||||
ws@8.20.1:
|
||||
resolution: {integrity: sha512-It4dO0K5v//JtTXuPkfEOaI3uUN87iYPnqo/ZzqCoG3g8uhA66QUMs/SrM0YK7/NAu+r4LMh/9dq2A7k+rHs+w==}
|
||||
ws@8.21.0:
|
||||
resolution: {integrity: sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g==}
|
||||
engines: {node: '>=10.0.0'}
|
||||
peerDependencies:
|
||||
bufferutil: ^4.0.1
|
||||
|
|
@ -512,25 +512,25 @@ snapshots:
|
|||
|
||||
'@cloudflare/kv-asset-handler@0.5.0': {}
|
||||
|
||||
'@cloudflare/unenv-preset@2.16.1(unenv@2.0.0-rc.24)(workerd@1.20260616.1)':
|
||||
'@cloudflare/unenv-preset@2.16.1(unenv@2.0.0-rc.24)(workerd@1.20260617.1)':
|
||||
dependencies:
|
||||
unenv: 2.0.0-rc.24
|
||||
optionalDependencies:
|
||||
workerd: 1.20260616.1
|
||||
workerd: 1.20260617.1
|
||||
|
||||
'@cloudflare/workerd-darwin-64@1.20260616.1':
|
||||
'@cloudflare/workerd-darwin-64@1.20260617.1':
|
||||
optional: true
|
||||
|
||||
'@cloudflare/workerd-darwin-arm64@1.20260616.1':
|
||||
'@cloudflare/workerd-darwin-arm64@1.20260617.1':
|
||||
optional: true
|
||||
|
||||
'@cloudflare/workerd-linux-64@1.20260616.1':
|
||||
'@cloudflare/workerd-linux-64@1.20260617.1':
|
||||
optional: true
|
||||
|
||||
'@cloudflare/workerd-linux-arm64@1.20260616.1':
|
||||
'@cloudflare/workerd-linux-arm64@1.20260617.1':
|
||||
optional: true
|
||||
|
||||
'@cloudflare/workerd-windows-64@1.20260616.1':
|
||||
'@cloudflare/workerd-windows-64@1.20260617.1':
|
||||
optional: true
|
||||
|
||||
'@cloudflare/workers-types@4.20260617.1': {}
|
||||
|
|
@ -544,82 +544,82 @@ snapshots:
|
|||
tslib: 2.8.1
|
||||
optional: true
|
||||
|
||||
'@esbuild/aix-ppc64@0.27.3':
|
||||
'@esbuild/aix-ppc64@0.28.1':
|
||||
optional: true
|
||||
|
||||
'@esbuild/android-arm64@0.27.3':
|
||||
'@esbuild/android-arm64@0.28.1':
|
||||
optional: true
|
||||
|
||||
'@esbuild/android-arm@0.27.3':
|
||||
'@esbuild/android-arm@0.28.1':
|
||||
optional: true
|
||||
|
||||
'@esbuild/android-x64@0.27.3':
|
||||
'@esbuild/android-x64@0.28.1':
|
||||
optional: true
|
||||
|
||||
'@esbuild/darwin-arm64@0.27.3':
|
||||
'@esbuild/darwin-arm64@0.28.1':
|
||||
optional: true
|
||||
|
||||
'@esbuild/darwin-x64@0.27.3':
|
||||
'@esbuild/darwin-x64@0.28.1':
|
||||
optional: true
|
||||
|
||||
'@esbuild/freebsd-arm64@0.27.3':
|
||||
'@esbuild/freebsd-arm64@0.28.1':
|
||||
optional: true
|
||||
|
||||
'@esbuild/freebsd-x64@0.27.3':
|
||||
'@esbuild/freebsd-x64@0.28.1':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-arm64@0.27.3':
|
||||
'@esbuild/linux-arm64@0.28.1':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-arm@0.27.3':
|
||||
'@esbuild/linux-arm@0.28.1':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-ia32@0.27.3':
|
||||
'@esbuild/linux-ia32@0.28.1':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-loong64@0.27.3':
|
||||
'@esbuild/linux-loong64@0.28.1':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-mips64el@0.27.3':
|
||||
'@esbuild/linux-mips64el@0.28.1':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-ppc64@0.27.3':
|
||||
'@esbuild/linux-ppc64@0.28.1':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-riscv64@0.27.3':
|
||||
'@esbuild/linux-riscv64@0.28.1':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-s390x@0.27.3':
|
||||
'@esbuild/linux-s390x@0.28.1':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-x64@0.27.3':
|
||||
'@esbuild/linux-x64@0.28.1':
|
||||
optional: true
|
||||
|
||||
'@esbuild/netbsd-arm64@0.27.3':
|
||||
'@esbuild/netbsd-arm64@0.28.1':
|
||||
optional: true
|
||||
|
||||
'@esbuild/netbsd-x64@0.27.3':
|
||||
'@esbuild/netbsd-x64@0.28.1':
|
||||
optional: true
|
||||
|
||||
'@esbuild/openbsd-arm64@0.27.3':
|
||||
'@esbuild/openbsd-arm64@0.28.1':
|
||||
optional: true
|
||||
|
||||
'@esbuild/openbsd-x64@0.27.3':
|
||||
'@esbuild/openbsd-x64@0.28.1':
|
||||
optional: true
|
||||
|
||||
'@esbuild/openharmony-arm64@0.27.3':
|
||||
'@esbuild/openharmony-arm64@0.28.1':
|
||||
optional: true
|
||||
|
||||
'@esbuild/sunos-x64@0.27.3':
|
||||
'@esbuild/sunos-x64@0.28.1':
|
||||
optional: true
|
||||
|
||||
'@esbuild/win32-arm64@0.27.3':
|
||||
'@esbuild/win32-arm64@0.28.1':
|
||||
optional: true
|
||||
|
||||
'@esbuild/win32-ia32@0.27.3':
|
||||
'@esbuild/win32-ia32@0.28.1':
|
||||
optional: true
|
||||
|
||||
'@esbuild/win32-x64@0.27.3':
|
||||
'@esbuild/win32-x64@0.28.1':
|
||||
optional: true
|
||||
|
||||
'@img/colour@1.1.0': {}
|
||||
|
|
@ -751,47 +751,47 @@ snapshots:
|
|||
|
||||
error-stack-parser-es@1.0.5: {}
|
||||
|
||||
esbuild@0.27.3:
|
||||
esbuild@0.28.1:
|
||||
optionalDependencies:
|
||||
'@esbuild/aix-ppc64': 0.27.3
|
||||
'@esbuild/android-arm': 0.27.3
|
||||
'@esbuild/android-arm64': 0.27.3
|
||||
'@esbuild/android-x64': 0.27.3
|
||||
'@esbuild/darwin-arm64': 0.27.3
|
||||
'@esbuild/darwin-x64': 0.27.3
|
||||
'@esbuild/freebsd-arm64': 0.27.3
|
||||
'@esbuild/freebsd-x64': 0.27.3
|
||||
'@esbuild/linux-arm': 0.27.3
|
||||
'@esbuild/linux-arm64': 0.27.3
|
||||
'@esbuild/linux-ia32': 0.27.3
|
||||
'@esbuild/linux-loong64': 0.27.3
|
||||
'@esbuild/linux-mips64el': 0.27.3
|
||||
'@esbuild/linux-ppc64': 0.27.3
|
||||
'@esbuild/linux-riscv64': 0.27.3
|
||||
'@esbuild/linux-s390x': 0.27.3
|
||||
'@esbuild/linux-x64': 0.27.3
|
||||
'@esbuild/netbsd-arm64': 0.27.3
|
||||
'@esbuild/netbsd-x64': 0.27.3
|
||||
'@esbuild/openbsd-arm64': 0.27.3
|
||||
'@esbuild/openbsd-x64': 0.27.3
|
||||
'@esbuild/openharmony-arm64': 0.27.3
|
||||
'@esbuild/sunos-x64': 0.27.3
|
||||
'@esbuild/win32-arm64': 0.27.3
|
||||
'@esbuild/win32-ia32': 0.27.3
|
||||
'@esbuild/win32-x64': 0.27.3
|
||||
'@esbuild/aix-ppc64': 0.28.1
|
||||
'@esbuild/android-arm': 0.28.1
|
||||
'@esbuild/android-arm64': 0.28.1
|
||||
'@esbuild/android-x64': 0.28.1
|
||||
'@esbuild/darwin-arm64': 0.28.1
|
||||
'@esbuild/darwin-x64': 0.28.1
|
||||
'@esbuild/freebsd-arm64': 0.28.1
|
||||
'@esbuild/freebsd-x64': 0.28.1
|
||||
'@esbuild/linux-arm': 0.28.1
|
||||
'@esbuild/linux-arm64': 0.28.1
|
||||
'@esbuild/linux-ia32': 0.28.1
|
||||
'@esbuild/linux-loong64': 0.28.1
|
||||
'@esbuild/linux-mips64el': 0.28.1
|
||||
'@esbuild/linux-ppc64': 0.28.1
|
||||
'@esbuild/linux-riscv64': 0.28.1
|
||||
'@esbuild/linux-s390x': 0.28.1
|
||||
'@esbuild/linux-x64': 0.28.1
|
||||
'@esbuild/netbsd-arm64': 0.28.1
|
||||
'@esbuild/netbsd-x64': 0.28.1
|
||||
'@esbuild/openbsd-arm64': 0.28.1
|
||||
'@esbuild/openbsd-x64': 0.28.1
|
||||
'@esbuild/openharmony-arm64': 0.28.1
|
||||
'@esbuild/sunos-x64': 0.28.1
|
||||
'@esbuild/win32-arm64': 0.28.1
|
||||
'@esbuild/win32-ia32': 0.28.1
|
||||
'@esbuild/win32-x64': 0.28.1
|
||||
|
||||
fsevents@2.3.3:
|
||||
optional: true
|
||||
|
||||
kleur@4.1.5: {}
|
||||
|
||||
miniflare@4.20260616.0:
|
||||
miniflare@4.20260617.1:
|
||||
dependencies:
|
||||
'@cspotcode/source-map-support': 0.8.1
|
||||
sharp: 0.34.5
|
||||
undici: 7.24.8
|
||||
workerd: 1.20260616.1
|
||||
ws: 8.20.1
|
||||
undici: 7.28.0
|
||||
workerd: 1.20260617.1
|
||||
ws: 8.21.0
|
||||
youch: 4.1.0-beta.10
|
||||
transitivePeerDependencies:
|
||||
- bufferutil
|
||||
|
|
@ -841,30 +841,30 @@ snapshots:
|
|||
|
||||
typescript@6.0.3: {}
|
||||
|
||||
undici@7.24.8: {}
|
||||
undici@7.28.0: {}
|
||||
|
||||
unenv@2.0.0-rc.24:
|
||||
dependencies:
|
||||
pathe: 2.0.3
|
||||
|
||||
workerd@1.20260616.1:
|
||||
workerd@1.20260617.1:
|
||||
optionalDependencies:
|
||||
'@cloudflare/workerd-darwin-64': 1.20260616.1
|
||||
'@cloudflare/workerd-darwin-arm64': 1.20260616.1
|
||||
'@cloudflare/workerd-linux-64': 1.20260616.1
|
||||
'@cloudflare/workerd-linux-arm64': 1.20260616.1
|
||||
'@cloudflare/workerd-windows-64': 1.20260616.1
|
||||
'@cloudflare/workerd-darwin-64': 1.20260617.1
|
||||
'@cloudflare/workerd-darwin-arm64': 1.20260617.1
|
||||
'@cloudflare/workerd-linux-64': 1.20260617.1
|
||||
'@cloudflare/workerd-linux-arm64': 1.20260617.1
|
||||
'@cloudflare/workerd-windows-64': 1.20260617.1
|
||||
|
||||
wrangler@4.101.0(@cloudflare/workers-types@4.20260617.1):
|
||||
wrangler@4.103.0(@cloudflare/workers-types@4.20260617.1):
|
||||
dependencies:
|
||||
'@cloudflare/kv-asset-handler': 0.5.0
|
||||
'@cloudflare/unenv-preset': 2.16.1(unenv@2.0.0-rc.24)(workerd@1.20260616.1)
|
||||
'@cloudflare/unenv-preset': 2.16.1(unenv@2.0.0-rc.24)(workerd@1.20260617.1)
|
||||
blake3-wasm: 2.1.5
|
||||
esbuild: 0.27.3
|
||||
miniflare: 4.20260616.0
|
||||
esbuild: 0.28.1
|
||||
miniflare: 4.20260617.1
|
||||
path-to-regexp: 6.3.0
|
||||
unenv: 2.0.0-rc.24
|
||||
workerd: 1.20260616.1
|
||||
workerd: 1.20260617.1
|
||||
optionalDependencies:
|
||||
'@cloudflare/workers-types': 4.20260617.1
|
||||
fsevents: 2.3.3
|
||||
|
|
@ -872,7 +872,7 @@ snapshots:
|
|||
- bufferutil
|
||||
- utf-8-validate
|
||||
|
||||
ws@8.20.1: {}
|
||||
ws@8.21.0: {}
|
||||
|
||||
youch-core@0.3.3:
|
||||
dependencies:
|
||||
|
|
|
|||
|
|
@ -2,3 +2,6 @@ allowBuilds:
|
|||
esbuild: true
|
||||
sharp: true
|
||||
workerd: true
|
||||
minimumReleaseAgeExclude:
|
||||
- miniflare@4.20260617.1
|
||||
- wrangler@4.103.0
|
||||
|
|
|
|||
|
|
@ -70,18 +70,34 @@ export async function fetchBotUser(env: Env, id: string): Promise<RawDiscordUser
|
|||
return (await res.json()) as RawDiscordUser;
|
||||
}
|
||||
|
||||
export interface UserProfileFetch {
|
||||
data: RawProfileResponse | null;
|
||||
/** HTTP status (0 = not attempted / no token). */
|
||||
status: number;
|
||||
/** Seconds from a 429 Retry-After header, when present. */
|
||||
retryAfter: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rich profile via USER token (self-bot — ToS risk). Returns null if no user
|
||||
* token is configured or the request fails, so callers degrade gracefully.
|
||||
* Rich profile via USER token (self-bot — ToS risk). Reports the HTTP status so
|
||||
* callers can tell a 429 rate-limit (back off) apart from a 401/403 token issue,
|
||||
* rather than silently degrading to the bot token.
|
||||
*/
|
||||
export async function fetchUserProfile(env: Env, id: string): Promise<RawProfileResponse | null> {
|
||||
if (!env.DISCORD_USER_TOKEN) return null;
|
||||
export async function fetchUserProfile(env: Env, id: string): Promise<UserProfileFetch> {
|
||||
if (!env.DISCORD_USER_TOKEN) return { data: null, status: 0, retryAfter: 0 };
|
||||
const url =
|
||||
`${apiBase(env)}/users/${id}/profile` +
|
||||
`?with_mutual_guilds=false&with_mutual_friends=false`;
|
||||
const res = await fetch(url, {
|
||||
headers: { Authorization: env.DISCORD_USER_TOKEN },
|
||||
});
|
||||
if (!res.ok) return null;
|
||||
return (await res.json()) as RawProfileResponse;
|
||||
if (!res.ok) {
|
||||
const retryAfter = Number(res.headers.get("retry-after")) || 0;
|
||||
console.warn(
|
||||
`[dough-restful] user-token /users/${id}/profile -> HTTP ${res.status}` +
|
||||
(retryAfter ? ` (retry ${retryAfter}s)` : "")
|
||||
);
|
||||
return { data: null, status: res.status, retryAfter };
|
||||
}
|
||||
return { data: (await res.json()) as RawProfileResponse, status: 200, retryAfter: 0 };
|
||||
}
|
||||
|
|
|
|||
127
src/profile.ts
127
src/profile.ts
|
|
@ -99,43 +99,93 @@ function cacheKey(id: string): string {
|
|||
return `profile:${id}`;
|
||||
}
|
||||
|
||||
type CachedProfile = Omit<ProfileResult, "source">;
|
||||
|
||||
/**
|
||||
* Build profile from Discord — LIVE-FIRST.
|
||||
* Get a user's profile — CACHE-FIRST, with a bot+user merge fallback.
|
||||
*
|
||||
* Always fetches fresh from Discord so profile/badges/connections are current,
|
||||
* and only falls back to the KV copy if the REST call fails (e.g. Discord is
|
||||
* rate-limiting us). The KV copy is refreshed in the background, throttled to
|
||||
* at most one write per TTL window so we don't blow KV write limits.
|
||||
* Profiles change rarely and Discord rate-limits the user-token /profile
|
||||
* endpoint hard, so we serve a cached rich profile for PROFILE_CACHE_TTL_SECONDS
|
||||
* before bothering Discord again — this is what stops the rate-limiting.
|
||||
*
|
||||
* When a refresh CAN only reach the bot token (the rich call got 429'd/blocked),
|
||||
* we don't downgrade: we keep the fresh bot base and layer the cached rich
|
||||
* fields (theme_colors, display_name_styles, bio, pronouns, rich badges +
|
||||
* connections) back over it — "use both at once" — so those never vanish during
|
||||
* a rate-limit window. Presence is unaffected; it streams from the gateway DO.
|
||||
*/
|
||||
export async function getProfile(
|
||||
env: Env,
|
||||
id: string,
|
||||
ctx?: ExecutionContext
|
||||
): Promise<ProfileResult | null> {
|
||||
const fresh = await buildFreshProfile(env, id);
|
||||
if (fresh) {
|
||||
const refresh = maybeRefreshCache(env, id, fresh);
|
||||
if (ctx) ctx.waitUntil(refresh);
|
||||
else await refresh;
|
||||
return fresh;
|
||||
const ttl = Math.max(60, Number(env.PROFILE_CACHE_TTL_SECONDS || "300"));
|
||||
const got = await env.PROFILE_CACHE.getWithMetadata(cacheKey(id), "json");
|
||||
const cached = (got.value as CachedProfile | null) ?? null;
|
||||
const lastWrite = (got.metadata as { t?: number } | null)?.t ?? 0;
|
||||
const cacheFresh = !!cached && Date.now() - lastWrite < ttl * 1000;
|
||||
|
||||
// 1) Fresh rich cache -> serve it without touching Discord at all.
|
||||
if (cached && cacheFresh) return { ...cached, source: "cache" };
|
||||
|
||||
// 2) Cache stale or missing -> fetch live. Skip the rich (user-token) attempt
|
||||
// while we're in a 429 cooldown so the rate-limit window can clear instead
|
||||
// of us hammering it on every request and never recovering.
|
||||
const cdRaw = await env.PROFILE_CACHE.get(COOLDOWN_KEY);
|
||||
const tryRich = !(cdRaw && Date.now() < Number(cdRaw));
|
||||
|
||||
const { result: built, richStatus, retryAfter } = await buildFreshProfile(env, id, tryRich);
|
||||
|
||||
if (richStatus === 429) {
|
||||
// back off all rich attempts for a while (honour Retry-After, clamp 30s–5m)
|
||||
const backoffMs = Math.min(Math.max(retryAfter, 30), 300) * 1000;
|
||||
const write = env.PROFILE_CACHE.put(COOLDOWN_KEY, String(Date.now() + backoffMs), {
|
||||
expirationTtl: Math.ceil(backoffMs / 1000) + 60,
|
||||
});
|
||||
if (ctx) ctx.waitUntil(write);
|
||||
else await write;
|
||||
}
|
||||
|
||||
// Discord REST failed — serve last-known-good from KV if we have it.
|
||||
const cached = await env.PROFILE_CACHE.get(cacheKey(id), "json");
|
||||
if (cached) {
|
||||
const c = cached as Omit<ProfileResult, "source">;
|
||||
return { ...c, source: "cache" };
|
||||
if (built && built.source === "user") {
|
||||
const write = writeCache(env, id, built);
|
||||
if (ctx) ctx.waitUntil(write);
|
||||
else await write;
|
||||
return built;
|
||||
}
|
||||
|
||||
if (built && built.source === "bot") {
|
||||
// Rich fetch skipped/degraded: fresh bot base + cached rich extras.
|
||||
if (cached) return { ...mergeRichOverBot(cached, built), source: "cache" };
|
||||
return built; // nothing cached yet — bot-only is the best we have
|
||||
}
|
||||
|
||||
// 3) Discord gave us nothing — serve stale cache if present.
|
||||
if (cached) return { ...cached, source: "cache" };
|
||||
return null;
|
||||
}
|
||||
|
||||
/** Write the fallback copy to KV, but at most once per TTL window. */
|
||||
async function maybeRefreshCache(env: Env, id: string, result: ProfileResult): Promise<void> {
|
||||
const ttl = Math.max(60, Number(env.PROFILE_CACHE_TTL_SECONDS || "300"));
|
||||
const { metadata } = await env.PROFILE_CACHE.getWithMetadata(cacheKey(id));
|
||||
const lastWrite = (metadata as { t?: number } | null)?.t ?? 0;
|
||||
if (Date.now() - lastWrite < ttl * 1000) return; // throttled
|
||||
/** Global KV key holding the timestamp until which rich fetches are paused. */
|
||||
const COOLDOWN_KEY = "profile:rich-cooldown";
|
||||
|
||||
/** Layer the rich-only fields from cache over a fresh bot-token result. */
|
||||
function mergeRichOverBot(cached: CachedProfile, bot: ProfileResult): CachedProfile {
|
||||
return {
|
||||
user: {
|
||||
...bot.user,
|
||||
bio: cached.user.bio,
|
||||
pronouns: cached.user.pronouns,
|
||||
theme_colors: cached.user.theme_colors,
|
||||
display_name_styles: cached.user.display_name_styles,
|
||||
},
|
||||
badges: cached.badges.length ? cached.badges : bot.badges,
|
||||
connected_accounts: cached.connected_accounts.length
|
||||
? cached.connected_accounts
|
||||
: bot.connected_accounts,
|
||||
};
|
||||
}
|
||||
|
||||
/** Persist a rich profile so it can drive cache-hits and bot-merge fallbacks. */
|
||||
async function writeCache(env: Env, id: string, result: ProfileResult): Promise<void> {
|
||||
await env.PROFILE_CACHE.put(
|
||||
cacheKey(id),
|
||||
JSON.stringify({
|
||||
|
|
@ -143,13 +193,26 @@ async function maybeRefreshCache(env: Env, id: string, result: ProfileResult): P
|
|||
badges: result.badges,
|
||||
connected_accounts: result.connected_accounts,
|
||||
}),
|
||||
{ expirationTtl: ttl * 2, metadata: { t: Date.now() } }
|
||||
{ expirationTtl: 86400, metadata: { t: Date.now() } }
|
||||
);
|
||||
}
|
||||
|
||||
async function buildFreshProfile(env: Env, id: string): Promise<ProfileResult | null> {
|
||||
// Rich path first (if user token present); fall back to bot-only.
|
||||
const profile = await fetchUserProfile(env, id);
|
||||
interface BuildResult {
|
||||
result: ProfileResult | null;
|
||||
/** HTTP status of the rich (user-token) attempt; 0 if it was skipped. */
|
||||
richStatus: number;
|
||||
/** Retry-After seconds from a 429, when present. */
|
||||
retryAfter: number;
|
||||
}
|
||||
|
||||
async function buildFreshProfile(env: Env, id: string, tryRich: boolean): Promise<BuildResult> {
|
||||
// Rich path first (unless we're cooling down from a 429); fall back to bot.
|
||||
const rich = tryRich
|
||||
? await fetchUserProfile(env, id)
|
||||
: { data: null, status: 0, retryAfter: 0 };
|
||||
const richStatus = rich.status;
|
||||
const retryAfter = rich.retryAfter;
|
||||
const profile = rich.data;
|
||||
|
||||
if (profile && profile.user) {
|
||||
const u = profile.user;
|
||||
|
|
@ -184,16 +247,24 @@ async function buildFreshProfile(env: Env, id: string): Promise<ProfileResult |
|
|||
verified: !!c.verified,
|
||||
}));
|
||||
|
||||
return { user: buildUser(u, bio, pronouns, themeColors), badges, connected_accounts: connected, source: "user" };
|
||||
return {
|
||||
result: { user: buildUser(u, bio, pronouns, themeColors), badges, connected_accounts: connected, source: "user" },
|
||||
richStatus,
|
||||
retryAfter,
|
||||
};
|
||||
}
|
||||
|
||||
// Bot-only fallback.
|
||||
const u = await fetchBotUser(env, id);
|
||||
if (!u) return null;
|
||||
if (!u) return { result: null, richStatus, retryAfter };
|
||||
return {
|
||||
result: {
|
||||
user: buildUser(u, null, null, null),
|
||||
badges: flagBadges(u.public_flags ?? u.flags ?? 0),
|
||||
connected_accounts: [],
|
||||
source: "bot",
|
||||
},
|
||||
richStatus,
|
||||
retryAfter,
|
||||
};
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue