Repository: manikandanraji/instaclone-backend
Branch: master
Commit: 5124424007f6
Files: 18
Total size: 23.5 KB
Directory structure:
gitextract_g_axr77_/
├── .gitignore
├── README.md
├── package.json
└── src/
├── controllers/
│ ├── auth.js
│ ├── post.js
│ └── user.js
├── middlewares/
│ ├── asyncHandler.js
│ ├── auth.js
│ └── errorHandler.js
├── models/
│ ├── Comment.js
│ ├── Post.js
│ └── User.js
├── routes/
│ ├── auth.js
│ ├── post.js
│ └── user.js
├── seeder.js
├── server.js
└── utils/
└── db.js
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
node_modules/
.env
================================================
FILE: README.md
================================================
# Instaclone Backend
**NOTE: As of 10-06-2022 19:52 IST, I am archiving this repository. It was fun while it lasted.**
Instagram clone using MERN stack
This is the backend repo built with Express and MongoDB. If you looking for the frontend repo, [click here](https://github.com/manikandanraji/instaclone-frontend)
## Running Locally
At the root of the project, you should have a .env with the following contents
```js
JWT_SECRET=<yoursupersecret>
JWT_EXPIRE=30d // or anything you prefer
MONGOURI=<your_mongodb_connection_uri>
```
Then run <code>npm i && npm run dev</code> to start the development server
## Deploying the backend to heroku
First create an heroku account and install the heroku cli globally and login
```bash
npm i -g heroku
heroku login
```
Once logged in, create a new heroku application and push it to the remote 'heroku'
```bash
heroku create
git push heroku master
```
Then we need to manually setup the environmental variables using the heroku dashboard
## UI
### Home

### Explore

### Followers

### Profile

### Edit Profile

### New Post

================================================
FILE: package.json
================================================
{
"name": "instaclone-backend",
"version": "1.0.0",
"description": "Instaclone backend using Express, MongoDB",
"main": "src/server.js",
"scripts": {
"start": "NODE_ENV=production node src/server",
"dev": "nodemon src/server"
},
"author": "Manikandan Raji",
"license": "MIT",
"dependencies": {
"bcryptjs": "^2.4.3",
"cors": "^2.8.5",
"dotenv": "^8.2.0",
"express": "^4.17.1",
"jsonwebtoken": "^8.5.1",
"mongoose": "^5.9.19",
"nodemon": "^2.0.4"
}
}
================================================
FILE: src/controllers/auth.js
================================================
const User = require("../models/User");
const asyncHandler = require("../middlewares/asyncHandler");
exports.login = asyncHandler(async (req, res, next) => {
const { email, password } = req.body;
// make sure the email, pw is not empty
if (!email || !password) {
return next({
message: "Please provide email and password",
statusCode: 400,
});
}
// check if the user exists
const user = await User.findOne({ email });
if (!user) {
return next({
message: "The email is not yet registered to an accout",
statusCode: 400,
});
}
// if exists, make sure the password matches
const match = await user.checkPassword(password);
if (!match) {
return next({ message: "The password does not match", statusCode: 400 });
}
const token = user.getJwtToken();
// then send json web token as response
res.status(200).json({ success: true, token });
});
exports.signup = asyncHandler(async (req, res, next) => {
const { fullname, username, email, password } = req.body;
const user = await User.create({ fullname, username, email, password });
const token = user.getJwtToken();
res.status(200).json({ success: true, token });
});
exports.me = asyncHandler(async (req, res, next) => {
const { avatar, username, fullname, email, _id, website, bio } = req.user;
res
.status(200)
.json({
success: true,
data: { avatar, username, fullname, email, _id, website, bio },
});
});
================================================
FILE: src/controllers/post.js
================================================
const mongoose = require("mongoose");
const Post = require("../models/Post");
const User = require("../models/User");
const Comment = require("../models/Comment");
const asyncHandler = require("../middlewares/asyncHandler");
exports.getPosts = asyncHandler(async (req, res, next) => {
const posts = await Post.find();
res.status(200).json({ success: true, data: posts });
});
exports.getPost = asyncHandler(async (req, res, next) => {
const post = await Post.findById(req.params.id)
.populate({
path: "comments",
select: "text",
populate: {
path: "user",
select: "username avatar",
},
})
.populate({
path: "user",
select: "username avatar",
})
.lean()
.exec();
if (!post) {
return next({
message: `No post found for id ${req.params.id}`,
statusCode: 404,
});
}
// is the post belongs to loggedin user?
post.isMine = req.user.id === post.user._id.toString();
// is the loggedin user liked the post??
const likes = post.likes.map((like) => like.toString());
post.isLiked = likes.includes(req.user.id);
// is the loggedin user liked the post??
const savedPosts = req.user.savedPosts.map((post) => post.toString());
post.isSaved = savedPosts.includes(req.params.id);
// is the comment on the post belongs to the logged in user?
post.comments.forEach((comment) => {
comment.isCommentMine = false;
const userStr = comment.user._id.toString();
if (userStr === req.user.id) {
comment.isCommentMine = true;
}
});
res.status(200).json({ success: true, data: post });
});
exports.deletePost = asyncHandler(async (req, res, next) => {
const post = await Post.findById(req.params.id);
if (!post) {
return next({
message: `No post found for id ${req.params.id}`,
statusCode: 404,
});
}
if (post.user.toString() !== req.user.id) {
return next({
message: "You are not authorized to delete this post",
statusCode: 401,
});
}
await User.findByIdAndUpdate(req.user.id, {
$pull: { posts: req.params.id },
$inc: { postCount: -1 },
});
await post.remove();
res.status(200).json({ success: true, data: {} });
});
exports.addPost = asyncHandler(async (req, res, next) => {
const { caption, files, tags } = req.body;
const user = req.user.id;
let post = await Post.create({ caption, files, tags, user });
await User.findByIdAndUpdate(req.user.id, {
$push: { posts: post._id },
$inc: { postCount: 1 },
});
post = await post
.populate({ path: "user", select: "avatar username fullname" })
.execPopulate();
res.status(200).json({ success: true, data: post });
});
exports.toggleLike = asyncHandler(async (req, res, next) => {
// make sure that the post exists
const post = await Post.findById(req.params.id);
if (!post) {
return next({
message: `No post found for id ${req.params.id}`,
statusCode: 404,
});
}
if (post.likes.includes(req.user.id)) {
const index = post.likes.indexOf(req.user.id);
post.likes.splice(index, 1);
post.likesCount = post.likesCount - 1;
await post.save();
} else {
post.likes.push(req.user.id);
post.likesCount = post.likesCount + 1;
await post.save();
}
res.status(200).json({ success: true, data: {} });
});
exports.addComment = asyncHandler(async (req, res, next) => {
const post = await Post.findById(req.params.id);
if (!post) {
return next({
message: `No post found for id ${req.params.id}`,
statusCode: 404,
});
}
let comment = await Comment.create({
user: req.user.id,
post: req.params.id,
text: req.body.text,
});
post.comments.push(comment._id);
post.commentsCount = post.commentsCount + 1;
await post.save();
comment = await comment
.populate({ path: "user", select: "avatar username fullname" })
.execPopulate();
res.status(200).json({ success: true, data: comment });
});
exports.deleteComment = asyncHandler(async (req, res, next) => {
const post = await Post.findById(req.params.id);
if (!post) {
return next({
message: `No post found for id ${req.params.id}`,
statusCode: 404,
});
}
const comment = await Comment.findOne({
_id: req.params.commentId,
post: req.params.id,
});
if (!comment) {
return next({
message: `No comment found for id ${req.params.id}`,
statusCode: 404,
});
}
if (comment.user.toString() !== req.user.id) {
return next({
message: "You are not authorized to delete this comment",
statusCode: 401,
});
}
// remove the comment from the post
const index = post.comments.indexOf(comment._id);
post.comments.splice(index, 1);
post.commentsCount = post.commentsCount - 1;
await post.save();
await comment.remove();
res.status(200).json({ success: true, data: {} });
});
exports.searchPost = asyncHandler(async (req, res, next) => {
if (!req.query.caption && !req.query.tag) {
return next({
message: "Please enter either caption or tag to search for",
statusCode: 400,
});
}
let posts = [];
if (req.query.caption) {
const regex = new RegExp(req.query.caption, "i");
posts = await Post.find({ caption: regex });
}
if (req.query.tag) {
posts = posts.concat([await Post.find({ tags: req.query.tag })]);
}
res.status(200).json({ success: true, data: posts });
});
exports.toggleSave = asyncHandler(async (req, res, next) => {
// make sure that the post exists
const post = await Post.findById(req.params.id);
if (!post) {
return next({
message: `No post found for id ${req.params.id}`,
statusCode: 404,
});
}
const { user } = req;
if (user.savedPosts.includes(req.params.id)) {
console.log("removing saved post");
await User.findByIdAndUpdate(user.id, {
$pull: { savedPosts: req.params.id },
});
} else {
console.log("saving post");
await User.findByIdAndUpdate(user.id, {
$push: { savedPosts: req.params.id },
});
}
res.status(200).json({ success: true, data: {} });
});
================================================
FILE: src/controllers/user.js
================================================
const User = require("../models/User");
const Post = require("../models/Post");
const asyncHandler = require("../middlewares/asyncHandler");
exports.getUsers = asyncHandler(async (req, res, next) => {
let users = await User.find().select("-password").lean().exec();
users.forEach((user) => {
user.isFollowing = false;
const followers = user.followers.map((follower) => follower._id.toString());
if (followers.includes(req.user.id)) {
user.isFollowing = true;
}
});
users = users.filter((user) => user._id.toString() !== req.user.id);
res.status(200).json({ success: true, data: users });
});
exports.getUser = asyncHandler(async (req, res, next) => {
const user = await User.findOne({ username: req.params.username })
.select("-password")
.populate({ path: "posts", select: "files commentsCount likesCount" })
.populate({ path: "savedPosts", select: "files commentsCount likesCount" })
.populate({ path: "followers", select: "avatar username fullname" })
.populate({ path: "following", select: "avatar username fullname" })
.lean()
.exec();
if (!user) {
return next({
message: `The user ${req.params.username} is not found`,
statusCode: 404,
});
}
user.isFollowing = false;
const followers = user.followers.map((follower) => follower._id.toString());
user.followers.forEach((follower) => {
follower.isFollowing = false;
if (req.user.following.includes(follower._id.toString())) {
follower.isFollowing = true;
}
});
user.following.forEach((user) => {
user.isFollowing = false;
if (req.user.following.includes(user._id.toString())) {
user.isFollowing = true;
}
});
if (followers.includes(req.user.id)) {
user.isFollowing = true;
}
user.isMe = req.user.id === user._id.toString();
res.status(200).json({ success: true, data: user });
});
exports.follow = asyncHandler(async (req, res, next) => {
// make sure the user exists
const user = await User.findById(req.params.id);
if (!user) {
return next({
message: `No user found for id ${req.params.id}`,
statusCode: 404,
});
}
// make the sure the user is not the logged in user
if (req.params.id === req.user.id) {
return next({ message: "You can't unfollow/follow yourself", status: 400 });
}
// only follow if the user is not following already
if (user.followers.includes(req.user.id)) {
return next({ message: "You are already following him", status: 400 });
}
await User.findByIdAndUpdate(req.params.id, {
$push: { followers: req.user.id },
$inc: { followersCount: 1 },
});
await User.findByIdAndUpdate(req.user.id, {
$push: { following: req.params.id },
$inc: { followingCount: 1 },
});
res.status(200).json({ success: true, data: {} });
});
exports.unfollow = asyncHandler(async (req, res, next) => {
const user = await User.findById(req.params.id);
if (!user) {
return next({
message: `No user found for ID ${req.params.id}`,
statusCode: 404,
});
}
// make the sure the user is not the logged in user
if (req.params.id === req.user.id) {
return next({ message: "You can't follow/unfollow yourself", status: 400 });
}
await User.findByIdAndUpdate(req.params.id, {
$pull: { followers: req.user.id },
$inc: { followersCount: -1 },
});
await User.findByIdAndUpdate(req.user.id, {
$pull: { following: req.params.id },
$inc: { followingCount: -1 },
});
res.status(200).json({ success: true, data: {} });
});
exports.feed = asyncHandler(async (req, res, next) => {
const following = req.user.following;
const users = await User.find()
.where("_id")
.in(following.concat([req.user.id]))
.exec();
const postIds = users.map((user) => user.posts).flat();
const posts = await Post.find()
.populate({
path: "comments",
select: "text",
populate: { path: "user", select: "avatar fullname username" },
})
.populate({ path: "user", select: "avatar fullname username" })
.sort("-createdAt")
.where("_id")
.in(postIds)
.lean()
.exec();
posts.forEach((post) => {
// is the loggedin user liked the post
post.isLiked = false;
const likes = post.likes.map((like) => like.toString());
if (likes.includes(req.user.id)) {
post.isLiked = true;
}
// is the loggedin saved this post
post.isSaved = false;
const savedPosts = req.user.savedPosts.map((post) => post.toString());
if (savedPosts.includes(post._id)) {
post.isSaved = true;
}
// is the post belongs to the loggedin user
post.isMine = false;
if (post.user._id.toString() === req.user.id) {
post.isMine = true;
}
// is the comment belongs to the loggedin user
post.comments.map((comment) => {
comment.isCommentMine = false;
if (comment.user._id.toString() === req.user.id) {
comment.isCommentMine = true;
}
});
});
res.status(200).json({ success: true, data: posts });
});
exports.searchUser = asyncHandler(async (req, res, next) => {
if (!req.query.username) {
return next({ message: "The username cannot be empty", statusCode: 400 });
}
const regex = new RegExp(req.query.username, "i");
const users = await User.find({ username: regex });
res.status(200).json({ success: true, data: users });
});
exports.editUser = asyncHandler(async (req, res, next) => {
const { avatar, username, fullname, website, bio, email } = req.body;
const fieldsToUpdate = {};
if (avatar) fieldsToUpdate.avatar = avatar;
if (username) fieldsToUpdate.username = username;
if (fullname) fieldsToUpdate.fullname = fullname;
if (email) fieldsToUpdate.email = email;
const user = await User.findByIdAndUpdate(
req.user.id,
{
$set: { ...fieldsToUpdate, website, bio },
},
{
new: true,
runValidators: true,
}
).select("avatar username fullname email bio website");
res.status(200).json({ success: true, data: user });
});
================================================
FILE: src/middlewares/asyncHandler.js
================================================
const asyncHandler = (fn) => (req, res, next) =>
Promise.resolve(fn(req, res, next)).catch(next);
module.exports = asyncHandler;
================================================
FILE: src/middlewares/auth.js
================================================
const jwt = require("jsonwebtoken");
const User = require("../models/User");
exports.protect = async (req, res, next) => {
let token;
if (
req.headers.authorization &&
req.headers.authorization.startsWith("Bearer")
) {
token = req.headers.authorization.split(" ")[1];
}
if (!token) {
return next({
message: "You need to be logged in to visit this route",
statusCode: 403,
});
}
try {
const decoded = jwt.verify(token, process.env.JWT_SECRET);
const user = await User.findById(decoded.id).select("-password");
if (!user) {
return next({ message: `No user found for ID ${decoded.id}` });
}
req.user = user;
next();
} catch (err) {
next({
message: "You need to be logged in to visit this route",
statusCode: 403,
});
}
};
================================================
FILE: src/middlewares/errorHandler.js
================================================
const errorHandler = (err, req, res, next) => {
console.log(err);
let message = err.message || "Internal server error";
let statusCode = err.statusCode || 500;
if (err.code === 11000) {
message = "Duplicate key";
if (err.keyValue.email) {
message = "The email is already taken";
}
if (err.keyValue.username) {
message = "The username is already taken";
}
statusCode = 400;
}
if (err.name === "ValidationError") {
const fields = Object.keys(err.errors);
fields.map((field) => {
if (err.errors[field].kind === "maxlength") {
message = "Password should be maximum of 12 characters";
} else {
message = "Password should be minimum of 6 characters";
}
});
statusCode = 400;
}
if (err.name === "CastError") {
message = "The ObjectID is malformed";
statusCode = 400;
}
res.status(statusCode).json({ success: false, message });
};
module.exports = errorHandler;
================================================
FILE: src/models/Comment.js
================================================
const mongoose = require("mongoose");
const CommentSchema = new mongoose.Schema({
user: {
type: mongoose.Schema.ObjectId,
ref: "User",
required: true,
},
post: {
type: mongoose.Schema.ObjectId,
ref: "Post",
required: true,
},
text: {
type: String,
required: [true, "Please enter the comment"],
trim: true,
},
createdAt: {
type: Date,
default: Date.now,
},
});
module.exports = mongoose.model("Comment", CommentSchema);
================================================
FILE: src/models/Post.js
================================================
const mongoose = require("mongoose");
const PostSchema = new mongoose.Schema({
user: {
type: mongoose.Schema.ObjectId,
ref: "User",
required: true,
},
caption: {
type: String,
required: [true, "Please enter the caption"],
trim: true,
},
tags: {
type: [String],
},
files: {
type: [String],
validate: (v) => v === null || v.length > 0,
},
likes: [{ type: mongoose.Schema.ObjectId, ref: "User" }],
likesCount: {
type: Number,
default: 0,
},
comments: [{ type: mongoose.Schema.ObjectId, ref: "Comment" }],
commentsCount: {
type: Number,
default: 0,
},
createdAt: {
type: Date,
default: Date.now,
},
});
module.exports = mongoose.model("Post", PostSchema);
================================================
FILE: src/models/User.js
================================================
const mongoose = require("mongoose");
const jwt = require("jsonwebtoken");
const bcrypt = require("bcryptjs");
const UserSchema = new mongoose.Schema({
fullname: {
type: String,
required: [true, "Please enter your fullname"],
trim: true,
},
username: {
type: String,
required: [true, "Please enter your username"],
trim: true,
unique: true,
},
email: {
type: String,
required: [true, "Please enter your email"],
trim: true,
lowercase: true,
unique: true,
},
password: {
type: String,
required: [true, "Please enter your password"],
minlength: [6, "Password should be atleast minimum of 6 characters"],
maxlength: [12, "Password should be maximum of 12 characters"],
},
avatar: {
type: String,
default:
"https://res.cloudinary.com/tylerdurden/image/upload/v1602657481/random/pngfind.com-default-image-png-6764065_krremh.png",
},
bio: String,
website: String,
followers: [{ type: mongoose.Schema.ObjectId, ref: "User" }],
followersCount: {
type: Number,
default: 0,
},
followingCount: {
type: Number,
default: 0,
},
following: [{ type: mongoose.Schema.ObjectId, ref: "User" }],
posts: [{ type: mongoose.Schema.ObjectId, ref: "Post" }],
postCount: {
type: Number,
default: 0,
},
savedPosts: [{ type: mongoose.Schema.ObjectId, ref: "Post" }],
createdAt: {
type: Date,
default: Date.now,
},
});
UserSchema.pre("save", async function (next) {
const salt = await bcrypt.genSalt(10);
this.password = await bcrypt.hash(this.password, salt);
next();
});
UserSchema.methods.getJwtToken = function () {
return jwt.sign({ id: this._id }, process.env.JWT_SECRET, {
expiresIn: process.env.JWT_EXPIRE,
});
};
UserSchema.methods.checkPassword = async function (password) {
return await bcrypt.compare(password, this.password);
};
module.exports = mongoose.model("User", UserSchema);
================================================
FILE: src/routes/auth.js
================================================
const express = require("express");
const router = express.Router();
const { login, signup, me } = require("../controllers/auth");
const { protect } = require("../middlewares/auth");
router.route("/signup").post(signup);
router.route("/login").post(login);
router.route("/me").get(protect, me);
module.exports = router;
================================================
FILE: src/routes/post.js
================================================
const express = require("express");
const router = express.Router();
const {
getPosts,
getPost,
addPost,
deletePost,
toggleLike,
toggleSave,
addComment,
deleteComment,
searchPost,
} = require("../controllers/post");
const { protect } = require("../middlewares/auth");
router.route("/").get(getPosts).post(protect, addPost);
router.route("/search").get(searchPost);
router.route("/:id").get(protect, getPost).delete(protect, deletePost);
router.route("/:id/togglelike").get(protect, toggleLike);
router.route("/:id/togglesave").get(protect, toggleSave);
router.route("/:id/comments").post(protect, addComment);
router.route("/:id/comments/:commentId").delete(protect, deleteComment);
module.exports = router;
================================================
FILE: src/routes/user.js
================================================
const express = require("express");
const router = express.Router();
const {
getUsers,
getUser,
follow,
unfollow,
feed,
searchUser,
editUser,
} = require("../controllers/user");
const { protect } = require("../middlewares/auth");
router.route("/").get(protect, getUsers);
router.route("/").put(protect, editUser);
router.route("/feed").get(protect, feed);
router.route("/search").get(searchUser);
router.route("/:username").get(protect, getUser);
router.route("/:id/follow").get(protect, follow);
router.route("/:id/unfollow").get(protect, unfollow);
module.exports = router;
================================================
FILE: src/seeder.js
================================================
require("dotenv").config();
const mongoose = require("mongoose");
const User = require("./models/User");
const Comment = require("./models/Comment");
const Post = require("./models/Post");
mongoose.connect(process.env.MONGOURI, {
useCreateIndex: true,
useNewUrlParser: true,
useUnifiedTopology: true,
useFindAndModify: false,
});
const deleteData = async () => {
try {
await User.deleteMany();
await Comment.deleteMany();
await Post.deleteMany();
console.log("Deleted data...");
process.exit();
} catch (err) {
console.error(err);
}
};
if (process.argv[2] === "-d") {
deleteData();
} else {
console.log("not enough arguments");
process.exit(1);
}
================================================
FILE: src/server.js
================================================
require("dotenv").config();
const express = require("express");
const cors = require("cors");
const auth = require("./routes/auth");
const user = require("./routes/user");
const post = require("./routes/post");
const connectToDb = require("./utils/db");
const errorHandler = require("./middlewares/errorHandler");
const app = express();
connectToDb();
app.use(express.json());
app.use(cors());
app.use("/api/v1/auth", auth);
app.use("/api/v1/users", user);
app.use("/api/v1/posts", post);
app.use(errorHandler);
const PORT = process.env.PORT || 5000;
app.listen(
PORT,
console.log(`server started in ${process.env.NODE_ENV} mode at port ${PORT}`)
);
================================================
FILE: src/utils/db.js
================================================
const mongoose = require("mongoose");
const connectToDb = async () => {
try {
const connection = await mongoose.connect(process.env.MONGOURI, {
useCreateIndex: true,
useNewUrlParser: true,
useUnifiedTopology: true,
useFindAndModify: false,
});
console.log(`Connected to database ${connection.connections[0].name}`);
} catch (err) {
console.error(err);
}
};
module.exports = connectToDb;
gitextract_g_axr77_/
├── .gitignore
├── README.md
├── package.json
└── src/
├── controllers/
│ ├── auth.js
│ ├── post.js
│ └── user.js
├── middlewares/
│ ├── asyncHandler.js
│ ├── auth.js
│ └── errorHandler.js
├── models/
│ ├── Comment.js
│ ├── Post.js
│ └── User.js
├── routes/
│ ├── auth.js
│ ├── post.js
│ └── user.js
├── seeder.js
├── server.js
└── utils/
└── db.js
SYMBOL INDEX (1 symbols across 1 files) FILE: src/server.js constant PORT (line 22) | const PORT = process.env.PORT || 5000;
Condensed preview — 18 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (26K chars).
[
{
"path": ".gitignore",
"chars": 19,
"preview": "node_modules/\n.env\n"
},
{
"path": "README.md",
"chars": 1333,
"preview": "# Instaclone Backend\n\n**NOTE: As of 10-06-2022 19:52 IST, I am archiving this repository. It was fun while it lasted.**\n"
},
{
"path": "package.json",
"chars": 505,
"preview": "{\n \"name\": \"instaclone-backend\",\n \"version\": \"1.0.0\",\n \"description\": \"Instaclone backend using Express, MongoDB\",\n "
},
{
"path": "src/controllers/auth.js",
"chars": 1475,
"preview": "const User = require(\"../models/User\");\nconst asyncHandler = require(\"../middlewares/asyncHandler\");\n\nexports.login = as"
},
{
"path": "src/controllers/post.js",
"chars": 6139,
"preview": "const mongoose = require(\"mongoose\");\nconst Post = require(\"../models/Post\");\nconst User = require(\"../models/User\");\nco"
},
{
"path": "src/controllers/user.js",
"chars": 6055,
"preview": "const User = require(\"../models/User\");\nconst Post = require(\"../models/Post\");\nconst asyncHandler = require(\"../middlew"
},
{
"path": "src/middlewares/asyncHandler.js",
"chars": 132,
"preview": "const asyncHandler = (fn) => (req, res, next) =>\n Promise.resolve(fn(req, res, next)).catch(next);\n\nmodule.exports = as"
},
{
"path": "src/middlewares/auth.js",
"chars": 826,
"preview": "const jwt = require(\"jsonwebtoken\");\nconst User = require(\"../models/User\");\n\nexports.protect = async (req, res, next) ="
},
{
"path": "src/middlewares/errorHandler.js",
"chars": 979,
"preview": "const errorHandler = (err, req, res, next) => {\n console.log(err);\n\n let message = err.message || \"Internal server err"
},
{
"path": "src/models/Comment.js",
"chars": 481,
"preview": "const mongoose = require(\"mongoose\");\n\nconst CommentSchema = new mongoose.Schema({\n user: {\n type: mongoose.Schema.O"
},
{
"path": "src/models/Post.js",
"chars": 746,
"preview": "const mongoose = require(\"mongoose\");\n\nconst PostSchema = new mongoose.Schema({\n user: {\n type: mongoose.Schema.Obje"
},
{
"path": "src/models/User.js",
"chars": 1945,
"preview": "const mongoose = require(\"mongoose\");\nconst jwt = require(\"jsonwebtoken\");\nconst bcrypt = require(\"bcryptjs\");\n\nconst Us"
},
{
"path": "src/routes/auth.js",
"chars": 322,
"preview": "const express = require(\"express\");\nconst router = express.Router();\nconst { login, signup, me } = require(\"../controlle"
},
{
"path": "src/routes/post.js",
"chars": 728,
"preview": "const express = require(\"express\");\nconst router = express.Router();\nconst {\n getPosts,\n getPost,\n addPost,\n deleteP"
},
{
"path": "src/routes/user.js",
"chars": 592,
"preview": "const express = require(\"express\");\nconst router = express.Router();\nconst {\n getUsers,\n getUser,\n follow,\n unfollow"
},
{
"path": "src/seeder.js",
"chars": 694,
"preview": "require(\"dotenv\").config();\nconst mongoose = require(\"mongoose\");\nconst User = require(\"./models/User\");\nconst Comment ="
},
{
"path": "src/server.js",
"chars": 659,
"preview": "require(\"dotenv\").config();\nconst express = require(\"express\");\nconst cors = require(\"cors\");\nconst auth = require(\"./ro"
},
{
"path": "src/utils/db.js",
"chars": 436,
"preview": "const mongoose = require(\"mongoose\");\n\nconst connectToDb = async () => {\n try {\n const connection = await mongoose.c"
}
]
About this extraction
This page contains the full source code of the manikandanraji/instaclone-backend GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 18 files (23.5 KB), approximately 6.7k tokens, and a symbol index with 1 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.