Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .babelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"presets": [
["@babel/preset-env", {
"useBuiltIns": "usage",
"corejs": 3,
}]
],
"plugins": ["@babel/plugin-transform-runtime"]
}
3 changes: 2 additions & 1 deletion azure-pipelines.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ steps:

- script: |
npm install
displayName: 'npm install'
npm run build
displayName: 'npm install and build'

- task: ArchiveFiles@2
displayName: 'Archive files'
Expand Down
19 changes: 14 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@
"name": "postgres-express-node",
"version": "1.0.0",
"description": "Setting up a todo list backend",
"main": "index.js",
"main": "build/bin/www",
"scripts": {
"start": "node ./bin/www",
"start:dev": "nodemon ./bin/www",
"build": "exit 0",
"test": "NODE_ENV=test npm run reset:db && NODE_ENV=test nyc mocha --timeout 5000 server/tests/**/*.spec.js",
"start": "node build/bin/www",
"start:dev": "nodemon --exec babel-node -- server/bin/www",
"build": "rm -rf build && babel server -d build --copy-files",
"test": "NODE_ENV=test npm run reset:db && NODE_ENV=test nyc mocha --require @babel/register --timeout 5000 server/tests/**/*.spec.js",
"migrate": "sequelize db:migrate",
"reset:db": "sequelize db:migrate:undo:all && npm run migrate",
"coveralls-coverage": "nyc report --reporter=text-lcov | coveralls",
Expand All @@ -24,6 +24,7 @@
"**/*.spec.js",
"coverage",
"dist",
"build",
"server/tests",
"server/migrations",
".eslintrc.js"
Expand All @@ -38,9 +39,11 @@
"author": "Ryan Wire",
"license": "ISC",
"dependencies": {
"@babel/runtime": "^7.5.5",
"bcrypt": "^3.0.6",
"body-parser": "^1.19.0",
"celebrate": "^10.0.1",
"core-js": "^3.2.1",
"cors": "^2.8.5",
"dotenv": "^8.0.0",
"express": "^4.17.1",
Expand All @@ -53,6 +56,12 @@
"sequelize": "^5.8.9"
},
"devDependencies": {
"@babel/cli": "^7.5.5",
"@babel/core": "^7.5.5",
"@babel/node": "^7.5.5",
"@babel/plugin-transform-runtime": "^7.5.5",
"@babel/preset-env": "^7.5.5",
"@babel/register": "^7.5.5",
"chai": "^4.2.0",
"chai-http": "^4.3.0",
"coveralls": "^3.0.6",
Expand Down
27 changes: 13 additions & 14 deletions app.js → server/app.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
const express = require('express');
const cors = require('cors');
const logger = require('morgan');
const bodyParser = require('body-parser');
const passport = require('passport');
require('dotenv').config();
const joiErrors = require('./server/middlewares/joiErrors');
import express from 'express';
import cors from 'cors';
import logger from 'morgan';
import bodyParser from 'body-parser';
import passport from 'passport';
import dotenv from 'dotenv';
import joiErrors from './middlewares/joiErrors';

// Require our routes and passport into the application
const todosRouter = require('./server/routes').todosRouter();
const authRouter = require('./server/routes').authRouter();
const usersRouter = require('./server/routes').usersRouter();
const { passportAuth } = require('./server/config/passport');
import routers from './routes';
import passportAuth from './config/passport';

dotenv.config();
passportAuth(passport);

const apiPrefix = '/api';
Expand All @@ -33,9 +32,9 @@ app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));

app.use(apiPrefix, passport.authenticate('jwt', { session: false }));
app.use(apiPrefix, usersRouter);
app.use(apiPrefix, todosRouter);
app.use(authRouter);
app.use(apiPrefix, routers.usersRouter());
app.use(apiPrefix, routers.todosRouter());
app.use(routers.authRouter());

app.use(joiErrors);

Expand Down
File renamed without changes.
10 changes: 4 additions & 6 deletions server/config/passport.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
const passportJWT = require('passport-jwt');
const { User } = require('../models');
import passportJWT from 'passport-jwt';
import db from '../models';

const { ExtractJwt } = passportJWT;
const JwtStrategy = passportJWT.Strategy;
Expand All @@ -9,7 +9,7 @@ jwtOptions.jwtFromRequest = ExtractJwt.fromAuthHeaderAsBearerToken();
jwtOptions.secretOrKey = process.env.SECRET_KEY;

const passportAuth = (passport) => {
const getUser = async (username) => User.findOne({
const getUser = async (username) => db.User.findOne({
attributes: ['id', 'username', 'createdAt', 'updatedAt'],
where: {
username,
Expand All @@ -27,6 +27,4 @@ const passportAuth = (passport) => {
passport.use(strategy);
};

module.exports = {
passportAuth,
};
export default passportAuth;
10 changes: 6 additions & 4 deletions server/controllers/index.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
const todos = require('./todos');
const todoItems = require('./todoitems');
const users = require('./users');
import todos from './todos';
import todoItems from './todoitems';
import users from './users';

module.exports = {
const controllers = {
todos,
todoItems,
users,
};

export default controllers;
88 changes: 47 additions & 41 deletions server/controllers/todoitems.js
Original file line number Diff line number Diff line change
@@ -1,48 +1,54 @@
const { TodoItem } = require('../models');
import db from '../models';

module.exports = {
async createTodoItem(req, res) {
const todoItem = await TodoItem.create({
content: req.body.content,
const createTodoItem = async (req, res) => {
const todoItem = await db.TodoItem.create({
content: req.body.content,
todoId: req.params.todoId,
});
return res.status(201).send(todoItem);
};

const update = async (req, res) => {
const todoItem = await db.TodoItem.findOne({
attributes: ['id', 'todoId', 'content', 'complete', 'updatedAt'],
where: {
id: req.params.todoItemId,
todoId: req.params.todoId,
});
return res.status(201).send(todoItem);
},
async update(req, res) {
const todoItem = await TodoItem.findOne({
attributes: ['id', 'todoId', 'content', 'complete', 'updatedAt'],
where: {
id: req.params.todoItemId,
todoId: req.params.todoId,
},
});
},
});

if (!todoItem) {
return res.status(404).send({
message: 'TodoItem Not Found',
});
}
const updatedTodoItem = await todoItem.update({
content: req.body.content || todoItem.content,
complete: req.body.complete || todoItem.complete,
if (!todoItem) {
return res.status(404).send({
message: 'TodoItem Not Found',
});
return res.status(200).send(updatedTodoItem);
},
async destroy(req, res) {
const todoItem = await TodoItem.findOne({
attributes: ['id'],
where: {
id: req.params.todoItemId,
todoId: req.params.todoId,
},
}
const updatedTodoItem = await todoItem.update({
content: req.body.content || todoItem.content,
complete: req.body.complete || todoItem.complete,
});
return res.status(200).send(updatedTodoItem);
};

const destroy = async (req, res) => {
const todoItem = await db.TodoItem.findOne({
attributes: ['id'],
where: {
id: req.params.todoItemId,
todoId: req.params.todoId,
},
});

if (!todoItem) {
return res.status(404).send({
message: 'TodoItem Not Found',
});
}
await todoItem.destroy();
return res.sendStatus(204);
};

if (!todoItem) {
return res.status(404).send({
message: 'TodoItem Not Found',
});
}
await todoItem.destroy();
return res.sendStatus(204);
},
export default {
createTodoItem,
update,
destroy,
};
121 changes: 62 additions & 59 deletions server/controllers/todos.js
Original file line number Diff line number Diff line change
@@ -1,60 +1,63 @@
const { Todo } = require('../models');
const { TodoItem } = require('../models');

module.exports = {
async createTodo(req, res) {
const { body, user } = req;
const createdTodo = await Todo.create({
title: body.title,
UserId: user.id,
});
return res.status(201).send(createdTodo);
},

async list(req, res) {
const { limit, page, offset } = req.query;

const todos = await Todo.findAndCountAll({
limit,
offset,
where: { UserId: req.user.id },
include: [
{
model: TodoItem,
attributes: ['id', 'complete', 'content', 'todoId', 'createdAt', 'updatedAt'],
as: 'todoItems',
},
],
order: [
['createdAt', 'DESC'],
[{ model: TodoItem, as: 'todoItems' }, 'createdAt', 'ASC'],
],
});

const meta = {
total: todos.count,
pageCount: Math.ceil(todos.count / limit),
perPage: limit,
page,
};
return res.status(200).send({ meta, data: todos.rows });
},

retrieve(req, res) {
return res.status(200).send(req.todo);
},

async update(req, res) {
const { todo, body } = req;
const updatedTodo = await todo.update({
title: body.title,
});
return res.status(200).send(updatedTodo);
},

async destroy(req, res) {
const { todo } = req;
await todo.destroy();
return res.sendStatus(204);
},
import db from '../models';

const createTodo = async (req, res) => {
const { body, user } = req;
const createdTodo = await db.Todo.create({
title: body.title,
UserId: user.id,
});
return res.status(201).send(createdTodo);
};

const list = async (req, res) => {
const { limit, page, offset } = req.query;

const todos = await db.Todo.findAndCountAll({
limit,
offset,
where: { UserId: req.user.id },
include: [
{
model: db.TodoItem,
attributes: ['id', 'complete', 'content', 'todoId', 'createdAt', 'updatedAt'],
as: 'todoItems',
},
],
order: [
['createdAt', 'DESC'],
[{ model: db.TodoItem, as: 'todoItems' }, 'createdAt', 'ASC'],
],
});

const meta = {
total: todos.count,
pageCount: Math.ceil(todos.count / limit),
perPage: limit,
page,
};
return res.status(200).send({ meta, data: todos.rows });
};

const retrieve = (req, res) => res.status(200).send(req.todo);

const update = async (req, res) => {
const { todo, body } = req;
const updatedTodo = await todo.update({
title: body.title,
});
return res.status(200).send(updatedTodo);
};

const destroy = async (req, res) => {
const { todo } = req;
await todo.destroy();
return res.sendStatus(204);
};

export default {
createTodo,
list,
retrieve,
update,
destroy,
};
Loading