From 7c1041009f037a498510cc71a23056b9319ab9b4 Mon Sep 17 00:00:00 2001 From: himanshu goyal Date: Thu, 3 Jul 2025 15:33:11 +0530 Subject: [PATCH 01/11] update user resolver --- .env.example | 7 ------- graphql/resolvers.js | 33 +++++++++++++++++++++++++++++++-- graphql/schema.js | 2 ++ models/user.js | 4 ++++ 4 files changed, 37 insertions(+), 9 deletions(-) delete mode 100644 .env.example diff --git a/.env.example b/.env.example deleted file mode 100644 index a2da8de..0000000 --- a/.env.example +++ /dev/null @@ -1,7 +0,0 @@ -DB = mongodb+srv://username:password@bacon.someurl.mongodb.net/test?retryWrites=true&w=majority -JWT_SECRET = somesupersecretstring -REDIS_AUTH = Redis password you get while provisioning a Redis DB -REDIS_URL = Redis DB connection string -REDIS_PORT = Any port you want. -REDIS_USERNAME = Username of the user that has access to the Redis DB -INSTANCE = ec2 instance id diff --git a/graphql/resolvers.js b/graphql/resolvers.js index 4523d66..5ba613a 100644 --- a/graphql/resolvers.js +++ b/graphql/resolvers.js @@ -28,7 +28,7 @@ const resolvers = { .populate("leader followers") .populate({ path: "landmarks", - populate: { path: "createdBy", select: "name email" }, + populate: { path: "createdBy", select: "name email imageUrl" }, }); if (!beacon) return new UserInputError("No beacon exists with that id."); // return error iff user not in beacon @@ -56,7 +56,9 @@ const resolvers = { return group; }, groups: async (_parent, { page, pageSize }, { user }) => { + console.log("ye hit kia", user.id, page, pageSize); if (!user.groups) return Error(`User have no groups!`); + console.log("group to hai", user.groups); let groups = await Group.find({ _id: { $in: user.groups } }) .sort({ updatedAt: -1 }) @@ -67,6 +69,7 @@ const resolvers = { // it might be possible that group has been deleted groups = groups.filter(group => group !== null); + console.log("groups", groups[0].members); return groups ?? []; }, @@ -541,6 +544,7 @@ const resolvers = { const newLandmark = new Landmark({ createdBy: user.id, ...landmark }); const populatedLandmark = await newLandmark.save().then(lan => lan.populate("createdBy")); + console.log("populatedLandmark", populatedLandmark); beacon.landmarks.push(newLandmark.id); pubsub.publish("BEACON_LOCATIONS", { @@ -694,6 +698,31 @@ const resolvers = { return false; } }, + + updateUserImage: async (_parent, { userId, imageUrl }, context) => { + // Optional: Add authentication check + if (!context.user) throw new AuthenticationError("Not authenticated"); + console.log("userId", userId, imageUrl); + + try { + const updatedUser = await User.findByIdAndUpdate( + userId, + { imageUrl }, + { new: true } // Return the updated document + ); + + console.log("updatedUser", updatedUser); + + if (!updatedUser) { + throw new UserInputError("User not found"); + } + + return updatedUser; + } catch (error) { + console.log("error", error); + throw new Error("Failed to update user image"); + } + }, }, ...(process.env._HANDLER == null && { Subscription: { @@ -709,7 +738,7 @@ const resolvers = { const isFollower = followers.includes(user.id); const isLeader = leaderID == user.id; const istrue = variables.id === beaconID && (isFollower || isLeader); - + console.log("sosuser", userSOS); if (userSOS != null && user.id != userSOS._id) { payload.beaconLocations.userSOS = parseUserObject(userSOS); return istrue; diff --git a/graphql/schema.js b/graphql/schema.js index efb7bb2..c325c38 100644 --- a/graphql/schema.js +++ b/graphql/schema.js @@ -73,6 +73,7 @@ const typeDefs = gql` location: Location beacons: [Beacon!]! groups: [Group!]! + imageUrl: String! } input AuthPayload { @@ -159,6 +160,7 @@ const typeDefs = gql` deleteBeacon(id: ID!): Boolean! sos(id: ID!): User! deleteUser(credentials: AuthPayload!): Boolean! + updateUserImage(userId: ID!, imageUrl: String!): User! } type Subscription { diff --git a/models/user.js b/models/user.js index 9d83f0c..184590c 100644 --- a/models/user.js +++ b/models/user.js @@ -14,6 +14,10 @@ const UserSchema = new Schema( location: LocationSchema, beacons: { type: [Schema.Types.ObjectId], ref: "Beacon", default: [] }, groups: { type: [Schema.Types.ObjectId], ref: "Group", default: [] }, + imageUrl: { + type: String, + default: "https://cdn.jsdelivr.net/gh/alohe/avatars/png/memo_35.png", // default avatar URL + }, }, { timestamps: true, From ab8c75d68983e0cf72fa3c3fc33248d72780f5a0 Mon Sep 17 00:00:00 2001 From: himanshu goyal Date: Thu, 3 Jul 2025 15:42:38 +0530 Subject: [PATCH 02/11] removed console logs --- .env.example | 7 +++++++ graphql/resolvers.js | 3 --- 2 files changed, 7 insertions(+), 3 deletions(-) create mode 100644 .env.example diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..6e06cca --- /dev/null +++ b/.env.example @@ -0,0 +1,7 @@ +DB = mongodb+srv://username:password@bacon.someurl.mongodb.net/test?retryWrites=true&w=majority +JWT_SECRET = somesupersecretstring +REDIS_AUTH = Redis password you get while provisioning a Redis DB +REDIS_URL = Redis DB connection string +REDIS_PORT = Any port you want. +REDIS_USERNAME = Username of the user that has access to the Redis DB +INSTANCE = ec2 instance id \ No newline at end of file diff --git a/graphql/resolvers.js b/graphql/resolvers.js index 5ba613a..031b5c0 100644 --- a/graphql/resolvers.js +++ b/graphql/resolvers.js @@ -56,9 +56,7 @@ const resolvers = { return group; }, groups: async (_parent, { page, pageSize }, { user }) => { - console.log("ye hit kia", user.id, page, pageSize); if (!user.groups) return Error(`User have no groups!`); - console.log("group to hai", user.groups); let groups = await Group.find({ _id: { $in: user.groups } }) .sort({ updatedAt: -1 }) @@ -738,7 +736,6 @@ const resolvers = { const isFollower = followers.includes(user.id); const isLeader = leaderID == user.id; const istrue = variables.id === beaconID && (isFollower || isLeader); - console.log("sosuser", userSOS); if (userSOS != null && user.id != userSOS._id) { payload.beaconLocations.userSOS = parseUserObject(userSOS); return istrue; From 8282a1faa9e57a2a9e78511d3b1a805daf8ae8cf Mon Sep 17 00:00:00 2001 From: himanshu goyal Date: Sun, 6 Jul 2025 14:35:18 +0530 Subject: [PATCH 03/11] icon for landmarks --- graphql/resolvers.js | 55 ++++++++++++++++++++++++++------------------ graphql/schema.js | 2 ++ models/landmark.js | 1 + 3 files changed, 36 insertions(+), 22 deletions(-) diff --git a/graphql/resolvers.js b/graphql/resolvers.js index 031b5c0..52c325d 100644 --- a/graphql/resolvers.js +++ b/graphql/resolvers.js @@ -532,33 +532,44 @@ const resolvers = { }, createLandmark: async (_, { landmark, beaconID }, { user, pubsub }) => { - const beacon = await Beacon.findById(beaconID); - // to save on a db call to populate leader, we just use the stored id to compare + try { + const beacon = await Beacon.findById(beaconID); + console.log("inside create landmark"); + // to save on a db call to populate leader, we just use the stored id to compare - if (!beacon) return new UserInputError("Beacon doesn't exist"); + if (!beacon) return new UserInputError("Beacon doesn't exist"); - if (!beacon.followers.includes(user.id) && beacon.leader != user.id) - return new UserInputError("User should be part of beacon"); - const newLandmark = new Landmark({ createdBy: user.id, ...landmark }); - const populatedLandmark = await newLandmark.save().then(lan => lan.populate("createdBy")); + console.log("below return"); - console.log("populatedLandmark", populatedLandmark); - beacon.landmarks.push(newLandmark.id); + if (!beacon.followers.includes(user.id) && beacon.leader != user.id) + return new UserInputError("User should be part of beacon"); + const newLandmark = new Landmark({ createdBy: user.id, ...landmark }); + console.log("new landmark", newLandmark); + const savedLandmark = await newLandmark.save(); + console.log("savedLandmark", savedLandmark); + const populatedLandmark = await savedLandmark.populate("createdBy"); - pubsub.publish("BEACON_LOCATIONS", { - beaconLocations: { - userSOS: null, - route: null, - updatedUser: null, - landmark: populatedLandmark, - }, - beaconID: beacon.id, - followers: beacon.followers, - leaderID: beacon.leader, - }); - await beacon.save(); + console.log("populatedLandmark", populatedLandmark); + beacon.landmarks.push(newLandmark.id); - return populatedLandmark; + pubsub.publish("BEACON_LOCATIONS", { + beaconLocations: { + userSOS: null, + route: null, + updatedUser: null, + landmark: populatedLandmark, + }, + beaconID: beacon.id, + followers: beacon.followers, + leaderID: beacon.leader, + }); + await beacon.save(); + console.log("populated 2", populatedLandmark); + return populatedLandmark; + } catch (error) { + console.log("error", error); + throw new Error("Failed to create landmark"); + } }, updateUserLocation: async (_, { id, location }, { user, pubsub }) => { diff --git a/graphql/schema.js b/graphql/schema.js index c325c38..79601ee 100644 --- a/graphql/schema.js +++ b/graphql/schema.js @@ -49,6 +49,7 @@ const typeDefs = gql` _id: ID! createdAt: Float! title: String! + icon: String! location: Location! createdBy: User! } @@ -56,6 +57,7 @@ const typeDefs = gql` input LandmarkInput { title: String! location: LocationInput! + icon: String! } type User { diff --git a/models/landmark.js b/models/landmark.js index 0fe9ccc..780f35b 100644 --- a/models/landmark.js +++ b/models/landmark.js @@ -8,6 +8,7 @@ const landmarkSchema = new Schema( { title: { type: String, required: true }, location: { type: LocationSchema, required: true }, + icon: { type: String, required: true }, createdBy: { type: Schema.Types.ObjectId, required: true, ref: "User" }, }, { From bc71ef3744050f21f8c0f2e14968548228e5bd70 Mon Sep 17 00:00:00 2001 From: himanshu goyal Date: Sun, 6 Jul 2025 14:38:54 +0530 Subject: [PATCH 04/11] disable cache for lint erros --- .github/workflows/lint.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 89b89fa..2b67270 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -22,7 +22,7 @@ jobs: uses: actions/setup-node@v2 with: node-version: ${{ matrix.node-version }} - cache: "npm" + # cache: "npm" - name: Clean npm cache and remove node_modules run: | From f2421b341b65a0b91081119d9486246f249a4bf6 Mon Sep 17 00:00:00 2001 From: himanshu goyal Date: Fri, 11 Jul 2025 12:21:03 +0530 Subject: [PATCH 05/11] oauth fix --- graphql/resolvers.js | 15 +++++---------- graphql/schema.js | 1 + 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/graphql/resolvers.js b/graphql/resolvers.js index 52c325d..50b2c10 100644 --- a/graphql/resolvers.js +++ b/graphql/resolvers.js @@ -67,7 +67,6 @@ const resolvers = { // it might be possible that group has been deleted groups = groups.filter(group => group !== null); - console.log("groups", groups[0].members); return groups ?? []; }, @@ -182,11 +181,11 @@ const resolvers = { }, oAuth: async (_parent, { userInput }) => { - const { name, email } = userInput; + const { name, email, imageUrl } = userInput; let user = await User.findOne({ email }); if (!user) { - const newUser = new User({ name, email, isVerified: true }); + const newUser = new User({ name, email, isVerified: true, imageUrl }); user = await newUser.save(); } @@ -534,22 +533,17 @@ const resolvers = { createLandmark: async (_, { landmark, beaconID }, { user, pubsub }) => { try { const beacon = await Beacon.findById(beaconID); - console.log("inside create landmark"); // to save on a db call to populate leader, we just use the stored id to compare if (!beacon) return new UserInputError("Beacon doesn't exist"); - console.log("below return"); - if (!beacon.followers.includes(user.id) && beacon.leader != user.id) return new UserInputError("User should be part of beacon"); const newLandmark = new Landmark({ createdBy: user.id, ...landmark }); - console.log("new landmark", newLandmark); + const savedLandmark = await newLandmark.save(); - console.log("savedLandmark", savedLandmark); const populatedLandmark = await savedLandmark.populate("createdBy"); - console.log("populatedLandmark", populatedLandmark); beacon.landmarks.push(newLandmark.id); pubsub.publish("BEACON_LOCATIONS", { @@ -564,7 +558,7 @@ const resolvers = { leaderID: beacon.leader, }); await beacon.save(); - console.log("populated 2", populatedLandmark); + return populatedLandmark; } catch (error) { console.log("error", error); @@ -743,6 +737,7 @@ const resolvers = { (payload, variables, { user }) => { const { beaconLocations, leaderID, followers, beaconID } = payload; const { userSOS, route, updatedUser, landmark } = beaconLocations; + console.log("payload", payload); const isFollower = followers.includes(user.id); const isLeader = leaderID == user.id; diff --git a/graphql/schema.js b/graphql/schema.js index 79601ee..e9c7049 100644 --- a/graphql/schema.js +++ b/graphql/schema.js @@ -115,6 +115,7 @@ const typeDefs = gql` input oAuthInput { email: String name: String + imageUrl: String } type UpdatedGroupPayload { From 5eee4c93a498d54c0a690e8303b9ac942c9f2b51 Mon Sep 17 00:00:00 2001 From: himanshu goyal Date: Tue, 15 Jul 2025 14:06:47 +0530 Subject: [PATCH 06/11] add cache in workflow --- .github/workflows/lint.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 2b67270..89b89fa 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -22,7 +22,7 @@ jobs: uses: actions/setup-node@v2 with: node-version: ${{ matrix.node-version }} - # cache: "npm" + cache: "npm" - name: Clean npm cache and remove node_modules run: | From 28ec1f11ba098978736378922c718af1234a671f Mon Sep 17 00:00:00 2001 From: himanshu goyal Date: Tue, 15 Jul 2025 14:11:16 +0530 Subject: [PATCH 07/11] setup-node to v3 --- .github/workflows/lint.yml | 62 +++++++++++++++++++------------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 89b89fa..23772df 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -1,45 +1,45 @@ name: Lint on: - push: - branches: [master] - pull_request: - branches: [master] + push: + branches: [master] + pull_request: + branches: [master] jobs: - build: - runs-on: ubuntu-latest + build: + runs-on: ubuntu-latest - strategy: - matrix: - node-version: [18.x] + strategy: + matrix: + node-version: [18.x] - steps: - - name: Checkout repository - uses: actions/checkout@v2 + steps: + - name: Checkout repository + uses: actions/checkout@v4 - - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v2 - with: - node-version: ${{ matrix.node-version }} - cache: "npm" + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v3 + with: + node-version: ${{ matrix.node-version }} + cache: npm - - name: Clean npm cache and remove node_modules - run: | - rm -rf node_modules package-lock.json - npm cache clean --force + - name: Clean npm cache and remove node_modules + run: | + rm -rf node_modules package-lock.json + npm cache clean --force - - name: Install dependencies - run: npm install + - name: Install dependencies + run: npm install - - name: Verify package-lock.json - run: git diff --exit-code package-lock.json || echo "⚠️ package-lock.json changed, please update it." + - name: Verify package-lock.json + run: git diff --exit-code package-lock.json || echo "⚠️ package-lock.json changed, please update it." - - name: Run npm ci - run: npm ci + - name: Run npm ci + run: npm ci - - name: Run Prettier - run: npx prettier -c "**/*.js" + - name: Run Prettier + run: npx prettier -c "**/*.js" - - name: Run ESLint - run: npx eslint . + - name: Run ESLint + run: npx eslint . From 8e167017a7d66518665d121307b682192d2c3b48 Mon Sep 17 00:00:00 2001 From: himanshu goyal Date: Wed, 16 Jul 2025 11:14:21 +0530 Subject: [PATCH 08/11] clean commit --- graphql/resolvers.js | 10 ++-------- index.mjs | 1 - 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/graphql/resolvers.js b/graphql/resolvers.js index 50b2c10..077924e 100644 --- a/graphql/resolvers.js +++ b/graphql/resolvers.js @@ -265,9 +265,8 @@ const resolvers = { return verificationCode; }, - completeVerification: async (_, { userId }, { user }) => { + completeVerification: async (_, { userId }) => { let currentUser = await User.findById(userId); - console.log("Current user: ", currentUser, user); currentUser.isVerified = true; await currentUser.save(); return currentUser; @@ -639,7 +638,6 @@ const resolvers = { deleteUser: async (_, { credentials }) => { try { const userToDelete = await User.findOne({ email: credentials.email }); - console.log("User to delete:", userToDelete); if (!userToDelete) { throw new UserInputError("User not found"); } @@ -705,17 +703,14 @@ const resolvers = { updateUserImage: async (_parent, { userId, imageUrl }, context) => { // Optional: Add authentication check if (!context.user) throw new AuthenticationError("Not authenticated"); - console.log("userId", userId, imageUrl); try { const updatedUser = await User.findByIdAndUpdate( userId, { imageUrl }, - { new: true } // Return the updated document + { new: true } ); - console.log("updatedUser", updatedUser); - if (!updatedUser) { throw new UserInputError("User not found"); } @@ -737,7 +732,6 @@ const resolvers = { (payload, variables, { user }) => { const { beaconLocations, leaderID, followers, beaconID } = payload; const { userSOS, route, updatedUser, landmark } = beaconLocations; - console.log("payload", payload); const isFollower = followers.includes(user.id); const isLeader = leaderID == user.id; diff --git a/index.mjs b/index.mjs index dc03f57..c8828d9 100644 --- a/index.mjs +++ b/index.mjs @@ -64,7 +64,6 @@ app.use( app.get("/", (req, res) => res.send("Hello World! This is a GraphQL API. Check out /graphql")); app.get("/j/:shortcode", async (_req, res) => { - console.log(`shortcode route hit`); res.send("this should open in the app eventually"); }); From b755ce2cf81b73aa1d716aa6eddc0ae67f13b5d5 Mon Sep 17 00:00:00 2001 From: himanshu goyal Date: Wed, 16 Jul 2025 11:17:24 +0530 Subject: [PATCH 09/11] resolve prettier error --- graphql/resolvers.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/graphql/resolvers.js b/graphql/resolvers.js index 077924e..243cc87 100644 --- a/graphql/resolvers.js +++ b/graphql/resolvers.js @@ -705,11 +705,7 @@ const resolvers = { if (!context.user) throw new AuthenticationError("Not authenticated"); try { - const updatedUser = await User.findByIdAndUpdate( - userId, - { imageUrl }, - { new: true } - ); + const updatedUser = await User.findByIdAndUpdate(userId, { imageUrl }, { new: true }); if (!updatedUser) { throw new UserInputError("User not found"); From 56b7397c971d6d01aa7ae1070d3f86701c62188b Mon Sep 17 00:00:00 2001 From: himanshu goyal Date: Thu, 17 Jul 2025 12:10:54 +0530 Subject: [PATCH 10/11] sos subscription fix --- graphql/resolvers.js | 53 +++++++++++---- parsing.js | 153 +++++++++++++++++++++++++++++-------------- 2 files changed, 144 insertions(+), 62 deletions(-) diff --git a/graphql/resolvers.js b/graphql/resolvers.js index 243cc87..688c1af 100644 --- a/graphql/resolvers.js +++ b/graphql/resolvers.js @@ -619,7 +619,7 @@ const resolvers = { const currentDate = new Date(); if (new Date(beacon.expiresAt) < currentDate) return new UserInputError("Beacon is already expired!"); - + // console.log("inside sos", user); pubsub.publish("BEACON_LOCATIONS", { beaconLocations: { userSOS: user, @@ -729,27 +729,56 @@ const resolvers = { const { beaconLocations, leaderID, followers, beaconID } = payload; const { userSOS, route, updatedUser, landmark } = beaconLocations; + + // Check if user is part of this beacon const isFollower = followers.includes(user.id); const isLeader = leaderID == user.id; - const istrue = variables.id === beaconID && (isFollower || isLeader); - if (userSOS != null && user.id != userSOS._id) { + const isBeaconParticipant = variables.id === beaconID && (isFollower || isLeader); + + // If user is not part of this beacon, don't send updates + if (!isBeaconParticipant) { + return false; + } + + // Handle userSOS updates + if (userSOS != null) { + // Don't send SOS updates to the user who triggered the SOS + if (user.id == userSOS._id) { + return false; + } payload.beaconLocations.userSOS = parseUserObject(userSOS); - return istrue; + return true; } - if (route != null && leaderID != user.id) { - return istrue; + + // Handle route updates + if (route != null) { + // Don't send route updates to the leader who created the route + if (leaderID == user.id) { + return false; + } + return true; } - // stopping user who has updated the location - if (updatedUser != null && updatedUser._id != user.id) { + // Handle user location updates + if (updatedUser != null) { + // Don't send location updates to the user who updated their location + if (updatedUser._id == user.id) { + return false; + } payload.beaconLocations.updatedUser = parseUserObject(updatedUser); - return istrue; + return true; } - // stopping the creator of landmark - if (landmark != null && landmark.createdBy._id != user.id) { + + // Handle landmark updates + if (landmark != null) { + // Don't send landmark updates to the user who created the landmark + if (landmark.createdBy._id == user.id) { + return false; + } payload.beaconLocations.landmark = parseLandmarkObject(landmark); - return istrue; + return true; } + // If none of the above conditions are met, don't send the update return false; } ), diff --git a/parsing.js b/parsing.js index 1834feb..ab07c82 100644 --- a/parsing.js +++ b/parsing.js @@ -1,76 +1,113 @@ const { default: mongoose } = require("mongoose"); -function parseBeaconObject(beaconObject) { - if (typeof beaconObject === "string") { - return convertToObjectId(beaconObject); +function parseUserObject(userObject) { + if (!userObject) { + return null; } - var model = { - _id: convertToObjectId(beaconObject._id), - title: beaconObject.title, - shortcode: beaconObject.shortcode, - startsAt: convertToDate(beaconObject.startsAt), - expiresAt: convertToDate(beaconObject.expiresAt), - group: parseGroupObject(beaconObject.group), - leader: parseUserObject(beaconObject.leader), - location: beaconObject.location, - followers: Array.isArray(beaconObject.followers) - ? beaconObject.followers.map(follower => parseUserObject(follower)) - : [], - landmarks: Array.isArray(beaconObject.landmarks) - ? beaconObject.landmarks.map(landmark => parseLandmarkObject(landmark)) - : [], - route: beaconObject.route.map(single => parseLocationObject(single)), - geofence: beaconObject.geofence, - - updatedAt: convertToDate(beaconObject.updatedAt), - __v: beaconObject.__v, - }; - - return model; -} - -function parseUserObject(userObject) { if (typeof userObject === "string") { return convertToObjectId(userObject); } + let model = null; + try { - var model = { - _id: convertToObjectId(userObject._id), + model = { + _id: safeObjectId(userObject._id), name: userObject.name, email: userObject.email, password: userObject.password, - groups: Array.isArray(userObject.groups) ? userObject.groups.map(group => parseGroupObject(group)) : [], + groups: Array.isArray(userObject.groups) + ? userObject.groups + .filter(Boolean) + .map(group => safeParse(parseGroupObject, group)) + .filter(Boolean) + : [], beacons: Array.isArray(userObject.beacons) - ? userObject.beacons.map(beacon => parseBeaconObject(beacon)) + ? userObject.beacons + .filter(Boolean) + .map(beacon => safeParse(parseBeaconObject, beacon)) + .filter(Boolean) : [], - location: userObject.location, + location: parseLocationObject(userObject.location), createdAt: convertToDate(userObject.createdAt), updatedAt: convertToDate(userObject.updatedAt), __v: userObject.__v, }; } catch (error) { - console.log(error); + return null; } return model; } +function parseBeaconObject(beaconObject) { + if (!beaconObject) { + return null; + } + + if (typeof beaconObject === "string") { + return convertToObjectId(beaconObject); + } + + const model = { + _id: safeObjectId(beaconObject._id), + title: beaconObject.title, + shortcode: beaconObject.shortcode, + startsAt: convertToDate(beaconObject.startsAt), + expiresAt: convertToDate(beaconObject.expiresAt), + group: safeParse(parseGroupObject, beaconObject.group), + leader: safeParse(parseUserObject, beaconObject.leader), + location: parseLocationObject(beaconObject.location), + followers: Array.isArray(beaconObject.followers) + ? beaconObject.followers + .filter(Boolean) + .map(follower => safeParse(parseUserObject, follower)) + .filter(Boolean) + : [], + landmarks: Array.isArray(beaconObject.landmarks) + ? beaconObject.landmarks + .filter(Boolean) + .map(landmark => safeParse(parseLandmarkObject, landmark)) + .filter(Boolean) + : [], + route: Array.isArray(beaconObject.route) ? beaconObject.route.filter(Boolean).map(parseLocationObject) : [], + geofence: beaconObject.geofence, + updatedAt: convertToDate(beaconObject.updatedAt), + __v: beaconObject.__v, + }; + + return model; +} + function parseGroupObject(groupObject) { + if (!groupObject) { + return null; + } + if (typeof groupObject === "string") { return convertToObjectId(groupObject); } - var model = { - _id: convertToObjectId(groupObject._id), + const model = { + _id: safeObjectId(groupObject._id), title: groupObject.title, shortcode: groupObject.shortcode, - createdAt: new Date(groupObject.createdAt), - updatedAt: new Date(groupObject.updatedAtt), - leader: parseUserObject(groupObject.leader), - members: Array.isArray(groupObject.members) ? groupObject.members.map(member => parseUserObject(member)) : [], - beacons: Array.isArray(groupObject.beacons) ? groupObject.beacons.map(beacon => parseBeaconObject(beacon)) : [], + createdAt: convertToDate(groupObject.createdAt), + updatedAt: convertToDate(groupObject.updatedAt), // ← FIXED TYPO + leader: safeParse(parseUserObject, groupObject.leader), + members: Array.isArray(groupObject.members) + ? groupObject.members + .filter(Boolean) + .map(member => safeParse(parseUserObject, member)) + .filter(Boolean) + : [], + beacons: Array.isArray(groupObject.beacons) + ? groupObject.beacons + .filter(Boolean) + .map(beacon => safeParse(parseBeaconObject, beacon)) + .filter(Boolean) + : [], __v: groupObject.__v, }; @@ -78,15 +115,19 @@ function parseGroupObject(groupObject) { } function parseLandmarkObject(landmarkObject) { + if (!landmarkObject) { + return null; + } + if (typeof landmarkObject === "string") { return convertToObjectId(landmarkObject); } - var model = { - _id: convertToObjectId(landmarkObject._id), + const model = { + _id: safeObjectId(landmarkObject._id), title: landmarkObject.title, location: parseLocationObject(landmarkObject.location), - createdBy: parseUserObject(landmarkObject.createdBy), + createdBy: safeParse(parseUserObject, landmarkObject.createdBy), createdAt: convertToDate(landmarkObject.createdAt), updatedAt: convertToDate(landmarkObject.updatedAt), __v: landmarkObject.__v, @@ -96,25 +137,37 @@ function parseLandmarkObject(landmarkObject) { } function parseLocationObject(locationObject) { - console.log(JSON.stringify(locationObject)); - if (locationObject == null) return undefined; + if (!locationObject) return undefined; - var model = { + return { lat: locationObject.lat, lon: locationObject.lon, }; - - return model; } function convertToObjectId(id) { return new mongoose.Types.ObjectId(id); } +function safeObjectId(id) { + if (!id) return null; + return convertToObjectId(id); +} + function convertToDate(date) { + if (!date) return null; return new Date(date); } +function safeParse(fn, obj) { + if (!obj) return null; + try { + return fn(obj); + } catch (err) { + return null; + } +} + module.exports = { parseUserObject, parseBeaconObject, From 5e9f9c0f4a6a191766cfd046ca92211ffa608976 Mon Sep 17 00:00:00 2001 From: himanshu goyal Date: Thu, 17 Jul 2025 12:13:34 +0530 Subject: [PATCH 11/11] lint fix --- graphql/resolvers.js | 1 - 1 file changed, 1 deletion(-) diff --git a/graphql/resolvers.js b/graphql/resolvers.js index 688c1af..8903769 100644 --- a/graphql/resolvers.js +++ b/graphql/resolvers.js @@ -729,7 +729,6 @@ const resolvers = { const { beaconLocations, leaderID, followers, beaconID } = payload; const { userSOS, route, updatedUser, landmark } = beaconLocations; - // Check if user is part of this beacon const isFollower = followers.includes(user.id); const isLeader = leaderID == user.id;