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
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@
* [NPM](https://www.npmjs.com/)

## Course
This course has two parts, slides and exercises. The slides describe the exercises in detail. Each exercise has a folder
## Exercises
=======
Thanks for taking the [Introduction to Node.js course](https://frontendmasters.com/courses/node-js/) -- the course has two parts: slides and exercises. The slides describe the exercises in detail. Each exercise have a folder.

## Exercises
Expand Down
48 changes: 16 additions & 32 deletions exercises/api/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,45 +2,37 @@ const http = require('http')
const url = require('url')
const fs = require('fs')
const path = require('path')
const mime = require('mime')

/**
* async function that reads asset from disk
* this function is blocking, fix that
* @param {String} name full file name of asset in asset folder
*/
const findAsset = (name) => {
return new Promise((resolve, reject) => {
const assetPath = path.join(__dirname, 'assets', name)
fs.readFile(assetPath, {encoding: 'utf-8'}, (err, asset) => {
if (err) {
reject(err)
} else {
resolve(asset)
}
})
})
const assetPath = path.join(__dirname, 'assets', name)
return fs.readFileSync(assetPath, {encoding: 'utf-8'}).toString()
}

const hostname = '127.0.0.1'
const port = 3000
// simple, quick router object
const router = {
'/ GET': {
asset: 'index.html',
type: mime.getType('html')
},
'/style.css GET': {
asset: 'style.css',
type: mime.getType('css')
}
}

// log incoming request coming into the server. Helpful for debugging and tracking
const logRequest = (method, route, status) => console.log(method, route, status)

const server = http.createServer(async (req, res) => {
const server = http.createServer((req, res) => {
const method = req.method
const route = url.parse(req.url).pathname

// this is sloppy, especially with more assets, create a "router"
if (route === '/') {
res.writeHead(200, {'Content-Type': 'text/html'})
res.write(findAsset('index.html'))
logRequest(method, route, 200)
res.end()
} else {
// missing asset should not cause server crash
throw new Error('route not found')
res.end()
=======
// check the router for the incomming route + method pair
const routeMatch = router[`${route} ${method}`]
// return not found if the router does not have a match
Expand All @@ -49,15 +41,7 @@ const server = http.createServer(async (req, res) => {
logRequest(method, route, 404)
return res.end()
}

const {type, asset} = routeMatch

// set the content-type header for the asset so applications like a browser will know how to handle it
res.writeHead(200,{'Content-Type': type})
// most important part, send down the asset
res.write(await findAsset(asset))
logRequest(method, route, 200)
res.end()
})

server.listen(port, hostname, () => {
Expand Down
1 change: 1 addition & 0 deletions exercises/cli/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// install any missing modules
const program = require('commander')
const { prompt } = require('inquirer')
const {newContactPrompts} = require('./prompts')
Expand Down
29 changes: 25 additions & 4 deletions exercises/cli/utils.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,30 @@
const fs = require('fs')
const path = require('path')

const contactsLocation = path.join(__dirname, 'contacts.json')
const getContacts = () => JSON.parse(fs.readFileSync(contactsLocation))
const saveContacts = (contacts) => fs.writeFileSync(contactsLocation, JSON.stringify(contacts, null, 2))
// this path needs to be relative to work with fs
const contactsLocation = 'contacts.json'

module.exports = {contactsLocation, getContacts, saveContacts}
/**
* should read the contacts at the
* @contactsLocation path and convert
* it to a js object
*/
const getContacts = () => {

}

/**
* takes a contacts object, converts it to JSON
* and saves it at the @contactsLocation path
* @param {Object} contacts contacts object
*/
const saveContacts = (contacts) => {

}

module.exports = {
contactsLocation,
getContacts,
saveContacts
}

20 changes: 9 additions & 11 deletions exercises/modules/node/api.js
Original file line number Diff line number Diff line change
@@ -1,22 +1,20 @@
const data = require('./data')

const { users,posts } = require('./data');
const getUserById = (id, cb) => {
// simulate API call
setTimeout(() => {
const user = data.users.find(user => user.id === id)
setTimeout(() => {
const user = users.find(user => user.id === id)
cb(user)
}, 150)
}

const getPostsForUser = (userId, cb) => {
// simulate API call
setTimeout(() => {
const posts = data.posts.filter(post => post.createdBy === userId)
cb(posts)
setTimeout(() => {
const _posts = posts.filter(post => post.createdBy === userId)
cb(_posts)
}, 150)
}

module.exports = {
getUserById,
getPostsForUser
}
getPostsForUser,
getUserById
}
13 changes: 5 additions & 8 deletions exercises/modules/node/app.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
const api = require('./api')

const { getPostsForUser,getUserById } = require('./api');
const showPostsForCurrentUser = (userId, cb) => {
api.getPostsForUser(userId, posts => {
getPostsForUser(userId, posts => {
const postTemplates = posts.map(post => {
return `
<div class="post">
Expand All @@ -14,20 +13,18 @@ const showPostsForCurrentUser = (userId, cb) => {
})
}

const showUserProfile = (userId, cb) => {
api.getUserById(userId, user => {
showUserProfile = (userId, cb) => {
getUserById(userId, user => {
const profile = `
<div>
${user.name}
</div>
`
cb(profile)
cb(user)
})
}

module.exports = {
showPostsForCurrentUser,
showUserProfile
}


4 changes: 4 additions & 0 deletions exercises/testing/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,11 @@ app.get('/user/:id', async (req, res) => {
})

app.delete('/user/:id', async (req, res) => {

const id = req.id
=======
const id = req.params.id

await users.deleteUser(id)
res.status(201).send({id})
})
Expand Down
27 changes: 1 addition & 26 deletions exercises/testing/test.js
Original file line number Diff line number Diff line change
@@ -1,29 +1,4 @@
const { findUser, deleteUser, fixId } = require('./users')
// write some tests
describe('users', () => {
describe('fixId', () => {
test('convert param id to db id', () => {
expect(fixId('200')).toBe(200)
})
})
describe('findUser', () => {
test('finds user by id if user is there', async () => {
const user = await findUser(1)
expect(user.id).toBe(1)
})
})
describe('deletUser', () => {
test('deletes user with id if user is there', async () => {
expect.assertions(2)

const user = await findUser(1)
const deletedUser = await deleteUser(user.id)
expect(deletedUser.id).toBe(1)
try {
await findUser(1)
} catch(e) {
expect(e).toBeTruthy()
}
})
})

})
20 changes: 8 additions & 12 deletions exercises/testing/users.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,33 +7,29 @@ const users = new Array(20).fill(0)
}
})

const fixId = id => parseInt(id)

// simulate async db call with promise
const findUser = (id) => new Promise((resolve, reject) => {
let _id = fixId(id)
const user = users.find(user => user.id === _id)
const user = users.find(user => user.id === id)
if (user) {
return resolve(user)
}
reject(new Error(`No user with id "${_id}"`))
reject(new Error(`No user with id "${id}"`))
})

// simulate async db call with promise
const deleteUser = (id) => new Promise((resolve, reject) => {
const _id = fixId(id)
const i = users.findIndex(user => user.id === _id)
const id = fixId(id)
const i = users.findIndex(user => user.id === id)

if (i < 0) {
return reject(new Error(`No user with id "${_id}"`))
return reject(new Error(`No user with id "${id}"`))
}

users.splice(i, 1)
resolve({id: _id})
users.slice(i, 1)
resolve({id})
})

module.exports = {
findUser,
deleteUser,
fixId
deleteUser
}
Loading