use mongoose as orm

This commit is contained in:
StarAppeal
2024-11-22 20:20:54 +01:00
parent d84c07211a
commit 49057b2c6e
7 changed files with 211 additions and 111 deletions
+125 -23
View File
@@ -17,7 +17,7 @@
"dotenv": "^16.4.4",
"express": "5.0.0",
"jsonwebtoken": "^9.0.2",
"mongodb": "^6.3.0",
"mongoose": "^8.8.2",
"rimraf": "^5.0.5",
"typescript": "^5.3.3",
"ws": "8.17.1"
@@ -45,9 +45,9 @@
}
},
"node_modules/@mongodb-js/saslprep": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.1.4.tgz",
"integrity": "sha512-8zJ8N1x51xo9hwPh6AWnKdLGEC5N3lDa6kms1YHmFBoRhTpJR6HG8wWk0td1MVCu9cD4YBrvjZEtd5Obw0Fbnw==",
"version": "1.1.9",
"resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.1.9.tgz",
"integrity": "sha512-tVkljjeEaAhCqTzajSdgbQ6gE6f3oneVwa3iXR6csiEwXXOFsiC6Uh9iAjAhXPtqa/XMDHWjjeNH/77m/Yq2dw==",
"dependencies": {
"sparse-bitfield": "^3.0.3"
}
@@ -320,9 +320,9 @@
}
},
"node_modules/bson": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/bson/-/bson-6.3.0.tgz",
"integrity": "sha512-balJfqwwTBddxfnidJZagCBPP/f48zj9Sdp3OJswREOgsJzHiQSaOIAtApSgDQFYgHqAvFkp53AFSqjMDZoTFw==",
"version": "6.10.0",
"resolved": "https://registry.npmjs.org/bson/-/bson-6.10.0.tgz",
"integrity": "sha512-ROchNosXMJD2cbQGm84KoP7vOGPO6/bOAW0veMMbzhXLqoZptcaYRVLitwvuhwhjjpU1qP4YZRWLhgETdgqUQw==",
"engines": {
"node": ">=16.20.1"
}
@@ -963,6 +963,14 @@
"safe-buffer": "^5.0.1"
}
},
"node_modules/kareem": {
"version": "2.6.3",
"resolved": "https://registry.npmjs.org/kareem/-/kareem-2.6.3.tgz",
"integrity": "sha512-C3iHfuGUXK2u8/ipq9LfjFfXFxAZMQJJq7vLS45r3D9Y2xQ/m4S8zaR4zMLFWh9AsNPXmcFfUDhTEO8UIC/V6Q==",
"engines": {
"node": ">=12.0.0"
}
},
"node_modules/lodash.includes": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz",
@@ -1087,12 +1095,12 @@
}
},
"node_modules/mongodb": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.3.0.tgz",
"integrity": "sha512-tt0KuGjGtLUhLoU263+xvQmPHEGTw5LbcNC73EoFRYgSHwZt5tsoJC110hDyO1kjQzpgNrpdcSza9PknWN4LrA==",
"version": "6.10.0",
"resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.10.0.tgz",
"integrity": "sha512-gP9vduuYWb9ZkDM546M+MP2qKVk5ZG2wPF63OvSRuUbqCR+11ZCAE1mOfllhlAG0wcoJY5yDL/rV3OmYEwXIzg==",
"dependencies": {
"@mongodb-js/saslprep": "^1.1.0",
"bson": "^6.2.0",
"@mongodb-js/saslprep": "^1.1.5",
"bson": "^6.7.0",
"mongodb-connection-string-url": "^3.0.0"
},
"engines": {
@@ -1140,6 +1148,51 @@
"whatwg-url": "^13.0.0"
}
},
"node_modules/mongoose": {
"version": "8.8.2",
"resolved": "https://registry.npmjs.org/mongoose/-/mongoose-8.8.2.tgz",
"integrity": "sha512-jCTSqDANfRzk909v4YoZQi7jlGRB2MTvgG+spVBc/BA4tOs1oWJr//V6yYujqNq9UybpOtsSfBqxI0dSOEFJHQ==",
"dependencies": {
"bson": "^6.7.0",
"kareem": "2.6.3",
"mongodb": "~6.10.0",
"mpath": "0.9.0",
"mquery": "5.0.0",
"ms": "2.1.3",
"sift": "17.1.3"
},
"engines": {
"node": ">=16.20.1"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/mongoose"
}
},
"node_modules/mongoose/node_modules/ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
},
"node_modules/mpath": {
"version": "0.9.0",
"resolved": "https://registry.npmjs.org/mpath/-/mpath-0.9.0.tgz",
"integrity": "sha512-ikJRQTk8hw5DEoFVxHG1Gn9T/xcjtdnOKIU1JTmGjZZlg9LST2mBLmcX3/ICIbgJydT2GOc15RnNy5mHmzfSew==",
"engines": {
"node": ">=4.0.0"
}
},
"node_modules/mquery": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/mquery/-/mquery-5.0.0.tgz",
"integrity": "sha512-iQMncpmEK8R8ncT8HJGsGc9Dsp8xcgYMVSbs5jgnm1lFHTZqMJTUWTDx1LBO8+mK3tPNZWFLBghQEIOULSTHZg==",
"dependencies": {
"debug": "4.x"
},
"engines": {
"node": ">=14.0.0"
}
},
"node_modules/ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
@@ -1540,6 +1593,11 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/sift": {
"version": "17.1.3",
"resolved": "https://registry.npmjs.org/sift/-/sift-17.1.3.tgz",
"integrity": "sha512-Rtlj66/b0ICeFzYTuNvX/EF1igRbbnGSvEyT79McoZa/DeGhMyC5pWKOEsZKnpkqtSeovd5FL/bjHWC3CIIvCQ=="
},
"node_modules/signal-exit": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
@@ -1931,9 +1989,9 @@
}
},
"@mongodb-js/saslprep": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.1.4.tgz",
"integrity": "sha512-8zJ8N1x51xo9hwPh6AWnKdLGEC5N3lDa6kms1YHmFBoRhTpJR6HG8wWk0td1MVCu9cD4YBrvjZEtd5Obw0Fbnw==",
"version": "1.1.9",
"resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.1.9.tgz",
"integrity": "sha512-tVkljjeEaAhCqTzajSdgbQ6gE6f3oneVwa3iXR6csiEwXXOFsiC6Uh9iAjAhXPtqa/XMDHWjjeNH/77m/Yq2dw==",
"requires": {
"sparse-bitfield": "^3.0.3"
}
@@ -2165,9 +2223,9 @@
}
},
"bson": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/bson/-/bson-6.3.0.tgz",
"integrity": "sha512-balJfqwwTBddxfnidJZagCBPP/f48zj9Sdp3OJswREOgsJzHiQSaOIAtApSgDQFYgHqAvFkp53AFSqjMDZoTFw=="
"version": "6.10.0",
"resolved": "https://registry.npmjs.org/bson/-/bson-6.10.0.tgz",
"integrity": "sha512-ROchNosXMJD2cbQGm84KoP7vOGPO6/bOAW0veMMbzhXLqoZptcaYRVLitwvuhwhjjpU1qP4YZRWLhgETdgqUQw=="
},
"buffer-equal-constant-time": {
"version": "1.0.1",
@@ -2609,6 +2667,11 @@
"safe-buffer": "^5.0.1"
}
},
"kareem": {
"version": "2.6.3",
"resolved": "https://registry.npmjs.org/kareem/-/kareem-2.6.3.tgz",
"integrity": "sha512-C3iHfuGUXK2u8/ipq9LfjFfXFxAZMQJJq7vLS45r3D9Y2xQ/m4S8zaR4zMLFWh9AsNPXmcFfUDhTEO8UIC/V6Q=="
},
"lodash.includes": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz",
@@ -2699,12 +2762,12 @@
"integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ=="
},
"mongodb": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.3.0.tgz",
"integrity": "sha512-tt0KuGjGtLUhLoU263+xvQmPHEGTw5LbcNC73EoFRYgSHwZt5tsoJC110hDyO1kjQzpgNrpdcSza9PknWN4LrA==",
"version": "6.10.0",
"resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.10.0.tgz",
"integrity": "sha512-gP9vduuYWb9ZkDM546M+MP2qKVk5ZG2wPF63OvSRuUbqCR+11ZCAE1mOfllhlAG0wcoJY5yDL/rV3OmYEwXIzg==",
"requires": {
"@mongodb-js/saslprep": "^1.1.0",
"bson": "^6.2.0",
"@mongodb-js/saslprep": "^1.1.5",
"bson": "^6.7.0",
"mongodb-connection-string-url": "^3.0.0"
}
},
@@ -2717,6 +2780,40 @@
"whatwg-url": "^13.0.0"
}
},
"mongoose": {
"version": "8.8.2",
"resolved": "https://registry.npmjs.org/mongoose/-/mongoose-8.8.2.tgz",
"integrity": "sha512-jCTSqDANfRzk909v4YoZQi7jlGRB2MTvgG+spVBc/BA4tOs1oWJr//V6yYujqNq9UybpOtsSfBqxI0dSOEFJHQ==",
"requires": {
"bson": "^6.7.0",
"kareem": "2.6.3",
"mongodb": "~6.10.0",
"mpath": "0.9.0",
"mquery": "5.0.0",
"ms": "2.1.3",
"sift": "17.1.3"
},
"dependencies": {
"ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
}
}
},
"mpath": {
"version": "0.9.0",
"resolved": "https://registry.npmjs.org/mpath/-/mpath-0.9.0.tgz",
"integrity": "sha512-ikJRQTk8hw5DEoFVxHG1Gn9T/xcjtdnOKIU1JTmGjZZlg9LST2mBLmcX3/ICIbgJydT2GOc15RnNy5mHmzfSew=="
},
"mquery": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/mquery/-/mquery-5.0.0.tgz",
"integrity": "sha512-iQMncpmEK8R8ncT8HJGsGc9Dsp8xcgYMVSbs5jgnm1lFHTZqMJTUWTDx1LBO8+mK3tPNZWFLBghQEIOULSTHZg==",
"requires": {
"debug": "4.x"
}
},
"ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
@@ -2975,6 +3072,11 @@
"object-inspect": "^1.13.1"
}
},
"sift": {
"version": "17.1.3",
"resolved": "https://registry.npmjs.org/sift/-/sift-17.1.3.tgz",
"integrity": "sha512-Rtlj66/b0ICeFzYTuNvX/EF1igRbbnGSvEyT79McoZa/DeGhMyC5pWKOEsZKnpkqtSeovd5FL/bjHWC3CIIvCQ=="
},
"signal-exit": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
+1 -1
View File
@@ -22,7 +22,7 @@
"dotenv": "^16.4.4",
"express": "5.0.0",
"jsonwebtoken": "^9.0.2",
"mongodb": "^6.3.0",
"mongoose": "^8.8.2",
"rimraf": "^5.0.5",
"typescript": "^5.3.3",
"ws": "8.17.1"
+42 -14
View File
@@ -1,18 +1,46 @@
import { ObjectId } from "mongodb";
import "dotenv/config";
export default class User {
constructor(
public name: string,
public uuid: string,
public id: ObjectId,
public config : UserConfig
) {}
import {ObjectId} from "mongodb";
import mongoose from "mongoose";
export interface IUser {
name: string,
uuid: string,
id: ObjectId,
config: UserConfig
}
export class UserConfig {
constructor(
public isVisible: boolean ,
public canBeModified: boolean,
public isAdmin: boolean
) {}
export interface UserConfig {
isVisible: boolean,
canBeModified: boolean,
isAdmin: boolean
}
const userSchema = new mongoose.Schema<IUser>({
name: {
type: String,
required: true,
},
uuid: {
type: String,
required: true,
},
config: {
isVisible: {
type: Boolean,
required: true,
},
canBeModified: {
type: Boolean,
required: true,
},
isAdmin: {
type: Boolean,
required: true,
},
},
});
export const UserModel = mongoose.model<IUser>(process.env.USER_COLLECTION_NAME!, userSchema);
+29
View File
@@ -0,0 +1,29 @@
import { UserModel, IUser } from "../models/user";
import {connectToDatabase} from "./database.service";
import mongoose from "mongoose";
export class UserService {
private static _instance: UserService;
private constructor() {}
public static async create(): Promise<UserService> {
if (!this._instance) {
await connectToDatabase();
this._instance = new UserService();
}
return this._instance;
}
public async updateUser(id: string, user: Partial<IUser>): Promise<IUser | null> {
return await UserModel.findByIdAndUpdate(id, user, { new: true }).exec();
}
public async getAllUsers(): Promise<IUser[]> {
return await UserModel.find().exec();
}
public async getUserById(id: string): Promise<IUser | null> {
return await UserModel.findById(id).exec();
}
}
+7 -63
View File
@@ -1,68 +1,12 @@
import "dotenv/config";
import * as mongoDB from "mongodb";
import {ObjectId, ReturnDocument} from "mongodb";
import User from "../models/user";
import mongoose from "mongoose";
let mongoDb: mongoDB.Db;
export async function connectToDatabase() {
await mongoose.connect(process.env.DB_CONN_STRING!, {
dbName: process.env.DB_NAME!,
serverApi: {version: '1', strict: true, deprecationErrors: true}
});
async function getDatabase(): Promise<mongoDB.Db> {
if (mongoDb) {
return mongoDb;
}
const client = new mongoDB.MongoClient(process.env.DB_CONN_STRING!);
await client.connect();
mongoDb = client.db(process.env.DB_NAME!);
return mongoDb;
}
export class UserService {
private static _instance: UserService;
private readonly collection: mongoDB.Collection;
private constructor(db: mongoDB.Db) {
this.collection = db.collection(process.env.USER_COLLECTION_NAME!);
}
public static async create(): Promise<UserService> {
if (this._instance) {
return this._instance;
}
const db = await getDatabase();
this._instance = new UserService(db);
return this._instance;
}
public async updateUser(id: string, user: User): Promise<User> {
return await this.executeWithExceptionHandling(() => {
return this.collection.findOneAndUpdate(
{_id: new ObjectId(id)},
{$set: user},
{returnDocument: ReturnDocument.AFTER}
);
}) as unknown as User;
}
public async getAllUsers() {
return await this.executeWithExceptionHandling(() => {
return this.collection.find<User>({}).toArray();
});
}
async getUserById(id: string) {
return (await this.executeWithExceptionHandling(() => {
return this.collection.findOne<User>({
_id: new ObjectId(id),
});
}));
}
private async executeWithExceptionHandling<T>(operation: () => Promise<T>) {
try {
return await operation();
} catch (e) {
console.error(e);
return null;
}
}
console.log("Connected to MongoDB with Mongoose");
}
+1 -2
View File
@@ -1,7 +1,6 @@
import express from "express";
import { ExtendedWebSocketServer } from "./websocket";
import { RestWebSocket } from "./rest/restWebSocket";
import { UserService } from "./db/services/database.service";
import { RestUser } from "./rest/restUser";
import { authenticateJwt } from "./rest/middleware/authenticateJwt";
import { JwtTokenPropertiesExtractor } from "./rest/jwtTokenPropertiesExtractor";
@@ -24,7 +23,7 @@ app.use(express.json({ limit: "15mb" }));
const webSocketServer = new ExtendedWebSocketServer(server);
const restWebSocket = new RestWebSocket(webSocketServer);
const restUser = new RestUser(UserService.create);
const restUser = new RestUser();
const jwtTokenPropertiesExtractor = new JwtTokenPropertiesExtractor();
app.use("/api/websocket", authenticateJwt, restWebSocket.createRouter());
+6 -8
View File
@@ -1,21 +1,19 @@
import { UserService } from "../db/services/database.service";
import express from "express";
import User from "../db/models/user";
import {UserService} from "../db/services/UserService";
import {IUser} from "../db/models/user";
export class RestUser {
constructor(private createService: () => Promise<UserService>) {}
public createRouter() {
const router = express.Router();
router.get("/", async (req, res) => {
const userService = await this.createService();
const userService = await UserService.create();
const users = await userService.getAllUsers();
res.status(200).send({ users });
});
router.get("/:id", async (req, res) => {
const userService = await this.createService();
const userService = await UserService.create();
const id = req.params.id;
const user = await userService.getUserById(id);
@@ -27,9 +25,9 @@ export class RestUser {
});
router.put("/:id", async (req, res) => {
const userService = await this.createService();
const userService = await UserService.create();
const id = req.params.id;
const user = req.body as User;
const user = req.body as IUser;
const result = await userService.updateUser(id, user);
result