refactor: migrate from MongoDB to Prisma for data management, removing mongoose models and updating services to use Prisma client
This commit is contained in:
@@ -1,16 +1,66 @@
|
||||
.git
|
||||
.gitignore
|
||||
# dependencies
|
||||
node_modules
|
||||
.pnp
|
||||
.pnp.js
|
||||
.pnpm-store
|
||||
|
||||
# testing
|
||||
coverage
|
||||
|
||||
# next.js
|
||||
.next
|
||||
.env.local
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
README.md
|
||||
.vscode
|
||||
.idea
|
||||
*.log
|
||||
out
|
||||
|
||||
# production
|
||||
build
|
||||
dist
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
*.pem
|
||||
|
||||
# debug
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
.DS_Store
|
||||
.pnpm-debug.log*
|
||||
|
||||
# local env files
|
||||
.env*.local
|
||||
.env
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
|
||||
# vercel
|
||||
.vercel
|
||||
|
||||
# typescript
|
||||
*.tsbuildinfo
|
||||
next-env.d.ts
|
||||
|
||||
# IDE
|
||||
.idea
|
||||
.vscode
|
||||
.vscode-test
|
||||
|
||||
# git
|
||||
.git
|
||||
.gitignore
|
||||
|
||||
# cache
|
||||
.cache
|
||||
debug-logs
|
||||
|
||||
# docker
|
||||
Dockerfile
|
||||
docker-compose.yml
|
||||
docker-compose.dev.yml
|
||||
.dockerignore
|
||||
|
||||
# documentation
|
||||
README.md
|
||||
docs
|
||||
|
||||
# scripts
|
||||
scripts
|
||||
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -39,6 +39,9 @@ next-env.d.ts
|
||||
.cache
|
||||
debug-logs
|
||||
|
||||
# MongoDB
|
||||
mongo-keyfile
|
||||
|
||||
# Environment variables
|
||||
.env
|
||||
.env.local
|
||||
|
||||
23
Dockerfile
23
Dockerfile
@@ -20,6 +20,9 @@ RUN corepack enable && corepack prepare pnpm@9.0.0 --activate
|
||||
# Copy package files first to leverage Docker cache
|
||||
COPY package.json pnpm-lock.yaml ./
|
||||
|
||||
# Copy Prisma schema
|
||||
COPY prisma ./prisma
|
||||
|
||||
# Copy configuration files
|
||||
COPY tsconfig.json .eslintrc.json ./
|
||||
COPY tailwind.config.ts postcss.config.js ./
|
||||
@@ -28,6 +31,9 @@ COPY tailwind.config.ts postcss.config.js ./
|
||||
RUN pnpm config set store-dir /app/.pnpm-store && \
|
||||
pnpm install --frozen-lockfile
|
||||
|
||||
# Generate Prisma Client
|
||||
RUN pnpm prisma generate
|
||||
|
||||
# Copy source files
|
||||
COPY src ./src
|
||||
COPY public ./public
|
||||
@@ -40,13 +46,18 @@ FROM node:20-alpine AS runner
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# Install production dependencies only
|
||||
# Install OpenSSL (required by Prisma)
|
||||
RUN apk add --no-cache openssl libc6-compat
|
||||
|
||||
# Copy package files and prisma schema
|
||||
COPY package.json pnpm-lock.yaml ./
|
||||
RUN corepack enable && \
|
||||
corepack prepare pnpm@9.0.0 --activate && \
|
||||
pnpm config set store-dir /app/.pnpm-store && \
|
||||
pnpm install --prod --frozen-lockfile && \
|
||||
pnpm store prune
|
||||
COPY prisma ./prisma
|
||||
|
||||
# Enable pnpm
|
||||
RUN corepack enable && corepack prepare pnpm@9.0.0 --activate
|
||||
|
||||
# Copy the entire node_modules from builder (includes Prisma Client)
|
||||
COPY --from=builder /app/node_modules ./node_modules
|
||||
|
||||
# Copy built application from builder stage
|
||||
COPY --from=builder /app/.next ./.next
|
||||
|
||||
10
ENV.md
10
ENV.md
@@ -5,7 +5,7 @@
|
||||
# MongoDB Configuration
|
||||
MONGO_USER=admin
|
||||
MONGO_PASSWORD=your-secure-password
|
||||
MONGODB_URI=mongodb://admin:your-secure-password@mongodb:27017/stripstream?authSource=admin
|
||||
MONGODB_URI=mongodb://admin:your-secure-password@mongodb:27017/stripstream?authSource=admin&replicaSet=rs0
|
||||
|
||||
# NextAuth Configuration
|
||||
NEXTAUTH_SECRET=your-secret-key-here-generate-with-openssl-rand-base64-32
|
||||
@@ -20,5 +20,13 @@ NODE_ENV=production
|
||||
openssl rand -base64 32
|
||||
```
|
||||
|
||||
## Génération du keyFile MongoDB (requis pour Prisma)
|
||||
```bash
|
||||
openssl rand -base64 756 > mongo-keyfile
|
||||
chmod 400 mongo-keyfile
|
||||
```
|
||||
|
||||
Ce fichier est nécessaire pour MongoDB en mode replica set (requis par Prisma pour les relations et transactions).
|
||||
|
||||
## Développement
|
||||
Pour le développement, les variables sont définies directement dans `docker-compose.dev.yml`.
|
||||
|
||||
@@ -12,6 +12,7 @@ services:
|
||||
- "3020:3000"
|
||||
volumes:
|
||||
- ./src:/app/src
|
||||
- ./prisma:/app/prisma
|
||||
- ./public:/app/public
|
||||
- ./package.json:/app/package.json
|
||||
- ./pnpm-lock.yaml:/app/pnpm-lock.yaml
|
||||
@@ -31,7 +32,7 @@ services:
|
||||
- WATCHPACK_POLLING=true
|
||||
- NEXTAUTH_SECRET=${NEXTAUTH_SECRET}
|
||||
- NEXTAUTH_URL=${NEXTAUTH_URL}
|
||||
command: sh -c "pnpm config set store-dir /app/.pnpm-store && pnpm install --frozen-lockfile && pnpm dev"
|
||||
command: sh -c "pnpm config set store-dir /app/.pnpm-store && pnpm install --frozen-lockfile && pnpm prisma generate && pnpm dev"
|
||||
|
||||
mongodb:
|
||||
image: mongo:latest
|
||||
@@ -46,6 +47,14 @@ services:
|
||||
volumes:
|
||||
- mongodb_data:/data/db
|
||||
- ./mongo-init.js:/docker-entrypoint-initdb.d/mongo-init.js:ro
|
||||
- ./mongo-keyfile:/data/keyfile:ro
|
||||
command: ["mongod", "--replSet", "rs0", "--bind_ip_all", "--keyFile", "/data/keyfile"]
|
||||
healthcheck:
|
||||
test: echo "try { rs.status() } catch (err) { rs.initiate({_id:'rs0',members:[{_id:0,host:'mongodb:27017'}]}) }" | mongosh -u ${MONGO_USER} -p ${MONGO_PASSWORD} --authenticationDatabase admin --quiet
|
||||
interval: 10s
|
||||
timeout: 10s
|
||||
retries: 5
|
||||
start_period: 40s
|
||||
|
||||
volumes:
|
||||
mongodb_data:
|
||||
|
||||
@@ -45,6 +45,7 @@ services:
|
||||
MONGO_INITDB_ROOT_PASSWORD: ${MONGO_PASSWORD}
|
||||
volumes:
|
||||
- stripstream_mongodb_data:/data/db
|
||||
- ./mongo-keyfile:/data/keyfile:ro
|
||||
networks:
|
||||
- stripstream-network
|
||||
deploy:
|
||||
@@ -54,7 +55,13 @@ services:
|
||||
memory: 512M
|
||||
ports:
|
||||
- "27017:27017"
|
||||
command: ["mongod", "--auth", "--bind_ip_all"]
|
||||
command: ["mongod", "--auth", "--bind_ip_all", "--replSet", "rs0", "--keyFile", "/data/keyfile"]
|
||||
healthcheck:
|
||||
test: echo "try { rs.status() } catch (err) { rs.initiate({_id:'rs0',members:[{_id:0,host:'mongodb:27017'}]}) }" | mongosh -u ${MONGO_USER} -p ${MONGO_PASSWORD} --authenticationDatabase admin --quiet
|
||||
interval: 10s
|
||||
timeout: 10s
|
||||
retries: 5
|
||||
start_period: 40s
|
||||
|
||||
networks:
|
||||
stripstream-network:
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
"icons": "node scripts/generate-icons.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@prisma/client": "^6.17.1",
|
||||
"@radix-ui/react-dialog": "1.0.5",
|
||||
"@radix-ui/react-dropdown-menu": "^2.1.6",
|
||||
"@radix-ui/react-progress": "^1.1.2",
|
||||
@@ -18,7 +19,6 @@
|
||||
"@radix-ui/react-slot": "1.0.2",
|
||||
"@radix-ui/react-toast": "1.1.5",
|
||||
"@types/bcryptjs": "^3.0.0",
|
||||
"@types/mongoose": "5.11.97",
|
||||
"bcryptjs": "^3.0.2",
|
||||
"class-variance-authority": "^0.7.0",
|
||||
"clsx": "^2.1.1",
|
||||
@@ -26,7 +26,6 @@
|
||||
"i18next": "^24.2.2",
|
||||
"i18next-browser-languagedetector": "^8.0.4",
|
||||
"lucide-react": "^0.487.0",
|
||||
"mongoose": "8.1.0",
|
||||
"next": "15.2.0",
|
||||
"next-auth": "5.0.0-beta.29",
|
||||
"next-themes": "0.2.1",
|
||||
@@ -53,6 +52,7 @@
|
||||
"eslint-plugin-typescript-sort-keys": "^3.3.0",
|
||||
"eslint-plugin-unused-imports": "^4.1.4",
|
||||
"postcss": "8.4.33",
|
||||
"prisma": "^6.17.1",
|
||||
"tailwindcss": "3.4.1",
|
||||
"typescript": "5.3.3"
|
||||
},
|
||||
|
||||
452
pnpm-lock.yaml
generated
452
pnpm-lock.yaml
generated
@@ -8,6 +8,9 @@ importers:
|
||||
|
||||
.:
|
||||
dependencies:
|
||||
'@prisma/client':
|
||||
specifier: ^6.17.1
|
||||
version: 6.17.1(prisma@6.17.1(typescript@5.3.3))(typescript@5.3.3)
|
||||
'@radix-ui/react-dialog':
|
||||
specifier: 1.0.5
|
||||
version: 1.0.5(@types/react-dom@18.2.21)(@types/react@18.2.64)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
|
||||
@@ -29,9 +32,6 @@ importers:
|
||||
'@types/bcryptjs':
|
||||
specifier: ^3.0.0
|
||||
version: 3.0.0
|
||||
'@types/mongoose':
|
||||
specifier: 5.11.97
|
||||
version: 5.11.97
|
||||
bcryptjs:
|
||||
specifier: ^3.0.2
|
||||
version: 3.0.2
|
||||
@@ -53,9 +53,6 @@ importers:
|
||||
lucide-react:
|
||||
specifier: ^0.487.0
|
||||
version: 0.487.0(react@18.2.0)
|
||||
mongoose:
|
||||
specifier: 8.1.0
|
||||
version: 8.1.0
|
||||
next:
|
||||
specifier: 15.2.0
|
||||
version: 15.2.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
|
||||
@@ -129,6 +126,9 @@ importers:
|
||||
postcss:
|
||||
specifier: 8.4.33
|
||||
version: 8.4.33
|
||||
prisma:
|
||||
specifier: ^6.17.1
|
||||
version: 6.17.1(typescript@5.3.3)
|
||||
tailwindcss:
|
||||
specifier: 3.4.1
|
||||
version: 3.4.1
|
||||
@@ -459,9 +459,6 @@ packages:
|
||||
'@jridgewell/trace-mapping@0.3.31':
|
||||
resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==}
|
||||
|
||||
'@mongodb-js/saslprep@1.3.1':
|
||||
resolution: {integrity: sha512-6nZrq5kfAz0POWyhljnbWQQJQ5uT8oE2ddX303q1uY0tWsivWKgBDXBBvuFPwOqRRalXJuVO9EjOdVtuhLX0zg==}
|
||||
|
||||
'@napi-rs/wasm-runtime@0.2.12':
|
||||
resolution: {integrity: sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==}
|
||||
|
||||
@@ -542,6 +539,36 @@ packages:
|
||||
resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==}
|
||||
engines: {node: '>=14'}
|
||||
|
||||
'@prisma/client@6.17.1':
|
||||
resolution: {integrity: sha512-zL58jbLzYamjnNnmNA51IOZdbk5ci03KviXCuB0Tydc9btH2kDWsi1pQm2VecviRTM7jGia0OPPkgpGnT3nKvw==}
|
||||
engines: {node: '>=18.18'}
|
||||
peerDependencies:
|
||||
prisma: '*'
|
||||
typescript: '>=5.1.0'
|
||||
peerDependenciesMeta:
|
||||
prisma:
|
||||
optional: true
|
||||
typescript:
|
||||
optional: true
|
||||
|
||||
'@prisma/config@6.17.1':
|
||||
resolution: {integrity: sha512-fs8wY6DsvOCzuiyWVckrVs1LOcbY4LZNz8ki4uUIQ28jCCzojTGqdLhN2Jl5lDnC1yI8/gNIKpsWDM8pLhOdwA==}
|
||||
|
||||
'@prisma/debug@6.17.1':
|
||||
resolution: {integrity: sha512-Vf7Tt5Wh9XcndpbmeotuqOMLWPTjEKCsgojxXP2oxE1/xYe7PtnP76hsouG9vis6fctX+TxgmwxTuYi/+xc7dQ==}
|
||||
|
||||
'@prisma/engines-version@6.17.1-1.272a37d34178c2894197e17273bf937f25acdeac':
|
||||
resolution: {integrity: sha512-17140E3huOuD9lMdJ9+SF/juOf3WR3sTJMVyyenzqUPbuH+89nPhSWcrY+Mf7tmSs6HvaO+7S+HkELinn6bhdg==}
|
||||
|
||||
'@prisma/engines@6.17.1':
|
||||
resolution: {integrity: sha512-D95Ik3GYZkqZ8lSR4EyFOJ/tR33FcYRP8kK61o+WMsyD10UfJwd7+YielflHfKwiGodcqKqoraWw8ElAgMDbPw==}
|
||||
|
||||
'@prisma/fetch-engine@6.17.1':
|
||||
resolution: {integrity: sha512-AYZiHOs184qkDMiTeshyJCtyL4yERkjfTkJiSJdYuSfc24m94lTNL5+GFinZ6vVz+ktX4NJzHKn1zIFzGTWrWg==}
|
||||
|
||||
'@prisma/get-platform@6.17.1':
|
||||
resolution: {integrity: sha512-AKEn6fsfz0r482S5KRDFlIGEaq9wLNcgalD1adL+fPcFFblIKs1sD81kY/utrHdqKuVC6E1XSRpegDK3ZLL4Qg==}
|
||||
|
||||
'@radix-ui/number@1.1.1':
|
||||
resolution: {integrity: sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g==}
|
||||
|
||||
@@ -1066,6 +1093,9 @@ packages:
|
||||
'@rushstack/eslint-patch@1.14.0':
|
||||
resolution: {integrity: sha512-WJFej426qe4RWOm9MMtP4V3CV4AucXolQty+GRgAWLgQXmpCuwzs7hEpxxhSc/znXUSxum9d/P/32MW0FlAAlA==}
|
||||
|
||||
'@standard-schema/spec@1.0.0':
|
||||
resolution: {integrity: sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==}
|
||||
|
||||
'@swc/counter@0.1.3':
|
||||
resolution: {integrity: sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==}
|
||||
|
||||
@@ -1085,10 +1115,6 @@ packages:
|
||||
'@types/json5@0.0.29':
|
||||
resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==}
|
||||
|
||||
'@types/mongoose@5.11.97':
|
||||
resolution: {integrity: sha512-cqwOVYT3qXyLiGw7ueU2kX9noE8DPGRY6z8eUxudhXY8NZ7DMKYAxyZkLSevGfhCX3dO/AoX5/SO9lAzfjon0Q==}
|
||||
deprecated: Mongoose publishes its own types, so you do not need to install this package.
|
||||
|
||||
'@types/node@24.7.2':
|
||||
resolution: {integrity: sha512-/NbVmcGTP+lj5oa4yiYxxeBjRivKQ5Ns1eSZeB99ExsEQ6rX5XYU1Zy/gGxY/ilqtD4Etx9mKyrPxZRetiahhA==}
|
||||
|
||||
@@ -1107,12 +1133,6 @@ packages:
|
||||
'@types/semver@7.7.1':
|
||||
resolution: {integrity: sha512-FmgJfu+MOcQ370SD0ev7EI8TlCAfKYU+B4m5T3yXc1CiRN94g/SZPtsCkk506aUDtlMnFZvasDwHHUcZUEaYuA==}
|
||||
|
||||
'@types/webidl-conversions@7.0.3':
|
||||
resolution: {integrity: sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA==}
|
||||
|
||||
'@types/whatwg-url@11.0.5':
|
||||
resolution: {integrity: sha512-coYR071JRaHa+xoEvvYqvnIHaVqaYrLPbsufM9BF63HkwI5Lgmy2QR8Q5K/lYDYo5AK82wOvSOS0UsLTpTG7uQ==}
|
||||
|
||||
'@typescript-eslint/eslint-plugin@8.46.1':
|
||||
resolution: {integrity: sha512-rUsLh8PXmBjdiPY+Emjz9NX2yHvhS11v0SR6xNJkm5GM1MO9ea/1GoDKlHHZGrOJclL/cZ2i/vRUYVtjRhrHVQ==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
@@ -1469,14 +1489,18 @@ packages:
|
||||
engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
|
||||
hasBin: true
|
||||
|
||||
bson@6.10.4:
|
||||
resolution: {integrity: sha512-WIsKqkSC0ABoBJuT1LEX+2HEvNmNKKgnTAyd0fL8qzK4SH2i9NXg+t08YtdZp/V9IZ33cxe3iV4yM0qg8lMQng==}
|
||||
engines: {node: '>=16.20.1'}
|
||||
|
||||
busboy@1.6.0:
|
||||
resolution: {integrity: sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==}
|
||||
engines: {node: '>=10.16.0'}
|
||||
|
||||
c12@3.1.0:
|
||||
resolution: {integrity: sha512-uWoS8OU1MEIsOv8p/5a82c3H31LsWVR5qiyXVfBNOzfffjUWtPnhAb4BYI2uG2HfGmZmFjCtui5XNWaps+iFuw==}
|
||||
peerDependencies:
|
||||
magicast: ^0.3.5
|
||||
peerDependenciesMeta:
|
||||
magicast:
|
||||
optional: true
|
||||
|
||||
call-bind-apply-helpers@1.0.2:
|
||||
resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==}
|
||||
engines: {node: '>= 0.4'}
|
||||
@@ -1508,6 +1532,13 @@ packages:
|
||||
resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==}
|
||||
engines: {node: '>= 8.10.0'}
|
||||
|
||||
chokidar@4.0.3:
|
||||
resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==}
|
||||
engines: {node: '>= 14.16.0'}
|
||||
|
||||
citty@0.1.6:
|
||||
resolution: {integrity: sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ==}
|
||||
|
||||
class-variance-authority@0.7.1:
|
||||
resolution: {integrity: sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==}
|
||||
|
||||
@@ -1539,6 +1570,13 @@ packages:
|
||||
concat-map@0.0.1:
|
||||
resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
|
||||
|
||||
confbox@0.2.2:
|
||||
resolution: {integrity: sha512-1NB+BKqhtNipMsov4xI/NnhCKp9XG9NamYp5PVm9klAT0fsrNPjaFICsCFhNhwZJKNh7zB/3q8qXz0E9oaMNtQ==}
|
||||
|
||||
consola@3.4.2:
|
||||
resolution: {integrity: sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==}
|
||||
engines: {node: ^14.18.0 || >=16.10.0}
|
||||
|
||||
cross-spawn@7.0.6:
|
||||
resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==}
|
||||
engines: {node: '>= 8'}
|
||||
@@ -1586,6 +1624,10 @@ packages:
|
||||
deep-is@0.1.4:
|
||||
resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==}
|
||||
|
||||
deepmerge-ts@7.1.5:
|
||||
resolution: {integrity: sha512-HOJkrhaYsweh+W+e74Yn7YStZOilkoPb6fycpwNLKzSPtruFs48nYis0zy5yJz1+ktUhHxoRDJ27RQAWLIJVJw==}
|
||||
engines: {node: '>=16.0.0'}
|
||||
|
||||
define-data-property@1.1.4:
|
||||
resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==}
|
||||
engines: {node: '>= 0.4'}
|
||||
@@ -1594,6 +1636,12 @@ packages:
|
||||
resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
defu@6.1.4:
|
||||
resolution: {integrity: sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==}
|
||||
|
||||
destr@2.0.5:
|
||||
resolution: {integrity: sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA==}
|
||||
|
||||
detect-libc@2.1.2:
|
||||
resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==}
|
||||
engines: {node: '>=8'}
|
||||
@@ -1619,6 +1667,10 @@ packages:
|
||||
resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==}
|
||||
engines: {node: '>=6.0.0'}
|
||||
|
||||
dotenv@16.6.1:
|
||||
resolution: {integrity: sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
dunder-proto@1.0.1:
|
||||
resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==}
|
||||
engines: {node: '>= 0.4'}
|
||||
@@ -1626,6 +1678,9 @@ packages:
|
||||
eastasianwidth@0.2.0:
|
||||
resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==}
|
||||
|
||||
effect@3.16.12:
|
||||
resolution: {integrity: sha512-N39iBk0K71F9nb442TLbTkjl24FLUzuvx2i1I2RsEAQsdAdUTuUoW0vlfUXgkMTUOnYqKnWcFfqw4hK4Pw27hg==}
|
||||
|
||||
electron-to-chromium@1.5.235:
|
||||
resolution: {integrity: sha512-i/7ntLFwOdoHY7sgjlTIDo4Sl8EdoTjWIaKinYOVfC6bOp71bmwenyZthWHcasxgHDNWbWxvG9M3Ia116zIaYQ==}
|
||||
|
||||
@@ -1635,6 +1690,10 @@ packages:
|
||||
emoji-regex@9.2.2:
|
||||
resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==}
|
||||
|
||||
empathic@2.0.0:
|
||||
resolution: {integrity: sha512-i6UzDscO/XfAcNYD75CfICkmfLedpyPDdozrLMmQc5ORaQcdMoc21OnlEylMIqI7U8eniKrPMxxtj8k0vhmJhA==}
|
||||
engines: {node: '>=14'}
|
||||
|
||||
es-abstract@1.24.0:
|
||||
resolution: {integrity: sha512-WSzPgsdLtTcQwm4CROfS5ju2Wa1QQcVeT37jFjYzdFz1r9ahadC8B8/a4qxJxM+09F18iumCdRmlr96ZYkQvEg==}
|
||||
engines: {node: '>= 0.4'}
|
||||
@@ -1818,6 +1877,13 @@ packages:
|
||||
resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
exsolve@1.0.7:
|
||||
resolution: {integrity: sha512-VO5fQUzZtI6C+vx4w/4BWJpg3s/5l+6pRQEHzFRM8WFi4XffSP1Z+4qi7GbjWbvRQEbdIco5mIMq+zX4rPuLrw==}
|
||||
|
||||
fast-check@3.23.2:
|
||||
resolution: {integrity: sha512-h5+1OzzfCC3Ef7VbtKdcv7zsstUQwUDlYpUTvjeUsJAssPgLn7QzbboPtL5ro04Mq0rPOsMzl7q5hIbRs2wD1A==}
|
||||
engines: {node: '>=8.0.0'}
|
||||
|
||||
fast-deep-equal@3.1.3:
|
||||
resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==}
|
||||
|
||||
@@ -1929,6 +1995,10 @@ packages:
|
||||
get-tsconfig@4.12.0:
|
||||
resolution: {integrity: sha512-LScr2aNr2FbjAjZh2C6X6BxRx1/x+aTDExct/xyq2XKbYOiG5c0aK7pMsSuyc0brz3ibr/lbQiHD9jzt4lccJw==}
|
||||
|
||||
giget@2.0.0:
|
||||
resolution: {integrity: sha512-L5bGsVkxJbJgdnwyuheIunkGatUF/zssUoxxjACCseZYAVbaqdh9Tsmmlkl8vYan09H7sbvKt4pS8GqKLBrEzA==}
|
||||
hasBin: true
|
||||
|
||||
glob-parent@5.1.2:
|
||||
resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
|
||||
engines: {node: '>= 6'}
|
||||
@@ -2167,6 +2237,10 @@ packages:
|
||||
resolution: {integrity: sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==}
|
||||
hasBin: true
|
||||
|
||||
jiti@2.6.1:
|
||||
resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==}
|
||||
hasBin: true
|
||||
|
||||
jose@6.1.0:
|
||||
resolution: {integrity: sha512-TTQJyoEoKcC1lscpVDCSsVgYzUDg/0Bt3WE//WiTPK6uOCQC2KZS4MpugbMWt/zyjkopgZoXhZuCi00gLudfUA==}
|
||||
|
||||
@@ -2197,10 +2271,6 @@ packages:
|
||||
resolution: {integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==}
|
||||
engines: {node: '>=4.0'}
|
||||
|
||||
kareem@2.5.1:
|
||||
resolution: {integrity: sha512-7jFxRVm+jD+rkq3kY0iZDJfsO2/t4BBPeEb2qKn2lR/9KhuksYk5hxzfRYWMPV8P/x2d0kHD306YyWLzjjH+uA==}
|
||||
engines: {node: '>=12.0.0'}
|
||||
|
||||
keyv@4.5.4:
|
||||
resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==}
|
||||
|
||||
@@ -2249,9 +2319,6 @@ packages:
|
||||
resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
memory-pager@1.5.0:
|
||||
resolution: {integrity: sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==}
|
||||
|
||||
merge2@1.4.1:
|
||||
resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==}
|
||||
engines: {node: '>= 8'}
|
||||
@@ -2278,48 +2345,6 @@ packages:
|
||||
resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==}
|
||||
engines: {node: '>=16 || 14 >=14.17'}
|
||||
|
||||
mongodb-connection-string-url@3.0.2:
|
||||
resolution: {integrity: sha512-rMO7CGo/9BFwyZABcKAWL8UJwH/Kc2x0g72uhDWzG48URRax5TCIcJ7Rc3RZqffZzO/Gwff/jyKwCU9TN8gehA==}
|
||||
|
||||
mongodb@6.3.0:
|
||||
resolution: {integrity: sha512-tt0KuGjGtLUhLoU263+xvQmPHEGTw5LbcNC73EoFRYgSHwZt5tsoJC110hDyO1kjQzpgNrpdcSza9PknWN4LrA==}
|
||||
engines: {node: '>=16.20.1'}
|
||||
peerDependencies:
|
||||
'@aws-sdk/credential-providers': ^3.188.0
|
||||
'@mongodb-js/zstd': ^1.1.0
|
||||
gcp-metadata: ^5.2.0
|
||||
kerberos: ^2.0.1
|
||||
mongodb-client-encryption: '>=6.0.0 <7'
|
||||
snappy: ^7.2.2
|
||||
socks: ^2.7.1
|
||||
peerDependenciesMeta:
|
||||
'@aws-sdk/credential-providers':
|
||||
optional: true
|
||||
'@mongodb-js/zstd':
|
||||
optional: true
|
||||
gcp-metadata:
|
||||
optional: true
|
||||
kerberos:
|
||||
optional: true
|
||||
mongodb-client-encryption:
|
||||
optional: true
|
||||
snappy:
|
||||
optional: true
|
||||
socks:
|
||||
optional: true
|
||||
|
||||
mongoose@8.1.0:
|
||||
resolution: {integrity: sha512-kOA4Xnq2goqNpN9EmYElGNWfxA9H80fxcr7UdJKWi3UMflza0R7wpTihCpM67dE/0MNFljoa0sjQtlXVkkySAQ==}
|
||||
engines: {node: '>=16.20.1'}
|
||||
|
||||
mpath@0.9.0:
|
||||
resolution: {integrity: sha512-ikJRQTk8hw5DEoFVxHG1Gn9T/xcjtdnOKIU1JTmGjZZlg9LST2mBLmcX3/ICIbgJydT2GOc15RnNy5mHmzfSew==}
|
||||
engines: {node: '>=4.0.0'}
|
||||
|
||||
mquery@5.0.0:
|
||||
resolution: {integrity: sha512-iQMncpmEK8R8ncT8HJGsGc9Dsp8xcgYMVSbs5jgnm1lFHTZqMJTUWTDx1LBO8+mK3tPNZWFLBghQEIOULSTHZg==}
|
||||
engines: {node: '>=14.0.0'}
|
||||
|
||||
ms@2.1.3:
|
||||
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
|
||||
|
||||
@@ -2386,6 +2411,9 @@ packages:
|
||||
sass:
|
||||
optional: true
|
||||
|
||||
node-fetch-native@1.6.7:
|
||||
resolution: {integrity: sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q==}
|
||||
|
||||
node-releases@2.0.23:
|
||||
resolution: {integrity: sha512-cCmFDMSm26S6tQSDpBCg/NR8NENrVPhAJSf+XbxBG4rPFaaonlEoE9wHQmun+cls499TQGSb7ZyPBRlzgKfpeg==}
|
||||
|
||||
@@ -2397,6 +2425,11 @@ packages:
|
||||
resolution: {integrity: sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
nypm@0.6.2:
|
||||
resolution: {integrity: sha512-7eM+hpOtrKrBDCh7Ypu2lJ9Z7PNZBdi/8AT3AX8xoCj43BBVHD0hPSTEvMtkMpfs8FCqBGhxB+uToIQimA111g==}
|
||||
engines: {node: ^14.16.0 || >=16.10.0}
|
||||
hasBin: true
|
||||
|
||||
oauth4webapi@3.8.2:
|
||||
resolution: {integrity: sha512-FzZZ+bht5X0FKe7Mwz3DAVAmlH1BV5blSak/lHMBKz0/EBMhX6B10GlQYI51+oRp8ObJaX0g6pXrAxZh5s8rjw==}
|
||||
|
||||
@@ -2436,6 +2469,9 @@ packages:
|
||||
resolution: {integrity: sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
ohash@2.0.11:
|
||||
resolution: {integrity: sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==}
|
||||
|
||||
once@1.4.0:
|
||||
resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
|
||||
|
||||
@@ -2485,6 +2521,12 @@ packages:
|
||||
resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
pathe@2.0.3:
|
||||
resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==}
|
||||
|
||||
perfect-debounce@1.0.0:
|
||||
resolution: {integrity: sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==}
|
||||
|
||||
picocolors@1.1.1:
|
||||
resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
|
||||
|
||||
@@ -2504,6 +2546,9 @@ packages:
|
||||
resolution: {integrity: sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==}
|
||||
engines: {node: '>= 6'}
|
||||
|
||||
pkg-types@2.3.0:
|
||||
resolution: {integrity: sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig==}
|
||||
|
||||
possible-typed-array-names@1.1.0:
|
||||
resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==}
|
||||
engines: {node: '>= 0.4'}
|
||||
@@ -2565,6 +2610,16 @@ packages:
|
||||
resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==}
|
||||
engines: {node: '>= 0.8.0'}
|
||||
|
||||
prisma@6.17.1:
|
||||
resolution: {integrity: sha512-ac6h0sM1Tg3zu8NInY+qhP/S9KhENVaw9n1BrGKQVFu05JT5yT5Qqqmb8tMRIE3ZXvVj4xcRA5yfrsy4X7Yy5g==}
|
||||
engines: {node: '>=18.18'}
|
||||
hasBin: true
|
||||
peerDependencies:
|
||||
typescript: '>=5.1.0'
|
||||
peerDependenciesMeta:
|
||||
typescript:
|
||||
optional: true
|
||||
|
||||
prop-types@15.8.1:
|
||||
resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==}
|
||||
|
||||
@@ -2572,9 +2627,15 @@ packages:
|
||||
resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==}
|
||||
engines: {node: '>=6'}
|
||||
|
||||
pure-rand@6.1.0:
|
||||
resolution: {integrity: sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==}
|
||||
|
||||
queue-microtask@1.2.3:
|
||||
resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
|
||||
|
||||
rc9@2.1.2:
|
||||
resolution: {integrity: sha512-btXCnMmRIBINM2LDZoEmOogIZU7Qe7zn4BpomSKZ/ykbLObuBdvG+mFq11DL6fjH1DRwHhrlgtYWG96bJiC7Cg==}
|
||||
|
||||
react-dom@18.2.0:
|
||||
resolution: {integrity: sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==}
|
||||
peerDependencies:
|
||||
@@ -2657,6 +2718,10 @@ packages:
|
||||
resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==}
|
||||
engines: {node: '>=8.10.0'}
|
||||
|
||||
readdirp@4.1.2:
|
||||
resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==}
|
||||
engines: {node: '>= 14.18.0'}
|
||||
|
||||
reflect.getprototypeof@1.0.10:
|
||||
resolution: {integrity: sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==}
|
||||
engines: {node: '>= 0.4'}
|
||||
@@ -2761,9 +2826,6 @@ packages:
|
||||
resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
sift@16.0.1:
|
||||
resolution: {integrity: sha512-Wv6BjQ5zbhW7VFefWusVP33T/EM0vYikCaQ2qR8yULbsilAT8/wQaXvuQ3ptGLpoKx+lihJE3y2UTgKDyyNHZQ==}
|
||||
|
||||
signal-exit@4.1.0:
|
||||
resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==}
|
||||
engines: {node: '>=14'}
|
||||
@@ -2779,9 +2841,6 @@ packages:
|
||||
resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
sparse-bitfield@3.0.3:
|
||||
resolution: {integrity: sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==}
|
||||
|
||||
stable-hash@0.0.5:
|
||||
resolution: {integrity: sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA==}
|
||||
|
||||
@@ -2889,6 +2948,9 @@ packages:
|
||||
thenify@3.3.1:
|
||||
resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==}
|
||||
|
||||
tinyexec@1.0.1:
|
||||
resolution: {integrity: sha512-5uC6DDlmeqiOwCPmK9jMSdOuZTh8bU39Ys6yidB+UTt5hfZUPGAypSgFRiEp+jbi9qH40BLDvy85jIU88wKSqw==}
|
||||
|
||||
tinyglobby@0.2.15:
|
||||
resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==}
|
||||
engines: {node: '>=12.0.0'}
|
||||
@@ -2897,10 +2959,6 @@ packages:
|
||||
resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
|
||||
engines: {node: '>=8.0'}
|
||||
|
||||
tr46@5.1.1:
|
||||
resolution: {integrity: sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
ts-api-utils@1.4.3:
|
||||
resolution: {integrity: sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw==}
|
||||
engines: {node: '>=16'}
|
||||
@@ -3010,14 +3068,6 @@ packages:
|
||||
resolution: {integrity: sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
webidl-conversions@7.0.0:
|
||||
resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
whatwg-url@14.2.0:
|
||||
resolution: {integrity: sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
which-boxed-primitive@1.1.1:
|
||||
resolution: {integrity: sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==}
|
||||
engines: {node: '>= 0.4'}
|
||||
@@ -3334,10 +3384,6 @@ snapshots:
|
||||
'@jridgewell/resolve-uri': 3.1.2
|
||||
'@jridgewell/sourcemap-codec': 1.5.5
|
||||
|
||||
'@mongodb-js/saslprep@1.3.1':
|
||||
dependencies:
|
||||
sparse-bitfield: 3.0.3
|
||||
|
||||
'@napi-rs/wasm-runtime@0.2.12':
|
||||
dependencies:
|
||||
'@emnapi/core': 1.5.0
|
||||
@@ -3394,6 +3440,41 @@ snapshots:
|
||||
'@pkgjs/parseargs@0.11.0':
|
||||
optional: true
|
||||
|
||||
'@prisma/client@6.17.1(prisma@6.17.1(typescript@5.3.3))(typescript@5.3.3)':
|
||||
optionalDependencies:
|
||||
prisma: 6.17.1(typescript@5.3.3)
|
||||
typescript: 5.3.3
|
||||
|
||||
'@prisma/config@6.17.1':
|
||||
dependencies:
|
||||
c12: 3.1.0
|
||||
deepmerge-ts: 7.1.5
|
||||
effect: 3.16.12
|
||||
empathic: 2.0.0
|
||||
transitivePeerDependencies:
|
||||
- magicast
|
||||
|
||||
'@prisma/debug@6.17.1': {}
|
||||
|
||||
'@prisma/engines-version@6.17.1-1.272a37d34178c2894197e17273bf937f25acdeac': {}
|
||||
|
||||
'@prisma/engines@6.17.1':
|
||||
dependencies:
|
||||
'@prisma/debug': 6.17.1
|
||||
'@prisma/engines-version': 6.17.1-1.272a37d34178c2894197e17273bf937f25acdeac
|
||||
'@prisma/fetch-engine': 6.17.1
|
||||
'@prisma/get-platform': 6.17.1
|
||||
|
||||
'@prisma/fetch-engine@6.17.1':
|
||||
dependencies:
|
||||
'@prisma/debug': 6.17.1
|
||||
'@prisma/engines-version': 6.17.1-1.272a37d34178c2894197e17273bf937f25acdeac
|
||||
'@prisma/get-platform': 6.17.1
|
||||
|
||||
'@prisma/get-platform@6.17.1':
|
||||
dependencies:
|
||||
'@prisma/debug': 6.17.1
|
||||
|
||||
'@radix-ui/number@1.1.1': {}
|
||||
|
||||
'@radix-ui/primitive@1.0.1':
|
||||
@@ -3889,6 +3970,8 @@ snapshots:
|
||||
|
||||
'@rushstack/eslint-patch@1.14.0': {}
|
||||
|
||||
'@standard-schema/spec@1.0.0': {}
|
||||
|
||||
'@swc/counter@0.1.3': {}
|
||||
|
||||
'@swc/helpers@0.5.15':
|
||||
@@ -3908,19 +3991,6 @@ snapshots:
|
||||
|
||||
'@types/json5@0.0.29': {}
|
||||
|
||||
'@types/mongoose@5.11.97':
|
||||
dependencies:
|
||||
mongoose: 8.1.0
|
||||
transitivePeerDependencies:
|
||||
- '@aws-sdk/credential-providers'
|
||||
- '@mongodb-js/zstd'
|
||||
- gcp-metadata
|
||||
- kerberos
|
||||
- mongodb-client-encryption
|
||||
- snappy
|
||||
- socks
|
||||
- supports-color
|
||||
|
||||
'@types/node@24.7.2':
|
||||
dependencies:
|
||||
undici-types: 7.14.0
|
||||
@@ -3941,12 +4011,6 @@ snapshots:
|
||||
|
||||
'@types/semver@7.7.1': {}
|
||||
|
||||
'@types/webidl-conversions@7.0.3': {}
|
||||
|
||||
'@types/whatwg-url@11.0.5':
|
||||
dependencies:
|
||||
'@types/webidl-conversions': 7.0.3
|
||||
|
||||
'@typescript-eslint/eslint-plugin@8.46.1(@typescript-eslint/parser@6.21.0(eslint@8.56.0)(typescript@5.3.3))(eslint@8.56.0)(typescript@5.3.3)':
|
||||
dependencies:
|
||||
'@eslint-community/regexpp': 4.12.1
|
||||
@@ -4338,12 +4402,25 @@ snapshots:
|
||||
node-releases: 2.0.23
|
||||
update-browserslist-db: 1.1.3(browserslist@4.26.3)
|
||||
|
||||
bson@6.10.4: {}
|
||||
|
||||
busboy@1.6.0:
|
||||
dependencies:
|
||||
streamsearch: 1.1.0
|
||||
|
||||
c12@3.1.0:
|
||||
dependencies:
|
||||
chokidar: 4.0.3
|
||||
confbox: 0.2.2
|
||||
defu: 6.1.4
|
||||
dotenv: 16.6.1
|
||||
exsolve: 1.0.7
|
||||
giget: 2.0.0
|
||||
jiti: 2.6.1
|
||||
ohash: 2.0.11
|
||||
pathe: 2.0.3
|
||||
perfect-debounce: 1.0.0
|
||||
pkg-types: 2.3.0
|
||||
rc9: 2.1.2
|
||||
|
||||
call-bind-apply-helpers@1.0.2:
|
||||
dependencies:
|
||||
es-errors: 1.3.0
|
||||
@@ -4384,6 +4461,14 @@ snapshots:
|
||||
optionalDependencies:
|
||||
fsevents: 2.3.3
|
||||
|
||||
chokidar@4.0.3:
|
||||
dependencies:
|
||||
readdirp: 4.1.2
|
||||
|
||||
citty@0.1.6:
|
||||
dependencies:
|
||||
consola: 3.4.2
|
||||
|
||||
class-variance-authority@0.7.1:
|
||||
dependencies:
|
||||
clsx: 2.1.1
|
||||
@@ -4412,6 +4497,10 @@ snapshots:
|
||||
|
||||
concat-map@0.0.1: {}
|
||||
|
||||
confbox@0.2.2: {}
|
||||
|
||||
consola@3.4.2: {}
|
||||
|
||||
cross-spawn@7.0.6:
|
||||
dependencies:
|
||||
path-key: 3.1.1
|
||||
@@ -4452,6 +4541,8 @@ snapshots:
|
||||
|
||||
deep-is@0.1.4: {}
|
||||
|
||||
deepmerge-ts@7.1.5: {}
|
||||
|
||||
define-data-property@1.1.4:
|
||||
dependencies:
|
||||
es-define-property: 1.0.1
|
||||
@@ -4464,6 +4555,10 @@ snapshots:
|
||||
has-property-descriptors: 1.0.2
|
||||
object-keys: 1.1.1
|
||||
|
||||
defu@6.1.4: {}
|
||||
|
||||
destr@2.0.5: {}
|
||||
|
||||
detect-libc@2.1.2: {}
|
||||
|
||||
detect-node-es@1.1.0: {}
|
||||
@@ -4484,6 +4579,8 @@ snapshots:
|
||||
dependencies:
|
||||
esutils: 2.0.3
|
||||
|
||||
dotenv@16.6.1: {}
|
||||
|
||||
dunder-proto@1.0.1:
|
||||
dependencies:
|
||||
call-bind-apply-helpers: 1.0.2
|
||||
@@ -4492,12 +4589,19 @@ snapshots:
|
||||
|
||||
eastasianwidth@0.2.0: {}
|
||||
|
||||
effect@3.16.12:
|
||||
dependencies:
|
||||
'@standard-schema/spec': 1.0.0
|
||||
fast-check: 3.23.2
|
||||
|
||||
electron-to-chromium@1.5.235: {}
|
||||
|
||||
emoji-regex@8.0.0: {}
|
||||
|
||||
emoji-regex@9.2.2: {}
|
||||
|
||||
empathic@2.0.0: {}
|
||||
|
||||
es-abstract@1.24.0:
|
||||
dependencies:
|
||||
array-buffer-byte-length: 1.0.2
|
||||
@@ -4829,6 +4933,12 @@ snapshots:
|
||||
|
||||
esutils@2.0.3: {}
|
||||
|
||||
exsolve@1.0.7: {}
|
||||
|
||||
fast-check@3.23.2:
|
||||
dependencies:
|
||||
pure-rand: 6.1.0
|
||||
|
||||
fast-deep-equal@3.1.3: {}
|
||||
|
||||
fast-glob@3.3.1:
|
||||
@@ -4949,6 +5059,15 @@ snapshots:
|
||||
dependencies:
|
||||
resolve-pkg-maps: 1.0.0
|
||||
|
||||
giget@2.0.0:
|
||||
dependencies:
|
||||
citty: 0.1.6
|
||||
consola: 3.4.2
|
||||
defu: 6.1.4
|
||||
node-fetch-native: 1.6.7
|
||||
nypm: 0.6.2
|
||||
pathe: 2.0.3
|
||||
|
||||
glob-parent@5.1.2:
|
||||
dependencies:
|
||||
is-glob: 4.0.3
|
||||
@@ -5200,6 +5319,8 @@ snapshots:
|
||||
|
||||
jiti@1.21.7: {}
|
||||
|
||||
jiti@2.6.1: {}
|
||||
|
||||
jose@6.1.0: {}
|
||||
|
||||
js-tokens@4.0.0: {}
|
||||
@@ -5227,8 +5348,6 @@ snapshots:
|
||||
object.assign: 4.1.7
|
||||
object.values: 1.2.1
|
||||
|
||||
kareem@2.5.1: {}
|
||||
|
||||
keyv@4.5.4:
|
||||
dependencies:
|
||||
json-buffer: 3.0.1
|
||||
@@ -5268,8 +5387,6 @@ snapshots:
|
||||
|
||||
math-intrinsics@1.1.0: {}
|
||||
|
||||
memory-pager@1.5.0: {}
|
||||
|
||||
merge2@1.4.1: {}
|
||||
|
||||
micromatch@4.0.8:
|
||||
@@ -5293,44 +5410,6 @@ snapshots:
|
||||
|
||||
minipass@7.1.2: {}
|
||||
|
||||
mongodb-connection-string-url@3.0.2:
|
||||
dependencies:
|
||||
'@types/whatwg-url': 11.0.5
|
||||
whatwg-url: 14.2.0
|
||||
|
||||
mongodb@6.3.0:
|
||||
dependencies:
|
||||
'@mongodb-js/saslprep': 1.3.1
|
||||
bson: 6.10.4
|
||||
mongodb-connection-string-url: 3.0.2
|
||||
|
||||
mongoose@8.1.0:
|
||||
dependencies:
|
||||
bson: 6.10.4
|
||||
kareem: 2.5.1
|
||||
mongodb: 6.3.0
|
||||
mpath: 0.9.0
|
||||
mquery: 5.0.0
|
||||
ms: 2.1.3
|
||||
sift: 16.0.1
|
||||
transitivePeerDependencies:
|
||||
- '@aws-sdk/credential-providers'
|
||||
- '@mongodb-js/zstd'
|
||||
- gcp-metadata
|
||||
- kerberos
|
||||
- mongodb-client-encryption
|
||||
- snappy
|
||||
- socks
|
||||
- supports-color
|
||||
|
||||
mpath@0.9.0: {}
|
||||
|
||||
mquery@5.0.0:
|
||||
dependencies:
|
||||
debug: 4.4.3
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
ms@2.1.3: {}
|
||||
|
||||
mz@2.7.0:
|
||||
@@ -5384,12 +5463,22 @@ snapshots:
|
||||
- '@babel/core'
|
||||
- babel-plugin-macros
|
||||
|
||||
node-fetch-native@1.6.7: {}
|
||||
|
||||
node-releases@2.0.23: {}
|
||||
|
||||
normalize-path@3.0.0: {}
|
||||
|
||||
normalize-range@0.1.2: {}
|
||||
|
||||
nypm@0.6.2:
|
||||
dependencies:
|
||||
citty: 0.1.6
|
||||
consola: 3.4.2
|
||||
pathe: 2.0.3
|
||||
pkg-types: 2.3.0
|
||||
tinyexec: 1.0.1
|
||||
|
||||
oauth4webapi@3.8.2: {}
|
||||
|
||||
object-assign@4.1.1: {}
|
||||
@@ -5436,6 +5525,8 @@ snapshots:
|
||||
define-properties: 1.2.1
|
||||
es-object-atoms: 1.1.1
|
||||
|
||||
ohash@2.0.11: {}
|
||||
|
||||
once@1.4.0:
|
||||
dependencies:
|
||||
wrappy: 1.0.2
|
||||
@@ -5484,6 +5575,10 @@ snapshots:
|
||||
|
||||
path-type@4.0.0: {}
|
||||
|
||||
pathe@2.0.3: {}
|
||||
|
||||
perfect-debounce@1.0.0: {}
|
||||
|
||||
picocolors@1.1.1: {}
|
||||
|
||||
picomatch@2.3.1: {}
|
||||
@@ -5494,6 +5589,12 @@ snapshots:
|
||||
|
||||
pirates@4.0.7: {}
|
||||
|
||||
pkg-types@2.3.0:
|
||||
dependencies:
|
||||
confbox: 0.2.2
|
||||
exsolve: 1.0.7
|
||||
pathe: 2.0.3
|
||||
|
||||
possible-typed-array-names@1.1.0: {}
|
||||
|
||||
postcss-import@15.1.0(postcss@8.4.33):
|
||||
@@ -5547,6 +5648,15 @@ snapshots:
|
||||
|
||||
prelude-ls@1.2.1: {}
|
||||
|
||||
prisma@6.17.1(typescript@5.3.3):
|
||||
dependencies:
|
||||
'@prisma/config': 6.17.1
|
||||
'@prisma/engines': 6.17.1
|
||||
optionalDependencies:
|
||||
typescript: 5.3.3
|
||||
transitivePeerDependencies:
|
||||
- magicast
|
||||
|
||||
prop-types@15.8.1:
|
||||
dependencies:
|
||||
loose-envify: 1.4.0
|
||||
@@ -5555,8 +5665,15 @@ snapshots:
|
||||
|
||||
punycode@2.3.1: {}
|
||||
|
||||
pure-rand@6.1.0: {}
|
||||
|
||||
queue-microtask@1.2.3: {}
|
||||
|
||||
rc9@2.1.2:
|
||||
dependencies:
|
||||
defu: 6.1.4
|
||||
destr: 2.0.5
|
||||
|
||||
react-dom@18.2.0(react@18.2.0):
|
||||
dependencies:
|
||||
loose-envify: 1.4.0
|
||||
@@ -5630,6 +5747,8 @@ snapshots:
|
||||
dependencies:
|
||||
picomatch: 2.3.1
|
||||
|
||||
readdirp@4.1.2: {}
|
||||
|
||||
reflect.getprototypeof@1.0.10:
|
||||
dependencies:
|
||||
call-bind: 1.0.8
|
||||
@@ -5812,8 +5931,6 @@ snapshots:
|
||||
side-channel-map: 1.0.1
|
||||
side-channel-weakmap: 1.0.2
|
||||
|
||||
sift@16.0.1: {}
|
||||
|
||||
signal-exit@4.1.0: {}
|
||||
|
||||
simple-swizzle@0.2.4:
|
||||
@@ -5824,10 +5941,6 @@ snapshots:
|
||||
|
||||
source-map-js@1.2.1: {}
|
||||
|
||||
sparse-bitfield@3.0.3:
|
||||
dependencies:
|
||||
memory-pager: 1.5.0
|
||||
|
||||
stable-hash@0.0.5: {}
|
||||
|
||||
stop-iteration-iterator@1.1.0:
|
||||
@@ -5975,6 +6088,8 @@ snapshots:
|
||||
dependencies:
|
||||
any-promise: 1.3.0
|
||||
|
||||
tinyexec@1.0.1: {}
|
||||
|
||||
tinyglobby@0.2.15:
|
||||
dependencies:
|
||||
fdir: 6.5.0(picomatch@4.0.3)
|
||||
@@ -5984,10 +6099,6 @@ snapshots:
|
||||
dependencies:
|
||||
is-number: 7.0.0
|
||||
|
||||
tr46@5.1.1:
|
||||
dependencies:
|
||||
punycode: 2.3.1
|
||||
|
||||
ts-api-utils@1.4.3(typescript@5.3.3):
|
||||
dependencies:
|
||||
typescript: 5.3.3
|
||||
@@ -6119,13 +6230,6 @@ snapshots:
|
||||
|
||||
void-elements@3.1.0: {}
|
||||
|
||||
webidl-conversions@7.0.0: {}
|
||||
|
||||
whatwg-url@14.2.0:
|
||||
dependencies:
|
||||
tr46: 5.1.1
|
||||
webidl-conversions: 7.0.0
|
||||
|
||||
which-boxed-primitive@1.1.1:
|
||||
dependencies:
|
||||
is-bigint: 1.1.0
|
||||
|
||||
91
prisma/schema.prisma
Normal file
91
prisma/schema.prisma
Normal file
@@ -0,0 +1,91 @@
|
||||
// This is your Prisma schema file,
|
||||
// learn more about it in the docs: https://pris.ly/d/prisma-schema
|
||||
|
||||
generator client {
|
||||
provider = "prisma-client-js"
|
||||
}
|
||||
|
||||
datasource db {
|
||||
provider = "mongodb"
|
||||
url = env("MONGODB_URI")
|
||||
}
|
||||
|
||||
model User {
|
||||
id String @id @default(auto()) @map("_id") @db.ObjectId
|
||||
email String @unique
|
||||
password String
|
||||
roles String[] @default(["ROLE_USER"])
|
||||
authenticated Boolean @default(true)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
// Relations
|
||||
config KomgaConfig?
|
||||
ttlConfig TTLConfig?
|
||||
preferences Preferences?
|
||||
favorites Favorite[]
|
||||
|
||||
@@map("users")
|
||||
}
|
||||
|
||||
model KomgaConfig {
|
||||
id String @id @default(auto()) @map("_id") @db.ObjectId
|
||||
userId String @unique
|
||||
url String
|
||||
username String
|
||||
authHeader String
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@map("komgaconfigs")
|
||||
}
|
||||
|
||||
model TTLConfig {
|
||||
id String @id @default(auto()) @map("_id") @db.ObjectId
|
||||
userId String @unique
|
||||
defaultTTL Int @default(5)
|
||||
homeTTL Int @default(5)
|
||||
librariesTTL Int @default(1440)
|
||||
seriesTTL Int @default(5)
|
||||
booksTTL Int @default(5)
|
||||
imagesTTL Int @default(1440)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@map("ttlconfigs")
|
||||
}
|
||||
|
||||
model Preferences {
|
||||
id String @id @default(auto()) @map("_id") @db.ObjectId
|
||||
userId String @unique
|
||||
showThumbnails Boolean @default(true)
|
||||
cacheMode String @default("memory") // "memory" | "file"
|
||||
showOnlyUnread Boolean @default(false)
|
||||
debug Boolean @default(false)
|
||||
displayMode Json @default("{\"compact\": false, \"itemsPerPage\": 20}")
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@map("preferences")
|
||||
}
|
||||
|
||||
model Favorite {
|
||||
id String @id @default(auto()) @map("_id") @db.ObjectId
|
||||
userId String
|
||||
seriesId String
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@unique([userId, seriesId])
|
||||
@@index([userId])
|
||||
@@map("favorites")
|
||||
}
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
import mongoose from "mongoose";
|
||||
|
||||
const configSchema = new mongoose.Schema(
|
||||
{
|
||||
userId: {
|
||||
type: String,
|
||||
required: true,
|
||||
unique: true,
|
||||
},
|
||||
url: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
username: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
authHeader: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
timestamps: true,
|
||||
}
|
||||
);
|
||||
|
||||
// Middleware pour mettre à jour le champ updatedAt avant la sauvegarde
|
||||
configSchema.pre("save", function (next) {
|
||||
this.updatedAt = new Date();
|
||||
next();
|
||||
});
|
||||
|
||||
export const KomgaConfig =
|
||||
mongoose.models.KomgaConfig || mongoose.model("KomgaConfig", configSchema);
|
||||
@@ -1,23 +0,0 @@
|
||||
import mongoose from "mongoose";
|
||||
|
||||
const favoriteSchema = new mongoose.Schema(
|
||||
{
|
||||
userId: {
|
||||
type: String,
|
||||
required: true,
|
||||
index: true,
|
||||
},
|
||||
seriesId: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
timestamps: true,
|
||||
}
|
||||
);
|
||||
|
||||
// Index composé pour s'assurer qu'un utilisateur ne peut pas avoir deux fois le même favori
|
||||
favoriteSchema.index({ userId: 1, seriesId: 1 }, { unique: true });
|
||||
|
||||
export const FavoriteModel = mongoose.models.Favorite || mongoose.model("Favorite", favoriteSchema);
|
||||
@@ -1,94 +0,0 @@
|
||||
import mongoose from "mongoose";
|
||||
|
||||
const preferencesSchema = new mongoose.Schema(
|
||||
{
|
||||
userId: {
|
||||
type: String,
|
||||
required: true,
|
||||
unique: true,
|
||||
},
|
||||
showThumbnails: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
cacheMode: {
|
||||
type: String,
|
||||
enum: ["memory", "file"],
|
||||
default: "memory",
|
||||
},
|
||||
showOnlyUnread: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
required: false,
|
||||
},
|
||||
debug: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
required: false,
|
||||
},
|
||||
displayMode: {
|
||||
compact: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
itemsPerPage: {
|
||||
type: Number,
|
||||
default: 20,
|
||||
enum: [20, 50, 100],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
timestamps: true,
|
||||
strict: true,
|
||||
toObject: {
|
||||
transform: function (doc, ret) {
|
||||
// Force la conversion en booléen
|
||||
ret.showOnlyUnread = Boolean(ret.showOnlyUnread);
|
||||
ret.debug = Boolean(ret.debug);
|
||||
ret.displayMode = ret.displayMode || { compact: false, itemsPerPage: 20 };
|
||||
ret.displayMode.compact = Boolean(ret.displayMode.compact);
|
||||
return ret;
|
||||
},
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
// Middleware pour s'assurer que les booléens sont toujours des booléens
|
||||
preferencesSchema.pre("save", function (next) {
|
||||
if (this.showOnlyUnread === undefined) {
|
||||
this.showOnlyUnread = false;
|
||||
}
|
||||
if (this.debug === undefined) {
|
||||
this.debug = false;
|
||||
}
|
||||
if (!this.displayMode) {
|
||||
this.displayMode = { compact: false, itemsPerPage: 20 };
|
||||
}
|
||||
this.showOnlyUnread = Boolean(this.showOnlyUnread);
|
||||
this.debug = Boolean(this.debug);
|
||||
this.displayMode.compact = Boolean(this.displayMode.compact);
|
||||
next();
|
||||
});
|
||||
|
||||
preferencesSchema.pre("findOneAndUpdate", function (next) {
|
||||
const update = this.getUpdate() as mongoose.UpdateQuery<any>;
|
||||
if (update && "$set" in update && update.$set && typeof update.$set === "object") {
|
||||
if ("showOnlyUnread" in update.$set) {
|
||||
update.$set.showOnlyUnread = Boolean(update.$set.showOnlyUnread);
|
||||
}
|
||||
if ("debug" in update.$set) {
|
||||
update.$set.debug = Boolean(update.$set.debug);
|
||||
}
|
||||
if ("displayMode" in update.$set) {
|
||||
update.$set.displayMode = {
|
||||
compact: Boolean(update.$set.displayMode?.compact),
|
||||
itemsPerPage: update.$set.displayMode?.itemsPerPage || 20,
|
||||
};
|
||||
}
|
||||
}
|
||||
next();
|
||||
});
|
||||
|
||||
export const PreferencesModel =
|
||||
mongoose.models.Preferences || mongoose.model("Preferences", preferencesSchema);
|
||||
@@ -1,46 +0,0 @@
|
||||
import mongoose from "mongoose";
|
||||
|
||||
const ttlConfigSchema = new mongoose.Schema(
|
||||
{
|
||||
userId: {
|
||||
type: String,
|
||||
required: true,
|
||||
unique: true,
|
||||
},
|
||||
defaultTTL: {
|
||||
type: Number,
|
||||
default: 5,
|
||||
},
|
||||
homeTTL: {
|
||||
type: Number,
|
||||
default: 5,
|
||||
},
|
||||
librariesTTL: {
|
||||
type: Number,
|
||||
default: 1440,
|
||||
},
|
||||
seriesTTL: {
|
||||
type: Number,
|
||||
default: 5,
|
||||
},
|
||||
booksTTL: {
|
||||
type: Number,
|
||||
default: 5,
|
||||
},
|
||||
imagesTTL: {
|
||||
type: Number,
|
||||
default: 1440,
|
||||
},
|
||||
},
|
||||
{
|
||||
timestamps: true,
|
||||
}
|
||||
);
|
||||
|
||||
// Middleware pour mettre à jour le champ updatedAt avant la sauvegarde
|
||||
ttlConfigSchema.pre("save", function (next) {
|
||||
this.updatedAt = new Date();
|
||||
next();
|
||||
});
|
||||
|
||||
export const TTLConfig = mongoose.models.TTLConfig || mongoose.model("TTLConfig", ttlConfigSchema);
|
||||
@@ -1,36 +0,0 @@
|
||||
import mongoose from "mongoose";
|
||||
|
||||
const userSchema = new mongoose.Schema(
|
||||
{
|
||||
email: {
|
||||
type: String,
|
||||
required: true,
|
||||
unique: true,
|
||||
lowercase: true,
|
||||
trim: true,
|
||||
},
|
||||
password: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
roles: {
|
||||
type: [String],
|
||||
default: ["ROLE_USER"],
|
||||
},
|
||||
authenticated: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
timestamps: true,
|
||||
}
|
||||
);
|
||||
|
||||
// Middleware pour mettre à jour le champ updatedAt avant la sauvegarde
|
||||
userSchema.pre("save", function (next) {
|
||||
this.updatedAt = new Date();
|
||||
next();
|
||||
});
|
||||
|
||||
export const UserModel = mongoose.models.User || mongoose.model("User", userSchema);
|
||||
@@ -1,52 +0,0 @@
|
||||
import mongoose from "mongoose";
|
||||
import { ERROR_CODES } from "../constants/errorCodes";
|
||||
import { AppError } from "../utils/errors";
|
||||
|
||||
const MONGODB_URI = process.env.MONGODB_URI;
|
||||
|
||||
if (!MONGODB_URI) {
|
||||
throw new AppError(ERROR_CODES.MONGODB.MISSING_URI);
|
||||
}
|
||||
|
||||
interface MongooseCache {
|
||||
conn: typeof mongoose | null;
|
||||
promise: Promise<typeof mongoose> | null;
|
||||
}
|
||||
|
||||
declare global {
|
||||
var mongoose: MongooseCache | undefined;
|
||||
}
|
||||
|
||||
let cached: MongooseCache = global.mongoose || { conn: null, promise: null };
|
||||
|
||||
if (!global.mongoose) {
|
||||
global.mongoose = { conn: null, promise: null };
|
||||
}
|
||||
|
||||
async function connectDB(): Promise<typeof mongoose> {
|
||||
if (cached.conn) {
|
||||
return cached.conn;
|
||||
}
|
||||
|
||||
if (!cached.promise) {
|
||||
const opts = {
|
||||
bufferCommands: false,
|
||||
};
|
||||
|
||||
cached.promise = mongoose.connect(MONGODB_URI!, opts).then((mongoose) => {
|
||||
return mongoose;
|
||||
});
|
||||
}
|
||||
|
||||
try {
|
||||
cached.conn = await cached.promise;
|
||||
} catch (e) {
|
||||
console.error("Error connecting to MongoDB:", e);
|
||||
cached.promise = null;
|
||||
throw new AppError(ERROR_CODES.MONGODB.CONNECTION_FAILED, {}, e);
|
||||
}
|
||||
|
||||
return cached.conn;
|
||||
}
|
||||
|
||||
export default connectDB;
|
||||
14
src/lib/prisma.ts
Normal file
14
src/lib/prisma.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import { PrismaClient } from "@prisma/client";
|
||||
|
||||
declare global {
|
||||
var prisma: PrismaClient | undefined;
|
||||
}
|
||||
|
||||
const prisma = global.prisma || new PrismaClient();
|
||||
|
||||
if (process.env.NODE_ENV !== "production") {
|
||||
global.prisma = prisma;
|
||||
}
|
||||
|
||||
export default prisma;
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import connectDB from "@/lib/mongodb";
|
||||
import { UserModel } from "@/lib/models/user.model";
|
||||
import prisma from "@/lib/prisma";
|
||||
import bcrypt from "bcryptjs";
|
||||
import { ERROR_CODES } from "../../constants/errorCodes";
|
||||
import { AppError } from "../../utils/errors";
|
||||
@@ -15,15 +14,16 @@ export class AuthServerService {
|
||||
private static readonly SALT_ROUNDS = 10;
|
||||
|
||||
static async registerUser(email: string, password: string): Promise<UserData> {
|
||||
await connectDB();
|
||||
|
||||
//check if password is strong
|
||||
if (!AuthServerService.isPasswordStrong(password)) {
|
||||
throw new AppError(ERROR_CODES.AUTH.PASSWORD_NOT_STRONG);
|
||||
}
|
||||
|
||||
// Check if user already exists
|
||||
const existingUser = await UserModel.findOne({ email: email.toLowerCase() });
|
||||
const existingUser = await prisma.user.findUnique({
|
||||
where: { email: email.toLowerCase() },
|
||||
});
|
||||
|
||||
if (existingUser) {
|
||||
throw new AppError(ERROR_CODES.AUTH.EMAIL_EXISTS);
|
||||
}
|
||||
@@ -32,15 +32,17 @@ export class AuthServerService {
|
||||
const hashedPassword = await bcrypt.hash(password, this.SALT_ROUNDS);
|
||||
|
||||
// Create new user
|
||||
const user = await UserModel.create({
|
||||
email: email.toLowerCase(),
|
||||
password: hashedPassword,
|
||||
roles: ["ROLE_USER"],
|
||||
authenticated: true,
|
||||
const user = await prisma.user.create({
|
||||
data: {
|
||||
email: email.toLowerCase(),
|
||||
password: hashedPassword,
|
||||
roles: ["ROLE_USER"],
|
||||
authenticated: true,
|
||||
},
|
||||
});
|
||||
|
||||
const userData: UserData = {
|
||||
id: user._id.toString(),
|
||||
id: user.id,
|
||||
email: user.email,
|
||||
roles: user.roles,
|
||||
authenticated: true,
|
||||
@@ -67,9 +69,9 @@ export class AuthServerService {
|
||||
}
|
||||
|
||||
static async loginUser(email: string, password: string): Promise<UserData> {
|
||||
await connectDB();
|
||||
|
||||
const user = await UserModel.findOne({ email: email.toLowerCase() });
|
||||
const user = await prisma.user.findUnique({
|
||||
where: { email: email.toLowerCase() },
|
||||
});
|
||||
|
||||
if (!user) {
|
||||
throw new AppError(ERROR_CODES.AUTH.INVALID_CREDENTIALS);
|
||||
@@ -82,7 +84,7 @@ export class AuthServerService {
|
||||
}
|
||||
|
||||
const userData: UserData = {
|
||||
id: user._id.toString(),
|
||||
id: user.id,
|
||||
email: user.email,
|
||||
roles: user.roles,
|
||||
authenticated: true,
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
import connectDB from "@/lib/mongodb";
|
||||
import { KomgaConfig as KomgaConfigModel } from "@/lib/models/config.model";
|
||||
import { TTLConfig as TTLConfigModel } from "@/lib/models/ttl-config.model";
|
||||
import prisma from "@/lib/prisma";
|
||||
import { DebugService } from "./debug.service";
|
||||
import { getCurrentUser } from "../auth-utils";
|
||||
import { ERROR_CODES } from "../../constants/errorCodes";
|
||||
@@ -19,28 +17,27 @@ export class ConfigDBService {
|
||||
static async saveConfig(data: KomgaConfigData): Promise<KomgaConfig> {
|
||||
try {
|
||||
const user: User | null = await this.getCurrentUser();
|
||||
await connectDB();
|
||||
|
||||
const authHeader: string = Buffer.from(`${data.username}:${data.password}`).toString(
|
||||
"base64"
|
||||
);
|
||||
|
||||
const config: KomgaConfig | null = await KomgaConfigModel.findOneAndUpdate(
|
||||
{ userId: user.id },
|
||||
{
|
||||
const config = await prisma.komgaConfig.upsert({
|
||||
where: { userId: user.id },
|
||||
update: {
|
||||
url: data.url,
|
||||
username: data.username,
|
||||
authHeader,
|
||||
},
|
||||
create: {
|
||||
userId: user.id,
|
||||
url: data.url,
|
||||
username: data.username,
|
||||
// password: data.password,
|
||||
authHeader,
|
||||
},
|
||||
{ upsert: true, new: true }
|
||||
);
|
||||
if (!config) {
|
||||
throw new AppError(ERROR_CODES.CONFIG.SAVE_ERROR);
|
||||
}
|
||||
});
|
||||
|
||||
return config;
|
||||
return config as KomgaConfig;
|
||||
} catch (error) {
|
||||
if (error instanceof AppError) {
|
||||
throw error;
|
||||
@@ -52,11 +49,12 @@ export class ConfigDBService {
|
||||
static async getConfig(): Promise<KomgaConfig | null> {
|
||||
try {
|
||||
const user: User | null = await this.getCurrentUser();
|
||||
await connectDB();
|
||||
|
||||
return DebugService.measureMongoOperation("getConfig", async () => {
|
||||
const config: KomgaConfig | null = await KomgaConfigModel.findOne({ userId: user.id });
|
||||
return config;
|
||||
const config = await prisma.komgaConfig.findUnique({
|
||||
where: { userId: user.id },
|
||||
});
|
||||
return config as KomgaConfig | null;
|
||||
});
|
||||
} catch (error) {
|
||||
if (error instanceof AppError) {
|
||||
@@ -69,11 +67,12 @@ export class ConfigDBService {
|
||||
static async getTTLConfig(): Promise<TTLConfig | null> {
|
||||
try {
|
||||
const user: User | null = await this.getCurrentUser();
|
||||
await connectDB();
|
||||
|
||||
return DebugService.measureMongoOperation("getTTLConfig", async () => {
|
||||
const config: TTLConfig | null = await TTLConfigModel.findOne({ userId: user.id });
|
||||
return config;
|
||||
const config = await prisma.tTLConfig.findUnique({
|
||||
where: { userId: user.id },
|
||||
});
|
||||
return config as TTLConfig | null;
|
||||
});
|
||||
} catch (error) {
|
||||
if (error instanceof AppError) {
|
||||
@@ -86,23 +85,30 @@ export class ConfigDBService {
|
||||
static async saveTTLConfig(data: TTLConfigData): Promise<TTLConfig> {
|
||||
try {
|
||||
const user: User | null = await this.getCurrentUser();
|
||||
await connectDB();
|
||||
|
||||
return DebugService.measureMongoOperation("saveTTLConfig", async () => {
|
||||
const config: TTLConfig | null = await TTLConfigModel.findOneAndUpdate(
|
||||
{ userId: user.id },
|
||||
{
|
||||
userId: user.id,
|
||||
...data,
|
||||
const config = await prisma.tTLConfig.upsert({
|
||||
where: { userId: user.id },
|
||||
update: {
|
||||
defaultTTL: data.defaultTTL,
|
||||
homeTTL: data.homeTTL,
|
||||
librariesTTL: data.librariesTTL,
|
||||
seriesTTL: data.seriesTTL,
|
||||
booksTTL: data.booksTTL,
|
||||
imagesTTL: data.imagesTTL,
|
||||
},
|
||||
{ upsert: true, new: true }
|
||||
);
|
||||
create: {
|
||||
userId: user.id,
|
||||
defaultTTL: data.defaultTTL,
|
||||
homeTTL: data.homeTTL,
|
||||
librariesTTL: data.librariesTTL,
|
||||
seriesTTL: data.seriesTTL,
|
||||
booksTTL: data.booksTTL,
|
||||
imagesTTL: data.imagesTTL,
|
||||
},
|
||||
});
|
||||
|
||||
if (!config) {
|
||||
throw new AppError(ERROR_CODES.CONFIG.TTL_SAVE_ERROR);
|
||||
}
|
||||
|
||||
return config;
|
||||
return config as TTLConfig;
|
||||
});
|
||||
} catch (error) {
|
||||
if (error instanceof AppError) {
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import connectDB from "@/lib/mongodb";
|
||||
import { FavoriteModel } from "@/lib/models/favorite.model";
|
||||
import prisma from "@/lib/prisma";
|
||||
import { DebugService } from "./debug.service";
|
||||
import { getCurrentUser } from "../auth-utils";
|
||||
import { ERROR_CODES } from "../../constants/errorCodes";
|
||||
@@ -30,12 +29,13 @@ export class FavoriteService {
|
||||
static async isFavorite(seriesId: string): Promise<boolean> {
|
||||
try {
|
||||
const user = await this.getCurrentUser();
|
||||
await connectDB();
|
||||
|
||||
return DebugService.measureMongoOperation("isFavorite", async () => {
|
||||
const favorite = await FavoriteModel.findOne({
|
||||
userId: user.id,
|
||||
seriesId: seriesId,
|
||||
const favorite = await prisma.favorite.findFirst({
|
||||
where: {
|
||||
userId: user.id,
|
||||
seriesId: seriesId,
|
||||
},
|
||||
});
|
||||
return !!favorite;
|
||||
});
|
||||
@@ -51,14 +51,21 @@ export class FavoriteService {
|
||||
static async addToFavorites(seriesId: string): Promise<void> {
|
||||
try {
|
||||
const user = await this.getCurrentUser();
|
||||
await connectDB();
|
||||
|
||||
await DebugService.measureMongoOperation("addToFavorites", async () => {
|
||||
await FavoriteModel.findOneAndUpdate(
|
||||
{ userId: user.id, seriesId },
|
||||
{ userId: user.id, seriesId },
|
||||
{ upsert: true }
|
||||
);
|
||||
await prisma.favorite.upsert({
|
||||
where: {
|
||||
userId_seriesId: {
|
||||
userId: user.id,
|
||||
seriesId,
|
||||
},
|
||||
},
|
||||
update: {},
|
||||
create: {
|
||||
userId: user.id,
|
||||
seriesId,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
this.dispatchFavoritesChanged();
|
||||
@@ -73,12 +80,13 @@ export class FavoriteService {
|
||||
static async removeFromFavorites(seriesId: string): Promise<void> {
|
||||
try {
|
||||
const user = await this.getCurrentUser();
|
||||
await connectDB();
|
||||
|
||||
await DebugService.measureMongoOperation("removeFromFavorites", async () => {
|
||||
await FavoriteModel.findOneAndDelete({
|
||||
userId: user.id,
|
||||
seriesId,
|
||||
await prisma.favorite.deleteMany({
|
||||
where: {
|
||||
userId: user.id,
|
||||
seriesId,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
@@ -93,35 +101,48 @@ export class FavoriteService {
|
||||
*/
|
||||
static async getAllFavoriteIds(): Promise<string[]> {
|
||||
const user = await this.getCurrentUser();
|
||||
await connectDB();
|
||||
|
||||
return DebugService.measureMongoOperation("getAllFavoriteIds", async () => {
|
||||
const favorites = await FavoriteModel.find({ userId: user.id });
|
||||
const favorites = await prisma.favorite.findMany({
|
||||
where: { userId: user.id },
|
||||
select: { seriesId: true },
|
||||
});
|
||||
return favorites.map((favorite) => favorite.seriesId);
|
||||
});
|
||||
}
|
||||
|
||||
static async addFavorite(seriesId: string) {
|
||||
const user = await this.getCurrentUser();
|
||||
await connectDB();
|
||||
|
||||
return DebugService.measureMongoOperation("addFavorite", async () => {
|
||||
const favorite = await FavoriteModel.findOneAndUpdate(
|
||||
{ userId: user.id, seriesId },
|
||||
{ userId: user.id, seriesId },
|
||||
{ upsert: true, new: true }
|
||||
);
|
||||
const favorite = await prisma.favorite.upsert({
|
||||
where: {
|
||||
userId_seriesId: {
|
||||
userId: user.id,
|
||||
seriesId,
|
||||
},
|
||||
},
|
||||
update: {},
|
||||
create: {
|
||||
userId: user.id,
|
||||
seriesId,
|
||||
},
|
||||
});
|
||||
return favorite;
|
||||
});
|
||||
}
|
||||
|
||||
static async removeFavorite(seriesId: string): Promise<boolean> {
|
||||
const user = await this.getCurrentUser();
|
||||
await connectDB();
|
||||
|
||||
return DebugService.measureMongoOperation("removeFavorite", async () => {
|
||||
const result = await FavoriteModel.deleteOne({ userId: user.id, seriesId });
|
||||
return result.deletedCount > 0;
|
||||
const result = await prisma.favorite.deleteMany({
|
||||
where: {
|
||||
userId: user.id,
|
||||
seriesId,
|
||||
},
|
||||
});
|
||||
return result.count > 0;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
import { PreferencesModel } from "@/lib/models/preferences.model";
|
||||
import prisma from "@/lib/prisma";
|
||||
import { getCurrentUser } from "../auth-utils";
|
||||
import { ERROR_CODES } from "../../constants/errorCodes";
|
||||
import { AppError } from "../../utils/errors";
|
||||
import type { UserPreferences } from "@/types/preferences";
|
||||
import { defaultPreferences } from "@/types/preferences";
|
||||
import type { User } from "@/types/komga";
|
||||
import connectDB from "@/lib/mongodb";
|
||||
|
||||
export class PreferencesService {
|
||||
static async getCurrentUser(): Promise<User> {
|
||||
@@ -19,15 +18,20 @@ export class PreferencesService {
|
||||
static async getPreferences(): Promise<UserPreferences> {
|
||||
try {
|
||||
const user = await this.getCurrentUser();
|
||||
await connectDB();
|
||||
const preferences = await PreferencesModel.findOne({ userId: user.id });
|
||||
const preferences = await prisma.preferences.findUnique({
|
||||
where: { userId: user.id },
|
||||
});
|
||||
|
||||
if (!preferences) {
|
||||
return defaultPreferences;
|
||||
return { ...defaultPreferences };
|
||||
}
|
||||
|
||||
return {
|
||||
...defaultPreferences,
|
||||
...preferences.toObject(),
|
||||
_id: undefined, //plain object KO on server components hydration
|
||||
showThumbnails: preferences.showThumbnails,
|
||||
cacheMode: preferences.cacheMode as "memory" | "file",
|
||||
showOnlyUnread: preferences.showOnlyUnread,
|
||||
debug: preferences.debug,
|
||||
displayMode: preferences.displayMode as UserPreferences["displayMode"],
|
||||
};
|
||||
} catch (error) {
|
||||
if (error instanceof AppError) {
|
||||
@@ -40,18 +44,34 @@ export class PreferencesService {
|
||||
static async updatePreferences(preferences: Partial<UserPreferences>): Promise<UserPreferences> {
|
||||
try {
|
||||
const user = await this.getCurrentUser();
|
||||
await connectDB();
|
||||
const updatedPreferences = await PreferencesModel.findOneAndUpdate(
|
||||
{ userId: user.id },
|
||||
{ $set: preferences },
|
||||
{ new: true, upsert: true }
|
||||
);
|
||||
|
||||
const updateData: Record<string, any> = {};
|
||||
if (preferences.showThumbnails !== undefined) updateData.showThumbnails = preferences.showThumbnails;
|
||||
if (preferences.cacheMode !== undefined) updateData.cacheMode = preferences.cacheMode;
|
||||
if (preferences.showOnlyUnread !== undefined) updateData.showOnlyUnread = preferences.showOnlyUnread;
|
||||
if (preferences.debug !== undefined) updateData.debug = preferences.debug;
|
||||
if (preferences.displayMode !== undefined) updateData.displayMode = preferences.displayMode;
|
||||
|
||||
const result = {
|
||||
...defaultPreferences,
|
||||
...updatedPreferences.toObject(),
|
||||
const updatedPreferences = await prisma.preferences.upsert({
|
||||
where: { userId: user.id },
|
||||
update: updateData,
|
||||
create: {
|
||||
userId: user.id,
|
||||
showThumbnails: preferences.showThumbnails ?? defaultPreferences.showThumbnails,
|
||||
cacheMode: preferences.cacheMode ?? defaultPreferences.cacheMode,
|
||||
showOnlyUnread: preferences.showOnlyUnread ?? defaultPreferences.showOnlyUnread,
|
||||
debug: preferences.debug ?? defaultPreferences.debug,
|
||||
displayMode: preferences.displayMode ?? defaultPreferences.displayMode,
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
showThumbnails: updatedPreferences.showThumbnails,
|
||||
cacheMode: updatedPreferences.cacheMode as "memory" | "file",
|
||||
showOnlyUnread: updatedPreferences.showOnlyUnread,
|
||||
debug: updatedPreferences.debug,
|
||||
displayMode: updatedPreferences.displayMode as UserPreferences["displayMode"],
|
||||
};
|
||||
return result;
|
||||
} catch (error) {
|
||||
if (error instanceof AppError) {
|
||||
throw error;
|
||||
|
||||
@@ -18,4 +18,4 @@ export const defaultPreferences: UserPreferences = {
|
||||
compact: false,
|
||||
itemsPerPage: 20,
|
||||
},
|
||||
} as const;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user