I’m currently developing some utility code that I consider as a small library to help speed up CRUD operations using ExpressJS and MongoDB, with Mongoose as the ODM.
Initially, it worked quite well — it could quickly handle creating, reading, updating, and deleting records.
Later on, I wanted to improve it by integrating Mongoose’s populate feature to fetch related data.
However, this caused an issue where certain routes could no longer be detected correctly.
I’m hoping someone can take a look, help me fix the problem, or suggest a better solution — or even collaborate with me to improve the library further. Thank you in advance!
This is the server side
const mapModel = {
product: productsModel,
user:usersModel,
order:ordersModel,
review:reviewsModel,
};
function Method(app) {
app.all("/api/CRUD/:type/{/:id}", async (req, res) => {
const { type, id } = req.params;
console.log({ type,populate, id })
const data = req.body;
console.log({ type, id })
const models = mapModel[type];
if (!models) {
return res.status(400).json({
message: "Invalid type",
status: "error",
});
}
if (id) {
try {
let isExist = await models.findById(id);
if (!isExist) {
return res.json({
message: "Nothing found",
status: "error",
});
}
} catch (error) {
return res.json({
message: "Invalid ID format",
status: "error",
err: error,
});
}
}
// POST
if (req.method === "POST") {
try {
const newObj = new models(data);
await newObj.save();
return res.json({
message: "Post successful",
status: "ok",
});
} catch (error) {
return res.json({
message: "Post failed",
status: "error",
err: error,
});
}
}
// GET
else if (req.method === "GET") {
try {
const populate = req.query.populate
? JSON.parse(req.query.populate)
: null;
const keyword = req.query.q || "";
console.log(keyword)
let query;
if (id) {
query = models.findById(id);
} else {
if (keyword) {
query = models.find({
name: { $regex: keyword, $options: "i" },
});
} else {
query = models.find({});
}
}
if (Array.isArray(populate)) {
populate.forEach((field) => {
query = query.populate(field);
});
}
const result = await query.exec();
return res.json({
message: "Get successful",
data: result,
status: "ok",
});
} catch (error) {
return res.json({
message: "Get failed",
status: "error",
err: error,
});
}
}
// DELETE
else if (req.method === "DELETE") {
try {
if (id) {
await models.findOneAndDelete({ _id: id });
return res.json({
message: "Delete successful",
status: "ok",
});
} else {
await models.deleteMany({});
return res.json({
message: "Delete all successful",
status: "ok",
});
}
} catch (error) {
return res.json({
message: "Delete failed",
status: "error",
err: error,
});
}
}
// PUT
else if (req.method === "PUT") {
try {
const updated = await models.findByIdAndUpdate(id, data, { new: true });
return res.json({
message: "Update successful",
data: updated,
status: "ok",
});
} catch (error) {
return res.json({
message: "Update failed",
status: "error",
err: error,
});
}
}
});
}
Method(app)
This is the clients side
async function callApi(method, type, handle) {
let { id, data, populate, q } = handle;
let options = {
method,
headers: { "Content-Type": "application/json" },
};
let url = `/api/CRUD/${type}`;
if (id) url += `/${id}`;
let query = [];
if (populate) {
query.push(`populate=${encodeURIComponent(JSON.stringify(populate))}`);
}
if (q) {
query.push(`q=${encodeURIComponent(q)}`);
}
if (query.length > 0) {
url += "?" + query.join("&");
}
if (method !== "GET" && method !== "HEAD" && method !== "DELETE") {
options.body = JSON.stringify(data);
}
let res = await fetch(url, options);
const contentType = res.headers.get("content-type");
if (contentType && contentType.includes("application/json")) {
return await res.json();
} else {
const text = await res.text();
console.warn("text);
return text;
}
}
document.querySelector("#c").onclick =async function(){
let data = await callApi("GET", "order", {
id: "6864b1b2372ff33aa986b123",
data: null,
populate:["userId"],
q:"teas"
});
}
Top comments (0)