/
hn.js
79 lines (72 loc) · 1.93 KB
/
hn.js
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
const remove = (map, key) => {
map.delete(key);
};
export default (firebase, MAX_AGE = 1000 * 60 * 5) => {
firebase.initializeApp({
databaseURL: 'https://hacker-news.firebaseio.com'
});
const db = firebase.database().ref('v0');
const stories = [
'top',
'new',
'show',
'ask',
'job'
];
const cache = new Map;
const request = key => new Promise($ => {
db.child(key).once('value', snap => {
const value = snap.val();
// if there is a value, clean it up in MAX_AGE time
if (value)
setTimeout(remove, MAX_AGE, cache, key);
// otherwise drop it already, as it's useless
else
cache.delete(key);
// resolve for the time being whatever value it has
$(value);
});
});
// cache each request until it's resolved
const load = key => cache.get(key) ||
cache.set(key, request(key)).get(key);
return {
cache,
stories,
item: id => load(`item/${id}`),
user: id => load(`user/${id}`),
story: type => load(`${type}stories`),
parse: url => {
const result = {
type: 'unknown',
id: -1,
page: 1,
user: '',
pathname: ''
};
if (/\/([a-z]+)\/(\?[^&]+)$/.test(url)) {
const {$1: pathname, $2: search} = RegExp;
const sliced = search.slice(1);
if (pathname === 'user') {
result.pathname = pathname;
result.type = 'user';
result.user = sliced;
}
else if (pathname === 'item') {
const id = parseInt(sliced, 10);
if (id && 0 < id) {
result.pathname = pathname;
result.type = 'item';
result.id = id;
}
}
else if (stories.includes(pathname)) {
result.pathname = pathname;
result.type = 'story';
result.page = Math.max(parseInt(sliced, 10) || 1, 1);
}
}
return result;
}
};
};