-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
mohamed
authored and
mohamed
committed
May 16, 2020
1 parent
c3f5d91
commit 053a1e1
Showing
10 changed files
with
949 additions
and
30 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
export async function handleResponse(response) { | ||
if (response.ok) return response.json(); | ||
if (response.status === 400) { | ||
// So, a server-side validation error occurred. | ||
// Server side validation returns a string error message, so parse as text instead of json. | ||
const error = await response.text(); | ||
throw new Error(error); | ||
} | ||
throw new Error("Network response was not ok."); | ||
} | ||
|
||
// In a real app, would likely call an error logging service. | ||
export function handleError(error) { | ||
// eslint-disable-next-line no-console | ||
console.error("API call failed. " + error); | ||
throw error; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import { handleResponse, handleError } from './apiUtils'; | ||
const baseUrl = process.env.REACT_APP_API_URL + '/authors/'; | ||
|
||
export function getAuthors() { | ||
return fetch(baseUrl) | ||
.then(handleResponse) | ||
.catch(handleError); | ||
} | ||
|
||
export function saveAuthor(author) { | ||
return fetch(baseUrl + (author.id || ''), { | ||
method: author.id ? 'PUT' : 'POST', // POST for create, PUT to update when id already exists. | ||
headers: { 'content-type': 'application/json' }, | ||
body: JSON.stringify(author), | ||
}) | ||
.then(handleResponse) | ||
.catch(handleError); | ||
} | ||
|
||
export function deleteAuthor(authorId) { | ||
return fetch(baseUrl + authorId, { method: 'DELETE' }) | ||
.then(handleResponse) | ||
.catch(handleError); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
import { handleResponse, handleError } from './apiUtils'; | ||
const baseUrl = process.env.REACT_APP_API_URL + '/courses/'; | ||
|
||
export function getCourses() { | ||
return fetch(baseUrl).then(handleResponse).catch(handleError); | ||
} | ||
|
||
export function getCourseBySlug(slug) { | ||
return fetch(baseUrl + '?slug=' + slug) | ||
.then((response) => { | ||
if (!response.ok) { | ||
throw new Error('Network response was not ok.'); | ||
} | ||
return response.json().then((courses) => { | ||
if (courses.length !== 1) { | ||
throw new Error('Course not found: ' + slug); | ||
} | ||
return courses[0]; // should only find one course for a given slug, so return it. | ||
}); | ||
}) | ||
.catch(handleError); | ||
} | ||
|
||
export function saveCourse(course) { | ||
return fetch(baseUrl + (course.id || ''), { | ||
method: course.id ? 'PUT' : 'POST', // POST for create, PUT to update when id already exists. | ||
headers: { 'content-type': 'application/json' }, | ||
body: JSON.stringify({ | ||
...course, | ||
// Parse authorId to a number (in case it was sent as a string). | ||
authorId: parseInt(course.authorId, 10), | ||
}), | ||
}) | ||
.then(handleResponse) | ||
.catch(handleError); | ||
} | ||
|
||
export function deleteCourse(courseId) { | ||
return fetch(baseUrl + courseId, { method: 'DELETE' }) | ||
.then(handleResponse) | ||
.catch(handleError); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
/* | ||
This uses json-server, but with the module approach: https://github.com/typicode/json-server#module | ||
Downside: You can't pass the json-server command line options. | ||
Instead, can override some defaults by passing a config object to jsonServer.defaults(); | ||
You have to check the source code to set some items. | ||
Examples: | ||
Validation/Customization: https://github.com/typicode/json-server/issues/266 | ||
Delay: https://github.com/typicode/json-server/issues/534 | ||
ID: https://github.com/typicode/json-server/issues/613#issuecomment-325393041 | ||
Relevant source code: https://github.com/typicode/json-server/blob/master/src/cli/run.js | ||
*/ | ||
|
||
/* eslint-disable no-console */ | ||
const jsonServer = require('json-server'); | ||
const server = jsonServer.create(); | ||
const path = require('path'); | ||
const router = jsonServer.router(path.join(__dirname, 'db.json')); | ||
|
||
// Can pass a limited number of options to this to override (some) defaults. See https://github.com/typicode/json-server#api | ||
const middlewares = jsonServer.defaults({ | ||
// Display json-server's built in homepage when json-server starts. | ||
static: 'node_modules/json-server/dist', | ||
}); | ||
|
||
// Set default middlewares (logger, static, cors and no-cache) | ||
server.use(middlewares); | ||
|
||
// To handle POST, PUT and PATCH you need to use a body-parser. Using JSON Server's bodyParser | ||
server.use(jsonServer.bodyParser); | ||
|
||
// Simulate delay on all requests | ||
server.use(function (req, res, next) { | ||
setTimeout(next, 0); | ||
}); | ||
|
||
// Declaring custom routes below. Add custom routes before JSON Server router | ||
|
||
// Add createdAt to all POSTS | ||
server.use((req, res, next) => { | ||
if (req.method === 'POST') { | ||
req.body.createdAt = Date.now(); | ||
} | ||
// Continue to JSON Server router | ||
next(); | ||
}); | ||
|
||
server.post('/courses/', function (req, res, next) { | ||
const error = validateCourse(req.body); | ||
if (error) { | ||
res.status(400).send(error); | ||
} else { | ||
req.body.slug = createSlug(req.body.title); // Generate a slug for new courses. | ||
next(); | ||
} | ||
}); | ||
|
||
// Use default router | ||
server.use(router); | ||
|
||
// Start server | ||
const port = 3001; | ||
server.listen(port, () => { | ||
console.log(`JSON Server is running on port ${port}`); | ||
}); | ||
|
||
// Centralized logic | ||
|
||
// Returns a URL friendly slug | ||
function createSlug(value) { | ||
return value | ||
.replace(/[^a-z0-9_]+/gi, '-') | ||
.replace(/^-|-$/g, '') | ||
.toLowerCase(); | ||
} | ||
|
||
function validateCourse(course) { | ||
if (!course.title) { | ||
return 'Title is required.'; | ||
} | ||
if (!course.authorId) { | ||
return 'Author is required.'; | ||
} | ||
if (!course.category) { | ||
return 'Category is required.'; | ||
} | ||
return ''; | ||
} | ||
|
||
export {}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
// import * as mockData from './mockData'; | ||
const fs = require('fs'); | ||
const path = require('path'); | ||
const mockData = require('./mockData'); | ||
|
||
const { courses, authors } = mockData; | ||
|
||
const data = JSON.stringify({ courses, authors }); | ||
const filepath = path.join(__dirname, 'db.json'); | ||
|
||
fs.writeFile(filepath, data, function (err) { | ||
err ? console.log(err) : console.log('Mock DB created.'); | ||
}); | ||
|
||
export {}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
{"courses":[{"id":1,"title":"Securing React Apps with Auth0","slug":"react-auth0-authentication-security","authorId":1,"category":"JavaScript"},{"id":2,"title":"React: The Big Picture","slug":"react-big-picture","authorId":1,"category":"JavaScript"},{"id":3,"title":"Creating Reusable React Components","slug":"react-creating-reusable-components","authorId":1,"category":"JavaScript"},{"id":4,"title":"Building a JavaScript Development Environment","slug":"javascript-development-environment","authorId":1,"category":"JavaScript"},{"id":5,"title":"Building Applications with React and Redux","slug":"react-redux-react-router-es6","authorId":1,"category":"JavaScript"},{"id":6,"title":"Building Applications in React and Flux","slug":"react-flux-building-applications","authorId":1,"category":"JavaScript"},{"id":7,"title":"Clean Code: Writing Code for Humans","slug":"writing-clean-code-humans","authorId":1,"category":"Software Practices"},{"id":8,"title":"Architecting Applications for the Real World","slug":"architecting-applications-dotnet","authorId":1,"category":"Software Architecture"},{"id":9,"title":"Becoming an Outlier: Reprogramming the Developer Mind","slug":"career-reboot-for-developer-mind","authorId":1,"category":"Career"},{"id":10,"title":"Web Component Fundamentals","slug":"web-components-shadow-dom","authorId":1,"category":"HTML5"}],"authors":[{"id":1,"name":"Cory House"},{"id":2,"name":"Scott Allen"},{"id":3,"name":"Dan Wahlin"}]} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
const courses = [ | ||
{ | ||
id: 1, | ||
title: 'Securing React Apps with Auth0', | ||
slug: 'react-auth0-authentication-security', | ||
authorId: 1, | ||
category: 'JavaScript', | ||
}, | ||
{ | ||
id: 2, | ||
title: 'React: The Big Picture', | ||
slug: 'react-big-picture', | ||
authorId: 1, | ||
category: 'JavaScript', | ||
}, | ||
{ | ||
id: 3, | ||
title: 'Creating Reusable React Components', | ||
slug: 'react-creating-reusable-components', | ||
authorId: 1, | ||
category: 'JavaScript', | ||
}, | ||
{ | ||
id: 4, | ||
title: 'Building a JavaScript Development Environment', | ||
slug: 'javascript-development-environment', | ||
authorId: 1, | ||
category: 'JavaScript', | ||
}, | ||
{ | ||
id: 5, | ||
title: 'Building Applications with React and Redux', | ||
slug: 'react-redux-react-router-es6', | ||
authorId: 1, | ||
category: 'JavaScript', | ||
}, | ||
{ | ||
id: 6, | ||
title: 'Building Applications in React and Flux', | ||
slug: 'react-flux-building-applications', | ||
authorId: 1, | ||
category: 'JavaScript', | ||
}, | ||
{ | ||
id: 7, | ||
title: 'Clean Code: Writing Code for Humans', | ||
slug: 'writing-clean-code-humans', | ||
authorId: 1, | ||
category: 'Software Practices', | ||
}, | ||
{ | ||
id: 8, | ||
title: 'Architecting Applications for the Real World', | ||
slug: 'architecting-applications-dotnet', | ||
authorId: 1, | ||
category: 'Software Architecture', | ||
}, | ||
{ | ||
id: 9, | ||
title: 'Becoming an Outlier: Reprogramming the Developer Mind', | ||
slug: 'career-reboot-for-developer-mind', | ||
authorId: 1, | ||
category: 'Career', | ||
}, | ||
{ | ||
id: 10, | ||
title: 'Web Component Fundamentals', | ||
slug: 'web-components-shadow-dom', | ||
authorId: 1, | ||
category: 'HTML5', | ||
}, | ||
]; | ||
|
||
const authors = [ | ||
{ id: 1, name: 'Cory House' }, | ||
{ id: 2, name: 'Scott Allen' }, | ||
{ id: 3, name: 'Dan Wahlin' }, | ||
]; | ||
|
||
const newCourse = { | ||
id: null, | ||
title: '', | ||
authorId: null, | ||
category: '', | ||
}; | ||
|
||
module.exports = { | ||
newCourse, | ||
courses, | ||
authors, | ||
}; | ||
|
||
export {}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.