Skip to content

Commit 2620134

Browse files
committed
chore
0 parents  commit 2620134

20 files changed

+4038
-0
lines changed

.gitignore

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
node_modules
2+
*.log
3+
*.error
4+
dist
5+
DS_Store

README.md

+67
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
# Intro to Nodejs
2+
> Scott Moss & Frontend Masters
3+
- [Resources](#resources)
4+
- [Course](#course)
5+
- [Excercises](#excercises)
6+
- [Installing Node](#installing-node)
7+
- [Modules (node vs browser)](#modules-node-vs-browser)
8+
- [CLI (npm)](#cli-npm)
9+
- [API (async code)](#api-async-code)
10+
- [Debugging & Testing](#debugging--testing)
11+
- [Sharing and Deploying](#sharing-and-deploying)
12+
13+
## Resources
14+
* [Slides](https://slides.com/scotups/deck/fullscreen)
15+
* [Nodejs](https://nodejs.org/en/)
16+
* [NVM](https://github.com/creationix/nvm)
17+
18+
## Course
19+
This course has two parts, slides and excercises. The slides describe the excerices in detail. Each excercise has a folder
20+
## Excercises
21+
### Installing Node
22+
Install node with [node version manager (NVM)](https://github.com/creationix/nvm). NVM was created by the community and not the Nodejs foundation. However, it is the recommended approach. After installing nvm, use nvm to install the lates version of Nodejs, which at the time is `10` and set it to the default version
23+
```bash
24+
nvm install node # node is an alias for the latest version
25+
nvm alias default node
26+
```
27+
If this fails, or you want to install nodejs from nodejs source, [then go here](https://nodejs.org/en/)
28+
### Modules (node vs browser)
29+
* location - `exercises/modules`
30+
* commands
31+
* test - `npx jest`
32+
33+
This exercise will have you convert some JavaScript written for the browser, so that it works with node.
34+
- [ ] check out to start branch
35+
- [ ] check the README on how to run test (will talk later about that command)
36+
- [ ] fix and convert the 3 js files in the exercises/modules/browser to Nodejs JavaScript and place them in exercises/modules/node
37+
- [ ] ensure all tests pass by running test command again
38+
### CLI (npm)
39+
* location - `exercises/cli`
40+
* commands
41+
* new - `node exercises/cli/index.js new`
42+
* list - `node exercises/cli/index.js list`
43+
44+
You'll be creating a CLI program that saves and retrieves contacts from and address book. The program is partially there, however, you must install some remote modules, and use the fileSystem to get some things to work.
45+
46+
- [ ] install all remote modules (hint: use npm)
47+
- [ ] Check the README on how to run your CLI
48+
- [ ] Fix the CLI so that the "new" command works by saving contacts to contacts.json
49+
- [ ] Fix the CLI so that the "list" command works by listing all contacts and allowing you to select one, the prints out the selected contact
50+
### API (async code)
51+
* location - `exercises/api`
52+
* commands
53+
* start the server - `node exercises/api/server.js`
54+
55+
You'll be refacoring and fixing a simple static asset server. The server uses blocking sync code and crashes whenever a request comes in that is asking for an asset that is not found. Neither of those are desirable. You'll also have to teach the server how to server the assets it has in the `assets` folder.
56+
57+
- [ ] install all remote modules (hint: use npm)
58+
- [ ] Check the README on how to run your CLI
59+
- [ ] refactor the sync file reading code to be async with a callback, promise, or async await
60+
- [ ] prevent the server from crashing when an assets is not found. Instead, respond with a 404 status code
61+
- [ ] create some sort of router logic to handle incoming requests for assets
62+
63+
### Debugging & Testing
64+
### Sharing and Deploying
65+
66+
67+

exercises/api/assets/index.html

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
6+
<meta http-equiv="X-UA-Compatible" content="ie=edge">
7+
<link rel="stylesheet" href="style.css">
8+
<title>Document</title>
9+
</head>
10+
<body>
11+
<div class="box">
12+
<div class="card">
13+
<h3>Yo! my first server in Nodejs</h3>
14+
</div>
15+
</div>
16+
</body>
17+
</html>

exercises/api/assets/style.css

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
html, body, ul, ol {
2+
margin: 0px;
3+
padding: 0px;
4+
}
5+
6+
* {
7+
font-family: Roboto;
8+
}
9+
10+
* {
11+
box-sizing: border-box;
12+
}
13+
14+
body, html {
15+
height: 100%;
16+
background: #efefef;
17+
}
18+
19+
body {
20+
display: flex;
21+
justify-content: center;
22+
align-items: center;
23+
}
24+
25+
.box {
26+
width: 33%;
27+
}
28+
.card {
29+
border: 1px solid lightgray;
30+
border-radius: 3px;
31+
text-align: center;
32+
background: white;
33+
}

exercises/api/server.js

+66
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
const http = require('http')
2+
const url = require('url')
3+
const fs = require('fs')
4+
const path = require('path')
5+
const mime = require('mime')
6+
7+
/**
8+
* async function that reads asset from disk
9+
* @param {String} name full file name of asset in asset folder
10+
*/
11+
const findAsset = (name) => {
12+
return new Promise((resolve, reject) => {
13+
const assetPath = path.join(__dirname, 'assets', name)
14+
fs.readFile(assetPath, {encoding: 'utf-8'}, (err, asset) => {
15+
if (err) {
16+
reject(err)
17+
} else {
18+
resolve(asset)
19+
}
20+
})
21+
})
22+
}
23+
24+
const hostname = '127.0.0.1'
25+
const port = 3000
26+
// simple, quick router object
27+
const router = {
28+
'/ GET': {
29+
asset: 'index.html',
30+
type: mime.getType('html')
31+
},
32+
'/style.css GET': {
33+
asset: 'style.css',
34+
type: mime.getType('css')
35+
}
36+
}
37+
38+
// log incoming request coming into the server. Helpful for debugging and tracking
39+
const logRequest = (method, route, status) => console.log(method, route, status)
40+
41+
const server = http.createServer(async (req, res) => {
42+
const method = req.method
43+
const route = url.parse(req.url).pathname
44+
// check the router for the incomming route + method pair
45+
const routeMatch = router[`${route} ${method}`]
46+
debugger
47+
// return not found if the router does not have a match
48+
if (!routeMatch) {
49+
res.writeHead(404)
50+
logRequest(method, route, 404)
51+
return res.end()
52+
}
53+
54+
const {type, asset} = routeMatch
55+
56+
// set the content-type header for the asset so applications like a browser will know how to handle it
57+
res.writeHead(200,{'Content-Type': type})
58+
// most important part, send down the asset
59+
res.write(await findAsset(asset))
60+
logRequest(method, route, 200)
61+
res.end()
62+
})
63+
64+
server.listen(port, hostname, () => {
65+
console.log(`Server running at http://${hostname}:${port}/`)
66+
})

exercises/cli/contacts.json

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"adfsadf asfdasdf": {
3+
"firstName": "adfsadf",
4+
"lastName": "asfdasdf",
5+
"phoneNumber": "asfdsf"
6+
}
7+
}

exercises/cli/index.js

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
const program = require('commander')
2+
const { prompt } = require('inquirer')
3+
const {newContactPrompts} = require('./prompts')
4+
const {getContacts, saveContacts} = require('./utils')
5+
6+
program
7+
.version('0.0.1')
8+
.description('Address book CLI program')
9+
10+
program
11+
.command('new')
12+
.alias('n')
13+
.description('add a new contact')
14+
.action(() => {
15+
prompt(newContactPrompts)
16+
.then(({firstName, lastName, phoneNumber}) => {
17+
const key = firstName + ' ' + lastName
18+
const contacts = getContacts()
19+
contacts[key] = {firstName, lastName, phoneNumber}
20+
saveContacts(contacts)
21+
})
22+
})
23+
24+
program
25+
.command('list')
26+
.alias('l')
27+
.description('list all contacts')
28+
.action(() => {
29+
const contacts = getContacts()
30+
prompt([
31+
{
32+
type: 'list',
33+
name: 'selected',
34+
message: 'Select a contact',
35+
choices: Object.keys(contacts)
36+
}
37+
])
38+
.then(({selected}) => {
39+
const contact = contacts[selected]
40+
console.log(JSON.stringify(contact, null, 2))
41+
})
42+
})
43+
44+
program.parse(process.argv)

exercises/cli/prompts.js

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
const newContactPrompts = [
2+
{name: 'firstName', message: 'First Name'},
3+
{name: 'lastName', message: 'Last Name'},
4+
{name: 'phoneNumber', message: 'Phone Number'}
5+
]
6+
7+
module.exports = {newContactPrompts}

exercises/cli/utils.js

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
const fs = require('fs')
2+
const path = require('path')
3+
4+
const contactsLocation = path.join(__dirname, 'contacts.json')
5+
const getContacts = () => JSON.parse(fs.readFileSync(contactsLocation))
6+
const saveContacts = (contacts) => fs.writeFileSync(contactsLocation, JSON.stringify(contacts, null, 2))
7+
8+
module.exports = {contactsLocation, getContacts, saveContacts}
9+

exercises/modules/browser/api.js

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
window.App = window.App || {}
2+
3+
window.App.getUserById = (id, cb) => {
4+
// simulate API call
5+
window.setTimeout(() => {
6+
const user = window.App.users.find(user => user.id === id)
7+
cb(user)
8+
}, 150)
9+
}
10+
11+
window.App.getPostsForUser = (userId, cb) => {
12+
// simulate API call
13+
window.setTimeout(() => {
14+
const posts = window.App.posts.filter(post => post.createdBy === userId)
15+
cb(posts)
16+
}, 150)
17+
}

exercises/modules/browser/app.js

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
window.App = window.App || {}
2+
3+
window.App.showPostsForCurrentUser = (userId, cb) => {
4+
window.App.getPostsForUser(userId, posts => {
5+
const postTemplates = posts.map(post => {
6+
return `
7+
<div class="post">
8+
${post.title}
9+
${post.body}
10+
${post.createdBy}
11+
</div>`
12+
})
13+
cb(postTemplates)
14+
})
15+
}
16+
17+
window.App.showUserProfile = (userId, cb) => {
18+
window.App.getUserById(userId, user => {
19+
const profile = `
20+
<div>
21+
${user.name}
22+
</div>
23+
`
24+
cb(user)
25+
})
26+
}
27+
28+

exercises/modules/browser/data.js

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
window.App = {
2+
users: [
3+
{id: 1, name: 'Weezy'}
4+
],
5+
posts: [
6+
{title: 'yo', body: 'I ate today', createdBy: 1},
7+
{title: 'Me', body: 'Look at my selfie', createdBy: 1},
8+
{title: 'My doggy', body: 'my dog is better than yours', createdBy: 1}
9+
]
10+
}

exercises/modules/browser/index.html

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
6+
<meta http-equiv="X-UA-Compatible" content="ie=edge">
7+
<link rel="stylesheet" href="style.css">
8+
<!-- order matters here for the script tags, as the next relies on the previous -->
9+
<script src="data.js"></script>
10+
<script src="api.js"></script>
11+
<script src="app.js"></script>
12+
<title>app</title>
13+
</head>
14+
<body>
15+
<div id="app"></div>
16+
17+
<script>
18+
// browser only DOM code, don't try to convert this to Node.
19+
App.showPostsForCurrentUser(1, posts => {
20+
const root = document.getElementById('app')
21+
posts.forEach(post => {
22+
const element = document.createElement('div')
23+
element.className = 'box'
24+
element.innerHTML = post
25+
root.appendChild(element)
26+
})
27+
})
28+
</script>
29+
</body>
30+
</html>

exercises/modules/browser/style.css

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
body, html, ul, ol {
2+
margin: 0px;
3+
padding: 0px;
4+
}
5+
6+
#app {
7+
display: flex;
8+
justify-content: space-between;
9+
padding: 50px;
10+
}
11+
.box {
12+
flex: 1;
13+
padding: 10px;
14+
}
15+
.post {
16+
border: 1px solid blueviolet;
17+
padding: 10px;
18+
border-radius: 3px;
19+
}
20+
header {
21+
height: 60px;
22+
background-color: blueviolet;
23+
}

0 commit comments

Comments
 (0)