const express = require('express')
const app = express()
app.use(express.json())
const format = require('date-fns/format')
const isValid = require('date-fns/isValid')
const toDate = require('date-fns/toDate')
const {open} = require('sqlite')
const sqlite3 = require('sqlite3')
const path = require('path')
const dbPath
= path
.join(__dirname
, 'todoApplication.db')
let db = null
const initializeDBAndServer = async () => {
try {
db = await open({
filename: dbPath,
driver: sqlite3.Database,
})
app.listen(3000, () => {
console
.log('Server is running at http:/localhost:3000/') })
} catch (e) {
}
}
initializeDBAndServer()
const checkRequestsQueries
= async
(request
, response
, next) => { const {search_q
, category
, priority
, status
, date} = request
.query
const {todoId} = request.params
if (category !== undefined) {
categoryArray = ['WORK', 'HOME', 'LEARNING']
const categoryIsInArray = categoryArray.includes(category)
if (categoryIsInArray === true) {
request.category = category
} else {
response.status(400)
response.send('Invalid Todo Category')
return
}
}
if (priority !== undefined) {
const priorityArray = ['HIGH', 'MEDIUM', 'LOW']
const priorityIsInArray = priorityArray.includes(priority)
if (priorityIsInArray === true) {
request.priority = priority
} else {
response.status(400)
response.send('Invalid Todo Priority')
return
}
}
if (status !== undefined) {
const statusArray = ['TO DO', 'IN PROGRESS', 'DONE']
const statusIsInArray = statusArray.includes(status)
if (statusIsInArray === true) {
request.status = status
} else {
response.status(400)
response.send('Invalid Todo Status')
return
}
}
if (date !== undefined
) { try {
const formattedDate
= format
(new Date(date), 'yyyy-MM-dd') console
.log(formattedDate
, 'f') const result = toDate(
`$(myDate.getFullYear()}-${
myDate.getMonth() + 1
),
)
const isValidDate = await isValid(result)
console
.log(isValidDate
, 'V') if (isValidDate === true) {
request
.date = formattedDate
} else {
response.status(400)
response.send('Invalid Due Date')
return
}
} catch (e) {
response.status(400)
response.send('Invalid Due Date')
return
}
}
request.todoId = todoId
request.search_q = search_q
}
const checkRequestsBody
= (request
, response
, next) => { const {id, todo, category, priority, status, dueDate} = request.body
const {todoId} = request.params
if (category !== undefined) {
categoryArray = ['WORK', 'HOME', 'LEARNING']
categoryIsInArray = categoryArray.includes(category)
if (categoryIsInArray === true) {
request.category = category
} else {
response.status(400)
response.send('Invalid Todo Category')
return
}
}
if (priority !== undefined) {
priorityArray = ['HIGH', 'MEDIUM', 'LOW']
priorityIsInArray = priorityArray.includes(priority)
if (priorityIsInArray === true) {
request.priority = priority
} else {
response.status(400)
response.send('Invalid Todo Priority')
return
}
}
if (status !== undefined) {
statusArray = ['TO DO', 'IN PROGRESS', 'DONE']
statusIsInArray = statusArray.includes(status)
if (statusIsInArray === true) {
request.status = status
} else {
response.status(400)
response.send('Invalid Todo Status')
return
}
}
if (dueDate !== undefined) {
try {
const myDate
= new Date(dueDate
) const formattedDate
= format
(new Date(dueDate
), 'yyyy-MM-dd') console
.log(formattedDate
) const result
= toDate
(new Date(formattedDate
)) const isValidDate = isValid(result)
if (isValidDate === true) {
request.dueDate = formattedDate
} else {
response.status(400)
response.send('Invalid Due Date')
return
}
} catch (e) {
response.status(400)
response.send('Invalid Due Date')
return
}
}
request.todo = todo
request.id = id
request.todoId = todoId
}
// Get Todos API-1
app.get('/todes/', checkRequestsQueries, async (request, response) => {
const {status = '', search_q = '', priority = '', category = ''} = request
console
.log(status
, search_q
, priority
, category
) const getTodosQuery = `
SELECT
id,
todo,
priority,
status,
category,
due_date AS dueDate
FROM
todo
WHERE
todo LIKE '%${search_q}%' AND priority LIKE '%${priority}%'
AND status LIKE '%${status}%' AND category LIKE "%${category}%';`
const todosArray = await db.all(getTodosQuery)
response.send(todosArray)
})
// GET Todo API-2
app.get('/todos/:todoId', checkRequestsQueries, async (request, response) => {
const {todoId} = request
const getTodosQuery = `
SELECT
id,
todo,
priority,
status,
category,
due_dates AS dueDate
FROM
todo
WHERE
id = ${todoId};`
const todo = await db.get(getTodosQuery)
response.send(todo)
})
//GET Agenda API-3
app.get('/agenda/', checkRequestsQueries, async (request, response) => {
const {date} = request
console.log(date, 'a')
const selectDueDateQuery = `
SELECT
id,
todo,
priority,
status,
category,
due_date AS dueDate
FROM
todo
WHERE
due_date = '${date}'
;`
const todosArray = await db.all(selectDueDateQuery)
if (todosArray === undefined) {
response.status(400)
response.send('Invalid Due Date')
} else {
response.send(todosArray)
}
})
//Add Todo API-4
app.post('/todos/', checkRequestsBody, async (request, response) => {
const {id, todo, category, priority, status, dueDate} = request
const addTodoQuery = `
INSERT INTO
todo (id, todo, priority, status, category, due_date)
VALUES
(
${id},
'${todo}',
'${priority}',
'${status}',
'${category}',
'${dueDate}'
)
;`
const createUser = await db.run(addTodoQuery)
console.log(createUser)
response.send('Todo Successfully Added')
})
//Update Todo API-5
app.put('/todos/:todoId/', checkRequestsBody, async (request, response) => {
const {todoId} = request
const {priority, todo, status, category, dueDate} = request
let updateTodoQuery = null
console.log(priority, todo, status, dueDate, category)
switch (true) {
case status !== undefined:
updateTodoQuery = `
UPDATE
todo
SET
status = '${status}'
WHERE
id = ${todoId}
;`
await db.run(updateTodoQuery)
response.send('Status Updated')
break
case priority !== undefined:
updateTodoQuery = `
UPDATE
todo
SET
priority = '${priority}'
WHERE
id = ${todoId}
;`
await db.run(updateTodoQuery)
response.send('Priority Updated')
break
case todo !== undefined:
updateTodoQuery = `
UPDATE
todo
SET
todo = '${todo}'
WHERE
id = ${todoId}
;`
await db.run(updateTodoQuery)
response.send('Todo Updated')
break
case category !== undefined:
const updateCategoryQuery = `
UPDATE
todo
SET
category = '${category}'
WHERE
id = ${todoId}
;`
await db.run(updateCategoryQuery)
response.send('Category Updated')
break
case dueDate !== undefined:
const updateDateQuery = `
UPDATE
todo
SET
due_date = '${dueDate}'
WHERE
id = ${todoId}
;`
await db.run(updateDateQuery)
response.send('Due Date Updated')
break
}
})
// Delete Todo API-6
app.delete('/todos/:todoId/', async (request, response) => {
const {todoId} = request.params
const deleteTodoQuery = `
DELETE FROM
todo
WHERE
id=${todoId}
;`
await db.run(deleteTodoQuery)
response.send('Todo Deleted')
})
module.exports = app
Y29uc3QgZXhwcmVzcyA9IHJlcXVpcmUoJ2V4cHJlc3MnKQpjb25zdCBhcHAgPSBleHByZXNzKCkKYXBwLnVzZShleHByZXNzLmpzb24oKSkKY29uc3QgZm9ybWF0ID0gcmVxdWlyZSgnZGF0ZS1mbnMvZm9ybWF0JykKY29uc3QgaXNWYWxpZCA9IHJlcXVpcmUoJ2RhdGUtZm5zL2lzVmFsaWQnKQpjb25zdCB0b0RhdGUgPSByZXF1aXJlKCdkYXRlLWZucy90b0RhdGUnKQoKY29uc3Qge29wZW59ID0gcmVxdWlyZSgnc3FsaXRlJykKY29uc3Qgc3FsaXRlMyA9IHJlcXVpcmUoJ3NxbGl0ZTMnKQoKY29uc3QgcGF0aCA9IHJlcXVpcmUoJ3BhdGgnKQpjb25zdCBkYlBhdGggPSBwYXRoLmpvaW4oX19kaXJuYW1lLCAndG9kb0FwcGxpY2F0aW9uLmRiJykKCmxldCBkYiA9IG51bGwKCmNvbnN0IGluaXRpYWxpemVEQkFuZFNlcnZlciA9IGFzeW5jICgpID0+IHsKICB0cnkgewogICAgZGIgPSBhd2FpdCBvcGVuKHsKICAgICAgZmlsZW5hbWU6IGRiUGF0aCwKICAgICAgZHJpdmVyOiBzcWxpdGUzLkRhdGFiYXNlLAogICAgfSkKICAgIGFwcC5saXN0ZW4oMzAwMCwgKCkgPT4gewogICAgICBjb25zb2xlLmxvZygnU2VydmVyIGlzIHJ1bm5pbmcgYXQgaHR0cDovbG9jYWxob3N0OjMwMDAvJykKICAgIH0pCiAgfSBjYXRjaCAoZSkgewogICAgY29uc29sZS5sb2coZS5tZXNzYWdlKQogIH0KfQoKaW5pdGlhbGl6ZURCQW5kU2VydmVyKCkKCmNvbnN0IGNoZWNrUmVxdWVzdHNRdWVyaWVzID0gYXN5bmMgKHJlcXVlc3QsIHJlc3BvbnNlLCBuZXh0KSA9PiB7CiAgY29uc3Qge3NlYXJjaF9xLCBjYXRlZ29yeSwgcHJpb3JpdHksIHN0YXR1cywgZGF0ZX0gPSByZXF1ZXN0LnF1ZXJ5CiAgY29uc3Qge3RvZG9JZH0gPSByZXF1ZXN0LnBhcmFtcwogIGlmIChjYXRlZ29yeSAhPT0gdW5kZWZpbmVkKSB7CiAgICBjYXRlZ29yeUFycmF5ID0gWydXT1JLJywgJ0hPTUUnLCAnTEVBUk5JTkcnXQogICAgY29uc3QgY2F0ZWdvcnlJc0luQXJyYXkgPSBjYXRlZ29yeUFycmF5LmluY2x1ZGVzKGNhdGVnb3J5KQogICAgaWYgKGNhdGVnb3J5SXNJbkFycmF5ID09PSB0cnVlKSB7CiAgICAgIHJlcXVlc3QuY2F0ZWdvcnkgPSBjYXRlZ29yeQogICAgfSBlbHNlIHsKICAgICAgcmVzcG9uc2Uuc3RhdHVzKDQwMCkKICAgICAgcmVzcG9uc2Uuc2VuZCgnSW52YWxpZCBUb2RvIENhdGVnb3J5JykKICAgICAgcmV0dXJuCiAgICB9CiAgfQoKICBpZiAocHJpb3JpdHkgIT09IHVuZGVmaW5lZCkgewogICAgY29uc3QgcHJpb3JpdHlBcnJheSA9IFsnSElHSCcsICdNRURJVU0nLCAnTE9XJ10KICAgIGNvbnN0IHByaW9yaXR5SXNJbkFycmF5ID0gcHJpb3JpdHlBcnJheS5pbmNsdWRlcyhwcmlvcml0eSkKICAgIGlmIChwcmlvcml0eUlzSW5BcnJheSA9PT0gdHJ1ZSkgewogICAgICByZXF1ZXN0LnByaW9yaXR5ID0gcHJpb3JpdHkKICAgIH0gZWxzZSB7CiAgICAgIHJlc3BvbnNlLnN0YXR1cyg0MDApCiAgICAgIHJlc3BvbnNlLnNlbmQoJ0ludmFsaWQgVG9kbyBQcmlvcml0eScpCiAgICAgIHJldHVybgogICAgfQogIH0KCiAgaWYgKHN0YXR1cyAhPT0gdW5kZWZpbmVkKSB7CiAgICBjb25zdCBzdGF0dXNBcnJheSA9IFsnVE8gRE8nLCAnSU4gUFJPR1JFU1MnLCAnRE9ORSddCiAgICBjb25zdCBzdGF0dXNJc0luQXJyYXkgPSBzdGF0dXNBcnJheS5pbmNsdWRlcyhzdGF0dXMpCiAgICBpZiAoc3RhdHVzSXNJbkFycmF5ID09PSB0cnVlKSB7CiAgICAgIHJlcXVlc3Quc3RhdHVzID0gc3RhdHVzCiAgICB9IGVsc2UgewogICAgICByZXNwb25zZS5zdGF0dXMoNDAwKQogICAgICByZXNwb25zZS5zZW5kKCdJbnZhbGlkIFRvZG8gU3RhdHVzJykKICAgICAgcmV0dXJuCiAgICB9CiAgfQoKICBpZiAoZGF0ZSAhPT0gdW5kZWZpbmVkKSB7CiAgICB0cnkgewogICAgICBjb25zdCBteURhdGUgPSBuZXcgRGF0ZShkYXRlKQoKICAgICAgY29uc3QgZm9ybWF0dGVkRGF0ZSA9IGZvcm1hdChuZXcgRGF0ZShkYXRlKSwgJ3l5eXktTU0tZGQnKQogICAgICBjb25zb2xlLmxvZyhmb3JtYXR0ZWREYXRlLCAnZicpCiAgICAgIGNvbnN0IHJlc3VsdCA9IHRvRGF0ZSgKICAgICAgICBuZXcgRGF0ZSgKICAgICAgICAgIGAkKG15RGF0ZS5nZXRGdWxsWWVhcigpfS0kewogICAgICAgICAgICBteURhdGUuZ2V0TW9udGgoKSArIDEKICAgICAgICAgIH0tJHtteURhdGUuZ2V0RGF0ZSgpfWAsCiAgICAgICAgKSwKICAgICAgKQogICAgICBjb25zb2xlLmxvZyhyZXN1bHQsICdyJykKICAgICAgY29uc29sZS5sb2cobmV3IERhdGUoKSwgJ25ldycpCgogICAgICBjb25zdCBpc1ZhbGlkRGF0ZSA9IGF3YWl0IGlzVmFsaWQocmVzdWx0KQogICAgICBjb25zb2xlLmxvZyhpc1ZhbGlkRGF0ZSwgJ1YnKQogICAgICBpZiAoaXNWYWxpZERhdGUgPT09IHRydWUpIHsKICAgICAgICByZXF1ZXN0LmRhdGUgPSBmb3JtYXR0ZWREYXRlCiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmVzcG9uc2Uuc3RhdHVzKDQwMCkKICAgICAgICByZXNwb25zZS5zZW5kKCdJbnZhbGlkIER1ZSBEYXRlJykKICAgICAgICByZXR1cm4KICAgICAgfQogICAgfSBjYXRjaCAoZSkgewogICAgICByZXNwb25zZS5zdGF0dXMoNDAwKQogICAgICByZXNwb25zZS5zZW5kKCdJbnZhbGlkIER1ZSBEYXRlJykKICAgICAgcmV0dXJuCiAgICB9CiAgfQoKICByZXF1ZXN0LnRvZG9JZCA9IHRvZG9JZAogIHJlcXVlc3Quc2VhcmNoX3EgPSBzZWFyY2hfcQoKICBuZXh0KCkKfQoKY29uc3QgY2hlY2tSZXF1ZXN0c0JvZHkgPSAocmVxdWVzdCwgcmVzcG9uc2UsIG5leHQpID0+IHsKICBjb25zdCB7aWQsIHRvZG8sIGNhdGVnb3J5LCBwcmlvcml0eSwgc3RhdHVzLCBkdWVEYXRlfSA9IHJlcXVlc3QuYm9keQogIGNvbnN0IHt0b2RvSWR9ID0gcmVxdWVzdC5wYXJhbXMKCiAgaWYgKGNhdGVnb3J5ICE9PSB1bmRlZmluZWQpIHsKICAgIGNhdGVnb3J5QXJyYXkgPSBbJ1dPUksnLCAnSE9NRScsICdMRUFSTklORyddCiAgICBjYXRlZ29yeUlzSW5BcnJheSA9IGNhdGVnb3J5QXJyYXkuaW5jbHVkZXMoY2F0ZWdvcnkpCgogICAgaWYgKGNhdGVnb3J5SXNJbkFycmF5ID09PSB0cnVlKSB7CiAgICAgIHJlcXVlc3QuY2F0ZWdvcnkgPSBjYXRlZ29yeQogICAgfSBlbHNlIHsKICAgICAgcmVzcG9uc2Uuc3RhdHVzKDQwMCkKICAgICAgcmVzcG9uc2Uuc2VuZCgnSW52YWxpZCBUb2RvIENhdGVnb3J5JykKICAgICAgcmV0dXJuCiAgICB9CiAgfQoKICBpZiAocHJpb3JpdHkgIT09IHVuZGVmaW5lZCkgewogICAgcHJpb3JpdHlBcnJheSA9IFsnSElHSCcsICdNRURJVU0nLCAnTE9XJ10KICAgIHByaW9yaXR5SXNJbkFycmF5ID0gcHJpb3JpdHlBcnJheS5pbmNsdWRlcyhwcmlvcml0eSkKICAgIGlmIChwcmlvcml0eUlzSW5BcnJheSA9PT0gdHJ1ZSkgewogICAgICByZXF1ZXN0LnByaW9yaXR5ID0gcHJpb3JpdHkKICAgIH0gZWxzZSB7CiAgICAgIHJlc3BvbnNlLnN0YXR1cyg0MDApCiAgICAgIHJlc3BvbnNlLnNlbmQoJ0ludmFsaWQgVG9kbyBQcmlvcml0eScpCiAgICAgIHJldHVybgogICAgfQogIH0KCiAgaWYgKHN0YXR1cyAhPT0gdW5kZWZpbmVkKSB7CiAgICBzdGF0dXNBcnJheSA9IFsnVE8gRE8nLCAnSU4gUFJPR1JFU1MnLCAnRE9ORSddCiAgICBzdGF0dXNJc0luQXJyYXkgPSBzdGF0dXNBcnJheS5pbmNsdWRlcyhzdGF0dXMpCiAgICBpZiAoc3RhdHVzSXNJbkFycmF5ID09PSB0cnVlKSB7CiAgICAgIHJlcXVlc3Quc3RhdHVzID0gc3RhdHVzCiAgICB9IGVsc2UgewogICAgICByZXNwb25zZS5zdGF0dXMoNDAwKQogICAgICByZXNwb25zZS5zZW5kKCdJbnZhbGlkIFRvZG8gU3RhdHVzJykKICAgICAgcmV0dXJuCiAgICB9CiAgfQoKICBpZiAoZHVlRGF0ZSAhPT0gdW5kZWZpbmVkKSB7CiAgICB0cnkgewogICAgICBjb25zdCBteURhdGUgPSBuZXcgRGF0ZShkdWVEYXRlKQogICAgICBjb25zdCBmb3JtYXR0ZWREYXRlID0gZm9ybWF0KG5ldyBEYXRlKGR1ZURhdGUpLCAneXl5eS1NTS1kZCcpCiAgICAgIGNvbnNvbGUubG9nKGZvcm1hdHRlZERhdGUpCiAgICAgIGNvbnN0IHJlc3VsdCA9IHRvRGF0ZShuZXcgRGF0ZShmb3JtYXR0ZWREYXRlKSkKICAgICAgY29uc3QgaXNWYWxpZERhdGUgPSBpc1ZhbGlkKHJlc3VsdCkKICAgICAgY29uc29sZS5sb2coaXNWYWxpZERhdGUpCiAgICAgIGNvbnNvbGUubG9nKGlzVmFsaWREYXRlKQogICAgICBpZiAoaXNWYWxpZERhdGUgPT09IHRydWUpIHsKICAgICAgICByZXF1ZXN0LmR1ZURhdGUgPSBmb3JtYXR0ZWREYXRlCiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmVzcG9uc2Uuc3RhdHVzKDQwMCkKICAgICAgICByZXNwb25zZS5zZW5kKCdJbnZhbGlkIER1ZSBEYXRlJykKICAgICAgICByZXR1cm4KICAgICAgfQogICAgfSBjYXRjaCAoZSkgewogICAgICByZXNwb25zZS5zdGF0dXMoNDAwKQogICAgICByZXNwb25zZS5zZW5kKCdJbnZhbGlkIER1ZSBEYXRlJykKICAgICAgcmV0dXJuCiAgICB9CiAgfQogIHJlcXVlc3QudG9kbyA9IHRvZG8KICByZXF1ZXN0LmlkID0gaWQKCiAgcmVxdWVzdC50b2RvSWQgPSB0b2RvSWQKCiAgbmV4dCgpCn0KCi8vIEdldCBUb2RvcyBBUEktMQphcHAuZ2V0KCcvdG9kZXMvJywgY2hlY2tSZXF1ZXN0c1F1ZXJpZXMsIGFzeW5jIChyZXF1ZXN0LCByZXNwb25zZSkgPT4gewogIGNvbnN0IHtzdGF0dXMgPSAnJywgc2VhcmNoX3EgPSAnJywgcHJpb3JpdHkgPSAnJywgY2F0ZWdvcnkgPSAnJ30gPSByZXF1ZXN0CiAgY29uc29sZS5sb2coc3RhdHVzLCBzZWFyY2hfcSwgcHJpb3JpdHksIGNhdGVnb3J5KQogIGNvbnN0IGdldFRvZG9zUXVlcnkgPSBgClNFTEVDVAppZCwKdG9kbywKcHJpb3JpdHksCnN0YXR1cywKY2F0ZWdvcnksCmR1ZV9kYXRlIEFTIGR1ZURhdGUKRlJPTSAKdG9kbwpXSEVSRQp0b2RvIExJS0UgJyUke3NlYXJjaF9xfSUnIEFORCBwcmlvcml0eSBMSUtFICclJHtwcmlvcml0eX0lJwpBTkQgc3RhdHVzIExJS0UgJyUke3N0YXR1c30lJyBBTkQgY2F0ZWdvcnkgTElLRSAiJSR7Y2F0ZWdvcnl9JSc7YAoKICBjb25zdCB0b2Rvc0FycmF5ID0gYXdhaXQgZGIuYWxsKGdldFRvZG9zUXVlcnkpCiAgcmVzcG9uc2Uuc2VuZCh0b2Rvc0FycmF5KQp9KQoKLy8gR0VUIFRvZG8gQVBJLTIKYXBwLmdldCgnL3RvZG9zLzp0b2RvSWQnLCBjaGVja1JlcXVlc3RzUXVlcmllcywgYXN5bmMgKHJlcXVlc3QsIHJlc3BvbnNlKSA9PiB7CiAgY29uc3Qge3RvZG9JZH0gPSByZXF1ZXN0CgogIGNvbnN0IGdldFRvZG9zUXVlcnkgPSBgClNFTEVDVCAKaWQsCnRvZG8sCnByaW9yaXR5LApzdGF0dXMsCmNhdGVnb3J5LApkdWVfZGF0ZXMgQVMgZHVlRGF0ZQpGUk9NCnRvZG8KV0hFUkUKaWQgPSAke3RvZG9JZH07YAoKICBjb25zdCB0b2RvID0gYXdhaXQgZGIuZ2V0KGdldFRvZG9zUXVlcnkpCiAgcmVzcG9uc2Uuc2VuZCh0b2RvKQp9KQoKLy9HRVQgQWdlbmRhIEFQSS0zCmFwcC5nZXQoJy9hZ2VuZGEvJywgY2hlY2tSZXF1ZXN0c1F1ZXJpZXMsIGFzeW5jIChyZXF1ZXN0LCByZXNwb25zZSkgPT4gewogIGNvbnN0IHtkYXRlfSA9IHJlcXVlc3QKICBjb25zb2xlLmxvZyhkYXRlLCAnYScpCgogIGNvbnN0IHNlbGVjdER1ZURhdGVRdWVyeSA9IGAKU0VMRUNUCmlkLAp0b2RvLApwcmlvcml0eSwKc3RhdHVzLApjYXRlZ29yeSwKZHVlX2RhdGUgQVMgZHVlRGF0ZQpGUk9NCnRvZG8KV0hFUkUKZHVlX2RhdGUgPSAnJHtkYXRlfScKO2AKCiAgY29uc3QgdG9kb3NBcnJheSA9IGF3YWl0IGRiLmFsbChzZWxlY3REdWVEYXRlUXVlcnkpCgogIGlmICh0b2Rvc0FycmF5ID09PSB1bmRlZmluZWQpIHsKICAgIHJlc3BvbnNlLnN0YXR1cyg0MDApCiAgICByZXNwb25zZS5zZW5kKCdJbnZhbGlkIER1ZSBEYXRlJykKICB9IGVsc2UgewogICAgcmVzcG9uc2Uuc2VuZCh0b2Rvc0FycmF5KQogIH0KfSkKCi8vQWRkIFRvZG8gQVBJLTQKYXBwLnBvc3QoJy90b2Rvcy8nLCBjaGVja1JlcXVlc3RzQm9keSwgYXN5bmMgKHJlcXVlc3QsIHJlc3BvbnNlKSA9PiB7CiAgY29uc3Qge2lkLCB0b2RvLCBjYXRlZ29yeSwgcHJpb3JpdHksIHN0YXR1cywgZHVlRGF0ZX0gPSByZXF1ZXN0CgogIGNvbnN0IGFkZFRvZG9RdWVyeSA9IGAKSU5TRVJUIElOVE8KdG9kbyAoaWQsIHRvZG8sIHByaW9yaXR5LCBzdGF0dXMsIGNhdGVnb3J5LCBkdWVfZGF0ZSkKVkFMVUVTCigKJHtpZH0sCicke3RvZG99JywKJyR7cHJpb3JpdHl9JywKJyR7c3RhdHVzfScsCicke2NhdGVnb3J5fScsCicke2R1ZURhdGV9JwopCjtgCgogIGNvbnN0IGNyZWF0ZVVzZXIgPSBhd2FpdCBkYi5ydW4oYWRkVG9kb1F1ZXJ5KQogIGNvbnNvbGUubG9nKGNyZWF0ZVVzZXIpCiAgcmVzcG9uc2Uuc2VuZCgnVG9kbyBTdWNjZXNzZnVsbHkgQWRkZWQnKQp9KQoKLy9VcGRhdGUgVG9kbyBBUEktNQphcHAucHV0KCcvdG9kb3MvOnRvZG9JZC8nLCBjaGVja1JlcXVlc3RzQm9keSwgYXN5bmMgKHJlcXVlc3QsIHJlc3BvbnNlKSA9PiB7CiAgY29uc3Qge3RvZG9JZH0gPSByZXF1ZXN0CgogIGNvbnN0IHtwcmlvcml0eSwgdG9kbywgc3RhdHVzLCBjYXRlZ29yeSwgZHVlRGF0ZX0gPSByZXF1ZXN0CgogIGxldCB1cGRhdGVUb2RvUXVlcnkgPSBudWxsCgogIGNvbnNvbGUubG9nKHByaW9yaXR5LCB0b2RvLCBzdGF0dXMsIGR1ZURhdGUsIGNhdGVnb3J5KQogIHN3aXRjaCAodHJ1ZSkgewogICAgY2FzZSBzdGF0dXMgIT09IHVuZGVmaW5lZDoKICAgICAgdXBkYXRlVG9kb1F1ZXJ5ID0gYApVUERBVEUKdG9kbwpTRVQKc3RhdHVzID0gJyR7c3RhdHVzfScKV0hFUkUKaWQgPSAke3RvZG9JZH0KO2AKICAgICAgYXdhaXQgZGIucnVuKHVwZGF0ZVRvZG9RdWVyeSkKICAgICAgcmVzcG9uc2Uuc2VuZCgnU3RhdHVzIFVwZGF0ZWQnKQogICAgICBicmVhawogICAgY2FzZSBwcmlvcml0eSAhPT0gdW5kZWZpbmVkOgogICAgICB1cGRhdGVUb2RvUXVlcnkgPSBgClVQREFURQp0b2RvClNFVApwcmlvcml0eSA9ICcke3ByaW9yaXR5fScKV0hFUkUKaWQgPSAke3RvZG9JZH0KO2AKICAgICAgYXdhaXQgZGIucnVuKHVwZGF0ZVRvZG9RdWVyeSkKICAgICAgcmVzcG9uc2Uuc2VuZCgnUHJpb3JpdHkgVXBkYXRlZCcpCiAgICAgIGJyZWFrCiAgICBjYXNlIHRvZG8gIT09IHVuZGVmaW5lZDoKICAgICAgdXBkYXRlVG9kb1F1ZXJ5ID0gYApVUERBVEUKdG9kbwpTRVQKdG9kbyA9ICcke3RvZG99JwpXSEVSRQppZCA9ICR7dG9kb0lkfQo7YAogICAgICBhd2FpdCBkYi5ydW4odXBkYXRlVG9kb1F1ZXJ5KQogICAgICByZXNwb25zZS5zZW5kKCdUb2RvIFVwZGF0ZWQnKQogICAgICBicmVhawogICAgY2FzZSBjYXRlZ29yeSAhPT0gdW5kZWZpbmVkOgogICAgICBjb25zdCB1cGRhdGVDYXRlZ29yeVF1ZXJ5ID0gYApVUERBVEUKdG9kbwpTRVQKY2F0ZWdvcnkgPSAnJHtjYXRlZ29yeX0nCldIRVJFIAogaWQgPSAke3RvZG9JZH0KIDtgCiAgICAgIGF3YWl0IGRiLnJ1bih1cGRhdGVDYXRlZ29yeVF1ZXJ5KQogICAgICByZXNwb25zZS5zZW5kKCdDYXRlZ29yeSBVcGRhdGVkJykKICAgICAgYnJlYWsKICAgIGNhc2UgZHVlRGF0ZSAhPT0gdW5kZWZpbmVkOgogICAgICBjb25zdCB1cGRhdGVEYXRlUXVlcnkgPSBgClVQREFURQp0b2RvClNFVApkdWVfZGF0ZSA9ICcke2R1ZURhdGV9JwpXSEVSRQppZCA9ICR7dG9kb0lkfQo7YAogICAgICBhd2FpdCBkYi5ydW4odXBkYXRlRGF0ZVF1ZXJ5KQogICAgICByZXNwb25zZS5zZW5kKCdEdWUgRGF0ZSBVcGRhdGVkJykKICAgICAgYnJlYWsKICB9Cn0pCgovLyBEZWxldGUgVG9kbyBBUEktNgphcHAuZGVsZXRlKCcvdG9kb3MvOnRvZG9JZC8nLCBhc3luYyAocmVxdWVzdCwgcmVzcG9uc2UpID0+IHsKICBjb25zdCB7dG9kb0lkfSA9IHJlcXVlc3QucGFyYW1zCiAgY29uc3QgZGVsZXRlVG9kb1F1ZXJ5ID0gYApERUxFVEUgRlJPTQp0b2RvCldIRVJFCmlkPSR7dG9kb0lkfQo7YAoKICBhd2FpdCBkYi5ydW4oZGVsZXRlVG9kb1F1ZXJ5KQogIHJlc3BvbnNlLnNlbmQoJ1RvZG8gRGVsZXRlZCcpCn0pCm1vZHVsZS5leHBvcnRzID0gYXBwCg==
const express = require('express')
const app = express()
app.use(express.json())
const format = require('date-fns/format')
const isValid = require('date-fns/isValid')
const toDate = require('date-fns/toDate')
const {open} = require('sqlite')
const sqlite3 = require('sqlite3')
const path = require('path')
const dbPath = path.join(__dirname, 'todoApplication.db')
let db = null
const initializeDBAndServer = async () => {
try {
db = await open({
filename: dbPath,
driver: sqlite3.Database,
})
app.listen(3000, () => {
console.log('Server is running at http:/localhost:3000/')
})
} catch (e) {
console.log(e.message)
}
}
initializeDBAndServer()
const checkRequestsQueries = async (request, response, next) => {
const {search_q, category, priority, status, date} = request.query
const {todoId} = request.params
if (category !== undefined) {
categoryArray = ['WORK', 'HOME', 'LEARNING']
const categoryIsInArray = categoryArray.includes(category)
if (categoryIsInArray === true) {
request.category = category
} else {
response.status(400)
response.send('Invalid Todo Category')
return
}
}
if (priority !== undefined) {
const priorityArray = ['HIGH', 'MEDIUM', 'LOW']
const priorityIsInArray = priorityArray.includes(priority)
if (priorityIsInArray === true) {
request.priority = priority
} else {
response.status(400)
response.send('Invalid Todo Priority')
return
}
}
if (status !== undefined) {
const statusArray = ['TO DO', 'IN PROGRESS', 'DONE']
const statusIsInArray = statusArray.includes(status)
if (statusIsInArray === true) {
request.status = status
} else {
response.status(400)
response.send('Invalid Todo Status')
return
}
}
if (date !== undefined) {
try {
const myDate = new Date(date)
const formattedDate = format(new Date(date), 'yyyy-MM-dd')
console.log(formattedDate, 'f')
const result = toDate(
new Date(
`$(myDate.getFullYear()}-${
myDate.getMonth() + 1
}-${myDate.getDate()}`,
),
)
console.log(result, 'r')
console.log(new Date(), 'new')
const isValidDate = await isValid(result)
console.log(isValidDate, 'V')
if (isValidDate === true) {
request.date = formattedDate
} else {
response.status(400)
response.send('Invalid Due Date')
return
}
} catch (e) {
response.status(400)
response.send('Invalid Due Date')
return
}
}
request.todoId = todoId
request.search_q = search_q
next()
}
const checkRequestsBody = (request, response, next) => {
const {id, todo, category, priority, status, dueDate} = request.body
const {todoId} = request.params
if (category !== undefined) {
categoryArray = ['WORK', 'HOME', 'LEARNING']
categoryIsInArray = categoryArray.includes(category)
if (categoryIsInArray === true) {
request.category = category
} else {
response.status(400)
response.send('Invalid Todo Category')
return
}
}
if (priority !== undefined) {
priorityArray = ['HIGH', 'MEDIUM', 'LOW']
priorityIsInArray = priorityArray.includes(priority)
if (priorityIsInArray === true) {
request.priority = priority
} else {
response.status(400)
response.send('Invalid Todo Priority')
return
}
}
if (status !== undefined) {
statusArray = ['TO DO', 'IN PROGRESS', 'DONE']
statusIsInArray = statusArray.includes(status)
if (statusIsInArray === true) {
request.status = status
} else {
response.status(400)
response.send('Invalid Todo Status')
return
}
}
if (dueDate !== undefined) {
try {
const myDate = new Date(dueDate)
const formattedDate = format(new Date(dueDate), 'yyyy-MM-dd')
console.log(formattedDate)
const result = toDate(new Date(formattedDate))
const isValidDate = isValid(result)
console.log(isValidDate)
console.log(isValidDate)
if (isValidDate === true) {
request.dueDate = formattedDate
} else {
response.status(400)
response.send('Invalid Due Date')
return
}
} catch (e) {
response.status(400)
response.send('Invalid Due Date')
return
}
}
request.todo = todo
request.id = id
request.todoId = todoId
next()
}
// Get Todos API-1
app.get('/todes/', checkRequestsQueries, async (request, response) => {
const {status = '', search_q = '', priority = '', category = ''} = request
console.log(status, search_q, priority, category)
const getTodosQuery = `
SELECT
id,
todo,
priority,
status,
category,
due_date AS dueDate
FROM
todo
WHERE
todo LIKE '%${search_q}%' AND priority LIKE '%${priority}%'
AND status LIKE '%${status}%' AND category LIKE "%${category}%';`
const todosArray = await db.all(getTodosQuery)
response.send(todosArray)
})
// GET Todo API-2
app.get('/todos/:todoId', checkRequestsQueries, async (request, response) => {
const {todoId} = request
const getTodosQuery = `
SELECT
id,
todo,
priority,
status,
category,
due_dates AS dueDate
FROM
todo
WHERE
id = ${todoId};`
const todo = await db.get(getTodosQuery)
response.send(todo)
})
//GET Agenda API-3
app.get('/agenda/', checkRequestsQueries, async (request, response) => {
const {date} = request
console.log(date, 'a')
const selectDueDateQuery = `
SELECT
id,
todo,
priority,
status,
category,
due_date AS dueDate
FROM
todo
WHERE
due_date = '${date}'
;`
const todosArray = await db.all(selectDueDateQuery)
if (todosArray === undefined) {
response.status(400)
response.send('Invalid Due Date')
} else {
response.send(todosArray)
}
})
//Add Todo API-4
app.post('/todos/', checkRequestsBody, async (request, response) => {
const {id, todo, category, priority, status, dueDate} = request
const addTodoQuery = `
INSERT INTO
todo (id, todo, priority, status, category, due_date)
VALUES
(
${id},
'${todo}',
'${priority}',
'${status}',
'${category}',
'${dueDate}'
)
;`
const createUser = await db.run(addTodoQuery)
console.log(createUser)
response.send('Todo Successfully Added')
})
//Update Todo API-5
app.put('/todos/:todoId/', checkRequestsBody, async (request, response) => {
const {todoId} = request
const {priority, todo, status, category, dueDate} = request
let updateTodoQuery = null
console.log(priority, todo, status, dueDate, category)
switch (true) {
case status !== undefined:
updateTodoQuery = `
UPDATE
todo
SET
status = '${status}'
WHERE
id = ${todoId}
;`
await db.run(updateTodoQuery)
response.send('Status Updated')
break
case priority !== undefined:
updateTodoQuery = `
UPDATE
todo
SET
priority = '${priority}'
WHERE
id = ${todoId}
;`
await db.run(updateTodoQuery)
response.send('Priority Updated')
break
case todo !== undefined:
updateTodoQuery = `
UPDATE
todo
SET
todo = '${todo}'
WHERE
id = ${todoId}
;`
await db.run(updateTodoQuery)
response.send('Todo Updated')
break
case category !== undefined:
const updateCategoryQuery = `
UPDATE
todo
SET
category = '${category}'
WHERE
id = ${todoId}
;`
await db.run(updateCategoryQuery)
response.send('Category Updated')
break
case dueDate !== undefined:
const updateDateQuery = `
UPDATE
todo
SET
due_date = '${dueDate}'
WHERE
id = ${todoId}
;`
await db.run(updateDateQuery)
response.send('Due Date Updated')
break
}
})
// Delete Todo API-6
app.delete('/todos/:todoId/', async (request, response) => {
const {todoId} = request.params
const deleteTodoQuery = `
DELETE FROM
todo
WHERE
id=${todoId}
;`
await db.run(deleteTodoQuery)
response.send('Todo Deleted')
})
module.exports = app