Skip to content

Commit f83c7d6

Browse files
committed
Better looking error pages
1 parent 24b4e5b commit f83c7d6

File tree

5 files changed

+175
-36
lines changed

5 files changed

+175
-36
lines changed

Diff for: .gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
creds.json
12
# Logs
23
logs
34
*.log

Diff for: functions/index.js

+93-36
Original file line numberDiff line numberDiff line change
@@ -3,52 +3,109 @@ const _ = require("lodash");
33
const axios = require("axios");
44
const express = require("express");
55
const cors = require("cors");
6+
const resumeSchema = require("resume-schema");
67
const fs = require("fs");
78
const app = express();
9+
// Import Admin SDK
10+
var admin = require("firebase-admin");
811

12+
if (process.env.NODE_ENV === "production") {
13+
admin.initializeApp(functions.config().firebase);
14+
} else {
15+
var serviceAccount = require("../creds.json");
16+
admin.initializeApp({
17+
credential: admin.credential.cert(serviceAccount),
18+
databaseURL: "https://jsonresume-registry.firebaseio.com"
19+
});
20+
}
21+
22+
var db = admin.database();
923
app.use(cors({ origin: true }));
1024

25+
const makeTemplate = message => {
26+
const template = fs.readFileSync(__dirname + "/template.html", "utf8");
27+
return template.replace("{MESSAGE}", message);
28+
};
29+
1130
app.get("/:username", async (req, res) => {
1231
const username = req.params.username;
13-
if (username === "favicon.ico") {
32+
if (
33+
[
34+
"favicon.ico",
35+
"competition",
36+
"stats",
37+
"apple-touch-icon.png",
38+
"apple-touch-icon-precomposed.png",
39+
"robots.txt"
40+
].indexOf(username) !== -1
41+
) {
1442
return res.send(null);
1543
}
16-
console.log(`https://api.github.com/users/${req.params.username}/gists`);
17-
const gistData = await axios.get(
18-
`https://api.github.com/users/${req.params.username}/gists`
19-
);
20-
if (!gistData.data) {
21-
res.send("This username does not exist on Github");
22-
}
23-
const resumeUrl = _.find(gistData.data, f => {
24-
return f.files["resume.json"];
25-
});
26-
if (!resumeUrl) {
27-
res.send("You have no gists named resume.json");
28-
}
29-
const gistId = resumeUrl.id;
30-
const options =
31-
resumeUrl.description.length > 0 ? JSON.parse(resumeUrl.description) : {};
32-
const theme = options.theme || "flat";
33-
const fullResumeGistUrl = `https://gist.githubusercontent.com/${username}/${gistId}/raw/`;
34-
console.log(fullResumeGistUrl);
35-
const resumeRes = await axios({
36-
method: "GET",
37-
headers: { "content-type": "application/json" },
38-
url: fullResumeGistUrl
44+
var ref = db.ref();
45+
var usersRef = ref.child("gists/" + username);
46+
usersRef.on("value", async dataSnapshot => {
47+
console.log("=======");
48+
console.log(dataSnapshot.val());
49+
let gistId;
50+
if (!dataSnapshot.val() || !dataSnapshot.val().gistId) {
51+
console.log("Fetching gistId");
52+
console.log(`https://api.github.com/users/${req.params.username}/gists`);
53+
let gistData = {};
54+
try {
55+
gistData = await axios.get(
56+
`https://api.github.com/users/${req.params.username}/gists`
57+
);
58+
} catch (e) {
59+
return res.send(makeTemplate("This is not a valid Github username"));
60+
}
61+
if (!gistData.data) {
62+
return res.send(makeTemplate("This is not a valid Github username"));
63+
}
64+
const resumeUrl = _.find(gistData.data, f => {
65+
return f.files["resume.json"];
66+
});
67+
if (!resumeUrl) {
68+
return res.send(makeTemplate("You have no gists named resume.json"));
69+
}
70+
gistId = resumeUrl.id;
71+
} else {
72+
console.log("Using cached gistId");
73+
gistId = dataSnapshot.val().gistId;
74+
}
75+
76+
usersRef.set({ gistId: gistId }, () => {});
77+
const fullResumeGistUrl =
78+
`https://gist.githubusercontent.com/${username}/${gistId}/raw?cachebust=` +
79+
new Date().getTime();
80+
console.log(fullResumeGistUrl);
81+
const resumeRes = await axios({
82+
method: "GET",
83+
headers: { "content-type": "application/json" },
84+
url: fullResumeGistUrl
85+
});
86+
if (!resumeRes.data) {
87+
return res.send(makeTemplate("Something went wrong fetching resume"));
88+
}
89+
resumeSchema.validate(resumeRes.data, async (err, report) => {
90+
console.log("validation finished");
91+
if (err) {
92+
console.log(err);
93+
return res.send(
94+
makeTemplate("Resume json invalid - " + JSON.stringify(err))
95+
);
96+
}
97+
const theme =
98+
(resumeRes.data.meta && resumeRes.data.meta.theme) || "flat";
99+
const resumeHTMLRes = await axios.post(
100+
`https://themes.jsonresume.org/theme/${theme}`,
101+
{ resume: resumeRes.data }
102+
);
103+
if (!resumeHTMLRes.data) {
104+
res.send("There was an error generatoring your resume");
105+
}
106+
res.send(resumeHTMLRes.data);
107+
});
39108
});
40-
if (!resumeRes.data) {
41-
res.send("Something went wrong fetching resume");
42-
}
43-
console.log(resumeRes);
44-
const resumeHTMLRes = await axios.post(
45-
`https://themes.jsonresume.org/theme/${theme}`,
46-
{ resume: resumeRes.data }
47-
);
48-
if (!resumeHTMLRes.data) {
49-
res.send("There was an error generatoring your resume");
50-
}
51-
res.send(resumeHTMLRes.data);
52109
});
53110
app.listen(3000);
54111
exports.registry = functions.https.onRequest(app);

Diff for: functions/package-lock.json

+40
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: functions/package.json

+1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
"firebase-admin": "~7.0.0",
2020
"firebase-functions": "^2.3.0",
2121
"lodash": "^4.17.11",
22+
"resume-schema": "0.0.17",
2223
"superagent": "^5.1.0"
2324
},
2425
"devDependencies": {

Diff for: functions/template.html

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
2+
<!doctype html>
3+
<html class="no-js" lang="">
4+
5+
<head>
6+
<meta charset="utf-8">
7+
<title>JSON resume</title>
8+
<meta name="description" content="JSON Resume's official open hosting">
9+
<meta name="viewport" content="width=device-width, initial-scale=1">
10+
11+
12+
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/8.0.1/normalize.min.css" integrity="sha256-l85OmPOjvil/SOvVt3HnSSjzF1TUMyT9eV0c2BzEGzU=" crossorigin="anonymous" />
13+
<link href="https://fonts.googleapis.com/css?family=Open+Sans:400,400i,600,600i&display=swap" rel="stylesheet">
14+
<style>
15+
body {
16+
background-color: rgb(255, 241, 143);
17+
18+
font-family: 'Open Sans', sans-serif;
19+
padding-top: 300px;
20+
text-align: center;
21+
color: #222;
22+
}
23+
h1 {
24+
font: 300 70px "Open Sans";
25+
}
26+
p {
27+
font: 300 30px "Open Sans";
28+
29+
}
30+
</style>
31+
</head>
32+
33+
<body>
34+
<h1>JSON Resume</h1>
35+
<!-- Add your site or application content here -->
36+
<p>{MESSAGE}</p>
37+
38+
</body>
39+
40+
</html>

0 commit comments

Comments
 (0)