Use anilist.xml to handle weird anime names & have anidb IDs (#1376)

This commit is contained in:
Zoe Roux 2026-03-18 19:56:12 +01:00 committed by GitHub
commit 02ad4dabcd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
57 changed files with 1334 additions and 530 deletions

View File

@ -8,42 +8,42 @@
"@elysiajs/opentelemetry": "^1.4.10",
"@elysiajs/swagger": "zoriya/elysia-swagger#build",
"@kubiks/otel-drizzle": "zoriya/drizzle-otel#build",
"@logtape/elysia": "2.0.2",
"@logtape/logtape": "2.0.2",
"@logtape/otel": "2.0.2",
"@logtape/redaction": "2.0.2",
"@logtape/elysia": "2.0.4",
"@logtape/logtape": "2.0.4",
"@logtape/otel": "2.0.4",
"@logtape/redaction": "2.0.4",
"@opentelemetry/api": "^1.9.0",
"@opentelemetry/api-logs": "^0.212.0",
"@opentelemetry/core": "^2.5.1",
"@opentelemetry/exporter-logs-otlp-grpc": "^0.212.0",
"@opentelemetry/exporter-logs-otlp-http": "^0.212.0",
"@opentelemetry/exporter-logs-otlp-proto": "^0.212.0",
"@opentelemetry/exporter-metrics-otlp-grpc": "^0.212.0",
"@opentelemetry/exporter-metrics-otlp-http": "^0.212.0",
"@opentelemetry/exporter-metrics-otlp-proto": "^0.212.0",
"@opentelemetry/exporter-trace-otlp-grpc": "^0.212.0",
"@opentelemetry/exporter-trace-otlp-http": "^0.212.0",
"@opentelemetry/exporter-trace-otlp-proto": "^0.212.0",
"@opentelemetry/resources": "^2.5.1",
"@opentelemetry/sdk-logs": "^0.212.0",
"@opentelemetry/sdk-metrics": "^2.5.1",
"@opentelemetry/sdk-trace-base": "^2.5.1",
"@opentelemetry/sdk-trace-node": "^2.5.1",
"@opentelemetry/semantic-conventions": "^1.39.0",
"@types/bun": "^1.3.9",
"@opentelemetry/api-logs": "^0.213.0",
"@opentelemetry/core": "^2.6.0",
"@opentelemetry/exporter-logs-otlp-grpc": "^0.213.0",
"@opentelemetry/exporter-logs-otlp-http": "^0.213.0",
"@opentelemetry/exporter-logs-otlp-proto": "^0.213.0",
"@opentelemetry/exporter-metrics-otlp-grpc": "^0.213.0",
"@opentelemetry/exporter-metrics-otlp-http": "^0.213.0",
"@opentelemetry/exporter-metrics-otlp-proto": "^0.213.0",
"@opentelemetry/exporter-trace-otlp-grpc": "^0.213.0",
"@opentelemetry/exporter-trace-otlp-http": "^0.213.0",
"@opentelemetry/exporter-trace-otlp-proto": "^0.213.0",
"@opentelemetry/resources": "^2.6.0",
"@opentelemetry/sdk-logs": "^0.213.0",
"@opentelemetry/sdk-metrics": "^2.6.0",
"@opentelemetry/sdk-trace-base": "^2.6.0",
"@opentelemetry/sdk-trace-node": "^2.6.0",
"@opentelemetry/semantic-conventions": "^1.40.0",
"@types/bun": "^1.3.10",
"blurhash": "^2.0.5",
"drizzle-kit": "^0.31.5",
"drizzle-orm": "0.44.7",
"elysia": "^1.4.25",
"jose": "^6.1.3",
"node-addon-api": "^8.5.0",
"elysia": "^1.4.28",
"jose": "^6.2.1",
"node-addon-api": "^8.6.0",
"parjs": "^1.3.9",
"pg": "^8.17.2",
"pg": "^8.20.0",
"sharp": "^0.34.5",
},
"devDependencies": {
"@biomejs/biome": "2.4.4",
"@types/pg": "^8.16.0",
"@biomejs/biome": "2.4.7",
"@types/pg": "^8.18.0",
"typescript": "^5.9.3",
},
},
@ -52,23 +52,23 @@
"drizzle-orm@0.44.7": "patches/drizzle-orm@0.44.7.patch",
},
"packages": {
"@biomejs/biome": ["@biomejs/biome@2.4.4", "", { "optionalDependencies": { "@biomejs/cli-darwin-arm64": "2.4.4", "@biomejs/cli-darwin-x64": "2.4.4", "@biomejs/cli-linux-arm64": "2.4.4", "@biomejs/cli-linux-arm64-musl": "2.4.4", "@biomejs/cli-linux-x64": "2.4.4", "@biomejs/cli-linux-x64-musl": "2.4.4", "@biomejs/cli-win32-arm64": "2.4.4", "@biomejs/cli-win32-x64": "2.4.4" }, "bin": { "biome": "bin/biome" } }, "sha512-tigwWS5KfJf0cABVd52NVaXyAVv4qpUXOWJ1rxFL8xF1RVoeS2q/LK+FHgYoKMclJCuRoCWAPy1IXaN9/mS61Q=="],
"@biomejs/biome": ["@biomejs/biome@2.4.7", "", { "optionalDependencies": { "@biomejs/cli-darwin-arm64": "2.4.7", "@biomejs/cli-darwin-x64": "2.4.7", "@biomejs/cli-linux-arm64": "2.4.7", "@biomejs/cli-linux-arm64-musl": "2.4.7", "@biomejs/cli-linux-x64": "2.4.7", "@biomejs/cli-linux-x64-musl": "2.4.7", "@biomejs/cli-win32-arm64": "2.4.7", "@biomejs/cli-win32-x64": "2.4.7" }, "bin": { "biome": "bin/biome" } }, "sha512-vXrgcmNGZ4lpdwZSpMf1hWw1aWS6B+SyeSYKTLrNsiUsAdSRN0J4d/7mF3ogJFbIwFFSOL3wT92Zzxia/d5/ng=="],
"@biomejs/cli-darwin-arm64": ["@biomejs/cli-darwin-arm64@2.4.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-jZ+Xc6qvD6tTH5jM6eKX44dcbyNqJHssfl2nnwT6vma6B1sj7ZLTGIk6N5QwVBs5xGN52r3trk5fgd3sQ9We9A=="],
"@biomejs/cli-darwin-arm64": ["@biomejs/cli-darwin-arm64@2.4.7", "", { "os": "darwin", "cpu": "arm64" }, "sha512-Oo0cF5mHzmvDmTXw8XSjhCia8K6YrZnk7aCS54+/HxyMdZMruMO3nfpDsrlar/EQWe41r1qrwKiCa2QDYHDzWA=="],
"@biomejs/cli-darwin-x64": ["@biomejs/cli-darwin-x64@2.4.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-Dh1a/+W+SUCXhEdL7TiX3ArPTFCQKJTI1mGncZNWfO+6suk+gYA4lNyJcBB+pwvF49uw0pEbUS49BgYOY4hzUg=="],
"@biomejs/cli-darwin-x64": ["@biomejs/cli-darwin-x64@2.4.7", "", { "os": "darwin", "cpu": "x64" }, "sha512-I+cOG3sd/7HdFtvDSnF9QQPrWguUH7zrkIMMykM3PtfWU9soTcS2yRb9Myq6MHmzbeCT08D1UmY+BaiMl5CcoQ=="],
"@biomejs/cli-linux-arm64": ["@biomejs/cli-linux-arm64@2.4.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-V/NFfbWhsUU6w+m5WYbBenlEAz8eYnSqRMDMAW3K+3v0tYVkNyZn8VU0XPxk/lOqNXLSCCrV7FmV/u3SjCBShg=="],
"@biomejs/cli-linux-arm64": ["@biomejs/cli-linux-arm64@2.4.7", "", { "os": "linux", "cpu": "arm64" }, "sha512-om6FugwmibzfP/6ALj5WRDVSND4H2G9X0nkI1HZpp2ySf9lW2j0X68oQSaHEnls6666oy4KDsc5RFjT4m0kV0w=="],
"@biomejs/cli-linux-arm64-musl": ["@biomejs/cli-linux-arm64-musl@2.4.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-+sPAXq3bxmFwhVFJnSwkSF5Rw2ZAJMH3MF6C9IveAEOdSpgajPhoQhbbAK12SehN9j2QrHpk4J/cHsa/HqWaYQ=="],
"@biomejs/cli-linux-arm64-musl": ["@biomejs/cli-linux-arm64-musl@2.4.7", "", { "os": "linux", "cpu": "arm64" }, "sha512-I2NvM9KPb09jWml93O2/5WMfNR7Lee5Latag1JThDRMURVhPX74p9UDnyTw3Ae6cE1DgXfw7sqQgX7rkvpc0vw=="],
"@biomejs/cli-linux-x64": ["@biomejs/cli-linux-x64@2.4.4", "", { "os": "linux", "cpu": "x64" }, "sha512-R4+ZCDtG9kHArasyBO+UBD6jr/FcFCTH8QkNTOCu0pRJzCWyWC4EtZa2AmUZB5h3e0jD7bRV2KvrENcf8rndBg=="],
"@biomejs/cli-linux-x64": ["@biomejs/cli-linux-x64@2.4.7", "", { "os": "linux", "cpu": "x64" }, "sha512-bV8/uo2Tj+gumnk4sUdkerWyCPRabaZdv88IpbmDWARQQoA/Q0YaqPz1a+LSEDIL7OfrnPi9Hq1Llz4ZIGyIQQ=="],
"@biomejs/cli-linux-x64-musl": ["@biomejs/cli-linux-x64-musl@2.4.4", "", { "os": "linux", "cpu": "x64" }, "sha512-gGvFTGpOIQDb5CQ2VC0n9Z2UEqlP46c4aNgHmAMytYieTGEcfqhfCFnhs6xjt0S3igE6q5GLuIXtdQt3Izok+g=="],
"@biomejs/cli-linux-x64-musl": ["@biomejs/cli-linux-x64-musl@2.4.7", "", { "os": "linux", "cpu": "x64" }, "sha512-00kx4YrBMU8374zd2wHuRV5wseh0rom5HqRND+vDldJPrWwQw+mzd/d8byI9hPx926CG+vWzq6AeiT7Yi5y59g=="],
"@biomejs/cli-win32-arm64": ["@biomejs/cli-win32-arm64@2.4.4", "", { "os": "win32", "cpu": "arm64" }, "sha512-trzCqM7x+Gn832zZHgr28JoYagQNX4CZkUZhMUac2YxvvyDRLJDrb5m9IA7CaZLlX6lTQmADVfLEKP1et1Ma4Q=="],
"@biomejs/cli-win32-arm64": ["@biomejs/cli-win32-arm64@2.4.7", "", { "os": "win32", "cpu": "arm64" }, "sha512-hOUHBMlFCvDhu3WCq6vaBoG0dp0LkWxSEnEEsxxXvOa9TfT6ZBnbh72A/xBM7CBYB7WgwqboetzFEVDnMxelyw=="],
"@biomejs/cli-win32-x64": ["@biomejs/cli-win32-x64@2.4.4", "", { "os": "win32", "cpu": "x64" }, "sha512-gnOHKVPFAAPrpoPt2t+Q6FZ7RPry/FDV3GcpU53P3PtLNnQjBmKyN2Vh/JtqXet+H4pme8CC76rScwdjDcT1/A=="],
"@biomejs/cli-win32-x64": ["@biomejs/cli-win32-x64@2.4.7", "", { "os": "win32", "cpu": "x64" }, "sha512-qEpGjSkPC3qX4ycbMUthXvi9CkRq7kZpkqMY1OyhmYlYLnANnooDQ7hDerM8+0NJ+DZKVnsIc07h30XOpt7LtQ=="],
"@borewit/text-codec": ["@borewit/text-codec@0.2.1", "", {}, "sha512-k7vvKPbf7J2fZ5klGRD9AeKfUvojuZIQ3BT5u7Jfv+puwXkUBUT5PVyMDfJZpy30CBDXGMgw7fguK/lpOMBvgw=="],
@ -194,41 +194,41 @@
"@kubiks/otel-drizzle": ["@kubiks/otel-drizzle@github:zoriya/drizzle-otel#cc1d59b", { "peerDependencies": { "@opentelemetry/api": ">=1.9.0 <2.0.0", "drizzle-orm": ">=0.28.0" } }, "zoriya-drizzle-otel-cc1d59b", "sha512-H8EQ2UrVrF6Qt3NIer0++QuIsvIXN8FCMnAMMOMtmy1OSJ1ViziHnEMV+5QA3zGg5G7JgbNZ7hHCZd6bEqjdJQ=="],
"@logtape/elysia": ["@logtape/elysia@2.0.2", "", { "peerDependencies": { "@logtape/logtape": "^2.0.2", "elysia": "^1.4.0" } }, "sha512-PI5/1d2h33mDmSitCJe0Rwyq7LFTc5hn/iBRE4ZQNcmbWY3Au4RYbLscVShwm4PLWVkjexwuG4rXaM5zHGtAFA=="],
"@logtape/elysia": ["@logtape/elysia@2.0.4", "", { "peerDependencies": { "@logtape/logtape": "^2.0.4", "elysia": "^1.4.0" } }, "sha512-GwbgPSmhaHOq5zBW9iZnhjA5ci4ajJdY+35uJC0uMQWvC2l+YejeNes5iBnLwggqih8dLcXrW11N9SsuCqxiyA=="],
"@logtape/logtape": ["@logtape/logtape@2.0.2", "", {}, "sha512-cveUBLbCMFkvkLycP/2vNWvywl47JcJbazHIju94/QNGboZ/jyYAgZIm0ZXezAOx3eIz8OG1EOZ5CuQP3+2FQg=="],
"@logtape/logtape": ["@logtape/logtape@2.0.4", "", {}, "sha512-Z4COeAMdedcBFuFkXaPFvDPOVuHoEom1hwNnPCIkSyojyikuNguplwPoSG+kZthWrS7GiOJo1USQyjWwIFfTKA=="],
"@logtape/otel": ["@logtape/otel@2.0.2", "", { "dependencies": { "@opentelemetry/api": "^1.9.0", "@opentelemetry/api-logs": "^0.208.0", "@opentelemetry/exporter-logs-otlp-grpc": "^0.208.0", "@opentelemetry/exporter-logs-otlp-http": "^0.208.0", "@opentelemetry/exporter-logs-otlp-proto": "^0.208.0", "@opentelemetry/otlp-exporter-base": "^0.208.0", "@opentelemetry/resources": "^2.2.0", "@opentelemetry/sdk-logs": "^0.208.0", "@opentelemetry/semantic-conventions": "^1.38.0" }, "peerDependencies": { "@logtape/logtape": "^2.0.2" } }, "sha512-9XBu9S2feM6qRN2G/oDFkSXpA8bEaOBJtlzkTaJ5AMipKUumGDAXXtDo/m7rc5bXMkyqUju94uaZS5p11hm+MQ=="],
"@logtape/otel": ["@logtape/otel@2.0.4", "", { "dependencies": { "@opentelemetry/api": "^1.9.0", "@opentelemetry/api-logs": "^0.208.0", "@opentelemetry/exporter-logs-otlp-grpc": "^0.208.0", "@opentelemetry/exporter-logs-otlp-http": "^0.208.0", "@opentelemetry/exporter-logs-otlp-proto": "^0.208.0", "@opentelemetry/otlp-exporter-base": "^0.208.0", "@opentelemetry/resources": "^2.2.0", "@opentelemetry/sdk-logs": "^0.208.0", "@opentelemetry/semantic-conventions": "^1.38.0" }, "peerDependencies": { "@logtape/logtape": "^2.0.4" } }, "sha512-ywtbgRjMqTruves8TONHF7lvlWWNQudSSlI+EUH4JJGe9NDfvvoICLICS7Lsh75zRRoo2klLe0UkAe2SxAO8Zg=="],
"@logtape/redaction": ["@logtape/redaction@2.0.2", "", { "peerDependencies": { "@logtape/logtape": "^2.0.2" } }, "sha512-NSURYmPLk2E3H1VgxSqG1P65qScVWXntChS3pvXthku6v2E2bHWp+BvDYksoA15SNT7KtTXYgfsV2O3LCMJQrw=="],
"@logtape/redaction": ["@logtape/redaction@2.0.4", "", { "peerDependencies": { "@logtape/logtape": "^2.0.4" } }, "sha512-kDMm8GapB50GIa5v64nKAGiwRAeR2sll6Q7k/nrhNHiesR1mxsDFWivFfkcYegnHVDQW9dPWbIlh0iyvi0Lrfg=="],
"@opentelemetry/api": ["@opentelemetry/api@1.9.0", "", {}, "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg=="],
"@opentelemetry/api-logs": ["@opentelemetry/api-logs@0.212.0", "", { "dependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-TEEVrLbNROUkYY51sBJGk7lO/OLjuepch8+hmpM6ffMJQ2z/KVCjdHuCFX6fJj8OkJP2zckPjrJzQtXU3IAsFg=="],
"@opentelemetry/api-logs": ["@opentelemetry/api-logs@0.213.0", "", { "dependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-zRM5/Qj6G84Ej3F1yt33xBVY/3tnMxtL1fiDIxYbDWYaZ/eudVw3/PBiZ8G7JwUxXxjW8gU4g6LnOyfGKYHYgw=="],
"@opentelemetry/context-async-hooks": ["@opentelemetry/context-async-hooks@2.5.1", "", { "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, "sha512-MHbu8XxCHcBn6RwvCt2Vpn1WnLMNECfNKYB14LI5XypcgH4IE0/DiVifVR9tAkwPMyLXN8dOoPJfya3IryLQVw=="],
"@opentelemetry/context-async-hooks": ["@opentelemetry/context-async-hooks@2.6.0", "", { "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, "sha512-L8UyDwqpTcbkIK5cgwDRDYDoEhQoj8wp8BwsO19w3LB1Z41yEQm2VJyNfAi9DrLP/YTqXqWpKHyZfR9/tFYo1Q=="],
"@opentelemetry/core": ["@opentelemetry/core@2.5.1", "", { "dependencies": { "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, "sha512-Dwlc+3HAZqpgTYq0MUyZABjFkcrKTePwuiFVLjahGD8cx3enqihmpAmdgNFO1R4m/sIe5afjJrA25Prqy4NXlA=="],
"@opentelemetry/core": ["@opentelemetry/core@2.6.0", "", { "dependencies": { "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, "sha512-HLM1v2cbZ4TgYN6KEOj+Bbj8rAKriOdkF9Ed3tG25FoprSiQl7kYc+RRT6fUZGOvx0oMi5U67GoFdT+XUn8zEg=="],
"@opentelemetry/exporter-logs-otlp-grpc": ["@opentelemetry/exporter-logs-otlp-grpc@0.212.0", "", { "dependencies": { "@grpc/grpc-js": "^1.14.3", "@opentelemetry/core": "2.5.1", "@opentelemetry/otlp-exporter-base": "0.212.0", "@opentelemetry/otlp-grpc-exporter-base": "0.212.0", "@opentelemetry/otlp-transformer": "0.212.0", "@opentelemetry/sdk-logs": "0.212.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-/0bk6fQG+eSFZ4L6NlckGTgUous/ib5+OVdg0x4OdwYeHzV3lTEo3it1HgnPY6UKpmX7ki+hJvxjsOql8rCeZA=="],
"@opentelemetry/exporter-logs-otlp-grpc": ["@opentelemetry/exporter-logs-otlp-grpc@0.213.0", "", { "dependencies": { "@grpc/grpc-js": "^1.14.3", "@opentelemetry/core": "2.6.0", "@opentelemetry/otlp-exporter-base": "0.213.0", "@opentelemetry/otlp-grpc-exporter-base": "0.213.0", "@opentelemetry/otlp-transformer": "0.213.0", "@opentelemetry/sdk-logs": "0.213.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-QiRZzvayEOFnenSXi85Eorgy5WTqyNQ+E7gjl6P6r+W3IUIwAIH8A9/BgMWfP056LwmdrBL6+qvnwaIEmug6Yg=="],
"@opentelemetry/exporter-logs-otlp-http": ["@opentelemetry/exporter-logs-otlp-http@0.212.0", "", { "dependencies": { "@opentelemetry/api-logs": "0.212.0", "@opentelemetry/core": "2.5.1", "@opentelemetry/otlp-exporter-base": "0.212.0", "@opentelemetry/otlp-transformer": "0.212.0", "@opentelemetry/sdk-logs": "0.212.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-JidJasLwG/7M9RTxV/64xotDKmFAUSBc9SNlxI32QYuUMK5rVKhHNWMPDzC7E0pCAL3cu+FyiKvsTwLi2KqPYw=="],
"@opentelemetry/exporter-logs-otlp-http": ["@opentelemetry/exporter-logs-otlp-http@0.213.0", "", { "dependencies": { "@opentelemetry/api-logs": "0.213.0", "@opentelemetry/core": "2.6.0", "@opentelemetry/otlp-exporter-base": "0.213.0", "@opentelemetry/otlp-transformer": "0.213.0", "@opentelemetry/sdk-logs": "0.213.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-vqDVSpLp09ZzcFIdb7QZrEFPxUlO3GzdhBKLstq3jhYB5ow3+ZtV5V0ngSdi/0BZs+J5WPiN1+UDV4X5zD/GzA=="],
"@opentelemetry/exporter-logs-otlp-proto": ["@opentelemetry/exporter-logs-otlp-proto@0.212.0", "", { "dependencies": { "@opentelemetry/api-logs": "0.212.0", "@opentelemetry/core": "2.5.1", "@opentelemetry/otlp-exporter-base": "0.212.0", "@opentelemetry/otlp-transformer": "0.212.0", "@opentelemetry/resources": "2.5.1", "@opentelemetry/sdk-logs": "0.212.0", "@opentelemetry/sdk-trace-base": "2.5.1" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-RpKB5UVfxc7c6Ta1UaCrxXDTQ0OD7BCGT66a97Q5zR1x3+9fw4dSaiqMXT/6FAWj2HyFbem6Rcu1UzPZikGTWQ=="],
"@opentelemetry/exporter-logs-otlp-proto": ["@opentelemetry/exporter-logs-otlp-proto@0.213.0", "", { "dependencies": { "@opentelemetry/api-logs": "0.213.0", "@opentelemetry/core": "2.6.0", "@opentelemetry/otlp-exporter-base": "0.213.0", "@opentelemetry/otlp-transformer": "0.213.0", "@opentelemetry/resources": "2.6.0", "@opentelemetry/sdk-logs": "0.213.0", "@opentelemetry/sdk-trace-base": "2.6.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-gQk41nqfK3KhDk8jbSo3LR/fQBlV7f6Q5xRcfDmL1hZlbgXQPdVFV9/rIfYUrCoq1OM+2NnKnFfGjBt6QpLSsA=="],
"@opentelemetry/exporter-metrics-otlp-grpc": ["@opentelemetry/exporter-metrics-otlp-grpc@0.212.0", "", { "dependencies": { "@grpc/grpc-js": "^1.14.3", "@opentelemetry/core": "2.5.1", "@opentelemetry/exporter-metrics-otlp-http": "0.212.0", "@opentelemetry/otlp-exporter-base": "0.212.0", "@opentelemetry/otlp-grpc-exporter-base": "0.212.0", "@opentelemetry/otlp-transformer": "0.212.0", "@opentelemetry/resources": "2.5.1", "@opentelemetry/sdk-metrics": "2.5.1" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-/6Gqf9wpBq22XsomR1i0iPGnbQtCq2Vwnrq5oiDPjYSqveBdK1jtQbhGfmpK2mLLxk4cPDtD1ZEYdIou5K8EaA=="],
"@opentelemetry/exporter-metrics-otlp-grpc": ["@opentelemetry/exporter-metrics-otlp-grpc@0.213.0", "", { "dependencies": { "@grpc/grpc-js": "^1.14.3", "@opentelemetry/core": "2.6.0", "@opentelemetry/exporter-metrics-otlp-http": "0.213.0", "@opentelemetry/otlp-exporter-base": "0.213.0", "@opentelemetry/otlp-grpc-exporter-base": "0.213.0", "@opentelemetry/otlp-transformer": "0.213.0", "@opentelemetry/resources": "2.6.0", "@opentelemetry/sdk-metrics": "2.6.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-Z8gYKUAU48qwm+a1tjnGv9xbE7a5lukVIwgF6Z5i3VPXPVMe4Sjra0nN3zU7m277h+V+ZpsPGZJ2Xf0OTkL7/w=="],
"@opentelemetry/exporter-metrics-otlp-http": ["@opentelemetry/exporter-metrics-otlp-http@0.212.0", "", { "dependencies": { "@opentelemetry/core": "2.5.1", "@opentelemetry/otlp-exporter-base": "0.212.0", "@opentelemetry/otlp-transformer": "0.212.0", "@opentelemetry/resources": "2.5.1", "@opentelemetry/sdk-metrics": "2.5.1" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-8hgBw3aTTRpSTkU4b9MLf/2YVLnfWp+hfnLq/1Fa2cky+vx6HqTodo+Zv1GTIrAKMOOwgysOjufy0gTxngqeBg=="],
"@opentelemetry/exporter-metrics-otlp-http": ["@opentelemetry/exporter-metrics-otlp-http@0.213.0", "", { "dependencies": { "@opentelemetry/core": "2.6.0", "@opentelemetry/otlp-exporter-base": "0.213.0", "@opentelemetry/otlp-transformer": "0.213.0", "@opentelemetry/resources": "2.6.0", "@opentelemetry/sdk-metrics": "2.6.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-yw3fTIw4KQIRXC/ZyYQq5gtA3Ogfdfz/g5HVgleobQAcjUUE8Nj3spGMx8iQPp+S+u6/js7BixufRkXhzLmpJA=="],
"@opentelemetry/exporter-metrics-otlp-proto": ["@opentelemetry/exporter-metrics-otlp-proto@0.212.0", "", { "dependencies": { "@opentelemetry/core": "2.5.1", "@opentelemetry/exporter-metrics-otlp-http": "0.212.0", "@opentelemetry/otlp-exporter-base": "0.212.0", "@opentelemetry/otlp-transformer": "0.212.0", "@opentelemetry/resources": "2.5.1", "@opentelemetry/sdk-metrics": "2.5.1" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-C7I4WN+ghn3g7SnxXm2RK3/sRD0k/BYcXaK6lGU3yPjiM7a1M25MLuM6zY3PeVPPzzTZPfuS7+wgn/tHk768Xw=="],
"@opentelemetry/exporter-metrics-otlp-proto": ["@opentelemetry/exporter-metrics-otlp-proto@0.213.0", "", { "dependencies": { "@opentelemetry/core": "2.6.0", "@opentelemetry/exporter-metrics-otlp-http": "0.213.0", "@opentelemetry/otlp-exporter-base": "0.213.0", "@opentelemetry/otlp-transformer": "0.213.0", "@opentelemetry/resources": "2.6.0", "@opentelemetry/sdk-metrics": "2.6.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-geHF+zZaDb0/WRkJTxR8o8dG4fCWT/Wq7HBdNZCxwH5mxhwRi/5f37IDYH7nvU+dwU6IeY4Pg8TPI435JCiNkg=="],
"@opentelemetry/exporter-prometheus": ["@opentelemetry/exporter-prometheus@0.200.0", "", { "dependencies": { "@opentelemetry/core": "2.0.0", "@opentelemetry/resources": "2.0.0", "@opentelemetry/sdk-metrics": "2.0.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-ZYdlU9r0USuuYppiDyU2VFRA0kFl855ylnb3N/2aOlXrbA4PMCznen7gmPbetGQu7pz8Jbaf4fwvrDnVdQQXSw=="],
"@opentelemetry/exporter-trace-otlp-grpc": ["@opentelemetry/exporter-trace-otlp-grpc@0.212.0", "", { "dependencies": { "@grpc/grpc-js": "^1.14.3", "@opentelemetry/core": "2.5.1", "@opentelemetry/otlp-exporter-base": "0.212.0", "@opentelemetry/otlp-grpc-exporter-base": "0.212.0", "@opentelemetry/otlp-transformer": "0.212.0", "@opentelemetry/resources": "2.5.1", "@opentelemetry/sdk-trace-base": "2.5.1" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-9xTuYWp8ClBhljDGAoa0NSsJcsxJsC9zCFKMSZJp1Osb9pjXCMRdA6fwXtlubyqe7w8FH16EWtQNKx/FWi+Ghw=="],
"@opentelemetry/exporter-trace-otlp-grpc": ["@opentelemetry/exporter-trace-otlp-grpc@0.213.0", "", { "dependencies": { "@grpc/grpc-js": "^1.14.3", "@opentelemetry/core": "2.6.0", "@opentelemetry/otlp-exporter-base": "0.213.0", "@opentelemetry/otlp-grpc-exporter-base": "0.213.0", "@opentelemetry/otlp-transformer": "0.213.0", "@opentelemetry/resources": "2.6.0", "@opentelemetry/sdk-trace-base": "2.6.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-L8y6piP4jBIIx1Nv7/9hkx25ql6/Cro/kQrs+f9e8bPF0Ar5Dm991v7PnbtubKz6Q4fT872H56QXUWVnz/Cs4Q=="],
"@opentelemetry/exporter-trace-otlp-http": ["@opentelemetry/exporter-trace-otlp-http@0.212.0", "", { "dependencies": { "@opentelemetry/core": "2.5.1", "@opentelemetry/otlp-exporter-base": "0.212.0", "@opentelemetry/otlp-transformer": "0.212.0", "@opentelemetry/resources": "2.5.1", "@opentelemetry/sdk-trace-base": "2.5.1" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-v/0wMozNoiEPRolzC4YoPo4rAT0q8r7aqdnRw3Nu7IDN0CGFzNQazkfAlBJ6N5y0FYJkban7Aw5WnN73//6YlA=="],
"@opentelemetry/exporter-trace-otlp-http": ["@opentelemetry/exporter-trace-otlp-http@0.213.0", "", { "dependencies": { "@opentelemetry/core": "2.6.0", "@opentelemetry/otlp-exporter-base": "0.213.0", "@opentelemetry/otlp-transformer": "0.213.0", "@opentelemetry/resources": "2.6.0", "@opentelemetry/sdk-trace-base": "2.6.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-tnRmJD39aWrE/Sp7F6AbRNAjKHToDkAqBi6i0lESpGWz3G+f4bhVAV6mgSXH2o18lrDVJXo6jf9bAywQw43wRA=="],
"@opentelemetry/exporter-trace-otlp-proto": ["@opentelemetry/exporter-trace-otlp-proto@0.212.0", "", { "dependencies": { "@opentelemetry/core": "2.5.1", "@opentelemetry/otlp-exporter-base": "0.212.0", "@opentelemetry/otlp-transformer": "0.212.0", "@opentelemetry/resources": "2.5.1", "@opentelemetry/sdk-trace-base": "2.5.1" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-d1ivqPT0V+i0IVOOdzGaLqonjtlk5jYrW7ItutWzXL/Mk+PiYb59dymy/i2reot9dDnBFWfrsvxyqdutGF5Vig=="],
"@opentelemetry/exporter-trace-otlp-proto": ["@opentelemetry/exporter-trace-otlp-proto@0.213.0", "", { "dependencies": { "@opentelemetry/core": "2.6.0", "@opentelemetry/otlp-exporter-base": "0.213.0", "@opentelemetry/otlp-transformer": "0.213.0", "@opentelemetry/resources": "2.6.0", "@opentelemetry/sdk-trace-base": "2.6.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-six3vPq3sL+ge1iZOfKEg+RHuFQhGb8ZTdlvD234w/0gi8ty/qKD46qoGpKvM3amy5yYunWBKiFBW47WaVS26w=="],
"@opentelemetry/exporter-zipkin": ["@opentelemetry/exporter-zipkin@2.0.0", "", { "dependencies": { "@opentelemetry/core": "2.0.0", "@opentelemetry/resources": "2.0.0", "@opentelemetry/sdk-trace-base": "2.0.0", "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": "^1.0.0" } }, "sha512-icxaKZ+jZL/NHXX8Aru4HGsrdhK0MLcuRXkX5G5IRmCgoRLw+Br6I/nMVozX2xjGGwV7hw2g+4Slj8K7s4HbVg=="],
@ -236,27 +236,27 @@
"@opentelemetry/otlp-exporter-base": ["@opentelemetry/otlp-exporter-base@0.208.0", "", { "dependencies": { "@opentelemetry/core": "2.2.0", "@opentelemetry/otlp-transformer": "0.208.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-gMd39gIfVb2OgxldxUtOwGJYSH8P1kVFFlJLuut32L6KgUC4gl1dMhn+YC2mGn0bDOiQYSk/uHOdSjuKp58vvA=="],
"@opentelemetry/otlp-grpc-exporter-base": ["@opentelemetry/otlp-grpc-exporter-base@0.212.0", "", { "dependencies": { "@grpc/grpc-js": "^1.14.3", "@opentelemetry/core": "2.5.1", "@opentelemetry/otlp-exporter-base": "0.212.0", "@opentelemetry/otlp-transformer": "0.212.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-YidOSlzpsun9uw0iyIWrQp6HxpMtBlECE3tiHGAsnpEqJWbAUWcMnIffvIuvTtTQ1OyRtwwaE79dWSQ8+eiB7g=="],
"@opentelemetry/otlp-grpc-exporter-base": ["@opentelemetry/otlp-grpc-exporter-base@0.213.0", "", { "dependencies": { "@grpc/grpc-js": "^1.14.3", "@opentelemetry/core": "2.6.0", "@opentelemetry/otlp-exporter-base": "0.213.0", "@opentelemetry/otlp-transformer": "0.213.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-XgRGuLE9usFNlnw2lgMIM4HTwpcIyjdU/xPoJ8v3LbBLBfjaDkIugjc9HoWa7ZSJ/9Bhzgvm/aD0bGdYUFgnTw=="],
"@opentelemetry/otlp-transformer": ["@opentelemetry/otlp-transformer@0.212.0", "", { "dependencies": { "@opentelemetry/api-logs": "0.212.0", "@opentelemetry/core": "2.5.1", "@opentelemetry/resources": "2.5.1", "@opentelemetry/sdk-logs": "0.212.0", "@opentelemetry/sdk-metrics": "2.5.1", "@opentelemetry/sdk-trace-base": "2.5.1", "protobufjs": "8.0.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-bj7zYFOg6Db7NUwsRZQ/WoVXpAf41WY2gsd3kShSfdpZQDRKHWJiRZIg7A8HvWsf97wb05rMFzPbmSHyjEl9tw=="],
"@opentelemetry/otlp-transformer": ["@opentelemetry/otlp-transformer@0.213.0", "", { "dependencies": { "@opentelemetry/api-logs": "0.213.0", "@opentelemetry/core": "2.6.0", "@opentelemetry/resources": "2.6.0", "@opentelemetry/sdk-logs": "0.213.0", "@opentelemetry/sdk-metrics": "2.6.0", "@opentelemetry/sdk-trace-base": "2.6.0", "protobufjs": "^7.0.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-RSuAlxFFPjeK4d5Y6ps8L2WhaQI6CXWllIjvo5nkAlBpmq2XdYWEBGiAbOF4nDs8CX4QblJDv5BbMUft3sEfDw=="],
"@opentelemetry/propagator-b3": ["@opentelemetry/propagator-b3@2.0.0", "", { "dependencies": { "@opentelemetry/core": "2.0.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, "sha512-blx9S2EI49Ycuw6VZq+bkpaIoiJFhsDuvFGhBIoH3vJ5oYjJ2U0s3fAM5jYft99xVIAv6HqoPtlP9gpVA2IZtA=="],
"@opentelemetry/propagator-jaeger": ["@opentelemetry/propagator-jaeger@2.0.0", "", { "dependencies": { "@opentelemetry/core": "2.0.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, "sha512-Mbm/LSFyAtQKP0AQah4AfGgsD+vsZcyreZoQ5okFBk33hU7AquU4TltgyL9dvaO8/Zkoud8/0gEvwfOZ5d7EPA=="],
"@opentelemetry/resources": ["@opentelemetry/resources@2.5.1", "", { "dependencies": { "@opentelemetry/core": "2.5.1", "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, "sha512-BViBCdE/GuXRlp9k7nS1w6wJvY5fnFX5XvuEtWsTAOQFIO89Eru7lGW3WbfbxtCuZ/GbrJfAziXG0w0dpxL7eQ=="],
"@opentelemetry/resources": ["@opentelemetry/resources@2.6.0", "", { "dependencies": { "@opentelemetry/core": "2.6.0", "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, "sha512-D4y/+OGe3JSuYUCBxtH5T9DSAWNcvCb/nQWIga8HNtXTVPQn59j0nTBAgaAXxUVBDl40mG3Tc76b46wPlZaiJQ=="],
"@opentelemetry/sdk-logs": ["@opentelemetry/sdk-logs@0.212.0", "", { "dependencies": { "@opentelemetry/api-logs": "0.212.0", "@opentelemetry/core": "2.5.1", "@opentelemetry/resources": "2.5.1" }, "peerDependencies": { "@opentelemetry/api": ">=1.4.0 <1.10.0" } }, "sha512-qglb5cqTf0mOC1sDdZ7nfrPjgmAqs2OxkzOPIf2+Rqx8yKBK0pS7wRtB1xH30rqahBIut9QJDbDePyvtyqvH/Q=="],
"@opentelemetry/sdk-logs": ["@opentelemetry/sdk-logs@0.213.0", "", { "dependencies": { "@opentelemetry/api-logs": "0.213.0", "@opentelemetry/core": "2.6.0", "@opentelemetry/resources": "2.6.0", "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.4.0 <1.10.0" } }, "sha512-00xlU3GZXo3kXKve4DLdrAL0NAFUaZ9appU/mn00S/5kSUdAvyYsORaDUfR04Mp2CLagAOhrzfUvYozY/EZX2g=="],
"@opentelemetry/sdk-metrics": ["@opentelemetry/sdk-metrics@2.5.1", "", { "dependencies": { "@opentelemetry/core": "2.5.1", "@opentelemetry/resources": "2.5.1" }, "peerDependencies": { "@opentelemetry/api": ">=1.9.0 <1.10.0" } }, "sha512-RKMn3QKi8nE71ULUo0g/MBvq1N4icEBo7cQSKnL3URZT16/YH3nSVgWegOjwx7FRBTrjOIkMJkCUn/ZFIEfn4A=="],
"@opentelemetry/sdk-metrics": ["@opentelemetry/sdk-metrics@2.6.0", "", { "dependencies": { "@opentelemetry/core": "2.6.0", "@opentelemetry/resources": "2.6.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.9.0 <1.10.0" } }, "sha512-CicxWZxX6z35HR83jl+PLgtFgUrKRQ9LCXyxgenMnz5A1lgYWfAog7VtdOvGkJYyQgMNPhXQwkYrDLujk7z1Iw=="],
"@opentelemetry/sdk-node": ["@opentelemetry/sdk-node@0.200.0", "", { "dependencies": { "@opentelemetry/api-logs": "0.200.0", "@opentelemetry/core": "2.0.0", "@opentelemetry/exporter-logs-otlp-grpc": "0.200.0", "@opentelemetry/exporter-logs-otlp-http": "0.200.0", "@opentelemetry/exporter-logs-otlp-proto": "0.200.0", "@opentelemetry/exporter-metrics-otlp-grpc": "0.200.0", "@opentelemetry/exporter-metrics-otlp-http": "0.200.0", "@opentelemetry/exporter-metrics-otlp-proto": "0.200.0", "@opentelemetry/exporter-prometheus": "0.200.0", "@opentelemetry/exporter-trace-otlp-grpc": "0.200.0", "@opentelemetry/exporter-trace-otlp-http": "0.200.0", "@opentelemetry/exporter-trace-otlp-proto": "0.200.0", "@opentelemetry/exporter-zipkin": "2.0.0", "@opentelemetry/instrumentation": "0.200.0", "@opentelemetry/propagator-b3": "2.0.0", "@opentelemetry/propagator-jaeger": "2.0.0", "@opentelemetry/resources": "2.0.0", "@opentelemetry/sdk-logs": "0.200.0", "@opentelemetry/sdk-metrics": "2.0.0", "@opentelemetry/sdk-trace-base": "2.0.0", "@opentelemetry/sdk-trace-node": "2.0.0", "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, "sha512-S/YSy9GIswnhYoDor1RusNkmRughipvTCOQrlF1dzI70yQaf68qgf5WMnzUxdlCl3/et/pvaO75xfPfuEmCK5A=="],
"@opentelemetry/sdk-trace-base": ["@opentelemetry/sdk-trace-base@2.5.1", "", { "dependencies": { "@opentelemetry/core": "2.5.1", "@opentelemetry/resources": "2.5.1", "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, "sha512-iZH3Gw8cxQn0gjpOjJMmKLd9GIaNh/E3v3ST67vyzLSxHBs14HsG4dy7jMYyC5WXGdBVEcM7U/XTF5hCQxjDMw=="],
"@opentelemetry/sdk-trace-base": ["@opentelemetry/sdk-trace-base@2.6.0", "", { "dependencies": { "@opentelemetry/core": "2.6.0", "@opentelemetry/resources": "2.6.0", "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, "sha512-g/OZVkqlxllgFM7qMKqbPV9c1DUPhQ7d4n3pgZFcrnrNft9eJXZM2TNHTPYREJBrtNdRytYyvwjgL5geDKl3EQ=="],
"@opentelemetry/sdk-trace-node": ["@opentelemetry/sdk-trace-node@2.5.1", "", { "dependencies": { "@opentelemetry/context-async-hooks": "2.5.1", "@opentelemetry/core": "2.5.1", "@opentelemetry/sdk-trace-base": "2.5.1" }, "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, "sha512-9lopQ6ZoElETOEN0csgmtEV5/9C7BMfA7VtF4Jape3i954b6sTY2k3Xw3CxUTKreDck/vpAuJM+EDo4zheUw+A=="],
"@opentelemetry/sdk-trace-node": ["@opentelemetry/sdk-trace-node@2.6.0", "", { "dependencies": { "@opentelemetry/context-async-hooks": "2.6.0", "@opentelemetry/core": "2.6.0", "@opentelemetry/sdk-trace-base": "2.6.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, "sha512-YhswtasmsbIGEFvLGvR9p/y3PVRTfFf+mgY8van4Ygpnv4sA3vooAjvh+qAn9PNWxs4/IwGGqiQS0PPsaRJ0vQ=="],
"@opentelemetry/semantic-conventions": ["@opentelemetry/semantic-conventions@1.39.0", "", {}, "sha512-R5R9tb2AXs2IRLNKLBJDynhkfmx7mX0vi8NkhZb3gUkPWHn6HXk5J8iQ/dql0U3ApfWym4kXXmBDRGO+oeOfjg=="],
"@opentelemetry/semantic-conventions": ["@opentelemetry/semantic-conventions@1.40.0", "", {}, "sha512-cifvXDhcqMwwTlTK04GBNeIe7yyo28Mfby85QXFe1Yk8nmi36Ab/5UQwptOx84SsoGNRg+EVSjwzfSZMy6pmlw=="],
"@protobufjs/aspromise": ["@protobufjs/aspromise@1.1.2", "", {}, "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ=="],
@ -290,11 +290,11 @@
"@tokenizer/token": ["@tokenizer/token@0.3.0", "", {}, "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A=="],
"@types/bun": ["@types/bun@1.3.9", "", { "dependencies": { "bun-types": "1.3.9" } }, "sha512-KQ571yULOdWJiMH+RIWIOZ7B2RXQGpL1YQrBtLIV3FqDcCu6FsbFUBwhdKUlCKUpS3PJDsHlJ1QKlpxoVR+xtw=="],
"@types/bun": ["@types/bun@1.3.10", "", { "dependencies": { "bun-types": "1.3.10" } }, "sha512-0+rlrUrOrTSskibryHbvQkDOWRJwJZqZlxrUs1u4oOoTln8+WIXBPmAuCF35SWB2z4Zl3E84Nl/D0P7803nigQ=="],
"@types/node": ["@types/node@25.2.2", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-BkmoP5/FhRYek5izySdkOneRyXYN35I860MFAGupTdebyE66uZaR+bXLHq8k4DirE5DwQi3NuhvRU1jqTVwUrQ=="],
"@types/pg": ["@types/pg@8.16.0", "", { "dependencies": { "@types/node": "*", "pg-protocol": "*", "pg-types": "^2.2.0" } }, "sha512-RmhMd/wD+CF8Dfo+cVIy3RR5cl8CyfXQ0tGgW6XBL8L4LM/UTEbNXYRbLwU6w+CgrKBNbrQWt4FUtTfaU5jSYQ=="],
"@types/pg": ["@types/pg@8.18.0", "", { "dependencies": { "@types/node": "*", "pg-protocol": "*", "pg-types": "^2.2.0" } }, "sha512-gT+oueVQkqnj6ajGJXblFR4iavIXWsGAFCk3dP4Kki5+a9R4NMt0JARdk6s8cUKcfUoqP5dAtDSLU8xYUTFV+Q=="],
"@types/shimmer": ["@types/shimmer@1.2.0", "", {}, "sha512-UE7oxhQLLd9gub6JKIAhDq06T0F6FnztwMNRvYgjeQSBeMc1ZG/tA47EwfduvkuQS8apbkM/lpLpWsaCeYsXVg=="],
@ -312,7 +312,7 @@
"buffer-from": ["buffer-from@1.1.2", "", {}, "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="],
"bun-types": ["bun-types@1.3.9", "", { "dependencies": { "@types/node": "*" } }, "sha512-+UBWWOakIP4Tswh0Bt0QD0alpTY8cb5hvgiYeWCMet9YukHbzuruIEeXC2D7nMJPB12kbh8C7XJykSexEqGKJg=="],
"bun-types": ["bun-types@1.3.10", "", { "dependencies": { "@types/node": "*" } }, "sha512-tcpfCCl6XWo6nCVnpcVrxQ+9AYN1iqMIzgrSKYMB/fjLtV2eyAVEg7AxQJuCq/26R6HpKWykQXuSOq/21RYcbg=="],
"char-info": ["char-info@0.3.6", "", { "dependencies": { "node-interval-tree": "^1.3.3" } }, "sha512-JskE1gqij+E0bHxs7hZt4h1xG3mvFntZGPn+jFWqImn2y/g53ugy/4J7/thcOCriiZFcLDFph4w+A0xbe2NFbg=="],
@ -330,18 +330,16 @@
"detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="],
"drizzle-kit": ["drizzle-kit@0.31.9", "", { "dependencies": { "@drizzle-team/brocli": "^0.10.2", "@esbuild-kit/esm-loader": "^2.5.5", "esbuild": "^0.25.4", "esbuild-register": "^3.5.0" }, "bin": { "drizzle-kit": "bin.cjs" } }, "sha512-GViD3IgsXn7trFyBUUHyTFBpH/FsHTxYJ66qdbVggxef4UBPHRYxQaRzYLTuekYnk9i5FIEL9pbBIwMqX/Uwrg=="],
"drizzle-kit": ["drizzle-kit@0.31.10", "", { "dependencies": { "@drizzle-team/brocli": "^0.10.2", "@esbuild-kit/esm-loader": "^2.5.5", "esbuild": "^0.25.4", "tsx": "^4.21.0" }, "bin": { "drizzle-kit": "bin.cjs" } }, "sha512-7OZcmQUrdGI+DUNNsKBn1aW8qSoKuTH7d0mYgSP8bAzdFzKoovxEFnoGQp2dVs82EOJeYycqRtciopszwUf8bw=="],
"drizzle-orm": ["drizzle-orm@0.44.7", "", { "peerDependencies": { "@aws-sdk/client-rds-data": ">=3", "@cloudflare/workers-types": ">=4", "@electric-sql/pglite": ">=0.2.0", "@libsql/client": ">=0.10.0", "@libsql/client-wasm": ">=0.10.0", "@neondatabase/serverless": ">=0.10.0", "@op-engineering/op-sqlite": ">=2", "@opentelemetry/api": "^1.4.1", "@planetscale/database": ">=1.13", "@prisma/client": "*", "@tidbcloud/serverless": "*", "@types/better-sqlite3": "*", "@types/pg": "*", "@types/sql.js": "*", "@upstash/redis": ">=1.34.7", "@vercel/postgres": ">=0.8.0", "@xata.io/client": "*", "better-sqlite3": ">=7", "bun-types": "*", "expo-sqlite": ">=14.0.0", "gel": ">=2", "knex": "*", "kysely": "*", "mysql2": ">=2", "pg": ">=8", "postgres": ">=3", "sql.js": ">=1", "sqlite3": ">=5" }, "optionalPeers": ["@aws-sdk/client-rds-data", "@cloudflare/workers-types", "@electric-sql/pglite", "@libsql/client", "@libsql/client-wasm", "@neondatabase/serverless", "@op-engineering/op-sqlite", "@opentelemetry/api", "@planetscale/database", "@prisma/client", "@tidbcloud/serverless", "@types/better-sqlite3", "@types/pg", "@types/sql.js", "@upstash/redis", "@vercel/postgres", "@xata.io/client", "better-sqlite3", "bun-types", "expo-sqlite", "gel", "knex", "kysely", "mysql2", "pg", "postgres", "sql.js", "sqlite3"] }, "sha512-quIpnYznjU9lHshEOAYLoZ9s3jweleHlZIAWR/jX9gAWNg/JhQ1wj0KGRf7/Zm+obRrYd9GjPVJg790QY9N5AQ=="],
"elysia": ["elysia@1.4.25", "", { "dependencies": { "cookie": "^1.1.1", "exact-mirror": "^0.2.7", "fast-decode-uri-component": "^1.0.1", "memoirist": "^0.4.0" }, "peerDependencies": { "@sinclair/typebox": ">= 0.34.0 < 1", "@types/bun": ">= 1.2.0", "file-type": ">= 20.0.0", "openapi-types": ">= 12.0.0", "typescript": ">= 5.0.0" }, "optionalPeers": ["@types/bun", "typescript"] }, "sha512-liKjavH99Gpzrv9cDil6uYWmPuqESfPFV1FIaFSd3iNqo3y7e29sN43VxFIK8tWWnyi6eDAmi2SZk8hNAMQMyg=="],
"elysia": ["elysia@1.4.28", "", { "dependencies": { "cookie": "^1.1.1", "exact-mirror": "^0.2.7", "fast-decode-uri-component": "^1.0.1", "memoirist": "^0.4.0" }, "peerDependencies": { "@sinclair/typebox": ">= 0.34.0 < 1", "@types/bun": ">= 1.2.0", "file-type": ">= 20.0.0", "openapi-types": ">= 12.0.0", "typescript": ">= 5.0.0" }, "optionalPeers": ["@types/bun", "typescript"] }, "sha512-Vrx8sBnvq8squS/3yNBzR1jBXI+SgmnmvwawPjNuEHndUe5l1jV2Gp6JJ4ulDkEB8On6bWmmuyPpA+bq4t+WYg=="],
"emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="],
"esbuild": ["esbuild@0.25.12", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.12", "@esbuild/android-arm": "0.25.12", "@esbuild/android-arm64": "0.25.12", "@esbuild/android-x64": "0.25.12", "@esbuild/darwin-arm64": "0.25.12", "@esbuild/darwin-x64": "0.25.12", "@esbuild/freebsd-arm64": "0.25.12", "@esbuild/freebsd-x64": "0.25.12", "@esbuild/linux-arm": "0.25.12", "@esbuild/linux-arm64": "0.25.12", "@esbuild/linux-ia32": "0.25.12", "@esbuild/linux-loong64": "0.25.12", "@esbuild/linux-mips64el": "0.25.12", "@esbuild/linux-ppc64": "0.25.12", "@esbuild/linux-riscv64": "0.25.12", "@esbuild/linux-s390x": "0.25.12", "@esbuild/linux-x64": "0.25.12", "@esbuild/netbsd-arm64": "0.25.12", "@esbuild/netbsd-x64": "0.25.12", "@esbuild/openbsd-arm64": "0.25.12", "@esbuild/openbsd-x64": "0.25.12", "@esbuild/openharmony-arm64": "0.25.12", "@esbuild/sunos-x64": "0.25.12", "@esbuild/win32-arm64": "0.25.12", "@esbuild/win32-ia32": "0.25.12", "@esbuild/win32-x64": "0.25.12" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg=="],
"esbuild-register": ["esbuild-register@3.6.0", "", { "dependencies": { "debug": "^4.3.4" }, "peerDependencies": { "esbuild": ">=0.12 <1" } }, "sha512-H2/S7Pm8a9CL1uhp9OvjwrBh5Pvx0H8qVOxNu8Wed9Y7qv56MPtq+GGM8RJpq6glYJn9Wspr8uw7l55uyinNeg=="],
"escalade": ["escalade@3.2.0", "", {}, "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="],
"exact-mirror": ["exact-mirror@0.2.7", "", { "peerDependencies": { "@sinclair/typebox": "^0.34.15" }, "optionalPeers": ["@sinclair/typebox"] }, "sha512-+MeEmDcLA4o/vjK2zujgk+1VTxPR4hdp23qLqkWfStbECtAq9gmsvQa3LW6z/0GXZyHJobrCnmy1cdeE7BjsYg=="],
@ -350,6 +348,8 @@
"file-type": ["file-type@21.3.0", "", { "dependencies": { "@tokenizer/inflate": "^0.4.1", "strtok3": "^10.3.4", "token-types": "^6.1.1", "uint8array-extras": "^1.4.0" } }, "sha512-8kPJMIGz1Yt/aPEwOsrR97ZyZaD1Iqm8PClb1nYFclUCkBi0Ma5IsYNQzvSFS9ib51lWyIw5mIT9rWzI/xjpzA=="],
"fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="],
"function-bind": ["function-bind@1.1.2", "", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="],
"get-caller-file": ["get-caller-file@2.0.5", "", {}, "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="],
@ -368,7 +368,7 @@
"is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="],
"jose": ["jose@6.1.3", "", {}, "sha512-0TpaTfihd4QMNwrz/ob2Bp7X04yuxJkjRGi4aKmOqwhov54i6u79oCv7T+C7lo70MKH6BesI3vscD1yb/yzKXQ=="],
"jose": ["jose@6.2.1", "", {}, "sha512-jUaKr1yrbfaImV7R2TN/b3IcZzsw38/chqMpo2XJ7i2F8AfM/lA4G1goC3JVEwg0H7UldTmSt3P68nt31W7/mw=="],
"lodash.camelcase": ["lodash.camelcase@4.3.0", "", {}, "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA=="],
@ -382,7 +382,7 @@
"nanoid": ["nanoid@5.1.6", "", { "bin": { "nanoid": "bin/nanoid.js" } }, "sha512-c7+7RQ+dMB5dPwwCp4ee1/iV/q2P6aK1mTZcfr1BTuVlyW9hJYiMPybJCcnBlQtuSmTIWNeazm/zqNoZSSElBg=="],
"node-addon-api": ["node-addon-api@8.5.0", "", {}, "sha512-/bRZty2mXUIFY/xU5HLvveNHlswNJej+RnxBjOMkidWfwZzgTbPG1E3K5TOxRLOR+5hX7bSofy8yf1hZevMS8A=="],
"node-addon-api": ["node-addon-api@8.6.0", "", {}, "sha512-gBVjCaqDlRUk0EwoPNKzIr9KkS9041G/q31IBShPs1Xz6UTA+EXdZADbzqAJQrpDRq71CIMnOP5VMut3SL0z5Q=="],
"node-interval-tree": ["node-interval-tree@1.3.3", "", { "dependencies": { "shallowequal": "^1.0.2" } }, "sha512-K9vk96HdTK5fEipJwxSvIIqwTqr4e3HRJeJrNxBSeVMNSC/JWARRaX7etOLOuTmrRMeOI/K5TCJu3aWIwZiNTw=="],
@ -394,15 +394,15 @@
"pathe": ["pathe@1.1.2", "", {}, "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ=="],
"pg": ["pg@8.18.0", "", { "dependencies": { "pg-connection-string": "^2.11.0", "pg-pool": "^3.11.0", "pg-protocol": "^1.11.0", "pg-types": "2.2.0", "pgpass": "1.0.5" }, "optionalDependencies": { "pg-cloudflare": "^1.3.0" }, "peerDependencies": { "pg-native": ">=3.0.1" }, "optionalPeers": ["pg-native"] }, "sha512-xqrUDL1b9MbkydY/s+VZ6v+xiMUmOUk7SS9d/1kpyQxoJ6U9AO1oIJyUWVZojbfe5Cc/oluutcgFG4L9RDP1iQ=="],
"pg": ["pg@8.20.0", "", { "dependencies": { "pg-connection-string": "^2.12.0", "pg-pool": "^3.13.0", "pg-protocol": "^1.13.0", "pg-types": "2.2.0", "pgpass": "1.0.5" }, "optionalDependencies": { "pg-cloudflare": "^1.3.0" }, "peerDependencies": { "pg-native": ">=3.0.1" }, "optionalPeers": ["pg-native"] }, "sha512-ldhMxz2r8fl/6QkXnBD3CR9/xg694oT6DZQ2s6c/RI28OjtSOpxnPrUCGOBJ46RCUxcWdx3p6kw/xnDHjKvaRA=="],
"pg-cloudflare": ["pg-cloudflare@1.3.0", "", {}, "sha512-6lswVVSztmHiRtD6I8hw4qP/nDm1EJbKMRhf3HCYaqud7frGysPv7FYJ5noZQdhQtN2xJnimfMtvQq21pdbzyQ=="],
"pg-connection-string": ["pg-connection-string@2.11.0", "", {}, "sha512-kecgoJwhOpxYU21rZjULrmrBJ698U2RxXofKVzOn5UDj61BPj/qMb7diYUR1nLScCDbrztQFl1TaQZT0t1EtzQ=="],
"pg-connection-string": ["pg-connection-string@2.12.0", "", {}, "sha512-U7qg+bpswf3Cs5xLzRqbXbQl85ng0mfSV/J0nnA31MCLgvEaAo7CIhmeyrmJpOr7o+zm0rXK+hNnT5l9RHkCkQ=="],
"pg-int8": ["pg-int8@1.0.1", "", {}, "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw=="],
"pg-pool": ["pg-pool@3.11.0", "", { "peerDependencies": { "pg": ">=8.0" } }, "sha512-MJYfvHwtGp870aeusDh+hg9apvOe2zmpZJpyt+BMtzUWlVqbhFmMK6bOBXLBUPd7iRtIF9fZplDc7KrPN3PN7w=="],
"pg-pool": ["pg-pool@3.13.0", "", { "peerDependencies": { "pg": ">=8.0" } }, "sha512-gB+R+Xud1gLFuRD/QgOIgGOBE2KCQPaPwkzBBGC9oG69pHTkhQeIuejVIk3/cnDyX39av2AxomQiyPT13WKHQA=="],
"pg-protocol": ["pg-protocol@1.11.0", "", {}, "sha512-pfsxk2M9M3BuGgDOfuy37VNRRX3jmKgMjcvAcWqNDpZSf4cUmv8HSOl5ViRQFsfARFn0KuUQTgLxVMbNq5NW3g=="],
@ -418,7 +418,7 @@
"postgres-interval": ["postgres-interval@1.2.0", "", { "dependencies": { "xtend": "^4.0.0" } }, "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ=="],
"protobufjs": ["protobufjs@8.0.0", "", { "dependencies": { "@protobufjs/aspromise": "^1.1.2", "@protobufjs/base64": "^1.1.2", "@protobufjs/codegen": "^2.0.4", "@protobufjs/eventemitter": "^1.1.0", "@protobufjs/fetch": "^1.1.0", "@protobufjs/float": "^1.0.2", "@protobufjs/inquire": "^1.1.0", "@protobufjs/path": "^1.1.2", "@protobufjs/pool": "^1.1.0", "@protobufjs/utf8": "^1.1.0", "@types/node": ">=13.7.0", "long": "^5.0.0" } }, "sha512-jx6+sE9h/UryaCZhsJWbJtTEy47yXoGNYI4z8ZaRncM0zBKeRqjO2JEcOUYwrYGb1WLhXM1FfMzW3annvFv0rw=="],
"protobufjs": ["protobufjs@7.5.4", "", { "dependencies": { "@protobufjs/aspromise": "^1.1.2", "@protobufjs/base64": "^1.1.2", "@protobufjs/codegen": "^2.0.4", "@protobufjs/eventemitter": "^1.1.0", "@protobufjs/fetch": "^1.1.0", "@protobufjs/float": "^1.0.2", "@protobufjs/inquire": "^1.1.0", "@protobufjs/path": "^1.1.2", "@protobufjs/pool": "^1.1.0", "@protobufjs/utf8": "^1.1.0", "@types/node": ">=13.7.0", "long": "^5.0.0" } }, "sha512-CvexbZtbov6jW2eXAvLukXjXUW1TzFaivC46BpWc/3BpcCysb5Vffu+B3XHMm8lVEuy2Mm4XGex8hBSg1yapPg=="],
"require-directory": ["require-directory@2.1.1", "", {}, "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q=="],
@ -454,6 +454,8 @@
"tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
"tsx": ["tsx@4.21.0", "", { "dependencies": { "esbuild": "~0.27.0", "get-tsconfig": "^4.7.5" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "bin": { "tsx": "dist/cli.mjs" } }, "sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw=="],
"type-fest": ["type-fest@4.41.0", "", {}, "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA=="],
"typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],
@ -478,8 +480,6 @@
"@esbuild-kit/core-utils/esbuild": ["esbuild@0.18.20", "", { "optionalDependencies": { "@esbuild/android-arm": "0.18.20", "@esbuild/android-arm64": "0.18.20", "@esbuild/android-x64": "0.18.20", "@esbuild/darwin-arm64": "0.18.20", "@esbuild/darwin-x64": "0.18.20", "@esbuild/freebsd-arm64": "0.18.20", "@esbuild/freebsd-x64": "0.18.20", "@esbuild/linux-arm": "0.18.20", "@esbuild/linux-arm64": "0.18.20", "@esbuild/linux-ia32": "0.18.20", "@esbuild/linux-loong64": "0.18.20", "@esbuild/linux-mips64el": "0.18.20", "@esbuild/linux-ppc64": "0.18.20", "@esbuild/linux-riscv64": "0.18.20", "@esbuild/linux-s390x": "0.18.20", "@esbuild/linux-x64": "0.18.20", "@esbuild/netbsd-x64": "0.18.20", "@esbuild/openbsd-x64": "0.18.20", "@esbuild/sunos-x64": "0.18.20", "@esbuild/win32-arm64": "0.18.20", "@esbuild/win32-ia32": "0.18.20", "@esbuild/win32-x64": "0.18.20" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA=="],
"@grpc/proto-loader/protobufjs": ["protobufjs@7.5.4", "", { "dependencies": { "@protobufjs/aspromise": "^1.1.2", "@protobufjs/base64": "^1.1.2", "@protobufjs/codegen": "^2.0.4", "@protobufjs/eventemitter": "^1.1.0", "@protobufjs/fetch": "^1.1.0", "@protobufjs/float": "^1.0.2", "@protobufjs/inquire": "^1.1.0", "@protobufjs/path": "^1.1.2", "@protobufjs/pool": "^1.1.0", "@protobufjs/utf8": "^1.1.0", "@types/node": ">=13.7.0", "long": "^5.0.0" } }, "sha512-CvexbZtbov6jW2eXAvLukXjXUW1TzFaivC46BpWc/3BpcCysb5Vffu+B3XHMm8lVEuy2Mm4XGex8hBSg1yapPg=="],
"@logtape/otel/@opentelemetry/api-logs": ["@opentelemetry/api-logs@0.208.0", "", { "dependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-CjruKY9V6NMssL/T1kAFgzosF1v9o6oeN+aX5JB/C/xPNtmgIJqcXHG7fA82Ou1zCpWGl4lROQUKwUNE1pMCyg=="],
"@logtape/otel/@opentelemetry/exporter-logs-otlp-grpc": ["@opentelemetry/exporter-logs-otlp-grpc@0.208.0", "", { "dependencies": { "@grpc/grpc-js": "^1.7.1", "@opentelemetry/core": "2.2.0", "@opentelemetry/otlp-exporter-base": "0.208.0", "@opentelemetry/otlp-grpc-exporter-base": "0.208.0", "@opentelemetry/otlp-transformer": "0.208.0", "@opentelemetry/sdk-logs": "0.208.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-AmZDKFzbq/idME/yq68M155CJW1y056MNBekH9OZewiZKaqgwYN4VYfn3mXVPftYsfrCM2r4V6tS8H2LmfiDCg=="],
@ -488,21 +488,19 @@
"@logtape/otel/@opentelemetry/exporter-logs-otlp-proto": ["@opentelemetry/exporter-logs-otlp-proto@0.208.0", "", { "dependencies": { "@opentelemetry/api-logs": "0.208.0", "@opentelemetry/core": "2.2.0", "@opentelemetry/otlp-exporter-base": "0.208.0", "@opentelemetry/otlp-transformer": "0.208.0", "@opentelemetry/resources": "2.2.0", "@opentelemetry/sdk-logs": "0.208.0", "@opentelemetry/sdk-trace-base": "2.2.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-Wy8dZm16AOfM7yddEzSFzutHZDZ6HspKUODSUJVjyhnZFMBojWDjSNgduyCMlw6qaxJYz0dlb0OEcb4Eme+BfQ=="],
"@logtape/otel/@opentelemetry/resources": ["@opentelemetry/resources@2.5.0", "", { "dependencies": { "@opentelemetry/core": "2.5.0", "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, "sha512-F8W52ApePshpoSrfsSk1H2yJn9aKjCrbpQF1M9Qii0GHzbfVeFUB+rc3X4aggyZD8x9Gu3Slua+s6krmq6Dt8g=="],
"@logtape/otel/@opentelemetry/sdk-logs": ["@opentelemetry/sdk-logs@0.208.0", "", { "dependencies": { "@opentelemetry/api-logs": "0.208.0", "@opentelemetry/core": "2.2.0", "@opentelemetry/resources": "2.2.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.4.0 <1.10.0" } }, "sha512-QlAyL1jRpOeaqx7/leG1vJMp84g0xKP6gJmfELBpnI4O/9xPX+Hu5m1POk9Kl+veNkyth5t19hRlN6tNY1sjbA=="],
"@opentelemetry/exporter-logs-otlp-grpc/@opentelemetry/otlp-exporter-base": ["@opentelemetry/otlp-exporter-base@0.212.0", "", { "dependencies": { "@opentelemetry/core": "2.5.1", "@opentelemetry/otlp-transformer": "0.212.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-HoMv5pQlzbuxiMS0hN7oiUtg8RsJR5T7EhZccumIWxYfNo/f4wFc7LPDfFK6oHdG2JF/+qTocfqIHoom+7kLpw=="],
"@opentelemetry/exporter-logs-otlp-grpc/@opentelemetry/otlp-exporter-base": ["@opentelemetry/otlp-exporter-base@0.213.0", "", { "dependencies": { "@opentelemetry/core": "2.6.0", "@opentelemetry/otlp-transformer": "0.213.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-MegxAP1/n09Ob2dQvY5NBDVjAFkZRuKtWKxYev1R2M8hrsgXzQGkaMgoEKeUOyQ0FUyYcO29UOnYdQWmWa0PXg=="],
"@opentelemetry/exporter-logs-otlp-http/@opentelemetry/otlp-exporter-base": ["@opentelemetry/otlp-exporter-base@0.212.0", "", { "dependencies": { "@opentelemetry/core": "2.5.1", "@opentelemetry/otlp-transformer": "0.212.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-HoMv5pQlzbuxiMS0hN7oiUtg8RsJR5T7EhZccumIWxYfNo/f4wFc7LPDfFK6oHdG2JF/+qTocfqIHoom+7kLpw=="],
"@opentelemetry/exporter-logs-otlp-http/@opentelemetry/otlp-exporter-base": ["@opentelemetry/otlp-exporter-base@0.213.0", "", { "dependencies": { "@opentelemetry/core": "2.6.0", "@opentelemetry/otlp-transformer": "0.213.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-MegxAP1/n09Ob2dQvY5NBDVjAFkZRuKtWKxYev1R2M8hrsgXzQGkaMgoEKeUOyQ0FUyYcO29UOnYdQWmWa0PXg=="],
"@opentelemetry/exporter-logs-otlp-proto/@opentelemetry/otlp-exporter-base": ["@opentelemetry/otlp-exporter-base@0.212.0", "", { "dependencies": { "@opentelemetry/core": "2.5.1", "@opentelemetry/otlp-transformer": "0.212.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-HoMv5pQlzbuxiMS0hN7oiUtg8RsJR5T7EhZccumIWxYfNo/f4wFc7LPDfFK6oHdG2JF/+qTocfqIHoom+7kLpw=="],
"@opentelemetry/exporter-logs-otlp-proto/@opentelemetry/otlp-exporter-base": ["@opentelemetry/otlp-exporter-base@0.213.0", "", { "dependencies": { "@opentelemetry/core": "2.6.0", "@opentelemetry/otlp-transformer": "0.213.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-MegxAP1/n09Ob2dQvY5NBDVjAFkZRuKtWKxYev1R2M8hrsgXzQGkaMgoEKeUOyQ0FUyYcO29UOnYdQWmWa0PXg=="],
"@opentelemetry/exporter-metrics-otlp-grpc/@opentelemetry/otlp-exporter-base": ["@opentelemetry/otlp-exporter-base@0.212.0", "", { "dependencies": { "@opentelemetry/core": "2.5.1", "@opentelemetry/otlp-transformer": "0.212.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-HoMv5pQlzbuxiMS0hN7oiUtg8RsJR5T7EhZccumIWxYfNo/f4wFc7LPDfFK6oHdG2JF/+qTocfqIHoom+7kLpw=="],
"@opentelemetry/exporter-metrics-otlp-grpc/@opentelemetry/otlp-exporter-base": ["@opentelemetry/otlp-exporter-base@0.213.0", "", { "dependencies": { "@opentelemetry/core": "2.6.0", "@opentelemetry/otlp-transformer": "0.213.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-MegxAP1/n09Ob2dQvY5NBDVjAFkZRuKtWKxYev1R2M8hrsgXzQGkaMgoEKeUOyQ0FUyYcO29UOnYdQWmWa0PXg=="],
"@opentelemetry/exporter-metrics-otlp-http/@opentelemetry/otlp-exporter-base": ["@opentelemetry/otlp-exporter-base@0.212.0", "", { "dependencies": { "@opentelemetry/core": "2.5.1", "@opentelemetry/otlp-transformer": "0.212.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-HoMv5pQlzbuxiMS0hN7oiUtg8RsJR5T7EhZccumIWxYfNo/f4wFc7LPDfFK6oHdG2JF/+qTocfqIHoom+7kLpw=="],
"@opentelemetry/exporter-metrics-otlp-http/@opentelemetry/otlp-exporter-base": ["@opentelemetry/otlp-exporter-base@0.213.0", "", { "dependencies": { "@opentelemetry/core": "2.6.0", "@opentelemetry/otlp-transformer": "0.213.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-MegxAP1/n09Ob2dQvY5NBDVjAFkZRuKtWKxYev1R2M8hrsgXzQGkaMgoEKeUOyQ0FUyYcO29UOnYdQWmWa0PXg=="],
"@opentelemetry/exporter-metrics-otlp-proto/@opentelemetry/otlp-exporter-base": ["@opentelemetry/otlp-exporter-base@0.212.0", "", { "dependencies": { "@opentelemetry/core": "2.5.1", "@opentelemetry/otlp-transformer": "0.212.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-HoMv5pQlzbuxiMS0hN7oiUtg8RsJR5T7EhZccumIWxYfNo/f4wFc7LPDfFK6oHdG2JF/+qTocfqIHoom+7kLpw=="],
"@opentelemetry/exporter-metrics-otlp-proto/@opentelemetry/otlp-exporter-base": ["@opentelemetry/otlp-exporter-base@0.213.0", "", { "dependencies": { "@opentelemetry/core": "2.6.0", "@opentelemetry/otlp-transformer": "0.213.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-MegxAP1/n09Ob2dQvY5NBDVjAFkZRuKtWKxYev1R2M8hrsgXzQGkaMgoEKeUOyQ0FUyYcO29UOnYdQWmWa0PXg=="],
"@opentelemetry/exporter-prometheus/@opentelemetry/core": ["@opentelemetry/core@2.0.0", "", { "dependencies": { "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, "sha512-SLX36allrcnVaPYG3R78F/UZZsBsvbc7lMCLx37LyH5MJ1KAAZ2E3mW9OAD3zGz0G8q/BtoS5VUrjzDydhD6LQ=="],
@ -510,11 +508,11 @@
"@opentelemetry/exporter-prometheus/@opentelemetry/sdk-metrics": ["@opentelemetry/sdk-metrics@2.0.0", "", { "dependencies": { "@opentelemetry/core": "2.0.0", "@opentelemetry/resources": "2.0.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.9.0 <1.10.0" } }, "sha512-Bvy8QDjO05umd0+j+gDeWcTaVa1/R2lDj/eOvjzpm8VQj1K1vVZJuyjThpV5/lSHyYW2JaHF2IQ7Z8twJFAhjA=="],
"@opentelemetry/exporter-trace-otlp-grpc/@opentelemetry/otlp-exporter-base": ["@opentelemetry/otlp-exporter-base@0.212.0", "", { "dependencies": { "@opentelemetry/core": "2.5.1", "@opentelemetry/otlp-transformer": "0.212.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-HoMv5pQlzbuxiMS0hN7oiUtg8RsJR5T7EhZccumIWxYfNo/f4wFc7LPDfFK6oHdG2JF/+qTocfqIHoom+7kLpw=="],
"@opentelemetry/exporter-trace-otlp-grpc/@opentelemetry/otlp-exporter-base": ["@opentelemetry/otlp-exporter-base@0.213.0", "", { "dependencies": { "@opentelemetry/core": "2.6.0", "@opentelemetry/otlp-transformer": "0.213.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-MegxAP1/n09Ob2dQvY5NBDVjAFkZRuKtWKxYev1R2M8hrsgXzQGkaMgoEKeUOyQ0FUyYcO29UOnYdQWmWa0PXg=="],
"@opentelemetry/exporter-trace-otlp-http/@opentelemetry/otlp-exporter-base": ["@opentelemetry/otlp-exporter-base@0.212.0", "", { "dependencies": { "@opentelemetry/core": "2.5.1", "@opentelemetry/otlp-transformer": "0.212.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-HoMv5pQlzbuxiMS0hN7oiUtg8RsJR5T7EhZccumIWxYfNo/f4wFc7LPDfFK6oHdG2JF/+qTocfqIHoom+7kLpw=="],
"@opentelemetry/exporter-trace-otlp-http/@opentelemetry/otlp-exporter-base": ["@opentelemetry/otlp-exporter-base@0.213.0", "", { "dependencies": { "@opentelemetry/core": "2.6.0", "@opentelemetry/otlp-transformer": "0.213.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-MegxAP1/n09Ob2dQvY5NBDVjAFkZRuKtWKxYev1R2M8hrsgXzQGkaMgoEKeUOyQ0FUyYcO29UOnYdQWmWa0PXg=="],
"@opentelemetry/exporter-trace-otlp-proto/@opentelemetry/otlp-exporter-base": ["@opentelemetry/otlp-exporter-base@0.212.0", "", { "dependencies": { "@opentelemetry/core": "2.5.1", "@opentelemetry/otlp-transformer": "0.212.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-HoMv5pQlzbuxiMS0hN7oiUtg8RsJR5T7EhZccumIWxYfNo/f4wFc7LPDfFK6oHdG2JF/+qTocfqIHoom+7kLpw=="],
"@opentelemetry/exporter-trace-otlp-proto/@opentelemetry/otlp-exporter-base": ["@opentelemetry/otlp-exporter-base@0.213.0", "", { "dependencies": { "@opentelemetry/core": "2.6.0", "@opentelemetry/otlp-transformer": "0.213.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-MegxAP1/n09Ob2dQvY5NBDVjAFkZRuKtWKxYev1R2M8hrsgXzQGkaMgoEKeUOyQ0FUyYcO29UOnYdQWmWa0PXg=="],
"@opentelemetry/exporter-zipkin/@opentelemetry/core": ["@opentelemetry/core@2.0.0", "", { "dependencies": { "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, "sha512-SLX36allrcnVaPYG3R78F/UZZsBsvbc7lMCLx37LyH5MJ1KAAZ2E3mW9OAD3zGz0G8q/BtoS5VUrjzDydhD6LQ=="],
@ -522,13 +520,15 @@
"@opentelemetry/exporter-zipkin/@opentelemetry/sdk-trace-base": ["@opentelemetry/sdk-trace-base@2.0.0", "", { "dependencies": { "@opentelemetry/core": "2.0.0", "@opentelemetry/resources": "2.0.0", "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, "sha512-qQnYdX+ZCkonM7tA5iU4fSRsVxbFGml8jbxOgipRGMFHKaXKHQ30js03rTobYjKjIfnOsZSbHKWF0/0v0OQGfw=="],
"@opentelemetry/exporter-zipkin/@opentelemetry/semantic-conventions": ["@opentelemetry/semantic-conventions@1.39.0", "", {}, "sha512-R5R9tb2AXs2IRLNKLBJDynhkfmx7mX0vi8NkhZb3gUkPWHn6HXk5J8iQ/dql0U3ApfWym4kXXmBDRGO+oeOfjg=="],
"@opentelemetry/instrumentation/@opentelemetry/api-logs": ["@opentelemetry/api-logs@0.200.0", "", { "dependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-IKJBQxh91qJ+3ssRly5hYEJ8NDHu9oY/B1PXVSCWf7zytmYO9RNLB0Ox9XQ/fJ8m6gY6Q6NtBWlmXfaXt5Uc4Q=="],
"@opentelemetry/otlp-exporter-base/@opentelemetry/core": ["@opentelemetry/core@2.2.0", "", { "dependencies": { "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, "sha512-FuabnnUm8LflnieVxs6eP7Z383hgQU4W1e3KJS6aOG3RxWxcHyBxH8fDMHNgu/gFx/M2jvTOW/4/PHhLz6bjWw=="],
"@opentelemetry/otlp-exporter-base/@opentelemetry/otlp-transformer": ["@opentelemetry/otlp-transformer@0.208.0", "", { "dependencies": { "@opentelemetry/api-logs": "0.208.0", "@opentelemetry/core": "2.2.0", "@opentelemetry/resources": "2.2.0", "@opentelemetry/sdk-logs": "0.208.0", "@opentelemetry/sdk-metrics": "2.2.0", "@opentelemetry/sdk-trace-base": "2.2.0", "protobufjs": "^7.3.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-DCFPY8C6lAQHUNkzcNT9R+qYExvsk6C5Bto2pbNxgicpcSWbe2WHShLxkOxIdNcBiYPdVHv/e7vH7K6TI+C+fQ=="],
"@opentelemetry/otlp-grpc-exporter-base/@opentelemetry/otlp-exporter-base": ["@opentelemetry/otlp-exporter-base@0.212.0", "", { "dependencies": { "@opentelemetry/core": "2.5.1", "@opentelemetry/otlp-transformer": "0.212.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-HoMv5pQlzbuxiMS0hN7oiUtg8RsJR5T7EhZccumIWxYfNo/f4wFc7LPDfFK6oHdG2JF/+qTocfqIHoom+7kLpw=="],
"@opentelemetry/otlp-grpc-exporter-base/@opentelemetry/otlp-exporter-base": ["@opentelemetry/otlp-exporter-base@0.213.0", "", { "dependencies": { "@opentelemetry/core": "2.6.0", "@opentelemetry/otlp-transformer": "0.213.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-MegxAP1/n09Ob2dQvY5NBDVjAFkZRuKtWKxYev1R2M8hrsgXzQGkaMgoEKeUOyQ0FUyYcO29UOnYdQWmWa0PXg=="],
"@opentelemetry/propagator-b3/@opentelemetry/core": ["@opentelemetry/core@2.0.0", "", { "dependencies": { "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, "sha512-SLX36allrcnVaPYG3R78F/UZZsBsvbc7lMCLx37LyH5MJ1KAAZ2E3mW9OAD3zGz0G8q/BtoS5VUrjzDydhD6LQ=="],
@ -566,8 +566,14 @@
"@opentelemetry/sdk-node/@opentelemetry/sdk-trace-node": ["@opentelemetry/sdk-trace-node@2.0.0", "", { "dependencies": { "@opentelemetry/context-async-hooks": "2.0.0", "@opentelemetry/core": "2.0.0", "@opentelemetry/sdk-trace-base": "2.0.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, "sha512-omdilCZozUjQwY3uZRBwbaRMJ3p09l4t187Lsdf0dGMye9WKD4NGcpgZRvqhI1dwcH6og+YXQEtoO9Wx3ykilg=="],
"@opentelemetry/sdk-node/@opentelemetry/semantic-conventions": ["@opentelemetry/semantic-conventions@1.39.0", "", {}, "sha512-R5R9tb2AXs2IRLNKLBJDynhkfmx7mX0vi8NkhZb3gUkPWHn6HXk5J8iQ/dql0U3ApfWym4kXXmBDRGO+oeOfjg=="],
"@scalar/themes/@scalar/types": ["@scalar/types@0.1.7", "", { "dependencies": { "@scalar/openapi-types": "0.2.0", "@unhead/schema": "^1.11.11", "nanoid": "^5.1.5", "type-fest": "^4.20.0", "zod": "^3.23.8" } }, "sha512-irIDYzTQG2KLvFbuTI8k2Pz/R4JR+zUUSykVTbEMatkzMmVFnn1VzNSMlODbadycwZunbnL2tA27AXed9URVjw=="],
"pg/pg-protocol": ["pg-protocol@1.13.0", "", {}, "sha512-zzdvXfS6v89r6v7OcFCHfHlyG/wvry1ALxZo4LqgUoy7W9xhBDMaqOuMiF3qEV45VqsN6rdlcehHrfDtlCPc8w=="],
"tsx/esbuild": ["esbuild@0.27.4", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.27.4", "@esbuild/android-arm": "0.27.4", "@esbuild/android-arm64": "0.27.4", "@esbuild/android-x64": "0.27.4", "@esbuild/darwin-arm64": "0.27.4", "@esbuild/darwin-x64": "0.27.4", "@esbuild/freebsd-arm64": "0.27.4", "@esbuild/freebsd-x64": "0.27.4", "@esbuild/linux-arm": "0.27.4", "@esbuild/linux-arm64": "0.27.4", "@esbuild/linux-ia32": "0.27.4", "@esbuild/linux-loong64": "0.27.4", "@esbuild/linux-mips64el": "0.27.4", "@esbuild/linux-ppc64": "0.27.4", "@esbuild/linux-riscv64": "0.27.4", "@esbuild/linux-s390x": "0.27.4", "@esbuild/linux-x64": "0.27.4", "@esbuild/netbsd-arm64": "0.27.4", "@esbuild/netbsd-x64": "0.27.4", "@esbuild/openbsd-arm64": "0.27.4", "@esbuild/openbsd-x64": "0.27.4", "@esbuild/openharmony-arm64": "0.27.4", "@esbuild/sunos-x64": "0.27.4", "@esbuild/win32-arm64": "0.27.4", "@esbuild/win32-ia32": "0.27.4", "@esbuild/win32-x64": "0.27.4" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-Rq4vbHnYkK5fws5NF7MYTU68FPRE1ajX7heQ/8QXXWqNgqqJ/GkmmyxIzUnf2Sr/bakf8l54716CcMGHYhMrrQ=="],
"@esbuild-kit/core-utils/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.18.20", "", { "os": "android", "cpu": "arm" }, "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw=="],
"@esbuild-kit/core-utils/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.18.20", "", { "os": "android", "cpu": "arm64" }, "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ=="],
@ -630,12 +636,16 @@
"@logtape/otel/@opentelemetry/exporter-logs-otlp-proto/@opentelemetry/sdk-trace-base": ["@opentelemetry/sdk-trace-base@2.2.0", "", { "dependencies": { "@opentelemetry/core": "2.2.0", "@opentelemetry/resources": "2.2.0", "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, "sha512-xWQgL0Bmctsalg6PaXExmzdedSp3gyKV8mQBwK/j9VGdCDu2fmXIb2gAehBKbkXCpJ4HPkgv3QfoJWRT4dHWbw=="],
"@logtape/otel/@opentelemetry/resources/@opentelemetry/core": ["@opentelemetry/core@2.5.0", "", { "dependencies": { "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, "sha512-ka4H8OM6+DlUhSAZpONu0cPBtPPTQKxbxVzC4CzVx5+K4JnroJVBtDzLAMx4/3CDTJXRvVFhpFjtl4SaiTNoyQ=="],
"@logtape/otel/@opentelemetry/sdk-logs/@opentelemetry/core": ["@opentelemetry/core@2.2.0", "", { "dependencies": { "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, "sha512-FuabnnUm8LflnieVxs6eP7Z383hgQU4W1e3KJS6aOG3RxWxcHyBxH8fDMHNgu/gFx/M2jvTOW/4/PHhLz6bjWw=="],
"@logtape/otel/@opentelemetry/sdk-logs/@opentelemetry/resources": ["@opentelemetry/resources@2.2.0", "", { "dependencies": { "@opentelemetry/core": "2.2.0", "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, "sha512-1pNQf/JazQTMA0BiO5NINUzH0cbLbbl7mntLa4aJNmCCXSj0q03T5ZXXL0zw4G55TjdL9Tz32cznGClf+8zr5A=="],
"@opentelemetry/exporter-prometheus/@opentelemetry/core/@opentelemetry/semantic-conventions": ["@opentelemetry/semantic-conventions@1.39.0", "", {}, "sha512-R5R9tb2AXs2IRLNKLBJDynhkfmx7mX0vi8NkhZb3gUkPWHn6HXk5J8iQ/dql0U3ApfWym4kXXmBDRGO+oeOfjg=="],
"@opentelemetry/exporter-prometheus/@opentelemetry/resources/@opentelemetry/semantic-conventions": ["@opentelemetry/semantic-conventions@1.39.0", "", {}, "sha512-R5R9tb2AXs2IRLNKLBJDynhkfmx7mX0vi8NkhZb3gUkPWHn6HXk5J8iQ/dql0U3ApfWym4kXXmBDRGO+oeOfjg=="],
"@opentelemetry/otlp-exporter-base/@opentelemetry/core/@opentelemetry/semantic-conventions": ["@opentelemetry/semantic-conventions@1.39.0", "", {}, "sha512-R5R9tb2AXs2IRLNKLBJDynhkfmx7mX0vi8NkhZb3gUkPWHn6HXk5J8iQ/dql0U3ApfWym4kXXmBDRGO+oeOfjg=="],
"@opentelemetry/otlp-exporter-base/@opentelemetry/otlp-transformer/@opentelemetry/api-logs": ["@opentelemetry/api-logs@0.208.0", "", { "dependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-CjruKY9V6NMssL/T1kAFgzosF1v9o6oeN+aX5JB/C/xPNtmgIJqcXHG7fA82Ou1zCpWGl4lROQUKwUNE1pMCyg=="],
"@opentelemetry/otlp-exporter-base/@opentelemetry/otlp-transformer/@opentelemetry/resources": ["@opentelemetry/resources@2.2.0", "", { "dependencies": { "@opentelemetry/core": "2.2.0", "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, "sha512-1pNQf/JazQTMA0BiO5NINUzH0cbLbbl7mntLa4aJNmCCXSj0q03T5ZXXL0zw4G55TjdL9Tz32cznGClf+8zr5A=="],
@ -646,7 +656,9 @@
"@opentelemetry/otlp-exporter-base/@opentelemetry/otlp-transformer/@opentelemetry/sdk-trace-base": ["@opentelemetry/sdk-trace-base@2.2.0", "", { "dependencies": { "@opentelemetry/core": "2.2.0", "@opentelemetry/resources": "2.2.0", "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, "sha512-xWQgL0Bmctsalg6PaXExmzdedSp3gyKV8mQBwK/j9VGdCDu2fmXIb2gAehBKbkXCpJ4HPkgv3QfoJWRT4dHWbw=="],
"@opentelemetry/otlp-exporter-base/@opentelemetry/otlp-transformer/protobufjs": ["protobufjs@7.5.4", "", { "dependencies": { "@protobufjs/aspromise": "^1.1.2", "@protobufjs/base64": "^1.1.2", "@protobufjs/codegen": "^2.0.4", "@protobufjs/eventemitter": "^1.1.0", "@protobufjs/fetch": "^1.1.0", "@protobufjs/float": "^1.0.2", "@protobufjs/inquire": "^1.1.0", "@protobufjs/path": "^1.1.2", "@protobufjs/pool": "^1.1.0", "@protobufjs/utf8": "^1.1.0", "@types/node": ">=13.7.0", "long": "^5.0.0" } }, "sha512-CvexbZtbov6jW2eXAvLukXjXUW1TzFaivC46BpWc/3BpcCysb5Vffu+B3XHMm8lVEuy2Mm4XGex8hBSg1yapPg=="],
"@opentelemetry/propagator-b3/@opentelemetry/core/@opentelemetry/semantic-conventions": ["@opentelemetry/semantic-conventions@1.39.0", "", {}, "sha512-R5R9tb2AXs2IRLNKLBJDynhkfmx7mX0vi8NkhZb3gUkPWHn6HXk5J8iQ/dql0U3ApfWym4kXXmBDRGO+oeOfjg=="],
"@opentelemetry/propagator-jaeger/@opentelemetry/core/@opentelemetry/semantic-conventions": ["@opentelemetry/semantic-conventions@1.39.0", "", {}, "sha512-R5R9tb2AXs2IRLNKLBJDynhkfmx7mX0vi8NkhZb3gUkPWHn6HXk5J8iQ/dql0U3ApfWym4kXXmBDRGO+oeOfjg=="],
"@opentelemetry/sdk-node/@opentelemetry/exporter-logs-otlp-grpc/@opentelemetry/otlp-exporter-base": ["@opentelemetry/otlp-exporter-base@0.200.0", "", { "dependencies": { "@opentelemetry/core": "2.0.0", "@opentelemetry/otlp-transformer": "0.200.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-IxJgA3FD7q4V6gGq4bnmQM5nTIyMDkoGFGrBrrDjB6onEiq1pafma55V+bHvGYLWvcqbBbRfezr1GED88lacEQ=="],
@ -694,13 +706,67 @@
"@scalar/themes/@scalar/types/@scalar/openapi-types": ["@scalar/openapi-types@0.2.0", "", { "dependencies": { "zod": "^3.23.8" } }, "sha512-waiKk12cRCqyUCWTOX0K1WEVX46+hVUK+zRPzAahDJ7G0TApvbNkuy5wx7aoUyEk++HHde0XuQnshXnt8jsddA=="],
"tsx/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.27.4", "", { "os": "aix", "cpu": "ppc64" }, "sha512-cQPwL2mp2nSmHHJlCyoXgHGhbEPMrEEU5xhkcy3Hs/O7nGZqEpZ2sUtLaL9MORLtDfRvVl2/3PAuEkYZH0Ty8Q=="],
"tsx/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.27.4", "", { "os": "android", "cpu": "arm" }, "sha512-X9bUgvxiC8CHAGKYufLIHGXPJWnr0OCdR0anD2e21vdvgCI8lIfqFbnoeOz7lBjdrAGUhqLZLcQo6MLhTO2DKQ=="],
"tsx/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.27.4", "", { "os": "android", "cpu": "arm64" }, "sha512-gdLscB7v75wRfu7QSm/zg6Rx29VLdy9eTr2t44sfTW7CxwAtQghZ4ZnqHk3/ogz7xao0QAgrkradbBzcqFPasw=="],
"tsx/esbuild/@esbuild/android-x64": ["@esbuild/android-x64@0.27.4", "", { "os": "android", "cpu": "x64" }, "sha512-PzPFnBNVF292sfpfhiyiXCGSn9HZg5BcAz+ivBuSsl6Rk4ga1oEXAamhOXRFyMcjwr2DVtm40G65N3GLeH1Lvw=="],
"tsx/esbuild/@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.27.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-b7xaGIwdJlht8ZFCvMkpDN6uiSmnxxK56N2GDTMYPr2/gzvfdQN8rTfBsvVKmIVY/X7EM+/hJKEIbbHs9oA4tQ=="],
"tsx/esbuild/@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.27.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-sR+OiKLwd15nmCdqpXMnuJ9W2kpy0KigzqScqHI3Hqwr7IXxBp3Yva+yJwoqh7rE8V77tdoheRYataNKL4QrPw=="],
"tsx/esbuild/@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.27.4", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-jnfpKe+p79tCnm4GVav68A7tUFeKQwQyLgESwEAUzyxk/TJr4QdGog9sqWNcUbr/bZt/O/HXouspuQDd9JxFSw=="],
"tsx/esbuild/@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.27.4", "", { "os": "freebsd", "cpu": "x64" }, "sha512-2kb4ceA/CpfUrIcTUl1wrP/9ad9Atrp5J94Lq69w7UwOMolPIGrfLSvAKJp0RTvkPPyn6CIWrNy13kyLikZRZQ=="],
"tsx/esbuild/@esbuild/linux-arm": ["@esbuild/linux-arm@0.27.4", "", { "os": "linux", "cpu": "arm" }, "sha512-aBYgcIxX/wd5n2ys0yESGeYMGF+pv6g0DhZr3G1ZG4jMfruU9Tl1i2Z+Wnj9/KjGz1lTLCcorqE2viePZqj4Eg=="],
"tsx/esbuild/@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.27.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-7nQOttdzVGth1iz57kxg9uCz57dxQLHWxopL6mYuYthohPKEK0vU0C3O21CcBK6KDlkYVcnDXY099HcCDXd9dA=="],
"tsx/esbuild/@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.27.4", "", { "os": "linux", "cpu": "ia32" }, "sha512-oPtixtAIzgvzYcKBQM/qZ3R+9TEUd1aNJQu0HhGyqtx6oS7qTpvjheIWBbes4+qu1bNlo2V4cbkISr8q6gRBFA=="],
"tsx/esbuild/@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.27.4", "", { "os": "linux", "cpu": "none" }, "sha512-8mL/vh8qeCoRcFH2nM8wm5uJP+ZcVYGGayMavi8GmRJjuI3g1v6Z7Ni0JJKAJW+m0EtUuARb6Lmp4hMjzCBWzA=="],
"tsx/esbuild/@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.27.4", "", { "os": "linux", "cpu": "none" }, "sha512-1RdrWFFiiLIW7LQq9Q2NES+HiD4NyT8Itj9AUeCl0IVCA459WnPhREKgwrpaIfTOe+/2rdntisegiPWn/r/aAw=="],
"tsx/esbuild/@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.27.4", "", { "os": "linux", "cpu": "ppc64" }, "sha512-tLCwNG47l3sd9lpfyx9LAGEGItCUeRCWeAx6x2Jmbav65nAwoPXfewtAdtbtit/pJFLUWOhpv0FpS6GQAmPrHA=="],
"tsx/esbuild/@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.27.4", "", { "os": "linux", "cpu": "none" }, "sha512-BnASypppbUWyqjd1KIpU4AUBiIhVr6YlHx/cnPgqEkNoVOhHg+YiSVxM1RLfiy4t9cAulbRGTNCKOcqHrEQLIw=="],
"tsx/esbuild/@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.27.4", "", { "os": "linux", "cpu": "s390x" }, "sha512-+eUqgb/Z7vxVLezG8bVB9SfBie89gMueS+I0xYh2tJdw3vqA/0ImZJ2ROeWwVJN59ihBeZ7Tu92dF/5dy5FttA=="],
"tsx/esbuild/@esbuild/linux-x64": ["@esbuild/linux-x64@0.27.4", "", { "os": "linux", "cpu": "x64" }, "sha512-S5qOXrKV8BQEzJPVxAwnryi2+Iq5pB40gTEIT69BQONqR7JH1EPIcQ/Uiv9mCnn05jff9umq/5nqzxlqTOg9NA=="],
"tsx/esbuild/@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.27.4", "", { "os": "none", "cpu": "arm64" }, "sha512-xHT8X4sb0GS8qTqiwzHqpY00C95DPAq7nAwX35Ie/s+LO9830hrMd3oX0ZMKLvy7vsonee73x0lmcdOVXFzd6Q=="],
"tsx/esbuild/@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.27.4", "", { "os": "none", "cpu": "x64" }, "sha512-RugOvOdXfdyi5Tyv40kgQnI0byv66BFgAqjdgtAKqHoZTbTF2QqfQrFwa7cHEORJf6X2ht+l9ABLMP0dnKYsgg=="],
"tsx/esbuild/@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.27.4", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-2MyL3IAaTX+1/qP0O1SwskwcwCoOI4kV2IBX1xYnDDqthmq5ArrW94qSIKCAuRraMgPOmG0RDTA74mzYNQA9ow=="],
"tsx/esbuild/@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.27.4", "", { "os": "openbsd", "cpu": "x64" }, "sha512-u8fg/jQ5aQDfsnIV6+KwLOf1CmJnfu1ShpwqdwC0uA7ZPwFws55Ngc12vBdeUdnuWoQYx/SOQLGDcdlfXhYmXQ=="],
"tsx/esbuild/@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.27.4", "", { "os": "none", "cpu": "arm64" }, "sha512-JkTZrl6VbyO8lDQO3yv26nNr2RM2yZzNrNHEsj9bm6dOwwu9OYN28CjzZkH57bh4w0I2F7IodpQvUAEd1mbWXg=="],
"tsx/esbuild/@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.27.4", "", { "os": "sunos", "cpu": "x64" }, "sha512-/gOzgaewZJfeJTlsWhvUEmUG4tWEY2Spp5M20INYRg2ZKl9QPO3QEEgPeRtLjEWSW8FilRNacPOg8R1uaYkA6g=="],
"tsx/esbuild/@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.27.4", "", { "os": "win32", "cpu": "arm64" }, "sha512-Z9SExBg2y32smoDQdf1HRwHRt6vAHLXcxD2uGgO/v2jK7Y718Ix4ndsbNMU/+1Qiem9OiOdaqitioZwxivhXYg=="],
"tsx/esbuild/@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.27.4", "", { "os": "win32", "cpu": "ia32" }, "sha512-DAyGLS0Jz5G5iixEbMHi5KdiApqHBWMGzTtMiJ72ZOLhbu/bzxgAe8Ue8CTS3n3HbIUHQz/L51yMdGMeoxXNJw=="],
"tsx/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.27.4", "", { "os": "win32", "cpu": "x64" }, "sha512-+knoa0BDoeXgkNvvV1vvbZX4+hizelrkwmGJBdT17t8FNPwG2lKemmuMZlmaNQ3ws3DKKCxpb4zRZEIp3UxFCg=="],
"@logtape/otel/@opentelemetry/exporter-logs-otlp-grpc/@opentelemetry/core/@opentelemetry/semantic-conventions": ["@opentelemetry/semantic-conventions@1.39.0", "", {}, "sha512-R5R9tb2AXs2IRLNKLBJDynhkfmx7mX0vi8NkhZb3gUkPWHn6HXk5J8iQ/dql0U3ApfWym4kXXmBDRGO+oeOfjg=="],
"@logtape/otel/@opentelemetry/exporter-logs-otlp-grpc/@opentelemetry/otlp-transformer/@opentelemetry/resources": ["@opentelemetry/resources@2.2.0", "", { "dependencies": { "@opentelemetry/core": "2.2.0", "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, "sha512-1pNQf/JazQTMA0BiO5NINUzH0cbLbbl7mntLa4aJNmCCXSj0q03T5ZXXL0zw4G55TjdL9Tz32cznGClf+8zr5A=="],
"@logtape/otel/@opentelemetry/exporter-logs-otlp-grpc/@opentelemetry/otlp-transformer/@opentelemetry/sdk-metrics": ["@opentelemetry/sdk-metrics@2.2.0", "", { "dependencies": { "@opentelemetry/core": "2.2.0", "@opentelemetry/resources": "2.2.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.9.0 <1.10.0" } }, "sha512-G5KYP6+VJMZzpGipQw7Giif48h6SGQ2PFKEYCybeXJsOCB4fp8azqMAAzE5lnnHK3ZVwYQrgmFbsUJO/zOnwGw=="],
"@logtape/otel/@opentelemetry/exporter-logs-otlp-grpc/@opentelemetry/otlp-transformer/@opentelemetry/sdk-trace-base": ["@opentelemetry/sdk-trace-base@2.2.0", "", { "dependencies": { "@opentelemetry/core": "2.2.0", "@opentelemetry/resources": "2.2.0", "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, "sha512-xWQgL0Bmctsalg6PaXExmzdedSp3gyKV8mQBwK/j9VGdCDu2fmXIb2gAehBKbkXCpJ4HPkgv3QfoJWRT4dHWbw=="],
"@logtape/otel/@opentelemetry/exporter-logs-otlp-grpc/@opentelemetry/otlp-transformer/protobufjs": ["protobufjs@7.5.4", "", { "dependencies": { "@protobufjs/aspromise": "^1.1.2", "@protobufjs/base64": "^1.1.2", "@protobufjs/codegen": "^2.0.4", "@protobufjs/eventemitter": "^1.1.0", "@protobufjs/fetch": "^1.1.0", "@protobufjs/float": "^1.0.2", "@protobufjs/inquire": "^1.1.0", "@protobufjs/path": "^1.1.2", "@protobufjs/pool": "^1.1.0", "@protobufjs/utf8": "^1.1.0", "@types/node": ">=13.7.0", "long": "^5.0.0" } }, "sha512-CvexbZtbov6jW2eXAvLukXjXUW1TzFaivC46BpWc/3BpcCysb5Vffu+B3XHMm8lVEuy2Mm4XGex8hBSg1yapPg=="],
"@logtape/otel/@opentelemetry/exporter-logs-otlp-http/@opentelemetry/core/@opentelemetry/semantic-conventions": ["@opentelemetry/semantic-conventions@1.39.0", "", {}, "sha512-R5R9tb2AXs2IRLNKLBJDynhkfmx7mX0vi8NkhZb3gUkPWHn6HXk5J8iQ/dql0U3ApfWym4kXXmBDRGO+oeOfjg=="],
"@logtape/otel/@opentelemetry/exporter-logs-otlp-http/@opentelemetry/otlp-transformer/@opentelemetry/resources": ["@opentelemetry/resources@2.2.0", "", { "dependencies": { "@opentelemetry/core": "2.2.0", "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, "sha512-1pNQf/JazQTMA0BiO5NINUzH0cbLbbl7mntLa4aJNmCCXSj0q03T5ZXXL0zw4G55TjdL9Tz32cznGClf+8zr5A=="],
@ -708,28 +774,28 @@
"@logtape/otel/@opentelemetry/exporter-logs-otlp-http/@opentelemetry/otlp-transformer/@opentelemetry/sdk-trace-base": ["@opentelemetry/sdk-trace-base@2.2.0", "", { "dependencies": { "@opentelemetry/core": "2.2.0", "@opentelemetry/resources": "2.2.0", "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, "sha512-xWQgL0Bmctsalg6PaXExmzdedSp3gyKV8mQBwK/j9VGdCDu2fmXIb2gAehBKbkXCpJ4HPkgv3QfoJWRT4dHWbw=="],
"@logtape/otel/@opentelemetry/exporter-logs-otlp-http/@opentelemetry/otlp-transformer/protobufjs": ["protobufjs@7.5.4", "", { "dependencies": { "@protobufjs/aspromise": "^1.1.2", "@protobufjs/base64": "^1.1.2", "@protobufjs/codegen": "^2.0.4", "@protobufjs/eventemitter": "^1.1.0", "@protobufjs/fetch": "^1.1.0", "@protobufjs/float": "^1.0.2", "@protobufjs/inquire": "^1.1.0", "@protobufjs/path": "^1.1.2", "@protobufjs/pool": "^1.1.0", "@protobufjs/utf8": "^1.1.0", "@types/node": ">=13.7.0", "long": "^5.0.0" } }, "sha512-CvexbZtbov6jW2eXAvLukXjXUW1TzFaivC46BpWc/3BpcCysb5Vffu+B3XHMm8lVEuy2Mm4XGex8hBSg1yapPg=="],
"@logtape/otel/@opentelemetry/exporter-logs-otlp-proto/@opentelemetry/core/@opentelemetry/semantic-conventions": ["@opentelemetry/semantic-conventions@1.39.0", "", {}, "sha512-R5R9tb2AXs2IRLNKLBJDynhkfmx7mX0vi8NkhZb3gUkPWHn6HXk5J8iQ/dql0U3ApfWym4kXXmBDRGO+oeOfjg=="],
"@logtape/otel/@opentelemetry/exporter-logs-otlp-proto/@opentelemetry/otlp-transformer/@opentelemetry/sdk-metrics": ["@opentelemetry/sdk-metrics@2.2.0", "", { "dependencies": { "@opentelemetry/core": "2.2.0", "@opentelemetry/resources": "2.2.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.9.0 <1.10.0" } }, "sha512-G5KYP6+VJMZzpGipQw7Giif48h6SGQ2PFKEYCybeXJsOCB4fp8azqMAAzE5lnnHK3ZVwYQrgmFbsUJO/zOnwGw=="],
"@logtape/otel/@opentelemetry/exporter-logs-otlp-proto/@opentelemetry/otlp-transformer/protobufjs": ["protobufjs@7.5.4", "", { "dependencies": { "@protobufjs/aspromise": "^1.1.2", "@protobufjs/base64": "^1.1.2", "@protobufjs/codegen": "^2.0.4", "@protobufjs/eventemitter": "^1.1.0", "@protobufjs/fetch": "^1.1.0", "@protobufjs/float": "^1.0.2", "@protobufjs/inquire": "^1.1.0", "@protobufjs/path": "^1.1.2", "@protobufjs/pool": "^1.1.0", "@protobufjs/utf8": "^1.1.0", "@types/node": ">=13.7.0", "long": "^5.0.0" } }, "sha512-CvexbZtbov6jW2eXAvLukXjXUW1TzFaivC46BpWc/3BpcCysb5Vffu+B3XHMm8lVEuy2Mm4XGex8hBSg1yapPg=="],
"@logtape/otel/@opentelemetry/exporter-logs-otlp-proto/@opentelemetry/resources/@opentelemetry/semantic-conventions": ["@opentelemetry/semantic-conventions@1.39.0", "", {}, "sha512-R5R9tb2AXs2IRLNKLBJDynhkfmx7mX0vi8NkhZb3gUkPWHn6HXk5J8iQ/dql0U3ApfWym4kXXmBDRGO+oeOfjg=="],
"@opentelemetry/sdk-node/@opentelemetry/exporter-logs-otlp-grpc/@opentelemetry/otlp-transformer/protobufjs": ["protobufjs@7.5.4", "", { "dependencies": { "@protobufjs/aspromise": "^1.1.2", "@protobufjs/base64": "^1.1.2", "@protobufjs/codegen": "^2.0.4", "@protobufjs/eventemitter": "^1.1.0", "@protobufjs/fetch": "^1.1.0", "@protobufjs/float": "^1.0.2", "@protobufjs/inquire": "^1.1.0", "@protobufjs/path": "^1.1.2", "@protobufjs/pool": "^1.1.0", "@protobufjs/utf8": "^1.1.0", "@types/node": ">=13.7.0", "long": "^5.0.0" } }, "sha512-CvexbZtbov6jW2eXAvLukXjXUW1TzFaivC46BpWc/3BpcCysb5Vffu+B3XHMm8lVEuy2Mm4XGex8hBSg1yapPg=="],
"@logtape/otel/@opentelemetry/exporter-logs-otlp-proto/@opentelemetry/sdk-trace-base/@opentelemetry/semantic-conventions": ["@opentelemetry/semantic-conventions@1.39.0", "", {}, "sha512-R5R9tb2AXs2IRLNKLBJDynhkfmx7mX0vi8NkhZb3gUkPWHn6HXk5J8iQ/dql0U3ApfWym4kXXmBDRGO+oeOfjg=="],
"@opentelemetry/sdk-node/@opentelemetry/exporter-logs-otlp-http/@opentelemetry/otlp-transformer/protobufjs": ["protobufjs@7.5.4", "", { "dependencies": { "@protobufjs/aspromise": "^1.1.2", "@protobufjs/base64": "^1.1.2", "@protobufjs/codegen": "^2.0.4", "@protobufjs/eventemitter": "^1.1.0", "@protobufjs/fetch": "^1.1.0", "@protobufjs/float": "^1.0.2", "@protobufjs/inquire": "^1.1.0", "@protobufjs/path": "^1.1.2", "@protobufjs/pool": "^1.1.0", "@protobufjs/utf8": "^1.1.0", "@types/node": ">=13.7.0", "long": "^5.0.0" } }, "sha512-CvexbZtbov6jW2eXAvLukXjXUW1TzFaivC46BpWc/3BpcCysb5Vffu+B3XHMm8lVEuy2Mm4XGex8hBSg1yapPg=="],
"@logtape/otel/@opentelemetry/sdk-logs/@opentelemetry/core/@opentelemetry/semantic-conventions": ["@opentelemetry/semantic-conventions@1.39.0", "", {}, "sha512-R5R9tb2AXs2IRLNKLBJDynhkfmx7mX0vi8NkhZb3gUkPWHn6HXk5J8iQ/dql0U3ApfWym4kXXmBDRGO+oeOfjg=="],
"@opentelemetry/sdk-node/@opentelemetry/exporter-logs-otlp-proto/@opentelemetry/otlp-transformer/protobufjs": ["protobufjs@7.5.4", "", { "dependencies": { "@protobufjs/aspromise": "^1.1.2", "@protobufjs/base64": "^1.1.2", "@protobufjs/codegen": "^2.0.4", "@protobufjs/eventemitter": "^1.1.0", "@protobufjs/fetch": "^1.1.0", "@protobufjs/float": "^1.0.2", "@protobufjs/inquire": "^1.1.0", "@protobufjs/path": "^1.1.2", "@protobufjs/pool": "^1.1.0", "@protobufjs/utf8": "^1.1.0", "@types/node": ">=13.7.0", "long": "^5.0.0" } }, "sha512-CvexbZtbov6jW2eXAvLukXjXUW1TzFaivC46BpWc/3BpcCysb5Vffu+B3XHMm8lVEuy2Mm4XGex8hBSg1yapPg=="],
"@logtape/otel/@opentelemetry/sdk-logs/@opentelemetry/resources/@opentelemetry/semantic-conventions": ["@opentelemetry/semantic-conventions@1.39.0", "", {}, "sha512-R5R9tb2AXs2IRLNKLBJDynhkfmx7mX0vi8NkhZb3gUkPWHn6HXk5J8iQ/dql0U3ApfWym4kXXmBDRGO+oeOfjg=="],
"@opentelemetry/sdk-node/@opentelemetry/exporter-metrics-otlp-grpc/@opentelemetry/otlp-transformer/protobufjs": ["protobufjs@7.5.4", "", { "dependencies": { "@protobufjs/aspromise": "^1.1.2", "@protobufjs/base64": "^1.1.2", "@protobufjs/codegen": "^2.0.4", "@protobufjs/eventemitter": "^1.1.0", "@protobufjs/fetch": "^1.1.0", "@protobufjs/float": "^1.0.2", "@protobufjs/inquire": "^1.1.0", "@protobufjs/path": "^1.1.2", "@protobufjs/pool": "^1.1.0", "@protobufjs/utf8": "^1.1.0", "@types/node": ">=13.7.0", "long": "^5.0.0" } }, "sha512-CvexbZtbov6jW2eXAvLukXjXUW1TzFaivC46BpWc/3BpcCysb5Vffu+B3XHMm8lVEuy2Mm4XGex8hBSg1yapPg=="],
"@opentelemetry/otlp-exporter-base/@opentelemetry/otlp-transformer/@opentelemetry/resources/@opentelemetry/semantic-conventions": ["@opentelemetry/semantic-conventions@1.39.0", "", {}, "sha512-R5R9tb2AXs2IRLNKLBJDynhkfmx7mX0vi8NkhZb3gUkPWHn6HXk5J8iQ/dql0U3ApfWym4kXXmBDRGO+oeOfjg=="],
"@opentelemetry/sdk-node/@opentelemetry/exporter-metrics-otlp-http/@opentelemetry/otlp-transformer/protobufjs": ["protobufjs@7.5.4", "", { "dependencies": { "@protobufjs/aspromise": "^1.1.2", "@protobufjs/base64": "^1.1.2", "@protobufjs/codegen": "^2.0.4", "@protobufjs/eventemitter": "^1.1.0", "@protobufjs/fetch": "^1.1.0", "@protobufjs/float": "^1.0.2", "@protobufjs/inquire": "^1.1.0", "@protobufjs/path": "^1.1.2", "@protobufjs/pool": "^1.1.0", "@protobufjs/utf8": "^1.1.0", "@types/node": ">=13.7.0", "long": "^5.0.0" } }, "sha512-CvexbZtbov6jW2eXAvLukXjXUW1TzFaivC46BpWc/3BpcCysb5Vffu+B3XHMm8lVEuy2Mm4XGex8hBSg1yapPg=="],
"@opentelemetry/otlp-exporter-base/@opentelemetry/otlp-transformer/@opentelemetry/sdk-trace-base/@opentelemetry/semantic-conventions": ["@opentelemetry/semantic-conventions@1.39.0", "", {}, "sha512-R5R9tb2AXs2IRLNKLBJDynhkfmx7mX0vi8NkhZb3gUkPWHn6HXk5J8iQ/dql0U3ApfWym4kXXmBDRGO+oeOfjg=="],
"@opentelemetry/sdk-node/@opentelemetry/exporter-metrics-otlp-proto/@opentelemetry/otlp-transformer/protobufjs": ["protobufjs@7.5.4", "", { "dependencies": { "@protobufjs/aspromise": "^1.1.2", "@protobufjs/base64": "^1.1.2", "@protobufjs/codegen": "^2.0.4", "@protobufjs/eventemitter": "^1.1.0", "@protobufjs/fetch": "^1.1.0", "@protobufjs/float": "^1.0.2", "@protobufjs/inquire": "^1.1.0", "@protobufjs/path": "^1.1.2", "@protobufjs/pool": "^1.1.0", "@protobufjs/utf8": "^1.1.0", "@types/node": ">=13.7.0", "long": "^5.0.0" } }, "sha512-CvexbZtbov6jW2eXAvLukXjXUW1TzFaivC46BpWc/3BpcCysb5Vffu+B3XHMm8lVEuy2Mm4XGex8hBSg1yapPg=="],
"@logtape/otel/@opentelemetry/exporter-logs-otlp-grpc/@opentelemetry/otlp-transformer/@opentelemetry/resources/@opentelemetry/semantic-conventions": ["@opentelemetry/semantic-conventions@1.39.0", "", {}, "sha512-R5R9tb2AXs2IRLNKLBJDynhkfmx7mX0vi8NkhZb3gUkPWHn6HXk5J8iQ/dql0U3ApfWym4kXXmBDRGO+oeOfjg=="],
"@opentelemetry/sdk-node/@opentelemetry/exporter-trace-otlp-grpc/@opentelemetry/otlp-transformer/protobufjs": ["protobufjs@7.5.4", "", { "dependencies": { "@protobufjs/aspromise": "^1.1.2", "@protobufjs/base64": "^1.1.2", "@protobufjs/codegen": "^2.0.4", "@protobufjs/eventemitter": "^1.1.0", "@protobufjs/fetch": "^1.1.0", "@protobufjs/float": "^1.0.2", "@protobufjs/inquire": "^1.1.0", "@protobufjs/path": "^1.1.2", "@protobufjs/pool": "^1.1.0", "@protobufjs/utf8": "^1.1.0", "@types/node": ">=13.7.0", "long": "^5.0.0" } }, "sha512-CvexbZtbov6jW2eXAvLukXjXUW1TzFaivC46BpWc/3BpcCysb5Vffu+B3XHMm8lVEuy2Mm4XGex8hBSg1yapPg=="],
"@logtape/otel/@opentelemetry/exporter-logs-otlp-grpc/@opentelemetry/otlp-transformer/@opentelemetry/sdk-trace-base/@opentelemetry/semantic-conventions": ["@opentelemetry/semantic-conventions@1.39.0", "", {}, "sha512-R5R9tb2AXs2IRLNKLBJDynhkfmx7mX0vi8NkhZb3gUkPWHn6HXk5J8iQ/dql0U3ApfWym4kXXmBDRGO+oeOfjg=="],
"@opentelemetry/sdk-node/@opentelemetry/exporter-trace-otlp-http/@opentelemetry/otlp-transformer/protobufjs": ["protobufjs@7.5.4", "", { "dependencies": { "@protobufjs/aspromise": "^1.1.2", "@protobufjs/base64": "^1.1.2", "@protobufjs/codegen": "^2.0.4", "@protobufjs/eventemitter": "^1.1.0", "@protobufjs/fetch": "^1.1.0", "@protobufjs/float": "^1.0.2", "@protobufjs/inquire": "^1.1.0", "@protobufjs/path": "^1.1.2", "@protobufjs/pool": "^1.1.0", "@protobufjs/utf8": "^1.1.0", "@types/node": ">=13.7.0", "long": "^5.0.0" } }, "sha512-CvexbZtbov6jW2eXAvLukXjXUW1TzFaivC46BpWc/3BpcCysb5Vffu+B3XHMm8lVEuy2Mm4XGex8hBSg1yapPg=="],
"@logtape/otel/@opentelemetry/exporter-logs-otlp-http/@opentelemetry/otlp-transformer/@opentelemetry/resources/@opentelemetry/semantic-conventions": ["@opentelemetry/semantic-conventions@1.39.0", "", {}, "sha512-R5R9tb2AXs2IRLNKLBJDynhkfmx7mX0vi8NkhZb3gUkPWHn6HXk5J8iQ/dql0U3ApfWym4kXXmBDRGO+oeOfjg=="],
"@opentelemetry/sdk-node/@opentelemetry/exporter-trace-otlp-proto/@opentelemetry/otlp-transformer/protobufjs": ["protobufjs@7.5.4", "", { "dependencies": { "@protobufjs/aspromise": "^1.1.2", "@protobufjs/base64": "^1.1.2", "@protobufjs/codegen": "^2.0.4", "@protobufjs/eventemitter": "^1.1.0", "@protobufjs/fetch": "^1.1.0", "@protobufjs/float": "^1.0.2", "@protobufjs/inquire": "^1.1.0", "@protobufjs/path": "^1.1.2", "@protobufjs/pool": "^1.1.0", "@protobufjs/utf8": "^1.1.0", "@types/node": ">=13.7.0", "long": "^5.0.0" } }, "sha512-CvexbZtbov6jW2eXAvLukXjXUW1TzFaivC46BpWc/3BpcCysb5Vffu+B3XHMm8lVEuy2Mm4XGex8hBSg1yapPg=="],
"@logtape/otel/@opentelemetry/exporter-logs-otlp-http/@opentelemetry/otlp-transformer/@opentelemetry/sdk-trace-base/@opentelemetry/semantic-conventions": ["@opentelemetry/semantic-conventions@1.39.0", "", {}, "sha512-R5R9tb2AXs2IRLNKLBJDynhkfmx7mX0vi8NkhZb3gUkPWHn6HXk5J8iQ/dql0U3ApfWym4kXXmBDRGO+oeOfjg=="],
}
}

View File

@ -13,42 +13,42 @@
"@elysiajs/opentelemetry": "^1.4.10",
"@elysiajs/swagger": "zoriya/elysia-swagger#build",
"@kubiks/otel-drizzle": "zoriya/drizzle-otel#build",
"@logtape/elysia": "2.0.2",
"@logtape/logtape": "2.0.2",
"@logtape/otel": "2.0.2",
"@logtape/redaction": "2.0.2",
"@logtape/elysia": "2.0.4",
"@logtape/logtape": "2.0.4",
"@logtape/otel": "2.0.4",
"@logtape/redaction": "2.0.4",
"@opentelemetry/api": "^1.9.0",
"@opentelemetry/api-logs": "^0.212.0",
"@opentelemetry/core": "^2.5.1",
"@opentelemetry/exporter-logs-otlp-grpc": "^0.212.0",
"@opentelemetry/exporter-logs-otlp-http": "^0.212.0",
"@opentelemetry/exporter-logs-otlp-proto": "^0.212.0",
"@opentelemetry/exporter-metrics-otlp-grpc": "^0.212.0",
"@opentelemetry/exporter-metrics-otlp-http": "^0.212.0",
"@opentelemetry/exporter-metrics-otlp-proto": "^0.212.0",
"@opentelemetry/exporter-trace-otlp-grpc": "^0.212.0",
"@opentelemetry/exporter-trace-otlp-http": "^0.212.0",
"@opentelemetry/exporter-trace-otlp-proto": "^0.212.0",
"@opentelemetry/resources": "^2.5.1",
"@opentelemetry/sdk-logs": "^0.212.0",
"@opentelemetry/sdk-metrics": "^2.5.1",
"@opentelemetry/sdk-trace-base": "^2.5.1",
"@opentelemetry/sdk-trace-node": "^2.5.1",
"@opentelemetry/semantic-conventions": "^1.39.0",
"@types/bun": "^1.3.9",
"@opentelemetry/api-logs": "^0.213.0",
"@opentelemetry/core": "^2.6.0",
"@opentelemetry/exporter-logs-otlp-grpc": "^0.213.0",
"@opentelemetry/exporter-logs-otlp-http": "^0.213.0",
"@opentelemetry/exporter-logs-otlp-proto": "^0.213.0",
"@opentelemetry/exporter-metrics-otlp-grpc": "^0.213.0",
"@opentelemetry/exporter-metrics-otlp-http": "^0.213.0",
"@opentelemetry/exporter-metrics-otlp-proto": "^0.213.0",
"@opentelemetry/exporter-trace-otlp-grpc": "^0.213.0",
"@opentelemetry/exporter-trace-otlp-http": "^0.213.0",
"@opentelemetry/exporter-trace-otlp-proto": "^0.213.0",
"@opentelemetry/resources": "^2.6.0",
"@opentelemetry/sdk-logs": "^0.213.0",
"@opentelemetry/sdk-metrics": "^2.6.0",
"@opentelemetry/sdk-trace-base": "^2.6.0",
"@opentelemetry/sdk-trace-node": "^2.6.0",
"@opentelemetry/semantic-conventions": "^1.40.0",
"@types/bun": "^1.3.10",
"blurhash": "^2.0.5",
"drizzle-kit": "^0.31.5",
"drizzle-orm": "0.44.7",
"elysia": "^1.4.25",
"jose": "^6.1.3",
"node-addon-api": "^8.5.0",
"elysia": "^1.4.28",
"jose": "^6.2.1",
"node-addon-api": "^8.6.0",
"parjs": "^1.3.9",
"pg": "^8.17.2",
"pg": "^8.20.0",
"sharp": "^0.34.5"
},
"devDependencies": {
"@biomejs/biome": "2.4.4",
"@types/pg": "^8.16.0",
"@biomejs/biome": "2.4.7",
"@types/pg": "^8.18.0",
"typescript": "^5.9.3"
},
"module": "src/index.js",

View File

@ -175,7 +175,10 @@ export async function linkVideos(
),
and(
sql`j.entry ? 'externalId'`,
sql`j.entry->'externalId' <@ ${entriesQ.externalId}`,
sql`
(select jsonb_object_agg(key, jsonb_build_array(value))
from jsonb_each(j.entry->'externalId'))
<@ ${entriesQ.externalId}`,
),
),
),

View File

@ -20,7 +20,7 @@ import { linkVideos } from "./video-links";
const CreatedVideo = t.Object({
id: t.String({ format: "uuid" }),
path: t.String({ examples: [bubbleVideo.path] }),
guess: t.Omit(Guess, ["history"]),
guess: Guess,
entries: t.Array(
t.Object({
slug: t.String({ format: "slug", examples: ["bubble-v2"] }),

View File

@ -29,18 +29,22 @@ export const entry_extid = () =>
.$type<
Record<
string,
| {
// used for movies
dataId: string;
link: string | null;
}
| {
// used for episodes, specials & extra
serieId: string;
season: number | null;
episode: number;
link: string | null;
}
(
| {
// used for movies
dataId: string;
link: string | null;
label?: string | null;
}
| {
// used for episodes, specials & extra
serieId: string;
season: number | null;
episode: number;
link: string | null;
label?: string | null;
}
)[]
>
>()
.notNull()

View File

@ -23,7 +23,7 @@ export const season_extid = () =>
serieId: string;
season: number;
link: string | null;
}
}[]
>
>()
.notNull()

View File

@ -15,7 +15,8 @@ export const externalid = () =>
{
dataId: string;
link: string | null;
}
label?: string | null;
}[]
>
>()
.notNull()

View File

@ -58,14 +58,18 @@ export const bubble: SeedMovie = {
airDate: "2022-02-14",
originalLanguage: "ja",
externalId: {
themoviedatabase: {
dataId: "912598",
link: "https://www.themoviedb.org/movie/912598",
},
imdb: {
dataId: "tt16360006",
link: "https://www.imdb.com/title/tt16360006",
},
themoviedatabase: [
{
dataId: "912598",
link: "https://www.themoviedb.org/movie/912598",
},
],
imdb: [
{
dataId: "tt16360006",
link: "https://www.imdb.com/title/tt16360006",
},
],
},
videos: [bubbleVideo.id],
studios: [],

View File

@ -44,14 +44,18 @@ export const dune1984: SeedMovie = {
airDate: "1984-12-14",
originalLanguage: "en",
externalId: {
themoviedatabase: {
dataId: "9495",
link: "https://www.themoviedb.org/movie/9495",
},
imdb: {
dataId: "tt0087182",
link: "https://www.imdb.com/title/tt0087182",
},
themoviedatabase: [
{
dataId: "9495",
link: "https://www.themoviedb.org/movie/9495",
},
],
imdb: [
{
dataId: "tt0087182",
link: "https://www.imdb.com/title/tt0087182",
},
],
},
videos: [dune1984Video.id],
studios: [],

View File

@ -44,14 +44,18 @@ export const dune: SeedMovie = {
airDate: "2021-10-22",
originalLanguage: "en",
externalId: {
themoviedatabase: {
dataId: "438631",
link: "https://www.themoviedb.org/movie/438631-dune",
},
imdb: {
dataId: "tt1160419",
link: "https://www.imdb.com/title/tt1160419",
},
themoviedatabase: [
{
dataId: "438631",
link: "https://www.themoviedb.org/movie/438631-dune",
},
],
imdb: [
{
dataId: "tt1160419",
link: "https://www.imdb.com/title/tt1160419",
},
],
},
videos: [duneVideo.id],
studios: [],

View File

@ -22,9 +22,11 @@ export const duneCollection: SeedCollection = {
genres: ["adventure", "science-fiction"],
rating: 80,
externalId: {
themoviedatabase: {
dataId: "726871",
link: "https://www.themoviedb.org/collection/726871-dune-collection",
},
themoviedatabase: [
{
dataId: "726871",
link: "https://www.themoviedb.org/collection/726871-dune-collection",
},
],
},
};

View File

@ -109,12 +109,16 @@ export const madeInAbyss = {
startAir: "2017-07-07",
endAir: "2022-09-28",
externalId: {
themoviedatabase: {
dataId: "72636",
link: "https://www.themoviedb.org/tv/72636",
},
imdb: { dataId: "tt7222086", link: "https://www.imdb.com/title/tt7222086" },
tvdb: { dataId: "326109", link: null },
themoviedatabase: [
{
dataId: "72636",
link: "https://www.themoviedb.org/tv/72636",
},
],
imdb: [
{ dataId: "tt7222086", link: "https://www.imdb.com/title/tt7222086" },
],
tvdb: [{ dataId: "326109", link: null }],
},
seasons: [
{
@ -133,11 +137,13 @@ export const madeInAbyss = {
startAir: "2017-07-07",
endAir: "2017-09-29",
externalId: {
themoviedatabase: {
serieId: "72636",
season: 1,
link: "https://www.themoviedb.org/tv/72636/season/1",
},
themoviedatabase: [
{
serieId: "72636",
season: 1,
link: "https://www.themoviedb.org/tv/72636/season/1",
},
],
},
},
{
@ -156,11 +162,13 @@ export const madeInAbyss = {
startAir: "2022-07-06",
endAir: "2022-09-28",
externalId: {
themoviedatabase: {
serieId: "72636",
season: 2,
link: "https://www.themoviedb.org/tv/72636/season/2",
},
themoviedatabase: [
{
serieId: "72636",
season: 2,
link: "https://www.themoviedb.org/tv/72636/season/2",
},
],
},
},
],
@ -182,12 +190,14 @@ export const madeInAbyss = {
thumbnail:
"https://image.tmdb.org/t/p/original/j9t1quh24suXxBetV7Q77YngID6.jpg",
externalId: {
themoviedatabase: {
serieId: "72636",
season: 1,
episode: 13,
link: "https://www.themoviedb.org/tv/72636/season/1/episode/13",
},
themoviedatabase: [
{
serieId: "72636",
season: 1,
episode: 13,
link: "https://www.themoviedb.org/tv/72636/season/1/episode/13",
},
],
},
videos: [madeInAbyssVideo.id],
},
@ -208,12 +218,14 @@ export const madeInAbyss = {
thumbnail:
"https://image.tmdb.org/t/p/original/4cMeg2ihvACsGVaSUcQJJZd96Je.jpg",
externalId: {
themoviedatabase: {
serieId: "72636",
season: 0,
episode: 3,
link: "https://www.themoviedb.org/tv/72636/season/0/episode/3",
},
themoviedatabase: [
{
serieId: "72636",
season: 0,
episode: 3,
link: "https://www.themoviedb.org/tv/72636/season/0/episode/3",
},
],
},
},
{
@ -235,10 +247,12 @@ export const madeInAbyss = {
runtime: 105,
airDate: "2020-01-17",
externalId: {
themoviedatabase: {
dataId: "72636",
link: "https://www.themoviedb.org/tv/72636/season/0/episode/3",
},
themoviedatabase: [
{
dataId: "72636",
link: "https://www.themoviedb.org/tv/72636/season/0/episode/3",
},
],
},
},
{
@ -258,12 +272,14 @@ export const madeInAbyss = {
thumbnail:
"https://image.tmdb.org/t/p/original/Tgu6E3aMf7sFHFbEIMEjetnpMi.jpg",
externalId: {
themoviedatabase: {
serieId: "72636",
season: 2,
episode: 1,
link: "https://www.themoviedb.org/tv/72636/season/2/episode/1",
},
themoviedatabase: [
{
serieId: "72636",
season: 2,
episode: 1,
link: "https://www.themoviedb.org/tv/72636/season/2/episode/1",
},
],
},
},
{
@ -283,12 +299,14 @@ export const madeInAbyss = {
thumbnail:
"https://artworks.thetvdb.com/banners/episodes/326109/6174129.jpg",
externalId: {
themoviedatabase: {
serieId: "72636",
season: 2,
episode: 2,
link: "https://www.themoviedb.org/tv/72636/season/2/episode/2",
},
themoviedatabase: [
{
serieId: "72636",
season: 2,
episode: 2,
link: "https://www.themoviedb.org/tv/72636/season/2/episode/2",
},
],
},
},
{
@ -308,12 +326,14 @@ export const madeInAbyss = {
thumbnail:
"https://artworks.thetvdb.com/banners/episodes/326109/6180539.jpg",
externalId: {
themoviedatabase: {
serieId: "72636",
season: 2,
episode: 3,
link: "https://www.themoviedb.org/tv/72636/season/2/episode/4",
},
themoviedatabase: [
{
serieId: "72636",
season: 2,
episode: 3,
link: "https://www.themoviedb.org/tv/72636/season/2/episode/4",
},
],
},
},
{
@ -333,12 +353,14 @@ export const madeInAbyss = {
thumbnail:
"https://artworks.thetvdb.com/banners/episodes/326109/6180540.jpg",
externalId: {
themoviedatabase: {
serieId: "72636",
season: 2,
episode: 4,
link: "https://www.themoviedb.org/tv/72636/season/2/episode/4",
},
themoviedatabase: [
{
serieId: "72636",
season: 2,
episode: 4,
link: "https://www.themoviedb.org/tv/72636/season/2/episode/4",
},
],
},
},
],
@ -362,10 +384,12 @@ export const madeInAbyss = {
},
},
externalId: {
themoviedatabase: {
dataId: "16738",
link: "https://www.themoviedb.org/company/16738",
},
themoviedatabase: [
{
dataId: "16738",
link: "https://www.themoviedb.org/company/16738",
},
],
},
},
],
@ -383,10 +407,12 @@ export const madeInAbyss = {
latinName: "Mariya Ise",
image: "https://cdn.myanimelist.net/images/voiceactors/2/65504.jpg",
externalId: {
themoviedatabase: {
dataId: "1250465",
link: "https://www.themoviedb.org/person/1250465",
},
themoviedatabase: [
{
dataId: "1250465",
link: "https://www.themoviedb.org/person/1250465",
},
],
},
},
},

View File

@ -4,39 +4,18 @@ import { comment } from "../../utils";
export const ExternalId = () =>
t.Record(
t.String(),
t.Object({
dataId: t.String(),
link: t.Nullable(t.String({ format: "uri" })),
}),
t.Array(
t.Object({
dataId: t.String(),
link: t.Nullable(t.String({ format: "uri" })),
label: t.Optional(t.Nullable(t.String())),
}),
),
);
export const EpisodeId = t.Record(
t.String(),
t.Object({
serieId: t.String({
descrpition: comment`
Id on the external website.
We store the serie's id because episode id are rarely stable.
`,
}),
season: t.Nullable(
t.Integer({
description: "Null if the external website uses absolute numbering.",
}),
),
episode: t.Integer(),
link: t.Nullable(t.String({ format: "uri" })),
}),
);
export type EpisodeId = typeof EpisodeId.static;
export const MovieEpisodeId = t.Record(
t.String(),
t.Union([
t.Object({
dataId: t.String(),
link: t.Nullable(t.String({ format: "uri" })),
}),
t.Array(
t.Object({
serieId: t.String({
descrpition: comment`
@ -51,21 +30,55 @@ export const MovieEpisodeId = t.Record(
),
episode: t.Integer(),
link: t.Nullable(t.String({ format: "uri" })),
label: t.Optional(t.Nullable(t.String())),
}),
]),
),
);
export type EpisodeId = typeof EpisodeId.static;
export const MovieEpisodeId = t.Record(
t.String(),
t.Array(
t.Union([
t.Object({
dataId: t.String(),
link: t.Nullable(t.String({ format: "uri" })),
label: t.Optional(t.Nullable(t.String())),
}),
t.Object({
serieId: t.String({
descrpition: comment`
Id on the external website.
We store the serie's id because episode id are rarely stable.
`,
}),
season: t.Nullable(
t.Integer({
description:
"Null if the external website uses absolute numbering.",
}),
),
episode: t.Integer(),
link: t.Nullable(t.String({ format: "uri" })),
label: t.Optional(t.Nullable(t.String())),
}),
]),
),
);
export const SeasonId = t.Record(
t.String(),
t.Object({
serieId: t.String({
descrpition: comment`
t.Array(
t.Object({
serieId: t.String({
descrpition: comment`
Id on the external website.
We store the serie's id because episode id are rarely stable.
`,
}),
season: t.Integer(),
link: t.Nullable(t.String({ format: "uri" })),
}),
season: t.Integer(),
link: t.Nullable(t.String({ format: "uri" })),
}),
),
);
export type SeasonId = typeof SeasonId.static;

View File

@ -7,42 +7,52 @@ import { DbMetadata, EpisodeId, ExternalId, Resource } from "./utils";
const Opt = (schema: TSchema) => t.Optional(t.Nullable(schema));
export const Guess = t.Recursive((Self) =>
t.Object(
{
title: t.String(),
kind: Opt(t.UnionEnum(["episode", "movie", "extra"])),
extraKind: Opt(ExtraType),
years: Opt(t.Array(t.Integer(), { default: [] })),
episodes: Opt(
t.Array(
t.Object({ season: t.Nullable(t.Integer()), episode: t.Integer() }),
{ default: [] },
),
// Workaround: t.Omit(Self, ["history"]) inside t.Recursive produces an empty
// object schema because Self is only a $ref at construction time (typebox bug).
// Instead, define the base properties separately and compose.
const GuessBase = t.Object(
{
title: t.String(),
kind: Opt(t.UnionEnum(["episode", "movie", "extra"])),
extraKind: Opt(ExtraType),
years: Opt(t.Array(t.Integer(), { default: [] })),
episodes: Opt(
t.Array(
t.Object({ season: t.Nullable(t.Integer()), episode: t.Integer() }),
{ default: [] },
),
externalId: Opt(t.Record(t.String(), t.String())),
),
externalId: Opt(t.Record(t.String(), t.String())),
from: t.String({
description: "Name of the tool that made the guess",
}),
history: t.Array(t.Omit(Self, ["history"]), {
from: t.String({
description: "Name of the tool that made the guess",
}),
},
{ additionalProperties: true },
);
export const Guess = t.Composite(
[
GuessBase,
t.Object({
history: t.Array(GuessBase, {
default: [],
description: comment`
When another tool refines the guess or a user manually edit it, the history of the guesses
are kept in this \`history\` value.
When another tool refines the guess, the history of the guesses
is kept in this \`history\` value.
`,
}),
},
{
additionalProperties: true,
description: comment`
Metadata guessed from the filename. Kyoo can use those informations to bypass
the scanner/metadata fetching and just register videos to movies/entries that already
exists. If Kyoo can't find a matching movie/entry, this information will be sent to
the scanner.
`,
},
),
}),
],
{
additionalProperties: true,
description: comment`
Metadata guessed from the filename. Kyoo can use those informations to bypass
the scanner/metadata fetching and just register videos to movies/entries that already
exists. If Kyoo can't find a matching movie/entry, this information will be sent to
the scanner.
`,
},
);
export type Guess = typeof Guess.static;
@ -88,8 +98,8 @@ export const SeedVideo = t.Object({
t.String(),
t.Omit(
t.Union([
EpisodeId.patternProperties[PatternStringExact],
ExternalId().patternProperties[PatternStringExact],
EpisodeId.patternProperties[PatternStringExact].items,
ExternalId().patternProperties[PatternStringExact].items,
]),
["link"],
),
@ -154,7 +164,7 @@ registerExamples(SeedVideo, {
{
externalId: {
themoviedatabase: {
dataId: bubble.externalId.themoviedatabase.dataId,
dataId: bubble.externalId.themoviedatabase[0].dataId,
},
},
},

View File

@ -1,60 +1,30 @@
import { db, migrate } from "~/db";
import { profiles, shows } from "~/db/schema";
import { bubble, madeInAbyss } from "~/models/examples";
import { migrate } from "~/db";
import { setupLogging } from "../src/logtape";
import { createMovie, createSerie, createVideo, getGuesses } from "./helpers";
import { createVideo } from "./helpers";
// test file used to run manually using `bun tests/manual.ts`
// run those before running this script
// export JWT_SECRET="this is a secret";
// export JWT_ISSUER="https://kyoo.zoriya.dev";
// test file used to run manually using
// `JWT_SECRET="this is a secret" JWT_ISSUER="https://kyoo.zoriya.dev" bun tests/manual.ts`
await setupLogging();
await migrate();
await db.delete(shows);
await db.delete(profiles);
const [_, ser] = await createSerie(madeInAbyss);
const [__, mov] = await createMovie(bubble);
const [resp, body] = await createVideo([
{
guess: {
title: "mia",
episodes: [{ season: 1, episode: 13 }],
from: "test",
history: [],
},
part: null,
path: "/video/mia s1e13.mkv",
rendering: "sha2",
version: 1,
for: [{ slug: `${madeInAbyss.slug}-s1e13` }],
const [resp, body] = await createVideo({
guess: {
title: "mia",
episodes: [{ season: 1, episode: 13 }],
from: "test",
history: [
{
title: "toto",
from: "tata",
},
],
},
{
guess: {
title: "mia",
episodes: [{ season: 2, episode: 1 }],
years: [2017],
from: "test",
history: [],
},
part: null,
path: "/video/mia 2017 s2e1.mkv",
rendering: "sha8",
version: 1,
for: [{ slug: `${madeInAbyss.slug}-s2e1` }],
},
{
guess: { title: "bubble", from: "test", history: [] },
part: null,
path: "/video/bubble.mkv",
rendering: "sha5",
version: 1,
for: [{ movie: bubble.slug }],
},
]);
part: null,
path: "/video/mia s1e13.mkv",
rendering: "sha2",
version: 1,
});
console.log(body);
const [___, ret] = await getGuesses();
console.log(JSON.stringify(ret, undefined, 4));
process.exit(0);

View File

@ -42,11 +42,9 @@ describe("Get series", () => {
);
expect(body.firstEntry.videos).toBeArrayOfSize(1);
// check that it's an iso datetime
console.log(body.createdAt);
expect(body.createdAt).toMatch(
/\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+Z/,
);
console.log(body.firstEntry.createdAt);
expect(body.firstEntry.createdAt).toMatch(
/\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+Z/,
);

View File

@ -81,6 +81,27 @@ describe("Video seeding", () => {
expect(vid!.evj[0].entry.slug).toBe(`${madeInAbyss.slug}-s1e13`);
});
it("With history", async () => {
const [resp, body] = await createVideo({
guess: {
title: "mia",
episodes: [{ season: 1, episode: 13 }],
from: "test",
history: [{ title: "toto", from: "tata" }],
},
part: null,
path: "/video/mia-dup-test.mkv",
rendering: "oeunounthsha2",
version: 1,
});
expectStatus(resp, body).toBe(201);
expect(body).toBeArrayOfSize(1);
expect(body[0].id).toBeString();
expect(body[0].guess.history).toBeArrayOfSize(1);
expect(body[0].guess.history[0].title).toBe("toto");
});
it("With movie", async () => {
const [resp, body] = await createVideo({
guess: { title: "bubble", from: "test", history: [] },

View File

@ -140,7 +140,7 @@ services:
path: ./scanner
target: /app
- action: rebuild
path: ./scanner/pyproject.toml
path: ./scanner/uv.lock
transcoder:
<<: *transcoder-base

View File

@ -1,7 +1,7 @@
import { useState } from "react";
import { useTranslation } from "react-i18next";
import { View } from "react-native";
import type { KImage } from "~/models";
import type { Entry, KImage } from "~/models";
import {
Image,
Link,
@ -25,7 +25,8 @@ export const EntryBox = ({
thumbnail,
href,
watchedPercent,
videosCount,
videos,
onSelectVideos,
className,
...props
}: {
@ -38,7 +39,8 @@ export const EntryBox = ({
href: string;
thumbnail: KImage | null;
watchedPercent: number;
videosCount: number;
videos: Entry["videos"];
onSelectVideos: () => void;
className?: string;
}) => {
const [moreOpened, setMoreOpened] = useState(false);
@ -46,7 +48,8 @@ export const EntryBox = ({
return (
<Link
href={moreOpened ? undefined : href}
href={moreOpened || videos.length > 1 ? undefined : href}
onPress={videos.length > 1 ? onSelectVideos : undefined}
onLongPress={() => setMoreOpened(true)}
className={cn("group w-[350px] items-center p-1 outline-0", className)}
{...props}
@ -65,7 +68,7 @@ export const EntryBox = ({
kind={kind}
slug={slug}
serieSlug={serieSlug}
videosCount={videosCount}
videoSlug={videos.length === 1 ? videos[0].slug : null}
isOpen={moreOpened}
setOpen={(v) => setMoreOpened(v)}
className={cn(

View File

@ -4,7 +4,7 @@ import { useTranslation } from "react-i18next";
import { type PressableProps, View } from "react-native";
import { EntryContext } from "~/components/items/context-menus";
import { ItemProgress } from "~/components/items/item-grid";
import type { KImage } from "~/models";
import type { Entry, KImage } from "~/models";
import {
CroppedText,
Heading,
@ -37,7 +37,7 @@ export const EntryLine = ({
href,
className,
onSelectVideos,
videosCount,
videos,
...props
}: {
kind: "episode" | "movie" | "special";
@ -55,7 +55,7 @@ export const EntryLine = ({
watchedPercent: number | null;
href: string | null;
onSelectVideos?: () => void;
videosCount: number;
videos: Entry["videos"];
} & PressableProps) => {
const [moreOpened, setMoreOpened] = useState(false);
const { t } = useTranslation();
@ -102,7 +102,7 @@ export const EntryLine = ({
</View>
<View className="flex-row">
<View className="flex-col-reverse justify-end md:flex-row md:items-center">
{videosCount > 1 && (
{videos.length > 1 && (
<PressableFeedback
onPress={(e) => {
e.preventDefault();
@ -116,7 +116,7 @@ export const EntryLine = ({
className="fill-accent dark:fill-slate-400"
/>
<SubP className="ml-2">
{t("show.videosCount", { number: videosCount })}
{t("show.videosCount", { number: videos.length })}
</SubP>
</PressableFeedback>
)}
@ -136,7 +136,7 @@ export const EntryLine = ({
kind={kind}
slug={slug}
serieSlug={serieSlug}
videosCount={videosCount}
videoSlug={videos.length === 1 ? videos[0].slug : null}
isOpen={moreOpened}
setOpen={(v) => setMoreOpened(v)}
className={cn(

View File

@ -16,14 +16,14 @@ export const EntryContext = ({
kind,
slug,
serieSlug,
videosCount,
videoSlug,
className,
...props
}: {
kind: "movie" | "episode" | "special";
serieSlug: string | null;
slug: string;
videosCount: number;
videoSlug: string | null;
className?: string;
} & Partial<ComponentProps<typeof Menu>> &
Partial<ComponentProps<typeof IconButton>>) => {
@ -50,11 +50,11 @@ export const EntryContext = ({
{/* icon={Download} */}
{/* onSelect={() => downloader(type, slug)} */}
{/* /> */}
{videosCount === 1 && (
{videoSlug && (
<Menu.Item
label={t("home.episodeMore.mediainfo")}
icon={MovieInfo}
href={`/info/${slug}`}
href={`/info/${videoSlug}`}
/>
)}
</Menu>
@ -64,12 +64,14 @@ export const EntryContext = ({
export const ItemContext = ({
kind,
slug,
videoSlug,
status,
className,
...props
}: {
kind: "movie" | "serie";
slug: string;
videoSlug: string | null;
status: WatchStatusV | null;
className?: string;
} & Partial<ComponentProps<typeof Menu>> &
@ -123,7 +125,7 @@ export const ItemContext = ({
/>
)}
</Menu.Sub>
{kind === "movie" && (
{videoSlug && (
<>
{/* <Menu.Item */}
{/* label={t("home.episodeMore.download")} */}
@ -133,7 +135,7 @@ export const ItemContext = ({
<Menu.Item
label={t("home.episodeMore.mediainfo")}
icon={MovieInfo}
href={`/info/${slug}`}
href={`/info/${videoSlug}`}
/>
</>
)}

View File

@ -20,6 +20,10 @@ export const itemMap = (
item.kind === "movie" ? (item.watchStatus?.percent ?? null) : null,
availableCount: item.kind === "serie" ? item.availableCount : null,
seenCount: item.kind === "serie" ? item.watchStatus?.seenCount : null,
videoSlug:
item.kind === "movie" && item.videos?.length === 1
? item.videos[0].slug
: null,
});
export { ItemGrid, ItemList };

View File

@ -33,6 +33,7 @@ export const ItemDetails = ({
watchStatus,
availableCount,
seenCount,
videoSlug,
className,
...props
}: {
@ -49,6 +50,7 @@ export const ItemDetails = ({
watchStatus: WatchStatusV | null;
availableCount?: number | null;
seenCount?: number | null;
videoSlug: string | null;
} & ViewProps) => {
const [moreOpened, setMoreOpened] = useState(false);
const { t } = useTranslation();
@ -90,6 +92,7 @@ export const ItemDetails = ({
status={watchStatus}
isOpen={moreOpened}
setOpen={(v) => setMoreOpened(v)}
videoSlug={videoSlug}
/>
)}
{tagline && <P className="p-1">{tagline}</P>}

View File

@ -39,6 +39,7 @@ export const ItemGrid = ({
watchPercent,
availableCount,
seenCount,
videoSlug,
horizontal = false,
className,
...props
@ -53,6 +54,7 @@ export const ItemGrid = ({
kind: "movie" | "serie" | "collection";
availableCount?: number | null;
seenCount?: number | null;
videoSlug: string | null;
horizontal?: boolean;
className?: string;
}) => {
@ -89,6 +91,7 @@ export const ItemGrid = ({
<ItemContext
kind={kind}
slug={slug}
videoSlug={videoSlug}
status={watchStatus}
isOpen={moreOpened}
setOpen={(v) => setMoreOpened(v)}

View File

@ -27,6 +27,7 @@ export const ItemList = ({
watchStatus,
availableCount,
seenCount,
videoSlug,
className,
...props
}: {
@ -39,6 +40,7 @@ export const ItemList = ({
banner: KImage | null;
watchStatus: WatchStatusV | null;
availableCount?: number | null;
videoSlug: string | null;
seenCount?: number | null;
className?: string;
}) => {
@ -75,6 +77,7 @@ export const ItemList = ({
<ItemContext
kind={kind}
slug={slug}
videoSlug={videoSlug}
status={watchStatus}
isOpen={moreOpened}
setOpen={(v) => setMoreOpened(v)}

View File

@ -1,7 +1,6 @@
import { z } from "zod/v4";
import { Show } from "./show";
import { KImage } from "./utils/images";
import { Metadata } from "./utils/metadata";
import { zdate } from "./utils/utils";
const Base = z.object({
@ -42,12 +41,15 @@ export const Episode = Base.extend({
episodeNumber: z.int().gte(0),
externalId: z.record(
z.string(),
z.object({
serieId: z.string(),
season: z.int().nullable(),
episode: z.int(),
link: z.string().nullable(),
}),
z.array(
z.object({
serieId: z.string(),
season: z.int().nullable(),
episode: z.int(),
link: z.string().nullable(),
label: z.string().optional().nullable(),
}),
),
),
});
export type Episode = z.infer<typeof Episode>;
@ -56,7 +58,25 @@ export const MovieEntry = Base.extend({
kind: z.literal("movie"),
tagline: z.string().nullable(),
poster: KImage.nullable(),
externalId: Metadata,
externalId: z.record(
z.string(),
z.array(
z.union([
z.object({
serieId: z.string(),
season: z.int().nullable(),
episode: z.int(),
link: z.string().nullable(),
label: z.string().optional().nullable(),
}),
z.object({
dataId: z.string(),
link: z.string().nullable(),
label: z.string().optional().nullable(),
}),
]),
),
),
});
export type MovieEntry = z.infer<typeof MovieEntry>;
@ -65,12 +85,14 @@ export const Special = Base.extend({
number: z.int(),
externalId: z.record(
z.string(),
z.object({
serieId: z.string(),
season: z.int().nullable(),
episode: z.int(),
link: z.string().nullable(),
}),
z.array(
z.object({
serieId: z.string(),
season: z.int().nullable(),
episode: z.int(),
link: z.string().nullable(),
}),
),
),
});
export type Special = z.infer<typeof Special>;

View File

@ -14,11 +14,13 @@ export const Season = z.object({
endAir: zdate().nullable(),
externalId: z.record(
z.string(),
z.object({
serieId: z.string(),
season: z.number(),
link: z.string().nullable(),
}),
z.array(
z.object({
serieId: z.string(),
season: z.number(),
link: z.string().nullable(),
}),
),
),
poster: KImage.nullable(),

View File

@ -2,9 +2,12 @@ import { z } from "zod/v4";
export const Metadata = z.record(
z.string(),
z.object({
dataId: z.string(),
link: z.string().nullable(),
}),
z.array(
z.object({
dataId: z.string(),
link: z.string().nullable(),
label: z.string().optional().nullable(),
}),
),
);
export type Metadata = z.infer<typeof Metadata>;

View File

@ -1,3 +1,4 @@
import type { GestureResponderEvent } from "react-native";
import { View } from "react-native";
import { cn } from "~/utils";
import { Link } from "./links";
@ -21,6 +22,7 @@ export const Chip = ({
href: string | null;
replace?: boolean;
target?: string;
onPress?: (e: GestureResponderEvent) => void;
className?: string;
}) => {
return (

View File

@ -96,6 +96,7 @@ export const Link = ({
href,
replace,
children,
disabled,
...props
}: {
href?: string | null;
@ -109,10 +110,10 @@ export const Link = ({
<PressableFeedback
{...linkProps}
{...props}
disabled={!href}
disabled={disabled ?? (!href && !props?.onPress)}
onPress={(e?: any) => {
if (!href) return;
props?.onPress?.(e);
if (!href) return;
if (e?.defaultPrevented) return;
else linkProps.onPress?.(e);
}}

View File

@ -45,6 +45,11 @@ export const CollectionDetails = () => {
description={item.description}
genres={item.genres}
playHref={item.kind !== "collection" ? item.playHref : null}
videoSlug={
item.kind === "movie" && item.videos?.length === 1
? item.videos[0].slug
: null
}
/>
)}
Loader={() => <ItemDetails.Loader />}

View File

@ -37,6 +37,7 @@ import {
Link,
Menu,
P,
Popup,
Poster,
Skeleton,
tooltip,
@ -291,6 +292,50 @@ TitleLine.Loader = ({
);
};
const ExternalIdChip = ({
name,
items,
}: {
name: string;
items: Metadata[string];
}) => {
const [setPopup, closePopup] = usePopup();
const withLinks = items.filter((x) => x.link);
if (withLinks.length === 0) return null;
return (
<Chip
label={name}
href={withLinks.length === 1 ? withLinks[0].link : null}
target="_blank"
size="small"
outline
className="m-1"
onPress={() =>
setPopup(
<Popup title={capitalize(name)} close={closePopup}>
{withLinks
.sort((a, b) =>
(a.label ?? a.link!).localeCompare(b.label ?? b.link!),
)
.map((x) => (
<A
key={x.dataId}
href={x.link!}
target="_blank"
className="rounded p-4 hover:bg-popover"
>
{x.label ?? x.link}
</A>
))}
</Popup>,
)
}
/>
);
};
const Description = ({
description,
tags,
@ -364,19 +409,9 @@ const Description = ({
)}
<View className="flex-row flex-wrap items-center">
<P className="mr-1 text-center">{t("show.links")}:</P>
{Object.entries(externalIds)
.filter(([_, data]) => data.link)
.map(([name, data]) => (
<Chip
key={name}
label={name}
href={data.link}
target="_blank"
size="small"
outline
className="m-1"
/>
))}
{Object.entries(externalIds).map(([name, items]) => (
<ExternalIdChip key={name} name={name} items={items} />
))}
</View>
</Container>
);

View File

@ -142,7 +142,7 @@ export const EntryList = ({
<EntryLine
{...item}
// Don't display "Go to serie"
videosCount={item.videos.length}
videos={item.videos}
serieSlug={null}
displayNumber={entryDisplayNumber(item)}
watchedPercent={item.progress.percent}

View File

@ -45,7 +45,7 @@ export const NextUp = ({
<EntryLine
{...entry}
serieSlug={null}
videosCount={entry.videos.length}
videos={entry.videos}
watchedPercent={entry.progress.percent}
displayNumber={displayNumber}
onSelectVideos={() =>

View File

@ -1,12 +1,34 @@
import { useCallback } from "react";
import { useTranslation } from "react-i18next";
import { EntryBox, entryDisplayNumber } from "~/components/entries";
import { EntrySelect } from "~/components/entries/select";
import { Entry } from "~/models";
import { usePopup } from "~/primitives";
import { InfiniteFetch, type QueryIdentifier } from "~/query";
import { EmptyView } from "~/ui/empty-view";
import { Header } from "./genre";
export const NewsList = () => {
const { t } = useTranslation();
const [setPopup, closePopup] = usePopup();
const openEntrySelect = useCallback(
(entry: {
displayNumber: string;
name: string | null;
videos: Entry["videos"];
}) => {
setPopup(
<EntrySelect
displayNumber={entry.displayNumber}
name={entry.name ?? ""}
videos={entry.videos}
close={closePopup}
/>,
);
},
[setPopup, closePopup],
);
return (
<>
@ -25,7 +47,14 @@ export const NewsList = () => {
thumbnail={item.thumbnail ?? item.show!.thumbnail}
href={item.href ?? "#"}
watchedPercent={item.progress.percent}
videosCount={item.videos.length}
videos={item.videos}
onSelectVideos={() =>
openEntrySelect({
displayNumber: entryDisplayNumber(item),
name: item.name,
videos: item.videos,
})
}
/>
)}
Loader={EntryBox.Loader}

View File

@ -1,9 +1,11 @@
import { useCallback } from "react";
import { useTranslation } from "react-i18next";
import { View } from "react-native";
import { EntryBox, entryDisplayNumber } from "~/components/entries";
import { EntrySelect } from "~/components/entries/select";
import { ItemGrid } from "~/components/items";
import { Entry } from "~/models";
import { Button, Link, P } from "~/primitives";
import { Button, Link, P, usePopup } from "~/primitives";
import { useAccount } from "~/providers/account-context";
import { InfiniteFetch, type QueryIdentifier } from "~/query";
import { EmptyView } from "~/ui/empty-view";
@ -12,6 +14,25 @@ import { Header } from "./genre";
export const NextupList = () => {
const { t } = useTranslation();
const account = useAccount();
const [setPopup, closePopup] = usePopup();
const openEntrySelect = useCallback(
(entry: {
displayNumber: string;
name: string | null;
videos: Entry["videos"];
}) => {
setPopup(
<EntrySelect
displayNumber={entry.displayNumber}
name={entry.name ?? ""}
videos={entry.videos}
close={closePopup}
/>,
);
},
[setPopup, closePopup],
);
if (!account) {
return (
@ -47,7 +68,14 @@ export const NextupList = () => {
thumbnail={item.thumbnail ?? item.show!.thumbnail}
href={item.href ?? "#"}
watchedPercent={item.progress.percent}
videosCount={item.videos.length}
videos={item.videos}
onSelectVideos={() =>
openEntrySelect({
displayNumber: entryDisplayNumber(item),
name: item.name,
videos: item.videos,
})
}
/>
)}
Loader={EntryBox.Loader}

View File

@ -56,6 +56,11 @@ export const Recommended = () => {
seenCount={
item.kind === "serie" ? item.watchStatus?.seenCount : null
}
videoSlug={
item.kind === "movie" && item.videos?.length === 1
? item.videos[0].slug
: null
}
/>
);
})}

View File

@ -10,7 +10,6 @@ import { z } from "zod/v4";
import { ScanRequest, Video } from "~/models";
import {
Button,
Container,
DottedSeparator,
HR,
IconButton,
@ -259,11 +258,7 @@ export const UnmatchedPage = () => {
)}
Loader={() => <VideoItem.Loader />}
Divider
Empty={
<Container>
<P className="self-center py-8">{t("admin.unmatched.empty")}</P>
</Container>
}
Empty={<P className="self-center py-8">{t("admin.unmatched.empty")}</P>}
/>
);
};

View File

@ -18,6 +18,7 @@ dependencies = [
"opentelemetry-instrumentation-fastapi>=0.59b0",
"opentelemetry-sdk>=1.38.0",
"pydantic>=2.11.4",
"pydantic-xml>=2.14.0",
"pyjwt[crypto]>=2.10.1",
"python-slugify>=8.0.4",
"watchfiles>=1.0.5",

View File

@ -54,6 +54,8 @@ class KyooClient(metaclass=Singleton):
return VideoInfo(**await r.json())
async def create_videos(self, videos: list[Video]) -> list[VideoCreated]:
if len(videos) == 0:
return []
async with self._client.post(
"videos",
data=TypeAdapter(list[Video]).dump_json(videos, by_alias=True),

View File

@ -0,0 +1,371 @@
from __future__ import annotations
import re
import unicodedata
from collections import defaultdict
from dataclasses import dataclass, field
from datetime import datetime, timedelta
from functools import cached_property
from logging import getLogger
from typing import Literal
from aiohttp import ClientSession
from pydantic import field_validator
from pydantic_xml import BaseXmlModel, attr, element, wrapped
from ..cache import cache
from ..models.metadataid import EpisodeId, MetadataId, SeasonId
from ..models.serie import Serie
from ..models.videos import Guess
from ..providers.names import ProviderName
logger = getLogger(__name__)
class AnimeTitlesDb(BaseXmlModel, tag="animetitles"):
animes: list[AnimeTitlesEntry] = element(default=[])
@classmethod
def get_url(cls):
return "https://raw.githubusercontent.com/Anime-Lists/anime-lists/master/animetitles.xml"
class AnimeTitlesEntry(BaseXmlModel, tag="anime"):
aid: str = attr()
titles: list[AnimeTitle] = element(default=[])
class AnimeTitle(
BaseXmlModel,
tag="title",
nsmap={"xml": "http://www.w3.org/XML/1998/namespace"},
):
type: str = attr()
lang: str = attr(ns="xml")
text: str
class AnimeListDb(BaseXmlModel, tag="anime-list"):
animes: list[AnimeEntry] = element(default=[])
@classmethod
def get_url(cls):
return "https://raw.githubusercontent.com/Anime-Lists/anime-lists/refs/heads/master/anime-list.xml"
class AnimeEntry(BaseXmlModel, tag="anime"):
anidbid: str = attr()
tvdbid: str | None = attr(default=None)
defaulttvdbseason: int | Literal["a"] | None = attr(default=None)
episodeoffset: int = attr(default=0)
tmdbtv: str | None = attr(default=None)
tmdbid: str | None = attr(default=None)
imdbid: str | None = attr(default=None)
name: str | None = element(default=None)
mappings: list[EpisodeMapping] = wrapped(
"mapping-list", element(default=[], tag="mapping")
)
@field_validator("tvdbid", "tmdbtv", "tmdbid", "imdbid", "defaulttvdbseason")
@classmethod
def _empty_to_none(cls, v: str | None) -> str | None:
# pornographic titles have this id.
if v == "hentai" or v == "":
return None
return v
class EpisodeMapping(BaseXmlModel):
anidbseason: int = attr()
tvdbseason: int | None = attr(default=None)
start: int | None = attr(default=None)
end: int | None = attr(default=None)
offset: int = attr(default=0)
text: str | None = None
@cached_property
def tvdb_mappings(self) -> dict[int, list[int]]:
if self.tvdbseason is None or not self.text:
return {}
ret = {}
for map in self.text.split(";"):
map = map.strip()
if not map or "-" not in map:
continue
[aid, tvdbids] = map.split("-", 1)
try:
ret[int(aid.strip())] = [
int(x.strip()) for x in tvdbids.split("+")
]
except ValueError:
continue
return ret
@dataclass
class AnimeListData:
fetched_at: datetime
# normalized title -> anidbid
titles: dict[str, str] = field(default_factory=dict)
# anidbid -> AnimeEntry
animes: dict[str, AnimeListDb.AnimeEntry] = field(default_factory=dict)
# tvdbid -> anidbid
tvdb_anidb: dict[str, list[str]] = field(default_factory=dict)
@cache(ttl=timedelta(days=30))
async def get_anilist_data() -> AnimeListData:
logger.info("Fetching anime-lists XML databases...")
ret = AnimeListData(fetched_at=datetime.now())
async with ClientSession(
headers={
"User-Agent": "kyoo scanner v5",
},
) as session:
async with session.get(AnimeTitlesDb.get_url()) as resp:
resp.raise_for_status()
titles = AnimeTitlesDb.from_xml(await resp.read())
ret.titles = {
normalize_title(title.text): x.aid
for x in titles.animes
for title in x.titles
}
async with session.get(AnimeListDb.get_url()) as resp:
resp.raise_for_status()
db = AnimeListDb.from_xml(await resp.read())
ret.animes = {entry.anidbid: entry for entry in db.animes}
ret.tvdb_anidb = defaultdict(list)
for entry in db.animes:
if not entry.tvdbid:
continue
ret.tvdb_anidb[entry.tvdbid].append(entry.anidbid)
logger.info(
"Loaded %d anime titles from animelist-xml.",
len(ret.titles),
)
return ret
def normalize_title(title: str) -> str:
title = unicodedata.normalize("NFD", title)
title = "".join(c for c in title if unicodedata.category(c) != "Mn")
title = title.lower()
title = re.sub(r"[^\w\s]", "", title)
title = re.sub(r"\s+", " ", title).strip()
return title
def anidb_to_tvdb(
anime: AnimeListDb.AnimeEntry,
anidb_ep: int,
) -> tuple[int | None, list[int]]:
for map in anime.mappings:
if map.anidbseason != 1 or map.tvdbseason is None:
continue
# Handle mapping overrides (;anidb-tvdb; format)
if anidb_ep in map.tvdb_mappings:
tvdb_eps = map.tvdb_mappings[anidb_ep]
# Mapped to 0 means no TVDB equivalent
if tvdb_eps[0] == 0:
return (None, [])
return (map.tvdbseason, tvdb_eps)
# Check start/end range with offset
if (
map.start is not None
and map.end is not None
and map.start <= anidb_ep <= map.end
):
return (map.tvdbseason, [anidb_ep + map.offset])
if anime.defaulttvdbseason == "a":
return (None, [anidb_ep])
return (anime.defaulttvdbseason, [anidb_ep + anime.episodeoffset])
def tvdb_to_anidb(
animes: list[AnimeListDb.AnimeEntry],
tvdb_season: int,
tvdb_ep: int,
) -> list[tuple[AnimeListDb.AnimeEntry, int, int]]:
for anime in animes:
for map in anime.mappings:
if map.tvdbseason != tvdb_season:
continue
# Handle mapping overrides (;anidb-tvdb; format)
overrides = [
anidb_num
for anidb_num, tvdb_nums in map.tvdb_mappings.items()
if tvdb_ep in tvdb_nums
]
if len(overrides):
return [(anime, map.anidbseason, ep) for ep in overrides]
if map.start is not None and map.end is not None:
candidate = tvdb_ep - map.offset
if map.start <= candidate <= map.end:
return [(anime, map.anidbseason, candidate)]
seasons = sorted(
(
x
for x in animes
if x.defaulttvdbseason == tvdb_season and x.episodeoffset < tvdb_ep
),
key=lambda x: x.episodeoffset,
reverse=True,
)
fallback = next(
iter(seasons),
next(
(x for x in animes if x.defaulttvdbseason == "a"),
animes[0],
),
)
return [(fallback, 1, tvdb_ep - fallback.episodeoffset)]
async def identify_anilist(_path: str, guess: Guess) -> Guess:
data = await get_anilist_data()
aid = data.titles.get(normalize_title(guess.title))
if aid is None:
return guess
anime = data.animes.get(aid)
if anime is None:
return guess
new_external_id = dict(guess.external_id)
new_external_id[ProviderName.ANIDB] = aid
if anime.tvdbid:
new_external_id[ProviderName.TVDB] = anime.tvdbid
# tmdbtv is for TV series, tmdbid is for standalone movies
if anime.tmdbtv:
new_external_id[ProviderName.TMDB] = anime.tmdbtv
elif anime.tmdbid and "," not in anime.tmdbid:
new_external_id[ProviderName.TMDB] = anime.tmdbid
if anime.imdbid and "," not in anime.imdbid:
new_external_id[ProviderName.IMDB] = anime.imdbid
# if we don't have a single external id, skip it and use the normal flow
if len(new_external_id) == 1:
return guess
logger.info(
"Matched '%s' to AniDB id %s (tvdb=%s, tmdbid=%s)",
guess.title,
aid,
anime.tvdbid,
anime.tmdbid,
)
animes = (
[data.animes[id] for id in data.tvdb_anidb.get(anime.tvdbid, [])]
if anime.tvdbid
else []
)
new_title = next(
(x.name for x in animes if x.defaulttvdbseason == 1),
next(
(x.name for x in animes if x.defaulttvdbseason == "a"),
anime.name,
),
)
new_episodes: list[Guess.Episode] = []
for ep in guess.episodes:
if (
anime.tvdbid is None
or anime.defaulttvdbseason is None
or anime.defaulttvdbseason == 1
):
new_episodes.append(
Guess.Episode(
season=ep.season or (1 if anime.defaulttvdbseason else None),
episode=ep.episode,
)
)
continue
# guess numbers are anidb-relative if defaulttvdbseason != 1 because
# the title already contains season information.
tvdb_season, tvdb_eps = anidb_to_tvdb(anime, ep.episode)
new_episodes += [
Guess.Episode(
season=tvdb_season,
episode=tvdb_ep,
)
for tvdb_ep in tvdb_eps
]
kind = guess.kind
if (
guess.kind == "movie"
and anime.tvdbid
and isinstance(anime.defaulttvdbseason, int)
):
kind = "episode"
new_episodes.append(
Guess.Episode(
season=anime.defaulttvdbseason,
episode=1 + anime.episodeoffset,
)
)
return Guess(
title=new_title or guess.title,
kind=kind,
extra_kind=guess.extra_kind,
years=guess.years,
episodes=new_episodes,
external_id=new_external_id,
raw=guess.raw,
from_="anilist",
history=[*guess.history, guess],
)
async def anilist_enrich_ids(serie: Serie):
data = await get_anilist_data()
animes = [
data.animes[aid]
for tvdb_id in serie.external_id[ProviderName.TVDB]
for aid in data.tvdb_anidb.get(tvdb_id.data_id, [])
]
if not animes:
return serie
serie.external_id[ProviderName.ANIDB] = [
MetadataId(
data_id=anime.anidbid,
link=f"https://anidb.net/anime/{anime.anidbid}",
label=anime.name,
)
for anime in animes
]
for season in serie.seasons:
season.external_id[ProviderName.ANIDB] = [
SeasonId(
serie_id=anime.anidbid,
season=1,
link=f"https://anidb.net/anime/{anime.anidbid}",
label=anime.name,
)
for anime in animes
if anime.defaulttvdbseason == season.season_number
or anime.defaulttvdbseason == "a"
]
for entry in serie.entries:
season = entry.season_number or 0
episode = entry.episode_number or entry.number
if episode is None:
continue
entry.external_id[ProviderName.ANIDB] = [
EpisodeId(serie_id=anime.anidbid, season=season, episode=ep)
for anime, season, ep in tvdb_to_anidb(animes, season, episode)
]
return serie

View File

@ -21,7 +21,7 @@ def guessit(
{
"episode_prefer_number": True,
"excludes": "language",
"expected_title": expected_titles,
"expected_titles": expected_titles,
"enforce_list": True,
"advanced": True,
}

View File

@ -76,6 +76,95 @@ class UnlistTitles(Rule):
return [titles, [title]]
class ExpectedTitles(Rule):
"""Fix both alternate names and seasons that are known titles but parsed differently by guessit
Example: "JoJo's Bizarre Adventure - Diamond is Unbreakable - 12.mkv"
Default:
```json
{
"title": "JoJo's Bizarre Adventure",
"alternative_title": "Diamond is Unbreakable",
"episode": 12,
}
```
Expected:
```json
{
"title": "JoJo's Bizarre Adventure - Diamond is Unbreakable",
"episode": 12,
}
```
Or
Example: 'Owarimonogatari S2 E15.mkv'
Default:
```json
{
"title": "Owarimonogatari",
"season": 2,
"episode": 15
}
```
Expected:
```json
{
"title": "Owarimonogatari S2",
"episode": 15
}
```
"""
priority = POST_PROCESS
consequence = [RemoveMatch, AppendMatch]
@override
def when(self, matches: Matches, context) -> Any:
from ..anilist import normalize_title
titles: list[Match] = matches.named("title", lambda m: m.tagged("title")) # type: ignore
if not titles or not context["expected_titles"]:
return
title = titles[0]
# Greedily collect all adjacent matches that could be part of the title
absorbed: list[Match] = []
current = title
while True:
nmatch: list[Match] = matches.next(current)
if not nmatch or not (
nmatch[0].tagged("title")
or nmatch[0].named("season")
or nmatch[0].named("part")
):
break
absorbed.append(nmatch[0])
current = nmatch[0]
if not absorbed:
return
# Try longest combined title first, then progressively shorter ones
for end in range(len(absorbed), 0, -1):
candidate_matches = absorbed[:end]
mtitle = f"{title.value}"
prev = title
for m in candidate_matches:
holes: list[Match] = matches.holes(prev.end, m.start) # type: ignore
hole = "".join(
f" {h.value}" if h.value != "-" else " - " for h in holes
)
mtitle = f"{mtitle}{hole}{m.value}"
prev = m
if normalize_title(mtitle) in context["expected_titles"]:
new_title = copy(title)
new_title.end = candidate_matches[-1].end
new_title.value = mtitle
return [[title] + candidate_matches, [new_title]]
class MultipleSeasonRule(Rule):
"""Understand `abcd Season 2 - 5.mkv` as S2E5

View File

@ -7,19 +7,23 @@ from typing import Callable, Literal, cast
from rebulk.match import Match
from ..models.videos import Guess, Video
from .anilist import get_anilist_data, identify_anilist
from .guess.guess import guessit
logger = getLogger(__name__)
pipeline: list[Callable[[str, Guess], Awaitable[Guess]]] = [
identify_anilist,
# TODO: add nfo scanner
# TODO: add thexem
# TODO: add anilist
]
async def identify(path: str) -> Video:
raw = guessit(path, expected_titles=[])
raw = guessit(
path,
expected_titles=list((await get_anilist_data()).titles.keys()),
)
# guessit should only return one (according to the doc)
title = raw.get("title", [])[0]

View File

@ -10,7 +10,7 @@ class Collection(Model):
original_language: Language | None
genres: list[Genre]
rating: int | None
external_id: dict[str, MetadataId]
external_id: dict[str, list[MetadataId]]
translations: dict[Language, CollectionTranslation] = {}

View File

@ -26,7 +26,7 @@ class Entry(Model):
# Special-specific fields
number: int | None
external_id: dict[str, MetadataId | EpisodeId]
external_id: dict[str, list[MetadataId | EpisodeId]]
translations: dict[Language, EntryTranslation] = {}
videos: list[str] = []
extra: dict[str, Any] = Field(exclude=True)

View File

@ -6,19 +6,26 @@ from ..utils import Model
class MetadataId(Model):
data_id: str
link: str | None = None
label: str | None = None
@classmethod
def map_dict(cls, self: dict[str, MetadataId]):
return {k: v.data_id for k, v in self.items()}
def map_dict(cls, self: dict[str, list[MetadataId]]):
return {k: v[0].data_id for k, v in self.items()}
@classmethod
def merge(
cls, self: dict[str, MetadataId], other: dict[str, MetadataId]
) -> dict[str, MetadataId]:
cls,
self: dict[str, list[MetadataId]],
other: dict[str, list[MetadataId]],
) -> dict[str, list[MetadataId]]:
ret = other | self
for k in set(self.keys()) & set(other.keys()):
if ret[k].data_id == other[k].data_id and ret[k].link is None:
ret[k].link = other[k].link
for x in ret[k]:
if x.link is not None:
continue
o = next((ox for ox in other[k] if ox.data_id == x.data_id), None)
if o:
x = o.link
return ret
@ -26,6 +33,7 @@ class SeasonId(Model):
serie_id: str
season: int
link: str | None = None
label: str | None = None
class EpisodeId(Model):

View File

@ -26,7 +26,7 @@ class Movie(Model):
runtime: int | None
air_date: date | None
external_id: dict[str, MetadataId]
external_id: dict[str, list[MetadataId]]
translations: dict[Language, MovieTranslation] = {}
collection: Collection | None = None
studios: list[Studio] = []
@ -56,4 +56,4 @@ class SearchMovie(Model):
air_date: date | None
poster: str | None
original_language: Language | None
external_id: dict[str, MetadataId]
external_id: dict[str, list[MetadataId]]

View File

@ -13,7 +13,7 @@ class Season(Model):
season_number: int
start_air: date | None
end_air: date | None
external_id: dict[str, SeasonId]
external_id: dict[str, list[SeasonId]]
translations: dict[Language, SeasonTranslation] = {}
extra: dict[str, Any] = Field(exclude=True)

View File

@ -31,7 +31,7 @@ class Serie(Model):
start_air: date | None
end_air: date | None
external_id: dict[str, MetadataId]
external_id: dict[str, list[MetadataId]]
translations: dict[Language, SerieTranslation] = {}
seasons: list[Season] = []
entries: list[Entry] = []
@ -64,4 +64,4 @@ class SearchSerie(Model):
end_air: date | None
poster: str | None
original_language: Language | None
external_id: dict[str, MetadataId]
external_id: dict[str, list[MetadataId]]

View File

@ -33,4 +33,4 @@ class Person(Model):
name: str
latin_name: str | None
image: str | None
external_id: dict[str, MetadataId]
external_id: dict[str, list[MetadataId]]

View File

@ -6,7 +6,7 @@ from .metadataid import MetadataId
class Studio(Model):
slug: str
external_id: dict[str, MetadataId]
external_id: dict[str, list[MetadataId]]
translations: dict[str, StudioTranslation] = {}

View File

@ -2,7 +2,9 @@ from typing import override
from langcodes import Language
from scanner.identifiers.anilist import anilist_enrich_ids
from scanner.models.metadataid import MetadataId
from scanner.providers.names import ProviderName
from scanner.utils import uniq_by
from ..models.movie import Movie, SearchMovie
@ -59,6 +61,8 @@ class CompositeProvider(Provider):
ret.entries, lambda x: (x.season_number, x.episode_number, x.number, x.slug)
)
ret = await anilist_enrich_ids(ret)
# themoviedb has better global info than tvdb but tvdb has better entries info
info = await self._themoviedb.get_serie(
MetadataId.map_dict(ret.external_id), skip_entries=True

View File

@ -2,3 +2,4 @@ class ProviderName:
TMDB = "themoviedatabase"
TVDB = "tvdb"
IMDB = "imdb"
ANIDB = "anidb"

View File

@ -127,10 +127,12 @@ class TheMovieDatabase(Provider):
poster=self._map_image(x["poster_path"]),
original_language=Language.get(x["original_language"]),
external_id={
self.name: MetadataId(
data_id=str(x["id"]),
link=f"https://www.themoviedb.org/movie/{x['id']}",
)
self.name: [
MetadataId(
data_id=str(x["id"]),
link=f"https://www.themoviedb.org/movie/{x['id']}",
)
]
},
)
for x in search
@ -163,17 +165,21 @@ class TheMovieDatabase(Provider):
else None,
external_id=(
{
self.name: MetadataId(
data_id=str(movie["id"]),
link=f"https://www.themoviedb.org/movie/{movie['id']}",
)
self.name: [
MetadataId(
data_id=str(movie["id"]),
link=f"https://www.themoviedb.org/movie/{movie['id']}",
)
]
}
| (
{
ProviderName.IMDB: MetadataId(
data_id=str(movie["imdb_id"]),
link=f"https://www.imdb.com/title/{movie['imdb_id']}",
)
ProviderName.IMDB: [
MetadataId(
data_id=str(movie["imdb_id"]),
link=f"https://www.imdb.com/title/{movie['imdb_id']}",
)
]
}
if movie["imdb_id"]
else {}
@ -256,10 +262,12 @@ class TheMovieDatabase(Provider):
poster=self._map_image(x["poster_path"]),
original_language=Language.get(x["original_language"]),
external_id={
self.name: MetadataId(
data_id=str(x["id"]),
link=f"https://www.themoviedb.org/tv/{x['id']}",
)
self.name: [
MetadataId(
data_id=str(x["id"]),
link=f"https://www.themoviedb.org/tv/{x['id']}",
)
]
},
)
for x in search
@ -317,27 +325,33 @@ class TheMovieDatabase(Provider):
if serie["last_air_date"]
else None,
external_id={
self.name: MetadataId(
data_id=str((serie["id"])),
link=f"https://www.themoviedb.org/tv/{serie['id']}",
),
self.name: [
MetadataId(
data_id=str((serie["id"])),
link=f"https://www.themoviedb.org/tv/{serie['id']}",
)
],
}
| (
{
ProviderName.IMDB: MetadataId(
data_id=str(serie["external_ids"]["imdb_id"]),
link=f"https://www.imdb.com/title/{serie['external_ids']['imdb_id']}",
)
ProviderName.IMDB: [
MetadataId(
data_id=str(serie["external_ids"]["imdb_id"]),
link=f"https://www.imdb.com/title/{serie['external_ids']['imdb_id']}",
)
]
}
if serie["external_ids"]["imdb_id"]
else {}
)
| (
{
ProviderName.TVDB: MetadataId(
data_id=str(serie["external_ids"]["tvdb_id"]),
link=None,
)
ProviderName.TVDB: [
MetadataId(
data_id=str(serie["external_ids"]["tvdb_id"]),
link=None,
)
]
}
if serie["external_ids"]["tvdb_id"]
else {}
@ -408,11 +422,13 @@ class TheMovieDatabase(Provider):
else None,
end_air=None,
external_id={
self.name: SeasonId(
serie_id=str(serie_id),
season=season["season_number"],
link=f"https://www.themoviedb.org/tv/{serie_id}/season/{season['season_number']}",
)
self.name: [
SeasonId(
serie_id=str(serie_id),
season=season["season_number"],
link=f"https://www.themoviedb.org/tv/{serie_id}/season/{season['season_number']}",
)
]
},
translations={
Language.get(
@ -543,12 +559,14 @@ class TheMovieDatabase(Provider):
episode_number=episode["episode_number"],
number=episode["episode_number"],
external_id={
self.name: EpisodeId(
serie_id=str(serie_id),
season=episode["season_number"],
episode=episode["episode_number"],
link=f"https://www.themoviedb.org/tv/{serie_id}/season/{episode['season_number']}/episode/{episode['episode_number']}",
),
self.name: [
EpisodeId(
serie_id=str(serie_id),
season=episode["season_number"],
episode=episode["episode_number"],
link=f"https://www.themoviedb.org/tv/{serie_id}/season/{episode['season_number']}/episode/{episode['episode_number']}",
)
],
},
translations={
Language.get(
@ -583,10 +601,12 @@ class TheMovieDatabase(Provider):
mean(float(x["vote_average"]) * 10 for x in collection["parts"])
),
external_id={
self.name: MetadataId(
data_id=str(collection["id"]),
link=f"https://www.themoviedb.org/collection/{collection['id']}",
)
self.name: [
MetadataId(
data_id=str(collection["id"]),
link=f"https://www.themoviedb.org/collection/{collection['id']}",
)
]
},
translations={
Language.get(
@ -685,10 +705,12 @@ class TheMovieDatabase(Provider):
return Studio(
slug=to_slug(company["name"]),
external_id={
self.name: MetadataId(
data_id=str(company["id"]),
link=f"https://www.themoviedb.org/company/{company['id']}",
)
self.name: [
MetadataId(
data_id=str(company["id"]),
link=f"https://www.themoviedb.org/company/{company['id']}",
)
]
},
translations={
"en": StudioTranslation(
@ -714,10 +736,12 @@ class TheMovieDatabase(Provider):
latin_name=person["name"],
image=self._map_image(person["profile_path"]),
external_id={
self.name: MetadataId(
data_id=str(person["id"]),
link=f"https://www.themoviedb.org/person/{person['id']}",
)
self.name: [
MetadataId(
data_id=str(person["id"]),
link=f"https://www.themoviedb.org/person/{person['id']}",
)
]
},
),
)

View File

@ -181,10 +181,12 @@ class TVDB(Provider):
poster=x["image_url"],
original_language=Language.get(x["primary_language"]),
external_id={
self.name: MetadataId(
data_id=str(x["tvdb_id"]),
link=f"https://thetvdb.com/series/{x['slug']}",
),
self.name: [
MetadataId(
data_id=str(x["tvdb_id"]),
link=f"https://thetvdb.com/series/{x['slug']}",
)
],
},
)
for x in ret["data"]
@ -234,10 +236,12 @@ class TVDB(Provider):
start_air=datetime.strptime(ret["firstAired"], "%Y-%m-%d").date(),
end_air=datetime.strptime(ret["lastAired"], "%Y-%m-%d").date(),
external_id={
self.name: MetadataId(
data_id=ret["id"],
link=f"https://thetvdb.com/series/{ret['slug']}",
),
self.name: [
MetadataId(
data_id=ret["id"],
link=f"https://thetvdb.com/series/{ret['slug']}",
)
],
**self._process_remote_id(ret["remoteIds"]),
},
translations={
@ -332,7 +336,7 @@ class TVDB(Provider):
def _process_remote_id(
self, ids: list[dict[str, Any]] | None
) -> dict[str, MetadataId]:
) -> dict[str, list[MetadataId]]:
# sometimes `remoteIds` is not even part of the response.
if ids is None:
return {}
@ -341,11 +345,11 @@ class TVDB(Provider):
imdb = next((x["id"] for x in ids if x["sourceName"] == "IMDB"), None)
if imdb is not None:
ret[ProviderName.IMDB] = MetadataId(data_id=imdb)
ret[ProviderName.IMDB] = [MetadataId(data_id=imdb)]
tmdb = next((x["id"] for x in ids if x["sourceName"] == "TheMovieDB.com"), None)
if tmdb is not None:
ret[ProviderName.TMDB] = MetadataId(data_id=tmdb)
ret[ProviderName.TMDB] = [MetadataId(data_id=tmdb)]
return ret
@ -421,10 +425,12 @@ class TVDB(Provider):
],
rating=None,
external_id={
self.name: MetadataId(
data_id=data["id"],
link=f"https://thetvdb.com/lists/{data['url']}",
)
self.name: [
MetadataId(
data_id=data["id"],
link=f"https://thetvdb.com/lists/{data['url']}",
)
]
},
translations={
Language.get(lang): tl
@ -472,10 +478,12 @@ class TVDB(Provider):
default=None,
),
external_id={
self.name: SeasonId(
serie_id=info["seriesId"],
season=info["number"],
),
self.name: [
SeasonId(
serie_id=info["seriesId"],
season=info["number"],
)
],
},
translations={Language.get(lang): tl for lang, tl in zip(languages, trans)},
extra={},
@ -520,12 +528,14 @@ class TVDB(Provider):
episode_number=entry["number"],
number=entry["number"],
external_id={
self.name: EpisodeId(
serie_id=str(serie_id),
season=entry["seasonNumber"],
episode=entry["number"],
link=f"https://thetvdb.com/series/{serie_id}/episodes/{entry['id']}",
),
self.name: [
EpisodeId(
serie_id=str(serie_id),
season=entry["seasonNumber"],
episode=entry["number"],
link=f"https://thetvdb.com/series/{serie_id}/episodes/{entry['id']}",
)
],
},
translations={
Language.get(lang): EntryTranslation(
@ -672,11 +682,13 @@ class TVDB(Provider):
for trans in ret["translations"]["nameTranslations"]
if trans.get("isAlias") is None or False
}
entry.external_id = {
self.name: MetadataId(
data_id=ret["id"],
link=f"https://thetvdb.com/movies/{ret['slug']}",
),
entry.external_id = { # pyright: ignore[reportAttributeAccessIssue]
self.name: [
MetadataId(
data_id=ret["id"],
link=f"https://thetvdb.com/movies/{ret['slug']}",
)
],
**self._process_remote_id(ret["remoteIds"]),
}
@ -731,10 +743,12 @@ class TVDB(Provider):
if ret.get("first_release") and ret["first_release"].get("date")
else None,
external_id={
self.name: MetadataId(
data_id=ret["id"],
link=f"https://thetvdb.com/series/{ret['slug']}",
),
self.name: [
MetadataId(
data_id=ret["id"],
link=f"https://thetvdb.com/series/{ret['slug']}",
)
],
**self._process_remote_id(ret["remoteIds"]),
},
translations={

15
scanner/uv.lock generated
View File

@ -1259,6 +1259,19 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/c1/60/5d4751ba3f4a40a6891f24eec885f51afd78d208498268c734e256fb13c4/pydantic_settings-2.12.0-py3-none-any.whl", hash = "sha256:fddb9fd99a5b18da837b29710391e945b1e30c135477f484084ee513adb93809", size = 51880, upload-time = "2025-11-10T14:25:45.546Z" },
]
[[package]]
name = "pydantic-xml"
version = "2.19.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "pydantic" },
{ name = "pydantic-core" },
]
sdist = { url = "https://files.pythonhosted.org/packages/b8/cb/5f80b61d73a8d6171ee4611bfd2b944c036c6f6e5f6e01d9fb02f29d7bfc/pydantic_xml-2.19.0.tar.gz", hash = "sha256:b7acba5a0966cbbbc9bf88d0d870b2bc875da063fe1bbe62d83939b549224730", size = 26228, upload-time = "2026-02-14T17:33:53.368Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/27/2d/dce0dc471fade04829c2948462d79c9bc4991305b0f73889f70c9645e540/pydantic_xml-2.19.0-py3-none-any.whl", hash = "sha256:42854bf962758bec338c112c2de984723708262793e108416f33aa4d6c11b3b4", size = 42536, upload-time = "2026-02-14T17:33:54.206Z" },
]
[[package]]
name = "pygments"
version = "2.19.2"
@ -1482,6 +1495,7 @@ dependencies = [
{ name = "opentelemetry-instrumentation-fastapi" },
{ name = "opentelemetry-sdk" },
{ name = "pydantic" },
{ name = "pydantic-xml" },
{ name = "pyjwt", extra = ["crypto"] },
{ name = "python-slugify" },
{ name = "watchfiles" },
@ -1502,6 +1516,7 @@ requires-dist = [
{ name = "opentelemetry-instrumentation-fastapi", specifier = ">=0.59b0" },
{ name = "opentelemetry-sdk", specifier = ">=1.38.0" },
{ name = "pydantic", specifier = ">=2.11.4" },
{ name = "pydantic-xml", specifier = ">=2.14.0" },
{ name = "pyjwt", extras = ["crypto"], specifier = ">=2.10.1" },
{ name = "python-slugify", specifier = ">=8.0.4" },
{ name = "watchfiles", specifier = ">=1.0.5" },