Skip to content

Commit

Permalink
✨ Add working solution!
Browse files Browse the repository at this point in the history
  • Loading branch information
w3cj committed May 15, 2018
1 parent cd23740 commit ba876ad
Show file tree
Hide file tree
Showing 11 changed files with 3,229 additions and 26 deletions.
54 changes: 28 additions & 26 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,35 +2,37 @@

A simple full stack app for creating short urls like bit.ly

* [ ] Create Server Folder
* [ ] Init npm
* [ ] Add express morgan body-parser nodemon
* [ ] Add start script and dev script
* [ ] Create public Folder
* [ ] Create index.html
* [ ] Add vue CDN
* [ ] Add bulma CSS
* [ ] Homepage Layout
* [ ] Serve public folder from express
* [ ] Create new url form on client
* [ ] Submit form - fetch POST to server
* [ ] Show any errors
* [ ] Show create link on page
puny.li/cg

* [x] Create Server Folder
* [x] Init npm
* [x] Add express morgan body-parser nodemon
* [x] Add start script and dev script
* [x] Create public Folder
* [x] Create index.html
* [x] Add vue CDN
* [x] Add bulma CSS
* [x] Homepage Layout
* [x] Serve public folder from express
* [x] Create new url form on client
* [ ] Add DB to server
* [ ] Add monk
* [ ] Create db folder
* [ ] Create db connection
* [x] Add monk
* [x] Create db folder
* [x] Create db connection
* [ ] Create route to add url to db `/api/url`
* [ ] validate url with joi
* [x] validate puny with joi
* url
* name alphanum, min 5 chars, max 100 chars
* [ ] Make sure name is not in use
* [ ] insert url into db
* [ ] respond with inserted message
* [ ] Respond with error if in use
* [ ] Create route to redirect a url
* [ ] Search by name - if found, redirect to url
* [ ] If not found, show 404
* name alphanum, min 1 chars, max 100 chars
* [x] Make sure name is not in use
* [x] insert url into db
* [x] respond with inserted message
* [x] Respond with error if in use
* [x] Submit form - fetch POST to server
* [x] Show any errors
* [x] Show create link on page
* [x] Create route to redirect a url
* [x] Search by name - if found, redirect to url
* [x] If not found, show 404
* [ ] Deploy!
* [ ] Alias domain

Expand Down
61 changes: 61 additions & 0 deletions server/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# Runtime data
pids
*.pid
*.seed
*.pid.lock

# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov

# Coverage directory used by tools like istanbul
coverage

# nyc test coverage
.nyc_output

# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt

# Bower dependency directory (https://bower.io/)
bower_components

# node-waf configuration
.lock-wscript

# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release

# Dependency directories
node_modules/
jspm_packages/

# TypeScript v1 declaration files
typings/

# Optional npm cache directory
.npm

# Optional eslint cache
.eslintcache

# Optional REPL history
.node_repl_history

# Output of 'npm pack'
*.tgz

# Yarn Integrity file
.yarn-integrity

# dotenv environment variables file
.env

# next.js build output
.next
5 changes: 5 additions & 0 deletions server/db/connection.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
const monk = require('monk');
const connectionURL = process.env.MONGODB_URI || 'localhost/puny-li';
const db = monk(connectionURL);

module.exports = db;
52 changes: 52 additions & 0 deletions server/db/urls.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
const Joi = require('joi');
const db = require('./connection');

const urls = db.get('urls');

const schema = Joi.object().keys({
name: Joi.string().token().min(1).max(100).required(),
url: Joi.string().uri({
scheme: [
/https?/
]
})
}).with('name', 'url');

function find(name) {
return urls.findOne({
name
});
}

/*
{
url: 'http://example.com',
name: 'super-catchy'
}
*/
async function create(almostPuny) {
const result = Joi.validate(almostPuny, schema);
// result.error === null
if (result.error === null) {
const url = await urls.findOne({
name: almostPuny.name
});
if (!url) {
return urls.insert(almostPuny);
} else {
return Promise.reject({
isJoi: true,
details: [{
message: 'Short name is in use.'
}]
});
}
} else {
return Promise.reject(result.error);
}
}

module.exports = {
create,
find
};
36 changes: 36 additions & 0 deletions server/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
const express = require('express');
const morgan = require('morgan');
const bodyParser = require('body-parser');

const urls = require('./db/urls');

const app = express();

app.use(morgan('tiny'));
app.use(bodyParser.json());
app.use(express.static('./public'));

app.get('/:name', async (req, res) => {
const puny = await urls.find(req.params.name);
if (puny) {
res.redirect(puny.url);
} else {
res.redirect(`/404.html?name=${req.params.name}`);
}
});

app.post('/api/puny', async (req, res) => {
console.log(req.body);
try {
const url = await urls.create(req.body);
res.json(url);
} catch (error) {
res.status(500);
res.json(error);
}
});

const port = process.env.PORT || 5000;
app.listen(port, () => {
console.log(`listening on port ${port}`);
});
Loading

0 comments on commit ba876ad

Please sign in to comment.