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,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