@amasad/

my blog

Nodejs

No description

fork
loading
Files
  • index.js
  • bin
  • essays
  • lib
  • pages
  • public
  • .eslintrc.json
  • package-lock.json
  • package.json
  • scratch.json
  • yarn.lock

This Plugin Crashed!

Error: Error: must not create an existing file {"type":"CREATE_FILE","wid":"0.7223900285779945","path":"index.js","file":{"path":"index.js","content":{"asEncoding":{"base64":"Y29uc3QgZXhwcmVzcyA9IHJlcXVpcmUoJ2V4cHJlc3MnKTsKY29uc3QgcmVuZGVyUGFnZSA9IHJlcXVpcmUoJy4vbGliL3JlbmRlclBhZ2UnKTsKY29uc3QgbWFya2VkID0gcmVxdWlyZSgnbWFya2VkJyk7CmNvbnN0IHBhdGggPSByZXF1aXJlKCdwYXRoJyk7CmNvbnN0IGFwcCA9IGV4cHJlc3MoKTsKY29uc3QgZnMgPSByZXF1aXJlKCdmcycpOwpjb25zdCBobGpzID0gcmVxdWlyZSgnaGlnaGxpZ2h0LmpzJyk7CmNvbnN0IF8gPSByZXF1aXJlKCdsb2Rhc2gnKTsKY29uc3QgeyBGZWVkIH0gPSByZXF1aXJlKCdmZWVkJyk7Cgpjb25zdCByZW5kZXJlciA9IG5ldyBtYXJrZWQuUmVuZGVyZXIoKTsKCi8vIFBhc3MgaHRtbCB1bmVzY2FwZWQKcmVuZGVyZXIuaHRtbCA9IHN0ciA9PiBfLnVuZXNjYXBlKHN0cik7CgptYXJrZWQuc2V0T3B0aW9ucyh7CiAgcmVuZGVyZXI6IHJlbmRlcmVyLAogIGhpZ2hsaWdodChjb2RlLCBsYW5nKSB7CiAgICB0cnkgewogICAgICByZXR1cm4gaGxqcy5oaWdobGlnaHQoY29kZSwgbGFuZykudmFsdWU7CiAgICB9IGNhdGNoIChlKSB7CiAgICAgIC8vIEZhaWxlZCB0byBoaWdobGlnaHQgdGhlIGxhbmd1YWdlCiAgICAgIHJldHVybiBobGpzLmhpZ2hsaWdodEF1dG8oY29kZSkudmFsdWU7CiAgICB9CiAgfSwKfSk7Cgpjb25zdCBzdGF0aWNPcHRzID0gewogIG1heEFnZTogMzY1ICogMjQgKiA2MCAqIDYwICogMTAwMCwKfTsKCmFwcC51c2UoJy9wdWJsaWMnLCBleHByZXNzLnN0YXRpYygKICBwYXRoLmpvaW4oX19kaXJuYW1lLCAncHVibGljJyksIHN0YXRpY09wdHMKKSk7Cgpjb25zdCBlc3NheXNEaXIgPSBwYXRoLmpvaW4oX19kaXJuYW1lLCAnZXNzYXlzJyk7CgpmdW5jdGlvbiBwYXJzZShmcGF0aCkgewogIGNvbnN0IHBvc3QgPSBmcy5yZWFkRmlsZVN5bmMocGF0aC5qb2luKGVzc2F5c0RpciwgZnBhdGgpLCAndXRmOCcpOwogIGNvbnN0IHBhcnRzID0gcG9zdC5zcGxpdCgnLS0tXG4nKTsKICBjb25zdCBqc29uID0gcGFydHMuc2hpZnQoKTsKICBjb25zdCBlc3NheSA9ICgoKSA9PiB7CiAgICB0cnkgewogICAgICByZXR1cm4gSlNPTi5wYXJzZShqc29uKTsKICAgIH0gY2F0Y2ggKGUpIHsKICAgICAgY29uc29sZS5lcnJvcignZXJyb3IgcGFyc2luZyBqc29uIGZvciBlc3NheScsIGZwYXRoKTsKICAgICAgdGhyb3cgZTsKICAgIH0KICB9KSgpOwoKICBjb25zdCBkYXRlID0gRGF0ZS5wYXJzZShlc3NheS5kYXRlKTsKICBpZiAoaXNOYU4oZGF0ZSkpIHsKICAgIHRocm93IG5ldyBFcnJvcihgSW52YWxpZCBkYXRlOiAke2Vzc2F5LmRhdGV9IC0gJHtmcGF0aH1gKTsKICB9CiAgZXNzYXkuZGF0ZSA9IG5ldyBEYXRlKGRhdGUpOwogIGVzc2F5LnJhdyA9IHBhcnRzLmpvaW4oJy0tLVxuJyk7CiAgZXNzYXkuY29udGVudCA9IG1hcmtlZChlc3NheS5yYXcpOwogIGVzc2F5LnVybCA9IHBhdGguYmFzZW5hbWUoZnBhdGgsICcubWQnKTsKICBlc3NheS5kZXNjcmlwdGlvbiA9IGVzc2F5LnJhdy5zbGljZSgwLCAyMDApLnJlcGxhY2UoL1xuL2csICcgJykgKyAnLi4uJzsKICByZXR1cm4gZXNzYXk7Cn0KCmNvbnN0IGVzc2F5cyA9IGZzLnJlYWRkaXJTeW5jKGVzc2F5c0RpcikKICAuZmlsdGVyKGZwYXRoID0+IGZwYXRoWzBdICE9PSAnLicpCiAgLm1hcChwYXJzZSkKICAuc29ydCgoYSwgYikgPT4gYi5kYXRlIC0gYS5kYXRlKTsKCmNvbnN0IGZlZWQgPSBuZXcgRmVlZCh7CiAgdGl0bGU6ICJBbWphZCBNYXNhZCIsCiAgZGVzY3JpcHRpb246ICJFc3NheXMiLAogIGlkOiAiaHR0cHM6Ly9hbWFzYWQubWUiLAogIGxpbms6ICJodHRwczovL2FtYXNhZC5tZSIsCiAgaW1hZ2U6ICJodHRwczovL3d3dy5ncmF2YXRhci5jb20vYXZhdGFyLzAzNjM3ZWYxYTUxMjEyMjJjOGRiMGVkNDhjMzRlMTI0LnBuZz9zPTIwMCIsCiAgZmF2aWNvbjogImh0dHBzOi8vd3d3LmdyYXZhdGFyLmNvbS9hdmF0YXIvMDM2MzdlZjFhNTEyMTIyMmM4ZGIwZWQ0OGMzNGUxMjQucG5nP3M9MjAwIiwKICBjb3B5cmlnaHQ6ICJBbGwgcmlnaHRzIHJlc2VydmVkIDIwMTksIEFtamFkIE1hc2FkIiwKICBnZW5lcmF0b3I6ICJhbWFzYWQubWUiLAogIGZlZWRMaW5rczogewogICAganNvbjogImh0dHBzOi8vYW1hc2FkLm1lL2pzb24iLAogICAgcnNzOiAiaHR0cHM6Ly9hbWFzYWQubWUvcnNzIgogIH0sCiAgYXV0aG9yOiB7CiAgICBuYW1lOiAiQW1qYWQgTWFzYWQiLAogICAgZW1haWw6ICJhbWphZC5tYXNhZEBnbWFpbC5jb20iLAogICAgbGluazogImh0dHBzOi8vYW1hc2FkLm1lIgogIH0KfSk7Cgpmb3IgKGNvbnN0IGVzc2F5IG9mIGVzc2F5cykgewogIGZlZWQuYWRkSXRlbSh7CiAgICB0aXRsZTogZXNzYXkudGl0bGUsCiAgICBpZDogZXNzYXkuaWQsCiAgICB1cmw6IGBodHRwczovL2FtYXNhZC5tZS8ke2Vzc2F5LnVybH1gLAogICAgZGVzY3JpcHRpb246IGVzc2F5LmRlc2NyaXB0aW9uLAogICAgY29udGVudDogZXNzYXkuY29udGVudCwKICAgIGRhdGU6IGVzc2F5LmRhdGUsCiAgICBpbWFnZTogZXNzYXkuaW1hZ2UsCiAgICBhdXRob3I6IFsKICAgICAgewogICAgICAgIG5hbWU6ICJBbWphZCBNYXNhZCIsCiAgICAgICAgZW1haWw6ICJhbWphZC5tYXNhZEBnbWFpbC5jb20iLAogICAgICAgIGxpbms6ICJodHRwczovL2FtYXNhZC5tZSIKICAgICAgfSwKICAgIF0sCiAgfSk7Cn0KCmZlZWQuYWRkQ2F0ZWdvcnkoIlRlY2giKTsKCmFwcC51c2UoZnVuY3Rpb24ocmVxLHJlcyxuZXh0KSB7CiAgcmVzLmhlYWRlcignWC1Sb2ItSXMtQXdlc29tJywgdHJ1ZSk7CiAgbmV4dCgpOwp9KTsKCmFwcC5nZXQoJy9qc29uJywgKHJlcSwgcmVzKSA9PiB7CiAgcmVzLmVuZChmZWVkLmpzb24xKCkpOwp9KTsKCmFwcC5nZXQoJy9yc3MnLCAocmVxLCByZXMpID0+IHsKICByZXMuZW5kKGZlZWQucnNzMigpKTsKfSk7CgphcHAuZ2V0KCcvaGVsbG8nLCAocmVxLCByZXMpID0+IHJlcy5lbmQoJ2hlbGxvIHdvcmxkJykpOwoKYXBwLmdldCgnLycsIChyZXEsIHJlcykgPT4geyAgCiAgY29uc3QgZXNzYXlMaXN0ID0gZXNzYXlzLmZpbHRlcihlcyA9PiAhZXMuaGlkZGVuKS5tYXAoZXMgPT4gKAogICAgYDxsaT4KICAgICAgIDxhIGhyZWY9IiR7ZXMudXJsfSI+JHtlcy50aXRsZX08L2E+CiAgICAgPC9saT5gCiAgKSkuam9pbignXG4nKTsKCiAgY29uc3QgaHRtbCA9IGAKICA8YXJ0aWNsZSBjbGFzcz0iaW5kZXggcG9zdENvbnRlbnQiPgogICAgPG5hdj4KICAgICAgPGEgaHJlZj0iL2Fib3V0Ij5BYm91dDwvYT4KICAgICAgPGEgaHJlZj0iaHR0cHM6Ly90d2l0dGVyLmNvbS9hbWFzYWQiPlR3aXR0ZXI8L2E+CiAgICAgIDxhIGhyZWY9Imh0dHBzOi8vZ2l0aHViLmNvbS9hbWFzYWQiPkdpdGh1YjwvYT4KICAgICAgPGEgaHJlZj0iaHR0cHM6Ly9hbWFzYWQubWUvcnNzIj5SU1M8L2E+CiAgICA8L25hdj4KICAgIDxkaXYgY2xhc3M9ImVzc2F5TGlzdCI+CiAgICAgIEVzc2F5czoKICAgICAgPHVsPgogICAgICAgICR7ZXNzYXlMaXN0fQogICAgICA8L3VsPgogICAgPC9kaXY+CiAgPC9hcnRpY2xlPgogIGA7CiAgY29uc3QgcGFnZSA9IHJlbmRlclBhZ2Uoe30sIGh0bWwpOwogIHJlcy5zZW5kKHBhZ2UpOwp9KTsKCmVzc2F5cy5mb3JFYWNoKChlcykgPT4gewogIGFwcC5nZXQoYC8ke2VzLnVybH1gLCAocmVxLCByZXMpID0+IHsKICAgIGNvbnN0IGh0bWwgPSBgCiAgICAgICAgPGFydGljbGUgY2xhc3M9InBvc3RJdGVtIj4KICAgICAgICAgIDxoMSBjbGFzcz0icG9zdFRpdGxlIj4KICAgICAgICAgICAgPGEgaHJlZj0iLyR7ZXMudXJsfSI+JHtlcy50aXRsZX08L2E+CiAgICAgICAgICA8L2gxPgogICAgICAgICAgPGgzIGNsYXNzPSJwb3N0QXV0aG9yIj4KICAgICAgICAgICAgJHtlcy5kYXRlLnRvRGF0ZVN0cmluZygpfQogICAgICAgICAgPC9oMz4KICAgICAgICAgIDxkaXYgY2xhc3M9InBvc3RDb250ZW50Ij4KICAgICAgICAgICAgJHtlcy5jb250ZW50fQogICAgICAgICAgPC9kaXY+CiAgICAgICAgPC9hcnRpY2xlPgogICAgICAgIGA7CgogICAgY29uc3QgcGFnZSA9IHJlbmRlclBhZ2UoewogICAgICB0aXRsZTogZXMudGl0bGUsCiAgICAgIGRlc2NyaXB0aW9uOiBlcy5kZXNjcmlwdGlvbiwKICAgICAgdXJsOiBgLyR7ZXMudXJsfWAsCiAgICAgIGltYWdlOiBlcy5pbWFnZSwKICAgIH0sIGh0bWwpOwogICAgcmVzLnNlbmQocGFnZSk7CiAgfSk7Cn0pOwoKYXBwLmdldCgnL2Fib3V0JywgKHJlcSwgcmVzKSA9PiB7CiAgZnMucmVhZEZpbGUoCiAgICBwYXRoLmpvaW4oX19kaXJuYW1lLCAncGFnZXMnLCAnYWJvdXQubWQnKSwKICAgIChlcnIsIGQpID0+IHsKICAgICAgaWYgKGVycikgewogICAgICAgIHJlcy5zdGF0dXMoNTAwKTsKICAgICAgICByZXMudGV4dCgnc29tZXRoaW5nIHdlbnQgd3JvbmcgOignKTsKICAgICAgICByZXR1cm47CiAgICAgIH0KCiAgICAgIHJlcy5zZXQoJ0NvbnRlbnQtVHlwZScsICd0ZXh0L2h0bWwnKTsKICAgICAgY29uc3QgY29udGVudCA9IG1hcmtlZChkLnRvU3RyaW5nKCd1dGY4JykpOwogICAgICBjb25zdCBodG1sID0gYDxhcnRpY2xlIGNsYXNzPSJwb3N0SXRlbSBwb3N0Q29udGVudCI+CiAgICAgICR7Y29udGVudH0KICAgICAgPC9hcnRpY2xlPmA7CgogICAgICBjb25zdCBwYWdlID0gcmVuZGVyUGFnZSh7fSwgaHRtbCk7CiAgICAgIHJlcy5zZW5kKHBhZ2UpOwogICAgfQogICk7Cn0pOwoKY29uc3QgcmVkaXJlY3Rpb25zID0gewogICcvMjAxMi8xMi8xMS9zdHVmZmpzJzogJy9zdHVmZmpzJywKICAnLzIwMTYvMDQvMTQva2llcmtlZ2FhcmQtYW5kLWVudHJlcHJlbmV1cnNoaXAnOiAnL2tpZXJrZWdhYXJkJywKICAnLzIwMTUvMDQvMDkvaGVsbG8td29ybGQnOiAnL2hlbGxvLXdvcmxkJywKICAnLzIwMTYvMDMvMDUvY2FjaGluZy1hbmQtcHJvbWlzZXMnOiAnL2NhY2hpbmctcHJvbWlzZXMnLAogICcvMjAxMi8wNy8xNy9vbi12bXMtaW4tamF2YXNjcmlwdCc6ICcvanMtdm1zJywKICAnLzIwMTYvMDEvMTcvZXZhbC1hcy1hLXNlcnZpY2UnOiAnL2V2YWwtYXMtYS1zZXJ2aWNlJywKICAnLzIwMTYvMDEvMDMvb3ZlcmNvbWluZy1pbnR1aXRpb24taW4tcHJvZ3JhbW1pbmcnOiAnL2ludHVpdGlvbicsCiAgJy8yMDE2LzAzLzA5L2pvaG4tY2FybWFjay1vbi1pZGVhLWdlbmVyYXRpb24nOiAnL2Nhcm1hY2snLAogICcvMjAxMi8wNy8wMi90aGUtZGFyay1zaWRlLW9mLWZ1bmN0aW9ucHJvdG90eXBlYmluZCc6ICcvYmluZCcsCiAgJy8yMDE2LzAxLzEzL3RoZS1zdG9pYy1vZi1vcGVuLXNvdXJjZSc6ICcvc3RvaWMtb3NzJywKICAnLzIwMTQvMDMvMDkvbGVzc2VyLWtub3duLWphdmFzY3JpcHQtZGVidWdnaW5nLXRlY2huaXF1ZXMnOiAnL2RlYnVnZ2luZycsCiAgJy8yMDE0LzAzLzE2L3doeS1pbS1leGNpdGVkLWFib3V0LW9iamVjdG9ic2VydmUnOiAnL29iamVjdC1vYnNlcnZlJywKICAnLzIwMTUvMTAvMzEvamF2YXNjcmlwdC1hc3luYy1mdW5jdGlvbnMtZm9yLWVhc2llci1jb25jdXJyZW50LXByb2dyYW1taW5nJzoKICAgICcvYXN5bmMtanMnLAogICcvMjAxNi8wMy8xMy93aGF0LWlzLXBlcmZlY3Rpb25pc20tYW5kLWhvdy10by1jdXJlLWl0JzogJy9wZXJmZWN0aW9uaXNtJywKICAnLzIwMTQvMDEvMTgvaW50cm9kdWNpbmctd2FyYWJ5LW1vYmlsZS1vcHRpbWl6ZWQtYXJhYmljLXNlYXJjaC13ZWItYXBwJzoKICAgICcvd2FyYWJ5JywKICAnLzIwMTQvMDEvMTAvaW1wbGVtZW50aW5nLWJyZXQtdmljdG9ycy1sZWFybmFibGUtcHJvZ3JhbW1pbmctaGFzLW5ldmVyLWJlZW4tZWFzaWVyJzogJy9sZWFybmFibGUnLAogICcvMjAxNC8wMS8wNi9idWlsZGluZy1hbi1pbi1icm93c2VyLWphdmFzY3JpcHQtdm0tYW5kLWRlYnVnZ2VyLXVzaW5nLWdlbmVyYXRvcnMnOiAnL2pzLWRlYnVnZ2VyJywKfTsKCk9iamVjdC5rZXlzKHJlZGlyZWN0aW9ucykuZm9yRWFjaCgoa2V5KSA9PiB7CiAgY29uc3Qgcm91dGUgPSByZWRpcmVjdGlvbnNba2V5XTsKICBhcHAuZ2V0KGtleSwgKHJlcSwgcmVzKSA9PiB7CiAgICByZXMucmVkaXJlY3QoMzAxLCByb3V0ZSk7CiAgfSk7Cn0pOwoKY29uc3QgcG9ydCA9IHByb2Nlc3MuZW52LlBPUlQgfHwgODAwMDsKYXBwLmxpc3Rlbihwb3J0LCAoKSA9PiB7CiAgY29uc29sZS5sb2coJ3J1bm5pbmcgb24gcG9ydCcsIHBvcnQpOwp9KTsK"},"asBuffer":null},"loaded":true}}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
const express = require('express');
const renderPage = require('./lib/renderPage');
const marked = require('marked');
const path = require('path');
const app = express();
const fs = require('fs');
const hljs = require('highlight.js');
const _ = require('lodash');
const { Feed } = require('feed');

const renderer = new marked.Renderer();

// Pass html unescaped
renderer.html = str => _.unescape(str);

marked.setOptions({
  renderer: renderer,
  highlight(code, lang) {
    try {
      return hljs.highlight(code, lang).value;
    } catch (e) {
      // Failed to highlight the language
      return hljs.highlightAuto(code).value;
    }
  },
});

const staticOpts = {
  maxAge: 365 * 24 * 60 * 60 * 1000,
};

app.use('/public', express.static(
  path.join(__dirname, 'public'), staticOpts
));

const essaysDir = path.join(__dirname, 'essays');

function parse(fpath) {
  const post = fs.readFileSync(path.join(essaysDir, fpath), 'utf8');
  const parts = post.split('---\n');
  const json = parts.shift();
  const essay = (() => {
    try {
      return JSON.parse(json);
    } catch (e) {
      console.error('error parsing json for essay', fpath);
      throw e;
    }
  })();

  const date = Date.parse(essay.date);
  if (isNaN(date)) {
    throw new Error(`Invalid date: ${essay.date} - ${fpath}`);
  }
  essay.date = new Date(date);
  essay.raw = parts.join('---\n');
  essay.content = marked(essay.raw);
  essay.url = path.basename(fpath, '.md');
  essay.description = essay.raw.slice(0, 200).replace(/\n/g, ' ') + '...';
  return essay;
}

const essays = fs.readdirSync(essaysDir)
  .filter(fpath => fpath[0] !== '.')
  .map(parse)
  .sort((a, b) => b.date - a.date);

const feed = new Feed({
  title: "Amjad Masad",
  description: "Essays",
  id: "https://amasad.me",
  link: "https://amasad.me",
  image: "https://www.gravatar.com/avatar/03637ef1a5121222c8db0ed48c34e124.png?s=200",
  favicon: "https://www.gravatar.com/avatar/03637ef1a5121222c8db0ed48c34e124.png?s=200",
  copyright: "All rights reserved 2019, Amjad Masad",
  generator: "amasad.me",
  feedLinks: {
    json: "https://amasad.me/json",
    rss: "https://amasad.me/rss"
  },
  author: {
    name: "Amjad Masad",
    email: "[email protected]",
    link: "https://amasad.me"
  }
});

for (const essay of essays) {
  feed.addItem({
    title: essay.title,
    id: essay.id,
    url: `https://amasad.me/${essay.url}`,
    description: essay.description,
    content: essay.content,
    date: essay.date,
    image: essay.image,
    author: [
      {
        name: "Amjad Masad",
        email: "[email protected]",
        link: "https://amasad.me"
      },
    ],
  });
}

feed.addCategory("Tech");

app.use(function(req,res,next) {
  res.header('X-Rob-Is-Awesom', true);
  next();
});

app.get('/json', (req, res) => {
  res.end(feed.json1());
});

app.get('/rss', (req, res) => {
  res.end(feed.rss2());
});

app.get('/hello', (req, res) => res.end('hello world'));

app.get('/', (req, res) => {  
  const essayList = essays.filter(es => !es.hidden).map(es => (
    `<li>
       <a href="${es.url}">${es.title}</a>
     </li>`
  )).join('\n');

  const html = `
  <article class="index postContent">
    <nav>
      <a href="/about">About</a>
      <a href="https://twitter.com/amasad">Twitter</a>
      <a href="https://github.com/amasad">Github</a>
      <a href="https://amasad.me/rss">RSS</a>
    </nav>
    <div class="essayList">
      Essays:
      <ul>
        ${essayList}
      </ul>
    </div>
  </article>
  `;
  const page = renderPage({}, html);
  res.send(page);
});

essays.forEach((es) => {
  app.get(`/${es.url}`, (req, res) => {
    const html = `
        <article class="postItem">
          <h1 class="postTitle">
            <a href="/${es.url}">${es.title}</a>
          </h1>
          <h3 class="postAuthor">
            ${es.date.toDateString()}
          </h3>
          <div class="postContent">
            ${es.content}
          </div>
        </article>
        `;

    const page = renderPage({
      title: es.title,
      description: es.description,
      url: `/${es.url}`,
      image: es.image,
    }, html);
    res.send(page);
  });
});

app.get('/about', (req, res) => {
  fs.readFile(
    path.join(__dirname, 'pages', 'about.md'),
    (err, d) => {
      if (err) {
        res.status(500);
        res.text('something went wrong :(');
        return;
      }

      res.set('Content-Type', 'text/html');
      const content = marked(d.toString('utf8'));
      const html = `<article class="postItem postContent">
      ${content}
      </article>`;

      const page = renderPage({}, html);
      res.send(page);
    }
  );
});

const redirections = {
  '/2012/12/11/stuffjs': '/stuffjs',
  '/2016/04/14/kierkegaard-and-entrepreneurship': '/kierkegaard',
  '/2015/04/09/hello-world': '/hello-world',
  '/2016/03/05/caching-and-promises': '/caching-promises',
  '/2012/07/17/on-vms-in-javascript': '/js-vms',
  '/2016/01/17/eval-as-a-service': '/eval-as-a-service',
  '/2016/01/03/overcoming-intuition-in-programming': '/intuition',
  '/2016/03/09/john-carmack-on-idea-generation': '/carmack',
  '/2012/07/02/the-dark-side-of-functionprototypebind': '/bind',
  '/2016/01/13/the-stoic-of-open-source': '/stoic-oss',
  '/2014/03/09/lesser-known-javascript-debugging-techniques': '/debugging',
  '/2014/03/16/why-im-excited-about-objectobserve': '/object-observe',
  '/2015/10/31/javascript-async-functions-for-easier-concurrent-programming':
    '/async-js',
  '/2016/03/13/what-is-perfectionism-and-how-to-cure-it': '/perfectionism',
  '/2014/01/18/introducing-waraby-mobile-optimized-arabic-search-web-app':
    '/waraby',
  '/2014/01/10/implementing-bret-victors-learnable-programming-has-never-been-easier': '/learnable',
  '/2014/01/06/building-an-in-browser-javascript-vm-and-debugger-using-generators': '/js-debugger',
};

Object.keys(redirections).forEach((key) => {
  const route = redirections[key];
  app.get(key, (req, res) => {
    res.redirect(301, route);
  });
});

const port = process.env.PORT || 8000;
app.listen(port, () => {
  console.log('running on port', port);
});
node v10.16.0