1 Commits

Author SHA1 Message Date
b657a20f77 chore(deps): update dependency @types/node to v18.19.71 2025-01-20 01:00:58 +00:00
29 changed files with 989 additions and 1526 deletions

View File

@ -1,34 +1,28 @@
name: docker name: Build and publish the docker image
on: on:
push: push:
branches: branches: ["custom"]
- "main"
paths-ignore:
- "README.md"
- "LICENSE.txt"
- "docker-compose.example.yml"
- "ups.json"
env: env:
REGISTRY: git.ngn.tf REGISTRY: git.ngn.tf
IMAGE: ${{gitea.repository}} IMAGE: ${{gitea.repository}}
jobs: jobs:
docker: build:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v4 uses: "https://github.com/actions/checkout@v4"
- name: Login to container repo - name: Login to container repo
uses: docker/login-action@v1 uses: "https://github.com/docker/login-action@v1"
with: with:
registry: ${{env.REGISTRY}} registry: ${{env.REGISTRY}}
username: ${{gitea.actor}} username: ${{gitea.actor}}
password: ${{secrets.PACKAGES_TOKEN}} password: ${{secrets.PACKAGES_TOKEN}}
- name: Build docker image - name: Build image
run: | run: |
docker build . --tag ${{env.REGISTRY}}/${{env.IMAGE}}:latest docker build . --tag ${{env.REGISTRY}}/${{env.IMAGE}}:latest
docker push ${{env.REGISTRY}}/${{env.IMAGE}}:latest docker push ${{env.REGISTRY}}/${{env.IMAGE}}:latest

View File

@ -1,25 +0,0 @@
name: ups
on:
schedule:
- cron: "@weekly"
jobs:
ups:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Install dependencies
run: |
sudo apt update -y
sudo apt install -y python3 python3-build python3-requests make
- name: Install ups
run: |
git clone https://git.ngn.tf/ngn/ups && cd ups
make && make install
- name: Run ups
run: PATH=~/.local/bin:$PATH ups-check

View File

@ -1,12 +1,20 @@
FROM node:lts-alpine AS deps
WORKDIR /app
COPY package.json pnpm-lock.yaml ./
RUN npm install -g pnpm
RUN pnpm install --frozen-lockfile
FROM node:lts-alpine AS builder FROM node:lts-alpine AS builder
WORKDIR /app WORKDIR /app
COPY . . COPY . .
COPY --from=deps /app/node_modules ./node_modules
ENV NODE_ENV=production ENV NODE_ENV=production
RUN npm install -g pnpm RUN npm install -g pnpm
RUN pnpm install
RUN pnpm build RUN pnpm build
FROM node:lts-alpine AS runner FROM node:lts-alpine AS runner

View File

@ -1,7 +1,5 @@
# libremdb - IMDb frontend # [ngn.tf] | libremdb
![](https://git.ngn.tf/ngn/libremdb/actions/workflows/docker.yml/badge.svg) ![](https://git.ngn.tf/ngn/libremdb/actions/workflows/build.yml/badge.svg)
![](https://git.ngn.tf/ngn/libremdb/actions/workflows/ups.yml/badge.svg)
A fork of the [libremdb](https://github.com/zyachel/libremdb) project, with my A fork of the [libremdb](https://github.com/zyachel/libremdb) project, with my personal changes.
personal changes.

View File

@ -8,7 +8,7 @@ services:
depends_on: depends_on:
- libremdb_redis - libremdb_redis
tmpfs: tmpfs:
- /app/.next/cache/:size=10M,mode=0770,uid=65534,gid=65534,noexec,nosuid,nodev - /opt/app/.next/cache/:size=10M,mode=0770,uid=65534,gid=65534,noexec,nosuid,nodev
security_opt: security_opt:
- no-new-privileges:true - no-new-privileges:true
cap_drop: cap_drop:

View File

@ -9,11 +9,6 @@ const nextConfig = {
destination: '/find', destination: '/find',
permanent: true, permanent: true,
}, },
{
source: '/:langcode(\\w{2})/:slug*',
destination: '/:slug*',
permanent: true,
},
]; ];
}, },
images: { images: {

View File

@ -1,6 +1,6 @@
{ {
"name": "libremdb", "name": "libremdb",
"version": "4.2.0", "version": "4.1.0",
"description": "a free & open source IMDb front-end", "description": "a free & open source IMDb front-end",
"private": true, "private": true,
"type": "module", "type": "module",
@ -26,7 +26,7 @@
"sharp": "^0.33.1" "sharp": "^0.33.1"
}, },
"devDependencies": { "devDependencies": {
"@types/node": "18.7.3", "@types/node": "18.19.71",
"@types/react": "18.0.17", "@types/react": "18.0.17",
"@types/react-dom": "18.0.6", "@types/react-dom": "18.0.6",
"eslint": "8.22.0", "eslint": "8.22.0",

307
pnpm-lock.yaml generated
View File

@ -19,7 +19,7 @@ importers:
version: 5.3.2 version: 5.3.2
next: next:
specifier: 12.2.5 specifier: 12.2.5
version: 12.2.5(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(sass@1.89.2) version: 12.2.5(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(sass@1.62.1)
react: react:
specifier: 18.2.0 specifier: 18.2.0
version: 18.2.0 version: 18.2.0
@ -31,8 +31,8 @@ importers:
version: 0.33.1 version: 0.33.1
devDependencies: devDependencies:
'@types/node': '@types/node':
specifier: 18.7.3 specifier: 18.19.71
version: 18.7.3 version: 18.19.71
'@types/react': '@types/react':
specifier: 18.0.17 specifier: 18.0.17
version: 18.0.17 version: 18.0.17
@ -47,7 +47,7 @@ importers:
version: 12.2.5(eslint@8.22.0)(typescript@4.7.4) version: 12.2.5(eslint@8.22.0)(typescript@4.7.4)
sass: sass:
specifier: ^1.62.1 specifier: ^1.62.1
version: 1.89.2 version: 1.62.1
typescript: typescript:
specifier: 4.7.4 specifier: 4.7.4
version: 4.7.4 version: 4.7.4
@ -289,88 +289,6 @@ packages:
resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==}
engines: {node: '>= 8'} engines: {node: '>= 8'}
'@parcel/watcher-android-arm64@2.5.1':
resolution: {integrity: sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA==}
engines: {node: '>= 10.0.0'}
cpu: [arm64]
os: [android]
'@parcel/watcher-darwin-arm64@2.5.1':
resolution: {integrity: sha512-eAzPv5osDmZyBhou8PoF4i6RQXAfeKL9tjb3QzYuccXFMQU0ruIc/POh30ePnaOyD1UXdlKguHBmsTs53tVoPw==}
engines: {node: '>= 10.0.0'}
cpu: [arm64]
os: [darwin]
'@parcel/watcher-darwin-x64@2.5.1':
resolution: {integrity: sha512-1ZXDthrnNmwv10A0/3AJNZ9JGlzrF82i3gNQcWOzd7nJ8aj+ILyW1MTxVk35Db0u91oD5Nlk9MBiujMlwmeXZg==}
engines: {node: '>= 10.0.0'}
cpu: [x64]
os: [darwin]
'@parcel/watcher-freebsd-x64@2.5.1':
resolution: {integrity: sha512-SI4eljM7Flp9yPuKi8W0ird8TI/JK6CSxju3NojVI6BjHsTyK7zxA9urjVjEKJ5MBYC+bLmMcbAWlZ+rFkLpJQ==}
engines: {node: '>= 10.0.0'}
cpu: [x64]
os: [freebsd]
'@parcel/watcher-linux-arm-glibc@2.5.1':
resolution: {integrity: sha512-RCdZlEyTs8geyBkkcnPWvtXLY44BCeZKmGYRtSgtwwnHR4dxfHRG3gR99XdMEdQ7KeiDdasJwwvNSF5jKtDwdA==}
engines: {node: '>= 10.0.0'}
cpu: [arm]
os: [linux]
'@parcel/watcher-linux-arm-musl@2.5.1':
resolution: {integrity: sha512-6E+m/Mm1t1yhB8X412stiKFG3XykmgdIOqhjWj+VL8oHkKABfu/gjFj8DvLrYVHSBNC+/u5PeNrujiSQ1zwd1Q==}
engines: {node: '>= 10.0.0'}
cpu: [arm]
os: [linux]
'@parcel/watcher-linux-arm64-glibc@2.5.1':
resolution: {integrity: sha512-LrGp+f02yU3BN9A+DGuY3v3bmnFUggAITBGriZHUREfNEzZh/GO06FF5u2kx8x+GBEUYfyTGamol4j3m9ANe8w==}
engines: {node: '>= 10.0.0'}
cpu: [arm64]
os: [linux]
'@parcel/watcher-linux-arm64-musl@2.5.1':
resolution: {integrity: sha512-cFOjABi92pMYRXS7AcQv9/M1YuKRw8SZniCDw0ssQb/noPkRzA+HBDkwmyOJYp5wXcsTrhxO0zq1U11cK9jsFg==}
engines: {node: '>= 10.0.0'}
cpu: [arm64]
os: [linux]
'@parcel/watcher-linux-x64-glibc@2.5.1':
resolution: {integrity: sha512-GcESn8NZySmfwlTsIur+49yDqSny2IhPeZfXunQi48DMugKeZ7uy1FX83pO0X22sHntJ4Ub+9k34XQCX+oHt2A==}
engines: {node: '>= 10.0.0'}
cpu: [x64]
os: [linux]
'@parcel/watcher-linux-x64-musl@2.5.1':
resolution: {integrity: sha512-n0E2EQbatQ3bXhcH2D1XIAANAcTZkQICBPVaxMeaCVBtOpBZpWJuf7LwyWPSBDITb7In8mqQgJ7gH8CILCURXg==}
engines: {node: '>= 10.0.0'}
cpu: [x64]
os: [linux]
'@parcel/watcher-win32-arm64@2.5.1':
resolution: {integrity: sha512-RFzklRvmc3PkjKjry3hLF9wD7ppR4AKcWNzH7kXR7GUe0Igb3Nz8fyPwtZCSquGrhU5HhUNDr/mKBqj7tqA2Vw==}
engines: {node: '>= 10.0.0'}
cpu: [arm64]
os: [win32]
'@parcel/watcher-win32-ia32@2.5.1':
resolution: {integrity: sha512-c2KkcVN+NJmuA7CGlaGD1qJh1cLfDnQsHjE89E60vUEMlqduHGCdCLJCID5geFVM0dOtA3ZiIO8BoEQmzQVfpQ==}
engines: {node: '>= 10.0.0'}
cpu: [ia32]
os: [win32]
'@parcel/watcher-win32-x64@2.5.1':
resolution: {integrity: sha512-9lHBdJITeNR++EvSQVUcaZoWupyHfXe1jZvGZ06O/5MflPcuPLtEphScIBL+AiCWBO46tDSHzWyD0uDmmZqsgA==}
engines: {node: '>= 10.0.0'}
cpu: [x64]
os: [win32]
'@parcel/watcher@2.5.1':
resolution: {integrity: sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg==}
engines: {node: '>= 10.0.0'}
'@rushstack/eslint-patch@1.2.0': '@rushstack/eslint-patch@1.2.0':
resolution: {integrity: sha512-sXo/qW2/pAcmT43VoRKOJbDOfV3cYpq3szSVfIThQXNt+E4DfKj361vaAt3c88U5tPUxzEswam7GW48PJqtKAg==} resolution: {integrity: sha512-sXo/qW2/pAcmT43VoRKOJbDOfV3cYpq3szSVfIThQXNt+E4DfKj361vaAt3c88U5tPUxzEswam7GW48PJqtKAg==}
@ -380,8 +298,8 @@ packages:
'@types/json5@0.0.29': '@types/json5@0.0.29':
resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==}
'@types/node@18.7.3': '@types/node@18.19.71':
resolution: {integrity: sha512-LJgzOEwWuMTBxHzgBR/fhhBOWrvBjvO+zPteUgbbuQi80rYIZHrk1mNbRUqPZqSLP2H7Rwt1EFLL/tNLD1Xx/w==} resolution: {integrity: sha512-evXpcgtZm8FY4jqBSN8+DmOTcVkkvTmAayeo4Wf3m1xAruyVGzGuDh/Fb/WWX2yLItUiho42ozyJjB0dw//Tkw==}
'@types/prop-types@15.7.5': '@types/prop-types@15.7.5':
resolution: {integrity: sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==} resolution: {integrity: sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==}
@ -447,6 +365,10 @@ packages:
resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
engines: {node: '>=8'} engines: {node: '>=8'}
anymatch@3.1.3:
resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==}
engines: {node: '>= 8'}
argparse@2.0.1: argparse@2.0.1:
resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==}
@ -498,6 +420,10 @@ packages:
balanced-match@1.0.2: balanced-match@1.0.2:
resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
binary-extensions@2.2.0:
resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==}
engines: {node: '>=8'}
boolbase@1.0.0: boolbase@1.0.0:
resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==}
@ -508,10 +434,6 @@ packages:
resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==}
engines: {node: '>=8'} engines: {node: '>=8'}
braces@3.0.3:
resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==}
engines: {node: '>=8'}
call-bind@1.0.2: call-bind@1.0.2:
resolution: {integrity: sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==} resolution: {integrity: sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==}
@ -533,9 +455,9 @@ packages:
resolution: {integrity: sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q==} resolution: {integrity: sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q==}
engines: {node: '>= 6'} engines: {node: '>= 6'}
chokidar@4.0.3: chokidar@3.5.3:
resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==} resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==}
engines: {node: '>= 14.16.0'} engines: {node: '>= 8.10.0'}
cluster-key-slot@1.1.2: cluster-key-slot@1.1.2:
resolution: {integrity: sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==} resolution: {integrity: sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==}
@ -614,11 +536,6 @@ packages:
resolution: {integrity: sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==} resolution: {integrity: sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==}
engines: {node: '>=0.10'} engines: {node: '>=0.10'}
detect-libc@1.0.3:
resolution: {integrity: sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==}
engines: {node: '>=0.10'}
hasBin: true
detect-libc@2.0.2: detect-libc@2.0.2:
resolution: {integrity: sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==} resolution: {integrity: sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==}
engines: {node: '>=8'} engines: {node: '>=8'}
@ -813,10 +730,6 @@ packages:
resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==}
engines: {node: '>=8'} engines: {node: '>=8'}
fill-range@7.1.1:
resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==}
engines: {node: '>=8'}
find-up@5.0.0: find-up@5.0.0:
resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==}
engines: {node: '>=10'} engines: {node: '>=10'}
@ -847,6 +760,11 @@ packages:
fs.realpath@1.0.0: fs.realpath@1.0.0:
resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==}
fsevents@2.3.3:
resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
os: [darwin]
function-bind@1.1.1: function-bind@1.1.1:
resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==} resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==}
@ -934,8 +852,8 @@ packages:
resolution: {integrity: sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==} resolution: {integrity: sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==}
engines: {node: '>= 4'} engines: {node: '>= 4'}
immutable@5.1.3: immutable@4.3.0:
resolution: {integrity: sha512-+chQdDfvscSF1SJqv2gn4SRO2ZyS3xL3r7IW/wWEEzrzLisnOlKiQu5ytC/BVNcS15C39WT2Hg/bjKjDMcu+zg==} resolution: {integrity: sha512-0AOCmOip+xgJwEVTQj1EfiDDOkPmuyllDuTuEX+DDXUgapLAsBIfkg3sxCYyCEA8mQqZrrxPUGjcOQ2JS3WLkg==}
import-fresh@3.3.0: import-fresh@3.3.0:
resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==}
@ -973,6 +891,10 @@ packages:
is-bigint@1.0.4: is-bigint@1.0.4:
resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==} resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==}
is-binary-path@2.1.0:
resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==}
engines: {node: '>=8'}
is-boolean-object@1.1.2: is-boolean-object@1.1.2:
resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==} resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==}
engines: {node: '>= 0.4'} engines: {node: '>= 0.4'}
@ -1108,10 +1030,6 @@ packages:
resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==}
engines: {node: '>=8.6'} engines: {node: '>=8.6'}
micromatch@4.0.8:
resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==}
engines: {node: '>=8.6'}
mime-db@1.52.0: mime-db@1.52.0:
resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==}
engines: {node: '>= 0.6'} engines: {node: '>= 0.6'}
@ -1158,8 +1076,9 @@ packages:
sass: sass:
optional: true optional: true
node-addon-api@7.1.1: normalize-path@3.0.0:
resolution: {integrity: sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==} resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==}
engines: {node: '>=0.10.0'}
nth-check@2.1.1: nth-check@2.1.1:
resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==}
@ -1279,9 +1198,9 @@ packages:
resolution: {integrity: sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==} resolution: {integrity: sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==}
engines: {node: '>=0.10.0'} engines: {node: '>=0.10.0'}
readdirp@4.1.2: readdirp@3.6.0:
resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==} resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==}
engines: {node: '>= 14.18.0'} engines: {node: '>=8.10.0'}
redis-errors@1.2.0: redis-errors@1.2.0:
resolution: {integrity: sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==} resolution: {integrity: sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==}
@ -1329,8 +1248,8 @@ packages:
safe-regex-test@1.0.0: safe-regex-test@1.0.0:
resolution: {integrity: sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==} resolution: {integrity: sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==}
sass@1.89.2: sass@1.62.1:
resolution: {integrity: sha512-xCmtksBKd/jdJ9Bt9p7nPKiuqrlBMBuuGkQlkhZjjQk3Ty48lv93k5Dq6OPkKt4XwxDJ7tvlfrTa1MPA9bf+QA==} resolution: {integrity: sha512-NHpxIzN29MXvWiuswfc1W3I0N8SXBd8UR26WntmDlRYf0bSADnwnOjsyMZ3lMezSlArD33Vs3YFhp7dWvL770A==}
engines: {node: '>=14.0.0'} engines: {node: '>=14.0.0'}
hasBin: true hasBin: true
@ -1373,8 +1292,8 @@ packages:
resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==}
engines: {node: '>=8'} engines: {node: '>=8'}
source-map-js@1.2.1: source-map-js@1.0.2:
resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==}
engines: {node: '>=0.10.0'} engines: {node: '>=0.10.0'}
standard-as-callback@2.1.0: standard-as-callback@2.1.0:
@ -1446,6 +1365,9 @@ packages:
tslib@2.5.0: tslib@2.5.0:
resolution: {integrity: sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==} resolution: {integrity: sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==}
tslib@2.6.2:
resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==}
tsutils@3.21.0: tsutils@3.21.0:
resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==} resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==}
engines: {node: '>= 6'} engines: {node: '>= 6'}
@ -1471,6 +1393,9 @@ packages:
unbox-primitive@1.0.2: unbox-primitive@1.0.2:
resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==}
undici-types@5.26.5:
resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==}
uri-js@4.4.1: uri-js@4.4.1:
resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==}
@ -1519,7 +1444,7 @@ snapshots:
'@emnapi/runtime@0.44.0': '@emnapi/runtime@0.44.0':
dependencies: dependencies:
tslib: 2.5.0 tslib: 2.6.2
optional: true optional: true
'@eslint/eslintrc@1.4.1': '@eslint/eslintrc@1.4.1':
@ -1682,67 +1607,6 @@ snapshots:
'@nodelib/fs.scandir': 2.1.5 '@nodelib/fs.scandir': 2.1.5
fastq: 1.15.0 fastq: 1.15.0
'@parcel/watcher-android-arm64@2.5.1':
optional: true
'@parcel/watcher-darwin-arm64@2.5.1':
optional: true
'@parcel/watcher-darwin-x64@2.5.1':
optional: true
'@parcel/watcher-freebsd-x64@2.5.1':
optional: true
'@parcel/watcher-linux-arm-glibc@2.5.1':
optional: true
'@parcel/watcher-linux-arm-musl@2.5.1':
optional: true
'@parcel/watcher-linux-arm64-glibc@2.5.1':
optional: true
'@parcel/watcher-linux-arm64-musl@2.5.1':
optional: true
'@parcel/watcher-linux-x64-glibc@2.5.1':
optional: true
'@parcel/watcher-linux-x64-musl@2.5.1':
optional: true
'@parcel/watcher-win32-arm64@2.5.1':
optional: true
'@parcel/watcher-win32-ia32@2.5.1':
optional: true
'@parcel/watcher-win32-x64@2.5.1':
optional: true
'@parcel/watcher@2.5.1':
dependencies:
detect-libc: 1.0.3
is-glob: 4.0.3
micromatch: 4.0.8
node-addon-api: 7.1.1
optionalDependencies:
'@parcel/watcher-android-arm64': 2.5.1
'@parcel/watcher-darwin-arm64': 2.5.1
'@parcel/watcher-darwin-x64': 2.5.1
'@parcel/watcher-freebsd-x64': 2.5.1
'@parcel/watcher-linux-arm-glibc': 2.5.1
'@parcel/watcher-linux-arm-musl': 2.5.1
'@parcel/watcher-linux-arm64-glibc': 2.5.1
'@parcel/watcher-linux-arm64-musl': 2.5.1
'@parcel/watcher-linux-x64-glibc': 2.5.1
'@parcel/watcher-linux-x64-musl': 2.5.1
'@parcel/watcher-win32-arm64': 2.5.1
'@parcel/watcher-win32-ia32': 2.5.1
'@parcel/watcher-win32-x64': 2.5.1
optional: true
'@rushstack/eslint-patch@1.2.0': {} '@rushstack/eslint-patch@1.2.0': {}
'@swc/helpers@0.4.3': '@swc/helpers@0.4.3':
@ -1751,7 +1615,9 @@ snapshots:
'@types/json5@0.0.29': {} '@types/json5@0.0.29': {}
'@types/node@18.7.3': {} '@types/node@18.19.71':
dependencies:
undici-types: 5.26.5
'@types/prop-types@15.7.5': {} '@types/prop-types@15.7.5': {}
@ -1824,6 +1690,11 @@ snapshots:
dependencies: dependencies:
color-convert: 2.0.1 color-convert: 2.0.1
anymatch@3.1.3:
dependencies:
normalize-path: 3.0.0
picomatch: 2.3.1
argparse@2.0.1: {} argparse@2.0.1: {}
aria-query@5.1.3: aria-query@5.1.3:
@ -1888,6 +1759,8 @@ snapshots:
balanced-match@1.0.2: {} balanced-match@1.0.2: {}
binary-extensions@2.2.0: {}
boolbase@1.0.0: {} boolbase@1.0.0: {}
brace-expansion@1.1.11: brace-expansion@1.1.11:
@ -1899,11 +1772,6 @@ snapshots:
dependencies: dependencies:
fill-range: 7.0.1 fill-range: 7.0.1
braces@3.0.3:
dependencies:
fill-range: 7.1.1
optional: true
call-bind@1.0.2: call-bind@1.0.2:
dependencies: dependencies:
function-bind: 1.1.1 function-bind: 1.1.1
@ -1937,9 +1805,17 @@ snapshots:
parse5: 7.1.2 parse5: 7.1.2
parse5-htmlparser2-tree-adapter: 7.0.0 parse5-htmlparser2-tree-adapter: 7.0.0
chokidar@4.0.3: chokidar@3.5.3:
dependencies: dependencies:
readdirp: 4.1.2 anymatch: 3.1.3
braces: 3.0.2
glob-parent: 5.1.2
is-binary-path: 2.1.0
is-glob: 4.0.3
normalize-path: 3.0.0
readdirp: 3.6.0
optionalDependencies:
fsevents: 2.3.3
cluster-key-slot@1.1.2: {} cluster-key-slot@1.1.2: {}
@ -2024,9 +1900,6 @@ snapshots:
denque@2.1.0: {} denque@2.1.0: {}
detect-libc@1.0.3:
optional: true
detect-libc@2.0.2: {} detect-libc@2.0.2: {}
dir-glob@3.0.1: dir-glob@3.0.1:
@ -2349,11 +2222,6 @@ snapshots:
dependencies: dependencies:
to-regex-range: 5.0.1 to-regex-range: 5.0.1
fill-range@7.1.1:
dependencies:
to-regex-range: 5.0.1
optional: true
find-up@5.0.0: find-up@5.0.0:
dependencies: dependencies:
locate-path: 6.0.0 locate-path: 6.0.0
@ -2380,6 +2248,9 @@ snapshots:
fs.realpath@1.0.0: {} fs.realpath@1.0.0: {}
fsevents@2.3.3:
optional: true
function-bind@1.1.1: {} function-bind@1.1.1: {}
function.prototype.name@1.1.5: function.prototype.name@1.1.5:
@ -2482,7 +2353,7 @@ snapshots:
ignore@5.2.4: {} ignore@5.2.4: {}
immutable@5.1.3: {} immutable@4.3.0: {}
import-fresh@3.3.0: import-fresh@3.3.0:
dependencies: dependencies:
@ -2535,6 +2406,10 @@ snapshots:
dependencies: dependencies:
has-bigints: 1.0.2 has-bigints: 1.0.2
is-binary-path@2.1.0:
dependencies:
binary-extensions: 2.2.0
is-boolean-object@1.1.2: is-boolean-object@1.1.2:
dependencies: dependencies:
call-bind: 1.0.2 call-bind: 1.0.2
@ -2663,12 +2538,6 @@ snapshots:
braces: 3.0.2 braces: 3.0.2
picomatch: 2.3.1 picomatch: 2.3.1
micromatch@4.0.8:
dependencies:
braces: 3.0.3
picomatch: 2.3.1
optional: true
mime-db@1.52.0: {} mime-db@1.52.0: {}
mime-types@2.1.35: mime-types@2.1.35:
@ -2689,7 +2558,7 @@ snapshots:
natural-compare@1.4.0: {} natural-compare@1.4.0: {}
next@12.2.5(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(sass@1.89.2): next@12.2.5(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(sass@1.62.1):
dependencies: dependencies:
'@next/env': 12.2.5 '@next/env': 12.2.5
'@swc/helpers': 0.4.3 '@swc/helpers': 0.4.3
@ -2713,13 +2582,12 @@ snapshots:
'@next/swc-win32-arm64-msvc': 12.2.5 '@next/swc-win32-arm64-msvc': 12.2.5
'@next/swc-win32-ia32-msvc': 12.2.5 '@next/swc-win32-ia32-msvc': 12.2.5
'@next/swc-win32-x64-msvc': 12.2.5 '@next/swc-win32-x64-msvc': 12.2.5
sass: 1.89.2 sass: 1.62.1
transitivePeerDependencies: transitivePeerDependencies:
- '@babel/core' - '@babel/core'
- babel-plugin-macros - babel-plugin-macros
node-addon-api@7.1.1: normalize-path@3.0.0: {}
optional: true
nth-check@2.1.1: nth-check@2.1.1:
dependencies: dependencies:
@ -2818,7 +2686,7 @@ snapshots:
dependencies: dependencies:
nanoid: 3.3.6 nanoid: 3.3.6
picocolors: 1.0.0 picocolors: 1.0.0
source-map-js: 1.2.1 source-map-js: 1.0.2
prelude-ls@1.2.1: {} prelude-ls@1.2.1: {}
@ -2844,7 +2712,9 @@ snapshots:
dependencies: dependencies:
loose-envify: 1.4.0 loose-envify: 1.4.0
readdirp@4.1.2: {} readdirp@3.6.0:
dependencies:
picomatch: 2.3.1
redis-errors@1.2.0: {} redis-errors@1.2.0: {}
@ -2892,13 +2762,11 @@ snapshots:
get-intrinsic: 1.2.0 get-intrinsic: 1.2.0
is-regex: 1.1.4 is-regex: 1.1.4
sass@1.89.2: sass@1.62.1:
dependencies: dependencies:
chokidar: 4.0.3 chokidar: 3.5.3
immutable: 5.1.3 immutable: 4.3.0
source-map-js: 1.2.1 source-map-js: 1.0.2
optionalDependencies:
'@parcel/watcher': 2.5.1
scheduler@0.23.0: scheduler@0.23.0:
dependencies: dependencies:
@ -2958,7 +2826,7 @@ snapshots:
slash@3.0.0: {} slash@3.0.0: {}
source-map-js@1.2.1: {} source-map-js@1.0.2: {}
standard-as-callback@2.1.0: {} standard-as-callback@2.1.0: {}
@ -3030,6 +2898,9 @@ snapshots:
tslib@2.5.0: {} tslib@2.5.0: {}
tslib@2.6.2:
optional: true
tsutils@3.21.0(typescript@4.7.4): tsutils@3.21.0(typescript@4.7.4):
dependencies: dependencies:
tslib: 1.14.1 tslib: 1.14.1
@ -3056,6 +2927,8 @@ snapshots:
has-symbols: 1.0.3 has-symbols: 1.0.3
which-boxed-primitive: 1.0.2 which-boxed-primitive: 1.0.2
undici-types@5.26.5: {}
uri-js@4.4.1: uri-js@4.4.1:
dependencies: dependencies:
punycode: 2.3.0 punycode: 2.3.0

View File

@ -1,2 +0,0 @@
onlyBuiltDependencies:
- sharp

View File

@ -1,7 +0,0 @@
<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/">
<ShortName>libremdb</ShortName>
<Description>Search libremdb</Description>
<InputEncoding>UTF-8</InputEncoding>
<Image width="16" height="16" type="image/x-icon">https://libremdb.iket.me/favicon.ico</Image>
<Url type="text/html" method="get" template="https://libremdb.iket.me/find?q={searchTerms}"/>
</OpenSearchDescription>

View File

@ -11,7 +11,6 @@ type Props = {
message: string; message: string;
statusCode?: number; statusCode?: number;
originalPath?: string; originalPath?: string;
stack?: string;
/** props specific to error boundary. */ /** props specific to error boundary. */
misc?: { misc?: {
subtext: string; subtext: string;
@ -20,9 +19,7 @@ type Props = {
}; };
}; };
const isDev = process.env.NODE_ENV === 'development'; const ErrorInfo = ({ message, statusCode, misc, originalPath }: Props) => {
const ErrorInfo = ({ message, statusCode, misc, originalPath, stack }: Props) => {
const title = statusCode ? `${message} (${statusCode})` : message; const title = statusCode ? `${message} (${statusCode})` : message;
return ( return (
<> <>
@ -42,11 +39,6 @@ const ErrorInfo = ({ message, statusCode, misc, originalPath, stack }: Props) =>
<use href='/svg/sadgnu.svg#sad-gnu'></use> <use href='/svg/sadgnu.svg#sad-gnu'></use>
</svg> </svg>
<h1 className={`heading heading__primary ${styles.heading}`}>{title}</h1> <h1 className={`heading heading__primary ${styles.heading}`}>{title}</h1>
{Boolean(stack && isDev) && (
<pre className={styles.stack}>
<code>{stack}</code>
</pre>
)}
{misc ? ( {misc ? (
<> <>
<p>{misc.subtext}</p> <p>{misc.subtext}</p>
@ -72,13 +64,6 @@ const ErrorInfo = ({ message, statusCode, misc, originalPath, stack }: Props) =>
. .
</p> </p>
)} )}
<p>
If you think this shouldn't happen,{' '}
<Link href='/contact'>
<a className='link'>let it be known</a>
</Link>
.
</p>
</Layout> </Layout>
</> </>
); );

View File

@ -14,41 +14,32 @@ type Props = {
const Media = ({ className, media }: Props) => { const Media = ({ className, media }: Props) => {
return ( return (
<div className={`${className} ${styles.media}`}> <div className={`${className} ${styles.media}`}>
{(media.trailers?.length || !!media.videos.total) && ( {(media.trailer || !!media.videos.total) && (
<section className={styles.videos}> <section className={styles.videos}>
<h2 className='heading heading__secondary'>Videos</h2> <h2 className='heading heading__secondary'>Videos</h2>
<div className={styles.videos__container}> <div className={styles.videos__container}>
{media.trailers?.map(trailer => ( {media.trailer && (
<div className={styles.trailer} key={trailer.id}> <div className={styles.trailer}>
<video <video
aria-label={trailer.caption ?? 'trailer video'} aria-label='trailer video'
controls controls
playsInline playsInline
poster={getProxiedIMDbImgUrl(modifyIMDbImg(trailer.thumbnail))} poster={getProxiedIMDbImgUrl(modifyIMDbImg(media.trailer.thumbnail))}
className={styles.trailer__video} className={styles.trailer__video}
preload='none' preload='none'
muted
> >
{trailer.urls.map(source => ( {media.trailer.urls.map(source => (
<source <source
key={source.url} key={source.url}
type='video/mp4' type={source.mimeType ?? undefined}
src={getProxiedIMDbImgUrl(source.url)} src={getProxiedIMDbImgUrl(source.url)}
media={source.resolution !== 'SD' ? '(min-width: 450px)' : undefined}
data-res={source.resolution} data-res={source.resolution}
/> />
))} ))}
<p>
{trailer.caption}:{' '}
<Link href={getProxiedIMDbImgUrl(trailer.urls[0]?.url)}>
<a className='link'>link</a>
</Link>
</p>
</video> </video>
</div> </div>
))} )}
{!!media.videos.total && {!!media.videos.total &&
media.videos.videos.map(video => ( media.videos.videos.map(video => (

View File

@ -36,13 +36,6 @@ const Meta = ({
<meta property='og:locale' content='en_US' /> <meta property='og:locale' content='en_US' />
<meta property='og:type' content='video.movie' /> <meta property='og:type' content='video.movie' />
<meta property='og:image' content={url.toString()} /> <meta property='og:image' content={url.toString()} />
<link
rel='search'
type='application/opensearchdescription+xml'
href='/opensearch.xml'
title='libremdb'
></link>
</Head> </Head>
); );
}; };

View File

@ -9,10 +9,6 @@ type Props = {
const DidYouKnow = ({ data }: Props) => ( const DidYouKnow = ({ data }: Props) => (
<section className={styles.container}> <section className={styles.container}>
<h2 className='heading heading__secondary'>Did you know</h2> <h2 className='heading heading__secondary'>Did you know</h2>
{isEmpty(data) ? (
<p>Nothing interesting to show.</p>
) : (
<>
{!!data.trivia?.total && ( {!!data.trivia?.total && (
<section> <section>
<h3 className='heading heading__tertiary'>Trivia</h3> <h3 className='heading heading__tertiary'>Trivia</h3>
@ -49,14 +45,7 @@ const DidYouKnow = ({ data }: Props) => (
</p> </p>
</section> </section>
)} )}
</>
)}
</section> </section>
); );
export default DidYouKnow; export default DidYouKnow;
const isEmpty = (data: Props['data']) =>
Boolean(
!data.nicknames.length && !data.quotes && !data.salary && !data.trademark && !data.trivia
);

View File

@ -86,21 +86,6 @@ const Basic = ({ data, className }: Props) => {
))} ))}
</p> </p>
)} )}
{!!data.interests.length && (
<p className={styles.genres}>
<span className={styles.genres__heading}>Interests: </span>
{data.interests.map((interest, i) => (
<Fragment key={interest.id}>
{i > 0 && ', '}
<Link href={`/interest/${interest.id}`}>
<a className={styles.link}>{interest.text}</a>
</Link>
</Fragment>
))}
</p>
)}
<p className={styles.overview}> <p className={styles.overview}>
<span className={styles.overview__heading}>Plot: </span> <span className={styles.overview__heading}>Plot: </span>
<span className={styles.overview__text}>{data.plot || '-'}</span> <span className={styles.overview__text}>{data.plot || '-'}</span>

View File

@ -7,13 +7,7 @@ type Props = {
}; };
const DidYouKnow = ({ data }: Props) => { const DidYouKnow = ({ data }: Props) => {
if (!Object.keys(data).length) if (!Object.keys(data).length) return <></>;
return (
<section className={styles.didYouKnow}>
<h2 className='heading heading__secondary'>Did you know</h2>
<p>Nothing interesting to show.</p>
</section>
);
return ( return (
<section className={styles.didYouKnow}> <section className={styles.didYouKnow}>
<h2 className='heading heading__secondary'>Did you know</h2> <h2 className='heading heading__secondary'>Did you know</h2>

View File

@ -1,127 +1,82 @@
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';
import Link from 'next/link'; import Link from 'next/link';
import type { Reviews as TReviews } from 'src/interfaces/shared/title'; import { Reviews } from 'src/interfaces/shared/title';
import { formatNumber } from 'src/utils/helpers'; import { formatNumber } from 'src/utils/helpers';
import styles from 'src/styles/modules/components/title/reviews.module.scss'; import styles from 'src/styles/modules/components/title/reviews.module.scss';
type Props = { type Props = {
reviews: TReviews; reviews: Reviews;
}; };
const Reviews = ({ reviews }: Props) => { const Reviews = ({ reviews }: Props) => {
return (
<section className={styles.reviews}>
<h2 className='heading heading__secondary'>Reviews</h2>
<RatingsDistribution ratings={reviews.ratingsDistribution} />
<section className={styles.userReviews}>
<h3 className='heading heading__tertiary'>User Reviews</h3>
{reviews.featuredReviews ? (
<ul className={styles.userReviews__list} role='list'>
{reviews.featuredReviews.map(featuredReview => (
<li key={featuredReview.id}>
<details className={styles.review}>
<summary className={styles.review__summary}>
<strong>{featuredReview.review.summary}</strong>
</summary>
<div
className={styles.review__text}
dangerouslySetInnerHTML={{
__html: featuredReview.review.html,
}}
></div>
<footer className={styles.review__metadata}>
<p>
{featuredReview.rating && <span>Rated {featuredReview.rating}/10</span>}
<span>
{' '}
by{' '}
<Link href={`/user/${featuredReview.reviewer.id}`}>
<a className='link'>{featuredReview.reviewer.name}</a>
</Link>
</span>
</p>
</footer>
</details>
</li>
))}
</ul>
) : (
<p>No reviews yet.</p>
)}
</section>
{reviews.ai?.summary && (
<details className={styles.reviewAi}>
<summary className='heading heading__tertiary'>AI Summary</summary>
<p dangerouslySetInnerHTML={{ __html: reviews.ai.summary }} />
<ul>
{reviews.ai.themes.map(theme => (
<li key={theme.id}>{theme.text}</li>
))}
</ul>
</details>
)}
<ReviewStats reviews={reviews} />
</section>
);
};
export default Reviews;
const RatingsDistribution = ({ ratings }: { ratings: Props['reviews']['ratingsDistribution'] }) => {
const maxRating = Math.max(...ratings.map(r => r.votes));
return (
<div className={styles.ratingsDistribution}>
<h3 className='heading heading__tertiary'>Ratings Distribution</h3>
{ratings.length ? (
<ul>
{ratings.map(rating => (
<li
key={rating.rating}
style={
{
'--bar-height': `${((rating.votes / maxRating) * 100).toFixed(2)}%`,
} as React.CSSProperties
}
>
<span>
{rating.rating} <span>({formatNumber(rating.votes)})</span>
</span>
</li>
))}
</ul>
) : (
<p>No ratings yet.</p>
)}
</div>
);
};
const ReviewStats = ({ reviews }: { reviews: Props['reviews'] }) => {
const router = useRouter(); const router = useRouter();
const { titleId } = router.query; const { titleId } = router.query;
return ( return (
<div className={styles.reviewStats}> <section className={styles.reviews}>
<h2 className="heading heading__secondary">Reviews</h2>
{reviews.featuredReview && (
<article className={styles.reviews__reviewContainer}>
<details className={styles.review}>
<summary className={styles.review__summary}>
<strong>{reviews.featuredReview.review.summary}</strong>
</summary>
<div
className={styles.review__text}
dangerouslySetInnerHTML={{
__html: reviews.featuredReview.review.html,
}}
></div>
</details>
<footer className={styles.review__metadata}>
<p>
{reviews.featuredReview.rating && (
<span>Rated {reviews.featuredReview.rating}/10</span>
)}
<span>
{' '}
by{' '}
<Link href={`/user/${reviews.featuredReview.reviewer.id}`}>
<a className="link">{reviews.featuredReview.reviewer.name}</a>
</Link>
</span>
<span> on {reviews.featuredReview.date}.</span>
</p>
<p>
<span>
{formatNumber(reviews.featuredReview.votes.up)} upvotes
</span>
<span>
, {formatNumber(reviews.featuredReview.votes.down)} downvotes
</span>
</p>
</footer>
</article>
)}
<div className={styles.reviews__stats}>
<p> <p>
<Link href={`/title/${titleId}/reviews`}> <Link href={`/title/${titleId}/reviews`}>
<a className='link'>{formatNumber(reviews.numUserReviews)} User reviews</a> <a className="link">
{formatNumber(reviews.numUserReviews)} User reviews
</a>
</Link> </Link>
</p> </p>
<p> <p>
<Link href={`/title/${titleId}/externalreviews`}> <Link href={`/title/${titleId}/externalreviews`}>
<a className='link'>{formatNumber(reviews.numCriticReviews)} Critic reviews</a> <a className="link">
{formatNumber(reviews.numCriticReviews)} Critic reviews
</a>
</Link> </Link>
</p> </p>
<p> <p>
<Link href={`/title/${titleId}/criticreviews`}> <Link href={`/title/${titleId}/criticreviews`}>
<a className='link'> {reviews.metacriticScore} Metascore</a> <a className="link"> {reviews.metacriticScore} Metascore</a>
</Link> </Link>
</p> </p>
</div> </div>
</section>
); );
}; };
export default Reviews;

View File

@ -143,7 +143,7 @@ export default interface Name {
value: string; value: string;
language: string; language: string;
}; };
videoMimeType?: string; mimeType?: string;
url: string; url: string;
}>; }>;
recommendedTimedTextTrack?: { recommendedTimedTextTrack?: {

File diff suppressed because it is too large Load Diff

View File

@ -1,3 +1,3 @@
import { AppError as AppErrorClass } from 'src/utils/helpers'; import { AppError as AppErrorClass } from 'src/utils/helpers';
export type AppError = Pick<InstanceType<typeof AppErrorClass>, 'message' | 'statusCode' | 'stack'>; export type AppError = Omit<InstanceType<typeof AppErrorClass>, 'name'>;

View File

@ -67,13 +67,13 @@ export const getServerSideProps: GetServerSideProps<Data, FindQueryParams> = asy
props: { data: { title: query, results: res }, error: null, originalPath }, props: { data: { title: query, results: res }, error: null, originalPath },
}; };
} catch (error) { } catch (error) {
const err = getErrorProperties(error); const { message, statusCode } = getErrorProperties(error);
ctx.res.statusCode = err.statusCode; ctx.res.statusCode = statusCode;
ctx.res.statusMessage = err.message; ctx.res.statusMessage = message;
return { return {
props: { props: {
error: { message: err.message, statusCode: err.statusCode, stack: err.format() }, error: { message, statusCode },
data: { title: query, results: null }, data: { title: query, results: null },
originalPath, originalPath,
}, },

View File

@ -55,17 +55,11 @@ export const getServerSideProps: GetServerSideProps<Data, Params> = async ctx =>
return { props: { data, error: null, originalPath } }; return { props: { data, error: null, originalPath } };
} catch (error) { } catch (error) {
const err = getErrorProperties(error); const { message, statusCode } = getErrorProperties(error);
ctx.res.statusCode = err.statusCode; ctx.res.statusCode = statusCode;
ctx.res.statusMessage = err.message; ctx.res.statusMessage = message;
return { return { props: { error: { message, statusCode }, data: null, originalPath } };
props: {
error: { message: err.message, statusCode: err.statusCode, stack: err.format() },
data: null,
originalPath,
},
};
} }
}; };

View File

@ -5,7 +5,7 @@ import ErrorInfo from 'src/components/error/ErrorInfo';
import Media from 'src/components/media/Media'; import Media from 'src/components/media/Media';
import { Basic, Cast, DidYouKnow, Info, MoreLikeThis, Reviews } from 'src/components/title'; import { Basic, Cast, DidYouKnow, Info, MoreLikeThis, Reviews } from 'src/components/title';
import Title from 'src/interfaces/shared/title'; import Title from 'src/interfaces/shared/title';
import type { AppError } from 'src/interfaces/shared/error'; import { AppError } from 'src/interfaces/shared/error';
import getOrSetApiCache from 'src/utils/getOrSetApiCache'; import getOrSetApiCache from 'src/utils/getOrSetApiCache';
import title from 'src/utils/fetchers/title'; import title from 'src/utils/fetchers/title';
import { getErrorProperties, getProxiedIMDbImgUrl } from 'src/utils/helpers'; import { getErrorProperties, getProxiedIMDbImgUrl } from 'src/utils/helpers';
@ -63,18 +63,12 @@ export const getServerSideProps: GetServerSideProps<Data, Params> = async ctx =>
const data = await getOrSetApiCache(titleKey(titleId), title, titleId); const data = await getOrSetApiCache(titleKey(titleId), title, titleId);
return { props: { data, error: null, originalPath } }; return { props: { data, error: null, originalPath } };
} catch (e) { } catch (error) {
const err = getErrorProperties(e); const { message, statusCode } = getErrorProperties(error);
ctx.res.statusCode = err.statusCode; ctx.res.statusCode = statusCode;
ctx.res.statusMessage = err.message; ctx.res.statusMessage = message;
const error = { return { props: { error: { message, statusCode }, data: null, originalPath } };
message: err.message,
statusCode: err.statusCode,
stack: err.format(),
};
console.error(err);
return { props: { error, data: null, originalPath } };
} }
}; };

View File

@ -8,7 +8,7 @@
display: grid; display: grid;
justify-content: center; justify-content: center;
justify-items: center; justify-items: center;
gap: var(--comp-whitespace); gap: var(--spacer-1);
@include helper.bp('bp-700') { @include helper.bp('bp-700') {
--doc-whitespace: var(--spacer-5); --doc-whitespace: var(--spacer-5);
@ -31,19 +31,6 @@
text-align: center; text-align: center;
} }
.stack {
max-width: 90%;
max-height: 20rem;
padding: var(--spacer-3);
white-space: pre-wrap;
overflow: scroll;
user-select: all;
border-radius: var(--spacer-1);
background-color: var(--clr-bg-muted);
}
.button { .button {
align-self: end; align-self: end;

View File

@ -1,94 +1,26 @@
.reviews { .reviews {
display: grid; display: grid;
gap: var(--comp-whitespace); gap: var(--comp-whitespace);
&__reviewContainer {
// background-color: antiquewhite;
} }
.ratingsDistribution { &__stats {
overflow: hidden;
ul {
list-style: none;
display: flex;
gap: var(--spacer-2);
overflow-x: auto;
padding-block: var(--spacer-1);
}
li {
text-align: center;
display: flex;
flex-direction: column;
height: 5em;
align-items: center;
flex-shrink: 0;
&::before {
display: block;
content: '';
height: var(--bar-height);
margin-top: auto;
background-color: var(--clr-fill);
width: var(--spacer-6);
border-radius: var(--spacer-0);
}
span {
font-weight: var(--fw-bold);
> span {
font-weight: initial;
font-size: 0.9em;
color: var(--clr-text-muted);
}
}
}
}
.reviewAi {
summary {
cursor: pointer;
}
p {
padding-block: var(--spacer-2);
}
ul {
list-style: none;
display: flex;
gap: var(--spacer-1);
flex-wrap: wrap;
li {
padding: var(--spacer-1);
background-color: var(--clr-bg-muted);
border-radius: var(--spacer-0);
}
}
}
.reviewStats {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
gap: var(--spacer-2); gap: var(--spacer-2);
} }
.userReviews {
&__list {
padding-block-start: var(--spacer-1);
display: grid;
gap: var(--spacer-1);
list-style: none;
}
} }
.review { .review {
&__summary { &__summary {
font-size: calc(var(--fs-5) * 1.1);
cursor: pointer; cursor: pointer;
} }
&__text, &__text,
&__metadata { &__metadata {
padding-top: var(--spacer-1); padding-top: var(--spacer-2);
} }
} }

View File

@ -42,18 +42,18 @@ const cleanName = (rawData: RawName) => {
}, },
media: { media: {
...(main.primaryVideos.edges.length && { ...(main.primaryVideos.edges.length && {
trailers: main.primaryVideos.edges.map(trailer => ({ trailer: {
id: trailer.node.id, id: main.primaryVideos.edges[0].node.id,
isMature: trailer.node.isMature, isMature: main.primaryVideos.edges[0].node.isMature,
thumbnail: trailer.node.thumbnail.url, thumbnail: main.primaryVideos.edges[0].node.thumbnail.url,
runtime: trailer.node.runtime.value, runtime: main.primaryVideos.edges[0].node.runtime.value,
caption: trailer.node.description?.value ?? null, caption: main.primaryVideos.edges[0].node.description?.value ?? null,
urls: trailer.node.playbackURLs.map(url => ({ urls: main.primaryVideos.edges[0].node.playbackURLs.map(url => ({
resolution: url.displayName.value as 'SD' | '480p', resolution: url.displayName.value,
mimeType: url.videoMimeType ?? null, mimeType: url.mimeType ?? null,
url: url.url, url: url.url,
})), })),
})), },
}), }),
images: { images: {
total: misc.images.total, total: misc.images.total,

View File

@ -12,7 +12,6 @@ const cleanTitle = (rawData: RawTitle) => {
titleId: main.id, titleId: main.id,
basic: { basic: {
id: main.id, id: main.id,
isAdult: main.isAdult,
title: main.titleText.text, title: main.titleText.text,
// ...(main.originalTitleText.text.toLowerCase() !== // ...(main.originalTitleText.text.toLowerCase() !==
// main.titleText.text.toLowerCase() && { // main.titleText.text.toLowerCase() && {
@ -51,10 +50,6 @@ const cleanTitle = (rawData: RawTitle) => {
id: genre.id, id: genre.id,
text: genre.text, text: genre.text,
})), })),
interests: main.interests.edges.map(interest => ({
id: interest.node.id,
text: interest.node.primaryText.text,
})),
plot: main.plot?.plotText?.plainText || null, plot: main.plot?.plotText?.plainText || null,
primaryCrew: main.principalCredits.map(type => ({ primaryCrew: main.principalCredits.map(type => ({
type: { category: type.category.text, id: type.category.id }, type: { category: type.category.text, id: type.category.id },
@ -81,18 +76,18 @@ const cleanTitle = (rawData: RawTitle) => {
})), })),
media: { media: {
...(main.primaryVideos.edges.length && { ...(main.primaryVideos.edges.length && {
trailers: main.primaryVideos.edges.map(trailer => ({ trailer: {
id: trailer.node.id, id: main.primaryVideos.edges[0].node.id,
isMature: trailer.node.isMature, isMature: main.primaryVideos.edges[0].node.isMature,
thumbnail: trailer.node.thumbnail.url, thumbnail: main.primaryVideos.edges[0].node.thumbnail.url,
runtime: trailer.node.runtime.value, runtime: main.primaryVideos.edges[0].node.runtime.value,
caption: trailer.node.description?.value ?? null, caption: main.primaryVideos.edges[0].node.description?.value ?? null,
urls: trailer.node.playbackURLs.map(url => ({ urls: main.primaryVideos.edges[0].node.playbackURLs.map(url => ({
resolution: url.displayName.value as 'SD' | '480p', resolution: url.displayName.value,
mimeType: url.videoMimeType ?? null, mimeType: url.mimeType ?? null,
url: url.url, url: url.url,
})), })),
})), },
}), }),
images: { images: {
total: misc.titleMainImages.total, total: misc.titleMainImages.total,
@ -127,9 +122,6 @@ const cleanTitle = (rawData: RawTitle) => {
}), }),
topRating: misc.ratingsSummary.topRanking?.rank || null, topRating: misc.ratingsSummary.topRanking?.rank || null,
}, },
watchlist: {
text: main.engagementStatistics?.watchlistStatistics.displayableCount.text || null,
},
meta: { meta: {
// for tv episode // for tv episode
...(main.series && { ...(main.series && {
@ -216,34 +208,24 @@ const cleanTitle = (rawData: RawTitle) => {
metacriticScore: main.metacritic?.metascore.score || null, metacriticScore: main.metacritic?.metascore.score || null,
numCriticReviews: main.criticReviewsTotal.total, numCriticReviews: main.criticReviewsTotal.total,
numUserReviews: misc.reviews.total, numUserReviews: misc.reviews.total,
ratingsDistribution:
misc.aggregateRatingsBreakdown.histogram?.histogramValues.map(v => ({
rating: v.rating,
votes: v.voteCount,
})) || [],
...(misc.reviewSummary && {
ai: {
summary: misc.reviewSummary.overall.medium.value.plaidHtml,
themes: misc.reviewSummary.themes.map(t => ({
text: t.label.value,
id: t.themeId,
sentiment: t.sentiment as 'POSITIVE' | 'NEGATIVE',
})),
},
}),
...(misc.featuredReviews.edges.length && { ...(misc.featuredReviews.edges.length && {
featuredReviews: misc.featuredReviews.edges.map(featuredReview => ({ featuredReview: {
id: featuredReview.node.id, id: misc.featuredReviews.edges[0].node.id,
reviewer: { reviewer: {
id: featuredReview.node.author.userId, id: misc.featuredReviews.edges[0].node.author.userId,
name: featuredReview.node.author.username.text, name: misc.featuredReviews.edges[0].node.author.nickName,
},
rating: misc.featuredReviews.edges[0].node.authorRating,
date: formatDate(misc.featuredReviews.edges[0].node.submissionDate),
votes: {
up: misc.featuredReviews.edges[0].node.helpfulness.upVotes,
down: misc.featuredReviews.edges[0].node.helpfulness.downVotes,
}, },
rating: featuredReview.node.authorRating,
review: { review: {
summary: featuredReview.node.summary.originalText, summary: misc.featuredReviews.edges[0].node.summary.originalText,
html: featuredReview.node.text.originalText.plaidHtml, html: misc.featuredReviews.edges[0].node.text.originalText.plaidHtml,
},
}, },
})),
}), }),
}, },
details: { details: {
@ -260,8 +242,8 @@ const cleanTitle = (rawData: RawTitle) => {
}, },
}, },
}), }),
...(misc.countriesDetails && { ...(misc.countriesOfOrigin && {
countriesOfOrigin: misc.countriesDetails.countries.map(country => ({ countriesOfOrigin: misc.countriesOfOrigin.countries.map(country => ({
id: country.id, id: country.id,
text: country.text, text: country.text,
})), })),
@ -371,10 +353,6 @@ const cleanTitle = (rawData: RawTitle) => {
}, },
genres: title.node.titleGenres?.genres.map(genre => genre.genre.text) ?? null, genres: title.node.titleGenres?.genres.map(genre => genre.genre.text) ?? null,
})), })),
faqs: {
questions: misc.faqs.edges.map(q => ({ question: q.node.question, id: q.node.id })),
total: misc.faqs.total,
},
}; };
return cleanData; return cleanData;

View File

@ -74,33 +74,12 @@ export const getProxiedIMDbImgUrl = (url: string) => {
}; };
export const AppError = class extends Error { export const AppError = class extends Error {
constructor(message: string, public statusCode: number, cause?: unknown) { constructor(message: string, public statusCode: number, errorOptions?: unknown) {
const _cause = cause ? AppError.toError(cause) : undefined; const saneErrorOptions = getErrorOptions(errorOptions);
super(message, { cause: _cause }); super(message, saneErrorOptions);
Error.captureStackTrace(this, AppError); Error.captureStackTrace(this, AppError);
} if (process.env.NODE_ENV === 'development') console.error(this);
static toError(err: unknown) {
if (err instanceof Error) return err;
return new Error(`Unexpected: ${JSON.stringify(err)}`);
}
format() {
let str = '';
let cur: Error | null = this;
let depth = 0;
while (cur && depth <= 4) {
if (cur.stack) str += `${cur.stack}\n`;
else str += `${cur.name}: ${cur.message}\n`;
cur = cur.cause instanceof Error ? cur.cause : null;
if (cur) str += 'Caused by:\n';
depth++;
}
return str.trimEnd();
} }
}; };
@ -131,6 +110,19 @@ export const isLocalStorageAvailable = () => {
} }
}; };
const getErrorOptions = (error: unknown): ErrorOptions | undefined => {
if (!error || typeof error !== 'object') return undefined;
let cause: unknown;
// @ts-expect-error it's not an error! just that project's ts version is old, which can't be upgraded
if ('cause' in error) cause = error.cause;
// @ts-expect-error it's not an error! just that project's ts version is old, which can't be upgraded
else if ('stack' in error) cause = error.stack;
// @ts-expect-error it's not an error! just that project's ts version is old, which can't be upgraded
return { cause };
};
export const getErrorProperties = ( export const getErrorProperties = (
error: unknown, error: unknown,
message = 'Something went very wrong', message = 'Something went very wrong',

View File

@ -1,5 +0,0 @@
{
"upstream": "https://github.com/zyachel/libremdb",
"provider": "github",
"commit": "dded1e59ca6df40ccb1b3f2c70de14144afbe922"
}