mirror of
https://github.com/fallenbagel/jellyseerr.git
synced 2025-12-23 18:29:19 -05:00
feat: dns caching manager (#1294)
* feat(dns): implement dns caching * feat: simple implementation of dnscaching * feat: dynamic ttl which is revalidated while using stale dns cache This is done as tmdb ttl is very less like 40 seconds so to make sure any issues wont be caused due to cached dns (previously we were caching for 5 minutes no matter what ttl) * feat(dns): improve DNS cache with multi-strategy fallback system - multiple DNS resolution strategie - graceful fallbacks between IPv6 and IPv4 addresses - network error reporting in fetch fix - compatibility with cypress testing (I HOPE) * fix: typos * feat: dns cache stats in jobs & cache page (and cleanup) * feat(networksettings): cache dns off by default * feat: make dnsCache optional and enable-able through network settings * chore(i18n): extract translation keys * test(cypress): fix cypress testing * feat(dnscache): dns cache entries are now flushable * style(cypress): run prettier * chore(cypresssettings): git ignore cypress json settings * chore: ignore cypress/config/settings.json * fix(dnscache): use entry specific hits and misses not global * refactor: clean up console logs * fix(dnscache): fix miss counter * feat(dnscache): global stats * chore(i18n): extract translation keys * refactor: use date-fns for formatting age and remove useless code * refactor: remove cypress testing options in dnsCacheManager * refactor: remove console logs * refactor: removed useless condition when its always truthy * fix: remove FetchAPI-related code * fix: remove old ipv4first setting * refactor: use our own dns-caching package instead * fix: correct dns-caching module configuration * fix: correct dns-caching module configuration * fix: remove useless lru-cache dependency * fix: update dns-caching to v0.2.0 * fix: add env variable for min/max ttl & update dns-caching * fix: update dns-caching package * fix: add force min/max TTL in network settings * docs: add docs for dns caching --------- Co-authored-by: Gauthier <mail@gauthierth.fr>
This commit is contained in:
@@ -4,6 +4,7 @@ dist/
|
||||
config/
|
||||
CHANGELOG.md
|
||||
pnpm-lock.yaml
|
||||
cypress/config/settings.cypress.json
|
||||
|
||||
# assets
|
||||
src/assets/
|
||||
|
||||
@@ -21,5 +21,11 @@ module.exports = {
|
||||
rangeEnd: 0, // default: Infinity
|
||||
},
|
||||
},
|
||||
{
|
||||
files: 'cypress/config/settings.cypress.json',
|
||||
options: {
|
||||
rangeEnd: 0,
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
"apiKey": "testkey",
|
||||
"applicationTitle": "Jellyseerr",
|
||||
"applicationUrl": "",
|
||||
"csrfProtection": false,
|
||||
"cacheImages": false,
|
||||
"defaultPermissions": 32,
|
||||
"defaultQuotas": {
|
||||
@@ -180,5 +179,26 @@
|
||||
"image-cache-cleanup": {
|
||||
"schedule": "0 0 5 * * *"
|
||||
}
|
||||
},
|
||||
"network": {
|
||||
"csrfProtection": false,
|
||||
"trustProxy": false,
|
||||
"forceIpv4First": false,
|
||||
"dnsServers": "",
|
||||
"proxy": {
|
||||
"enabled": false,
|
||||
"hostname": "",
|
||||
"port": 8080,
|
||||
"useSsl": false,
|
||||
"user": "",
|
||||
"password": "",
|
||||
"bypassFilter": "",
|
||||
"bypassLocalAddresses": true
|
||||
},
|
||||
"dnsCache": {
|
||||
"enabled": false,
|
||||
"forceMinTtl": 0,
|
||||
"forceMaxTtl": -1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
16
docs/using-jellyseerr/settings/dns-caching.md
Normal file
16
docs/using-jellyseerr/settings/dns-caching.md
Normal file
@@ -0,0 +1,16 @@
|
||||
---
|
||||
title: DNS Caching
|
||||
description: Configure DNS caching settings.
|
||||
sidebar_position: 7
|
||||
---
|
||||
|
||||
# DNS Caching
|
||||
|
||||
Jellyseerr uses DNS caching to improve performance and reduce the number of DNS lookups required for external API calls. This can help speed up response times and reduce load on DNS servers, when something like a Pi-hole is used as a DNS resolver.
|
||||
|
||||
## Configuration
|
||||
|
||||
You can enable the DNS caching settings in the Network tab of the Jellyseerr settings. The default values follow the standard DNS caching behavior.
|
||||
|
||||
- **Force Minimum TTL**: Set a minimum time-to-live (TTL) in seconds for DNS cache entries. This ensures that frequently accessed DNS records are cached for a longer period, reducing the need for repeated lookups. Default is 0.
|
||||
- **Force Maximum TTL**: Set a maximum time-to-live (TTL) in seconds for DNS cache entries. This prevents infrequently accessed DNS records from being cached indefinitely, allowing for more up-to-date information to be retrieved. Default is -1 (unlimited).
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
title: Jobs & Cache
|
||||
description: Configure jobs and cache settings.
|
||||
sidebar_position: 6
|
||||
---
|
||||
|
||||
# Jobs & Cache
|
||||
|
||||
@@ -260,9 +260,51 @@ components:
|
||||
csrfProtection:
|
||||
type: boolean
|
||||
example: false
|
||||
forceIpv4First:
|
||||
type: boolean
|
||||
example: false
|
||||
trustProxy:
|
||||
type: boolean
|
||||
example: false
|
||||
proxy:
|
||||
type: object
|
||||
properties:
|
||||
enabled:
|
||||
type: boolean
|
||||
example: false
|
||||
hostname:
|
||||
type: string
|
||||
example: ''
|
||||
port:
|
||||
type: number
|
||||
example: 8080
|
||||
useSsl:
|
||||
type: boolean
|
||||
example: false
|
||||
user:
|
||||
type: string
|
||||
example: ''
|
||||
password:
|
||||
type: string
|
||||
example: ''
|
||||
bypassFilter:
|
||||
type: string
|
||||
example: ''
|
||||
bypassLocalAddresses:
|
||||
type: boolean
|
||||
example: true
|
||||
dnsCache:
|
||||
type: object
|
||||
properties:
|
||||
enabled:
|
||||
type: boolean
|
||||
example: false
|
||||
forceMinTtl:
|
||||
type: number
|
||||
example: 0
|
||||
forceMaxTtl:
|
||||
type: number
|
||||
example: -1
|
||||
PlexLibrary:
|
||||
type: object
|
||||
properties:
|
||||
@@ -2967,6 +3009,68 @@ paths:
|
||||
imageCount:
|
||||
type: number
|
||||
example: 123
|
||||
dnsCache:
|
||||
type: object
|
||||
properties:
|
||||
stats:
|
||||
type: object
|
||||
properties:
|
||||
size:
|
||||
type: number
|
||||
example: 1
|
||||
maxSize:
|
||||
type: number
|
||||
example: 500
|
||||
hits:
|
||||
type: number
|
||||
example: 19
|
||||
misses:
|
||||
type: number
|
||||
example: 1
|
||||
failures:
|
||||
type: number
|
||||
example: 0
|
||||
ipv4Fallbacks:
|
||||
type: number
|
||||
example: 0
|
||||
hitRate:
|
||||
type: number
|
||||
example: 0.95
|
||||
entries:
|
||||
type: array
|
||||
additionalProperties:
|
||||
type: object
|
||||
properties:
|
||||
addresses:
|
||||
type: object
|
||||
properties:
|
||||
ipv4:
|
||||
type: number
|
||||
example: 1
|
||||
ipv6:
|
||||
type: number
|
||||
example: 1
|
||||
activeAddress:
|
||||
type: string
|
||||
example: 127.0.0.1
|
||||
family:
|
||||
type: number
|
||||
example: 4
|
||||
age:
|
||||
type: number
|
||||
example: 10
|
||||
ttl:
|
||||
type: number
|
||||
example: 10
|
||||
networkErrors:
|
||||
type: number
|
||||
example: 0
|
||||
hits:
|
||||
type: number
|
||||
example: 1
|
||||
misses:
|
||||
type: number
|
||||
example: 1
|
||||
apiCaches:
|
||||
type: array
|
||||
items:
|
||||
@@ -3006,6 +3110,21 @@ paths:
|
||||
responses:
|
||||
'204':
|
||||
description: 'Flushed cache'
|
||||
/settings/cache/dns/{dnsEntry}/flush:
|
||||
post:
|
||||
summary: Flush a specific DNS cache entry
|
||||
description: Flushes a specific DNS cache entry
|
||||
tags:
|
||||
- settings
|
||||
parameters:
|
||||
- in: path
|
||||
name: dnsEntry
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
responses:
|
||||
'204':
|
||||
description: 'Flushed dns cache'
|
||||
/settings/logs:
|
||||
get:
|
||||
summary: Returns logs
|
||||
|
||||
@@ -57,6 +57,7 @@
|
||||
"cronstrue": "2.23.0",
|
||||
"date-fns": "2.29.3",
|
||||
"dayjs": "1.11.7",
|
||||
"dns-caching": "^0.2.4",
|
||||
"email-templates": "12.0.1",
|
||||
"email-validator": "2.0.4",
|
||||
"express": "4.21.2",
|
||||
|
||||
214
pnpm-lock.yaml
generated
214
pnpm-lock.yaml
generated
@@ -83,6 +83,9 @@ importers:
|
||||
dayjs:
|
||||
specifier: 1.11.7
|
||||
version: 1.11.7
|
||||
dns-caching:
|
||||
specifier: ^0.2.4
|
||||
version: 0.2.4
|
||||
email-templates:
|
||||
specifier: 12.0.1
|
||||
version: 12.0.1(@babel/core@7.24.7)(encoding@0.1.13)(handlebars@4.7.8)(mustache@4.2.0)(pug@3.0.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(underscore@1.13.7)
|
||||
@@ -688,8 +691,8 @@ packages:
|
||||
resolution: {integrity: sha512-NlmJJtvcw72yRJRcnCmGvSi+3jDEg8qFu3z0AFoymmzLx5ERVWyzd9kVXr7Th9/8yIJi2Zc6av4Tqz3wFs8QWg==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
|
||||
'@babel/helpers@7.27.6':
|
||||
resolution: {integrity: sha512-muE8Tt8M22638HU31A3CgfSUciwz1fhATfoVai05aPXGor//CdWDCbnlY1yvBPo07njuVOCNGCSp/GTt12lIug==}
|
||||
'@babel/helpers@7.28.2':
|
||||
resolution: {integrity: sha512-/V9771t+EgXz62aCcyofnQhGM8DQACbRhvzKFsXKC9QM+5MadF8ZmIm0crDMaz3+o0h0zXfJnd4EhbYbxsrcFw==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
|
||||
'@babel/highlight@7.24.7':
|
||||
@@ -1455,8 +1458,8 @@ packages:
|
||||
resolution: {integrity: sha512-FDSOghenHTiToteC/QRlv2q3DhPZ/oOXTBoirfWNx1Cx3TMVcGWQtMMmQcSvb/JjpNeGzx8Pq/b4fKEJuWm1sw==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
|
||||
'@babel/runtime@7.27.6':
|
||||
resolution: {integrity: sha512-vbavdySgbTTrmFE+EsiqUTzlOr5bzlnJtUv9PynGCAKvfQqjIXbvFdumPM/GxMDfyuGMJaJAU6TO4zc1Jf1i8Q==}
|
||||
'@babel/runtime@7.28.2':
|
||||
resolution: {integrity: sha512-KHp2IflsnGywDjBWDkR9iEqiWSpc8GIi0lgTT3mOElT0PP1tG26P4tmFI2YvAdzgq9RGyoHZQEIEdZy6Ec5xCA==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
|
||||
'@babel/template@7.24.7':
|
||||
@@ -1483,8 +1486,8 @@ packages:
|
||||
resolution: {integrity: sha512-Y3IR1cRnOxOCDvMmNiym7XpXQ93iGDDPHx+Zj+NM+rg0fBaShfQLkg+hKPaZCEvg5N/LeCo4+Rj/i3FuJsIQaw==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
|
||||
'@babel/types@7.28.1':
|
||||
resolution: {integrity: sha512-x0LvFTekgSX+83TI28Y9wYPUfzrnl2aT5+5QLnO6v7mSJYtEEevuDRN0F0uSHRk1G1IWZC43o00Y0xDDrpBGPQ==}
|
||||
'@babel/types@7.28.2':
|
||||
resolution: {integrity: sha512-ruv7Ae4J5dUYULmeXw1gmb7rYRz57OWCPM57pHojnLq/3Z1CK2lNSLTCVjxVk1F/TZHwOZZrOWi0ur95BbLxNQ==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
|
||||
'@codedependant/semantic-release-docker@5.1.0':
|
||||
@@ -1975,8 +1978,8 @@ packages:
|
||||
resolution: {integrity: sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==}
|
||||
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
|
||||
|
||||
'@jridgewell/gen-mapping@0.3.12':
|
||||
resolution: {integrity: sha512-OuLGC46TjB5BbN1dH8JULVVZY4WTdkF7tV9Ys6wLL1rubZnCMstOhNHueU5bLCrnRuDhKPDM4g6sw4Bel5Gzqg==}
|
||||
'@jridgewell/gen-mapping@0.3.13':
|
||||
resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==}
|
||||
|
||||
'@jridgewell/gen-mapping@0.3.5':
|
||||
resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==}
|
||||
@@ -1990,20 +1993,20 @@ packages:
|
||||
resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==}
|
||||
engines: {node: '>=6.0.0'}
|
||||
|
||||
'@jridgewell/source-map@0.3.10':
|
||||
resolution: {integrity: sha512-0pPkgz9dY+bijgistcTTJ5mR+ocqRXLuhXHYdzoMmmoJ2C9S46RCm2GMUbatPEUK9Yjy26IrAy8D/M00lLkv+Q==}
|
||||
'@jridgewell/source-map@0.3.11':
|
||||
resolution: {integrity: sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==}
|
||||
|
||||
'@jridgewell/sourcemap-codec@1.4.15':
|
||||
resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==}
|
||||
|
||||
'@jridgewell/sourcemap-codec@1.5.4':
|
||||
resolution: {integrity: sha512-VT2+G1VQs/9oz078bLrYbecdZKs912zQlkelYpuf+SXF+QvZDYJlbx/LSx+meSAwdDFnF8FVXW92AVjjkVmgFw==}
|
||||
'@jridgewell/sourcemap-codec@1.5.5':
|
||||
resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==}
|
||||
|
||||
'@jridgewell/trace-mapping@0.3.25':
|
||||
resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==}
|
||||
|
||||
'@jridgewell/trace-mapping@0.3.29':
|
||||
resolution: {integrity: sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ==}
|
||||
'@jridgewell/trace-mapping@0.3.30':
|
||||
resolution: {integrity: sha512-GQ7Nw5G2lTu/BtHTKfXhKHok2WGetd4XYcVKGx00SjAk8GMwgJM3zr6zORiPGuOE+/vkc90KtTosSSvaCjKb2Q==}
|
||||
|
||||
'@jridgewell/trace-mapping@0.3.9':
|
||||
resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==}
|
||||
@@ -3229,8 +3232,8 @@ packages:
|
||||
'@swc/helpers@0.5.5':
|
||||
resolution: {integrity: sha512-KGYxvIOXcceOAbEk4bi/dVLEK9z8sZ0uBB3Il5b1rhfClSpcX0yfRO0KmTkqR2cnQDymwLB+25ZyMzICg/cm/A==}
|
||||
|
||||
'@swc/types@0.1.23':
|
||||
resolution: {integrity: sha512-u1iIVZV9Q0jxY+yM2vw/hZGDNudsN85bBpTqzAQ9rzkxW9D+e3aEM4Han+ow518gSewkXgjmEK0BD79ZcNVgPw==}
|
||||
'@swc/types@0.1.24':
|
||||
resolution: {integrity: sha512-tjTMh3V4vAORHtdTprLlfoMptu1WfTZG9Rsca6yOKyNYsRr+MUXutKmliB17orgSZk5DpnDxs8GUdd/qwYxOng==}
|
||||
|
||||
'@tailwindcss/aspect-ratio@0.4.2':
|
||||
resolution: {integrity: sha512-8QPrypskfBa7QIMuKHg2TA7BqES6vhBrDLOv8Unb6FcFyd3TjKbc6lcmb9UPQHxfl24sXoJ41ux/H7qQQvfaSQ==}
|
||||
@@ -3391,8 +3394,8 @@ packages:
|
||||
'@types/node@17.0.45':
|
||||
resolution: {integrity: sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==}
|
||||
|
||||
'@types/node@18.19.118':
|
||||
resolution: {integrity: sha512-hIPK0hSrrcaoAu/gJMzN3QClXE4QdCdFvaenJ0JsjIbExP1JFFVH+RHcBt25c9n8bx5dkIfqKE+uw6BmBns7ug==}
|
||||
'@types/node@18.19.122':
|
||||
resolution: {integrity: sha512-yzegtT82dwTNEe/9y+CM8cgb42WrUfMMCg2QqSddzO1J6uPmBD7qKCZ7dOHZP2Yrpm/kb0eqdNMn2MUyEiqBmA==}
|
||||
|
||||
'@types/node@20.5.1':
|
||||
resolution: {integrity: sha512-4tT2UrL5LBqDwoed9wZ6N3umC4Yhz3W3FloMmiiG4JwmUJWpie0c7lcnUNd4gtMKuDEO4wRVS8B6Xa0uMRsMKg==}
|
||||
@@ -4087,11 +4090,6 @@ packages:
|
||||
engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
|
||||
hasBin: true
|
||||
|
||||
browserslist@4.24.3:
|
||||
resolution: {integrity: sha512-1CPmv8iobE2fyRMV97dAcMVegvvWKxmq94hkLiAkUGwKVTyDLw33K+ZxiFrREKmmps4rIw6grcCFCnTMSZ/YiA==}
|
||||
engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
|
||||
hasBin: true
|
||||
|
||||
browserslist@4.25.1:
|
||||
resolution: {integrity: sha512-KGj0KoOMXLpSNkkEI6Z6mShmQy0bc1I+T7K9N81k4WWMrfz+6fQ6es80B/YLAeRoKvjYE1YSHHOW1qe9xIVzHw==}
|
||||
engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
|
||||
@@ -4196,8 +4194,8 @@ packages:
|
||||
caniuse-lite@1.0.30001700:
|
||||
resolution: {integrity: sha512-2S6XIXwaE7K7erT8dY+kLQcpa5ms63XlRkMkReXjle+kf6c5g38vyMl+Z5y8dSxOFDhcFe+nxnn261PLxBSQsQ==}
|
||||
|
||||
caniuse-lite@1.0.30001727:
|
||||
resolution: {integrity: sha512-pB68nIHmbN6L/4C6MH1DokyR3bYqFwjaSs/sWDHGj4CTcFtQUQMuJftVwWkXq7mNWOybD3KhUv3oWHoGxgP14Q==}
|
||||
caniuse-lite@1.0.30001734:
|
||||
resolution: {integrity: sha512-uhE1Ye5vgqju6OI71HTQqcBCZrvHugk0MjLak7Q+HfoBgoq5Bi+5YnwjP4fjDgrtYr/l8MVRBvzz9dPD4KyK0A==}
|
||||
|
||||
caseless@0.12.0:
|
||||
resolution: {integrity: sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==}
|
||||
@@ -4426,8 +4424,8 @@ packages:
|
||||
resolution: {integrity: sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==}
|
||||
engines: {node: '>= 0.6'}
|
||||
|
||||
compression@1.8.0:
|
||||
resolution: {integrity: sha512-k6WLKfunuqCYD3t6AsuPGvQWaKwuLLh2/xHNcX4qE+vIfDNXpSqnrhwA7O53R7WVQUnt8dVAIW+YHr7xTgOgGA==}
|
||||
compression@1.8.1:
|
||||
resolution: {integrity: sha512-9mAqGPHLakhCLeNyxPkK4xVo746zQ/czLH1Ky+vkitMnWfWZps8r0qXuwhwizagCRttsL4lfG4pIOvaWLpAP0w==}
|
||||
engines: {node: '>= 0.8.0'}
|
||||
|
||||
computed-style@0.1.4:
|
||||
@@ -4547,8 +4545,8 @@ packages:
|
||||
core-js-compat@3.37.1:
|
||||
resolution: {integrity: sha512-9TNiImhKvQqSUkOvk/mMRZzOANTiEVC7WaBNhHcKM7x+/5E1l5NvsysR19zuDQScE8k+kfQXWRN3AtS/eOSHpg==}
|
||||
|
||||
core-js-compat@3.44.0:
|
||||
resolution: {integrity: sha512-JepmAj2zfl6ogy34qfWtcE7nHKAJnKsQFRn++scjVS2bZFllwptzw61BZcZFYBPpUznLfAvh0LGhxKppk04ClA==}
|
||||
core-js-compat@3.45.0:
|
||||
resolution: {integrity: sha512-gRoVMBawZg0OnxaVv3zpqLLxaHmsubEGyTnqdpI/CEBvX4JadI1dMSHxagThprYRtSVbuQxvi6iUatdPxohHpA==}
|
||||
|
||||
core-util-is@1.0.2:
|
||||
resolution: {integrity: sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==}
|
||||
@@ -4866,6 +4864,9 @@ packages:
|
||||
dlv@1.1.3:
|
||||
resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==}
|
||||
|
||||
dns-caching@0.2.4:
|
||||
resolution: {integrity: sha512-J48CLnMScOAtWIdExkz+522A0nPUwG5o+w7vVsXBJDipVLugCnps5AVJMn9bOkqQm4GarHtutMHYJEryCTeMjA==}
|
||||
|
||||
doctrine@2.1.0:
|
||||
resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
@@ -4937,8 +4938,8 @@ packages:
|
||||
electron-to-chromium@1.4.810:
|
||||
resolution: {integrity: sha512-Kaxhu4T7SJGpRQx99tq216gCq2nMxJo+uuT6uzz9l8TVN2stL7M06MIIXAtr9jsrLs2Glflgf2vMQRepxawOdQ==}
|
||||
|
||||
electron-to-chromium@1.5.182:
|
||||
resolution: {integrity: sha512-Lv65Btwv9W4J9pyODI6EWpdnhfvrve/us5h1WspW8B2Fb0366REPtY3hX7ounk1CkV/TBjWCEvCBBbYbmV0qCA==}
|
||||
electron-to-chromium@1.5.200:
|
||||
resolution: {integrity: sha512-rFCxROw7aOe4uPTfIAx+rXv9cEcGx+buAF4npnhtTqCJk5KDFRnh3+KYj7rdVh6lsFt5/aPs+Irj9rZ33WMA7w==}
|
||||
|
||||
email-templates@12.0.1:
|
||||
resolution: {integrity: sha512-849pjBFVUAWWTa3HqhDjxlXHaSWmxf4CZOlZ9iVkrSAbQ8YCYi+7KiKqt35L6F20WhSViWX7lmMjno6zBv2rNQ==}
|
||||
@@ -5506,8 +5507,8 @@ packages:
|
||||
flow-enums-runtime@0.0.6:
|
||||
resolution: {integrity: sha512-3PYnM29RFXwvAN6Pc/scUfkI7RwhQ/xqyLUyPNlXUp9S40zI8nup9tUSrTLSVnWGBN38FNiGWbwZOB6uR4OGdw==}
|
||||
|
||||
flow-parser@0.275.0:
|
||||
resolution: {integrity: sha512-fHNwawoA2LM7FsxhU/1lTRGq9n6/Q8k861eHgN7GKtamYt9Qrxpg/ZSrev8o1WX7fQ2D3Gg3+uvYN15PmsG7Yw==}
|
||||
flow-parser@0.278.0:
|
||||
resolution: {integrity: sha512-9oUcYDHf9n+E/t0FXndgBqGbaUsGEcmWqIr1ldqCzTzctsJV5E/bHusOj4ThB72Ss2mqWpLFNz0+o2c1O8J6+A==}
|
||||
engines: {node: '>=0.4.0'}
|
||||
|
||||
fn.name@1.1.0:
|
||||
@@ -6744,6 +6745,10 @@ packages:
|
||||
resolution: {integrity: sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ==}
|
||||
engines: {node: 14 || >=16.14}
|
||||
|
||||
lru-cache@11.1.0:
|
||||
resolution: {integrity: sha512-QIXZUBJUx+2zHUdQujWejBkcD9+cs94tLn0+YL8UrCh+D5sCXZ4c7LaEH48pNwRY3MLDgqUFyhlCyjJPf1WP0A==}
|
||||
engines: {node: 20 || >=22}
|
||||
|
||||
lru-cache@5.1.1:
|
||||
resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==}
|
||||
|
||||
@@ -7534,6 +7539,10 @@ packages:
|
||||
resolution: {integrity: sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==}
|
||||
engines: {node: '>= 0.8'}
|
||||
|
||||
on-headers@1.1.0:
|
||||
resolution: {integrity: sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==}
|
||||
engines: {node: '>= 0.8'}
|
||||
|
||||
once@1.4.0:
|
||||
resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
|
||||
|
||||
@@ -8838,9 +8847,9 @@ packages:
|
||||
resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
source-map@0.7.4:
|
||||
resolution: {integrity: sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==}
|
||||
engines: {node: '>= 8'}
|
||||
source-map@0.7.6:
|
||||
resolution: {integrity: sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==}
|
||||
engines: {node: '>= 12'}
|
||||
|
||||
space-separated-tokens@2.0.2:
|
||||
resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==}
|
||||
@@ -9893,8 +9902,8 @@ packages:
|
||||
engines: {node: '>= 14'}
|
||||
hasBin: true
|
||||
|
||||
yaml@2.8.0:
|
||||
resolution: {integrity: sha512-4lLa/EcQCB0cJkyts+FpIRx5G/llPxfP6VQU5KByHEhLxY3IJCH0f0Hy1MHI8sClTvsIb8qwRJ6R/ZdlDJ/leQ==}
|
||||
yaml@2.8.1:
|
||||
resolution: {integrity: sha512-lcYcMxX2PO9XMGvAJkJ3OsNMw+/7FKes7/hgerGUYWIoWu5j/+YQqcZr5JnPZWzOsEBgMbSbiSTn/dv/69Mkpw==}
|
||||
engines: {node: '>= 14.6'}
|
||||
hasBin: true
|
||||
|
||||
@@ -10038,11 +10047,11 @@ snapshots:
|
||||
'@babel/generator': 7.28.0
|
||||
'@babel/helper-compilation-targets': 7.27.2
|
||||
'@babel/helper-module-transforms': 7.27.3(@babel/core@7.28.0)
|
||||
'@babel/helpers': 7.27.6
|
||||
'@babel/helpers': 7.28.2
|
||||
'@babel/parser': 7.28.0
|
||||
'@babel/template': 7.27.2
|
||||
'@babel/traverse': 7.28.0
|
||||
'@babel/types': 7.28.1
|
||||
'@babel/types': 7.28.2
|
||||
convert-source-map: 2.0.0
|
||||
debug: 4.4.1
|
||||
gensync: 1.0.0-beta.2
|
||||
@@ -10061,9 +10070,9 @@ snapshots:
|
||||
'@babel/generator@7.28.0':
|
||||
dependencies:
|
||||
'@babel/parser': 7.28.0
|
||||
'@babel/types': 7.28.1
|
||||
'@jridgewell/gen-mapping': 0.3.12
|
||||
'@jridgewell/trace-mapping': 0.3.29
|
||||
'@babel/types': 7.28.2
|
||||
'@jridgewell/gen-mapping': 0.3.13
|
||||
'@jridgewell/trace-mapping': 0.3.30
|
||||
jsesc: 3.1.0
|
||||
|
||||
'@babel/helper-annotate-as-pure@7.24.7':
|
||||
@@ -10072,7 +10081,7 @@ snapshots:
|
||||
|
||||
'@babel/helper-annotate-as-pure@7.27.3':
|
||||
dependencies:
|
||||
'@babel/types': 7.28.1
|
||||
'@babel/types': 7.28.2
|
||||
|
||||
'@babel/helper-builder-binary-assignment-operator-visitor@7.24.7':
|
||||
dependencies:
|
||||
@@ -10093,7 +10102,7 @@ snapshots:
|
||||
dependencies:
|
||||
'@babel/compat-data': 7.28.0
|
||||
'@babel/helper-validator-option': 7.27.1
|
||||
browserslist: 4.24.3
|
||||
browserslist: 4.25.1
|
||||
lru-cache: 5.1.1
|
||||
semver: 6.3.1
|
||||
|
||||
@@ -10199,7 +10208,7 @@ snapshots:
|
||||
'@babel/helper-member-expression-to-functions@7.27.1':
|
||||
dependencies:
|
||||
'@babel/traverse': 7.28.0
|
||||
'@babel/types': 7.28.1
|
||||
'@babel/types': 7.28.2
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
@@ -10213,7 +10222,7 @@ snapshots:
|
||||
'@babel/helper-module-imports@7.27.1':
|
||||
dependencies:
|
||||
'@babel/traverse': 7.28.0
|
||||
'@babel/types': 7.28.1
|
||||
'@babel/types': 7.28.2
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
@@ -10252,7 +10261,7 @@ snapshots:
|
||||
|
||||
'@babel/helper-optimise-call-expression@7.27.1':
|
||||
dependencies:
|
||||
'@babel/types': 7.28.1
|
||||
'@babel/types': 7.28.2
|
||||
|
||||
'@babel/helper-plugin-utils@7.24.7': {}
|
||||
|
||||
@@ -10320,7 +10329,7 @@ snapshots:
|
||||
'@babel/helper-skip-transparent-expression-wrappers@7.27.1':
|
||||
dependencies:
|
||||
'@babel/traverse': 7.28.0
|
||||
'@babel/types': 7.28.1
|
||||
'@babel/types': 7.28.2
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
@@ -10357,7 +10366,7 @@ snapshots:
|
||||
dependencies:
|
||||
'@babel/template': 7.27.2
|
||||
'@babel/traverse': 7.28.0
|
||||
'@babel/types': 7.28.1
|
||||
'@babel/types': 7.28.2
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
@@ -10366,10 +10375,10 @@ snapshots:
|
||||
'@babel/template': 7.24.7
|
||||
'@babel/types': 7.24.7
|
||||
|
||||
'@babel/helpers@7.27.6':
|
||||
'@babel/helpers@7.28.2':
|
||||
dependencies:
|
||||
'@babel/template': 7.27.2
|
||||
'@babel/types': 7.28.1
|
||||
'@babel/types': 7.28.2
|
||||
|
||||
'@babel/highlight@7.24.7':
|
||||
dependencies:
|
||||
@@ -10388,7 +10397,7 @@ snapshots:
|
||||
|
||||
'@babel/parser@7.28.0':
|
||||
dependencies:
|
||||
'@babel/types': 7.28.1
|
||||
'@babel/types': 7.28.2
|
||||
|
||||
'@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.24.7(@babel/core@7.24.7)':
|
||||
dependencies:
|
||||
@@ -11080,7 +11089,7 @@ snapshots:
|
||||
'@babel/helper-module-imports': 7.27.1
|
||||
'@babel/helper-plugin-utils': 7.27.1
|
||||
'@babel/plugin-syntax-jsx': 7.27.1(@babel/core@7.24.7)
|
||||
'@babel/types': 7.28.1
|
||||
'@babel/types': 7.28.2
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
@@ -11374,7 +11383,7 @@ snapshots:
|
||||
dependencies:
|
||||
regenerator-runtime: 0.14.1
|
||||
|
||||
'@babel/runtime@7.27.6': {}
|
||||
'@babel/runtime@7.28.2': {}
|
||||
|
||||
'@babel/template@7.24.7':
|
||||
dependencies:
|
||||
@@ -11386,7 +11395,7 @@ snapshots:
|
||||
dependencies:
|
||||
'@babel/code-frame': 7.27.1
|
||||
'@babel/parser': 7.28.0
|
||||
'@babel/types': 7.28.1
|
||||
'@babel/types': 7.28.2
|
||||
|
||||
'@babel/traverse@7.24.7':
|
||||
dependencies:
|
||||
@@ -11410,7 +11419,7 @@ snapshots:
|
||||
'@babel/helper-globals': 7.28.0
|
||||
'@babel/parser': 7.28.0
|
||||
'@babel/template': 7.27.2
|
||||
'@babel/types': 7.28.1
|
||||
'@babel/types': 7.28.2
|
||||
debug: 4.4.1
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
@@ -11426,7 +11435,7 @@ snapshots:
|
||||
'@babel/helper-string-parser': 7.25.9
|
||||
'@babel/helper-validator-identifier': 7.25.9
|
||||
|
||||
'@babel/types@7.28.1':
|
||||
'@babel/types@7.28.2':
|
||||
dependencies:
|
||||
'@babel/helper-string-parser': 7.27.1
|
||||
'@babel/helper-validator-identifier': 7.27.1
|
||||
@@ -12091,10 +12100,10 @@ snapshots:
|
||||
'@types/yargs': 17.0.33
|
||||
chalk: 4.1.2
|
||||
|
||||
'@jridgewell/gen-mapping@0.3.12':
|
||||
'@jridgewell/gen-mapping@0.3.13':
|
||||
dependencies:
|
||||
'@jridgewell/sourcemap-codec': 1.5.4
|
||||
'@jridgewell/trace-mapping': 0.3.29
|
||||
'@jridgewell/sourcemap-codec': 1.5.5
|
||||
'@jridgewell/trace-mapping': 0.3.30
|
||||
|
||||
'@jridgewell/gen-mapping@0.3.5':
|
||||
dependencies:
|
||||
@@ -12106,24 +12115,24 @@ snapshots:
|
||||
|
||||
'@jridgewell/set-array@1.2.1': {}
|
||||
|
||||
'@jridgewell/source-map@0.3.10':
|
||||
'@jridgewell/source-map@0.3.11':
|
||||
dependencies:
|
||||
'@jridgewell/gen-mapping': 0.3.12
|
||||
'@jridgewell/trace-mapping': 0.3.29
|
||||
'@jridgewell/gen-mapping': 0.3.13
|
||||
'@jridgewell/trace-mapping': 0.3.30
|
||||
|
||||
'@jridgewell/sourcemap-codec@1.4.15': {}
|
||||
|
||||
'@jridgewell/sourcemap-codec@1.5.4': {}
|
||||
'@jridgewell/sourcemap-codec@1.5.5': {}
|
||||
|
||||
'@jridgewell/trace-mapping@0.3.25':
|
||||
dependencies:
|
||||
'@jridgewell/resolve-uri': 3.1.2
|
||||
'@jridgewell/sourcemap-codec': 1.4.15
|
||||
|
||||
'@jridgewell/trace-mapping@0.3.29':
|
||||
'@jridgewell/trace-mapping@0.3.30':
|
||||
dependencies:
|
||||
'@jridgewell/resolve-uri': 3.1.2
|
||||
'@jridgewell/sourcemap-codec': 1.5.4
|
||||
'@jridgewell/sourcemap-codec': 1.5.5
|
||||
|
||||
'@jridgewell/trace-mapping@0.3.9':
|
||||
dependencies:
|
||||
@@ -12871,7 +12880,7 @@ snapshots:
|
||||
semver: 7.7.1
|
||||
strip-ansi: 5.2.0
|
||||
wcwidth: 1.0.1
|
||||
yaml: 2.8.0
|
||||
yaml: 2.8.1
|
||||
transitivePeerDependencies:
|
||||
- encoding
|
||||
|
||||
@@ -12916,7 +12925,7 @@ snapshots:
|
||||
dependencies:
|
||||
'@react-native-community/cli-debugger-ui': 13.6.8
|
||||
'@react-native-community/cli-tools': 13.6.8(encoding@0.1.13)
|
||||
compression: 1.8.0
|
||||
compression: 1.8.1
|
||||
connect: 3.7.0
|
||||
errorhandler: 1.5.1
|
||||
nocache: 3.0.4
|
||||
@@ -13392,7 +13401,7 @@ snapshots:
|
||||
|
||||
'@react-three/fiber@8.16.8(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react-native@0.74.2(@babel/core@7.24.7)(@babel/preset-env@7.24.7(@babel/core@7.24.7))(@types/react@18.3.3)(encoding@0.1.13)(react@18.3.1))(react@18.3.1)(three@0.165.0)':
|
||||
dependencies:
|
||||
'@babel/runtime': 7.27.6
|
||||
'@babel/runtime': 7.28.2
|
||||
'@types/react-reconciler': 0.26.7
|
||||
'@types/webxr': 0.5.22
|
||||
base64-js: 1.5.1
|
||||
@@ -13547,7 +13556,7 @@ snapshots:
|
||||
|
||||
'@rnx-kit/chromium-edge-launcher@1.0.0':
|
||||
dependencies:
|
||||
'@types/node': 18.19.118
|
||||
'@types/node': 18.19.122
|
||||
escape-string-regexp: 4.0.0
|
||||
is-wsl: 2.2.0
|
||||
lighthouse-logger: 1.4.2
|
||||
@@ -13810,7 +13819,7 @@ snapshots:
|
||||
'@swc/core@1.6.5(@swc/helpers@0.5.11)':
|
||||
dependencies:
|
||||
'@swc/counter': 0.1.3
|
||||
'@swc/types': 0.1.23
|
||||
'@swc/types': 0.1.24
|
||||
optionalDependencies:
|
||||
'@swc/core-darwin-arm64': 1.6.5
|
||||
'@swc/core-darwin-x64': 1.6.5
|
||||
@@ -13835,7 +13844,7 @@ snapshots:
|
||||
'@swc/counter': 0.1.3
|
||||
tslib: 2.8.1
|
||||
|
||||
'@swc/types@0.1.23':
|
||||
'@swc/types@0.1.24':
|
||||
dependencies:
|
||||
'@swc/counter': 0.1.3
|
||||
|
||||
@@ -14013,7 +14022,7 @@ snapshots:
|
||||
|
||||
'@types/node@17.0.45': {}
|
||||
|
||||
'@types/node@18.19.118':
|
||||
'@types/node@18.19.122':
|
||||
dependencies:
|
||||
undici-types: 5.26.5
|
||||
|
||||
@@ -14689,7 +14698,7 @@ snapshots:
|
||||
dependencies:
|
||||
'@babel/core': 7.24.7
|
||||
'@babel/helper-define-polyfill-provider': 0.6.5(@babel/core@7.24.7)
|
||||
core-js-compat: 3.44.0
|
||||
core-js-compat: 3.45.0
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
@@ -14804,17 +14813,10 @@ snapshots:
|
||||
node-releases: 2.0.14
|
||||
update-browserslist-db: 1.0.16(browserslist@4.23.1)
|
||||
|
||||
browserslist@4.24.3:
|
||||
dependencies:
|
||||
caniuse-lite: 1.0.30001727
|
||||
electron-to-chromium: 1.5.182
|
||||
node-releases: 2.0.19
|
||||
update-browserslist-db: 1.1.3(browserslist@4.24.3)
|
||||
|
||||
browserslist@4.25.1:
|
||||
dependencies:
|
||||
caniuse-lite: 1.0.30001727
|
||||
electron-to-chromium: 1.5.182
|
||||
caniuse-lite: 1.0.30001734
|
||||
electron-to-chromium: 1.5.200
|
||||
node-releases: 2.0.19
|
||||
update-browserslist-db: 1.1.3(browserslist@4.25.1)
|
||||
|
||||
@@ -14945,7 +14947,7 @@ snapshots:
|
||||
|
||||
caniuse-lite@1.0.30001700: {}
|
||||
|
||||
caniuse-lite@1.0.30001727: {}
|
||||
caniuse-lite@1.0.30001734: {}
|
||||
|
||||
caseless@0.12.0: {}
|
||||
|
||||
@@ -15195,13 +15197,13 @@ snapshots:
|
||||
dependencies:
|
||||
mime-db: 1.54.0
|
||||
|
||||
compression@1.8.0:
|
||||
compression@1.8.1:
|
||||
dependencies:
|
||||
bytes: 3.1.2
|
||||
compressible: 2.0.18
|
||||
debug: 2.6.9
|
||||
negotiator: 0.6.4
|
||||
on-headers: 1.0.2
|
||||
on-headers: 1.1.0
|
||||
safe-buffer: 5.2.1
|
||||
vary: 1.1.2
|
||||
transitivePeerDependencies:
|
||||
@@ -15332,7 +15334,7 @@ snapshots:
|
||||
dependencies:
|
||||
browserslist: 4.23.1
|
||||
|
||||
core-js-compat@3.44.0:
|
||||
core-js-compat@3.45.0:
|
||||
dependencies:
|
||||
browserslist: 4.25.1
|
||||
|
||||
@@ -15698,6 +15700,10 @@ snapshots:
|
||||
|
||||
dlv@1.1.3: {}
|
||||
|
||||
dns-caching@0.2.4:
|
||||
dependencies:
|
||||
lru-cache: 11.1.0
|
||||
|
||||
doctrine@2.1.0:
|
||||
dependencies:
|
||||
esutils: 2.0.3
|
||||
@@ -15782,7 +15788,7 @@ snapshots:
|
||||
|
||||
electron-to-chromium@1.4.810: {}
|
||||
|
||||
electron-to-chromium@1.5.182: {}
|
||||
electron-to-chromium@1.5.200: {}
|
||||
|
||||
email-templates@12.0.1(@babel/core@7.24.7)(encoding@0.1.13)(handlebars@4.7.8)(mustache@4.2.0)(pug@3.0.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(underscore@1.13.7):
|
||||
dependencies:
|
||||
@@ -16702,7 +16708,7 @@ snapshots:
|
||||
|
||||
flow-enums-runtime@0.0.6: {}
|
||||
|
||||
flow-parser@0.275.0: {}
|
||||
flow-parser@0.278.0: {}
|
||||
|
||||
fn.name@1.1.0: {}
|
||||
|
||||
@@ -17092,7 +17098,7 @@ snapshots:
|
||||
|
||||
hermes-profile-transformer@0.0.6:
|
||||
dependencies:
|
||||
source-map: 0.7.4
|
||||
source-map: 0.7.6
|
||||
|
||||
highlight.js@10.7.3: {}
|
||||
|
||||
@@ -17685,7 +17691,7 @@ snapshots:
|
||||
'@babel/register': 7.27.1(@babel/core@7.28.0)
|
||||
babel-core: 7.0.0-bridge.0(@babel/core@7.28.0)
|
||||
chalk: 4.1.2
|
||||
flow-parser: 0.275.0
|
||||
flow-parser: 0.278.0
|
||||
graceful-fs: 4.2.11
|
||||
micromatch: 4.0.8
|
||||
neo-async: 2.6.2
|
||||
@@ -18036,6 +18042,8 @@ snapshots:
|
||||
|
||||
lru-cache@10.2.2: {}
|
||||
|
||||
lru-cache@11.1.0: {}
|
||||
|
||||
lru-cache@5.1.1:
|
||||
dependencies:
|
||||
yallist: 3.1.1
|
||||
@@ -18307,13 +18315,13 @@ snapshots:
|
||||
|
||||
metro-runtime@0.80.12:
|
||||
dependencies:
|
||||
'@babel/runtime': 7.27.6
|
||||
'@babel/runtime': 7.28.2
|
||||
flow-enums-runtime: 0.0.6
|
||||
|
||||
metro-source-map@0.80.12:
|
||||
dependencies:
|
||||
'@babel/traverse': 7.28.0
|
||||
'@babel/types': 7.28.1
|
||||
'@babel/types': 7.28.2
|
||||
flow-enums-runtime: 0.0.6
|
||||
invariant: 2.2.4
|
||||
metro-symbolicate: 0.80.12
|
||||
@@ -18352,7 +18360,7 @@ snapshots:
|
||||
'@babel/core': 7.28.0
|
||||
'@babel/generator': 7.28.0
|
||||
'@babel/parser': 7.28.0
|
||||
'@babel/types': 7.28.1
|
||||
'@babel/types': 7.28.2
|
||||
flow-enums-runtime: 0.0.6
|
||||
metro: 0.80.12
|
||||
metro-babel-transformer: 0.80.12
|
||||
@@ -18375,7 +18383,7 @@ snapshots:
|
||||
'@babel/parser': 7.28.0
|
||||
'@babel/template': 7.27.2
|
||||
'@babel/traverse': 7.28.0
|
||||
'@babel/types': 7.28.1
|
||||
'@babel/types': 7.28.2
|
||||
accepts: 1.3.8
|
||||
chalk: 4.1.2
|
||||
ci-info: 2.0.0
|
||||
@@ -19002,6 +19010,8 @@ snapshots:
|
||||
|
||||
on-headers@1.0.2: {}
|
||||
|
||||
on-headers@1.1.0: {}
|
||||
|
||||
once@1.4.0:
|
||||
dependencies:
|
||||
wrappy: 1.0.2
|
||||
@@ -20534,7 +20544,7 @@ snapshots:
|
||||
|
||||
source-map@0.6.1: {}
|
||||
|
||||
source-map@0.7.4: {}
|
||||
source-map@0.7.6: {}
|
||||
|
||||
space-separated-tokens@2.0.2: {}
|
||||
|
||||
@@ -20871,7 +20881,7 @@ snapshots:
|
||||
|
||||
terser@5.43.1:
|
||||
dependencies:
|
||||
'@jridgewell/source-map': 0.3.10
|
||||
'@jridgewell/source-map': 0.3.11
|
||||
acorn: 8.15.0
|
||||
commander: 2.20.3
|
||||
source-map-support: 0.5.21
|
||||
@@ -21298,12 +21308,6 @@ snapshots:
|
||||
escalade: 3.1.2
|
||||
picocolors: 1.0.1
|
||||
|
||||
update-browserslist-db@1.1.3(browserslist@4.24.3):
|
||||
dependencies:
|
||||
browserslist: 4.24.3
|
||||
escalade: 3.2.0
|
||||
picocolors: 1.1.1
|
||||
|
||||
update-browserslist-db@1.1.3(browserslist@4.25.1):
|
||||
dependencies:
|
||||
browserslist: 4.25.1
|
||||
@@ -21594,7 +21598,7 @@ snapshots:
|
||||
|
||||
yaml@2.4.5: {}
|
||||
|
||||
yaml@2.8.0: {}
|
||||
yaml@2.8.1: {}
|
||||
|
||||
yamljs@0.3.0:
|
||||
dependencies:
|
||||
|
||||
@@ -25,6 +25,7 @@ import imageproxy from '@server/routes/imageproxy';
|
||||
import { appDataPermissions } from '@server/utils/appDataVolume';
|
||||
import { getAppVersion } from '@server/utils/appVersion';
|
||||
import createCustomProxyAgent from '@server/utils/customProxyAgent';
|
||||
import { initializeDnsCache } from '@server/utils/dnsCache';
|
||||
import restartFlag from '@server/utils/restartFlag';
|
||||
import { getClientIp } from '@supercharge/request-ip';
|
||||
import axios from 'axios';
|
||||
@@ -80,6 +81,14 @@ app
|
||||
axios.defaults.httpsAgent = new https.Agent({ family: 4 });
|
||||
}
|
||||
|
||||
// Add DNS caching
|
||||
if (settings.network.dnsCache) {
|
||||
initializeDnsCache({
|
||||
forceMinTtl: settings.network.dnsCache.forceMinTtl,
|
||||
forceMaxTtl: settings.network.dnsCache.forceMaxTtl,
|
||||
});
|
||||
}
|
||||
|
||||
// Register HTTP proxy
|
||||
if (settings.network.proxy.enabled) {
|
||||
await createCustomProxyAgent(settings.network.proxy);
|
||||
|
||||
@@ -61,9 +61,39 @@ export interface CacheItem {
|
||||
};
|
||||
}
|
||||
|
||||
export interface DNSAddresses {
|
||||
ipv4: number;
|
||||
ipv6: number;
|
||||
}
|
||||
|
||||
export interface DNSRecord {
|
||||
addresses: DNSAddresses;
|
||||
activeAddress: string;
|
||||
family: number;
|
||||
age: number;
|
||||
ttl: number;
|
||||
networkErrors: number;
|
||||
hits: number;
|
||||
misses: number;
|
||||
}
|
||||
|
||||
export interface DNSStats {
|
||||
size: number;
|
||||
maxSize: number;
|
||||
hits: number;
|
||||
misses: number;
|
||||
failures: number;
|
||||
ipv4Fallbacks: number;
|
||||
hitRate: number;
|
||||
}
|
||||
|
||||
export interface CacheResponse {
|
||||
apiCaches: CacheItem[];
|
||||
imageCache: Record<'tmdb' | 'avatar', { size: number; imageCount: number }>;
|
||||
dnsCache: {
|
||||
entries: Record<string, DNSRecord>;
|
||||
stats: DNSStats;
|
||||
};
|
||||
}
|
||||
|
||||
export interface StatusResponse {
|
||||
|
||||
@@ -100,17 +100,6 @@ interface Quota {
|
||||
quotaDays?: number;
|
||||
}
|
||||
|
||||
export interface ProxySettings {
|
||||
enabled: boolean;
|
||||
hostname: string;
|
||||
port: number;
|
||||
useSsl: boolean;
|
||||
user: string;
|
||||
password: string;
|
||||
bypassFilter: string;
|
||||
bypassLocalAddresses: boolean;
|
||||
}
|
||||
|
||||
export interface MainSettings {
|
||||
apiKey: string;
|
||||
applicationTitle: string;
|
||||
@@ -138,11 +127,29 @@ export interface MainSettings {
|
||||
youtubeUrl: string;
|
||||
}
|
||||
|
||||
export interface ProxySettings {
|
||||
enabled: boolean;
|
||||
hostname: string;
|
||||
port: number;
|
||||
useSsl: boolean;
|
||||
user: string;
|
||||
password: string;
|
||||
bypassFilter: string;
|
||||
bypassLocalAddresses: boolean;
|
||||
}
|
||||
|
||||
export interface DnsCacheSettings {
|
||||
enabled: boolean;
|
||||
forceMinTtl?: number;
|
||||
forceMaxTtl?: number;
|
||||
}
|
||||
|
||||
export interface NetworkSettings {
|
||||
csrfProtection: boolean;
|
||||
forceIpv4First: boolean;
|
||||
trustProxy: boolean;
|
||||
proxy: ProxySettings;
|
||||
dnsCache: DnsCacheSettings;
|
||||
}
|
||||
|
||||
interface PublicSettings {
|
||||
@@ -542,6 +549,11 @@ class Settings {
|
||||
bypassFilter: '',
|
||||
bypassLocalAddresses: true,
|
||||
},
|
||||
dnsCache: {
|
||||
enabled: false,
|
||||
forceMinTtl: 0,
|
||||
forceMaxTtl: -1,
|
||||
},
|
||||
},
|
||||
};
|
||||
if (initialSettings) {
|
||||
|
||||
@@ -28,6 +28,7 @@ import discoverSettingRoutes from '@server/routes/settings/discover';
|
||||
import { ApiError } from '@server/types/error';
|
||||
import { appDataPath } from '@server/utils/appDataVolume';
|
||||
import { getAppVersion } from '@server/utils/appVersion';
|
||||
import dnsCache from '@server/utils/dnsCache';
|
||||
import { getHostname } from '@server/utils/getHostname';
|
||||
import { Router } from 'express';
|
||||
import rateLimit from 'express-rate-limit';
|
||||
@@ -755,12 +756,19 @@ settingsRoutes.get('/cache', async (_req, res) => {
|
||||
const tmdbImageCache = await ImageProxy.getImageStats('tmdb');
|
||||
const avatarImageCache = await ImageProxy.getImageStats('avatar');
|
||||
|
||||
const stats = dnsCache?.getStats();
|
||||
const entries = dnsCache?.getCacheEntries();
|
||||
|
||||
return res.status(200).json({
|
||||
apiCaches,
|
||||
imageCache: {
|
||||
tmdb: tmdbImageCache,
|
||||
avatar: avatarImageCache,
|
||||
},
|
||||
dnsCache: {
|
||||
stats,
|
||||
entries,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
@@ -778,6 +786,20 @@ settingsRoutes.post<{ cacheId: AvailableCacheIds }>(
|
||||
}
|
||||
);
|
||||
|
||||
settingsRoutes.post<{ dnsEntry: string }>(
|
||||
'/cache/dns/:dnsEntry/flush',
|
||||
(req, res, next) => {
|
||||
const dnsEntry = req.params.dnsEntry;
|
||||
|
||||
if (dnsCache) {
|
||||
dnsCache.clear(dnsEntry);
|
||||
return res.status(204).send();
|
||||
}
|
||||
|
||||
next({ status: 404, message: 'Cache not found.' });
|
||||
}
|
||||
);
|
||||
|
||||
settingsRoutes.post(
|
||||
'/initialize',
|
||||
isAuthenticated(Permission.ADMIN),
|
||||
|
||||
28
server/utils/dnsCache.ts
Normal file
28
server/utils/dnsCache.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import logger from '@server/logger';
|
||||
import { DnsCacheManager } from 'dns-caching';
|
||||
|
||||
let dnsCache: DnsCacheManager | undefined;
|
||||
|
||||
export function initializeDnsCache({
|
||||
forceMinTtl,
|
||||
forceMaxTtl,
|
||||
}: {
|
||||
forceMinTtl?: number;
|
||||
forceMaxTtl?: number;
|
||||
}) {
|
||||
if (dnsCache) {
|
||||
logger.warn('DNS Cache is already initialized', { label: 'DNS Cache' });
|
||||
return;
|
||||
}
|
||||
|
||||
logger.info('Initializing DNS Cache', { label: 'DNS Cache' });
|
||||
|
||||
dnsCache = new DnsCacheManager({
|
||||
logger,
|
||||
forceMinTtl: typeof forceMinTtl === 'number' ? forceMinTtl * 1000 : 0,
|
||||
forceMaxTtl: typeof forceMaxTtl === 'number' ? forceMaxTtl * 1000 : -1,
|
||||
});
|
||||
dnsCache.initialize();
|
||||
}
|
||||
|
||||
export default dnsCache;
|
||||
@@ -22,6 +22,7 @@ import type {
|
||||
import type { JobId } from '@server/lib/settings';
|
||||
import axios from 'axios';
|
||||
import cronstrue from 'cronstrue/i18n';
|
||||
import { formatDuration, intervalToDuration } from 'date-fns';
|
||||
import { Fragment, useReducer, useState } from 'react';
|
||||
import type { MessageDescriptor } from 'react-intl';
|
||||
import { FormattedRelativeTime, useIntl } from 'react-intl';
|
||||
@@ -55,6 +56,26 @@ const messages: { [messageName: string]: MessageDescriptor } = defineMessages(
|
||||
cacheksize: 'Key Size',
|
||||
cachevsize: 'Value Size',
|
||||
flushcache: 'Flush Cache',
|
||||
dnsCache: 'DNS Cache',
|
||||
dnsCacheDescription:
|
||||
'Jellyseerr caches DNS lookups to optimize performance and avoid making unnecessary API calls.',
|
||||
dnscacheflushed: '{hostname} dns cache flushed.',
|
||||
dnscachename: 'Hostname',
|
||||
dnscacheactiveaddress: 'Active Address',
|
||||
dnscachehits: 'Hits',
|
||||
dnscachemisses: 'Misses',
|
||||
dnscacheage: 'Age',
|
||||
dnscachenetworkerrors: 'Network Errors',
|
||||
flushdnscache: 'Flush DNS Cache',
|
||||
dnsCacheGlobalStats: 'Global DNS Cache Stats',
|
||||
dnsCacheGlobalStatsDescription:
|
||||
'These stats are aggregated across all DNS cache entries.',
|
||||
size: 'Size',
|
||||
hits: 'Hits',
|
||||
misses: 'Misses',
|
||||
failures: 'Failures',
|
||||
ipv4Fallbacks: 'IPv4 Fallbacks',
|
||||
hitRate: 'Hit Rate',
|
||||
unknownJob: 'Unknown Job',
|
||||
'plex-recently-added-scan': 'Plex Recently Added Scan',
|
||||
'plex-full-scan': 'Plex Full Library Scan',
|
||||
@@ -242,6 +263,18 @@ const SettingsJobs = () => {
|
||||
cacheRevalidate();
|
||||
};
|
||||
|
||||
const flushDnsCache = async (hostname: string) => {
|
||||
await axios.post(`/api/v1/settings/cache/dns/${hostname}/flush`);
|
||||
addToast(
|
||||
intl.formatMessage(messages.dnscacheflushed, { hostname: hostname }),
|
||||
{
|
||||
appearance: 'success',
|
||||
autoDismiss: true,
|
||||
}
|
||||
);
|
||||
cacheRevalidate();
|
||||
};
|
||||
|
||||
const scheduleJob = async () => {
|
||||
const jobScheduleCron = ['0', '0', '*', '*', '*', '*'];
|
||||
|
||||
@@ -285,6 +318,18 @@ const SettingsJobs = () => {
|
||||
}
|
||||
};
|
||||
|
||||
const formatAge = (milliseconds: number): string => {
|
||||
const duration = intervalToDuration({
|
||||
start: 0,
|
||||
end: milliseconds,
|
||||
});
|
||||
|
||||
return formatDuration(duration, {
|
||||
format: ['minutes', 'seconds'],
|
||||
zero: false,
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<PageTitle
|
||||
@@ -567,6 +612,95 @@ const SettingsJobs = () => {
|
||||
</Table.TBody>
|
||||
</Table>
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="heading">{intl.formatMessage(messages.dnsCache)}</h3>
|
||||
<p className="description">
|
||||
{intl.formatMessage(messages.dnsCacheDescription)}
|
||||
</p>
|
||||
</div>
|
||||
<div className="section">
|
||||
<Table>
|
||||
<thead>
|
||||
<tr>
|
||||
<Table.TH>{intl.formatMessage(messages.dnscachename)}</Table.TH>
|
||||
<Table.TH>
|
||||
{intl.formatMessage(messages.dnscacheactiveaddress)}
|
||||
</Table.TH>
|
||||
<Table.TH>{intl.formatMessage(messages.dnscachehits)}</Table.TH>
|
||||
<Table.TH>{intl.formatMessage(messages.dnscachemisses)}</Table.TH>
|
||||
<Table.TH>{intl.formatMessage(messages.dnscacheage)}</Table.TH>
|
||||
<Table.TH>
|
||||
{intl.formatMessage(messages.dnscachenetworkerrors)}
|
||||
</Table.TH>
|
||||
<Table.TH></Table.TH>
|
||||
</tr>
|
||||
</thead>
|
||||
<Table.TBody>
|
||||
{Object.entries(cacheData?.dnsCache.entries || {}).map(
|
||||
([hostname, data]) => (
|
||||
<tr key={`cache-list-${hostname}`}>
|
||||
<Table.TD>{hostname}</Table.TD>
|
||||
<Table.TD>{data.activeAddress}</Table.TD>
|
||||
<Table.TD>{intl.formatNumber(data.hits)}</Table.TD>
|
||||
<Table.TD>{intl.formatNumber(data.misses)}</Table.TD>
|
||||
<Table.TD>{formatAge(data.age)}</Table.TD>
|
||||
<Table.TD>{intl.formatNumber(data.networkErrors)}</Table.TD>
|
||||
<Table.TD alignText="right">
|
||||
<Button
|
||||
buttonType="danger"
|
||||
onClick={() => flushDnsCache(hostname)}
|
||||
>
|
||||
<TrashIcon />
|
||||
<span>{intl.formatMessage(messages.flushdnscache)}</span>
|
||||
</Button>
|
||||
</Table.TD>
|
||||
</tr>
|
||||
)
|
||||
)}
|
||||
</Table.TBody>
|
||||
</Table>
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="heading">
|
||||
{intl.formatMessage(messages.dnsCacheGlobalStats)}
|
||||
</h3>
|
||||
<p className="description">
|
||||
{intl.formatMessage(messages.dnsCacheGlobalStatsDescription)}
|
||||
</p>
|
||||
</div>
|
||||
<div className="section">
|
||||
<Table>
|
||||
<thead>
|
||||
<tr>
|
||||
{Object.entries(cacheData?.dnsCache.stats || {})
|
||||
.filter(([statName]) => statName !== 'maxSize')
|
||||
.map(([statName]) => (
|
||||
<Table.TH key={`dns-stat-header-${statName}`}>
|
||||
{messages[statName]
|
||||
? intl.formatMessage(messages[statName])
|
||||
: statName}
|
||||
</Table.TH>
|
||||
))}
|
||||
</tr>
|
||||
</thead>
|
||||
<Table.TBody>
|
||||
<tr>
|
||||
{Object.entries(cacheData?.dnsCache.stats || {})
|
||||
.filter(([statName]) => statName !== 'maxSize')
|
||||
.map(([statName, statValue]) => (
|
||||
<Table.TD key={`dns-stat-${statName}`}>
|
||||
{statName === 'hitRate'
|
||||
? intl.formatNumber(statValue, {
|
||||
style: 'percent',
|
||||
maximumFractionDigits: 2,
|
||||
})
|
||||
: intl.formatNumber(statValue)}
|
||||
</Table.TD>
|
||||
))}
|
||||
</tr>
|
||||
</Table.TBody>
|
||||
</Table>
|
||||
</div>
|
||||
<div className="break-words">
|
||||
<h3 className="heading">{intl.formatMessage(messages.imagecache)}</h3>
|
||||
<p className="description">
|
||||
|
||||
@@ -45,6 +45,13 @@ const messages = defineMessages('components.Settings.SettingsNetwork', {
|
||||
forceIpv4First: 'Force IPv4 Resolution First',
|
||||
forceIpv4FirstTip:
|
||||
'Force Jellyseerr to resolve IPv4 addresses first instead of IPv6',
|
||||
dnsCache: 'DNS Cache',
|
||||
dnsCacheTip:
|
||||
'Enable caching of DNS lookups to optimize performance and avoid making unnecessary API calls',
|
||||
dnsCacheHoverTip:
|
||||
'Do NOT enable this if you are experiencing issues with DNS lookups',
|
||||
dnsCacheForceMinTtl: 'DNS Cache Minimum TTL',
|
||||
dnsCacheForceMaxTtl: 'DNS Cache Maximum TTL',
|
||||
});
|
||||
|
||||
const SettingsNetwork = () => {
|
||||
@@ -90,6 +97,9 @@ const SettingsNetwork = () => {
|
||||
initialValues={{
|
||||
csrfProtection: data?.csrfProtection,
|
||||
forceIpv4First: data?.forceIpv4First,
|
||||
dnsCacheEnabled: data?.dnsCache.enabled,
|
||||
dnsCacheForceMinTtl: data?.dnsCache.forceMinTtl,
|
||||
dnsCacheForceMaxTtl: data?.dnsCache.forceMaxTtl,
|
||||
trustProxy: data?.trustProxy,
|
||||
proxyEnabled: data?.proxy?.enabled,
|
||||
proxyHostname: data?.proxy?.hostname,
|
||||
@@ -108,6 +118,11 @@ const SettingsNetwork = () => {
|
||||
csrfProtection: values.csrfProtection,
|
||||
forceIpv4First: values.forceIpv4First,
|
||||
trustProxy: values.trustProxy,
|
||||
dnsCache: {
|
||||
enabled: values.dnsCacheEnabled,
|
||||
forceMinTtl: values.dnsCacheForceMinTtl,
|
||||
forceMaxTtl: values.dnsCacheForceMaxTtl,
|
||||
},
|
||||
proxy: {
|
||||
enabled: values.proxyEnabled,
|
||||
hostname: values.proxyHostname,
|
||||
@@ -221,6 +236,90 @@ const SettingsNetwork = () => {
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="form-row">
|
||||
<label htmlFor="dnsCacheEnabled" className="checkbox-label">
|
||||
<span className="mr-2">
|
||||
{intl.formatMessage(messages.dnsCache)}
|
||||
</span>
|
||||
<SettingsBadge badgeType="advanced" className="mr-2" />
|
||||
<SettingsBadge badgeType="restartRequired" />
|
||||
<SettingsBadge badgeType="experimental" className="mr-2" />
|
||||
<span className="label-tip">
|
||||
{intl.formatMessage(messages.dnsCacheTip)}
|
||||
</span>
|
||||
</label>
|
||||
<div className="form-input-area">
|
||||
<Tooltip
|
||||
content={intl.formatMessage(messages.dnsCacheHoverTip)}
|
||||
>
|
||||
<Field
|
||||
type="checkbox"
|
||||
id="dnsCacheEnabled"
|
||||
name="dnsCacheEnabled"
|
||||
onChange={() => {
|
||||
setFieldValue(
|
||||
'dnsCacheEnabled',
|
||||
!values.dnsCacheEnabled
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</div>
|
||||
{values.dnsCacheEnabled && (
|
||||
<>
|
||||
<div className="mr-2 ml-4">
|
||||
<div className="form-row">
|
||||
<label
|
||||
htmlFor="dnsCacheForceMinTtl"
|
||||
className="checkbox-label"
|
||||
>
|
||||
{intl.formatMessage(messages.dnsCacheForceMinTtl)}
|
||||
</label>
|
||||
<div className="form-input-area">
|
||||
<div className="form-input-field">
|
||||
<Field
|
||||
id="dnsCacheForceMinTtl"
|
||||
name="dnsCacheForceMinTtl"
|
||||
type="text"
|
||||
/>
|
||||
</div>
|
||||
{errors.dnsCacheForceMinTtl &&
|
||||
touched.dnsCacheForceMinTtl &&
|
||||
typeof errors.dnsCacheForceMinTtl === 'string' && (
|
||||
<div className="error">
|
||||
{errors.dnsCacheForceMinTtl}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="form-row">
|
||||
<label
|
||||
htmlFor="dnsCacheForceMaxTtl"
|
||||
className="checkbox-label"
|
||||
>
|
||||
{intl.formatMessage(messages.dnsCacheForceMaxTtl)}
|
||||
</label>
|
||||
<div className="form-input-area">
|
||||
<div className="form-input-field">
|
||||
<Field
|
||||
id="dnsCacheForceMaxTtl"
|
||||
name="dnsCacheForceMaxTtl"
|
||||
type="text"
|
||||
/>
|
||||
</div>
|
||||
{errors.dnsCacheForceMaxTtl &&
|
||||
touched.dnsCacheForceMaxTtl &&
|
||||
typeof errors.dnsCacheForceMaxTtl === 'string' && (
|
||||
<div className="error">
|
||||
{errors.dnsCacheForceMaxTtl}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
<div className="form-row">
|
||||
<label htmlFor="proxyEnabled" className="checkbox-label">
|
||||
<span className="mr-2">
|
||||
|
||||
@@ -873,6 +873,17 @@
|
||||
"components.Settings.SettingsJobsCache.cachevsize": "Value Size",
|
||||
"components.Settings.SettingsJobsCache.canceljob": "Cancel Job",
|
||||
"components.Settings.SettingsJobsCache.command": "Command",
|
||||
"components.Settings.SettingsJobsCache.dnsCache": "DNS Cache",
|
||||
"components.Settings.SettingsJobsCache.dnsCacheDescription": "Jellyseerr caches DNS lookups to optimize performance and avoid making unnecessary API calls.",
|
||||
"components.Settings.SettingsJobsCache.dnsCacheGlobalStats": "Global DNS Cache Stats",
|
||||
"components.Settings.SettingsJobsCache.dnsCacheGlobalStatsDescription": "These stats are aggregated across all DNS cache entries.",
|
||||
"components.Settings.SettingsJobsCache.dnscacheactiveaddress": "Active Address",
|
||||
"components.Settings.SettingsJobsCache.dnscacheage": "Age",
|
||||
"components.Settings.SettingsJobsCache.dnscacheflushed": "{hostname} dns cache flushed.",
|
||||
"components.Settings.SettingsJobsCache.dnscachehits": "Hits",
|
||||
"components.Settings.SettingsJobsCache.dnscachemisses": "Misses",
|
||||
"components.Settings.SettingsJobsCache.dnscachename": "Hostname",
|
||||
"components.Settings.SettingsJobsCache.dnscachenetworkerrors": "Network Errors",
|
||||
"components.Settings.SettingsJobsCache.download-sync": "Download Sync",
|
||||
"components.Settings.SettingsJobsCache.download-sync-reset": "Download Sync Reset",
|
||||
"components.Settings.SettingsJobsCache.editJobSchedule": "Modify Job",
|
||||
@@ -882,12 +893,17 @@
|
||||
"components.Settings.SettingsJobsCache.editJobScheduleSelectorHours": "Every {jobScheduleHours, plural, one {hour} other {{jobScheduleHours} hours}}",
|
||||
"components.Settings.SettingsJobsCache.editJobScheduleSelectorMinutes": "Every {jobScheduleMinutes, plural, one {minute} other {{jobScheduleMinutes} minutes}}",
|
||||
"components.Settings.SettingsJobsCache.editJobScheduleSelectorSeconds": "Every {jobScheduleSeconds, plural, one {second} other {{jobScheduleSeconds} seconds}}",
|
||||
"components.Settings.SettingsJobsCache.failures": "Failures",
|
||||
"components.Settings.SettingsJobsCache.flushcache": "Flush Cache",
|
||||
"components.Settings.SettingsJobsCache.flushdnscache": "Flush DNS Cache",
|
||||
"components.Settings.SettingsJobsCache.hitRate": "Hit Rate",
|
||||
"components.Settings.SettingsJobsCache.hits": "Hits",
|
||||
"components.Settings.SettingsJobsCache.image-cache-cleanup": "Image Cache Cleanup",
|
||||
"components.Settings.SettingsJobsCache.imagecache": "Image Cache",
|
||||
"components.Settings.SettingsJobsCache.imagecacheDescription": "When enabled in settings, Jellyseerr will proxy and cache images from pre-configured external sources. Cached images are saved into your config folder. You can find the files in <code>{appDataPath}/cache/images</code>.",
|
||||
"components.Settings.SettingsJobsCache.imagecachecount": "Images Cached",
|
||||
"components.Settings.SettingsJobsCache.imagecachesize": "Total Cache Size",
|
||||
"components.Settings.SettingsJobsCache.ipv4Fallbacks": "IPv4 Fallbacks",
|
||||
"components.Settings.SettingsJobsCache.jellyfin-full-scan": "Jellyfin Full Library Scan",
|
||||
"components.Settings.SettingsJobsCache.jellyfin-recently-added-scan": "Jellyfin Recently Added Scan",
|
||||
"components.Settings.SettingsJobsCache.jobScheduleEditFailed": "Something went wrong while saving the job.",
|
||||
@@ -899,6 +915,7 @@
|
||||
"components.Settings.SettingsJobsCache.jobsandcache": "Jobs & Cache",
|
||||
"components.Settings.SettingsJobsCache.jobstarted": "{jobname} started.",
|
||||
"components.Settings.SettingsJobsCache.jobtype": "Type",
|
||||
"components.Settings.SettingsJobsCache.misses": "Misses",
|
||||
"components.Settings.SettingsJobsCache.nextexecution": "Next Execution",
|
||||
"components.Settings.SettingsJobsCache.plex-full-scan": "Plex Full Library Scan",
|
||||
"components.Settings.SettingsJobsCache.plex-recently-added-scan": "Plex Recently Added Scan",
|
||||
@@ -908,6 +925,7 @@
|
||||
"components.Settings.SettingsJobsCache.process-blacklisted-tags": "Process Blacklisted Tags",
|
||||
"components.Settings.SettingsJobsCache.radarr-scan": "Radarr Scan",
|
||||
"components.Settings.SettingsJobsCache.runnow": "Run Now",
|
||||
"components.Settings.SettingsJobsCache.size": "Size",
|
||||
"components.Settings.SettingsJobsCache.sonarr-scan": "Sonarr Scan",
|
||||
"components.Settings.SettingsJobsCache.unknownJob": "Unknown Job",
|
||||
"components.Settings.SettingsJobsCache.usersavatars": "Users' Avatars",
|
||||
@@ -969,6 +987,9 @@
|
||||
"components.Settings.SettingsNetwork.csrfProtection": "Enable CSRF Protection",
|
||||
"components.Settings.SettingsNetwork.csrfProtectionHoverTip": "Do NOT enable this setting unless you understand what you are doing!",
|
||||
"components.Settings.SettingsNetwork.csrfProtectionTip": "Set external API access to read-only (requires HTTPS)",
|
||||
"components.Settings.SettingsNetwork.dnsCache": "DNS Cache",
|
||||
"components.Settings.SettingsNetwork.dnsCacheHoverTip": "Do NOT enable this if you are experiencing issues with DNS lookups",
|
||||
"components.Settings.SettingsNetwork.dnsCacheTip": "Enable caching of DNS lookups to optimize performance and avoid making unnecessary API calls",
|
||||
"components.Settings.SettingsNetwork.docs": "documentation",
|
||||
"components.Settings.SettingsNetwork.forceIpv4First": "Force IPv4 Resolution First",
|
||||
"components.Settings.SettingsNetwork.forceIpv4FirstTip": "Force Jellyseerr to resolve IPv4 addresses first instead of IPv6",
|
||||
|
||||
Reference in New Issue
Block a user