fixing things regarding bson error with node and such...now working?

This commit is contained in:
talksik
2022-04-03 09:04:25 -04:00
parent 7205fac3f5
commit 19b90b2196
11 changed files with 248 additions and 41 deletions
-2
View File
@@ -4,7 +4,6 @@ import { NextFunction } from "express";
import SocketChannels from "@nirvana/core/sockets/channels";
import { UserService } from "./services/user.service";
import { UserStatus } from "@nirvana/core/models";
import { connectToDatabase } from "./services/database.service";
import cors from "cors";
import getConversationRoutes from "./routes/conversation";
import getSearchRoutes from "./routes/search";
@@ -29,7 +28,6 @@ app.use("/api/conversations", getConversationRoutes());
const PORT = 5000;
var server = app.listen(PORT, () => console.log("express running"));
connectToDatabase();
// socket IO stuff
+81 -1
View File
@@ -1,11 +1,20 @@
import {
Conversation,
ConversationMember,
ConversationMemberState,
} from "../../core/models/conversation.model";
import { JwtClaims, authCheck } from "../middleware/auth";
import express, { Application, Request, Response } from "express";
import Content from "@nirvana/core/models/content.model";
import { ConversationService } from "../services/conversation.service";
import CreateConvoRequest from "../../core/requests/createConvo.request";
import GetConversationDetailsResponse from "@nirvana/core/responses/getConversationDetails.response";
import GetDmConversationByOtherUserIdResponse from "../../core/responses/getDmConversationByOtherUserId.response";
import MasterConversation from "../../core/models/masterConversation.model";
import { ObjectId } from "mongodb";
import Relationship from "@nirvana/core/models/relationship.model";
import { UserService } from "../services/user.service";
import { authCheck } from "../middleware/auth";
import { collections } from "../services/database.service";
export default function getConversationRoutes() {
@@ -16,5 +25,76 @@ export default function getConversationRoutes() {
// get data for a one on one conversation
// router.get("/:otherUserGoogleUserId", authCheck, getConversationDetails);
// create a convo
router.post("/", authCheck, createConversation);
// get conversation between user and other user
router.get("/dm/:otherUserId", authCheck, getDmByOtherUserId);
return router;
}
async function getDmByOtherUserId(req: Request, res: Response) {
try {
const { otherUserId } = req.params;
const userInfo = res.locals.userInfo as JwtClaims;
console.log(otherUserId);
// check db for convos between me and this other person
// if there is one, then return it with 200 status
// else return it with custom status that frontend will read
res.status(200).json();
return;
res.status(205).json("no such conversation between you two");
} catch (error) {
res.status(500).json(error);
}
}
async function createConversation(req: Request, res: Response) {
try {
const reqObj: CreateConvoRequest = req.body as CreateConvoRequest;
if (!reqObj?.otherMemberIds.length) {
res.status(400).json("must provide member Ids");
return;
}
const userInfo = res.locals.userInfo as JwtClaims;
const newConvo = new Conversation();
const convoMembers: ConversationMember[] =
reqObj.otherMemberIds.map((memId) => {
const newConvoMember = new ConversationMember(
newConvo._id,
new ObjectId(memId),
ConversationMemberState.INVITED
);
return newConvoMember;
}) ?? [];
convoMembers.push(
new ConversationMember(
newConvo._id,
new ObjectId(userInfo.userId),
ConversationMemberState.INBOX
)
);
const transactionResult = await ConversationService.createConversation(
newConvo,
convoMembers
);
transactionResult
? res.status(200).json(newConvo)
: res.status(400).json("unable to create convo");
} catch (error) {
console.log(error);
res.status(500).json(error);
}
}
+75 -9
View File
@@ -1,11 +1,77 @@
import {
Conversation,
ConversationMember,
} from "../../core/models/conversation.model";
import { client, collections } from "./database.service";
import { ObjectId } from "mongodb";
export class ConversationService {
// static async getUserById(userId: string) {
// const query = { googleId: userId };
// const res = await collections.users?.findOne(query);
// // exists
// if (res?._id) {
// return res as User;
// }
// return null;
// }
static async getConversationByOtherUserId(otherUserId: ObjectId) {
// get all of the conversations for this user that have exactly two conversation members
// get all of the conversationMembers for this user
// get all of the conversations for this user
// get all of the conversations
// const query = { googleId: userId };
// const res = await collections.users?.findOne(query);
// // exists
// if (res?._id) {
// return res as User;
// }
// return null;
}
static async createConversation(
convo: Conversation,
convoMembers: ConversationMember[]
) {
const session = client.startSession();
try {
const transactionResults = await session.withTransaction(async () => {
// todo: check if convoMembers userId's actually exist
const insertConvoRes = await collections.conversations?.insertOne(
convo
);
if (!insertConvoRes?.insertedId) {
await session.abortTransaction();
console.error("failed to create convo");
return;
}
const insertConvoMembersRes =
await collections.conversationMembers?.insertMany(convoMembers);
if (!insertConvoMembersRes?.insertedCount) {
await session.abortTransaction();
console.error("failed to create conversation members");
return;
}
console.log("success");
return insertConvoMembersRes;
});
console.log(transactionResults);
return "success";
// if (transactionResults) {
// console.log("The convo was successfully created.");
// return transactionResults;
// } else {
// console.log("The convo was intentionally aborted.");
// return null;
// }
} catch (e) {
console.log(
"The transaction was aborted due to an unexpected error: " + e
);
} finally {
await session.endSession();
}
return null;
}
}
+22 -13
View File
@@ -6,25 +6,34 @@ import { loadConfig } from "../config";
// Global Variables
export const collections: {
users?: mongoDB.Collection;
conversations?: mongoDB.Collection;
conversationMembers?: mongoDB.Collection;
audioClips?: mongoDB.Collection;
} = {};
// Initialize Connection
export async function connectToDatabase() {
const config = loadConfig();
const config = loadConfig();
const client: mongoDB.MongoClient = new mongoDB.MongoClient(
config.MONGO_CONNECTION_STRING
);
export const client: mongoDB.MongoClient = new mongoDB.MongoClient(
config.MONGO_CONNECTION_STRING
);
await client.connect();
client.connect();
const db: mongoDB.Db = client.db(process.env.DB_NAME);
const db: mongoDB.Db = client.db(process.env.DB_NAME);
const usersCollection: mongoDB.Collection = db.collection("users");
const usersCollection: mongoDB.Collection = db.collection("users");
const convoCollection: mongoDB.Collection = db.collection("conversations");
const convoMembersCollection: mongoDB.Collection = db.collection(
"conversationMembers"
);
const audioClipsCollection: mongoDB.Collection = db.collection("audioClips");
collections.users = usersCollection;
collections.users = usersCollection;
collections.conversations = convoCollection;
collections.conversationMembers = convoMembersCollection;
collections.audioClips = audioClipsCollection;
console.log(
`Successfully connected to database: ${db.databaseName} and collections`
);
}
console.log(
`Successfully connected to database: ${db.databaseName} and collections`
);
+13 -12
View File
@@ -1,25 +1,26 @@
import { ObjectId } from "mongodb";
export class Conversation {
_id: ObjectId;
name?: string;
createdDate: Date;
lastUpdatedDate: Date;
constructor() {}
constructor(
public _id?: ObjectId,
public createdDate: Date = new Date(),
public lastUpdatedDate: Date = new Date()
) {}
}
export class ConversationMember {
_id: ObjectId;
constructor(
// unique constraint
public conversationId: ObjectId,
public userId: ObjectId,
// unique constraint
conversationId: ObjectId;
userId: ObjectId;
public state: ConversationMemberState = ConversationMemberState.INVITED,
state: ConversationMemberState;
createdDate: Date;
public createdDate: Date = new Date(),
public _id?: ObjectId
) {}
}
export enum ConversationMemberState {
@@ -0,0 +1,3 @@
export default class CreateConvoRequest {
constructor(public otherMemberIds: string[]) {}
}
@@ -0,0 +1,5 @@
import { Conversation } from "../models/conversation.model";
export default class GetDmConversationByOtherUserIdResponse {
constructor(public conversation: Conversation) {}
}
+1
View File
@@ -105,6 +105,7 @@
"typescript": "~4.5.4"
},
"dependencies": {
"@nirvana/core": "*",
"@emotion/react": "^11.8.2",
"@emotion/styled": "^11.8.1",
"@getstation/electron-google-oauth2": "^2.1.0",
@@ -31,3 +31,6 @@ export function useUserSearch(searchQuery: string) {
}
// =========== MUTATIONS
export function useGetDmByUserId() {
return useMutation(ApiCalls.getDmByUserId);
}
@@ -1,5 +1,6 @@
import axios, { AxiosRequestConfig, AxiosResponse, Method } from "axios";
import { Conversation } from "../../../core/models/conversation.model";
import LoginResponse from "../../../core/responses/login.response";
import { User } from "@nirvana/core/models";
import UserDetailsResponse from "../../../core/responses/userDetails.response";
@@ -69,9 +70,18 @@ async function userSearch(searchQuery: string): Promise<UserSearchResponse> {
);
}
async function getDmByUserId(otherUserId: string): Promise<Conversation> {
return await NirvanaApi.fetch(
`/conversations/dm/${otherUserId}`,
"GET",
true
);
}
export const ApiCalls = {
login,
authCheck,
getUserDetails,
userSearch,
getDmByUserId,
};
@@ -8,12 +8,18 @@ import {
} from "@mui/material";
import { Check, Search } from "@mui/icons-material";
import { useEffect, useState } from "react";
import {
useGetDmByUserId,
useGetUserDetails,
useUserSearch,
} from "../../../controller/index";
import { $newConvoPage } from "../../../controller/recoil";
import { ApiCalls } from "../../../controller/nirvanaApi";
import { User } from "@nirvana/core/models/user.model";
import UserRow from "../../../components/User/basicUserDetailsRow";
import toast from "react-hot-toast";
import { useSetRecoilState } from "recoil";
import { useUserSearch } from "../../../controller/index";
export default function NewConvo() {
const setNewPageConvo = useSetRecoilState($newConvoPage);
@@ -21,6 +27,8 @@ export default function NewConvo() {
const [debUserSearchQ, setDebUserSearchQ] = useState<string>("");
const [selectedUsers, setSelectedUsers] = useState<User[]>([]);
const { data: userDetails } = useGetUserDetails();
const {
data,
isLoading: isSearching,
@@ -101,13 +109,36 @@ export default function NewConvo() {
);
}
const createConvo = () => {
const { mutateAsync } = useGetDmByUserId();
const createConvo = async () => {
if (!selectedUsers?.length) {
toast.error("Must select at least one person");
return;
}
// consolidate the user Ids into an array
// make sure that there are no duplicates
console;
// const userIds = selectedUsers.map((selUser) => selUser._id.toString());
// userIds.push(userDetails.user._id.toString());
// IF it's a one on one chat
// check backend with one route if there is an existing conversation
console;
if (selectedUsers?.length === 1) {
let existingConvo;
try {
existingConvo = await mutateAsync(selectedUsers[0]._id.toString());
console.log("there is an existing convo!");
console.log(existingConvo);
} catch (error) {
console.error(error);
} finally {
console.log("done");
}
}
// create a conversation object in db with two members, me and this other person
// IF it's a group convo/room/channel, create a channel with these people
};