diff --git a/.github/workflows/client-release.yml b/.github/workflows/client-release.yml index 1342d7b8..ee511a24 100644 --- a/.github/workflows/client-release.yml +++ b/.github/workflows/client-release.yml @@ -83,6 +83,10 @@ jobs: security unlock-keychain -p "$KEYCHAIN_PASSWORD" build.keychain security set-keychain-settings -t 3600 -u build.keychain + # Add build.keychain to the user keychain search list so that codesign + # (invoked later by tauri-action WITHOUT an explicit --keychain) can + # resolve the signing identity from it. + security list-keychains -d user -s build.keychain $(security list-keychains -d user | tr -d '"') echo "Created keychain" @@ -118,8 +122,12 @@ jobs: - uses: tauri-apps/tauri-action@v0 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }} - APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }} + # Do NOT set APPLE_CERTIFICATE / APPLE_CERTIFICATE_PASSWORD here. Doing so + # makes tauri-action import the cert into its own throwaway keychain and + # look up the identity by Apple-only name prefixes (e.g. + # "Developer ID Application:"), which never matches our "Drop OSS" cert + # and fails with "failed to resolve signing identity". Instead we rely on + # the build.keychain prepared above and only pass the resolved identity. APPLE_SIGNING_IDENTITY: ${{ env.CERT_ID }} NO_STRIP: true with: diff --git a/.github/workflows/server-release.yml b/.github/workflows/server-release.yml index b036009a..208f402f 100644 --- a/.github/workflows/server-release.yml +++ b/.github/workflows/server-release.yml @@ -89,8 +89,6 @@ jobs: build-args: | BUILD_DROP_VERSION=${{ steps.get_final_ver.outputs.final_ver }} BUILD_GIT_REF=${{ github.sha }} - context: ./server - file: ./server/Dockerfile - name: Export digest run: | diff --git a/Dockerfile b/Dockerfile index a647d2bc..ee3d89f7 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,8 @@ # syntax=docker/dockerfile:1 -FROM node:lts-alpine AS base +# Pinned to bookworm so the glibc here matches the torrential build stage +# and the libarchive runtime package is named `libarchive13` (trixie renames it to libarchive13t64). +FROM node:lts-bookworm-slim AS base ENV PNPM_HOME="/pnpm" ENV PATH="$PNPM_HOME:$PATH" RUN corepack enable @@ -20,11 +22,17 @@ FROM base AS deps RUN pnpm install --frozen-lockfile --ignore-scripts ### BUILD TORRENTIAL -FROM rustlang/rust:nightly-alpine AS torrential-build -RUN apk add musl-dev pkgconfig libarchive-dev libarchive +# Bookworm-pinned to match the runtime image's glibc (a trixie build would not run on bookworm). +FROM rustlang/rust:nightly-bookworm-slim AS torrential-build +## libarchive-dev + pkg-config let libarchive3-sys link libarchive dynamically (glibc). +## protobuf-compiler is kept for parity (torrential's build.rs uses a vendored protoc). +RUN apt-get update && apt-get install -y --no-install-recommends \ + pkg-config \ + libarchive-dev \ + protobuf-compiler \ + && rm -rf /var/lib/apt/lists/* WORKDIR /build COPY . . -RUN apk add protoc RUN cargo build --release --manifest-path ./torrential/Cargo.toml ### BUILD APP @@ -34,7 +42,8 @@ ENV NODE_ENV=production ENV NUXT_TELEMETRY_DISABLED=1 ## add git so drop can determine its git ref at build -RUN apk add --no-cache git +RUN apt-get update && apt-get install -y --no-install-recommends git \ + && rm -rf /var/lib/apt/lists/* ## copy deps and rest of project files COPY . . @@ -55,7 +64,19 @@ ENV NODE_ENV=production ENV NUXT_TELEMETRY_DISABLED=1 # RUN --mount=type=cache,target=/root/.yarn YARN_CACHE_FOLDER=/root/.yarn yarn add --network-timeout 1000000 --no-lockfile --ignore-scripts prisma@6.11.1 -RUN apk add --no-cache pnpm 7zip nginx +## runtime deps: +## - libarchive13: torrential now links libarchive dynamically (glibc build) +## - p7zip-full: provides the 7z CLI +## - nginx: front-end proxy +## - openssl + ca-certificates: required by Prisma's query engine on Debian +## pnpm itself is provided by corepack (enabled in the base stage) +RUN apt-get update && apt-get install -y --no-install-recommends \ + libarchive13 \ + p7zip-full \ + nginx \ + openssl \ + ca-certificates \ + && rm -rf /var/lib/apt/lists/* RUN pnpm install prisma@7.3.0 --global # init prisma to download all required files RUN pnpm prisma init diff --git a/desktop/.github/workflows/clippy.yml b/desktop/.github/workflows/clippy.yml deleted file mode 100644 index 0db08a07..00000000 --- a/desktop/.github/workflows/clippy.yml +++ /dev/null @@ -1,23 +0,0 @@ -on: push -name: Clippy check -jobs: - clippy_check: - runs-on: ubuntu-24.04 - permissions: - checks: write - steps: - - uses: actions/checkout@v1 - - name: install dependencies (ubuntu only) - run: | - sudo apt-get update - sudo apt-get install -y libglib2.0-dev libgtk-3-dev libwebkit2gtk-4.1-dev - - - uses: actions-rs/toolchain@v1 - with: - toolchain: nightly - components: clippy - override: true - - uses: actions-rs/clippy-check@v1 - with: - token: ${{ secrets.GITHUB_TOKEN }} - args: --manifest-path ./src-tauri/Cargo.toml \ No newline at end of file diff --git a/desktop/package.json b/desktop/package.json index 07451434..fe268aa9 100644 --- a/desktop/package.json +++ b/desktop/package.json @@ -7,7 +7,7 @@ "tauri": "tauri" }, "dependencies": { - "pino": "^9.7.0", + "pino": "^9.14.0", "pino-pretty": "^13.1.1", "tauri": "^0.15.0" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2ed4dfbc..c4a519b2 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -60,7 +60,7 @@ importers: desktop: dependencies: pino: - specifier: ^9.7.0 + specifier: ^9.14.0 version: 9.14.0 pino-pretty: specifier: ^13.1.1 @@ -209,10 +209,10 @@ importers: specifier: ^1.0.2 version: 1.0.2 pino: - specifier: 9.7.0 - version: 9.7.0 + specifier: ^9.14.0 + version: 9.14.0 pino-pretty: - specifier: ^13.0.0 + specifier: ^13.1.1 version: 13.1.3 prisma: specifier: 7.3.0 @@ -375,8 +375,8 @@ importers: specifier: ^12.23.11 version: 12.38.0(@emotion/is-prop-valid@1.4.0)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) next: - specifier: 15.4.4 - version: 15.4.4(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(sass@1.99.0) + specifier: 15.5.18 + version: 15.5.18(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(sass@1.99.0) react: specifier: ^19 version: 19.2.5 @@ -398,7 +398,7 @@ importers: version: 0.2.2(@content-collections/core@0.11.1(typescript@5.9.3))(react-dom@19.2.5(react@19.2.5))(react@19.2.5) '@content-collections/next': specifier: ^0.2.7 - version: 0.2.11(@content-collections/core@0.11.1(typescript@5.9.3))(next@15.4.4(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(sass@1.99.0)) + version: 0.2.11(@content-collections/core@0.11.1(typescript@5.9.3))(next@15.5.18(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(sass@1.99.0)) '@eslint/eslintrc': specifier: ^3 version: 3.3.5 @@ -1849,60 +1849,60 @@ packages: '@emnapi/core': ^1.7.1 '@emnapi/runtime': ^1.7.1 - '@next/env@15.4.4': - resolution: {integrity: sha512-SJKOOkULKENyHSYXE5+KiFU6itcIb6wSBjgM92meK0HVKpo94dNOLZVdLLuS7/BxImROkGoPsjR4EnuDucqiiA==} + '@next/env@15.5.18': + resolution: {integrity: sha512-hAV85Ckd9QR6RvH04MEKwsfLTksvFpO47j9xwtoIuvuPnlwecpSi+uZTtm8HirVbtlI2Fnz//xpcSTjFdyJk+g==} '@next/eslint-plugin-next@15.4.4': resolution: {integrity: sha512-1FDsyN//ai3Jd97SEd7scw5h1yLdzDACGOPRofr2GD3sEFsBylEEoL0MHSerd4n2dq9Zm/mFMqi4+NRMOreOKA==} - '@next/swc-darwin-arm64@15.4.4': - resolution: {integrity: sha512-eVG55dnGwfUuG+TtnUCt+mEJ+8TGgul6nHEvdb8HEH7dmJIFYOCApAaFrIrxwtEq2Cdf+0m5sG1Np8cNpw9EAw==} + '@next/swc-darwin-arm64@15.5.18': + resolution: {integrity: sha512-w0WvQf1n+txiwns/9pwIQteCJpZTbxzO2SE0FLcwuD4v0WEh1JPOjdyxWL21XwJsdpx8cFRjyzxzCS/siP7HcQ==} engines: {node: '>= 10'} cpu: [arm64] os: [darwin] - '@next/swc-darwin-x64@15.4.4': - resolution: {integrity: sha512-zqG+/8apsu49CltEj4NAmCGZvHcZbOOOsNoTVeIXphYWIbE4l6A/vuQHyqll0flU2o3dmYCXsBW5FmbrGDgljQ==} + '@next/swc-darwin-x64@15.5.18': + resolution: {integrity: sha512-znn71QmDuxm+BOaglihMZfvyySMnNljkVIY5Z2TCssBmm+WqL6c19VhtH5ktFkHa8EZ2bnTUpcNcmNSQsg67og==} engines: {node: '>= 10'} cpu: [x64] os: [darwin] - '@next/swc-linux-arm64-gnu@15.4.4': - resolution: {integrity: sha512-LRD4l2lq4R+2QCHBQVC0wjxxkLlALGJCwigaJ5FSRSqnje+MRKHljQNZgDCaKUZQzO/TXxlmUdkZP/X3KNGZaw==} + '@next/swc-linux-arm64-gnu@15.5.18': + resolution: {integrity: sha512-yPPe5MNL+igZUa+OsqQJisqSfh6oarIuA1Q0BDxljGJhRQyZeP+WRHh7rs/jZUGMh5aY0YdIjXZG0VohkKkUdw==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] libc: [glibc] - '@next/swc-linux-arm64-musl@15.4.4': - resolution: {integrity: sha512-LsGUCTvuZ0690fFWerA4lnQvjkYg9gHo12A3wiPUR4kCxbx/d+SlwmonuTH2SWZI+RVGA9VL3N0S03WTYv6bYg==} + '@next/swc-linux-arm64-musl@15.5.18': + resolution: {integrity: sha512-glaCczEWIrHsokFZ3pP08U4BpKxwIdnT+txdOM32OBgpL9Yw4aqx8NejmgtZQZOdstQ5f0L3CasIZudzCuD+nw==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] libc: [musl] - '@next/swc-linux-x64-gnu@15.4.4': - resolution: {integrity: sha512-aOy5yNRpLL3wNiJVkFYl6w22hdREERNjvegE6vvtix8LHRdsTHhWTpgvcYdCK7AIDCQW5ATmzr9XkPHvSoAnvg==} + '@next/swc-linux-x64-gnu@15.5.18': + resolution: {integrity: sha512-oUfg2EgJmU3R0OCOWiokGFUTvZiPfXtriXiuF3YNxRoROCdgvTedHIzYoeKH34gsZxS/V7mHbfq2hpAHwhH1/A==} engines: {node: '>= 10'} cpu: [x64] os: [linux] libc: [glibc] - '@next/swc-linux-x64-musl@15.4.4': - resolution: {integrity: sha512-FL7OAn4UkR8hKQRGBmlHiHinzOb07tsfARdGh7v0Z0jEJ3sz8/7L5bR23ble9E6DZMabSStqlATHlSxv1fuzAg==} + '@next/swc-linux-x64-musl@15.5.18': + resolution: {integrity: sha512-JLxSP3KTd9iu/bvUMQxH7RJo9xKSHf55/6RPE4a6FTSZygGn7uvZbCej0AHXydwkggQGSD9UddSjwv6Xz5ESfA==} engines: {node: '>= 10'} cpu: [x64] os: [linux] libc: [musl] - '@next/swc-win32-arm64-msvc@15.4.4': - resolution: {integrity: sha512-eEdNW/TXwjYhOulQh0pffTMMItWVwKCQpbziSBmgBNFZIIRn2GTXrhrewevs8wP8KXWYMx8Z+mNU0X+AfvtrRg==} + '@next/swc-win32-arm64-msvc@15.5.18': + resolution: {integrity: sha512-ir1v7enP52K2HNz3tQQvwF+x7VNxBk1ciiZ18WBPvxf4C59IqdfmHPJYK3vH7rSxpuCVw/8C712wTXNAtEp+NA==} engines: {node: '>= 10'} cpu: [arm64] os: [win32] - '@next/swc-win32-x64-msvc@15.4.4': - resolution: {integrity: sha512-SE5pYNbn/xZKMy1RE3pAs+4xD32OI4rY6mzJa4XUkp/ItZY+OMjIgilskmErt8ls/fVJ+Ihopi2QIeW6O3TrMw==} + '@next/swc-win32-x64-msvc@15.5.18': + resolution: {integrity: sha512-LIu5me6QTANCd25E7I5uIEfvgQ06RK7tvHAbYo3zCb3VpxQEPvMcSpd87NwUABDT6MbGPdEGR5VRiK4PPTJhQg==} engines: {node: '>= 10'} cpu: [x64] os: [win32] @@ -5784,10 +5784,6 @@ packages: resolution: {integrity: sha512-tWhw7z4jFuQgZB9tbQyUh5BY9nNd/wimM+fBLfmmJjakkJDNvbJKm0nQ5ruPKC0us1HGg7L6iBk1fxpSzcgSaA==} hasBin: true - fast-redact@3.5.0: - resolution: {integrity: sha512-dwsoQlS7h9hMeYUq1W++23NDcBLV4KqONnITDV9DjfS3q1SgDGVrBdvvTLUotWtPSD7asWDV9/CmsZPy8Hf70A==} - engines: {node: '>=6'} - fast-safe-stringify@2.1.1: resolution: {integrity: sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==} @@ -7635,10 +7631,9 @@ packages: resolution: {integrity: sha512-Z4SmBUweYa09+o6pG+eASabEpP6QkQ70yHj351pQoEXIs8uHbaU2DWVmzBANKgflPa47A50PtB2+NgRpQvr7vA==} engines: {node: '>= 10'} - next@15.4.4: - resolution: {integrity: sha512-kNcubvJjOL9yUOfwtZF3HfDhuhp+kVD+FM2A6Tyua1eI/xfmY4r/8ZS913MMz+oWKDlbps/dQOWdDricuIkXLw==} + next@15.5.18: + resolution: {integrity: sha512-eKL8zUJkX9Y5lE+RX/2YJoItVdGlIscyVyboeD9wSpp0PaGqjoA4tTpT2qPqz9ax+5IzGESyLSeZ/RCwbSZ2uQ==} engines: {node: ^18.18.0 || ^19.8.0 || >= 20.0.0} - deprecated: This version has a security vulnerability. Please upgrade to a patched version. See https://nextjs.org/blog/CVE-2025-66478 for more details. hasBin: true peerDependencies: '@opentelemetry/api': ^1.1.0 @@ -8221,10 +8216,6 @@ packages: resolution: {integrity: sha512-8OEwKp5juEvb/MjpIc4hjqfgCNysrS94RIOMXYvpYCdm/jglrKEiAYmiumbmGhCvs+IcInsphYDFwqrjr7398w==} hasBin: true - pino@9.7.0: - resolution: {integrity: sha512-vnMCM6xZTb1WDmLvtG2lE/2p+t9hDEIvTWJsu6FejkE62vB7gDhvzrpFR4Cw2to+9JNQxVnkAKVPA1KPB98vWg==} - hasBin: true - pkg-types@1.3.1: resolution: {integrity: sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==} @@ -11204,11 +11195,11 @@ snapshots: transitivePeerDependencies: - supports-color - '@content-collections/next@0.2.11(@content-collections/core@0.11.1(typescript@5.9.3))(next@15.4.4(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(sass@1.99.0))': + '@content-collections/next@0.2.11(@content-collections/core@0.11.1(typescript@5.9.3))(next@15.5.18(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(sass@1.99.0))': dependencies: '@content-collections/core': 0.11.1(typescript@5.9.3) '@content-collections/integrations': 0.5.0(@content-collections/core@0.11.1(typescript@5.9.3)) - next: 15.4.4(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(sass@1.99.0) + next: 15.5.18(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(sass@1.99.0) '@cto.af/wtf8@0.0.5': {} @@ -12103,34 +12094,34 @@ snapshots: '@tybys/wasm-util': 0.10.2 optional: true - '@next/env@15.4.4': {} + '@next/env@15.5.18': {} '@next/eslint-plugin-next@15.4.4': dependencies: fast-glob: 3.3.1 - '@next/swc-darwin-arm64@15.4.4': + '@next/swc-darwin-arm64@15.5.18': optional: true - '@next/swc-darwin-x64@15.4.4': + '@next/swc-darwin-x64@15.5.18': optional: true - '@next/swc-linux-arm64-gnu@15.4.4': + '@next/swc-linux-arm64-gnu@15.5.18': optional: true - '@next/swc-linux-arm64-musl@15.4.4': + '@next/swc-linux-arm64-musl@15.5.18': optional: true - '@next/swc-linux-x64-gnu@15.4.4': + '@next/swc-linux-x64-gnu@15.5.18': optional: true - '@next/swc-linux-x64-musl@15.4.4': + '@next/swc-linux-x64-musl@15.5.18': optional: true - '@next/swc-win32-arm64-msvc@15.4.4': + '@next/swc-win32-arm64-msvc@15.5.18': optional: true - '@next/swc-win32-x64-msvc@15.4.4': + '@next/swc-win32-x64-msvc@15.5.18': optional: true '@nodelib/fs.scandir@2.1.5': @@ -17044,8 +17035,6 @@ snapshots: fast-npm-meta@1.5.1: {} - fast-redact@3.5.0: {} - fast-safe-stringify@2.1.1: {} fast-string-truncated-width@1.2.1: {} @@ -19351,24 +19340,24 @@ snapshots: neotraverse@0.6.18: {} - next@15.4.4(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(sass@1.99.0): + next@15.5.18(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(sass@1.99.0): dependencies: - '@next/env': 15.4.4 + '@next/env': 15.5.18 '@swc/helpers': 0.5.15 - caniuse-lite: 1.0.30001788 + caniuse-lite: 1.0.30001793 postcss: 8.4.31 react: 19.2.5 react-dom: 19.2.5(react@19.2.5) styled-jsx: 5.1.6(react@19.2.5) optionalDependencies: - '@next/swc-darwin-arm64': 15.4.4 - '@next/swc-darwin-x64': 15.4.4 - '@next/swc-linux-arm64-gnu': 15.4.4 - '@next/swc-linux-arm64-musl': 15.4.4 - '@next/swc-linux-x64-gnu': 15.4.4 - '@next/swc-linux-x64-musl': 15.4.4 - '@next/swc-win32-arm64-msvc': 15.4.4 - '@next/swc-win32-x64-msvc': 15.4.4 + '@next/swc-darwin-arm64': 15.5.18 + '@next/swc-darwin-x64': 15.5.18 + '@next/swc-linux-arm64-gnu': 15.5.18 + '@next/swc-linux-arm64-musl': 15.5.18 + '@next/swc-linux-x64-gnu': 15.5.18 + '@next/swc-linux-x64-musl': 15.5.18 + '@next/swc-win32-arm64-msvc': 15.5.18 + '@next/swc-win32-x64-msvc': 15.5.18 sass: 1.99.0 sharp: 0.34.5 transitivePeerDependencies: @@ -20382,20 +20371,6 @@ snapshots: sonic-boom: 4.2.1 thread-stream: 3.1.0 - pino@9.7.0: - dependencies: - atomic-sleep: 1.0.0 - fast-redact: 3.5.0 - on-exit-leak-free: 2.1.2 - pino-abstract-transport: 2.0.0 - pino-std-serializers: 7.1.0 - process-warning: 5.0.0 - quick-format-unescaped: 4.0.4 - real-require: 0.2.0 - safe-stable-stringify: 2.5.0 - sonic-boom: 4.2.1 - thread-stream: 3.1.0 - pkg-types@1.3.1: dependencies: confbox: 0.1.8 @@ -20601,7 +20576,7 @@ snapshots: postcss@8.4.31: dependencies: - nanoid: 3.3.11 + nanoid: 3.3.12 picocolors: 1.1.1 source-map-js: 1.2.1 diff --git a/server/README.md b/server/README.md index 8ec199e9..ca29a1c6 100644 --- a/server/README.md +++ b/server/README.md @@ -1,3 +1,3 @@ # Server -The hosted, accessible portion of Drop. Exposes a web UI and API for applications to use. \ No newline at end of file +The hosted, accessible portion of Drop. Exposes a web UI and API for applications to use. diff --git a/server/buf.gen.yaml b/server/buf.gen.yaml index e14bc0bc..f276beb5 100644 --- a/server/buf.gen.yaml +++ b/server/buf.gen.yaml @@ -5,4 +5,4 @@ plugins: opt: target=ts inputs: - - directory: ../ \ No newline at end of file + - directory: ../ diff --git a/server/drop-base b/server/drop-base deleted file mode 160000 index dad3487b..00000000 --- a/server/drop-base +++ /dev/null @@ -1 +0,0 @@ -Subproject commit dad3487be66919348149c4392af2cc3f10f0a50b diff --git a/server/eslint.config.mjs b/server/eslint.config.mjs index c012cfde..bab6c849 100644 --- a/server/eslint.config.mjs +++ b/server/eslint.config.mjs @@ -11,9 +11,9 @@ export default withNuxt([ eslintConfigPrettier, // vue-i18n plugin - // @ts-expect-error + // @ts-expect-error ...vueI18n.configs.recommended, - // @ts-expect-error + // @ts-expect-error { rules: { // Optional. @@ -37,10 +37,10 @@ export default withNuxt([ }, }, }, - // @ts-expect-error + // @ts-expect-error { plugins: { drop: { rules: { "no-prisma-delete": noPrismaDelete } }, }, - } + }, ]); diff --git a/server/package.json b/server/package.json index b13886c0..a03cf9b1 100644 --- a/server/package.json +++ b/server/package.json @@ -56,8 +56,8 @@ "nuxt-security": "2.2.0", "otp-io": "^1.2.7", "parse-cosekey": "^1.0.2", - "pino": "9.7.0", - "pino-pretty": "^13.0.0", + "pino": "^9.14.0", + "pino-pretty": "^13.1.1", "prisma": "7.3.0", "sanitize-filename": "^1.6.3", "semver": "^7.7.1", diff --git a/server/server/internal/library/providers/filesystem.ts b/server/server/internal/library/providers/filesystem.ts index 7361fc4d..1bb2f3e1 100644 --- a/server/server/internal/library/providers/filesystem.ts +++ b/server/server/internal/library/providers/filesystem.ts @@ -14,9 +14,9 @@ export const FilesystemProviderConfig = type({ baseDir: "string", }); -export class FilesystemProvider - implements LibraryProvider -{ +export class FilesystemProvider implements LibraryProvider< + typeof FilesystemProviderConfig.infer +> { private config: typeof FilesystemProviderConfig.infer; private myId: string; diff --git a/server/server/internal/library/providers/flat.ts b/server/server/internal/library/providers/flat.ts index c02fa45d..893f2c66 100644 --- a/server/server/internal/library/providers/flat.ts +++ b/server/server/internal/library/providers/flat.ts @@ -11,9 +11,9 @@ export const FlatFilesystemProviderConfig = type({ baseDir: "string", }); -export class FlatFilesystemProvider - implements LibraryProvider -{ +export class FlatFilesystemProvider implements LibraryProvider< + typeof FlatFilesystemProviderConfig.infer +> { private config: typeof FlatFilesystemProviderConfig.infer; private myId: string; diff --git a/server/server/internal/metadata/pcgamingwiki.ts b/server/server/internal/metadata/pcgamingwiki.ts index c16f45fb..87e2fff7 100644 --- a/server/server/internal/metadata/pcgamingwiki.ts +++ b/server/server/internal/metadata/pcgamingwiki.ts @@ -188,7 +188,10 @@ export class PCGamingWikiProvider implements MetadataProvider { return url.pathname.replace("/games/", "").replace(/\/$/, ""); } default: { - logger.warn("Pcgamingwiki, unknown host", url.hostname); + logger.warn( + { hostname: url.hostname }, + "Pcgamingwiki, unknown host", + ); return undefined; } } @@ -222,8 +225,8 @@ export class PCGamingWikiProvider implements MetadataProvider { }); if (ratingObj instanceof type.errors) { logger.info( + { summary: ratingObj.summary }, "pcgamingwiki: failed to properly get review rating", - ratingObj.summary, ); return undefined; } @@ -327,7 +330,7 @@ export class PCGamingWikiProvider implements MetadataProvider { * @returns */ private parseTS(isoStr: string): DateTime { - return DateTime.fromISO(isoStr.split(";")[0]); + return DateTime.fromISO(isoStr.split(";")[0]!); } private parseWebsitesGetFirst(websiteStr?: string | null): string { @@ -429,7 +432,7 @@ export class PCGamingWikiProvider implements MetadataProvider { ); const released = game.Released - ? DateTime.fromISO(game.Released.split(";")[0]).toJSDate() + ? DateTime.fromISO(game.Released.split(";")[0]!).toJSDate() : new Date(); const metadata: GameMetadata = { diff --git a/server/server/internal/metadata/steam.ts b/server/server/internal/metadata/steam.ts index f89f90f7..706d6dda 100644 --- a/server/server/internal/metadata/steam.ts +++ b/server/server/internal/metadata/steam.ts @@ -306,7 +306,8 @@ export class SteamProvider implements MetadataProvider { "https://store.steampowered.com/publisher/", ), ) - .map((v) => v.attribs.href); + .map((v) => v.attribs.href) + .filter((v) => v !== undefined); const companies: { [key: string]: { @@ -320,6 +321,8 @@ export class SteamProvider implements MetadataProvider { .substring("https://store.steampowered.com/".length, v.indexOf("?")) .split("/"); + if (!type || !name) return; + companies[name] ??= { pub: false, dev: false }; switch (type) { case "publisher": @@ -546,7 +549,9 @@ export class SteamProvider implements MetadataProvider { let titleMatch = ogTitleRegex.exec(html); titleMatch ??= titleTagRegex.exec(html); - return titleMatch ? this._decodeHtmlEntities(titleMatch[1]) : undefined; + return titleMatch && titleMatch[1] + ? this._decodeHtmlEntities(titleMatch[1]) + : undefined; } private _extractDescription(html: string): string | undefined { @@ -558,7 +563,9 @@ export class SteamProvider implements MetadataProvider { let descMatch = ogDescRegex.exec(html); descMatch ??= nameDescRegex.exec(html); - return descMatch ? this._decodeHtmlEntities(descMatch[1]) : undefined; + return descMatch && descMatch[1] + ? this._decodeHtmlEntities(descMatch[1]) + : undefined; } private _extractImage(html: string): string | undefined { @@ -583,6 +590,7 @@ export class SteamProvider implements MetadataProvider { curatorUrlMatch ??= linkfilterRegex.exec(html); if (!curatorUrlMatch) return undefined; + if (!curatorUrlMatch[1]) return undefined; try { return decodeURIComponent(curatorUrlMatch[1]); @@ -601,11 +609,12 @@ export class SteamProvider implements MetadataProvider { bannerMatch ??= backgroundImageRegex.exec(html); if (!bannerMatch) return undefined; + if (!bannerMatch[1]) return undefined; let bannerUrl = bannerMatch[1].replace(/['"]/g, ""); // Clean up the URL if (bannerUrl.includes("?")) { - bannerUrl = bannerUrl.split("?")[0]; + bannerUrl = bannerUrl.split("?")[0]!; } return bannerUrl; } diff --git a/server/server/internal/objects/fsBackend.ts b/server/server/internal/objects/fsBackend.ts index e6f58ec2..f4ab6320 100644 --- a/server/server/internal/objects/fsBackend.ts +++ b/server/server/internal/objects/fsBackend.ts @@ -123,7 +123,10 @@ export class FsObjectBackend extends ObjectBackend { const metadataRaw = JSON.parse(fs.readFileSync(metadataPath, "utf-8")); const metadata = objectMetadata(metadataRaw); if (metadata instanceof type.errors) { - logger.error("FsObjectBackend#fetchMetadata", metadata.summary); + logger.error( + { summary: metadata.summary }, + "FsObjectBackend#fetchMetadata", + ); return undefined; } await this.metadataCache.set(id, metadata); @@ -198,8 +201,8 @@ export class FsObjectBackend extends ObjectBackend { ); } catch (error) { cleanupLogger.error( + { error }, `[FsObjectBackend#cleanupMetadata]: Failed to remove ${file}`, - error, ); } } diff --git a/server/server/internal/tasks/index.ts b/server/server/internal/tasks/index.ts index c34715b9..56418265 100644 --- a/server/server/internal/tasks/index.ts +++ b/server/server/internal/tasks/index.ts @@ -190,7 +190,7 @@ class TaskHandler { parentTask?.progress ?? ((progress: number) => { if (progress < 0 || progress > 100) { - logger.error("Progress must be between 0 and 100", { progress }); + logger.error({ progress }, "Progress must be between 0 and 100"); return; } const taskEntry = this.taskPool.get(task.id); diff --git a/server/server/internal/tasks/registry/update.ts b/server/server/internal/tasks/registry/update.ts index 452fd19b..245fd436 100644 --- a/server/server/internal/tasks/registry/update.ts +++ b/server/server/internal/tasks/registry/update.ts @@ -49,10 +49,13 @@ export default defineDropTask({ // if response failed somehow if (!response.ok) { - logger.info("Failed to check for update ", { - status: response.status, - body: response.body, - }); + logger.info( + { + status: response.status, + body: response.body, + }, + "Failed to check for update ", + ); throw new Error( `Failed to check for update: ${response.status} ${response.body}`,