From fd4be64ffe6a1545fc283b294ffe834776e13adb Mon Sep 17 00:00:00 2001 From: tamara-taylor Date: Sat, 18 Dec 2021 20:18:11 -0500 Subject: [PATCH 1/4] still working --- api/cars/cars-middleware.js | 57 +++++++++++++++++++++++++++++++++---- api/cars/cars-model.js | 31 ++++++++++++++++---- api/cars/cars-router.js | 34 +++++++++++++++++++++- api/server.js | 7 +++-- index.js | 2 +- package-lock.json | 20 +++++++++++-- package.json | 8 +++++- 7 files changed, 139 insertions(+), 20 deletions(-) diff --git a/api/cars/cars-middleware.js b/api/cars/cars-middleware.js index 7e738d6062..0acd86ac97 100644 --- a/api/cars/cars-middleware.js +++ b/api/cars/cars-middleware.js @@ -1,15 +1,60 @@ +const Cars = require('./cars-model') +const vinValidator = require('vin-validator') + const checkCarId = (req, res, next) => { - // DO YOUR MAGIC + const {id} = req.params + Cars.getById(id) + .then((car) => { + if(car){ + req.car = car + next() + }else{ + res.status(400).json({message: `Car with id ${id} is not found`}) + } + }) + .catch(next) } const checkCarPayload = (req, res, next) => { - // DO YOUR MAGIC + const {vin, make, model, mileage} = req.body + const err = {status: 400} + if(!vin || typeof vin !== 'string' || !vin.trim()){ + err.message = 'vin is missing' + }else if(!make || typeof make !== 'string' || make.trim()){ + err.message = 'make is missing' + }else if(!model || typeof model !== 'string' || model.trim()){ + err.message = 'model is missing' + }else if(!mileage || typeof mileage !== 'number'){ + err.message = 'mileage is missing' + } + if(err.message){ + next(err) + }else{ + next() + } } -const checkVinNumberValid = (req, res, next) => { - // DO YOUR MAGIC +const checkVinNumberValid = async (req, res, next) => { + const {vin} = req.body + if(vinValidator.validate(vin)){ + next() + }else{ + next({status: 400, message: `vin ${vin} is invalid`}) + } } -const checkVinNumberUnique = (req, res, next) => { - // DO YOUR MAGIC +const checkVinNumberUnique = async (req, res, next) => { + const {vin} = req.body + try{ + const existing = await Cars.getByVin(vin) + if(existing){ + next({status: 400, message: `vin ${vin} already exists`}) + }else{ + next() + } + }catch(err){ + next(err) + } } + +module.exports = {checkCarId, checkCarPayload, checkVinNumberUnique, checkVinNumberValid} diff --git a/api/cars/cars-model.js b/api/cars/cars-model.js index 39b2c50a8d..61954f29a2 100644 --- a/api/cars/cars-model.js +++ b/api/cars/cars-model.js @@ -1,11 +1,32 @@ +const db = require('../../data/db-config') + const getAll = () => { - // DO YOUR MAGIC + return db('cars') + .select('vin', 'make', 'model', 'mileage', 'title', 'transmission') +} + +const getById = (id) => { + return db('cars').where('id', id) + .first() +} + +const create = async car => { + const [id] = await db('cars').insert(car) + return getById(id) +} + +const getByVin = async (vin) => { + return db('cars').where('vin', vin) + .first() } -const getById = () => { - // DO YOUR MAGIC +const updateById = async (id, car) => { + await db('cars').where('id', id).update(car) + return getById(id) } -const create = () => { - // DO YOUR MAGIC +const deleteById = id => { + return db('cars').where('id', id).del() } + +module.exports = {getAll, getById, create, getByVin, updateById, deleteById} \ No newline at end of file diff --git a/api/cars/cars-router.js b/api/cars/cars-router.js index 3fca0e7d7d..080103e794 100644 --- a/api/cars/cars-router.js +++ b/api/cars/cars-router.js @@ -1 +1,33 @@ -// DO YOUR MAGIC +const router = require('express').Router() +const Cars = require('./cars-model') +const mw = require('./cars-middleware') + +router.get('/', async (req, res, next) => { + try{ + const cars = await Cars.getAll() + res.status(200).json(cars) + }catch(err){ + next(err) + } +}) + +router.get('/:id', mw.checkCarId, async (req, res, next) => { + try{ + await res.status(200).json(req.car) + }catch(err){ + next(err) + } +}) + +router.post('/', mw.checkCarPayload, mw.checkVinNumberUnique, mw.checkVinNumberValid, async (req, res, next) => { + try{ + const newCar = await Cars.create(req.body) + res.status(201).json(newCar) + }catch(err){ + next(err) + } +}) + +router.use((err, req, res, next) => { + res.status(err.status || 500).json({message: err.message}) +}) \ No newline at end of file diff --git a/api/server.js b/api/server.js index c5a0be1b41..a94b1de20b 100644 --- a/api/server.js +++ b/api/server.js @@ -1,7 +1,8 @@ const express = require("express") - +const CarRouter = require('./cars/cars-router') const server = express() -// DO YOUR MAGIC +server.use(express.json()) +server.use('/api/cars', CarRouter) -module.exports = server +module.exports = server \ No newline at end of file diff --git a/index.js b/index.js index 261b0ea92a..2e78630377 100644 --- a/index.js +++ b/index.js @@ -1,5 +1,5 @@ const server = require('./api/server') -const port = process.env.PORT || 9000; +const port = process.env.PORT || 5000; server.listen(port, () => console.log(`\n** Running on port ${port} **\n`)) diff --git a/package-lock.json b/package-lock.json index d1f3f92341..6e2f2186d5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5,12 +5,12 @@ "requires": true, "packages": { "": { - "name": "node-db2-project", "version": "1.0.0", "dependencies": { "express": "^4.17.1", "knex": "^0.95.14", - "sqlite3": "^5.0.2" + "sqlite3": "^5.0.2", + "vin-validator": "^1.0.0" }, "devDependencies": { "@types/jest": "^27.0.3", @@ -1844,6 +1844,7 @@ "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", + "fsevents": "~2.3.2", "glob-parent": "~5.1.2", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", @@ -2472,7 +2473,8 @@ "esprima": "^4.0.1", "estraverse": "^5.2.0", "esutils": "^2.0.2", - "optionator": "^0.8.1" + "optionator": "^0.8.1", + "source-map": "~0.6.1" }, "bin": { "escodegen": "bin/escodegen.js", @@ -4076,6 +4078,7 @@ "@types/node": "*", "anymatch": "^3.0.3", "fb-watchman": "^2.0.0", + "fsevents": "^2.3.2", "graceful-fs": "^4.2.4", "jest-regex-util": "^27.4.0", "jest-serializer": "^27.4.0", @@ -6209,6 +6212,7 @@ "hasInstallScript": true, "dependencies": { "node-addon-api": "^3.0.0", + "node-gyp": "3.x", "node-pre-gyp": "^0.11.0" }, "optionalDependencies": { @@ -6882,6 +6886,11 @@ "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", "optional": true }, + "node_modules/vin-validator": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/vin-validator/-/vin-validator-1.0.0.tgz", + "integrity": "sha1-F2Via4VYskAvd7bCXHYX9zzsrmc=" + }, "node_modules/w3c-hr-time": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", @@ -12518,6 +12527,11 @@ } } }, + "vin-validator": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/vin-validator/-/vin-validator-1.0.0.tgz", + "integrity": "sha1-F2Via4VYskAvd7bCXHYX9zzsrmc=" + }, "w3c-hr-time": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", diff --git a/package.json b/package.json index cdbfc72774..6b5ebb3c8d 100644 --- a/package.json +++ b/package.json @@ -4,6 +4,11 @@ "main": "index.js", "scripts": { "server": "nodemon index.js", + "up": "knex migrate: up", + "down": "knex migrate: down", + "rollback": "knex migrate: rollback", + "seed": "knex seed: run", + "latest": "knex migrate: latest", "test": "cross-env NODE_ENV=testing jest --verbose --runInBand" }, "devDependencies": { @@ -17,7 +22,8 @@ "dependencies": { "express": "^4.17.1", "knex": "^0.95.14", - "sqlite3": "^5.0.2" + "sqlite3": "^5.0.2", + "vin-validator": "^1.0.0" }, "repository": { "type": "git", From 26167a455997116fd538b842fc8cd770e06a8f77 Mon Sep 17 00:00:00 2001 From: tamara-taylor Date: Sat, 18 Dec 2021 20:35:49 -0500 Subject: [PATCH 2/4] still working --- api/cars/cars-middleware.js | 2 +- api/server.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/api/cars/cars-middleware.js b/api/cars/cars-middleware.js index 0acd86ac97..cc53ac4bb4 100644 --- a/api/cars/cars-middleware.js +++ b/api/cars/cars-middleware.js @@ -57,4 +57,4 @@ const checkVinNumberUnique = async (req, res, next) => { } } -module.exports = {checkCarId, checkCarPayload, checkVinNumberUnique, checkVinNumberValid} +module.exports = {logger, checkCarId, checkCarPayload, checkVinNumberUnique, checkVinNumberValid} diff --git a/api/server.js b/api/server.js index a94b1de20b..0a316c2ee8 100644 --- a/api/server.js +++ b/api/server.js @@ -3,6 +3,6 @@ const CarRouter = require('./cars/cars-router') const server = express() server.use(express.json()) -server.use('/api/cars', CarRouter) +server.use('/api/cars', logger, CarRouter) module.exports = server \ No newline at end of file From 090db6332f55317a4da549020e44f216e7493bf0 Mon Sep 17 00:00:00 2001 From: tamara-taylor Date: Sun, 19 Dec 2021 16:16:48 -0500 Subject: [PATCH 3/4] some working --- api/cars/cars-middleware.js | 61 +++++++------- api/cars/cars-model.js | 18 ++-- api/cars/cars-router.js | 14 ++-- api/server.js | 2 +- data/migrations/01-make_cars_table.js | 12 ++- data/seeds/01-cars.js | 1 - package-lock.json | 113 +++++++++++++++++++++++++- package.json | 3 +- 8 files changed, 167 insertions(+), 57 deletions(-) diff --git a/api/cars/cars-middleware.js b/api/cars/cars-middleware.js index cc53ac4bb4..f20b220102 100644 --- a/api/cars/cars-middleware.js +++ b/api/cars/cars-middleware.js @@ -1,36 +1,38 @@ const Cars = require('./cars-model') const vinValidator = require('vin-validator') +const yup = require('yup') +const db = require('../../data/db-config') -const checkCarId = (req, res, next) => { - const {id} = req.params - Cars.getById(id) - .then((car) => { - if(car){ +const checkCarId = async (req, res, next) => { + try{ + const car = await Cars.getById(req.params.id) + if(!car){ + next({message: `Car with id ${id} is not found`}) + }else{ req.car = car next() - }else{ - res.status(400).json({message: `Car with id ${id} is not found`}) } - }) - .catch(next) + }catch(err){ + next(err) + } } -const checkCarPayload = (req, res, next) => { - const {vin, make, model, mileage} = req.body - const err = {status: 400} - if(!vin || typeof vin !== 'string' || !vin.trim()){ - err.message = 'vin is missing' - }else if(!make || typeof make !== 'string' || make.trim()){ - err.message = 'make is missing' - }else if(!model || typeof model !== 'string' || model.trim()){ - err.message = 'model is missing' - }else if(!mileage || typeof mileage !== 'number'){ - err.message = 'mileage is missing' - } - if(err.message){ - next(err) - }else{ +const checkCarPayloadSchema = yup.object().shape({ + vin: yup.string().required('vin is missing'), + make: yup.string().required('make is missing'), + model: yup.string().required('model is missing'), + mileage: yup.string().required('mileage is missing'), + title: yup.string(), + transmission: yup.string() +}) + +const checkCarPayload = async (req, res, next) => { + try{ + const payValidation = await checkCarPayloadSchema.validate(req.body, {strict: false, stripUnkown: true}) + req.body = payValidation next() + }catch(err){ + res.status(400).json({message: err.message}) } } @@ -44,17 +46,16 @@ const checkVinNumberValid = async (req, res, next) => { } const checkVinNumberUnique = async (req, res, next) => { - const {vin} = req.body try{ - const existing = await Cars.getByVin(vin) - if(existing){ - next({status: 400, message: `vin ${vin} already exists`}) - }else{ + const existing = await db('cars').where('vin', req.body.vin).first() + if(!existing){ next() + }else{ + res.status(400).json({message: `vin ${req.body.vin} already exists`}) } }catch(err){ next(err) } } -module.exports = {logger, checkCarId, checkCarPayload, checkVinNumberUnique, checkVinNumberValid} +module.exports = {checkCarId, checkCarPayload, checkVinNumberUnique, checkVinNumberValid} \ No newline at end of file diff --git a/api/cars/cars-model.js b/api/cars/cars-model.js index 61954f29a2..8277dc5ecd 100644 --- a/api/cars/cars-model.js +++ b/api/cars/cars-model.js @@ -2,7 +2,6 @@ const db = require('../../data/db-config') const getAll = () => { return db('cars') - .select('vin', 'make', 'model', 'mileage', 'title', 'transmission') } const getById = (id) => { @@ -10,9 +9,11 @@ const getById = (id) => { .first() } -const create = async car => { +const create = async (car) => { const [id] = await db('cars').insert(car) - return getById(id) + .then(([id]) => { + return getById(id) + }) } const getByVin = async (vin) => { @@ -20,13 +21,4 @@ const getByVin = async (vin) => { .first() } -const updateById = async (id, car) => { - await db('cars').where('id', id).update(car) - return getById(id) -} - -const deleteById = id => { - return db('cars').where('id', id).del() -} - -module.exports = {getAll, getById, create, getByVin, updateById, deleteById} \ No newline at end of file +module.exports = {getAll, getById, create, getByVin} \ No newline at end of file diff --git a/api/cars/cars-router.js b/api/cars/cars-router.js index 080103e794..889d794e05 100644 --- a/api/cars/cars-router.js +++ b/api/cars/cars-router.js @@ -5,18 +5,14 @@ const mw = require('./cars-middleware') router.get('/', async (req, res, next) => { try{ const cars = await Cars.getAll() - res.status(200).json(cars) + res.json(cars) }catch(err){ next(err) } }) router.get('/:id', mw.checkCarId, async (req, res, next) => { - try{ - await res.status(200).json(req.car) - }catch(err){ - next(err) - } + res.status(200).json(req.car) }) router.post('/', mw.checkCarPayload, mw.checkVinNumberUnique, mw.checkVinNumberValid, async (req, res, next) => { @@ -29,5 +25,7 @@ router.post('/', mw.checkCarPayload, mw.checkVinNumberUnique, mw.checkVinNumberV }) router.use((err, req, res, next) => { - res.status(err.status || 500).json({message: err.message}) -}) \ No newline at end of file + res.status(err.status || 404).json({message: err.message}) +}) + +module.exports = router \ No newline at end of file diff --git a/api/server.js b/api/server.js index 0a316c2ee8..a94b1de20b 100644 --- a/api/server.js +++ b/api/server.js @@ -3,6 +3,6 @@ const CarRouter = require('./cars/cars-router') const server = express() server.use(express.json()) -server.use('/api/cars', logger, CarRouter) +server.use('/api/cars', CarRouter) module.exports = server \ No newline at end of file diff --git a/data/migrations/01-make_cars_table.js b/data/migrations/01-make_cars_table.js index 9723c175be..f432e7db20 100644 --- a/data/migrations/01-make_cars_table.js +++ b/data/migrations/01-make_cars_table.js @@ -1,7 +1,15 @@ exports.up = function (knex) { - // DO YOUR MAGIC + return knex.schema.createTable('cars', (table) => { + table.increments() + table.string('vin', 16).notNullable().unique() + table.string('make', 128).notNullable() + table.string('model', 256).notNullable() + table.string('mileage').unsigned().notNullable + table.string('title', 128) + table.string('transmission', 128) + }) }; exports.down = function (knex) { - // DO YOUR MAGIC + return knex.schema.dropTableIfExists('cars') }; diff --git a/data/seeds/01-cars.js b/data/seeds/01-cars.js index 3f7acdde23..e69de29bb2 100644 --- a/data/seeds/01-cars.js +++ b/data/seeds/01-cars.js @@ -1 +0,0 @@ -// STRETCH diff --git a/package-lock.json b/package-lock.json index 6e2f2186d5..5908e81a20 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,7 +10,8 @@ "express": "^4.17.1", "knex": "^0.95.14", "sqlite3": "^5.0.2", - "vin-validator": "^1.0.0" + "vin-validator": "^1.0.0", + "yup": "^0.32.11" }, "devDependencies": { "@types/jest": "^27.0.3", @@ -572,6 +573,17 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/runtime": { + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.16.5.tgz", + "integrity": "sha512-TXWihFIS3Pyv5hzR7j6ihmeLkZfrXGxAr5UfSl8CHf+6q/wpiYDkUau0czckpYG8QmnCIuPpdLtuA9VmuGGyMA==", + "dependencies": { + "regenerator-runtime": "^0.13.4" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/template": { "version": "7.16.0", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.16.0.tgz", @@ -1102,6 +1114,11 @@ "pretty-format": "^27.0.0" } }, + "node_modules/@types/lodash": { + "version": "4.14.178", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.178.tgz", + "integrity": "sha512-0d5Wd09ItQWH1qFbEyQ7oTQ3GZrMfth5JkbN3EvTKLXcHLRDSXeLnlvlOn0wvxVIwK5o2M8JzP/OWz7T3NRsbw==" + }, "node_modules/@types/node": { "version": "16.11.12", "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.12.tgz", @@ -4737,6 +4754,11 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, + "node_modules/lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==" + }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", @@ -4939,6 +4961,11 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, + "node_modules/nanoclone": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/nanoclone/-/nanoclone-0.2.1.tgz", + "integrity": "sha512-wynEP02LmIbLpcYw8uBKpcfF6dmg2vcpKqxeH5UcoKEYdExslsdUA4ugFauuaeYdTB76ez6gJW8XAZ6CgkXYxA==" + }, "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -5659,6 +5686,11 @@ "node": ">= 6" } }, + "node_modules/property-expr": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/property-expr/-/property-expr-2.0.4.tgz", + "integrity": "sha512-sFPkHQjVKheDNnPvotjQmm3KD3uk1fWKUN7CrpdbwmUx3CrG3QiM8QpTSimvig5vTXmTvjz7+TDvXOI9+4rkcg==" + }, "node_modules/proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -5809,6 +5841,11 @@ "node": ">= 0.10" } }, + "node_modules/regenerator-runtime": { + "version": "0.13.9", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz", + "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==" + }, "node_modules/regexpp": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", @@ -6597,6 +6634,11 @@ "node": ">=0.6" } }, + "node_modules/toposort": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz", + "integrity": "sha1-riF2gXXRVZ1IvvNUILL0li8JwzA=" + }, "node_modules/touch": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", @@ -7189,6 +7231,23 @@ "engines": { "node": ">=8" } + }, + "node_modules/yup": { + "version": "0.32.11", + "resolved": "https://registry.npmjs.org/yup/-/yup-0.32.11.tgz", + "integrity": "sha512-Z2Fe1bn+eLstG8DRR6FTavGD+MeAwyfmouhHsIUgaADz8jvFKbO/fXc2trJKZg+5EBjh4gGm3iU/t3onKlXHIg==", + "dependencies": { + "@babel/runtime": "^7.15.4", + "@types/lodash": "^4.14.175", + "lodash": "^4.17.21", + "lodash-es": "^4.17.21", + "nanoclone": "^0.2.1", + "property-expr": "^2.0.4", + "toposort": "^2.0.2" + }, + "engines": { + "node": ">=10" + } } }, "dependencies": { @@ -7606,6 +7665,14 @@ "@babel/helper-plugin-utils": "^7.14.5" } }, + "@babel/runtime": { + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.16.5.tgz", + "integrity": "sha512-TXWihFIS3Pyv5hzR7j6ihmeLkZfrXGxAr5UfSl8CHf+6q/wpiYDkUau0czckpYG8QmnCIuPpdLtuA9VmuGGyMA==", + "requires": { + "regenerator-runtime": "^0.13.4" + } + }, "@babel/template": { "version": "7.16.0", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.16.0.tgz", @@ -8052,6 +8119,11 @@ "pretty-format": "^27.0.0" } }, + "@types/lodash": { + "version": "4.14.178", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.178.tgz", + "integrity": "sha512-0d5Wd09ItQWH1qFbEyQ7oTQ3GZrMfth5JkbN3EvTKLXcHLRDSXeLnlvlOn0wvxVIwK5o2M8JzP/OWz7T3NRsbw==" + }, "@types/node": { "version": "16.11.12", "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.12.tgz", @@ -10867,6 +10939,11 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, + "lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==" + }, "lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", @@ -11025,6 +11102,11 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, + "nanoclone": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/nanoclone/-/nanoclone-0.2.1.tgz", + "integrity": "sha512-wynEP02LmIbLpcYw8uBKpcfF6dmg2vcpKqxeH5UcoKEYdExslsdUA4ugFauuaeYdTB76ez6gJW8XAZ6CgkXYxA==" + }, "natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -11572,6 +11654,11 @@ "sisteransi": "^1.0.5" } }, + "property-expr": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/property-expr/-/property-expr-2.0.4.tgz", + "integrity": "sha512-sFPkHQjVKheDNnPvotjQmm3KD3uk1fWKUN7CrpdbwmUx3CrG3QiM8QpTSimvig5vTXmTvjz7+TDvXOI9+4rkcg==" + }, "proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -11694,6 +11781,11 @@ "resolve": "^1.9.0" } }, + "regenerator-runtime": { + "version": "0.13.9", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz", + "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==" + }, "regexpp": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", @@ -12302,6 +12394,11 @@ "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" }, + "toposort": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz", + "integrity": "sha1-riF2gXXRVZ1IvvNUILL0li8JwzA=" + }, "touch": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", @@ -12765,6 +12862,20 @@ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", "dev": true + }, + "yup": { + "version": "0.32.11", + "resolved": "https://registry.npmjs.org/yup/-/yup-0.32.11.tgz", + "integrity": "sha512-Z2Fe1bn+eLstG8DRR6FTavGD+MeAwyfmouhHsIUgaADz8jvFKbO/fXc2trJKZg+5EBjh4gGm3iU/t3onKlXHIg==", + "requires": { + "@babel/runtime": "^7.15.4", + "@types/lodash": "^4.14.175", + "lodash": "^4.17.21", + "lodash-es": "^4.17.21", + "nanoclone": "^0.2.1", + "property-expr": "^2.0.4", + "toposort": "^2.0.2" + } } } } diff --git a/package.json b/package.json index 6b5ebb3c8d..33de5d533c 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,8 @@ "express": "^4.17.1", "knex": "^0.95.14", "sqlite3": "^5.0.2", - "vin-validator": "^1.0.0" + "vin-validator": "^1.0.0", + "yup": "^0.32.11" }, "repository": { "type": "git", From a40a94787ab533ebd8499487282057b8487728f0 Mon Sep 17 00:00:00 2001 From: tamara-taylor Date: Sun, 19 Dec 2021 17:21:58 -0500 Subject: [PATCH 4/4] MVP finished, all tests passing --- api/cars/cars-middleware.js | 9 +++++---- api/cars/cars-model.js | 4 +--- api/cars/cars-router.js | 5 +++-- data/migrations/01-make_cars_table.js | 20 ++++++++++---------- 4 files changed, 19 insertions(+), 19 deletions(-) diff --git a/api/cars/cars-middleware.js b/api/cars/cars-middleware.js index f20b220102..8de28c1365 100644 --- a/api/cars/cars-middleware.js +++ b/api/cars/cars-middleware.js @@ -47,11 +47,12 @@ const checkVinNumberValid = async (req, res, next) => { const checkVinNumberUnique = async (req, res, next) => { try{ - const existing = await db('cars').where('vin', req.body.vin).first() - if(!existing){ - next() + const {vin} = req.body + const existing = await Cars.getByVin(vin) + if(existing){ + next({status: 400, message: `vin ${vin} already exists`}) }else{ - res.status(400).json({message: `vin ${req.body.vin} already exists`}) + next() } }catch(err){ next(err) diff --git a/api/cars/cars-model.js b/api/cars/cars-model.js index 8277dc5ecd..92520d3276 100644 --- a/api/cars/cars-model.js +++ b/api/cars/cars-model.js @@ -11,9 +11,7 @@ const getById = (id) => { const create = async (car) => { const [id] = await db('cars').insert(car) - .then(([id]) => { - return getById(id) - }) + return getById(id) } const getByVin = async (vin) => { diff --git a/api/cars/cars-router.js b/api/cars/cars-router.js index 889d794e05..f7a2488c2a 100644 --- a/api/cars/cars-router.js +++ b/api/cars/cars-router.js @@ -11,8 +11,9 @@ router.get('/', async (req, res, next) => { } }) -router.get('/:id', mw.checkCarId, async (req, res, next) => { - res.status(200).json(req.car) +router.get('/:id', mw.checkCarId, async (req, res) => { + const car = await Cars.getById(req.params.id) + res.json(car) }) router.post('/', mw.checkCarPayload, mw.checkVinNumberUnique, mw.checkVinNumberValid, async (req, res, next) => { diff --git a/data/migrations/01-make_cars_table.js b/data/migrations/01-make_cars_table.js index f432e7db20..af3f2440df 100644 --- a/data/migrations/01-make_cars_table.js +++ b/data/migrations/01-make_cars_table.js @@ -1,15 +1,15 @@ -exports.up = function (knex) { - return knex.schema.createTable('cars', (table) => { +exports.up = async function (knex) { + await knex.schema.createTable('cars', table => { table.increments() - table.string('vin', 16).notNullable().unique() - table.string('make', 128).notNullable() - table.string('model', 256).notNullable() - table.string('mileage').unsigned().notNullable - table.string('title', 128) - table.string('transmission', 128) + table.text('vin', 17).unique().notNullable() + table.text('make', 128).notNullable() + table.text('model', 128).notNullable() + table.integer('mileage').notNullable() + table.text('title', 128) + table.text('transmission', 128) }) }; -exports.down = function (knex) { - return knex.schema.dropTableIfExists('cars') +exports.down = async function (knex) { + await knex.schema.dropTableIfExists('cars') };