issue-tracker/routes/api.js

115 lines
3.6 KiB
JavaScript
Raw Permalink Normal View History

2023-09-22 11:49:59 +02:00
"use strict";
const { randomBytes } = require("node:crypto");
2017-02-18 20:21:34 +01:00
module.exports = function (app) {
2023-09-22 11:49:59 +02:00
const projectsIssues = {};
const compulsoryFields = new Set(["issue_title", "issue_text", "created_by"]);
const optionalFields = new Set(["assigned_to", "status_text"]);
const updateFields = new Set([
"issue_title",
"issue_text",
"created_by",
"assigned_to",
"status_text",
]);
const queryFilters = new Set([
"_id",
"issue_title",
"issue_text",
"created_by",
"assigned_to",
"status_text",
"open",
]);
const autoGeneratedFields = new Map([
// FXIME: Not handling potential ID collisions
["_id", () => randomBytes(20).toString("hex")],
["created_on", () => new Date().toISOString()],
["updated_on", () => new Date().toISOString()],
["open", () => true],
]);
2017-02-18 20:21:34 +01:00
2023-09-22 11:49:59 +02:00
app
.route("/api/issues/:project")
.get(function (req, res) {
const project = req.params.project;
const issues = projectsIssues[project];
const filters = {};
for (const name of queryFilters) {
if (req.query[name])
filters[name] = Array.isArray(req.query[name])
? req.query[name][0]
: req.query[name];
}
if (!issues) res.status(404).json({ error: "Project not found" });
else
res.json(
Object.values(issues).filter((issue) =>
Object.entries(filters).every(([k, v]) => issue[k] === v)
)
);
2017-02-18 20:21:34 +01:00
})
2023-09-22 11:49:59 +02:00
.post(function (req, res) {
const project = req.params.project;
if (!project) {
res.status(400).json({ error: "Project not specified" });
return;
}
const issue = {};
for (const name of compulsoryFields) {
if (!req.body[name]) {
res.status(400).json({ error: "required field(s) missing" });
return;
}
issue[name] = req.body[name];
}
optionalFields.forEach((name) => (issue[name] = req.body[name] ?? ""));
autoGeneratedFields.forEach(
(generator, name) => (issue[name] = generator())
);
if (!projectsIssues[project])
projectsIssues[project] = { [issue._id]: { ...issue } };
else projectsIssues[project][issue._id] = { ...issue };
res.json(issue);
2017-02-18 20:21:34 +01:00
})
2023-09-22 11:49:59 +02:00
.put(function (req, res) {
const project = req.params.project;
if (!project) res.status(400).json({ error: "Project not specified" });
const _id = req.body._id;
const fields = {};
updateFields.forEach((name) => {
if (req.body[name]) fields[name] = req.body[name];
});
if (!_id) res.status(400).json({ error: "missing _id" });
else if (!projectsIssues[project][_id])
res.status(404).json({ error: "could not update", _id: _id });
else if (!Object.entries(fields).length)
res.status(400).json({ error: "no update field(s) sent", _id: _id });
else {
Object.entries(fields).forEach(
([name, value]) => (projectsIssues[project][_id][name] = value)
);
res.json({ result: "successfully updated", _id: _id });
}
2017-02-18 20:21:34 +01:00
})
2023-09-22 11:49:59 +02:00
.delete(function (req, res) {
const project = req.params.project;
if (!project) {
res.status(400).json({ error: "Project not specified" });
return;
}
const _id = req.body._id;
if (!_id) res.status(400).json({ error: "missing _id" });
else if (!projectsIssues[project][_id])
res.status(404).json({ error: "could not delete", _id: _id });
else {
delete projectsIssues[project][_id];
res.json({ result: "successfully deleted", _id: _id });
}
2017-02-18 20:21:34 +01:00
});
};