-
Notifications
You must be signed in to change notification settings - Fork 120
/
index.js
115 lines (94 loc) · 2.77 KB
/
index.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
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
addEventListener("fetch", (event) => {
event.respondWith(handleRequest(event));
});
async function handleRequest(event) {
const url = new URL(event.request.url);
if (url.pathname === "/") {
return new Response("", {
status: 302,
headers: {
location: "https://github.com/benborgers/opensheet#readme",
},
});
}
let [id, sheet, ...otherParams] = url.pathname
.slice(1)
.split("/")
.filter((x) => x);
if (!id || !sheet || otherParams.length > 0) {
return error("URL format is /spreadsheet_id/sheet_name", 404);
}
const cacheKey = `https://opensheet.elk.sh/${id}/${encodeURIComponent(
sheet
)}`;
const cache = caches.default;
const cachedResponse = await cache.match(cacheKey);
if (cachedResponse) {
console.log(`Serving from cache: ${cacheKey}`);
return cachedResponse;
} else {
console.log(`Cache miss: ${cacheKey}`);
}
sheet = decodeURIComponent(sheet.replace(/\+/g, " "));
if (!isNaN(sheet)) {
if (parseInt(sheet) === 0) {
return error("For this API, sheet numbers start at 1");
}
const sheetData = await (
await fetch(
`https://sheets.googleapis.com/v4/spreadsheets/${id}?key=${GOOGLE_API_KEY}`
)
).json();
if (sheetData.error) {
return error(sheetData.error.message);
}
const sheetIndex = parseInt(sheet) - 1;
const sheetWithThisIndex = sheetData.sheets[sheetIndex];
if (!sheetWithThisIndex) {
return error(`There is no sheet number ${sheet}`);
}
sheet = sheetWithThisIndex.properties.title;
}
const result = await (
await fetch(
`https://sheets.googleapis.com/v4/spreadsheets/${id}/values/${encodeURIComponent(
sheet
)}?key=${GOOGLE_API_KEY}`
)
).json();
if (result.error) {
return error(result.error.message);
}
const rows = [];
const rawRows = result.values || [];
const headers = rawRows.shift();
rawRows.forEach((row) => {
const rowData = {};
row.forEach((item, index) => {
rowData[headers[index]] = item;
});
rows.push(rowData);
});
const apiResponse = new Response(JSON.stringify(rows), {
headers: {
"Content-Type": "application/json",
"Cache-Control": `s-maxage=30`,
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Headers":
"Origin, X-Requested-With, Content-Type, Accept",
},
});
event.waitUntil(cache.put(cacheKey, apiResponse.clone()));
return apiResponse;
}
const error = (message, status = 400) => {
return new Response(JSON.stringify({ error: message }), {
status: status,
headers: {
"Content-Type": "application/json",
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Headers":
"Origin, X-Requested-With, Content-Type, Accept",
},
});
};